Merge branch 'pm-runtime'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 7 Nov 2013 18:27:37 +0000 (19:27 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 7 Nov 2013 18:27:37 +0000 (19:27 +0100)
* pm-runtime:
  PM / runtime: Use pm_runtime_put_sync() in __device_release_driver()

698 files changed:
Documentation/ABI/stable/sysfs-bus-usb
Documentation/ABI/testing/sysfs-class-powercap [new file with mode: 0644]
Documentation/ABI/testing/sysfs-devices-power
Documentation/ABI/testing/sysfs-power
Documentation/acpi/dsdt-override.txt
Documentation/connector/ucon.c
Documentation/cpu-freq/cpu-drivers.txt
Documentation/cpu-freq/governors.txt
Documentation/cpuidle/governor.txt
Documentation/devicetree/bindings/memory.txt [deleted file]
Documentation/power/opp.txt
Documentation/power/powercap/powercap.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/arm/boot/dts/integratorcp.dts
arch/arm/common/mcpm_entry.c
arch/arm/common/sharpsl_param.c
arch/arm/include/asm/Kbuild
arch/arm/include/asm/mcpm.h
arch/arm/include/asm/syscall.h
arch/arm/kernel/head.S
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/cpuidle.c [deleted file]
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/setup.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/cpuidle.c
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/omap-pm.h
arch/arm/mach-omap2/opp.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/generic.h
arch/arm/mach-ux500/Kconfig
arch/arm/mach-vexpress/Kconfig
arch/arm/mach-vexpress/Makefile
arch/arm/mach-vexpress/spc.c
arch/arm/mach-vexpress/spc.h
arch/arm/mach-vexpress/tc2_pm.c
arch/arm/mach-zynq/common.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/init.c
arch/arm/net/bpf_jit_32.c
arch/blackfin/Kconfig
arch/cris/Kconfig
arch/ia64/kernel/acpi.c
arch/parisc/configs/712_defconfig
arch/parisc/configs/a500_defconfig
arch/parisc/configs/b180_defconfig
arch/parisc/configs/c3000_defconfig
arch/parisc/configs/c8000_defconfig
arch/parisc/configs/default_defconfig
arch/parisc/kernel/cache.c
arch/parisc/kernel/head.S
arch/powerpc/kernel/smp.c
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/platforms/pseries/dlpar.c
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/timex.h
arch/s390/kernel/compat_signal.c
arch/s390/kernel/debug.c
arch/s390/kvm/interrupt.c
arch/s390/lib/delay.c
arch/s390/net/bpf_jit_comp.c
arch/sparc/net/bpf_jit_comp.c
arch/x86/Kconfig
arch/x86/include/asm/acpi.h
arch/x86/include/asm/mpspec.h
arch/x86/include/asm/msr.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/acpi/sleep.h
arch/x86/kernel/acpi/wakeup_32.S
arch/x86/kernel/acpi/wakeup_64.S
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/kvm.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/topology.c
arch/x86/lib/msr-smp.c
arch/x86/net/bpf_jit_comp.c
arch/x86/platform/olpc/olpc-xo15-sci.c
arch/x86/xen/smp.c
block/partitions/efi.c
drivers/Kconfig
drivers/Makefile
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/ac.c
drivers/acpi/acpi_ipmi.c
drivers/acpi/acpi_lpss.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/acpi_platform.c
drivers/acpi/acpi_processor.c
drivers/acpi/acpica/acdebug.h
drivers/acpi/acpica/acevents.h
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acmacros.h
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/acutils.h
drivers/acpi/acpica/dsargs.c
drivers/acpi/acpica/dsfield.c
drivers/acpi/acpica/dsmethod.c
drivers/acpi/acpica/dsobject.c
drivers/acpi/acpica/dsopcode.c
drivers/acpi/acpica/dsutils.c
drivers/acpi/acpica/dswexec.c
drivers/acpi/acpica/dswload2.c
drivers/acpi/acpica/evglock.c
drivers/acpi/acpica/evgpe.c
drivers/acpi/acpica/evgpeblk.c
drivers/acpi/acpica/evgpeinit.c
drivers/acpi/acpica/evgpeutil.c
drivers/acpi/acpica/evhandler.c
drivers/acpi/acpica/evmisc.c
drivers/acpi/acpica/evregion.c
drivers/acpi/acpica/evsci.c
drivers/acpi/acpica/evxface.c
drivers/acpi/acpica/evxfevnt.c
drivers/acpi/acpica/evxfgpe.c
drivers/acpi/acpica/evxfregn.c
drivers/acpi/acpica/excreate.c
drivers/acpi/acpica/exfield.c
drivers/acpi/acpica/exfldio.c
drivers/acpi/acpica/exmisc.c
drivers/acpi/acpica/exoparg1.c
drivers/acpi/acpica/exoparg2.c
drivers/acpi/acpica/exoparg3.c
drivers/acpi/acpica/exoparg6.c
drivers/acpi/acpica/exregion.c
drivers/acpi/acpica/exresolv.c
drivers/acpi/acpica/exresop.c
drivers/acpi/acpica/hwregs.c
drivers/acpi/acpica/hwtimer.c
drivers/acpi/acpica/hwxface.c
drivers/acpi/acpica/hwxfsleep.c
drivers/acpi/acpica/nsaccess.c
drivers/acpi/acpica/nsdump.c
drivers/acpi/acpica/nsdumpdv.c
drivers/acpi/acpica/nseval.c
drivers/acpi/acpica/nsinit.c
drivers/acpi/acpica/nsload.c
drivers/acpi/acpica/nsparse.c
drivers/acpi/acpica/nspredef.c
drivers/acpi/acpica/nsprepkg.c
drivers/acpi/acpica/nsrepair.c
drivers/acpi/acpica/nsrepair2.c
drivers/acpi/acpica/nssearch.c
drivers/acpi/acpica/nsutils.c
drivers/acpi/acpica/nsxfeval.c
drivers/acpi/acpica/nsxfname.c
drivers/acpi/acpica/nsxfobj.c
drivers/acpi/acpica/psparse.c
drivers/acpi/acpica/psxface.c
drivers/acpi/acpica/rsmisc.c
drivers/acpi/acpica/rsutils.c
drivers/acpi/acpica/rsxface.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/acpica/tbprint.c
drivers/acpi/acpica/tbutils.c
drivers/acpi/acpica/tbxface.c
drivers/acpi/acpica/tbxfload.c
drivers/acpi/acpica/tbxfroot.c
drivers/acpi/acpica/utalloc.c
drivers/acpi/acpica/utcache.c
drivers/acpi/acpica/utcopy.c
drivers/acpi/acpica/utdebug.c
drivers/acpi/acpica/utdecode.c
drivers/acpi/acpica/utdelete.c
drivers/acpi/acpica/uteval.c
drivers/acpi/acpica/utexcep.c
drivers/acpi/acpica/utglobal.c
drivers/acpi/acpica/utids.c
drivers/acpi/acpica/utobject.c
drivers/acpi/acpica/utownerid.c
drivers/acpi/acpica/utresrc.c
drivers/acpi/acpica/utstate.c
drivers/acpi/acpica/utstring.c
drivers/acpi/acpica/uttrack.c
drivers/acpi/acpica/utxface.c
drivers/acpi/acpica/utxferror.c
drivers/acpi/acpica/utxfinit.c
drivers/acpi/battery.c
drivers/acpi/blacklist.c
drivers/acpi/button.c
drivers/acpi/cm_sbs.c [deleted file]
drivers/acpi/device_pm.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/event.c
drivers/acpi/fan.c
drivers/acpi/internal.h
drivers/acpi/numa.c
drivers/acpi/osl.c
drivers/acpi/power.c
drivers/acpi/proc.c
drivers/acpi/processor_core.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_perflib.c
drivers/acpi/sbs.c
drivers/acpi/scan.c
drivers/acpi/sysfs.c
drivers/acpi/thermal.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/acpi/video_detect.c
drivers/ata/ahci.c
drivers/ata/ahci_platform.c
drivers/ata/libahci.c
drivers/ata/libata-acpi.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/libata.h
drivers/ata/pata_isapnp.c
drivers/base/cpu.c
drivers/base/memory.c
drivers/base/power/main.c
drivers/base/power/opp.c
drivers/char/tpm/xen-tpmfront.c
drivers/connector/cn_proc.c
drivers/connector/connector.c
drivers/cpufreq/Kconfig
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/Kconfig.powerpc
drivers/cpufreq/Kconfig.x86
drivers/cpufreq/Makefile
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/arm_big_little.c
drivers/cpufreq/arm_big_little.h
drivers/cpufreq/arm_big_little_dt.c
drivers/cpufreq/at32ap-cpufreq.c
drivers/cpufreq/blackfin-cpufreq.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq-nforce2.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_userspace.c
drivers/cpufreq/cris-artpec3-cpufreq.c
drivers/cpufreq/cris-etraxfs-cpufreq.c
drivers/cpufreq/davinci-cpufreq.c
drivers/cpufreq/dbx500-cpufreq.c
drivers/cpufreq/e_powersaver.c
drivers/cpufreq/elanfreq.c
drivers/cpufreq/exynos-cpufreq.c
drivers/cpufreq/exynos4210-cpufreq.c
drivers/cpufreq/exynos4x12-cpufreq.c
drivers/cpufreq/exynos5440-cpufreq.c
drivers/cpufreq/freq_table.c
drivers/cpufreq/gx-suspmod.c
drivers/cpufreq/highbank-cpufreq.c
drivers/cpufreq/ia64-acpi-cpufreq.c
drivers/cpufreq/imx6q-cpufreq.c
drivers/cpufreq/integrator-cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/kirkwood-cpufreq.c
drivers/cpufreq/longhaul.c
drivers/cpufreq/longrun.c
drivers/cpufreq/loongson2_cpufreq.c
drivers/cpufreq/maple-cpufreq.c
drivers/cpufreq/omap-cpufreq.c
drivers/cpufreq/p4-clockmod.c
drivers/cpufreq/pasemi-cpufreq.c
drivers/cpufreq/pcc-cpufreq.c
drivers/cpufreq/pmac32-cpufreq.c
drivers/cpufreq/pmac64-cpufreq.c
drivers/cpufreq/powernow-k6.c
drivers/cpufreq/powernow-k7.c
drivers/cpufreq/powernow-k8.c
drivers/cpufreq/ppc-corenet-cpufreq.c
drivers/cpufreq/ppc_cbe_cpufreq.c
drivers/cpufreq/pxa2xx-cpufreq.c
drivers/cpufreq/pxa3xx-cpufreq.c
drivers/cpufreq/s3c2416-cpufreq.c
drivers/cpufreq/s3c24xx-cpufreq.c
drivers/cpufreq/s3c64xx-cpufreq.c
drivers/cpufreq/s5pv210-cpufreq.c
drivers/cpufreq/sa1100-cpufreq.c
drivers/cpufreq/sa1110-cpufreq.c
drivers/cpufreq/sc520_freq.c
drivers/cpufreq/sh-cpufreq.c
drivers/cpufreq/sparc-us2e-cpufreq.c
drivers/cpufreq/sparc-us3-cpufreq.c
drivers/cpufreq/spear-cpufreq.c
drivers/cpufreq/speedstep-centrino.c
drivers/cpufreq/speedstep-ich.c
drivers/cpufreq/speedstep-smi.c
drivers/cpufreq/tegra-cpufreq.c
drivers/cpufreq/unicore2-cpufreq.c
drivers/cpufreq/vexpress-spc-cpufreq.c [new file with mode: 0644]
drivers/cpuidle/Kconfig.arm
drivers/cpuidle/Makefile
drivers/cpuidle/coupled.c
drivers/cpuidle/cpuidle-at91.c [new file with mode: 0644]
drivers/cpuidle/cpuidle-ux500.c
drivers/cpuidle/cpuidle-zynq.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/driver.c
drivers/cpuidle/governor.c
drivers/cpuidle/sysfs.c
drivers/devfreq/devfreq.c
drivers/devfreq/exynos/exynos4_bus.c
drivers/devfreq/exynos/exynos5_bus.c
drivers/dma/edma.c
drivers/gpio/gpio-lynxpoint.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_acpi.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/uvd_v1_0.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-wiimote-core.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/i2c/i2c-core.c
drivers/idle/intel_idle.c
drivers/iio/frequency/adf4350.c
drivers/iio/industrialio-buffer.c
drivers/infiniband/Kconfig
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/amso1100/c2_ae.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/mlx5/srq.c
drivers/infiniband/hw/mthca/mthca_eq.c
drivers/infiniband/hw/ocrdma/ocrdma_hw.c
drivers/infiniband/hw/ocrdma/ocrdma_main.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/iommu/dmar.c
drivers/iommu/intel_irq_remapping.c
drivers/md/bcache/request.c
drivers/md/dm-snap-persistent.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/dvb-frontends/tda10071.c
drivers/media/i2c/ad9389b.c
drivers/media/i2c/adv7511.c
drivers/media/i2c/adv7842.c
drivers/media/i2c/ths8200.c
drivers/media/pci/saa7134/saa7134-video.c
drivers/media/platform/s5p-jpeg/jpeg-core.c
drivers/media/platform/sh_vou.c
drivers/media/platform/soc_camera/mx3_camera.c
drivers/media/tuners/e4000.c
drivers/media/usb/stkwebcam/stk-webcam.c
drivers/media/usb/uvc/uvc_driver.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/net/can/at91_can.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/calxeda/xgmac.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
drivers/net/ethernet/moxa/moxart_ether.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/mcdi_pcol.h
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/smsc/smc91x.h
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/hamradio/yam.c
drivers/net/ieee802154/mrf24j40.c
drivers/net/tun.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/net/wan/farsync.c
drivers/net/wan/wanxl.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/cw1200/cw1200_spi.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/mvm/power.c
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/rt2x00/rt2x00pci.c
drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
drivers/net/xen-netback/xenbus.c
drivers/of/Kconfig
drivers/of/Makefile
drivers/of/base.c
drivers/of/fdt.c
drivers/of/of_reserved_mem.c [deleted file]
drivers/of/platform.c
drivers/pci/hotplug/acpi_pcihp.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/pci-acpi.c
drivers/platform/x86/Kconfig
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/fujitsu-laptop.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel-rst.c
drivers/platform/x86/intel-smartconnect.c
drivers/platform/x86/intel_menlow.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/topstar-laptop.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/wmi.c
drivers/pnp/pnpacpi/core.c
drivers/powercap/Kconfig [new file with mode: 0644]
drivers/powercap/Makefile [new file with mode: 0644]
drivers/powercap/intel_rapl.c [new file with mode: 0644]
drivers/powercap/powercap_sys.c [new file with mode: 0644]
drivers/s390/block/dasd_eckd.c
drivers/s390/char/sclp.c
drivers/s390/char/vmlogrdr.c
drivers/s390/cio/cio.c
drivers/s390/cio/qdio_main.c
drivers/scsi/BusLogic.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/sd.c
drivers/spi/spi.c
drivers/staging/media/msi3101/Kconfig
drivers/staging/media/msi3101/sdr-msi3101.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_sbc.c
drivers/target/target_core_xcopy.c
drivers/thermal/Kconfig
drivers/thermal/samsung/exynos_thermal_common.c
drivers/thermal/samsung/exynos_tmu.c
drivers/thermal/samsung/exynos_tmu.h
drivers/thermal/samsung/exynos_tmu_data.c
drivers/thermal/samsung/exynos_tmu_data.h
drivers/thermal/thermal_hwmon.c
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
drivers/thermal/x86_pkg_temp_thermal.c
drivers/tty/serial/imx.c
drivers/tty/serial/vt8500_serial.c
drivers/usb/chipidea/host.c
drivers/usb/core/quirks.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/Kconfig
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_virthub.c
drivers/usb/serial/option.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/unusual_devs.h
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/scsi.c
drivers/video/backlight/backlight.c
drivers/w1/w1.c
fs/btrfs/inode.c
fs/buffer.c
fs/cifs/cifsfs.c
fs/cifs/cifspdu.h
fs/cifs/cifssmb.c
fs/cifs/netmisc.c
fs/cifs/sess.c
fs/cifs/smb2pdu.c
fs/cifs/smbfsctl.h
fs/cifs/transport.c
fs/dcache.c
fs/ecryptfs/crypto.c
fs/ecryptfs/keystore.c
fs/ext3/namei.c
fs/ext4/namei.c
fs/file_table.c
fs/jfs/jfs_inode.c
fs/namei.c
fs/proc/inode.c
fs/proc/task_mmu.c
fs/seq_file.c
include/acpi/acconfig.h
include/acpi/acexcep.h
include/acpi/acnames.h
include/acpi/acpi_bus.h
include/acpi/acpiosxf.h
include/acpi/acpixf.h
include/acpi/actbl.h
include/acpi/actbl2.h
include/acpi/actypes.h
include/acpi/platform/acenv.h
include/acpi/platform/aclinux.h
include/acpi/processor.h
include/linux/acpi.h
include/linux/backlight.h
include/linux/bitops.h
include/linux/cpu.h
include/linux/cpufreq.h
include/linux/cpuidle.h
include/linux/devfreq.h
include/linux/filter.h
include/linux/memcontrol.h
include/linux/mlx5/device.h
include/linux/mlx5/driver.h
include/linux/netdevice.h
include/linux/of_reserved_mem.h [deleted file]
include/linux/opp.h [deleted file]
include/linux/pm_opp.h [new file with mode: 0644]
include/linux/powercap.h [new file with mode: 0644]
include/linux/sched.h
include/linux/tc_act/tc_defact.h [deleted file]
include/linux/usb/usb_phy_gen_xceiv.h
include/linux/usb_usual.h
include/linux/yam.h
include/net/cipso_ipv4.h
include/net/dst.h
include/net/ip6_route.h
include/net/mac802154.h
include/net/sock.h
include/sound/rcar_snd.h
include/trace/events/target.h
include/uapi/drm/drm_mode.h
include/uapi/linux/tc_act/Kbuild
include/uapi/linux/tc_act/tc_defact.h [new file with mode: 0644]
include/uapi/rdma/ib_user_verbs.h
ipc/sem.c
ipc/util.c
kernel/cgroup.c
kernel/events/core.c
kernel/mutex.c
kernel/power/Kconfig
kernel/power/hibernate.c
kernel/power/qos.c
kernel/power/snapshot.c
kernel/power/user.c
kernel/time/clockevents.c
lib/percpu-refcount.c
mm/filemap.c
mm/huge_memory.c
mm/hugetlb.c
mm/memcontrol.c
mm/memory.c
mm/migrate.c
mm/mprotect.c
mm/mremap.c
mm/oom_kill.c
mm/page-writeback.c
mm/slab_common.c
mm/swapfile.c
mm/vmscan.c
mm/zswap.c
net/8021q/vlan_netlink.c
net/batman-adv/main.c
net/batman-adv/network-coding.c
net/batman-adv/network-coding.h
net/bridge/br_fdb.c
net/bridge/br_mdb.c
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_stp_if.c
net/bridge/br_vlan.c
net/compat.c
net/core/dev.c
net/core/filter.c
net/core/secure_seq.c
net/core/sock.c
net/ieee802154/6lowpan.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_output.c
net/ipv4/ip_vti.c
net/ipv4/route.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/xfrm4_policy.c
net/ipv6/ah6.c
net/ipv6/esp6.c
net/ipv6/inet6_hashtables.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ipcomp6.c
net/ipv6/route.c
net/ipv6/udp.c
net/ipv6/xfrm6_policy.c
net/key/af_key.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_ppp.c
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/offchannel.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/status.c
net/mac80211/tx.c
net/mac80211/util.c
net/netfilter/nf_conntrack_h323_main.c
net/sched/sch_fq.c
net/sched/sch_netem.c
net/sctp/output.c
net/socket.c
net/unix/af_unix.c
net/unix/diag.c
net/wireless/core.c
net/wireless/core.h
net/wireless/ibss.c
net/wireless/nl80211.c
net/wireless/radiotap.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_replay.c
net/xfrm/xfrm_user.c
security/apparmor/apparmorfs.c
security/apparmor/policy.c
sound/pci/hda/hda_generic.c
sound/pci/rme9652/hdsp.c
sound/soc/codecs/pcm1681.c
sound/soc/codecs/pcm1792a.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/imx-mc13783.c
sound/soc/fsl/imx-ssi.c
sound/soc/fsl/imx-ssi.h
sound/soc/omap/Kconfig
sound/soc/sh/rcar/rsnd.h
sound/usb/usx2y/us122l.c
tools/perf/util/event.c
tools/perf/util/evsel.c
tools/perf/util/probe-finder.c
tools/perf/util/scripting-engines/trace-event-perl.c
tools/testing/selftests/timers/posix_timers.c

index 2be603c52a240fa55f1a630d4f3567cc9c134d19..a6b68572474062bf04329a434cb27bbf825d19b8 100644 (file)
@@ -37,8 +37,8 @@ Description:
                that the USB device has been connected to the machine.  This
                file is read-only.
 Users:
-               PowerTOP <power@bughost.org>
-               http://www.lesswatts.org/projects/powertop/
+               PowerTOP <powertop@lists.01.org>
+               https://01.org/powertop/
 
 What:          /sys/bus/usb/device/.../power/active_duration
 Date:          January 2008
@@ -57,8 +57,8 @@ Description:
                will give an integer percentage.  Note that this does not
                account for counter wrap.
 Users:
-               PowerTOP <power@bughost.org>
-               http://www.lesswatts.org/projects/powertop/
+               PowerTOP <powertop@lists.01.org>
+               https://01.org/powertop/
 
 What:          /sys/bus/usb/devices/<busnum>-<port[.port]>...:<config num>-<interface num>/supports_autosuspend
 Date:          January 2008
diff --git a/Documentation/ABI/testing/sysfs-class-powercap b/Documentation/ABI/testing/sysfs-class-powercap
new file mode 100644 (file)
index 0000000..db3b3ff
--- /dev/null
@@ -0,0 +1,152 @@
+What:          /sys/class/powercap/
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               The powercap/ class sub directory belongs to the power cap
+               subsystem. Refer to
+               Documentation/power/powercap/powercap.txt for details.
+
+What:          /sys/class/powercap/<control type>
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               A <control type> is a unique name under /sys/class/powercap.
+               Here <control type> determines how the power is going to be
+               controlled. A <control type> can contain multiple power zones.
+
+What:          /sys/class/powercap/<control type>/enabled
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               This allows to enable/disable power capping for a "control type".
+               This status affects every power zone using this "control_type.
+
+What:          /sys/class/powercap/<control type>/<power zone>
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               A power zone is a single or a collection of devices, which can
+               be independently monitored and controlled. A power zone sysfs
+               entry is qualified with the name of the <control type>.
+               E.g. intel-rapl:0:1:1.
+
+What:          /sys/class/powercap/<control type>/<power zone>/<child power zone>
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Power zones may be organized in a hierarchy in which child
+               power zones provide monitoring and control for a subset of
+               devices under the parent. For example, if there is a parent
+               power zone for a whole CPU package, each CPU core in it can
+               be a child power zone.
+
+What:          /sys/class/powercap/.../<power zone>/name
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Specifies the name of this power zone.
+
+What:          /sys/class/powercap/.../<power zone>/energy_uj
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Current energy counter in micro-joules. Write "0" to reset.
+               If the counter can not be reset, then this attribute is
+               read-only.
+
+What:          /sys/class/powercap/.../<power zone>/max_energy_range_uj
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Range of the above energy counter in micro-joules.
+
+
+What:          /sys/class/powercap/.../<power zone>/power_uw
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Current power in micro-watts.
+
+What:          /sys/class/powercap/.../<power zone>/max_power_range_uw
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Range of the above power value in micro-watts.
+
+What:          /sys/class/powercap/.../<power zone>/constraint_X_name
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Each power zone can define one or more constraints. Each
+               constraint can have an optional name. Here "X" can have values
+               from 0 to max integer.
+
+What:          /sys/class/powercap/.../<power zone>/constraint_X_power_limit_uw
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Power limit in micro-watts should be applicable for
+               the time window specified by "constraint_X_time_window_us".
+               Here "X" can have values from 0 to max integer.
+
+What:          /sys/class/powercap/.../<power zone>/constraint_X_time_window_us
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Time window in micro seconds. This is used along with
+               constraint_X_power_limit_uw to define a power constraint.
+               Here "X" can have values from 0 to max integer.
+
+
+What:          /sys/class/powercap/<control type>/.../constraint_X_max_power_uw
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Maximum allowed power in micro watts for this constraint.
+               Here "X" can have values from 0 to max integer.
+
+What:          /sys/class/powercap/<control type>/.../constraint_X_min_power_uw
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Minimum allowed power in micro watts for this constraint.
+               Here "X" can have values from 0 to max integer.
+
+What:          /sys/class/powercap/.../<power zone>/constraint_X_max_time_window_us
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Maximum allowed time window in micro seconds for this
+               constraint. Here "X" can have values from 0 to max integer.
+
+What:          /sys/class/powercap/.../<power zone>/constraint_X_min_time_window_us
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Minimum allowed time window in micro seconds for this
+               constraint. Here "X" can have values from 0 to max integer.
+
+What:          /sys/class/powercap/.../<power zone>/enabled
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description
+               This allows to enable/disable power capping at power zone level.
+               This applies to current power zone and its children.
index 9d43e76708413bdf6b3d25a0b1179714b06680ba..efe449bdf811db7a1c9f74f38a0371d2c0dd692e 100644 (file)
@@ -1,6 +1,6 @@
 What:          /sys/devices/.../power/
 Date:          January 2009
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power directory contains attributes
                allowing the user space to check and modify some power
@@ -8,7 +8,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup
 Date:          January 2009
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power/wakeup attribute allows the user
                space to check if the device is enabled to wake up the system
@@ -34,7 +34,7 @@ Description:
 
 What:          /sys/devices/.../power/control
 Date:          January 2009
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power/control attribute allows the user
                space to control the run-time power management of the device.
@@ -53,7 +53,7 @@ Description:
 
 What:          /sys/devices/.../power/async
 Date:          January 2009
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../async attribute allows the user space to
                enable or diasble the device's suspend and resume callbacks to
@@ -79,7 +79,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_count
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_count attribute contains the number
                of signaled wakeup events associated with the device.  This
@@ -88,7 +88,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_active_count
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_active_count attribute contains the
                number of times the processing of wakeup events associated with
@@ -98,7 +98,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_abort_count
 Date:          February 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_abort_count attribute contains the
                number of times the processing of a wakeup event associated with
@@ -109,7 +109,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_expire_count
 Date:          February 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_expire_count attribute contains the
                number of times a wakeup event associated with the device has
@@ -119,7 +119,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_active
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_active attribute contains either 1,
                or 0, depending on whether or not a wakeup event associated with
@@ -129,7 +129,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_total_time_ms
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_total_time_ms attribute contains
                the total time of processing wakeup events associated with the
@@ -139,7 +139,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_max_time_ms
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_max_time_ms attribute contains
                the maximum time of processing a single wakeup event associated
@@ -149,7 +149,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_last_time_ms
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_last_time_ms attribute contains
                the value of the monotonic clock corresponding to the time of
@@ -160,7 +160,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_prevent_sleep_time_ms
 Date:          February 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_prevent_sleep_time_ms attribute
                contains the total time the device has been preventing
@@ -189,7 +189,7 @@ Description:
 
 What:          /sys/devices/.../power/pm_qos_latency_us
 Date:          March 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power/pm_qos_resume_latency_us attribute
                contains the PM QoS resume latency limit for the given device,
@@ -207,7 +207,7 @@ Description:
 
 What:          /sys/devices/.../power/pm_qos_no_power_off
 Date:          September 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power/pm_qos_no_power_off attribute
                is used for manipulating the PM QoS "no power off" flag.  If
@@ -222,7 +222,7 @@ Description:
 
 What:          /sys/devices/.../power/pm_qos_remote_wakeup
 Date:          September 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power/pm_qos_remote_wakeup attribute
                is used for manipulating the PM QoS "remote wakeup required"
index 217772615d0288f996e05cc128b98c9a40d95042..205a7387844106804de496ec9b3a8c372b725977 100644 (file)
@@ -1,6 +1,6 @@
 What:          /sys/power/
 Date:          August 2006
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power directory will contain files that will
                provide a unified interface to the power management
@@ -8,7 +8,7 @@ Description:
 
 What:          /sys/power/state
 Date:          August 2006
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/state file controls the system power state.
                Reading from this file returns what states are supported,
@@ -22,7 +22,7 @@ Description:
 
 What:          /sys/power/disk
 Date:          September 2006
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/disk file controls the operating mode of the
                suspend-to-disk mechanism.  Reading from this file returns
@@ -67,7 +67,7 @@ Description:
 
 What:          /sys/power/image_size
 Date:          August 2006
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/image_size file controls the size of the image
                created by the suspend-to-disk mechanism.  It can be written a
@@ -84,7 +84,7 @@ Description:
 
 What:          /sys/power/pm_trace
 Date:          August 2006
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/pm_trace file controls the code which saves the
                last PM event point in the RTC across reboots, so that you can
@@ -133,7 +133,7 @@ Description:
 
 What:          /sys/power/pm_async
 Date:          January 2009
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/pm_async file controls the switch allowing the
                user space to enable or disable asynchronous suspend and resume
@@ -146,7 +146,7 @@ Description:
 
 What:          /sys/power/wakeup_count
 Date:          July 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/wakeup_count file allows user space to put the
                system into a sleep state while taking into account the
@@ -161,7 +161,7 @@ Description:
 
 What:          /sys/power/reserved_size
 Date:          May 2011
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/reserved_size file allows user space to control
                the amount of memory reserved for allocations made by device
@@ -175,7 +175,7 @@ Description:
 
 What:          /sys/power/autosleep
 Date:          April 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/autosleep file can be written one of the strings
                returned by reads from /sys/power/state.  If that happens, a
@@ -192,7 +192,7 @@ Description:
 
 What:          /sys/power/wake_lock
 Date:          February 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/wake_lock file allows user space to create
                wakeup source objects and activate them on demand (if one of
@@ -219,7 +219,7 @@ Description:
 
 What:          /sys/power/wake_unlock
 Date:          February 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/wake_unlock file allows user space to deactivate
                wakeup sources created with the help of /sys/power/wake_lock.
index febbb1ba4d2317b984e7217796ac39151f867531..784841caa6e63824ff2503351fb12e682f01e3b3 100644 (file)
@@ -4,4 +4,4 @@ CONFIG_ACPI_CUSTOM_DSDT builds the image into the kernel.
 
 When to use this method is described in detail on the
 Linux/ACPI home page:
-http://www.lesswatts.org/projects/acpi/overridingDSDT.php
+https://01.org/linux-acpi/documentation/overriding-dsdt
index 4848db8c71ff5118244888b620251f49831c92f2..8a4da64e02a8b08f3ad7ed6359ef713d7afd3b54 100644 (file)
@@ -71,7 +71,7 @@ static int netlink_send(int s, struct cn_msg *msg)
        nlh->nlmsg_seq = seq++;
        nlh->nlmsg_pid = getpid();
        nlh->nlmsg_type = NLMSG_DONE;
-       nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
+       nlh->nlmsg_len = size;
        nlh->nlmsg_flags = 0;
 
        m = NLMSG_DATA(nlh);
index 40282e6179135abc353bc8b04a86137820794468..8b1a4451422e747a2278c0ba48ed4ca58e131ba3 100644 (file)
@@ -23,8 +23,8 @@ Contents:
 1.1  Initialization
 1.2  Per-CPU Initialization
 1.3  verify
-1.4  target or setpolicy?
-1.5  target
+1.4  target/target_index or setpolicy?
+1.5  target/target_index
 1.6  setpolicy
 2.   Frequency Table Helpers
 
@@ -56,7 +56,8 @@ cpufreq_driver.init -         A pointer to the per-CPU initialization
 cpufreq_driver.verify -                A pointer to a "verification" function.
 
 cpufreq_driver.setpolicy _or_ 
-cpufreq_driver.target -                See below on the differences.
+cpufreq_driver.target/
+target_index           -       See below on the differences.
 
 And optionally
 
@@ -66,7 +67,7 @@ cpufreq_driver.resume -               A pointer to a per-CPU resume function
                                which is called with interrupts disabled
                                and _before_ the pre-suspend frequency
                                and/or policy is restored by a call to
-                               ->target or ->setpolicy.
+                               ->target/target_index or ->setpolicy.
 
 cpufreq_driver.attr -          A pointer to a NULL-terminated list of
                                "struct freq_attr" which allow to
@@ -103,8 +104,8 @@ policy->governor            must contain the "default policy" for
                                this CPU. A few moments later,
                                cpufreq_driver.verify and either
                                cpufreq_driver.setpolicy or
-                               cpufreq_driver.target is called with
-                               these values.
+                               cpufreq_driver.target/target_index is called
+                               with these values.
 
 For setting some of these values (cpuinfo.min[max]_freq, policy->min[max]), the
 frequency table helpers might be helpful. See the section 2 for more information
@@ -133,20 +134,28 @@ range) is within policy->min and policy->max. If necessary, increase
 policy->max first, and only if this is no solution, decrease policy->min.
 
 
-1.4 target or setpolicy?
+1.4 target/target_index or setpolicy?
 ----------------------------
 
 Most cpufreq drivers or even most cpu frequency scaling algorithms 
 only allow the CPU to be set to one frequency. For these, you use the
-->target call.
+->target/target_index call.
 
 Some cpufreq-capable processors switch the frequency between certain
 limits on their own. These shall use the ->setpolicy call
 
 
-1.4. target
+1.4. target/target_index
 -------------
 
+The target_index call has two arguments: struct cpufreq_policy *policy,
+and unsigned int index (into the exposed frequency table).
+
+The CPUfreq driver must set the new frequency when called here. The
+actual frequency must be determined by freq_table[index].frequency.
+
+Deprecated:
+----------
 The target call has three arguments: struct cpufreq_policy *policy,
 unsigned int target_frequency, unsigned int relation.
 
index 219970ba54b736b2ca6e9d841645b9e71d47df1d..77ec21574fb1873c37dfdd9791c2e82a97198de7 100644 (file)
@@ -40,7 +40,7 @@ Most cpufreq drivers (in fact, all except one, longrun) or even most
 cpu frequency scaling algorithms only offer the CPU to be set to one
 frequency. In order to offer dynamic frequency scaling, the cpufreq
 core must be able to tell these drivers of a "target frequency". So
-these specific drivers will be transformed to offer a "->target"
+these specific drivers will be transformed to offer a "->target/target_index"
 call instead of the existing "->setpolicy" call. For "longrun", all
 stays the same, though.
 
@@ -71,7 +71,7 @@ CPU can be set to switch independently         |         CPU can only be set
                    /                          the limits of policy->{min,max}
                   /                                \
                  /                                  \
-       Using the ->setpolicy call,              Using the ->target call,
+       Using the ->setpolicy call,              Using the ->target/target_index call,
            the limits and the                    the frequency closest
             "policy" is set.                     to target_freq is set.
                                                  It is assured that it
index 12c6bd50c9f6fa8dc47393a5dd03d3072cf1d4a4..d9020f5e847b2ae8c2e86df7a80b5a493ed107f2 100644 (file)
@@ -25,5 +25,4 @@ kernel configuration and platform will be selected by cpuidle.
 
 Interfaces:
 extern int cpuidle_register_governor(struct cpuidle_governor *gov);
-extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
 struct cpuidle_governor
diff --git a/Documentation/devicetree/bindings/memory.txt b/Documentation/devicetree/bindings/memory.txt
deleted file mode 100644 (file)
index eb24693..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-*** Memory binding ***
-
-The /memory node provides basic information about the address and size
-of the physical memory. This node is usually filled or updated by the
-bootloader, depending on the actual memory configuration of the given
-hardware.
-
-The memory layout is described by the following node:
-
-/ {
-       #address-cells = <(n)>;
-       #size-cells = <(m)>;
-       memory {
-               device_type = "memory";
-               reg =  <(baseaddr1) (size1)
-                       (baseaddr2) (size2)
-                       ...
-                       (baseaddrN) (sizeN)>;
-       };
-       ...
-};
-
-A memory node follows the typical device tree rules for "reg" property:
-n:             number of cells used to store base address value
-m:             number of cells used to store size value
-baseaddrX:     defines a base address of the defined memory bank
-sizeX:         the size of the defined memory bank
-
-
-More than one memory bank can be defined.
-
-
-*** Reserved memory regions ***
-
-In /memory/reserved-memory node one can create child nodes describing
-particular reserved (excluded from normal use) memory regions. Such
-memory regions are usually designed for the special usage by various
-device drivers. A good example are contiguous memory allocations or
-memory sharing with other operating system on the same hardware board.
-Those special memory regions might depend on the board configuration and
-devices used on the target system.
-
-Parameters for each memory region can be encoded into the device tree
-with the following convention:
-
-[(label):] (name) {
-       compatible = "linux,contiguous-memory-region", "reserved-memory-region";
-       reg = <(address) (size)>;
-       (linux,default-contiguous-region);
-};
-
-compatible:    one or more of:
-       - "linux,contiguous-memory-region" - enables binding of this
-         region to Contiguous Memory Allocator (special region for
-         contiguous memory allocations, shared with movable system
-         memory, Linux kernel-specific).
-       - "reserved-memory-region" - compatibility is defined, given
-         region is assigned for exclusive usage for by the respective
-         devices.
-
-reg:   standard property defining the base address and size of
-       the memory region
-
-linux,default-contiguous-region: property indicating that the region
-       is the default region for all contiguous memory
-       allocations, Linux specific (optional)
-
-It is optional to specify the base address, so if one wants to use
-autoconfiguration of the base address, '0' can be specified as a base
-address in the 'reg' property.
-
-The /memory/reserved-memory node must contain the same #address-cells
-and #size-cells value as the root node.
-
-
-*** Device node's properties ***
-
-Once regions in the /memory/reserved-memory node have been defined, they
-may be referenced by other device nodes. Bindings that wish to reference
-memory regions should explicitly document their use of the following
-property:
-
-memory-region = <&phandle_to_defined_region>;
-
-This property indicates that the device driver should use the memory
-region pointed by the given phandle.
-
-
-*** Example ***
-
-This example defines a memory consisting of 4 memory banks. 3 contiguous
-regions are defined for Linux kernel, one default of all device drivers
-(named contig_mem, placed at 0x72000000, 64MiB), one dedicated to the
-framebuffer device (labelled display_mem, placed at 0x78000000, 8MiB)
-and one for multimedia processing (labelled multimedia_mem, placed at
-0x77000000, 64MiB). 'display_mem' region is then assigned to fb@12300000
-device for DMA memory allocations (Linux kernel drivers will use CMA is
-available or dma-exclusive usage otherwise). 'multimedia_mem' is
-assigned to scaler@12500000 and codec@12600000 devices for contiguous
-memory allocations when CMA driver is enabled.
-
-The reason for creating a separate region for framebuffer device is to
-match the framebuffer base address to the one configured by bootloader,
-so once Linux kernel drivers starts no glitches on the displayed boot
-logo appears. Scaller and codec drivers should share the memory
-allocations.
-
-/ {
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       /* ... */
-
-       memory {
-               reg =  <0x40000000 0x10000000
-                       0x50000000 0x10000000
-                       0x60000000 0x10000000
-                       0x70000000 0x10000000>;
-
-               reserved-memory {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-
-                       /*
-                        * global autoconfigured region for contiguous allocations
-                        * (used only with Contiguous Memory Allocator)
-                        */
-                       contig_region@0 {
-                               compatible = "linux,contiguous-memory-region";
-                               reg = <0x0 0x4000000>;
-                               linux,default-contiguous-region;
-                       };
-
-                       /*
-                        * special region for framebuffer
-                        */
-                       display_region: region@78000000 {
-                               compatible = "linux,contiguous-memory-region", "reserved-memory-region";
-                               reg = <0x78000000 0x800000>;
-                       };
-
-                       /*
-                        * special region for multimedia processing devices
-                        */
-                       multimedia_region: region@77000000 {
-                               compatible = "linux,contiguous-memory-region";
-                               reg = <0x77000000 0x4000000>;
-                       };
-               };
-       };
-
-       /* ... */
-
-       fb0: fb@12300000 {
-               status = "okay";
-               memory-region = <&display_region>;
-       };
-
-       scaler: scaler@12500000 {
-               status = "okay";
-               memory-region = <&multimedia_region>;
-       };
-
-       codec: codec@12600000 {
-               status = "okay";
-               memory-region = <&multimedia_region>;
-       };
-};
index 425c51d56aefb8b991b3d97b5d3f01564f9baaf6..b8a907dc01697890747ead021b836b4c60c24ae0 100644 (file)
@@ -42,7 +42,7 @@ We can represent these as three OPPs as the following {Hz, uV} tuples:
 
 OPP library provides a set of helper functions to organize and query the OPP
 information. The library is located in drivers/base/power/opp.c and the header
-is located in include/linux/opp.h. OPP library can be enabled by enabling
+is located in include/linux/pm_opp.h. OPP library can be enabled by enabling
 CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on
 CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to
 optionally boot at a certain OPP without needing cpufreq.
@@ -71,14 +71,14 @@ operations until that OPP could be re-enabled if possible.
 
 OPP library facilitates this concept in it's implementation. The following
 operational functions operate only on available opps:
-opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count
-and opp_init_cpufreq_table
+opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count
+and dev_pm_opp_init_cpufreq_table
 
-opp_find_freq_exact is meant to be used to find the opp pointer which can then
-be used for opp_enable/disable functions to make an opp available as required.
+dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer which can then
+be used for dev_pm_opp_enable/disable functions to make an opp available as required.
 
 WARNING: Users of OPP library should refresh their availability count using
-get_opp_count if opp_enable/disable functions are invoked for a device, the
+get_opp_count if dev_pm_opp_enable/disable functions are invoked for a device, the
 exact mechanism to trigger these or the notification mechanism to other
 dependent subsystems such as cpufreq are left to the discretion of the SoC
 specific framework which uses the OPP library. Similar care needs to be taken
@@ -96,24 +96,24 @@ using RCU read locks. The opp_find_freq_{exact,ceil,floor},
 opp_get_{voltage, freq, opp_count} fall into this category.
 
 opp_{add,enable,disable} are updaters which use mutex and implement it's own
-RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses
+RCU locking mechanisms. dev_pm_opp_init_cpufreq_table acts as an updater and uses
 mutex to implment RCU updater strategy. These functions should *NOT* be called
 under RCU locks and other contexts that prevent blocking functions in RCU or
 mutex operations from working.
 
 2. Initial OPP List Registration
 ================================
-The SoC implementation calls opp_add function iteratively to add OPPs per
+The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per
 device. It is expected that the SoC framework will register the OPP entries
 optimally- typical numbers range to be less than 5. The list generated by
 registering the OPPs is maintained by OPP library throughout the device
 operation. The SoC framework can subsequently control the availability of the
-OPPs dynamically using the opp_enable / disable functions.
+OPPs dynamically using the dev_pm_opp_enable / disable functions.
 
-opp_add - Add a new OPP for a specific domain represented by the device pointer.
+dev_pm_opp_add - Add a new OPP for a specific domain represented by the device pointer.
        The OPP is defined using the frequency and voltage. Once added, the OPP
        is assumed to be available and control of it's availability can be done
-       with the opp_enable/disable functions. OPP library internally stores
+       with the dev_pm_opp_enable/disable functions. OPP library internally stores
        and manages this information in the opp struct. This function may be
        used by SoC framework to define a optimal list as per the demands of
        SoC usage environment.
@@ -124,7 +124,7 @@ opp_add - Add a new OPP for a specific domain represented by the device pointer.
         soc_pm_init()
         {
                /* Do things */
-               r = opp_add(mpu_dev, 1000000, 900000);
+               r = dev_pm_opp_add(mpu_dev, 1000000, 900000);
                if (!r) {
                        pr_err("%s: unable to register mpu opp(%d)\n", r);
                        goto no_cpufreq;
@@ -143,44 +143,44 @@ functions return the matching pointer representing the opp if a match is
 found, else returns error. These errors are expected to be handled by standard
 error checks such as IS_ERR() and appropriate actions taken by the caller.
 
-opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
+dev_pm_opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
        availability. This function is especially useful to enable an OPP which
        is not available by default.
        Example: In a case when SoC framework detects a situation where a
        higher frequency could be made available, it can use this function to
-       find the OPP prior to call the opp_enable to actually make it available.
+       find the OPP prior to call the dev_pm_opp_enable to actually make it available.
         rcu_read_lock();
-        opp = opp_find_freq_exact(dev, 1000000000, false);
+        opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
         rcu_read_unlock();
         /* dont operate on the pointer.. just do a sanity check.. */
         if (IS_ERR(opp)) {
                pr_err("frequency not disabled!\n");
                /* trigger appropriate actions.. */
         } else {
-               opp_enable(dev,1000000000);
+               dev_pm_opp_enable(dev,1000000000);
         }
 
        NOTE: This is the only search function that operates on OPPs which are
        not available.
 
-opp_find_freq_floor - Search for an available OPP which is *at most* the
+dev_pm_opp_find_freq_floor - Search for an available OPP which is *at most* the
        provided frequency. This function is useful while searching for a lesser
        match OR operating on OPP information in the order of decreasing
        frequency.
        Example: To find the highest opp for a device:
         freq = ULONG_MAX;
         rcu_read_lock();
-        opp_find_freq_floor(dev, &freq);
+        dev_pm_opp_find_freq_floor(dev, &freq);
         rcu_read_unlock();
 
-opp_find_freq_ceil - Search for an available OPP which is *at least* the
+dev_pm_opp_find_freq_ceil - Search for an available OPP which is *at least* the
        provided frequency. This function is useful while searching for a
        higher match OR operating on OPP information in the order of increasing
        frequency.
        Example 1: To find the lowest opp for a device:
         freq = 0;
         rcu_read_lock();
-        opp_find_freq_ceil(dev, &freq);
+        dev_pm_opp_find_freq_ceil(dev, &freq);
         rcu_read_unlock();
        Example 2: A simplified implementation of a SoC cpufreq_driver->target:
         soc_cpufreq_target(..)
@@ -188,7 +188,7 @@ opp_find_freq_ceil - Search for an available OPP which is *at least* the
                /* Do stuff like policy checks etc. */
                /* Find the best frequency match for the req */
                rcu_read_lock();
-               opp = opp_find_freq_ceil(dev, &freq);
+               opp = dev_pm_opp_find_freq_ceil(dev, &freq);
                rcu_read_unlock();
                if (!IS_ERR(opp))
                        soc_switch_to_freq_voltage(freq);
@@ -208,34 +208,34 @@ as thermal considerations (e.g. don't use OPPx until the temperature drops).
 
 WARNING: Do not use these functions in interrupt context.
 
-opp_enable - Make a OPP available for operation.
+dev_pm_opp_enable - Make a OPP available for operation.
        Example: Lets say that 1GHz OPP is to be made available only if the
        SoC temperature is lower than a certain threshold. The SoC framework
        implementation might choose to do something as follows:
         if (cur_temp < temp_low_thresh) {
                /* Enable 1GHz if it was disabled */
                rcu_read_lock();
-               opp = opp_find_freq_exact(dev, 1000000000, false);
+               opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
                rcu_read_unlock();
                /* just error check */
                if (!IS_ERR(opp))
-                       ret = opp_enable(dev, 1000000000);
+                       ret = dev_pm_opp_enable(dev, 1000000000);
                else
                        goto try_something_else;
         }
 
-opp_disable - Make an OPP to be not available for operation
+dev_pm_opp_disable - Make an OPP to be not available for operation
        Example: Lets say that 1GHz OPP is to be disabled if the temperature
        exceeds a threshold value. The SoC framework implementation might
        choose to do something as follows:
         if (cur_temp > temp_high_thresh) {
                /* Disable 1GHz if it was enabled */
                rcu_read_lock();
-               opp = opp_find_freq_exact(dev, 1000000000, true);
+               opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true);
                rcu_read_unlock();
                /* just error check */
                if (!IS_ERR(opp))
-                       ret = opp_disable(dev, 1000000000);
+                       ret = dev_pm_opp_disable(dev, 1000000000);
                else
                        goto try_something_else;
         }
@@ -247,7 +247,7 @@ information from the OPP structure is necessary. Once an OPP pointer is
 retrieved using the search functions, the following functions can be used by SoC
 framework to retrieve the information represented inside the OPP layer.
 
-opp_get_voltage - Retrieve the voltage represented by the opp pointer.
+dev_pm_opp_get_voltage - Retrieve the voltage represented by the opp pointer.
        Example: At a cpufreq transition to a different frequency, SoC
        framework requires to set the voltage represented by the OPP using
        the regulator framework to the Power Management chip providing the
@@ -256,15 +256,15 @@ opp_get_voltage - Retrieve the voltage represented by the opp pointer.
         {
                /* do things */
                rcu_read_lock();
-               opp = opp_find_freq_ceil(dev, &freq);
-               v = opp_get_voltage(opp);
+               opp = dev_pm_opp_find_freq_ceil(dev, &freq);
+               v = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
                if (v)
                        regulator_set_voltage(.., v);
                /* do other things */
         }
 
-opp_get_freq - Retrieve the freq represented by the opp pointer.
+dev_pm_opp_get_freq - Retrieve the freq represented by the opp pointer.
        Example: Lets say the SoC framework uses a couple of helper functions
        we could pass opp pointers instead of doing additional parameters to
        handle quiet a bit of data parameters.
@@ -273,8 +273,8 @@ opp_get_freq - Retrieve the freq represented by the opp pointer.
                /* do things.. */
                 max_freq = ULONG_MAX;
                 rcu_read_lock();
-                max_opp = opp_find_freq_floor(dev,&max_freq);
-                requested_opp = opp_find_freq_ceil(dev,&freq);
+                max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq);
+                requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq);
                 if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
                        r = soc_test_validity(max_opp, requested_opp);
                 rcu_read_unlock();
@@ -282,25 +282,25 @@ opp_get_freq - Retrieve the freq represented by the opp pointer.
         }
         soc_test_validity(..)
         {
-                if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp))
+                if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp))
                         return -EINVAL;
-                if(opp_get_freq(max_opp) < opp_get_freq(requested_opp))
+                if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp))
                         return -EINVAL;
                /* do things.. */
         }
 
-opp_get_opp_count - Retrieve the number of available opps for a device
+dev_pm_opp_get_opp_count - Retrieve the number of available opps for a device
        Example: Lets say a co-processor in the SoC needs to know the available
        frequencies in a table, the main processor can notify as following:
         soc_notify_coproc_available_frequencies()
         {
                /* Do things */
                rcu_read_lock();
-               num_available = opp_get_opp_count(dev);
+               num_available = dev_pm_opp_get_opp_count(dev);
                speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
                /* populate the table in increasing order */
                freq = 0;
-               while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) {
+               while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) {
                        speeds[i] = freq;
                        freq++;
                        i++;
@@ -313,7 +313,7 @@ opp_get_opp_count - Retrieve the number of available opps for a device
 
 6. Cpufreq Table Generation
 ===========================
-opp_init_cpufreq_table - cpufreq framework typically is initialized with
+dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
        cpufreq_frequency_table_cpuinfo which is provided with the list of
        frequencies that are available for operation. This function provides
        a ready to use conversion routine to translate the OPP layer's internal
@@ -326,7 +326,7 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with
         soc_pm_init()
         {
                /* Do things */
-               r = opp_init_cpufreq_table(dev, &freq_table);
+               r = dev_pm_opp_init_cpufreq_table(dev, &freq_table);
                if (!r)
                        cpufreq_frequency_table_cpuinfo(policy, freq_table);
                /* Do other things */
@@ -336,7 +336,7 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with
        addition to CONFIG_PM as power management feature is required to
        dynamically scale voltage and frequency in a system.
 
-opp_free_cpufreq_table - Free up the table allocated by opp_init_cpufreq_table
+dev_pm_opp_free_cpufreq_table - Free up the table allocated by dev_pm_opp_init_cpufreq_table
 
 7. Data Structures
 ==================
@@ -358,16 +358,16 @@ accessed by various functions as described above. However, the structures
 representing the actual OPPs and domains are internal to the OPP library itself
 to allow for suitable abstraction reusable across systems.
 
-struct opp - The internal data structure of OPP library which is used to
+struct dev_pm_opp - The internal data structure of OPP library which is used to
        represent an OPP. In addition to the freq, voltage, availability
        information, it also contains internal book keeping information required
        for the OPP library to operate on.  Pointer to this structure is
        provided back to the users such as SoC framework to be used as a
        identifier for OPP in the interactions with OPP layer.
 
-       WARNING: The struct opp pointer should not be parsed or modified by the
-       users. The defaults of for an instance is populated by opp_add, but the
-       availability of the OPP can be modified by opp_enable/disable functions.
+       WARNING: The struct dev_pm_opp pointer should not be parsed or modified by the
+       users. The defaults of for an instance is populated by dev_pm_opp_add, but the
+       availability of the OPP can be modified by dev_pm_opp_enable/disable functions.
 
 struct device - This is used to identify a domain to the OPP layer. The
        nature of the device and it's implementation is left to the user of
@@ -377,19 +377,19 @@ Overall, in a simplistic view, the data structure operations is represented as
 following:
 
 Initialization / modification:
-            +-----+        /- opp_enable
-opp_add --> | opp | <-------
-  |         +-----+        \- opp_disable
+            +-----+        /- dev_pm_opp_enable
+dev_pm_opp_add --> | opp | <-------
+  |         +-----+        \- dev_pm_opp_disable
   \-------> domain_info(device)
 
 Search functions:
-             /-- opp_find_freq_ceil  ---\   +-----+
-domain_info<---- opp_find_freq_exact -----> | opp |
-             \-- opp_find_freq_floor ---/   +-----+
+             /-- dev_pm_opp_find_freq_ceil  ---\   +-----+
+domain_info<---- dev_pm_opp_find_freq_exact -----> | opp |
+             \-- dev_pm_opp_find_freq_floor ---/   +-----+
 
 Retrieval functions:
-+-----+     /- opp_get_voltage
++-----+     /- dev_pm_opp_get_voltage
 | opp | <---
-+-----+     \- opp_get_freq
++-----+     \- dev_pm_opp_get_freq
 
-domain_info <- opp_get_opp_count
+domain_info <- dev_pm_opp_get_opp_count
diff --git a/Documentation/power/powercap/powercap.txt b/Documentation/power/powercap/powercap.txt
new file mode 100644 (file)
index 0000000..1e6ef16
--- /dev/null
@@ -0,0 +1,236 @@
+Power Capping Framework
+==================================
+
+The power capping framework provides a consistent interface between the kernel
+and the user space that allows power capping drivers to expose the settings to
+user space in a uniform way.
+
+Terminology
+=========================
+The framework exposes power capping devices to user space via sysfs in the
+form of a tree of objects. The objects at the root level of the tree represent
+'control types', which correspond to different methods of power capping.  For
+example, the intel-rapl control type represents the Intel "Running Average
+Power Limit" (RAPL) technology, whereas the 'idle-injection' control type
+corresponds to the use of idle injection for controlling power.
+
+Power zones represent different parts of the system, which can be controlled and
+monitored using the power capping method determined by the control type the
+given zone belongs to. They each contain attributes for monitoring power, as
+well as controls represented in the form of power constraints.  If the parts of
+the system represented by different power zones are hierarchical (that is, one
+bigger part consists of multiple smaller parts that each have their own power
+controls), those power zones may also be organized in a hierarchy with one
+parent power zone containing multiple subzones and so on to reflect the power
+control topology of the system.  In that case, it is possible to apply power
+capping to a set of devices together using the parent power zone and if more
+fine grained control is required, it can be applied through the subzones.
+
+
+Example sysfs interface tree:
+
+/sys/devices/virtual/powercap
+??? intel-rapl
+    ??? intel-rapl:0
+    ?   ??? constraint_0_name
+    ?   ??? constraint_0_power_limit_uw
+    ?   ??? constraint_0_time_window_us
+    ?   ??? constraint_1_name
+    ?   ??? constraint_1_power_limit_uw
+    ?   ??? constraint_1_time_window_us
+    ?   ??? device -> ../../intel-rapl
+    ?   ??? energy_uj
+    ?   ??? intel-rapl:0:0
+    ?   ?   ??? constraint_0_name
+    ?   ?   ??? constraint_0_power_limit_uw
+    ?   ?   ??? constraint_0_time_window_us
+    ?   ?   ??? constraint_1_name
+    ?   ?   ??? constraint_1_power_limit_uw
+    ?   ?   ??? constraint_1_time_window_us
+    ?   ?   ??? device -> ../../intel-rapl:0
+    ?   ?   ??? energy_uj
+    ?   ?   ??? max_energy_range_uj
+    ?   ?   ??? name
+    ?   ?   ??? enabled
+    ?   ?   ??? power
+    ?   ?   ?   ??? async
+    ?   ?   ?   []
+    ?   ?   ??? subsystem -> ../../../../../../class/power_cap
+    ?   ?   ??? uevent
+    ?   ??? intel-rapl:0:1
+    ?   ?   ??? constraint_0_name
+    ?   ?   ??? constraint_0_power_limit_uw
+    ?   ?   ??? constraint_0_time_window_us
+    ?   ?   ??? constraint_1_name
+    ?   ?   ??? constraint_1_power_limit_uw
+    ?   ?   ??? constraint_1_time_window_us
+    ?   ?   ??? device -> ../../intel-rapl:0
+    ?   ?   ??? energy_uj
+    ?   ?   ??? max_energy_range_uj
+    ?   ?   ??? name
+    ?   ?   ??? enabled
+    ?   ?   ??? power
+    ?   ?   ?   ??? async
+    ?   ?   ?   []
+    ?   ?   ??? subsystem -> ../../../../../../class/power_cap
+    ?   ?   ??? uevent
+    ?   ??? max_energy_range_uj
+    ?   ??? max_power_range_uw
+    ?   ??? name
+    ?   ??? enabled
+    ?   ??? power
+    ?   ?   ??? async
+    ?   ?   []
+    ?   ??? subsystem -> ../../../../../class/power_cap
+    ?   ??? enabled
+    ?   ??? uevent
+    ??? intel-rapl:1
+    ?   ??? constraint_0_name
+    ?   ??? constraint_0_power_limit_uw
+    ?   ??? constraint_0_time_window_us
+    ?   ??? constraint_1_name
+    ?   ??? constraint_1_power_limit_uw
+    ?   ??? constraint_1_time_window_us
+    ?   ??? device -> ../../intel-rapl
+    ?   ??? energy_uj
+    ?   ??? intel-rapl:1:0
+    ?   ?   ??? constraint_0_name
+    ?   ?   ??? constraint_0_power_limit_uw
+    ?   ?   ??? constraint_0_time_window_us
+    ?   ?   ??? constraint_1_name
+    ?   ?   ??? constraint_1_power_limit_uw
+    ?   ?   ??? constraint_1_time_window_us
+    ?   ?   ??? device -> ../../intel-rapl:1
+    ?   ?   ??? energy_uj
+    ?   ?   ??? max_energy_range_uj
+    ?   ?   ??? name
+    ?   ?   ??? enabled
+    ?   ?   ??? power
+    ?   ?   ?   ??? async
+    ?   ?   ?   []
+    ?   ?   ??? subsystem -> ../../../../../../class/power_cap
+    ?   ?   ??? uevent
+    ?   ??? intel-rapl:1:1
+    ?   ?   ??? constraint_0_name
+    ?   ?   ??? constraint_0_power_limit_uw
+    ?   ?   ??? constraint_0_time_window_us
+    ?   ?   ??? constraint_1_name
+    ?   ?   ??? constraint_1_power_limit_uw
+    ?   ?   ??? constraint_1_time_window_us
+    ?   ?   ??? device -> ../../intel-rapl:1
+    ?   ?   ??? energy_uj
+    ?   ?   ??? max_energy_range_uj
+    ?   ?   ??? name
+    ?   ?   ??? enabled
+    ?   ?   ??? power
+    ?   ?   ?   ??? async
+    ?   ?   ?   []
+    ?   ?   ??? subsystem -> ../../../../../../class/power_cap
+    ?   ?   ??? uevent
+    ?   ??? max_energy_range_uj
+    ?   ??? max_power_range_uw
+    ?   ??? name
+    ?   ??? enabled
+    ?   ??? power
+    ?   ?   ??? async
+    ?   ?   []
+    ?   ??? subsystem -> ../../../../../class/power_cap
+    ?   ??? uevent
+    ??? power
+    ?   ??? async
+    ?   []
+    ??? subsystem -> ../../../../class/power_cap
+    ??? enabled
+    ??? uevent
+
+The above example illustrates a case in which the Intel RAPL technology,
+available in Intel® IA-64 and IA-32 Processor Architectures, is used. There is one
+control type called intel-rapl which contains two power zones, intel-rapl:0 and
+intel-rapl:1, representing CPU packages.  Each of these power zones contains
+two subzones, intel-rapl:j:0 and intel-rapl:j:1 (j = 0, 1), representing the
+"core" and the "uncore" parts of the given CPU package, respectively.  All of
+the zones and subzones contain energy monitoring attributes (energy_uj,
+max_energy_range_uj) and constraint attributes (constraint_*) allowing controls
+to be applied (the constraints in the 'package' power zones apply to the whole
+CPU packages and the subzone constraints only apply to the respective parts of
+the given package individually). Since Intel RAPL doesn't provide instantaneous
+power value, there is no power_uw attribute.
+
+In addition to that, each power zone contains a name attribute, allowing the
+part of the system represented by that zone to be identified.
+For example:
+
+cat /sys/class/power_cap/intel-rapl/intel-rapl:0/name
+package-0
+
+The Intel RAPL technology allows two constraints, short term and long term,
+with two different time windows to be applied to each power zone.  Thus for
+each zone there are 2 attributes representing the constraint names, 2 power
+limits and 2 attributes representing the sizes of the time windows. Such that,
+constraint_j_* attributes correspond to the jth constraint (j = 0,1).
+
+For example:
+       constraint_0_name
+       constraint_0_power_limit_uw
+       constraint_0_time_window_us
+       constraint_1_name
+       constraint_1_power_limit_uw
+       constraint_1_time_window_us
+
+Power Zone Attributes
+=================================
+Monitoring attributes
+----------------------
+
+energy_uj (rw): Current energy counter in micro joules. Write "0" to reset.
+If the counter can not be reset, then this attribute is read only.
+
+max_energy_range_uj (ro): Range of the above energy counter in micro-joules.
+
+power_uw (ro): Current power in micro watts.
+
+max_power_range_uw (ro): Range of the above power value in micro-watts.
+
+name (ro): Name of this power zone.
+
+It is possible that some domains have both power ranges and energy counter ranges;
+however, only one is mandatory.
+
+Constraints
+----------------
+constraint_X_power_limit_uw (rw): Power limit in micro watts, which should be
+applicable for the time window specified by "constraint_X_time_window_us".
+
+constraint_X_time_window_us (rw): Time window in micro seconds.
+
+constraint_X_name (ro): An optional name of the constraint
+
+constraint_X_max_power_uw(ro): Maximum allowed power in micro watts.
+
+constraint_X_min_power_uw(ro): Minimum allowed power in micro watts.
+
+constraint_X_max_time_window_us(ro): Maximum allowed time window in micro seconds.
+
+constraint_X_min_time_window_us(ro): Minimum allowed time window in micro seconds.
+
+Except power_limit_uw and time_window_us other fields are optional.
+
+Common zone and control type attributes
+----------------------------------------
+enabled (rw): Enable/Disable controls at zone level or for all zones using
+a control type.
+
+Power Cap Client Driver Interface
+==================================
+The API summary:
+
+Call powercap_register_control_type() to register control type object.
+Call powercap_register_zone() to register a power zone (under a given
+control type), either as a top-level power zone or as a subzone of another
+power zone registered earlier.
+The number of constraints in a power zone and the corresponding callbacks have
+to be defined prior to calling powercap_register_zone() to register that zone.
+
+To Free a power zone call powercap_unregister_zone().
+To free a control type object call powercap_unregister_control_type().
+Detailed API can be generated using kernel-doc on include/linux/powercap.h.
index 8a0cbf3cf2c8c01c5be662eef372eff4060daffc..45cdfa3e106702165e7efd8ff09b015fb843d065 100644 (file)
@@ -237,11 +237,11 @@ F:        drivers/platform/x86/acer-wmi.c
 
 ACPI
 M:     Len Brown <lenb@kernel.org>
-M:     Rafael J. Wysocki <rjw@sisk.pl>
+M:     Rafael J. Wysocki <rjw@rjwysocki.net>
 L:     linux-acpi@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
-Q:     http://patchwork.kernel.org/project/linux-acpi/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
+W:     https://01.org/linux-acpi
+Q:     https://patchwork.kernel.org/project/linux-acpi/list/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
 S:     Supported
 F:     drivers/acpi/
 F:     drivers/pnp/pnpacpi/
@@ -253,24 +253,38 @@ F:        drivers/pci/*acpi*
 F:     drivers/pci/*/*acpi*
 F:     drivers/pci/*/*/*acpi*
 
+ACPI COMPONENT ARCHITECTURE (ACPICA)
+M:     Robert Moore <robert.moore@intel.com>
+M:     Lv Zheng <lv.zheng@intel.com>
+M:     Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+L:     linux-acpi@vger.kernel.org
+L:     devel@acpica.org
+W:     https://acpica.org/
+W:     https://github.com/acpica/acpica/
+Q:     https://patchwork.kernel.org/project/linux-acpi/list/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
+S:     Supported
+F:     drivers/acpi/acpica/
+F:     include/acpi/
+
 ACPI FAN DRIVER
 M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
+W:     https://01.org/linux-acpi
 S:     Supported
 F:     drivers/acpi/fan.c
 
 ACPI THERMAL DRIVER
 M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
+W:     https://01.org/linux-acpi
 S:     Supported
 F:     drivers/acpi/*thermal*
 
 ACPI VIDEO DRIVER
 M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
+W:     https://01.org/linux-acpi
 S:     Supported
 F:     drivers/acpi/video.c
 
@@ -1009,6 +1023,7 @@ ARM/Marvell Armada 370 and Armada XP SOC support
 M:     Jason Cooper <jason@lakedaemon.net>
 M:     Andrew Lunn <andrew@lunn.ch>
 M:     Gregory Clement <gregory.clement@free-electrons.com>
+M:     Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-mvebu/
@@ -1016,6 +1031,7 @@ F:        arch/arm/mach-mvebu/
 ARM/Marvell Dove/Kirkwood/MV78xx0/Orion SOC support
 M:     Jason Cooper <jason@lakedaemon.net>
 M:     Andrew Lunn <andrew@lunn.ch>
+M:     Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-dove/
@@ -1148,6 +1164,13 @@ F:       drivers/net/ethernet/i825xx/ether1*
 F:     drivers/net/ethernet/seeq/ether3*
 F:     drivers/scsi/arm/
 
+ARM/Rockchip SoC support
+M:     Heiko Stuebner <heiko@sntech.de>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-rockchip/
+F:     drivers/*/*rockchip*
+
 ARM/SHARK MACHINE SUPPORT
 M:     Alexander Schulz <alex@shark-linux.de>
 W:     http://www.shark-linux.de/shark.html
@@ -1791,6 +1814,7 @@ F:        include/net/bluetooth/
 
 BONDING DRIVER
 M:     Jay Vosburgh <fubar@us.ibm.com>
+M:     Veaceslav Falico <vfalico@redhat.com>
 M:     Andy Gospodarek <andy@greyhouse.net>
 L:     netdev@vger.kernel.org
 W:     http://sourceforge.net/projects/bonding/
@@ -2300,7 +2324,7 @@ S:        Maintained
 F:     drivers/net/ethernet/ti/cpmac.c
 
 CPU FREQUENCY DRIVERS
-M:     Rafael J. Wysocki <rjw@sisk.pl>
+M:     Rafael J. Wysocki <rjw@rjwysocki.net>
 M:     Viresh Kumar <viresh.kumar@linaro.org>
 L:     cpufreq@vger.kernel.org
 L:     linux-pm@vger.kernel.org
@@ -2331,7 +2355,7 @@ S:      Maintained
 F:      drivers/cpuidle/cpuidle-big_little.c
 
 CPUIDLE DRIVERS
-M:     Rafael J. Wysocki <rjw@sisk.pl>
+M:     Rafael J. Wysocki <rjw@rjwysocki.net>
 M:     Daniel Lezcano <daniel.lezcano@linaro.org>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
@@ -2718,6 +2742,8 @@ T:        git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
 DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
 M:     Vinod Koul <vinod.koul@intel.com>
 M:     Dan Williams <dan.j.williams@intel.com>
+L:     dmaengine@vger.kernel.org
+Q:     https://patchwork.kernel.org/project/linux-dmaengine/list/
 S:     Supported
 F:     drivers/dma/
 F:     include/linux/dma*
@@ -2821,7 +2847,7 @@ M:        Terje Bergström <tbergstrom@nvidia.com>
 L:     dri-devel@lists.freedesktop.org
 L:     linux-tegra@vger.kernel.org
 T:     git git://anongit.freedesktop.org/tegra/linux.git
-S:     Maintained
+S:     Supported
 F:     drivers/gpu/host1x/
 F:     include/uapi/drm/tegra_drm.h
 F:     Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
@@ -3553,7 +3579,7 @@ F:        fs/freevxfs/
 
 FREEZER
 M:     Pavel Machek <pavel@ucw.cz>
-M:     "Rafael J. Wysocki" <rjw@sisk.pl>
+M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 F:     Documentation/power/freezing-of-tasks.txt
@@ -3624,6 +3650,12 @@ L:       linux-scsi@vger.kernel.org
 S:     Odd Fixes (e.g., new signatures)
 F:     drivers/scsi/fdomain.*
 
+GCOV BASED KERNEL PROFILING
+M:     Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
+S:     Maintained
+F:     kernel/gcov/
+F:     Documentation/gcov.txt
+
 GDT SCSI DISK ARRAY CONTROLLER DRIVER
 M:     Achim Leubner <achim_leubner@adaptec.com>
 L:     linux-scsi@vger.kernel.org
@@ -3889,7 +3921,7 @@ F:        drivers/video/hgafb.c
 
 HIBERNATION (aka Software Suspend, aka swsusp)
 M:     Pavel Machek <pavel@ucw.cz>
-M:     "Rafael J. Wysocki" <rjw@sisk.pl>
+M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 F:     arch/x86/power/
@@ -4339,7 +4371,7 @@ F:        drivers/video/i810/
 INTEL MENLOW THERMAL DRIVER
 M:     Sujith Thomas <sujith.thomas@intel.com>
 L:     platform-driver-x86@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
+W:     https://01.org/linux-acpi
 S:     Supported
 F:     drivers/platform/x86/intel_menlow.c
 
@@ -4351,7 +4383,10 @@ F:       arch/x86/kernel/microcode_intel.c
 
 INTEL I/OAT DMA DRIVER
 M:     Dan Williams <dan.j.williams@intel.com>
-S:     Maintained
+M:     Dave Jiang <dave.jiang@intel.com>
+L:     dmaengine@vger.kernel.org
+Q:     https://patchwork.kernel.org/project/linux-dmaengine/list/
+S:     Supported
 F:     drivers/dma/ioat*
 
 INTEL IOMMU (VT-d)
@@ -7816,6 +7851,13 @@ F:       Documentation/sound/alsa/soc/
 F:     sound/soc/
 F:     include/sound/soc*
 
+SOUND - DMAENGINE HELPERS
+M:     Lars-Peter Clausen <lars@metafoo.de>
+S:     Supported
+F:     include/sound/dmaengine_pcm.h
+F:     sound/core/pcm_dmaengine.c
+F:     sound/soc/soc-generic-dmaengine-pcm.c
+
 SPARC + UltraSPARC (sparc/sparc64)
 M:     "David S. Miller" <davem@davemloft.net>
 L:     sparclinux@vger.kernel.org
@@ -8095,7 +8137,7 @@ F:        drivers/sh/
 SUSPEND TO RAM
 M:     Len Brown <len.brown@intel.com>
 M:     Pavel Machek <pavel@ucw.cz>
-M:     "Rafael J. Wysocki" <rjw@sisk.pl>
+M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 F:     Documentation/power/
@@ -8288,14 +8330,72 @@ L:      linux-media@vger.kernel.org
 S:     Maintained
 F:     drivers/media/rc/ttusbir.c
 
-TEGRA SUPPORT
+TEGRA ARCHITECTURE SUPPORT
 M:     Stephen Warren <swarren@wwwdotorg.org>
+M:     Thierry Reding <thierry.reding@gmail.com>
 L:     linux-tegra@vger.kernel.org
 Q:     http://patchwork.ozlabs.org/project/linux-tegra/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git
 S:     Supported
 N:     [^a-z]tegra
 
+TEGRA ASOC DRIVER
+M:     Stephen Warren <swarren@wwwdotorg.org>
+S:     Supported
+F:     sound/soc/tegra/
+
+TEGRA CLOCK DRIVER
+M:     Peter De Schrijver <pdeschrijver@nvidia.com>
+M:     Prashant Gaikwad <pgaikwad@nvidia.com>
+S:     Supported
+F:     drivers/clk/tegra/
+
+TEGRA DMA DRIVER
+M:     Laxman Dewangan <ldewangan@nvidia.com>
+S:     Supported
+F:     drivers/dma/tegra20-apb-dma.c
+
+TEGRA GPIO DRIVER
+M:     Stephen Warren <swarren@wwwdotorg.org>
+S:     Supported
+F:     drivers/gpio/gpio-tegra.c
+
+TEGRA I2C DRIVER
+M:     Laxman Dewangan <ldewangan@nvidia.com>
+S:     Supported
+F:     drivers/i2c/busses/i2c-tegra.c
+
+TEGRA IOMMU DRIVERS
+M:     Hiroshi Doyu <hdoyu@nvidia.com>
+S:     Supported
+F:     drivers/iommu/tegra*
+
+TEGRA KBC DRIVER
+M:     Rakesh Iyer <riyer@nvidia.com>
+M:     Laxman Dewangan <ldewangan@nvidia.com>
+S:     Supported
+F:     drivers/input/keyboard/tegra-kbc.c
+
+TEGRA PINCTRL DRIVER
+M:     Stephen Warren <swarren@wwwdotorg.org>
+S:     Supported
+F:     drivers/pinctrl/pinctrl-tegra*
+
+TEGRA PWM DRIVER
+M:     Thierry Reding <thierry.reding@gmail.com>
+S:     Supported
+F:     drivers/pwm/pwm-tegra.c
+
+TEGRA SERIAL DRIVER
+M:     Laxman Dewangan <ldewangan@nvidia.com>
+S:     Supported
+F:     drivers/tty/serial/serial-tegra.c
+
+TEGRA SPI DRIVER
+M:     Laxman Dewangan <ldewangan@nvidia.com>
+S:     Supported
+F:     drivers/spi/spi-tegra*
+
 TEHUTI ETHERNET DRIVER
 M:     Andy Gospodarek <andy@greyhouse.net>
 L:     netdev@vger.kernel.org
index deec08b7612b4c0d903ca6c9323eddaac6e4ea08..868c0eb67b081bcedbb9a284c0fdd2ec6f1af8ee 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 12
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc7
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
index ff1aea0ee04322bf26688e1bf8892b60b02a69ce..72693a69f8300421f687f404ffa9f95768ea33d3 100644 (file)
@@ -9,11 +9,6 @@
        model = "ARM Integrator/CP";
        compatible = "arm,integrator-cp";
 
-       aliases {
-               arm,timer-primary = &timer2;
-               arm,timer-secondary = &timer1;
-       };
-
        chosen {
                bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
        };
        };
 
        timer0: timer@13000000 {
+               /* TIMER0 runs @ 25MHz */
                compatible = "arm,integrator-cp-timer";
+               status = "disabled";
        };
 
        timer1: timer@13000100 {
+               /* TIMER1 runs @ 1MHz */
                compatible = "arm,integrator-cp-timer";
        };
 
        timer2: timer@13000200 {
+               /* TIMER2 runs @ 1MHz */
                compatible = "arm,integrator-cp-timer";
        };
 
index 370236dd1a03309ee3b123e705aa80132c908427..990250965f2cfb4e4e3a984678fcf62eedbcdb8d 100644 (file)
@@ -51,7 +51,8 @@ void mcpm_cpu_power_down(void)
 {
        phys_reset_t phys_reset;
 
-       BUG_ON(!platform_ops);
+       if (WARN_ON_ONCE(!platform_ops || !platform_ops->power_down))
+               return;
        BUG_ON(!irqs_disabled());
 
        /*
@@ -93,7 +94,8 @@ void mcpm_cpu_suspend(u64 expected_residency)
 {
        phys_reset_t phys_reset;
 
-       BUG_ON(!platform_ops);
+       if (WARN_ON_ONCE(!platform_ops || !platform_ops->suspend))
+               return;
        BUG_ON(!irqs_disabled());
 
        /* Very similar to mcpm_cpu_power_down() */
index d56c932580eb201439c8a63aa401abddd157cbbf..025f6ce38596736eea2c929a211b23fd4eaf0d56 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <asm/mach/sharpsl_param.h>
+#include <asm/memory.h>
 
 /*
  * Certain hardware parameters determined at the time of device manufacture,
  */
 #ifdef CONFIG_ARCH_SA1100
 #define PARAM_BASE     0xe8ffc000
+#define param_start(x) (void *)(x)
 #else
 #define PARAM_BASE     0xa0000a00
+#define param_start(x) __va(x)
 #endif
 #define MAGIC_CHG(a,b,c,d) ( ( d << 24 ) | ( c << 16 )  | ( b << 8 ) | a )
 
@@ -41,7 +44,7 @@ EXPORT_SYMBOL(sharpsl_param);
 
 void sharpsl_save_param(void)
 {
-       memcpy(&sharpsl_param, (void *)PARAM_BASE, sizeof(struct sharpsl_param_info));
+       memcpy(&sharpsl_param, param_start(PARAM_BASE), sizeof(struct sharpsl_param_info));
 
        if (sharpsl_param.comadj_keyword != COMADJ_MAGIC)
                sharpsl_param.comadj=-1;
index d3db39860b9cc5eb83053f99f9430b926443609c..59ceae8f3c959616851a21ba3f08ae18941146ca 100644 (file)
@@ -31,5 +31,4 @@ generic-y += termbits.h
 generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
-generic-y += types.h
 generic-y += unaligned.h
index 0f7b7620e9a554b0b4a0ba4939a60c905e0a435c..fc82a88f5b69e556e9235583364b5149b2572b66 100644 (file)
@@ -76,8 +76,11 @@ int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster);
  *
  * This must be called with interrupts disabled.
  *
- * This does not return.  Re-entry in the kernel is expected via
- * mcpm_entry_point.
+ * On success this does not return.  Re-entry in the kernel is expected
+ * via mcpm_entry_point.
+ *
+ * This will return if mcpm_platform_register() has not been called
+ * previously in which case the caller should take appropriate action.
  */
 void mcpm_cpu_power_down(void);
 
@@ -98,8 +101,11 @@ void mcpm_cpu_power_down(void);
  *
  * This must be called with interrupts disabled.
  *
- * This does not return.  Re-entry in the kernel is expected via
- * mcpm_entry_point.
+ * On success this does not return.  Re-entry in the kernel is expected
+ * via mcpm_entry_point.
+ *
+ * This will return if mcpm_platform_register() has not been called
+ * previously in which case the caller should take appropriate action.
  */
 void mcpm_cpu_suspend(u64 expected_residency);
 
index f1d96d4e8092a652aeb84f5825082a8f9064cd20..73ddd7239b33aa77d178ae1341c0c46c736a08e5 100644 (file)
@@ -57,6 +57,9 @@ static inline void syscall_get_arguments(struct task_struct *task,
                                         unsigned int i, unsigned int n,
                                         unsigned long *args)
 {
+       if (n == 0)
+               return;
+
        if (i + n > SYSCALL_MAX_ARGS) {
                unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
                unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
@@ -81,6 +84,9 @@ static inline void syscall_set_arguments(struct task_struct *task,
                                         unsigned int i, unsigned int n,
                                         const unsigned long *args)
 {
+       if (n == 0)
+               return;
+
        if (i + n > SYSCALL_MAX_ARGS) {
                pr_warning("%s called with max args %d, handling only %d\n",
                           __func__, i + n, SYSCALL_MAX_ARGS);
index 2c7cc1e03473aee9463e86d7dbedfc999f6e51f7..476de57dcef284602e126e29e2da03465df8ff09 100644 (file)
@@ -487,7 +487,26 @@ __fixup_smp:
        mrc     p15, 0, r0, c0, c0, 5   @ read MPIDR
        and     r0, r0, #0xc0000000     @ multiprocessing extensions and
        teq     r0, #0x80000000         @ not part of a uniprocessor system?
-       moveq   pc, lr                  @ yes, assume SMP
+       bne    __fixup_smp_on_up        @ no, assume UP
+
+       @ Core indicates it is SMP. Check for Aegis SOC where a single
+       @ Cortex-A9 CPU is present but SMP operations fault.
+       mov     r4, #0x41000000
+       orr     r4, r4, #0x0000c000
+       orr     r4, r4, #0x00000090
+       teq     r3, r4                  @ Check for ARM Cortex-A9
+       movne   pc, lr                  @ Not ARM Cortex-A9,
+
+       @ If a future SoC *does* use 0x0 as the PERIPH_BASE, then the
+       @ below address check will need to be #ifdef'd or equivalent
+       @ for the Aegis platform.
+       mrc     p15, 4, r0, c15, c0     @ get SCU base address
+       teq     r0, #0x0                @ '0' on actual UP A9 hardware
+       beq     __fixup_smp_on_up       @ So its an A9 UP
+       ldr     r0, [r0, #4]            @ read SCU Config
+       and     r0, r0, #0x3            @ number of CPUs
+       teq     r0, #0x0                @ is 1?
+       movne   pc, lr
 
 __fixup_smp_on_up:
        adr     r0, 1f
index 3b0a9538093c168cb4cd80f4ff559b0458d0dfb3..c1b737097c9543faf67c4ed78f2617e3add0606f 100644 (file)
@@ -98,7 +98,6 @@ obj-y                         += leds.o
 # Power Management
 obj-$(CONFIG_PM)               += pm.o
 obj-$(CONFIG_AT91_SLOW_CLOCK)  += pm_slowclock.o
-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
 
 ifeq ($(CONFIG_PM_DEBUG),y)
 CFLAGS_pm.o += -DDEBUG
index 4aad93d54d6f059cc275ac819d7c55df196df4b1..25805f2f6010f3d7b98035f9c8e3b1e09524a4e3 100644 (file)
@@ -27,6 +27,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -327,6 +328,7 @@ static void __init at91rm9200_ioremap_registers(void)
 {
        at91rm9200_ioremap_st(AT91RM9200_BASE_ST);
        at91_ioremap_ramc(0, AT91RM9200_BASE_MC, 256);
+       at91_pm_set_standby(at91rm9200_standby);
 }
 
 static void __init at91rm9200_initialize(void)
index 5de6074b4f4f3681d308cfb34a8554a05550b2f2..f8629a3fa2452791b6215c19f77124813e1d3f5f 100644 (file)
@@ -28,6 +28,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -342,6 +343,7 @@ static void __init at91sam9260_ioremap_registers(void)
        at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC);
        at91_ioremap_matrix(AT91SAM9260_BASE_MATRIX);
+       at91_pm_set_standby(at91sam9_sdram_standby);
 }
 
 static void __init at91sam9260_initialize(void)
index 0e0793241ab7e1938dc4ec3fd961557344342369..1f3867a17a289beee4bb1a44ae64ca3bc96b044d 100644 (file)
@@ -27,6 +27,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -284,6 +285,7 @@ static void __init at91sam9261_ioremap_registers(void)
        at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC);
        at91_ioremap_matrix(AT91SAM9261_BASE_MATRIX);
+       at91_pm_set_standby(at91sam9_sdram_standby);
 }
 
 static void __init at91sam9261_initialize(void)
index 6ce7d18508934a428ea2ac94ab51162b683b43d1..90d455d294a1814e7e72722b5614b4d15548c298 100644 (file)
@@ -26,6 +26,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -321,6 +322,7 @@ static void __init at91sam9263_ioremap_registers(void)
        at91sam9_ioremap_smc(0, AT91SAM9263_BASE_SMC0);
        at91sam9_ioremap_smc(1, AT91SAM9263_BASE_SMC1);
        at91_ioremap_matrix(AT91SAM9263_BASE_MATRIX);
+       at91_pm_set_standby(at91sam9_sdram_standby);
 }
 
 static void __init at91sam9263_initialize(void)
index 474ee04d24b93729bdf32e2e4d64a7db0ea9bed8..e9bf0b8f40eb745d317e2d1d50c500eea1491aa4 100644 (file)
@@ -26,6 +26,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -370,6 +371,7 @@ static void __init at91sam9g45_ioremap_registers(void)
        at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9G45_BASE_SMC);
        at91_ioremap_matrix(AT91SAM9G45_BASE_MATRIX);
+       at91_pm_set_standby(at91_ddr_standby);
 }
 
 static void __init at91sam9g45_initialize(void)
index d4ec0d9a9872660e22f2e3c95fc2e8c154cf38e6..88995af09c043abf6198124d1c651d60ac03b0ff 100644 (file)
@@ -27,6 +27,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -287,6 +288,7 @@ static void __init at91sam9rl_ioremap_registers(void)
        at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC);
        at91_ioremap_matrix(AT91SAM9RL_BASE_MATRIX);
+       at91_pm_set_standby(at91sam9_sdram_standby);
 }
 
 static void __init at91sam9rl_initialize(void)
diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c
deleted file mode 100644 (file)
index 4ec6a6d..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * based on arch/arm/mach-kirkwood/cpuidle.c
- *
- * CPU idle support for AT91 SoC
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- *
- * The cpu idle uses wait-for-interrupt and RAM self refresh in order
- * to implement two idle states -
- * #1 wait-for-interrupt
- * #2 wait-for-interrupt and RAM self refresh
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/cpuidle.h>
-#include <linux/io.h>
-#include <linux/export.h>
-#include <asm/proc-fns.h>
-#include <asm/cpuidle.h>
-#include <mach/cpu.h>
-
-#include "pm.h"
-
-#define AT91_MAX_STATES        2
-
-/* Actual code that puts the SoC in different idle states */
-static int at91_enter_idle(struct cpuidle_device *dev,
-                       struct cpuidle_driver *drv,
-                              int index)
-{
-       if (cpu_is_at91rm9200())
-               at91rm9200_standby();
-       else if (cpu_is_at91sam9g45())
-               at91sam9g45_standby();
-       else if (cpu_is_at91sam9263())
-               at91sam9263_standby();
-       else
-               at91sam9_standby();
-
-       return index;
-}
-
-static struct cpuidle_driver at91_idle_driver = {
-       .name                   = "at91_idle",
-       .owner                  = THIS_MODULE,
-       .states[0]              = ARM_CPUIDLE_WFI_STATE,
-       .states[1]              = {
-               .enter                  = at91_enter_idle,
-               .exit_latency           = 10,
-               .target_residency       = 10000,
-               .flags                  = CPUIDLE_FLAG_TIME_VALID,
-               .name                   = "RAM_SR",
-               .desc                   = "WFI and DDR Self Refresh",
-       },
-       .state_count = AT91_MAX_STATES,
-};
-
-/* Initialize CPU idle by registering the idle states */
-static int __init at91_init_cpuidle(void)
-{
-       return cpuidle_register(&at91_idle_driver, NULL);
-}
-
-device_initcall(at91_init_cpuidle);
index 15afb5d9271f2237e3c61acd920b2f9c6d6e0a78..9986542e8060119fcad4eee37564fdf3d8d164a6 100644 (file)
@@ -39,6 +39,8 @@
 #include "at91_rstc.h"
 #include "at91_shdwc.h"
 
+static void (*at91_pm_standby)(void);
+
 static void __init show_reset_status(void)
 {
        static char reset[] __initdata = "reset";
@@ -266,14 +268,8 @@ static int at91_pm_enter(suspend_state_t state)
                         * For ARM 926 based chips, this requirement is weaker
                         * as at91sam9 can access a RAM in self-refresh mode.
                         */
-                       if (cpu_is_at91rm9200())
-                               at91rm9200_standby();
-                       else if (cpu_is_at91sam9g45())
-                               at91sam9g45_standby();
-                       else if (cpu_is_at91sam9263())
-                               at91sam9263_standby();
-                       else
-                               at91sam9_standby();
+                       if (at91_pm_standby)
+                               at91_pm_standby();
                        break;
 
                case PM_SUSPEND_ON:
@@ -314,6 +310,18 @@ static const struct platform_suspend_ops at91_pm_ops = {
        .end    = at91_pm_end,
 };
 
+static struct platform_device at91_cpuidle_device = {
+       .name = "cpuidle-at91",
+};
+
+void at91_pm_set_standby(void (*at91_standby)(void))
+{
+       if (at91_standby) {
+               at91_cpuidle_device.dev.platform_data = at91_standby;
+               at91_pm_standby = at91_standby;
+       }
+}
+
 static int __init at91_pm_init(void)
 {
 #ifdef CONFIG_AT91_SLOW_CLOCK
@@ -325,6 +333,9 @@ static int __init at91_pm_init(void)
        /* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */
        if (cpu_is_at91rm9200())
                at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0);
+       
+       if (at91_cpuidle_device.dev.platform_data)
+               platform_device_register(&at91_cpuidle_device);
 
        suspend_set_ops(&at91_pm_ops);
 
index 2f5908f0b8c5ec6dc9481f85bcba758d98f00d88..3ed190ce062bd5add5a426e07b1cf6c5d1e5b89a 100644 (file)
 #ifndef __ARCH_ARM_MACH_AT91_PM
 #define __ARCH_ARM_MACH_AT91_PM
 
+#include <asm/proc-fns.h>
+
 #include <mach/at91_ramc.h>
 #include <mach/at91rm9200_sdramc.h>
 
+extern void at91_pm_set_standby(void (*at91_standby)(void));
+
 /*
  * The AT91RM9200 goes into self-refresh mode with this command, and will
  * terminate self-refresh automatically on the next SDRAM access.
@@ -45,16 +49,18 @@ static inline void at91rm9200_standby(void)
 /* We manage both DDRAM/SDRAM controllers, we need more than one value to
  * remember.
  */
-static inline void at91sam9g45_standby(void)
+static inline void at91_ddr_standby(void)
 {
        /* Those two values allow us to delay self-refresh activation
         * to the maximum. */
-       u32 lpr0, lpr1;
-       u32 saved_lpr0, saved_lpr1;
+       u32 lpr0, lpr1 = 0;
+       u32 saved_lpr0, saved_lpr1 = 0;
 
-       saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
-       lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
-       lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
+       if (at91_ramc_base[1]) {
+               saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
+               lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
+               lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
+       }
 
        saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
        lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
@@ -62,25 +68,29 @@ static inline void at91sam9g45_standby(void)
 
        /* self-refresh mode now */
        at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
-       at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
 
        cpu_do_idle();
 
        at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
-       at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
 }
 
 /* We manage both DDRAM/SDRAM controllers, we need more than one value to
  * remember.
  */
-static inline void at91sam9263_standby(void)
+static inline void at91sam9_sdram_standby(void)
 {
-       u32 lpr0, lpr1;
-       u32 saved_lpr0, saved_lpr1;
+       u32 lpr0, lpr1 = 0;
+       u32 saved_lpr0, saved_lpr1 = 0;
 
-       saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
-       lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
-       lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
+       if (at91_ramc_base[1]) {
+               saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
+               lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
+               lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
+       }
 
        saved_lpr0 = at91_ramc_read(0, AT91_SDRAMC_LPR);
        lpr0 = saved_lpr0 & ~AT91_SDRAMC_LPCB;
@@ -88,27 +98,14 @@ static inline void at91sam9263_standby(void)
 
        /* self-refresh mode now */
        at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0);
-       at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
 
        cpu_do_idle();
 
        at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0);
-       at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
-}
-
-static inline void at91sam9_standby(void)
-{
-       u32 saved_lpr, lpr;
-
-       saved_lpr = at91_ramc_read(0, AT91_SDRAMC_LPR);
-
-       lpr = saved_lpr & ~AT91_SDRAMC_LPCB;
-       at91_ramc_write(0, AT91_SDRAMC_LPR, lpr |
-                       AT91_SDRAMC_LPCB_SELF_REFRESH);
-
-       cpu_do_idle();
-
-       at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
 }
 
 #endif
index b17fbcf4d9e8f34dbd876ea96af334dae4780efc..094b3459c288e37700c42ea85a57ced905323eda 100644 (file)
@@ -23,6 +23,7 @@
 #include "at91_shdwc.h"
 #include "soc.h"
 #include "generic.h"
+#include "pm.h"
 
 struct at91_init_soc __initdata at91_boot_soc;
 
@@ -376,15 +377,16 @@ static void at91_dt_rstc(void)
 }
 
 static struct of_device_id ramc_ids[] = {
-       { .compatible = "atmel,at91rm9200-sdramc" },
-       { .compatible = "atmel,at91sam9260-sdramc" },
-       { .compatible = "atmel,at91sam9g45-ddramc" },
+       { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
+       { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
+       { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
        { /*sentinel*/ }
 };
 
 static void at91_dt_ramc(void)
 {
        struct device_node *np;
+       const struct of_device_id *of_id;
 
        np = of_find_matching_node(NULL, ramc_ids);
        if (!np)
@@ -396,6 +398,12 @@ static void at91_dt_ramc(void)
        /* the controller may have 2 banks */
        at91_ramc_base[1] = of_iomap(np, 1);
 
+       of_id = of_match_node(ramc_ids, np);
+       if (!of_id)
+               pr_warn("AT91: ramc no standby function available\n");
+       else
+               at91_pm_set_standby(of_id->data);
+
        of_node_put(np);
 }
 
index e026b19b23eaf1d8546f4996a387c13e1b8ed670..a075b3e0c5c7a5229aa87163e732d9c6b49a7a50 100644 (file)
@@ -40,7 +40,6 @@ config ARCH_DAVINCI_DA850
        bool "DA850/OMAP-L138/AM18x based system"
        select ARCH_DAVINCI_DA8XX
        select ARCH_HAS_CPUFREQ
-       select CPU_FREQ_TABLE
        select CP_INTC
 
 config ARCH_DAVINCI_DA8XX
index ba95e5db25011a0801c2ef1f7c27270b713280ee..c17407b16d7c687292fa6e064978d9ca1699ea0a 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/clk-provider.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/platform_device.h>
 
 #include <asm/proc-fns.h>
 #include <asm/exception.h>
@@ -294,6 +295,16 @@ void exynos5_restart(enum reboot_mode mode, const char *cmd)
        __raw_writel(val, addr);
 }
 
+static struct platform_device exynos_cpuidle = {
+       .name           = "exynos_cpuidle",
+       .id             = -1,
+};
+
+void __init exynos_cpuidle_init(void)
+{
+       platform_device_register(&exynos_cpuidle);
+}
+
 void __init exynos_init_late(void)
 {
        if (of_machine_is_compatible("samsung,exynos5440"))
index 8646a141ae467b8175aed00d0acf39ae73f02097..b2ac1885d381d6581717a111a92f6cec25723abe 100644 (file)
@@ -22,6 +22,7 @@ struct map_desc;
 void exynos_init_io(void);
 void exynos4_restart(enum reboot_mode mode, const char *cmd);
 void exynos5_restart(enum reboot_mode mode, const char *cmd);
+void exynos_cpuidle_init(void);
 void exynos_init_late(void);
 
 void exynos_firmware_init(void);
index ac139226d63c1d1aefe86a7e25087ad7e6da36da..ddbfe8709fe7fe4bd43fb5f2ea3301ba1e304b63 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/export.h>
 #include <linux/time.h>
+#include <linux/platform_device.h>
 
 #include <asm/proc-fns.h>
 #include <asm/smp_scu.h>
@@ -192,7 +193,7 @@ static void __init exynos5_core_down_clk(void)
        __raw_writel(tmp, EXYNOS5_PWR_CTRL2);
 }
 
-static int __init exynos4_init_cpuidle(void)
+static int exynos_cpuidle_probe(struct platform_device *pdev)
 {
        int cpu_id, ret;
        struct cpuidle_device *device;
@@ -205,7 +206,7 @@ static int __init exynos4_init_cpuidle(void)
 
        ret = cpuidle_register_driver(&exynos4_idle_driver);
        if (ret) {
-               printk(KERN_ERR "CPUidle failed to register driver\n");
+               dev_err(&pdev->dev, "failed to register cpuidle driver\n");
                return ret;
        }
 
@@ -219,11 +220,20 @@ static int __init exynos4_init_cpuidle(void)
 
                ret = cpuidle_register_device(device);
                if (ret) {
-                       printk(KERN_ERR "CPUidle register device failed\n");
+                       dev_err(&pdev->dev, "failed to register cpuidle device\n");
                        return ret;
                }
        }
 
        return 0;
 }
-device_initcall(exynos4_init_cpuidle);
+
+static struct platform_driver exynos_cpuidle_driver = {
+       .probe  = exynos_cpuidle_probe,
+       .driver = {
+               .name = "exynos_cpuidle",
+               .owner = THIS_MODULE,
+       },
+};
+
+module_platform_driver(exynos_cpuidle_driver);
index 0099c6c13bbaa9504dccd6fa760c21273de41d3f..53a3dc37a7303b0a5bbdbdc202fbe211e6b0dd9e 100644 (file)
@@ -25,6 +25,8 @@
 
 static void __init exynos4_dt_machine_init(void)
 {
+       exynos_cpuidle_init();
+
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
index f874b773ca134e231df3e21d3c5c5f65caac33a9..c9f7dd1cdc8f9fd0f7a9c75fd4bb625ad42366f7 100644 (file)
@@ -47,6 +47,8 @@ static void __init exynos5_dt_machine_init(void)
                }
        }
 
+       exynos_cpuidle_init();
+
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
index 90372a21087f9ef38535479ccc35aac9e37977dc..699aabe296e1e62b91f7ca1b0a65c5e635ed8515 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/phy.h>
 #include <linux/reboot.h>
 #include <linux/regmap.h>
@@ -226,7 +226,7 @@ static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev)
        val = readl_relaxed(base + OCOTP_CFG3);
        val >>= OCOTP_CFG3_SPEED_SHIFT;
        if ((val & 0x3) != OCOTP_CFG3_SPEED_1P2GHZ)
-               if (opp_disable(cpu_dev, 1200000000))
+               if (dev_pm_opp_disable(cpu_dev, 1200000000))
                        pr_warn("failed to disable 1.2 GHz OPP\n");
 
 put_node:
index f26918467efcf42cc13639317965ebdb6d34bf14..6432ab8d92078ac4779627d9ae143761bd78ebef 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/cpu.h>
 
 #include <linux/mtd/mtd.h>
@@ -522,11 +522,11 @@ static int __init beagle_opp_init(void)
                        return -ENODEV;
                }
                /* Enable MPU 1GHz and lower opps */
-               r = opp_enable(mpu_dev, 800000000);
+               r = dev_pm_opp_enable(mpu_dev, 800000000);
                /* TODO: MPU 1GHz needs SR and ABB */
 
                /* Enable IVA 800MHz and lower opps */
-               r |= opp_enable(iva_dev, 660000000);
+               r |= dev_pm_opp_enable(iva_dev, 660000000);
                /* TODO: DSP 800MHz needs SR and ABB */
                if (r) {
                        pr_err("%s: failed to enable higher opp %d\n",
@@ -535,8 +535,8 @@ static int __init beagle_opp_init(void)
                         * Cleanup - disable the higher freqs - we dont care
                         * about the results
                         */
-                       opp_disable(mpu_dev, 800000000);
-                       opp_disable(iva_dev, 660000000);
+                       dev_pm_opp_disable(mpu_dev, 800000000);
+                       dev_pm_opp_disable(iva_dev, 660000000);
                }
        }
        return 0;
index 67faa7b8fe92fd932889b65d55adbe0c5a97e5de..1d777e63e05c94ccf754bab89a65ca681638c67f 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/device.h>
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 
 /*
  * agent_id values for use with omap_pm_set_min_bus_tput():
index bd41d59a7cab08ecbca342a665f5f944aa67b6bc..ec21e6eb03e133be1c8b1ff2a4733d0f34052abc 100644 (file)
@@ -17,7 +17,7 @@
  * GNU General Public License for more details.
  */
 #include <linux/module.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/cpu.h>
 
 #include "omap_device.h"
@@ -81,14 +81,14 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
                        dev = &oh->od->pdev->dev;
                }
 
-               r = opp_add(dev, opp_def->freq, opp_def->u_volt);
+               r = dev_pm_opp_add(dev, opp_def->freq, opp_def->u_volt);
                if (r) {
                        dev_err(dev, "%s: add OPP %ld failed for %s [%d] result=%d\n",
                                __func__, opp_def->freq,
                                opp_def->hwmod_name, i, r);
                } else {
                        if (!opp_def->default_available)
-                               r = opp_disable(dev, opp_def->freq);
+                               r = dev_pm_opp_disable(dev, opp_def->freq);
                        if (r)
                                dev_err(dev, "%s: disable %ld failed for %s [%d] result=%d\n",
                                        __func__, opp_def->freq,
index e742118fcfd2b69adc367057e6f17670a5136903..2f569b3c3092dbdaf4d3bbc2ec6a85253402db74 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/err.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/cpu.h>
@@ -131,7 +131,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
 {
        struct voltagedomain *voltdm;
        struct clk *clk;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long freq, bootup_volt;
        struct device *dev;
 
@@ -172,7 +172,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
        clk_put(clk);
 
        rcu_read_lock();
-       opp = opp_find_freq_ceil(dev, &freq);
+       opp = dev_pm_opp_find_freq_ceil(dev, &freq);
        if (IS_ERR(opp)) {
                rcu_read_unlock();
                pr_err("%s: unable to find boot up OPP for vdd_%s\n",
@@ -180,7 +180,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
                goto exit;
        }
 
-       bootup_volt = opp_get_voltage(opp);
+       bootup_volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
        if (!bootup_volt) {
                pr_err("%s: unable to find voltage corresponding to the bootup OPP for vdd_%s\n",
index a8427115ee07b9a986d62dceac6006f8c9cecafd..96100dbf5a2e8353e9fad34ded41ec5e83dda7ad 100644 (file)
@@ -615,14 +615,12 @@ endmenu
 config PXA25x
        bool
        select CPU_XSCALE
-       select CPU_FREQ_TABLE if CPU_FREQ
        help
          Select code specific to PXA21x/25x/26x variants
 
 config PXA27x
        bool
        select CPU_XSCALE
-       select CPU_FREQ_TABLE if CPU_FREQ
        help
          Select code specific to PXA27x variants
 
@@ -635,7 +633,6 @@ config CPU_PXA26x
 config PXA3xx
        bool
        select CPU_XSC3
-       select CPU_FREQ_TABLE if CPU_FREQ
        help
          Select code specific to PXA3xx variants
 
index f25b6119e028cc42ee564712fb3ef746961e0574..d4ea142c4eddb7d7860f55539d1d79cc7e64d36f 100644 (file)
@@ -42,74 +42,31 @@ EXPORT_SYMBOL(reset_status);
 /*
  * This table is setup for a 3.6864MHz Crystal.
  */
-static const unsigned short cclk_frequency_100khz[NR_FREQS] = {
-        590,   /*  59.0 MHz */
-        737,   /*  73.7 MHz */
-        885,   /*  88.5 MHz */
-       1032,   /* 103.2 MHz */
-       1180,   /* 118.0 MHz */
-       1327,   /* 132.7 MHz */
-       1475,   /* 147.5 MHz */
-       1622,   /* 162.2 MHz */
-       1769,   /* 176.9 MHz */
-       1917,   /* 191.7 MHz */
-       2064,   /* 206.4 MHz */
-       2212,   /* 221.2 MHz */
-       2359,   /* 235.9 MHz */
-       2507,   /* 250.7 MHz */
-       2654,   /* 265.4 MHz */
-       2802    /* 280.2 MHz */
+struct cpufreq_frequency_table sa11x0_freq_table[NR_FREQS+1] = {
+       { .frequency = 59000,   /*  59.0 MHz */},
+       { .frequency = 73700,   /*  73.7 MHz */},
+       { .frequency = 88500,   /*  88.5 MHz */},
+       { .frequency = 103200,  /* 103.2 MHz */},
+       { .frequency = 118000,  /* 118.0 MHz */},
+       { .frequency = 132700,  /* 132.7 MHz */},
+       { .frequency = 147500,  /* 147.5 MHz */},
+       { .frequency = 162200,  /* 162.2 MHz */},
+       { .frequency = 176900,  /* 176.9 MHz */},
+       { .frequency = 191700,  /* 191.7 MHz */},
+       { .frequency = 206400,  /* 206.4 MHz */},
+       { .frequency = 221200,  /* 221.2 MHz */},
+       { .frequency = 235900,  /* 235.9 MHz */},
+       { .frequency = 250700,  /* 250.7 MHz */},
+       { .frequency = 265400,  /* 265.4 MHz */},
+       { .frequency = 280200,  /* 280.2 MHz */},
+       { .frequency = CPUFREQ_TABLE_END, },
 };
 
-/* rounds up(!)  */
-unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
-{
-       int i;
-
-       khz /= 100;
-
-       for (i = 0; i < NR_FREQS; i++)
-               if (cclk_frequency_100khz[i] >= khz)
-                       break;
-
-       return i;
-}
-
-unsigned int sa11x0_ppcr_to_freq(unsigned int idx)
-{
-       unsigned int freq = 0;
-       if (idx < NR_FREQS)
-               freq = cclk_frequency_100khz[idx] * 100;
-       return freq;
-}
-
-
-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
- * this platform, anyway.
- */
-int sa11x0_verify_speed(struct cpufreq_policy *policy)
-{
-       unsigned int tmp;
-       if (policy->cpu)
-               return -EINVAL;
-
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
-
-       /* make sure that at least one frequency is within the policy */
-       tmp = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->min)] * 100;
-       if (tmp > policy->max)
-               policy->max = tmp;
-
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
-
-       return 0;
-}
-
 unsigned int sa11x0_getspeed(unsigned int cpu)
 {
        if (cpu)
                return 0;
-       return cclk_frequency_100khz[PPCR & 0xf] * 100;
+       return sa11x0_freq_table[PPCR & 0xf].frequency;
 }
 
 /*
index 9a33695c9492d238879a43dd64002a88d878df23..0d92e119b36b13d28c2ab8036c21f23963a54ff8 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Author: Nicolas Pitre
  */
+#include <linux/cpufreq.h>
 #include <linux/reboot.h>
 
 extern void sa1100_timer_init(void);
@@ -19,12 +20,8 @@ extern void sa11x0_init_late(void);
 extern void sa1110_mb_enable(void);
 extern void sa1110_mb_disable(void);
 
-struct cpufreq_policy;
-
-extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
-extern int sa11x0_verify_speed(struct cpufreq_policy *policy);
+extern struct cpufreq_frequency_table sa11x0_freq_table[];
 extern unsigned int sa11x0_getspeed(unsigned int cpu);
-extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx);
 
 struct flash_platform_data;
 struct resource;
index 99a28d62829742d9103764c47abcb5ff24894fbf..7a3fc1af6944b2cd9175a46f7c1749c83a090220 100644 (file)
@@ -34,7 +34,6 @@ config UX500_SOC_COMMON
 
 config UX500_SOC_DB8500
        bool
-       select CPU_FREQ_TABLE if CPU_FREQ
        select MFD_DB8500_PRCMU
        select PINCTRL_DB8500
        select PINCTRL_DB8540
index 36579544780493706381c22008c64577bc04fde2..c77170c04fd06a0b9bbd56abef64dafb0a993e13 100644 (file)
@@ -66,10 +66,22 @@ config ARCH_VEXPRESS_DCSCB
          This is needed to provide CPU and cluster power management
          on RTSM implementing big.LITTLE.
 
+config ARCH_VEXPRESS_SPC
+       bool "Versatile Express Serial Power Controller (SPC)"
+       select ARCH_HAS_CPUFREQ
+       select ARCH_HAS_OPP
+       select PM_OPP
+       help
+         The TC2 (A15x2 A7x3) versatile express core tile integrates a logic
+         block called Serial Power Controller (SPC) that provides the interface
+         between the dual cluster test-chip and the M3 microcontroller that
+         carries out power management.
+
 config ARCH_VEXPRESS_TC2_PM
        bool "Versatile Express TC2 power management"
        depends on MCPM
        select ARM_CCI
+       select ARCH_VEXPRESS_SPC
        help
          Support for CPU and cluster power management on Versatile Express
          with a TC2 (A15x2 A7x3) big.LITTLE core tile.
index 505e64ab3eae68f471d0d494f619f7360c67b5c2..0997e0b7494c31bcbad551441c074d5bf9bc9873 100644 (file)
@@ -8,7 +8,8 @@ obj-y                                   := v2m.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)      += ct-ca9x4.o
 obj-$(CONFIG_ARCH_VEXPRESS_DCSCB)      += dcscb.o      dcscb_setup.o
 CFLAGS_dcscb.o                         += -march=armv7-a
-obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM)     += tc2_pm.o spc.o
+obj-$(CONFIG_ARCH_VEXPRESS_SPC)                += spc.o
+obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM)     += tc2_pm.o
 CFLAGS_tc2_pm.o                                += -march=armv7-a
 obj-$(CONFIG_SMP)                      += platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)              += hotplug.o
index eefb029197ca004f81167e6098e52da338886001..033d34dcbd3fb8a8e1325900ddecdeb64090e874 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
 #include <linux/slab.h>
+#include <linux/semaphore.h>
 
 #include <asm/cacheflush.h>
 
 #define SPCLOG "vexpress-spc: "
 
+#define PERF_LVL_A15           0x00
+#define PERF_REQ_A15           0x04
+#define PERF_LVL_A7            0x08
+#define PERF_REQ_A7            0x0c
+#define COMMS                  0x10
+#define COMMS_REQ              0x14
+#define PWC_STATUS             0x18
+#define PWC_FLAG               0x1c
+
 /* SPC wake-up IRQs status and mask */
 #define WAKE_INT_MASK          0x24
 #define WAKE_INT_RAW           0x28
 #define A15_BX_ADDR0           0x68
 #define A7_BX_ADDR0            0x78
 
+/* SPC system config interface registers */
+#define SYSCFG_WDATA           0x70
+#define SYSCFG_RDATA           0x74
+
+/* A15/A7 OPP virtual register base */
+#define A15_PERFVAL_BASE       0xC10
+#define A7_PERFVAL_BASE                0xC30
+
+/* Config interface control bits */
+#define SYSCFG_START           (1 << 31)
+#define SYSCFG_SCC             (6 << 20)
+#define SYSCFG_STAT            (14 << 20)
+
 /* wake-up interrupt masks */
 #define GBL_WAKEUP_INT_MSK     (0x3 << 10)
 
 /* TC2 static dual-cluster configuration */
 #define MAX_CLUSTERS           2
 
+/*
+ * Even though the SPC takes max 3-5 ms to complete any OPP/COMMS
+ * operation, the operation could start just before jiffie is about
+ * to be incremented. So setting timeout value of 20ms = 2jiffies@100Hz
+ */
+#define TIMEOUT_US     20000
+
+#define MAX_OPPS       8
+#define CA15_DVFS      0
+#define CA7_DVFS       1
+#define SPC_SYS_CFG    2
+#define STAT_COMPLETE(type)    ((1 << 0) << (type << 2))
+#define STAT_ERR(type)         ((1 << 1) << (type << 2))
+#define RESPONSE_MASK(type)    (STAT_COMPLETE(type) | STAT_ERR(type))
+
+struct ve_spc_opp {
+       unsigned long freq;
+       unsigned long u_volt;
+};
+
 struct ve_spc_drvdata {
        void __iomem *baseaddr;
        /*
@@ -49,6 +99,12 @@ struct ve_spc_drvdata {
         * It corresponds to A15 processors MPIDR[15:8] bitfield
         */
        u32 a15_clusid;
+       uint32_t cur_rsp_mask;
+       uint32_t cur_rsp_stat;
+       struct semaphore sem;
+       struct completion done;
+       struct ve_spc_opp *opps[MAX_CLUSTERS];
+       int num_opps[MAX_CLUSTERS];
 };
 
 static struct ve_spc_drvdata *info;
@@ -157,8 +213,197 @@ void ve_spc_powerdown(u32 cluster, bool enable)
        writel_relaxed(enable, info->baseaddr + pwdrn_reg);
 }
 
-int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid)
+static int ve_spc_get_performance(int cluster, u32 *freq)
+{
+       struct ve_spc_opp *opps = info->opps[cluster];
+       u32 perf_cfg_reg = 0;
+       u32 perf;
+
+       perf_cfg_reg = cluster_is_a15(cluster) ? PERF_LVL_A15 : PERF_LVL_A7;
+
+       perf = readl_relaxed(info->baseaddr + perf_cfg_reg);
+       if (perf >= info->num_opps[cluster])
+               return -EINVAL;
+
+       opps += perf;
+       *freq = opps->freq;
+
+       return 0;
+}
+
+/* find closest match to given frequency in OPP table */
+static int ve_spc_round_performance(int cluster, u32 freq)
+{
+       int idx, max_opp = info->num_opps[cluster];
+       struct ve_spc_opp *opps = info->opps[cluster];
+       u32 fmin = 0, fmax = ~0, ftmp;
+
+       freq /= 1000; /* OPP entries in kHz */
+       for (idx = 0; idx < max_opp; idx++, opps++) {
+               ftmp = opps->freq;
+               if (ftmp >= freq) {
+                       if (ftmp <= fmax)
+                               fmax = ftmp;
+               } else {
+                       if (ftmp >= fmin)
+                               fmin = ftmp;
+               }
+       }
+       if (fmax != ~0)
+               return fmax * 1000;
+       else
+               return fmin * 1000;
+}
+
+static int ve_spc_find_performance_index(int cluster, u32 freq)
+{
+       int idx, max_opp = info->num_opps[cluster];
+       struct ve_spc_opp *opps = info->opps[cluster];
+
+       for (idx = 0; idx < max_opp; idx++, opps++)
+               if (opps->freq == freq)
+                       break;
+       return (idx == max_opp) ? -EINVAL : idx;
+}
+
+static int ve_spc_waitforcompletion(int req_type)
+{
+       int ret = wait_for_completion_interruptible_timeout(
+                       &info->done, usecs_to_jiffies(TIMEOUT_US));
+       if (ret == 0)
+               ret = -ETIMEDOUT;
+       else if (ret > 0)
+               ret = info->cur_rsp_stat & STAT_COMPLETE(req_type) ? 0 : -EIO;
+       return ret;
+}
+
+static int ve_spc_set_performance(int cluster, u32 freq)
+{
+       u32 perf_cfg_reg, perf_stat_reg;
+       int ret, perf, req_type;
+
+       if (cluster_is_a15(cluster)) {
+               req_type = CA15_DVFS;
+               perf_cfg_reg = PERF_LVL_A15;
+               perf_stat_reg = PERF_REQ_A15;
+       } else {
+               req_type = CA7_DVFS;
+               perf_cfg_reg = PERF_LVL_A7;
+               perf_stat_reg = PERF_REQ_A7;
+       }
+
+       perf = ve_spc_find_performance_index(cluster, freq);
+
+       if (perf < 0)
+               return perf;
+
+       if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US)))
+               return -ETIME;
+
+       init_completion(&info->done);
+       info->cur_rsp_mask = RESPONSE_MASK(req_type);
+
+       writel(perf, info->baseaddr + perf_cfg_reg);
+       ret = ve_spc_waitforcompletion(req_type);
+
+       info->cur_rsp_mask = 0;
+       up(&info->sem);
+
+       return ret;
+}
+
+static int ve_spc_read_sys_cfg(int func, int offset, uint32_t *data)
+{
+       int ret;
+
+       if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US)))
+               return -ETIME;
+
+       init_completion(&info->done);
+       info->cur_rsp_mask = RESPONSE_MASK(SPC_SYS_CFG);
+
+       /* Set the control value */
+       writel(SYSCFG_START | func | offset >> 2, info->baseaddr + COMMS);
+       ret = ve_spc_waitforcompletion(SPC_SYS_CFG);
+
+       if (ret == 0)
+               *data = readl(info->baseaddr + SYSCFG_RDATA);
+
+       info->cur_rsp_mask = 0;
+       up(&info->sem);
+
+       return ret;
+}
+
+static irqreturn_t ve_spc_irq_handler(int irq, void *data)
+{
+       struct ve_spc_drvdata *drv_data = data;
+       uint32_t status = readl_relaxed(drv_data->baseaddr + PWC_STATUS);
+
+       if (info->cur_rsp_mask & status) {
+               info->cur_rsp_stat = status;
+               complete(&drv_data->done);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ *  +--------------------------+
+ *  | 31      20 | 19        0 |
+ *  +--------------------------+
+ *  |   u_volt   |  freq(kHz)  |
+ *  +--------------------------+
+ */
+#define MULT_FACTOR    20
+#define VOLT_SHIFT     20
+#define FREQ_MASK      (0xFFFFF)
+static int ve_spc_populate_opps(uint32_t cluster)
 {
+       uint32_t data = 0, off, ret, idx;
+       struct ve_spc_opp *opps;
+
+       opps = kzalloc(sizeof(*opps) * MAX_OPPS, GFP_KERNEL);
+       if (!opps)
+               return -ENOMEM;
+
+       info->opps[cluster] = opps;
+
+       off = cluster_is_a15(cluster) ? A15_PERFVAL_BASE : A7_PERFVAL_BASE;
+       for (idx = 0; idx < MAX_OPPS; idx++, off += 4, opps++) {
+               ret = ve_spc_read_sys_cfg(SYSCFG_SCC, off, &data);
+               if (!ret) {
+                       opps->freq = (data & FREQ_MASK) * MULT_FACTOR;
+                       opps->u_volt = data >> VOLT_SHIFT;
+               } else {
+                       break;
+               }
+       }
+       info->num_opps[cluster] = idx;
+
+       return ret;
+}
+
+static int ve_init_opp_table(struct device *cpu_dev)
+{
+       int cluster = topology_physical_package_id(cpu_dev->id);
+       int idx, ret = 0, max_opp = info->num_opps[cluster];
+       struct ve_spc_opp *opps = info->opps[cluster];
+
+       for (idx = 0; idx < max_opp; idx++, opps++) {
+               ret = dev_pm_opp_add(cpu_dev, opps->freq * 1000, opps->u_volt);
+               if (ret) {
+                       dev_warn(cpu_dev, "failed to add opp %lu %lu\n",
+                                opps->freq, opps->u_volt);
+                       return ret;
+               }
+       }
+       return ret;
+}
+
+int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid, int irq)
+{
+       int ret;
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info) {
                pr_err(SPCLOG "unable to allocate mem\n");
@@ -168,6 +413,25 @@ int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid)
        info->baseaddr = baseaddr;
        info->a15_clusid = a15_clusid;
 
+       if (irq <= 0) {
+               pr_err(SPCLOG "Invalid IRQ %d\n", irq);
+               kfree(info);
+               return -EINVAL;
+       }
+
+       init_completion(&info->done);
+
+       readl_relaxed(info->baseaddr + PWC_STATUS);
+
+       ret = request_irq(irq, ve_spc_irq_handler, IRQF_TRIGGER_HIGH
+                               | IRQF_ONESHOT, "vexpress-spc", info);
+       if (ret) {
+               pr_err(SPCLOG "IRQ %d request failed\n", irq);
+               kfree(info);
+               return -ENODEV;
+       }
+
+       sema_init(&info->sem, 1);
        /*
         * Multi-cluster systems may need this data when non-coherent, during
         * cluster power-up/power-down. Make sure driver info reaches main
@@ -178,3 +442,103 @@ int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid)
 
        return 0;
 }
+
+struct clk_spc {
+       struct clk_hw hw;
+       int cluster;
+};
+
+#define to_clk_spc(spc) container_of(spc, struct clk_spc, hw)
+static unsigned long spc_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct clk_spc *spc = to_clk_spc(hw);
+       u32 freq;
+
+       if (ve_spc_get_performance(spc->cluster, &freq))
+               return -EIO;
+
+       return freq * 1000;
+}
+
+static long spc_round_rate(struct clk_hw *hw, unsigned long drate,
+               unsigned long *parent_rate)
+{
+       struct clk_spc *spc = to_clk_spc(hw);
+
+       return ve_spc_round_performance(spc->cluster, drate);
+}
+
+static int spc_set_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
+{
+       struct clk_spc *spc = to_clk_spc(hw);
+
+       return ve_spc_set_performance(spc->cluster, rate / 1000);
+}
+
+static struct clk_ops clk_spc_ops = {
+       .recalc_rate = spc_recalc_rate,
+       .round_rate = spc_round_rate,
+       .set_rate = spc_set_rate,
+};
+
+static struct clk *ve_spc_clk_register(struct device *cpu_dev)
+{
+       struct clk_init_data init;
+       struct clk_spc *spc;
+
+       spc = kzalloc(sizeof(*spc), GFP_KERNEL);
+       if (!spc) {
+               pr_err("could not allocate spc clk\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       spc->hw.init = &init;
+       spc->cluster = topology_physical_package_id(cpu_dev->id);
+
+       init.name = dev_name(cpu_dev);
+       init.ops = &clk_spc_ops;
+       init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE;
+       init.num_parents = 0;
+
+       return devm_clk_register(cpu_dev, &spc->hw);
+}
+
+static int __init ve_spc_clk_init(void)
+{
+       int cpu;
+       struct clk *clk;
+
+       if (!info)
+               return 0; /* Continue only if SPC is initialised */
+
+       if (ve_spc_populate_opps(0) || ve_spc_populate_opps(1)) {
+               pr_err("failed to build OPP table\n");
+               return -ENODEV;
+       }
+
+       for_each_possible_cpu(cpu) {
+               struct device *cpu_dev = get_cpu_device(cpu);
+               if (!cpu_dev) {
+                       pr_warn("failed to get cpu%d device\n", cpu);
+                       continue;
+               }
+               clk = ve_spc_clk_register(cpu_dev);
+               if (IS_ERR(clk)) {
+                       pr_warn("failed to register cpu%d clock\n", cpu);
+                       continue;
+               }
+               if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
+                       pr_warn("failed to register cpu%d clock lookup\n", cpu);
+                       continue;
+               }
+
+               if (ve_init_opp_table(cpu_dev))
+                       pr_warn("failed to initialise cpu%d opp table\n", cpu);
+       }
+
+       platform_device_register_simple("vexpress-spc-cpufreq", -1, NULL, 0);
+       return 0;
+}
+module_init(ve_spc_clk_init);
index 5f7e4a446a1771190439bac5d39d3800bf79eafa..dbd44c3720f98e711e5cabf28e6734847d8c7ea8 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef __SPC_H_
 #define __SPC_H_
 
-int __init ve_spc_init(void __iomem *base, u32 a15_clusid);
+int __init ve_spc_init(void __iomem *base, u32 a15_clusid, int irq);
 void ve_spc_global_wakeup_irq(bool set);
 void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set);
 void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr);
index e6eb4819291241f30b51d5e7b58c14d1d07c0d32..d38130aba4644f206baab0e8d8f9a4b0e3ab88ee 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/irqchip/arm-gic.h>
@@ -311,7 +312,7 @@ static void __naked tc2_pm_power_up_setup(unsigned int affinity_level)
 
 static int __init tc2_pm_init(void)
 {
-       int ret;
+       int ret, irq;
        void __iomem *scc;
        u32 a15_cluster_id, a7_cluster_id, sys_info;
        struct device_node *np;
@@ -336,13 +337,15 @@ static int __init tc2_pm_init(void)
        tc2_nr_cpus[a15_cluster_id] = (sys_info >> 16) & 0xf;
        tc2_nr_cpus[a7_cluster_id] = (sys_info >> 20) & 0xf;
 
+       irq = irq_of_parse_and_map(np, 0);
+
        /*
         * A subset of the SCC registers is also used to communicate
         * with the SPC (power controller). We need to be able to
         * drive it very early in the boot process to power up
         * processors, so we initialize the SPC driver here.
         */
-       ret = ve_spc_init(scc + SPC_BASE, a15_cluster_id);
+       ret = ve_spc_init(scc + SPC_BASE, a15_cluster_id, irq);
        if (ret)
                return ret;
 
index 5f252569c68987d908546b55bb921d5f7693c7af..9a7bd137c8fd27d60f42a6b78c6dbf3cc234d348 100644 (file)
@@ -44,6 +44,10 @@ static struct of_device_id zynq_of_bus_ids[] __initdata = {
        {}
 };
 
+static struct platform_device zynq_cpuidle_device = {
+       .name = "cpuidle-zynq",
+};
+
 /**
  * zynq_init_machine - System specific initialization, intended to be
  *                    called from board specific initialization.
@@ -56,6 +60,8 @@ static void __init zynq_init_machine(void)
        l2x0_of_init(0x02060000, 0xF0F0FFFF);
 
        of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
+
+       platform_device_register(&zynq_cpuidle_device);
 }
 
 static void __init zynq_timer_init(void)
index f5e1a8471714cd421e2ab9dee54ae88f144316d1..1272ed202ddee97c2a9143d97afbf4bed69f0fea 100644 (file)
@@ -1232,7 +1232,8 @@ __iommu_create_mapping(struct device *dev, struct page **pages, size_t size)
                                break;
 
                len = (j - i) << PAGE_SHIFT;
-               ret = iommu_map(mapping->domain, iova, phys, len, 0);
+               ret = iommu_map(mapping->domain, iova, phys, len,
+                               IOMMU_READ|IOMMU_WRITE);
                if (ret < 0)
                        goto fail;
                iova += len;
@@ -1431,6 +1432,27 @@ static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
                                         GFP_KERNEL);
 }
 
+static int __dma_direction_to_prot(enum dma_data_direction dir)
+{
+       int prot;
+
+       switch (dir) {
+       case DMA_BIDIRECTIONAL:
+               prot = IOMMU_READ | IOMMU_WRITE;
+               break;
+       case DMA_TO_DEVICE:
+               prot = IOMMU_READ;
+               break;
+       case DMA_FROM_DEVICE:
+               prot = IOMMU_WRITE;
+               break;
+       default:
+               prot = 0;
+       }
+
+       return prot;
+}
+
 /*
  * Map a part of the scatter-gather list into contiguous io address space
  */
@@ -1444,6 +1466,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
        int ret = 0;
        unsigned int count;
        struct scatterlist *s;
+       int prot;
 
        size = PAGE_ALIGN(size);
        *handle = DMA_ERROR_CODE;
@@ -1460,7 +1483,9 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
                        !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
                        __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
 
-               ret = iommu_map(mapping->domain, iova, phys, len, 0);
+               prot = __dma_direction_to_prot(dir);
+
+               ret = iommu_map(mapping->domain, iova, phys, len, prot);
                if (ret < 0)
                        goto fail;
                count += len >> PAGE_SHIFT;
@@ -1665,19 +1690,7 @@ static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p
        if (dma_addr == DMA_ERROR_CODE)
                return dma_addr;
 
-       switch (dir) {
-       case DMA_BIDIRECTIONAL:
-               prot = IOMMU_READ | IOMMU_WRITE;
-               break;
-       case DMA_TO_DEVICE:
-               prot = IOMMU_READ;
-               break;
-       case DMA_FROM_DEVICE:
-               prot = IOMMU_WRITE;
-               break;
-       default:
-               prot = 0;
-       }
+       prot = __dma_direction_to_prot(dir);
 
        ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, prot);
        if (ret < 0)
index febaee7ca57be76487290a2ac45c6cf74e53759c..18ec4c504abf908ac9ddca01a4458a8183c6cc95 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/nodemask.h>
 #include <linux/initrd.h>
 #include <linux/of_fdt.h>
-#include <linux/of_reserved_mem.h>
 #include <linux/highmem.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
@@ -379,8 +378,6 @@ void __init arm_memblock_init(struct meminfo *mi,
        if (mdesc->reserve)
                mdesc->reserve();
 
-       early_init_dt_scan_reserved_mem();
-
        /*
         * reserve memory for DMA contigouos allocations,
         * must come from DMA area inside low memory
index f50d223a0bd31271ed73beabd60679c137ccb440..99b44e0e8d866983dd60d4b8324bf29010679e77 100644 (file)
@@ -930,4 +930,5 @@ void bpf_jit_free(struct sk_filter *fp)
 {
        if (fp->bpf_func != sk_run_filter)
                module_free(NULL, fp->bpf_func);
+       kfree(fp);
 }
index f78c9a2c7e281f2d441a40719e6735226231ceaa..eb382aedd9a232c9d85173356bf4ed44d33fb6b5 100644 (file)
@@ -1429,7 +1429,6 @@ source "drivers/cpufreq/Kconfig"
 config BFIN_CPU_FREQ
        bool
        depends on CPU_FREQ
-       select CPU_FREQ_TABLE
        default y
 
 config CPU_VOLTAGE
index 02380bed189c6fda4920412a18f1baab6203d1c1..9c957c81c6885acd595c42d1c470a1390cef6feb 100644 (file)
@@ -130,13 +130,11 @@ config SVINTO_SIM
 
 config ETRAXFS
        bool "ETRAX-FS-V32"
-       select CPU_FREQ_TABLE if CPU_FREQ
        help
          Support CRIS V32.
 
 config CRIS_MACH_ARTPEC3
         bool "ARTPEC-3"
-       select CPU_FREQ_TABLE if CPU_FREQ
         help
           Support Axis ARTPEC-3.
 
index 5eb71d22c3d5901030eec5c9ead78dc1279d815e..59d52e3aef125b79b67afdaf1fcffd2b892367ff 100644 (file)
@@ -882,40 +882,10 @@ __init void prefill_possible_map(void)
                set_cpu_possible(i, true);
 }
 
-static int _acpi_map_lsapic(acpi_handle handle, int *pcpu)
+static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
 {
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *obj;
-       struct acpi_madt_local_sapic *lsapic;
        cpumask_t tmp_map;
-       int cpu, physid;
-
-       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
-               return -EINVAL;
-
-       if (!buffer.length || !buffer.pointer)
-               return -EINVAL;
-
-       obj = buffer.pointer;
-       if (obj->type != ACPI_TYPE_BUFFER)
-       {
-               kfree(buffer.pointer);
-               return -EINVAL;
-       }
-
-       lsapic = (struct acpi_madt_local_sapic *)obj->buffer.pointer;
-
-       if ((lsapic->header.type != ACPI_MADT_TYPE_LOCAL_SAPIC) ||
-           (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))) {
-               kfree(buffer.pointer);
-               return -EINVAL;
-       }
-
-       physid = ((lsapic->id << 8) | (lsapic->eid));
-
-       kfree(buffer.pointer);
-       buffer.length = ACPI_ALLOCATE_BUFFER;
-       buffer.pointer = NULL;
+       int cpu;
 
        cpumask_complement(&tmp_map, cpu_present_mask);
        cpu = cpumask_first(&tmp_map);
@@ -934,9 +904,9 @@ static int _acpi_map_lsapic(acpi_handle handle, int *pcpu)
 }
 
 /* wrapper to silence section mismatch warning */
-int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
+int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
 {
-       return _acpi_map_lsapic(handle, pcpu);
+       return _acpi_map_lsapic(handle, physid, pcpu);
 }
 EXPORT_SYMBOL(acpi_map_lsapic);
 
index 0f90569b9d8546f7fa710a5b15f7883266e1ba95..9387cc2693f6a33a70459fcb46da058db395e2c4 100644 (file)
@@ -40,6 +40,8 @@ CONFIG_IP_NF_QUEUE=m
 CONFIG_LLC2=m
 CONFIG_NET_PKTGEN=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_PARPORT=y
index b647b182dacc17d6cf95fa79cee892fd8e0427bf..90025322b75ecd3b8a5672b76d18ce534b92ee2f 100644 (file)
@@ -79,6 +79,8 @@ CONFIG_IP_DCCP=m
 CONFIG_LLC2=m
 CONFIG_NET_PKTGEN=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_BLK_DEV_UMEM=m
index e289f5bf31488f0bb9eff29bb51bcbf25abd3bd1..f1a0c25bef8dc3a6667c608a092f96a39d5994aa 100644 (file)
@@ -4,6 +4,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODVERSIONS=y
@@ -27,6 +28,8 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
index 311ca367b62237b87bb78023f7687ef1f7d98c85..ec1b014952b6601458f4c3b2901d8e86670b96fc 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
@@ -39,6 +40,8 @@ CONFIG_NETFILTER_DEBUG=y
 CONFIG_IP_NF_QUEUE=m
 CONFIG_NET_PKTGEN=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_BLK_DEV_UMEM=m
index f11006361297eb152cf5f78471f6c69de41e5cfc..e1c8d2015c8938ac0a3440d38af427b4ac8eec7a 100644 (file)
@@ -62,6 +62,8 @@ CONFIG_TIPC=m
 CONFIG_LLC2=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
index dfe88f6c95c4d7c924b9e03d8c7abd236f100609..ba61495e1fa4b8d9ee576aff9a7559e619f229b6 100644 (file)
@@ -49,6 +49,8 @@ CONFIG_INET6_ESP=y
 CONFIG_INET6_IPCOMP=y
 CONFIG_LLC2=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_PARPORT=y
index b521c0adf4ec95317c2c00cd2c197bc8e3610c03..c035673209f732f0850aaa4dc98d2d49eee3b74c 100644 (file)
@@ -602,7 +602,6 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
                __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
        }
 }
-EXPORT_SYMBOL_GPL(flush_cache_page);
 
 #ifdef CONFIG_PARISC_TMPALIAS
 
index 37aabd772fbb91c3d4f07210a2543638cf4ef159..d2d58258aea68084c4f09cc6012a741b838b22d5 100644 (file)
@@ -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
index 8e59abc237d7f17c96effa20583206e75b2e4b7a..930cd8af35035441031e1abecbdde3472ab48808 100644 (file)
@@ -844,18 +844,6 @@ void __cpu_die(unsigned int cpu)
                smp_ops->cpu_die(cpu);
 }
 
-static DEFINE_MUTEX(powerpc_cpu_hotplug_driver_mutex);
-
-void cpu_hotplug_driver_lock()
-{
-       mutex_lock(&powerpc_cpu_hotplug_driver_mutex);
-}
-
-void cpu_hotplug_driver_unlock()
-{
-       mutex_unlock(&powerpc_cpu_hotplug_driver_mutex);
-}
-
 void cpu_die(void)
 {
        if (ppc_md.cpu_die)
index bf56e33f8257f68717b241c98abefb2f925f2858..2345bdb4d91784bb2bbdd8ce05d9c3566e48f309 100644 (file)
@@ -691,4 +691,5 @@ void bpf_jit_free(struct sk_filter *fp)
 {
        if (fp->bpf_func != sk_run_filter)
                module_free(NULL, fp->bpf_func);
+       kfree(fp);
 }
index 7cfdaae1721a925c1d7370515917e7d9af5cc553..a8fe5aa3d34fd545f87a31995153effd8a63521b 100644 (file)
@@ -404,46 +404,38 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
        unsigned long drc_index;
        int rc;
 
-       cpu_hotplug_driver_lock();
        rc = strict_strtoul(buf, 0, &drc_index);
-       if (rc) {
-               rc = -EINVAL;
-               goto out;
-       }
+       if (rc)
+               return -EINVAL;
 
        parent = of_find_node_by_path("/cpus");
-       if (!parent) {
-               rc = -ENODEV;
-               goto out;
-       }
+       if (!parent)
+               return -ENODEV;
 
        dn = dlpar_configure_connector(drc_index, parent);
-       if (!dn) {
-               rc = -EINVAL;
-               goto out;
-       }
+       if (!dn)
+               return -EINVAL;
 
        of_node_put(parent);
 
        rc = dlpar_acquire_drc(drc_index);
        if (rc) {
                dlpar_free_cc_nodes(dn);
-               rc = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        rc = dlpar_attach_node(dn);
        if (rc) {
                dlpar_release_drc(drc_index);
                dlpar_free_cc_nodes(dn);
-               goto out;
+               return rc;
        }
 
        rc = dlpar_online_cpu(dn);
-out:
-       cpu_hotplug_driver_unlock();
+       if (rc)
+               return rc;
 
-       return rc ? rc : count;
+       return count;
 }
 
 static int dlpar_offline_cpu(struct device_node *dn)
@@ -516,30 +508,27 @@ static ssize_t dlpar_cpu_release(const char *buf, size_t count)
                return -EINVAL;
        }
 
-       cpu_hotplug_driver_lock();
        rc = dlpar_offline_cpu(dn);
        if (rc) {
                of_node_put(dn);
-               rc = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        rc = dlpar_release_drc(*drc_index);
        if (rc) {
                of_node_put(dn);
-               goto out;
+               return rc;
        }
 
        rc = dlpar_detach_node(dn);
        if (rc) {
                dlpar_acquire_drc(*drc_index);
-               goto out;
+               return rc;
        }
 
        of_node_put(dn);
-out:
-       cpu_hotplug_driver_unlock();
-       return rc ? rc : count;
+
+       return count;
 }
 
 static int __init pseries_dlpar_init(void)
index 9b60a36c348d5422dc325463bcb26efeee64161d..2204400d0bd58d4a1e45c82394ff5cbd100aa2cc 100644 (file)
@@ -748,7 +748,9 @@ static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry)
 
 static inline void pgste_set_pte(pte_t *ptep, pte_t entry)
 {
-       if (!MACHINE_HAS_ESOP && (pte_val(entry) & _PAGE_WRITE)) {
+       if (!MACHINE_HAS_ESOP &&
+           (pte_val(entry) & _PAGE_PRESENT) &&
+           (pte_val(entry) & _PAGE_WRITE)) {
                /*
                 * Without enhanced suppression-on-protection force
                 * the dirty bit on for all writable ptes.
index 8ad8af915032a32573e06548e90d89ea7563349c..819b94d2272054d318fdd12c31b8718a9e4bb0bd 100644 (file)
@@ -71,30 +71,30 @@ static inline void local_tick_enable(unsigned long long comp)
 
 typedef unsigned long long cycles_t;
 
-static inline unsigned long long get_tod_clock(void)
-{
-       unsigned long long clk;
-
-#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
-       asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
-#else
-       asm volatile("stck %0" : "=Q" (clk) : : "cc");
-#endif
-       return clk;
-}
-
 static inline void get_tod_clock_ext(char *clk)
 {
        asm volatile("stcke %0" : "=Q" (*clk) : : "cc");
 }
 
-static inline unsigned long long get_tod_clock_xt(void)
+static inline unsigned long long get_tod_clock(void)
 {
        unsigned char clk[16];
        get_tod_clock_ext(clk);
        return *((unsigned long long *)&clk[1]);
 }
 
+static inline unsigned long long get_tod_clock_fast(void)
+{
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+       unsigned long long clk;
+
+       asm volatile("stckf %0" : "=Q" (clk) : : "cc");
+       return clk;
+#else
+       return get_tod_clock();
+#endif
+}
+
 static inline cycles_t get_cycles(void)
 {
        return (cycles_t) get_tod_clock() >> 2;
@@ -125,7 +125,7 @@ extern u64 sched_clock_base_cc;
  */
 static inline unsigned long long get_tod_clock_monotonic(void)
 {
-       return get_tod_clock_xt() - sched_clock_base_cc;
+       return get_tod_clock() - sched_clock_base_cc;
 }
 
 /**
index 1389b637dae55018e3eab8b18dd3f44e9440e078..adaa9e9478d83fb77a2e91a41de0934f84acfb66 100644 (file)
@@ -99,7 +99,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
                        break;
                }
        }
-       return err;
+       return err ? -EFAULT : 0;
 }
 
 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
@@ -148,7 +148,7 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
                        break;
                }
        }
-       return err;
+       return err ? -EFAULT : 0;
 }
 
 static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
index f1279dc2e1bcecae2a12ea246096f1458b2de77f..17d62fe5d7b70554c36b8f85b34da23d86c90407 100644 (file)
@@ -867,7 +867,7 @@ static inline void
 debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
                        int exception)
 {
-       active->id.stck = get_tod_clock();
+       active->id.stck = get_tod_clock_fast();
        active->id.fields.cpuid = smp_processor_id();
        active->caller = __builtin_return_address(0);
        active->id.fields.exception = exception;
index 7f35cb33e5102008244b4fd1376954400f2d0009..7f1f7ac5cf7f8a2c3f3966d4fe96fa23af90ea04 100644 (file)
@@ -385,7 +385,7 @@ static int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
        }
 
        if ((!rc) && (vcpu->arch.sie_block->ckc <
-               get_tod_clock() + vcpu->arch.sie_block->epoch)) {
+               get_tod_clock_fast() + vcpu->arch.sie_block->epoch)) {
                if ((!psw_extint_disabled(vcpu)) &&
                        (vcpu->arch.sie_block->gcr[0] & 0x800ul))
                        rc = 1;
@@ -425,7 +425,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
                goto no_timer;
        }
 
-       now = get_tod_clock() + vcpu->arch.sie_block->epoch;
+       now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
        if (vcpu->arch.sie_block->ckc < now) {
                __unset_cpu_idle(vcpu);
                return 0;
@@ -515,7 +515,7 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
        }
 
        if ((vcpu->arch.sie_block->ckc <
-               get_tod_clock() + vcpu->arch.sie_block->epoch))
+               get_tod_clock_fast() + vcpu->arch.sie_block->epoch))
                __try_deliver_ckc_interrupt(vcpu);
 
        if (atomic_read(&fi->active)) {
index 57c87d7d7ede01add784c291f31a82f502ca877e..a9f3d0042d58ba849b8c624f23915d88d03d6f70 100644 (file)
@@ -44,7 +44,7 @@ static void __udelay_disabled(unsigned long long usecs)
        do {
                set_clock_comparator(end);
                vtime_stop_cpu();
-       } while (get_tod_clock() < end);
+       } while (get_tod_clock_fast() < end);
        lockdep_on();
        __ctl_load(cr0, 0, 0);
        __ctl_load(cr6, 6, 6);
@@ -55,7 +55,7 @@ static void __udelay_enabled(unsigned long long usecs)
 {
        u64 clock_saved, end;
 
-       end = get_tod_clock() + (usecs << 12);
+       end = get_tod_clock_fast() + (usecs << 12);
        do {
                clock_saved = 0;
                if (end < S390_lowcore.clock_comparator) {
@@ -65,7 +65,7 @@ static void __udelay_enabled(unsigned long long usecs)
                vtime_stop_cpu();
                if (clock_saved)
                        local_tick_enable(clock_saved);
-       } while (get_tod_clock() < end);
+       } while (get_tod_clock_fast() < end);
 }
 
 /*
@@ -109,8 +109,8 @@ void udelay_simple(unsigned long long usecs)
 {
        u64 end;
 
-       end = get_tod_clock() + (usecs << 12);
-       while (get_tod_clock() < end)
+       end = get_tod_clock_fast() + (usecs << 12);
+       while (get_tod_clock_fast() < end)
                cpu_relax();
 }
 
@@ -120,10 +120,10 @@ void __ndelay(unsigned long long nsecs)
 
        nsecs <<= 9;
        do_div(nsecs, 125);
-       end = get_tod_clock() + nsecs;
+       end = get_tod_clock_fast() + nsecs;
        if (nsecs & ~0xfffUL)
                __udelay(nsecs >> 12);
-       while (get_tod_clock() < end)
+       while (get_tod_clock_fast() < end)
                barrier();
 }
 EXPORT_SYMBOL(__ndelay);
index 709239285869caa29fde3db90ea31da213cb5cb2..a5df511e27a220cf102d8ffee6b7b57f903eb8c3 100644 (file)
@@ -881,7 +881,9 @@ void bpf_jit_free(struct sk_filter *fp)
        struct bpf_binary_header *header = (void *)addr;
 
        if (fp->bpf_func == sk_run_filter)
-               return;
+               goto free_filter;
        set_memory_rw(addr, header->pages);
        module_free(NULL, header);
+free_filter:
+       kfree(fp);
 }
index 9c7be59e6f5ad3ad360facd10c6a2c35fd3bde75..218b6b23c378f888ef6ab0accf7ee4882e2911e2 100644 (file)
@@ -808,4 +808,5 @@ void bpf_jit_free(struct sk_filter *fp)
 {
        if (fp->bpf_func != sk_run_filter)
                module_free(NULL, fp->bpf_func);
+       kfree(fp);
 }
index 145d703227bf63542560df60a842d2b8aa0f1f7c..0c11032e2e913e4cf050f635cc2bd41bc71e7111 100644 (file)
@@ -254,10 +254,6 @@ config ARCH_HWEIGHT_CFLAGS
        default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
        default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
 
-config ARCH_CPU_PROBE_RELEASE
-       def_bool y
-       depends on HOTPLUG_CPU
-
 config ARCH_SUPPORTS_UPROBES
        def_bool y
 
@@ -1033,6 +1029,7 @@ config X86_REBOOTFIXUPS
 
 config MICROCODE
        tristate "CPU microcode loading support"
+       depends on CPU_SUP_AMD || CPU_SUP_INTEL
        select FW_LOADER
        ---help---
 
index b1977bad5435e5342af7e548700f08c1a04ff580..c8c1e700c26ed3426f0086c594a645bcc49261d9 100644 (file)
@@ -26,6 +26,7 @@
 #include <acpi/pdc_intel.h>
 
 #include <asm/numa.h>
+#include <asm/fixmap.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/mpspec.h>
index 626cf70082d7c8229b14a529625652f5646fcf09..3142a94c7b4bf90314838fa8beb67c4e7ed0b363 100644 (file)
@@ -94,7 +94,7 @@ static inline void early_reserve_e820_mpc_new(void) { }
 #define default_get_smp_config x86_init_uint_noop
 #endif
 
-void generic_processor_info(int apicid, int version);
+int 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,
index cb7502852acb0921e4e0c7132962c681f43b51ec..e139b13f2a33a3572d91e4f7297952e1bf8a1ffc 100644 (file)
@@ -218,10 +218,14 @@ void msrs_free(struct msr *msrs);
 #ifdef CONFIG_SMP
 int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q);
+int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q);
 void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
 void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
 int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q);
+int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q);
 int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
 int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
 #else  /*  CONFIG_SMP  */
@@ -235,6 +239,16 @@ static inline int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
        wrmsr(msr_no, l, h);
        return 0;
 }
+static inline int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
+{
+       rdmsrl(msr_no, *q);
+       return 0;
+}
+static inline int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
+{
+       wrmsrl(msr_no, q);
+       return 0;
+}
 static inline void rdmsr_on_cpus(const struct cpumask *m, u32 msr_no,
                                struct msr *msrs)
 {
@@ -254,6 +268,14 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 {
        return wrmsr_safe(msr_no, l, h);
 }
+static inline int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
+{
+       return rdmsrl_safe(msr_no, q);
+}
+static inline int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
+{
+       return wrmsrl_safe(msr_no, q);
+}
 static inline int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
 {
        return rdmsr_safe_regs(regs);
index 40c76604199f76e9263f94c10c249f2eee8e40dc..6c0b43bd024bb5890230ca45c61b3de082b611ef 100644 (file)
@@ -189,24 +189,31 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
        return 0;
 }
 
-static void acpi_register_lapic(int id, u8 enabled)
+/**
+ * acpi_register_lapic - register a local apic and generates a logic cpu number
+ * @id: local apic id to register
+ * @enabled: this cpu is enabled or not
+ *
+ * Returns the logic cpu number which maps to the local apic
+ */
+static int acpi_register_lapic(int id, u8 enabled)
 {
        unsigned int ver = 0;
 
        if (id >= MAX_LOCAL_APIC) {
                printk(KERN_INFO PREFIX "skipped apicid that is too big\n");
-               return;
+               return -EINVAL;
        }
 
        if (!enabled) {
                ++disabled_cpus;
-               return;
+               return -EINVAL;
        }
 
        if (boot_cpu_physical_apicid != -1U)
                ver = apic_version[boot_cpu_physical_apicid];
 
-       generic_processor_info(id, ver);
+       return generic_processor_info(id, ver);
 }
 
 static int __init
@@ -614,84 +621,27 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 #endif
 }
 
-static int _acpi_map_lsapic(acpi_handle handle, int *pcpu)
+static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
 {
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *obj;
-       struct acpi_madt_local_apic *lapic;
-       cpumask_var_t tmp_map, new_map;
-       u8 physid;
        int cpu;
-       int retval = -ENOMEM;
-
-       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
-               return -EINVAL;
-
-       if (!buffer.length || !buffer.pointer)
-               return -EINVAL;
-
-       obj = buffer.pointer;
-       if (obj->type != ACPI_TYPE_BUFFER ||
-           obj->buffer.length < sizeof(*lapic)) {
-               kfree(buffer.pointer);
-               return -EINVAL;
-       }
 
-       lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer;
-
-       if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC ||
-           !(lapic->lapic_flags & ACPI_MADT_ENABLED)) {
-               kfree(buffer.pointer);
-               return -EINVAL;
-       }
-
-       physid = lapic->id;
-
-       kfree(buffer.pointer);
-       buffer.length = ACPI_ALLOCATE_BUFFER;
-       buffer.pointer = NULL;
-       lapic = NULL;
-
-       if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL))
-               goto out;
-
-       if (!alloc_cpumask_var(&new_map, GFP_KERNEL))
-               goto free_tmp_map;
-
-       cpumask_copy(tmp_map, cpu_present_mask);
-       acpi_register_lapic(physid, ACPI_MADT_ENABLED);
-
-       /*
-        * If acpi_register_lapic successfully generates a new logical cpu
-        * number, then the following will get us exactly what was mapped
-        */
-       cpumask_andnot(new_map, cpu_present_mask, tmp_map);
-       if (cpumask_empty(new_map)) {
-               printk ("Unable to map lapic to logical cpu number\n");
-               retval = -EINVAL;
-               goto free_new_map;
+       cpu = acpi_register_lapic(physid, ACPI_MADT_ENABLED);
+       if (cpu < 0) {
+               pr_info(PREFIX "Unable to map lapic to logical cpu number\n");
+               return cpu;
        }
 
        acpi_processor_set_pdc(handle);
-
-       cpu = cpumask_first(new_map);
        acpi_map_cpu2node(handle, cpu, physid);
 
        *pcpu = cpu;
-       retval = 0;
-
-free_new_map:
-       free_cpumask_var(new_map);
-free_tmp_map:
-       free_cpumask_var(tmp_map);
-out:
-       return retval;
+       return 0;
 }
 
 /* wrapper to silence section mismatch warning */
-int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
+int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
 {
-       return _acpi_map_lsapic(handle, pcpu);
+       return _acpi_map_lsapic(handle, physid, pcpu);
 }
 EXPORT_SYMBOL(acpi_map_lsapic);
 
@@ -745,7 +695,7 @@ static int __init acpi_parse_sbf(struct acpi_table_header *table)
 #ifdef CONFIG_HPET_TIMER
 #include <asm/hpet.h>
 
-static struct __initdata resource *hpet_res;
+static struct resource *hpet_res __initdata;
 
 static int __init acpi_parse_hpet(struct acpi_table_header *table)
 {
index 33120100ff5e50486e306f35688620ee8c05754f..3a2ae4c88948dcadb5b9afbfc2e10ef502202930 100644 (file)
@@ -25,6 +25,17 @@ unsigned long acpi_realmode_flags;
 static char temp_stack[4096];
 #endif
 
+/**
+ * x86_acpi_enter_sleep_state - enter sleep state
+ * @state: Sleep state to enter.
+ *
+ * Wrapper around acpi_enter_sleep_state() to be called by assmebly.
+ */
+acpi_status asmlinkage x86_acpi_enter_sleep_state(u8 state)
+{
+       return acpi_enter_sleep_state(state);
+}
+
 /**
  * x86_acpi_suspend_lowlevel - save kernel state
  *
index c9c2c982d5e4e168a20a3a2e8fb98bbabf1860e0..65c7b606b60697d73cd4a91c2702aacb678765ec 100644 (file)
@@ -17,3 +17,5 @@ extern void wakeup_long64(void);
 extern void do_suspend_lowlevel(void);
 
 extern int x86_acpi_suspend_lowlevel(void);
+
+acpi_status asmlinkage x86_acpi_enter_sleep_state(u8 state);
index d1daa66ab162c872b84fe4a8050c53f6f997246f..665c6b7d2ea93c25740a4b18043d5602d33d9711 100644 (file)
@@ -73,7 +73,7 @@ ENTRY(do_suspend_lowlevel)
        call    save_processor_state
        call    save_registers
        pushl   $3
-       call    acpi_enter_sleep_state
+       call    x86_acpi_enter_sleep_state
        addl    $4, %esp
 
 #      In case of S3 failure, we'll emerge here.  Jump
index 8ea5164cbd0451a27b9048699f60c2420057edb3..ae693b51ed8ed589660570a77cfb5654af924388 100644 (file)
@@ -73,7 +73,7 @@ ENTRY(do_suspend_lowlevel)
        addq    $8, %rsp
        movl    $3, %edi
        xorl    %eax, %eax
-       call    acpi_enter_sleep_state
+       call    x86_acpi_enter_sleep_state
        /* in case something went wrong, restore the machine status and go on */
        jmp     resume_point
 
index a7eb82d9b0120d02147d8eb1620a7da1d708c282..ed165d657380062387d08da7bf2f607fff192490 100644 (file)
@@ -2107,7 +2107,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
        apic_write(APIC_LVT1, value);
 }
 
-void generic_processor_info(int apicid, int version)
+int generic_processor_info(int apicid, int version)
 {
        int cpu, max = nr_cpu_ids;
        bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
@@ -2127,7 +2127,7 @@ void generic_processor_info(int apicid, int version)
                        "  Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
 
                disabled_cpus++;
-               return;
+               return -ENODEV;
        }
 
        if (num_processors >= nr_cpu_ids) {
@@ -2138,7 +2138,7 @@ void generic_processor_info(int apicid, int version)
                        "  Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
 
                disabled_cpus++;
-               return;
+               return -EINVAL;
        }
 
        num_processors++;
@@ -2183,6 +2183,8 @@ void generic_processor_info(int apicid, int version)
 #endif
        set_cpu_possible(cpu, true);
        set_cpu_present(cpu, true);
+
+       return cpu;
 }
 
 int hard_smp_processor_id(void)
index 1191ac1c9d2598e64d13a1419b4a7a383933ce03..a419814cea575f9e2cf183772a9e99c59e097a11 100644 (file)
@@ -113,7 +113,7 @@ static int __init early_get_pnodeid(void)
                break;
        case UV3_HUB_PART_NUMBER:
        case UV3_HUB_PART_NUMBER_X:
-               uv_min_hub_revision_id += UV3_HUB_REVISION_BASE - 1;
+               uv_min_hub_revision_id += UV3_HUB_REVISION_BASE;
                break;
        }
 
index 697b93af02ddbc0fb4461b5d853810fa250cd0a1..a0e2a8a80c94129bb3d3d47bf975ef68f98f500e 100644 (file)
@@ -775,11 +775,22 @@ void __init kvm_spinlock_init(void)
        if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
                return;
 
-       printk(KERN_INFO "KVM setup paravirtual spinlock\n");
+       pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
+       pv_lock_ops.unlock_kick = kvm_unlock_kick;
+}
+
+static __init int kvm_spinlock_init_jump(void)
+{
+       if (!kvm_para_available())
+               return 0;
+       if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
+               return 0;
 
        static_key_slow_inc(&paravirt_ticketlocks_enabled);
+       printk(KERN_INFO "KVM setup paravirtual spinlock\n");
 
-       pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
-       pv_lock_ops.unlock_kick = kvm_unlock_kick;
+       return 0;
 }
+early_initcall(kvm_spinlock_init_jump);
+
 #endif /* CONFIG_PARAVIRT_SPINLOCKS */
index 6cacab671f9b76a35aaf49d41431b12e788e5bbe..e73b3f53310c7663b2c37a3cffd57c0cad974a3c 100644 (file)
 /* State of each CPU */
 DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * We need this for trampoline_base protection from concurrent accesses when
- * off- and onlining cores wildly.
- */
-static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex);
-
-void cpu_hotplug_driver_lock(void)
-{
-       mutex_lock(&x86_cpu_hotplug_driver_mutex);
-}
-
-void cpu_hotplug_driver_unlock(void)
-{
-       mutex_unlock(&x86_cpu_hotplug_driver_mutex);
-}
-
-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; }
-#endif
-
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
 EXPORT_SYMBOL(smp_num_siblings);
index 6e60b5fe224481d01ca8662c6edd01432da08518..649b010da00ba5a0c191a4144f2458c08f0500ab 100644 (file)
@@ -65,29 +65,32 @@ int __ref _debug_hotplug_cpu(int cpu, int action)
        if (!cpu_is_hotpluggable(cpu))
                return -EINVAL;
 
-       cpu_hotplug_driver_lock();
+       lock_device_hotplug();
 
        switch (action) {
        case 0:
                ret = cpu_down(cpu);
                if (!ret) {
                        pr_info("CPU %u is now offline\n", cpu);
+                       dev->offline = true;
                        kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
                } else
                        pr_debug("Can't offline CPU%d.\n", cpu);
                break;
        case 1:
                ret = cpu_up(cpu);
-               if (!ret)
+               if (!ret) {
+                       dev->offline = false;
                        kobject_uevent(&dev->kobj, KOBJ_ONLINE);
-               else
+               } else {
                        pr_debug("Can't online CPU%d.\n", cpu);
+               }
                break;
        default:
                ret = -EINVAL;
        }
 
-       cpu_hotplug_driver_unlock();
+       unlock_device_hotplug();
 
        return ret;
 }
index a6b1b86d225358f05e58a649fdadedc4eafdb87e..518532e6a3faa213eb0833c6781c9ceba34dea86 100644 (file)
@@ -47,6 +47,21 @@ int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
 }
 EXPORT_SYMBOL(rdmsr_on_cpu);
 
+int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
+       *q = rv.reg.q;
+
+       return err;
+}
+EXPORT_SYMBOL(rdmsrl_on_cpu);
+
 int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 {
        int err;
@@ -63,6 +78,22 @@ int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 }
 EXPORT_SYMBOL(wrmsr_on_cpu);
 
+int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       rv.reg.q = q;
+
+       err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
+
+       return err;
+}
+EXPORT_SYMBOL(wrmsrl_on_cpu);
+
 static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
                            struct msr *msrs,
                            void (*msr_func) (void *info))
@@ -159,6 +190,37 @@ int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 }
 EXPORT_SYMBOL(wrmsr_safe_on_cpu);
 
+int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       rv.reg.q = q;
+
+       err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(wrmsrl_safe_on_cpu);
+
+int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
+       *q = rv.reg.q;
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(rdmsrl_safe_on_cpu);
+
 /*
  * These variants are significantly slower, but allows control over
  * the entire 32-bit GPR set.
index 79c216aa0e2baaac3a65a43972161922489c4978..516593e1ce33b92175195c8de2983258b723493c 100644 (file)
@@ -772,13 +772,21 @@ out:
        return;
 }
 
+static void bpf_jit_free_deferred(struct work_struct *work)
+{
+       struct sk_filter *fp = container_of(work, struct sk_filter, work);
+       unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
+       struct bpf_binary_header *header = (void *)addr;
+
+       set_memory_rw(addr, header->pages);
+       module_free(NULL, header);
+       kfree(fp);
+}
+
 void bpf_jit_free(struct sk_filter *fp)
 {
        if (fp->bpf_func != sk_run_filter) {
-               unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
-               struct bpf_binary_header *header = (void *)addr;
-
-               set_memory_rw(addr, header->pages);
-               module_free(NULL, header);
+               INIT_WORK(&fp->work, bpf_jit_free_deferred);
+               schedule_work(&fp->work);
        }
 }
index fef7d0ba7e3a93d8e44ed09cec92db708759cbcf..649a12befba92f399895b947cc779e0269ac750d 100644 (file)
@@ -40,16 +40,9 @@ static bool                          lid_wake_on_close;
  */
 static int set_lid_wake_behavior(bool wake_on_close)
 {
-       struct acpi_object_list arg_list;
-       union acpi_object arg;
        acpi_status status;
 
-       arg_list.count          = 1;
-       arg_list.pointer        = &arg;
-       arg.type                = ACPI_TYPE_INTEGER;
-       arg.integer.value       = wake_on_close;
-
-       status = acpi_evaluate_object(NULL, "\\_SB.PCI0.LID.LIDW", &arg_list, NULL);
+       status = acpi_execute_simple_method(NULL, "\\_SB.PCI0.LID.LIDW", wake_on_close);
        if (ACPI_FAILURE(status)) {
                pr_warning(PFX "failed to set lid behavior\n");
                return 1;
index d1e4777b4e75352fea33ca6a3e3d43a679e19c6d..31d04758b76f6a2da41c309e368768d4881066d0 100644 (file)
@@ -278,6 +278,15 @@ static void __init xen_smp_prepare_boot_cpu(void)
                   old memory can be recycled */
                make_lowmem_page_readwrite(xen_initial_gdt);
 
+#ifdef CONFIG_X86_32
+               /*
+                * Xen starts us with XEN_FLAT_RING1_DS, but linux code
+                * expects __USER_DS
+                */
+               loadsegment(ds, __USER_DS);
+               loadsegment(es, __USER_DS);
+#endif
+
                xen_filter_cpu_maps();
                xen_setup_vcpu_info_placement();
        }
index 1eb09ee5311b414e448b28eb26a72f7ff6bbaa1c..a8287b49d0621d1778295ad0516c8ccbf22ed0fa 100644 (file)
@@ -222,11 +222,16 @@ check_hybrid:
         * the disk size.
         *
         * Hybrid MBRs do not necessarily comply with this.
+        *
+        * Consider a bad value here to be a warning to support dd'ing
+        * an image from a smaller disk to a larger disk.
         */
        if (ret == GPT_MBR_PROTECTIVE) {
                sz = le32_to_cpu(mbr->partition_record[part].size_in_lba);
                if (sz != (uint32_t) total_sectors - 1 && sz != 0xFFFFFFFF)
-                       ret = 0;
+                       pr_debug("GPT: mbr size in lba (%u) different than whole disk (%u).\n",
+                                sz, min_t(uint32_t,
+                                          total_sectors - 1, 0xFFFFFFFF));
        }
 done:
        return ret;
index aa43b911ccef582c78e70a914106ba454de2c05b..969e9871785ca5ae47e0153ef96c15c460daca18 100644 (file)
@@ -166,4 +166,6 @@ source "drivers/reset/Kconfig"
 
 source "drivers/fmc/Kconfig"
 
+source "drivers/powercap/Kconfig"
+
 endmenu
index ab93de8297f1338fc2440967ce8934a7ff6bc043..34c1d554f69b489fc523a811e9f1fc76b5a5cd4e 100644 (file)
@@ -152,3 +152,4 @@ obj-$(CONFIG_VME_BUS)               += vme/
 obj-$(CONFIG_IPACK_BUS)                += ipack/
 obj-$(CONFIG_NTB)              += ntb/
 obj-$(CONFIG_FMC)              += fmc/
+obj-$(CONFIG_POWERCAP)         += powercap/
index 22327e6a7236fc367313ec5acf45016d354863d4..589da059ce3939c9a2139907daefbf00a5a9b0e2 100644 (file)
@@ -24,7 +24,7 @@ menuconfig ACPI
          are configured, ACPI is used.
 
          The project home page for the Linux ACPI subsystem is here:
-         <http://www.lesswatts.org/projects/acpi/>
+         <https://01.org/linux-acpi>
 
          Linux support for ACPI is based on Intel Corporation's ACPI
          Component Architecture (ACPI CA).  For more information on the
@@ -56,23 +56,6 @@ config ACPI_PROCFS
 
          Say N to delete /proc/acpi/ files that have moved to /sys/
 
-config ACPI_PROCFS_POWER
-       bool "Deprecated power /proc/acpi directories"
-       depends on PROC_FS
-       help
-         For backwards compatibility, this option allows
-          deprecated power /proc/acpi/ directories to exist, even when
-          they have been replaced by functions in /sys.
-          The deprecated directories (and their replacements) include:
-         /proc/acpi/battery/* (/sys/class/power_supply/*)
-         /proc/acpi/ac_adapter/* (sys/class/power_supply/*)
-         This option has no effect on /proc/acpi/ directories
-         and functions, which do not yet exist in /sys
-         This option, together with the proc directories, will be
-         deleted in 2.6.39.
-
-         Say N to delete power /proc/acpi/ directories that have moved to /sys/
-
 config ACPI_EC_DEBUGFS
        tristate "EC read/write access through /sys/kernel/debug/ec"
        default n
@@ -123,9 +106,9 @@ config ACPI_BUTTON
        default y
        help
          This driver handles events on the power, sleep, and lid buttons.
-         A daemon reads /proc/acpi/event and perform user-defined actions
-         such as shutting down the system.  This is necessary for
-         software-controlled poweroff.
+         A daemon reads events from input devices or via netlink and
+         performs user-defined actions such as shutting down the system.
+         This is necessary for software-controlled poweroff.
 
          To compile this driver as a module, choose M here:
          the module will be called button.
@@ -175,9 +158,10 @@ config ACPI_PROCESSOR
 
          To compile this driver as a module, choose M here:
          the module will be called processor.
+
 config ACPI_IPMI
        tristate "IPMI"
-       depends on IPMI_SI && IPMI_HANDLER
+       depends on IPMI_SI
        default n
        help
          This driver enables the ACPI to access the BMC controller. And it
index cdaf68b58b006fb833f104f2d5e28baa4ecaf991..a55fc06db4ae705b47aa8ca9f2b33d456057c536 100644 (file)
@@ -47,7 +47,6 @@ acpi-y                                += sysfs.o
 acpi-$(CONFIG_X86)             += acpi_cmos_rtc.o
 acpi-$(CONFIG_DEBUG_FS)                += debugfs.o
 acpi-$(CONFIG_ACPI_NUMA)       += numa.o
-acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
 ifdef CONFIG_ACPI_VIDEO
 acpi-y                         += video_detect.o
 endif
index f37beaa32750106dffdf9fd7aeac764f1f0094f2..b9f0d5f4bba51cecb6ffe8fda126762850818263 100644 (file)
 #include <linux/types.h>
 #include <linux/dmi.h>
 #include <linux/delay.h>
-#ifdef CONFIG_ACPI_PROCFS_POWER
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#endif
+#include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
@@ -55,75 +52,30 @@ MODULE_AUTHOR("Paul Diefenbaugh");
 MODULE_DESCRIPTION("ACPI AC Adapter Driver");
 MODULE_LICENSE("GPL");
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-extern struct proc_dir_entry *acpi_lock_ac_dir(void);
-extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
-static int acpi_ac_open_fs(struct inode *inode, struct file *file);
-#endif
-
-static int acpi_ac_add(struct acpi_device *device);
-static int acpi_ac_remove(struct acpi_device *device);
-static void acpi_ac_notify(struct acpi_device *device, u32 event);
-
-static const struct acpi_device_id ac_device_ids[] = {
-       {"ACPI0003", 0},
-       {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, ac_device_ids);
-
-#ifdef CONFIG_PM_SLEEP
-static int acpi_ac_resume(struct device *dev);
-#endif
-static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
-
 static int ac_sleep_before_get_state_ms;
 
-static struct acpi_driver acpi_ac_driver = {
-       .name = "ac",
-       .class = ACPI_AC_CLASS,
-       .ids = ac_device_ids,
-       .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-       .ops = {
-               .add = acpi_ac_add,
-               .remove = acpi_ac_remove,
-               .notify = acpi_ac_notify,
-               },
-       .drv.pm = &acpi_ac_pm,
-};
-
 struct acpi_ac {
        struct power_supply charger;
-       struct acpi_device * device;
+       struct acpi_device *adev;
+       struct platform_device *pdev;
        unsigned long long state;
 };
 
 #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger)
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-static const struct file_operations acpi_ac_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_ac_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-#endif
-
 /* --------------------------------------------------------------------------
                                AC Adapter Management
    -------------------------------------------------------------------------- */
 
 static int acpi_ac_get_state(struct acpi_ac *ac)
 {
-       acpi_status status = AE_OK;
-
-
-       if (!ac)
-               return -EINVAL;
+       acpi_status status;
 
-       status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state);
+       status = acpi_evaluate_integer(ac->adev->handle, "_PSR", NULL,
+                                      &ac->state);
        if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state"));
+               ACPI_EXCEPTION((AE_INFO, status,
+                               "Error reading AC Adapter state"));
                ac->state = ACPI_AC_STATUS_UNKNOWN;
                return -ENODEV;
        }
@@ -160,91 +112,13 @@ static enum power_supply_property ac_props[] = {
        POWER_SUPPLY_PROP_ONLINE,
 };
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-/* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-
-static struct proc_dir_entry *acpi_ac_dir;
-
-static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_ac *ac = seq->private;
-
-
-       if (!ac)
-               return 0;
-
-       if (acpi_ac_get_state(ac)) {
-               seq_puts(seq, "ERROR: Unable to read AC Adapter state\n");
-               return 0;
-       }
-
-       seq_puts(seq, "state:                   ");
-       switch (ac->state) {
-       case ACPI_AC_STATUS_OFFLINE:
-               seq_puts(seq, "off-line\n");
-               break;
-       case ACPI_AC_STATUS_ONLINE:
-               seq_puts(seq, "on-line\n");
-               break;
-       default:
-               seq_puts(seq, "unknown\n");
-               break;
-       }
-
-       return 0;
-}
-
-static int acpi_ac_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_ac_seq_show, PDE_DATA(inode));
-}
-
-static int acpi_ac_add_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *entry = NULL;
-
-       printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded,"
-                       " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
-       if (!acpi_device_dir(device)) {
-               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-                                                    acpi_ac_dir);
-               if (!acpi_device_dir(device))
-                       return -ENODEV;
-       }
-
-       /* 'state' [R] */
-       entry = proc_create_data(ACPI_AC_FILE_STATE,
-                                S_IRUGO, acpi_device_dir(device),
-                                &acpi_ac_fops, acpi_driver_data(device));
-       if (!entry)
-               return -ENODEV;
-       return 0;
-}
-
-static int acpi_ac_remove_fs(struct acpi_device *device)
-{
-
-       if (acpi_device_dir(device)) {
-               remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device));
-
-               remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
-               acpi_device_dir(device) = NULL;
-       }
-
-       return 0;
-}
-#endif
-
 /* --------------------------------------------------------------------------
                                    Driver Model
    -------------------------------------------------------------------------- */
 
-static void acpi_ac_notify(struct acpi_device *device, u32 event)
+static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_ac *ac = acpi_driver_data(device);
-
+       struct acpi_ac *ac = data;
 
        if (!ac)
                return;
@@ -267,10 +141,10 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
                        msleep(ac_sleep_before_get_state_ms);
 
                acpi_ac_get_state(ac);
-               acpi_bus_generate_netlink_event(device->pnp.device_class,
-                                                 dev_name(&device->dev), event,
-                                                 (u32) ac->state);
-               acpi_notifier_call_chain(device, event, (u32) ac->state);
+               acpi_bus_generate_netlink_event(ac->adev->pnp.device_class,
+                                               dev_name(&ac->pdev->dev),
+                                               event, (u32) ac->state);
+               acpi_notifier_call_chain(ac->adev, event, (u32) ac->state);
                kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
        }
 
@@ -295,53 +169,55 @@ static struct dmi_system_id ac_dmi_table[] = {
        {},
 };
 
-static int acpi_ac_add(struct acpi_device *device)
+static int acpi_ac_probe(struct platform_device *pdev)
 {
        int result = 0;
        struct acpi_ac *ac = NULL;
+       struct acpi_device *adev;
 
-
-       if (!device)
+       if (!pdev)
                return -EINVAL;
 
+       result = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
+       if (result)
+               return -ENODEV;
+
        ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
        if (!ac)
                return -ENOMEM;
 
-       ac->device = device;
-       strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
-       strcpy(acpi_device_class(device), ACPI_AC_CLASS);
-       device->driver_data = ac;
+       strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME);
+       strcpy(acpi_device_class(adev), ACPI_AC_CLASS);
+       ac->adev = adev;
+       ac->pdev = pdev;
+       platform_set_drvdata(pdev, ac);
 
        result = acpi_ac_get_state(ac);
        if (result)
                goto end;
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       result = acpi_ac_add_fs(device);
-#endif
-       if (result)
-               goto end;
-       ac->charger.name = acpi_device_bid(device);
+       ac->charger.name = acpi_device_bid(adev);
        ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
        ac->charger.properties = ac_props;
        ac->charger.num_properties = ARRAY_SIZE(ac_props);
        ac->charger.get_property = get_ac_property;
-       result = power_supply_register(&ac->device->dev, &ac->charger);
+       result = power_supply_register(&pdev->dev, &ac->charger);
        if (result)
                goto end;
 
+       result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
+                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, ac);
+       if (result) {
+               power_supply_unregister(&ac->charger);
+               goto end;
+       }
        printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
-              acpi_device_name(device), acpi_device_bid(device),
+              acpi_device_name(adev), acpi_device_bid(adev),
               ac->state ? "on-line" : "off-line");
 
-      end:
-       if (result) {
-#ifdef CONFIG_ACPI_PROCFS_POWER
-               acpi_ac_remove_fs(device);
-#endif
+end:
+       if (result)
                kfree(ac);
-       }
 
        dmi_check_system(ac_dmi_table);
        return result;
@@ -356,7 +232,7 @@ static int acpi_ac_resume(struct device *dev)
        if (!dev)
                return -EINVAL;
 
-       ac = acpi_driver_data(to_acpi_device(dev));
+       ac = platform_get_drvdata(to_platform_device(dev));
        if (!ac)
                return -EINVAL;
 
@@ -368,28 +244,44 @@ static int acpi_ac_resume(struct device *dev)
        return 0;
 }
 #endif
+static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume);
 
-static int acpi_ac_remove(struct acpi_device *device)
+static int acpi_ac_remove(struct platform_device *pdev)
 {
-       struct acpi_ac *ac = NULL;
-
+       struct acpi_ac *ac;
 
-       if (!device || !acpi_driver_data(device))
+       if (!pdev)
                return -EINVAL;
 
-       ac = acpi_driver_data(device);
+       acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
+                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler);
 
+       ac = platform_get_drvdata(pdev);
        if (ac->charger.dev)
                power_supply_unregister(&ac->charger);
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_ac_remove_fs(device);
-#endif
 
        kfree(ac);
 
        return 0;
 }
 
+static const struct acpi_device_id acpi_ac_match[] = {
+       { "ACPI0003", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, acpi_ac_match);
+
+static struct platform_driver acpi_ac_driver = {
+       .probe          = acpi_ac_probe,
+       .remove         = acpi_ac_remove,
+       .driver         = {
+               .name   = "acpi-ac",
+               .owner  = THIS_MODULE,
+               .pm     = &acpi_ac_pm_ops,
+               .acpi_match_table = ACPI_PTR(acpi_ac_match),
+       },
+};
+
 static int __init acpi_ac_init(void)
 {
        int result;
@@ -397,34 +289,16 @@ static int __init acpi_ac_init(void)
        if (acpi_disabled)
                return -ENODEV;
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_ac_dir = acpi_lock_ac_dir();
-       if (!acpi_ac_dir)
+       result = platform_driver_register(&acpi_ac_driver);
+       if (result < 0)
                return -ENODEV;
-#endif
-
-       result = acpi_bus_register_driver(&acpi_ac_driver);
-       if (result < 0) {
-#ifdef CONFIG_ACPI_PROCFS_POWER
-               acpi_unlock_ac_dir(acpi_ac_dir);
-#endif
-               return -ENODEV;
-       }
 
        return 0;
 }
 
 static void __exit acpi_ac_exit(void)
 {
-
-       acpi_bus_unregister_driver(&acpi_ac_driver);
-
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_unlock_ac_dir(acpi_ac_dir);
-#endif
-
-       return;
+       platform_driver_unregister(&acpi_ac_driver);
 }
-
 module_init(acpi_ac_init);
 module_exit(acpi_ac_exit);
index a6977e12d5745ab5f2015e2f2879174bddd64bc0..ac0f52f6df2b862052a3de423ac039a6bd2eefe8 100644 (file)
@@ -1,8 +1,9 @@
 /*
  *  acpi_ipmi.c - ACPI IPMI opregion
  *
- *  Copyright (C) 2010 Intel Corporation
- *  Copyright (C) 2010 Zhao Yakui <yakui.zhao@intel.com>
+ *  Copyright (C) 2010, 2013 Intel Corporation
+ *    Author: Zhao Yakui <yakui.zhao@intel.com>
+ *            Lv Zheng <lv.zheng@intel.com>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
-#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <linux/ipmi.h>
-#include <linux/device.h>
-#include <linux/pnp.h>
 #include <linux/spinlock.h>
 
 MODULE_AUTHOR("Zhao Yakui");
 MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
 MODULE_LICENSE("GPL");
 
-#define IPMI_FLAGS_HANDLER_INSTALL     0
-
 #define ACPI_IPMI_OK                   0
 #define ACPI_IPMI_TIMEOUT              0x10
 #define ACPI_IPMI_UNKNOWN              0x07
 /* the IPMI timeout is 5s */
-#define IPMI_TIMEOUT                   (5 * HZ)
+#define IPMI_TIMEOUT                   (5000)
+#define ACPI_IPMI_MAX_MSG_LENGTH       64
 
 struct acpi_ipmi_device {
        /* the device list attached to driver_data.ipmi_devices */
        struct list_head head;
+
        /* the IPMI request message list */
        struct list_head tx_msg_list;
-       spinlock_t      tx_msg_lock;
+
+       spinlock_t tx_msg_lock;
        acpi_handle handle;
-       struct pnp_dev *pnp_dev;
-       ipmi_user_t     user_interface;
+       struct device *dev;
+       ipmi_user_t user_interface;
        int ipmi_ifnum; /* IPMI interface number */
        long curr_msgid;
-       unsigned long flags;
-       struct ipmi_smi_info smi_data;
+       bool dead;
+       struct kref kref;
 };
 
 struct ipmi_driver_data {
-       struct list_head        ipmi_devices;
-       struct ipmi_smi_watcher bmc_events;
-       struct ipmi_user_hndl   ipmi_hndlrs;
-       struct mutex            ipmi_lock;
+       struct list_head ipmi_devices;
+       struct ipmi_smi_watcher bmc_events;
+       struct ipmi_user_hndl ipmi_hndlrs;
+       struct mutex ipmi_lock;
+
+       /*
+        * NOTE: IPMI System Interface Selection
+        * There is no system interface specified by the IPMI operation
+        * region access.  We try to select one system interface with ACPI
+        * handle set.  IPMI messages passed from the ACPI codes are sent
+        * to this selected global IPMI system interface.
+        */
+       struct acpi_ipmi_device *selected_smi;
 };
 
 struct acpi_ipmi_msg {
        struct list_head head;
+
        /*
         * General speaking the addr type should be SI_ADDR_TYPE. And
         * the addr channel should be BMC.
@@ -86,30 +85,31 @@ struct acpi_ipmi_msg {
         */
        struct ipmi_addr addr;
        long tx_msgid;
+
        /* it is used to track whether the IPMI message is finished */
        struct completion tx_complete;
+
        struct kernel_ipmi_msg tx_message;
-       int     msg_done;
-       /* tx data . And copy it from ACPI object buffer */
-       u8      tx_data[64];
-       int     tx_len;
-       u8      rx_data[64];
-       int     rx_len;
+       int msg_done;
+
+       /* tx/rx data . And copy it from/to ACPI object buffer */
+       u8 data[ACPI_IPMI_MAX_MSG_LENGTH];
+       u8 rx_len;
+
        struct acpi_ipmi_device *device;
+       struct kref kref;
 };
 
 /* IPMI request/response buffer per ACPI 4.0, sec 5.5.2.4.3.2 */
 struct acpi_ipmi_buffer {
        u8 status;
        u8 length;
-       u8 data[64];
+       u8 data[ACPI_IPMI_MAX_MSG_LENGTH];
 };
 
 static void ipmi_register_bmc(int iface, struct device *dev);
 static void ipmi_bmc_gone(int iface);
 static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
-static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device);
-static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device);
 
 static struct ipmi_driver_data driver_data = {
        .ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices),
@@ -121,29 +121,142 @@ static struct ipmi_driver_data driver_data = {
        .ipmi_hndlrs = {
                .ipmi_recv_hndl = ipmi_msg_handler,
        },
+       .ipmi_lock = __MUTEX_INITIALIZER(driver_data.ipmi_lock)
 };
 
-static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi)
+static struct acpi_ipmi_device *
+ipmi_dev_alloc(int iface, struct device *dev, acpi_handle handle)
+{
+       struct acpi_ipmi_device *ipmi_device;
+       int err;
+       ipmi_user_t user;
+
+       ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL);
+       if (!ipmi_device)
+               return NULL;
+
+       kref_init(&ipmi_device->kref);
+       INIT_LIST_HEAD(&ipmi_device->head);
+       INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
+       spin_lock_init(&ipmi_device->tx_msg_lock);
+       ipmi_device->handle = handle;
+       ipmi_device->dev = get_device(dev);
+       ipmi_device->ipmi_ifnum = iface;
+
+       err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs,
+                              ipmi_device, &user);
+       if (err) {
+               put_device(dev);
+               kfree(ipmi_device);
+               return NULL;
+       }
+       ipmi_device->user_interface = user;
+
+       return ipmi_device;
+}
+
+static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device)
+{
+       ipmi_destroy_user(ipmi_device->user_interface);
+       put_device(ipmi_device->dev);
+       kfree(ipmi_device);
+}
+
+static void ipmi_dev_release_kref(struct kref *kref)
+{
+       struct acpi_ipmi_device *ipmi =
+               container_of(kref, struct acpi_ipmi_device, kref);
+
+       ipmi_dev_release(ipmi);
+}
+
+static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device)
+{
+       list_del(&ipmi_device->head);
+       if (driver_data.selected_smi == ipmi_device)
+               driver_data.selected_smi = NULL;
+
+       /*
+        * Always setting dead flag after deleting from the list or
+        * list_for_each_entry() codes must get changed.
+        */
+       ipmi_device->dead = true;
+}
+
+static struct acpi_ipmi_device *acpi_ipmi_dev_get(void)
+{
+       struct acpi_ipmi_device *ipmi_device = NULL;
+
+       mutex_lock(&driver_data.ipmi_lock);
+       if (driver_data.selected_smi) {
+               ipmi_device = driver_data.selected_smi;
+               kref_get(&ipmi_device->kref);
+       }
+       mutex_unlock(&driver_data.ipmi_lock);
+
+       return ipmi_device;
+}
+
+static void acpi_ipmi_dev_put(struct acpi_ipmi_device *ipmi_device)
+{
+       kref_put(&ipmi_device->kref, ipmi_dev_release_kref);
+}
+
+static struct acpi_ipmi_msg *ipmi_msg_alloc(void)
 {
+       struct acpi_ipmi_device *ipmi;
        struct acpi_ipmi_msg *ipmi_msg;
-       struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+
+       ipmi = acpi_ipmi_dev_get();
+       if (!ipmi)
+               return NULL;
 
        ipmi_msg = kzalloc(sizeof(struct acpi_ipmi_msg), GFP_KERNEL);
-       if (!ipmi_msg)  {
-               dev_warn(&pnp_dev->dev, "Can't allocate memory for ipmi_msg\n");
+       if (!ipmi_msg) {
+               acpi_ipmi_dev_put(ipmi);
                return NULL;
        }
+
+       kref_init(&ipmi_msg->kref);
        init_completion(&ipmi_msg->tx_complete);
        INIT_LIST_HEAD(&ipmi_msg->head);
        ipmi_msg->device = ipmi;
+       ipmi_msg->msg_done = ACPI_IPMI_UNKNOWN;
+
        return ipmi_msg;
 }
 
-#define                IPMI_OP_RGN_NETFN(offset)       ((offset >> 8) & 0xff)
-#define                IPMI_OP_RGN_CMD(offset)         (offset & 0xff)
-static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
-                               acpi_physical_address address,
-                               acpi_integer *value)
+static void ipmi_msg_release(struct acpi_ipmi_msg *tx_msg)
+{
+       acpi_ipmi_dev_put(tx_msg->device);
+       kfree(tx_msg);
+}
+
+static void ipmi_msg_release_kref(struct kref *kref)
+{
+       struct acpi_ipmi_msg *tx_msg =
+               container_of(kref, struct acpi_ipmi_msg, kref);
+
+       ipmi_msg_release(tx_msg);
+}
+
+static struct acpi_ipmi_msg *acpi_ipmi_msg_get(struct acpi_ipmi_msg *tx_msg)
+{
+       kref_get(&tx_msg->kref);
+
+       return tx_msg;
+}
+
+static void acpi_ipmi_msg_put(struct acpi_ipmi_msg *tx_msg)
+{
+       kref_put(&tx_msg->kref, ipmi_msg_release_kref);
+}
+
+#define IPMI_OP_RGN_NETFN(offset)      ((offset >> 8) & 0xff)
+#define IPMI_OP_RGN_CMD(offset)                (offset & 0xff)
+static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg,
+                                   acpi_physical_address address,
+                                   acpi_integer *value)
 {
        struct kernel_ipmi_msg *msg;
        struct acpi_ipmi_buffer *buffer;
@@ -151,21 +264,31 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
        unsigned long flags;
 
        msg = &tx_msg->tx_message;
+
        /*
         * IPMI network function and command are encoded in the address
         * within the IPMI OpRegion; see ACPI 4.0, sec 5.5.2.4.3.
         */
        msg->netfn = IPMI_OP_RGN_NETFN(address);
        msg->cmd = IPMI_OP_RGN_CMD(address);
-       msg->data = tx_msg->tx_data;
+       msg->data = tx_msg->data;
+
        /*
         * value is the parameter passed by the IPMI opregion space handler.
         * It points to the IPMI request message buffer
         */
        buffer = (struct acpi_ipmi_buffer *)value;
+
        /* copy the tx message data */
+       if (buffer->length > ACPI_IPMI_MAX_MSG_LENGTH) {
+               dev_WARN_ONCE(tx_msg->device->dev, true,
+                             "Unexpected request (msg len %d).\n",
+                             buffer->length);
+               return -EINVAL;
+       }
        msg->data_len = buffer->length;
-       memcpy(tx_msg->tx_data, buffer->data, msg->data_len);
+       memcpy(tx_msg->data, buffer->data, msg->data_len);
+
        /*
         * now the default type is SYSTEM_INTERFACE and channel type is BMC.
         * If the netfn is APP_REQUEST and the cmd is SEND_MESSAGE,
@@ -179,14 +302,17 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
 
        /* Get the msgid */
        device = tx_msg->device;
+
        spin_lock_irqsave(&device->tx_msg_lock, flags);
        device->curr_msgid++;
        tx_msg->tx_msgid = device->curr_msgid;
        spin_unlock_irqrestore(&device->tx_msg_lock, flags);
+
+       return 0;
 }
 
 static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
-               acpi_integer *value, int rem_time)
+                                     acpi_integer *value)
 {
        struct acpi_ipmi_buffer *buffer;
 
@@ -195,110 +321,158 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
         * IPMI message returned by IPMI command.
         */
        buffer = (struct acpi_ipmi_buffer *)value;
-       if (!rem_time && !msg->msg_done) {
-               buffer->status = ACPI_IPMI_TIMEOUT;
-               return;
-       }
+
        /*
-        * If the flag of msg_done is not set or the recv length is zero, it
-        * means that the IPMI command is not executed correctly.
-        * The status code will be ACPI_IPMI_UNKNOWN.
+        * If the flag of msg_done is not set, it means that the IPMI command is
+        * not executed correctly.
         */
-       if (!msg->msg_done || !msg->rx_len) {
-               buffer->status = ACPI_IPMI_UNKNOWN;
+       buffer->status = msg->msg_done;
+       if (msg->msg_done != ACPI_IPMI_OK)
                return;
-       }
+
        /*
         * If the IPMI response message is obtained correctly, the status code
         * will be ACPI_IPMI_OK
         */
-       buffer->status = ACPI_IPMI_OK;
        buffer->length = msg->rx_len;
-       memcpy(buffer->data, msg->rx_data, msg->rx_len);
+       memcpy(buffer->data, msg->data, msg->rx_len);
 }
 
 static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi)
 {
-       struct acpi_ipmi_msg *tx_msg, *temp;
-       int count = HZ / 10;
-       struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+       struct acpi_ipmi_msg *tx_msg;
+       unsigned long flags;
+
+       /*
+        * NOTE: On-going ipmi_recv_msg
+        * ipmi_msg_handler() may still be invoked by ipmi_si after
+        * flushing.  But it is safe to do a fast flushing on module_exit()
+        * without waiting for all ipmi_recv_msg(s) to complete from
+        * ipmi_msg_handler() as it is ensured by ipmi_si that all
+        * ipmi_recv_msg(s) are freed after invoking ipmi_destroy_user().
+        */
+       spin_lock_irqsave(&ipmi->tx_msg_lock, flags);
+       while (!list_empty(&ipmi->tx_msg_list)) {
+               tx_msg = list_first_entry(&ipmi->tx_msg_list,
+                                         struct acpi_ipmi_msg,
+                                         head);
+               list_del(&tx_msg->head);
+               spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags);
 
-       list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) {
                /* wake up the sleep thread on the Tx msg */
                complete(&tx_msg->tx_complete);
+               acpi_ipmi_msg_put(tx_msg);
+               spin_lock_irqsave(&ipmi->tx_msg_lock, flags);
        }
+       spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags);
+}
+
+static void ipmi_cancel_tx_msg(struct acpi_ipmi_device *ipmi,
+                              struct acpi_ipmi_msg *msg)
+{
+       struct acpi_ipmi_msg *tx_msg, *temp;
+       bool msg_found = false;
+       unsigned long flags;
 
-       /* wait for about 100ms to flush the tx message list */
-       while (count--) {
-               if (list_empty(&ipmi->tx_msg_list))
+       spin_lock_irqsave(&ipmi->tx_msg_lock, flags);
+       list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) {
+               if (msg == tx_msg) {
+                       msg_found = true;
+                       list_del(&tx_msg->head);
                        break;
-               schedule_timeout(1);
+               }
        }
-       if (!list_empty(&ipmi->tx_msg_list))
-               dev_warn(&pnp_dev->dev, "tx msg list is not NULL\n");
+       spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags);
+
+       if (msg_found)
+               acpi_ipmi_msg_put(tx_msg);
 }
 
 static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
 {
        struct acpi_ipmi_device *ipmi_device = user_msg_data;
-       int msg_found = 0;
-       struct acpi_ipmi_msg *tx_msg;
-       struct pnp_dev *pnp_dev = ipmi_device->pnp_dev;
+       bool msg_found = false;
+       struct acpi_ipmi_msg *tx_msg, *temp;
+       struct device *dev = ipmi_device->dev;
        unsigned long flags;
 
        if (msg->user != ipmi_device->user_interface) {
-               dev_warn(&pnp_dev->dev, "Unexpected response is returned. "
-                       "returned user %p, expected user %p\n",
-                       msg->user, ipmi_device->user_interface);
-               ipmi_free_recv_msg(msg);
-               return;
+               dev_warn(dev,
+                        "Unexpected response is returned. returned user %p, expected user %p\n",
+                        msg->user, ipmi_device->user_interface);
+               goto out_msg;
        }
+
        spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
-       list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) {
+       list_for_each_entry_safe(tx_msg, temp, &ipmi_device->tx_msg_list, head) {
                if (msg->msgid == tx_msg->tx_msgid) {
-                       msg_found = 1;
+                       msg_found = true;
+                       list_del(&tx_msg->head);
                        break;
                }
        }
-
        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);
-               ipmi_free_recv_msg(msg);
-               return;
+               dev_warn(dev,
+                        "Unexpected response (msg id %ld) is returned.\n",
+                        msg->msgid);
+               goto out_msg;
        }
 
-       if (msg->msg.data_len) {
-               /* copy the response data to Rx_data buffer */
-               memcpy(tx_msg->rx_data, msg->msg_data, msg->msg.data_len);
-               tx_msg->rx_len = msg->msg.data_len;
-               tx_msg->msg_done = 1;
+       /* copy the response data to Rx_data buffer */
+       if (msg->msg.data_len > ACPI_IPMI_MAX_MSG_LENGTH) {
+               dev_WARN_ONCE(dev, true,
+                             "Unexpected response (msg len %d).\n",
+                             msg->msg.data_len);
+               goto out_comp;
        }
+
+       /* response msg is an error msg */
+       msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
+       if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE &&
+           msg->msg.data_len == 1) {
+               if (msg->msg.data[0] == IPMI_TIMEOUT_COMPLETION_CODE) {
+                       dev_WARN_ONCE(dev, true,
+                                     "Unexpected response (timeout).\n");
+                       tx_msg->msg_done = ACPI_IPMI_TIMEOUT;
+               }
+               goto out_comp;
+       }
+
+       tx_msg->rx_len = msg->msg.data_len;
+       memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len);
+       tx_msg->msg_done = ACPI_IPMI_OK;
+
+out_comp:
        complete(&tx_msg->tx_complete);
+       acpi_ipmi_msg_put(tx_msg);
+out_msg:
        ipmi_free_recv_msg(msg);
-};
+}
 
 static void ipmi_register_bmc(int iface, struct device *dev)
 {
        struct acpi_ipmi_device *ipmi_device, *temp;
-       struct pnp_dev *pnp_dev;
-       ipmi_user_t             user;
        int err;
        struct ipmi_smi_info smi_data;
        acpi_handle handle;
 
        err = ipmi_get_smi_info(iface, &smi_data);
-
        if (err)
                return;
 
-       if (smi_data.addr_src != SI_ACPI) {
-               put_device(smi_data.dev);
-               return;
-       }
-
+       if (smi_data.addr_src != SI_ACPI)
+               goto err_ref;
        handle = smi_data.addr_info.acpi_info.acpi_handle;
+       if (!handle)
+               goto err_ref;
+
+       ipmi_device = ipmi_dev_alloc(iface, smi_data.dev, handle);
+       if (!ipmi_device) {
+               dev_warn(smi_data.dev, "Can't create IPMI user interface\n");
+               goto err_ref;
+       }
 
        mutex_lock(&driver_data.ipmi_lock);
        list_for_each_entry(temp, &driver_data.ipmi_devices, head) {
@@ -307,34 +481,20 @@ static void ipmi_register_bmc(int iface, struct device *dev)
                 * to the device list, don't add it again.
                 */
                if (temp->handle == handle)
-                       goto out;
+                       goto err_lock;
        }
-
-       ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL);
-
-       if (!ipmi_device)
-               goto out;
-
-       pnp_dev = to_pnp_dev(smi_data.dev);
-       ipmi_device->handle = handle;
-       ipmi_device->pnp_dev = pnp_dev;
-
-       err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs,
-                                       ipmi_device, &user);
-       if (err) {
-               dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n");
-               kfree(ipmi_device);
-               goto out;
-       }
-       acpi_add_ipmi_device(ipmi_device);
-       ipmi_device->user_interface = user;
-       ipmi_device->ipmi_ifnum = iface;
+       if (!driver_data.selected_smi)
+               driver_data.selected_smi = ipmi_device;
+       list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices);
        mutex_unlock(&driver_data.ipmi_lock);
-       memcpy(&ipmi_device->smi_data, &smi_data, sizeof(struct ipmi_smi_info));
+
+       put_device(smi_data.dev);
        return;
 
-out:
+err_lock:
        mutex_unlock(&driver_data.ipmi_lock);
+       ipmi_dev_release(ipmi_device);
+err_ref:
        put_device(smi_data.dev);
        return;
 }
@@ -342,23 +502,29 @@ out:
 static void ipmi_bmc_gone(int iface)
 {
        struct acpi_ipmi_device *ipmi_device, *temp;
+       bool dev_found = false;
 
        mutex_lock(&driver_data.ipmi_lock);
        list_for_each_entry_safe(ipmi_device, temp,
-                               &driver_data.ipmi_devices, head) {
-               if (ipmi_device->ipmi_ifnum != iface)
-                       continue;
-
-               acpi_remove_ipmi_device(ipmi_device);
-               put_device(ipmi_device->smi_data.dev);
-               kfree(ipmi_device);
-               break;
+                                &driver_data.ipmi_devices, head) {
+               if (ipmi_device->ipmi_ifnum != iface) {
+                       dev_found = true;
+                       __ipmi_dev_kill(ipmi_device);
+                       break;
+               }
        }
+       if (!driver_data.selected_smi)
+               driver_data.selected_smi = list_first_entry_or_null(
+                                       &driver_data.ipmi_devices,
+                                       struct acpi_ipmi_device, head);
        mutex_unlock(&driver_data.ipmi_lock);
+
+       if (dev_found) {
+               ipmi_flush_tx_msg(ipmi_device);
+               acpi_ipmi_dev_put(ipmi_device);
+       }
 }
-/* --------------------------------------------------------------------------
- *                     Address Space Management
- * -------------------------------------------------------------------------- */
+
 /*
  * This is the IPMI opregion space handler.
  * @function: indicates the read/write. In fact as the IPMI message is driven
@@ -371,17 +537,17 @@ static void ipmi_bmc_gone(int iface)
  *          the response IPMI message returned by IPMI command.
  * @handler_context: IPMI device context.
  */
-
 static acpi_status
 acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
-                     u32 bits, acpi_integer *value,
-                     void *handler_context, void *region_context)
+                       u32 bits, acpi_integer *value,
+                       void *handler_context, void *region_context)
 {
        struct acpi_ipmi_msg *tx_msg;
-       struct acpi_ipmi_device *ipmi_device = handler_context;
-       int err, rem_time;
+       struct acpi_ipmi_device *ipmi_device;
+       int err;
        acpi_status status;
        unsigned long flags;
+
        /*
         * IPMI opregion message.
         * IPMI message is firstly written to the BMC and system software
@@ -391,118 +557,75 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
        if ((function & ACPI_IO_MASK) == ACPI_READ)
                return AE_TYPE;
 
-       if (!ipmi_device->user_interface)
+       tx_msg = ipmi_msg_alloc();
+       if (!tx_msg)
                return AE_NOT_EXIST;
+       ipmi_device = tx_msg->device;
 
-       tx_msg = acpi_alloc_ipmi_msg(ipmi_device);
-       if (!tx_msg)
-               return AE_NO_MEMORY;
+       if (acpi_format_ipmi_request(tx_msg, address, value) != 0) {
+               ipmi_msg_release(tx_msg);
+               return AE_TYPE;
+       }
 
-       acpi_format_ipmi_msg(tx_msg, address, value);
+       acpi_ipmi_msg_get(tx_msg);
+       mutex_lock(&driver_data.ipmi_lock);
+       /* Do not add a tx_msg that can not be flushed. */
+       if (ipmi_device->dead) {
+               mutex_unlock(&driver_data.ipmi_lock);
+               ipmi_msg_release(tx_msg);
+               return AE_NOT_EXIST;
+       }
        spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
        list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list);
        spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
+       mutex_unlock(&driver_data.ipmi_lock);
+
        err = ipmi_request_settime(ipmi_device->user_interface,
-                                       &tx_msg->addr,
-                                       tx_msg->tx_msgid,
-                                       &tx_msg->tx_message,
-                                       NULL, 0, 0, 0);
+                                  &tx_msg->addr,
+                                  tx_msg->tx_msgid,
+                                  &tx_msg->tx_message,
+                                  NULL, 0, 0, IPMI_TIMEOUT);
        if (err) {
                status = AE_ERROR;
-               goto end_label;
+               goto out_msg;
        }
-       rem_time = wait_for_completion_timeout(&tx_msg->tx_complete,
-                                       IPMI_TIMEOUT);
-       acpi_format_ipmi_response(tx_msg, value, rem_time);
+       wait_for_completion(&tx_msg->tx_complete);
+
+       acpi_format_ipmi_response(tx_msg, value);
        status = AE_OK;
 
-end_label:
-       spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
-       list_del(&tx_msg->head);
-       spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
-       kfree(tx_msg);
+out_msg:
+       ipmi_cancel_tx_msg(ipmi_device, tx_msg);
+       acpi_ipmi_msg_put(tx_msg);
        return status;
 }
 
-static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi)
-{
-       if (!test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
-               return;
-
-       acpi_remove_address_space_handler(ipmi->handle,
-                               ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler);
-
-       clear_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
-}
-
-static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi)
+static int __init acpi_ipmi_init(void)
 {
+       int result;
        acpi_status status;
 
-       if (test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
+       if (acpi_disabled)
                return 0;
 
-       status = acpi_install_address_space_handler(ipmi->handle,
+       status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
                                                    ACPI_ADR_SPACE_IPMI,
                                                    &acpi_ipmi_space_handler,
-                                                   NULL, ipmi);
+                                                   NULL, NULL);
        if (ACPI_FAILURE(status)) {
-               struct pnp_dev *pnp_dev = ipmi->pnp_dev;
-               dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space "
-                       "handle\n");
+               pr_warn("Can't register IPMI opregion space handle\n");
                return -EINVAL;
        }
-       set_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
-       return 0;
-}
-
-static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device)
-{
-
-       INIT_LIST_HEAD(&ipmi_device->head);
-
-       spin_lock_init(&ipmi_device->tx_msg_lock);
-       INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
-       ipmi_install_space_handler(ipmi_device);
-
-       list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices);
-}
-
-static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device)
-{
-       /*
-        * If the IPMI user interface is created, it should be
-        * destroyed.
-        */
-       if (ipmi_device->user_interface) {
-               ipmi_destroy_user(ipmi_device->user_interface);
-               ipmi_device->user_interface = NULL;
-       }
-       /* flush the Tx_msg list */
-       if (!list_empty(&ipmi_device->tx_msg_list))
-               ipmi_flush_tx_msg(ipmi_device);
-
-       list_del(&ipmi_device->head);
-       ipmi_remove_space_handler(ipmi_device);
-}
-
-static int __init acpi_ipmi_init(void)
-{
-       int result = 0;
-
-       if (acpi_disabled)
-               return result;
-
-       mutex_init(&driver_data.ipmi_lock);
-
        result = ipmi_smi_watcher_register(&driver_data.bmc_events);
+       if (result)
+               pr_err("Can't register IPMI system interface watcher\n");
 
        return result;
 }
 
 static void __exit acpi_ipmi_exit(void)
 {
-       struct acpi_ipmi_device *ipmi_device, *temp;
+       struct acpi_ipmi_device *ipmi_device;
 
        if (acpi_disabled)
                return;
@@ -516,13 +639,22 @@ static void __exit acpi_ipmi_exit(void)
         * handler and free it.
         */
        mutex_lock(&driver_data.ipmi_lock);
-       list_for_each_entry_safe(ipmi_device, temp,
-                               &driver_data.ipmi_devices, head) {
-               acpi_remove_ipmi_device(ipmi_device);
-               put_device(ipmi_device->smi_data.dev);
-               kfree(ipmi_device);
+       while (!list_empty(&driver_data.ipmi_devices)) {
+               ipmi_device = list_first_entry(&driver_data.ipmi_devices,
+                                              struct acpi_ipmi_device,
+                                              head);
+               __ipmi_dev_kill(ipmi_device);
+               mutex_unlock(&driver_data.ipmi_lock);
+
+               ipmi_flush_tx_msg(ipmi_device);
+               acpi_ipmi_dev_put(ipmi_device);
+
+               mutex_lock(&driver_data.ipmi_lock);
        }
        mutex_unlock(&driver_data.ipmi_lock);
+       acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
+                                         ACPI_ADR_SPACE_IPMI,
+                                         &acpi_ipmi_space_handler);
 }
 
 module_init(acpi_ipmi_init);
index fb78bb9ad8f65888817fc6f7a3ecb2563b975134..d3961014aad7ff9d77bcb296ec2f851f96d64b5b 100644 (file)
@@ -30,6 +30,7 @@ ACPI_MODULE_NAME("acpi_lpss");
 /* Offsets relative to LPSS_PRIVATE_OFFSET */
 #define LPSS_GENERAL                   0x08
 #define LPSS_GENERAL_LTR_MODE_SW       BIT(2)
+#define LPSS_GENERAL_UART_RTS_OVRD     BIT(3)
 #define LPSS_SW_LTR                    0x10
 #define LPSS_AUTO_LTR                  0x14
 #define LPSS_TX_INT                    0x20
@@ -68,11 +69,16 @@ struct lpss_private_data {
 
 static void lpss_uart_setup(struct lpss_private_data *pdata)
 {
-       unsigned int tx_int_offset = pdata->dev_desc->prv_offset + LPSS_TX_INT;
+       unsigned int offset;
        u32 reg;
 
-       reg = readl(pdata->mmio_base + tx_int_offset);
-       writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + tx_int_offset);
+       offset = pdata->dev_desc->prv_offset + LPSS_TX_INT;
+       reg = readl(pdata->mmio_base + offset);
+       writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + offset);
+
+       offset = pdata->dev_desc->prv_offset + LPSS_GENERAL;
+       reg = readl(pdata->mmio_base + offset);
+       writel(reg | LPSS_GENERAL_UART_RTS_OVRD, pdata->mmio_base + offset);
 }
 
 static struct lpss_device_desc lpt_dev_desc = {
index 999adb5499c7270626466a7d74870531c3e3ae28..551dad712ffec451364a08c01487a1987c10d7db 100644 (file)
@@ -152,8 +152,9 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
        unsigned long long current_status;
 
        /* Get device present/absent information from the _STA */
-       if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA",
-                                              NULL, &current_status)))
+       if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle,
+                                              METHOD_NAME__STA, NULL,
+                                              &current_status)))
                return -ENODEV;
        /*
         * Check for device status. Device should be
@@ -281,7 +282,7 @@ static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
                if (!info->enabled)
                        continue;
 
-               if (nid < 0)
+               if (nid == NUMA_NO_NODE)
                        nid = memory_add_physaddr_to_nid(info->start_addr);
 
                acpi_unbind_memory_blocks(info, handle);
index 1bde12708f9e112c708bb71ae8d6162af5e367a9..8a4cfc7e71f0f83cc7a8644e75eab627c8e3c52d 100644 (file)
@@ -29,6 +29,13 @@ ACPI_MODULE_NAME("platform");
 static const struct acpi_device_id acpi_platform_device_ids[] = {
 
        { "PNP0D40" },
+       { "ACPI0003" },
+       { "VPC2004" },
+       { "BCM4752" },
+
+       /* Intel Smart Sound Technology */
+       { "INT33C8" },
+       { "80860F28" },
 
        { }
 };
index f29e06efa47976eba16e3b4e449a8b5a9235909f..3c1d6b0c09a4b7d1eeeb9347a7c743d1c7487988 100644 (file)
@@ -140,15 +140,11 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
        return 0;
 }
 
-static int acpi_processor_errata(struct acpi_processor *pr)
+static int acpi_processor_errata(void)
 {
        int result = 0;
        struct pci_dev *dev = NULL;
 
-
-       if (!pr)
-               return -EINVAL;
-
        /*
         * PIIX4
         */
@@ -181,7 +177,7 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
        cpu_maps_update_begin();
        cpu_hotplug_begin();
 
-       ret = acpi_map_lsapic(pr->handle, &pr->id);
+       ret = acpi_map_lsapic(pr->handle, pr->apic_id, &pr->id);
        if (ret)
                goto out;
 
@@ -219,11 +215,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
        int cpu_index, device_declaration = 0;
        acpi_status status = AE_OK;
        static int cpu0_initialized;
+       unsigned long long value;
 
-       if (num_online_cpus() > 1)
-               errata.smp = TRUE;
-
-       acpi_processor_errata(pr);
+       acpi_processor_errata();
 
        /*
         * Check to see if we have bus mastering arbitration control.  This
@@ -247,18 +241,12 @@ static int acpi_processor_get_info(struct acpi_device *device)
                        return -ENODEV;
                }
 
-               /*
-                * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
-                *      >>> 'acpi_get_processor_id(acpi_id, &id)' in
-                *      arch/xxx/acpi.c
-                */
                pr->acpi_id = object.processor.proc_id;
        } else {
                /*
                 * Declared with "Device" statement; match _UID.
                 * Note that we don't handle string _UIDs yet.
                 */
-               unsigned long long value;
                status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
                                                NULL, &value);
                if (ACPI_FAILURE(status)) {
@@ -270,7 +258,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
                device_declaration = 1;
                pr->acpi_id = value;
        }
-       cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id);
+       pr->apic_id = acpi_get_apicid(pr->handle, device_declaration,
+                                       pr->acpi_id);
+       cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id);
 
        /* Handle UP system running SMP kernel, with no LAPIC in MADT */
        if (!cpu0_initialized && (cpu_index == -1) &&
@@ -332,9 +322,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
         * ensure we get the right value in the "physical id" field
         * of /proc/cpuinfo
         */
-       status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+       status = acpi_evaluate_integer(pr->handle, "_SUN", NULL, &value);
        if (ACPI_SUCCESS(status))
-               arch_fix_phys_package_id(pr->id, object.integer.value);
+               arch_fix_phys_package_id(pr->id, value);
 
        return 0;
 }
index 9feba08c29fe08b772e976fdefc7531300eb4d2d..a9fd0b872062a6d22d279db3f126e2dd734868e6 100644 (file)
@@ -114,10 +114,12 @@ ACPI_HW_DEPENDENT_RETURN_VOID(void
                              acpi_db_generate_gpe(char *gpe_arg,
                                                   char *block_arg))
 
+ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void))
+
 /*
  * dbconvert - miscellaneous conversion routines
  */
- acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value);
+acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value);
 
 acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object);
 
@@ -154,6 +156,8 @@ void acpi_db_set_scope(char *name);
 
 void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
 
+void acpi_db_dump_namespace_paths(void);
+
 void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
 
 acpi_status acpi_db_find_name_in_namespace(char *name_arg);
@@ -240,6 +244,8 @@ void acpi_db_display_history(void);
 
 char *acpi_db_get_from_history(char *command_num_arg);
 
+char *acpi_db_get_history_by_index(u32 commandd_num);
+
 /*
  * dbinput - user front-end to the AML debugger
  */
index ab0e9771038127c83365fc3b1d72de841612fb99..41abe552c7a3c61709a42cdd2bedc794a309c538 100644 (file)
@@ -71,7 +71,8 @@ acpi_status acpi_ev_init_global_lock_handler(void);
 
 ACPI_HW_DEPENDENT_RETURN_OK(acpi_status
                            acpi_ev_acquire_global_lock(u16 timeout))
- ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void))
+
+ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void))
  acpi_status acpi_ev_remove_global_lock_handler(void);
 
 /*
@@ -242,11 +243,11 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
  */
 u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context);
 
-u32 acpi_ev_install_sci_handler(void);
+u32 acpi_ev_sci_dispatch(void);
 
-acpi_status acpi_ev_remove_sci_handler(void);
+u32 acpi_ev_install_sci_handler(void);
 
-u32 acpi_ev_initialize_SCI(u32 program_SCI);
+acpi_status acpi_ev_remove_all_sci_handlers(void);
 
 ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void))
 #endif                         /* __ACEVENTS_H__  */
index 90e846f985fa30caa109c8de336ac8e677a29bee..e9f1fc7f99c708618bb95fda1c64175f34808fdc 100644 (file)
@@ -269,6 +269,7 @@ ACPI_EXTERN acpi_table_handler acpi_gbl_table_handler;
 ACPI_EXTERN void *acpi_gbl_table_handler_context;
 ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
 ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler;
+ACPI_EXTERN struct acpi_sci_handler_info *acpi_gbl_sci_handler_list;
 
 /* Owner ID support */
 
@@ -405,7 +406,9 @@ extern u32 acpi_gbl_nesting_level;
 
 /* Event counters */
 
+ACPI_EXTERN u32 acpi_method_count;
 ACPI_EXTERN u32 acpi_gpe_count;
+ACPI_EXTERN u32 acpi_sci_count;
 ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS];
 
 /* Support for dynamic control method tracing mechanism */
@@ -445,13 +448,6 @@ ACPI_EXTERN u8 acpi_gbl_db_opt_tables;
 ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
 ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
 ACPI_EXTERN u8 acpi_gbl_db_opt_no_region_support;
-
-ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE];
-ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE];
-ACPI_EXTERN char acpi_gbl_db_scope_buf[80];
-ACPI_EXTERN char acpi_gbl_db_debug_filename[80];
 ACPI_EXTERN u8 acpi_gbl_db_output_to_file;
 ACPI_EXTERN char *acpi_gbl_db_buffer;
 ACPI_EXTERN char *acpi_gbl_db_filename;
@@ -459,6 +455,16 @@ ACPI_EXTERN u32 acpi_gbl_db_debug_level;
 ACPI_EXTERN u32 acpi_gbl_db_console_debug_level;
 ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node;
 
+ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
+ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS];
+
+/* These buffers should all be the same size */
+
+ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE];
+
 /*
  * Statistic globals
  */
index 0ed00669cd217a0754087ed61bc89465e31804f3..53ed1a8ba4f0f26ca367180204a12666c3231546 100644 (file)
@@ -398,6 +398,14 @@ struct acpi_simple_repair_info {
  *
  ****************************************************************************/
 
+/* Dispatch info for each host-installed SCI handler */
+
+struct acpi_sci_handler_info {
+       struct acpi_sci_handler_info *next;
+       acpi_sci_handler address;       /* Address of handler */
+       void *context;          /* Context to be passed to handler */
+};
+
 /* Dispatch info for each GPE -- either a method or handler, cannot be both */
 
 struct acpi_gpe_handler_info {
@@ -1064,7 +1072,7 @@ struct acpi_db_method_info {
        char *name;
        u32 flags;
        u32 num_loops;
-       char pathname[128];
+       char pathname[ACPI_DB_LINE_BUFFER_SIZE];
        char **args;
        acpi_object_type *types;
 
@@ -1086,6 +1094,7 @@ struct acpi_integrity_info {
        u32 objects;
 };
 
+#define ACPI_DB_DISABLE_OUTPUT          0x00
 #define ACPI_DB_REDIRECTABLE_OUTPUT     0x01
 #define ACPI_DB_CONSOLE_OUTPUT          0x02
 #define ACPI_DB_DUPLICATE_OUTPUT        0x03
index 530a2f8c1252da88d0598071b3f32da2bb739f1d..2a86c65d873bb6625d3a028b24d299fb2b6101ce 100644 (file)
 #define ACPI_DEBUGGER_EXEC(a)
 #endif
 
-/*
- * Memory allocation tracking (DEBUG ONLY)
- */
-#define ACPI_MEM_PARAMETERS         _COMPONENT, _acpi_module_name, __LINE__
-
-#ifndef ACPI_DBG_TRACK_ALLOCATIONS
-
-/* Memory allocation */
-
-#ifndef ACPI_ALLOCATE
-#define ACPI_ALLOCATE(a)            acpi_ut_allocate((acpi_size) (a), ACPI_MEM_PARAMETERS)
-#endif
-#ifndef ACPI_ALLOCATE_ZEROED
-#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed((acpi_size) (a), ACPI_MEM_PARAMETERS)
-#endif
-#ifndef ACPI_FREE
-#define ACPI_FREE(a)                acpi_os_free(a)
-#endif
-#define ACPI_MEM_TRACKING(a)
-
-#else
-
-/* Memory allocation */
-
-#define ACPI_ALLOCATE(a)            acpi_ut_allocate_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS)
-#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS)
-#define ACPI_FREE(a)                acpi_ut_free_and_track(a, ACPI_MEM_PARAMETERS)
-#define ACPI_MEM_TRACKING(a)        a
-
-#endif                         /* ACPI_DBG_TRACK_ALLOCATIONS */
-
 /*
  * Macros used for ACPICA utilities only
  */
index 40b04bd5579e36abec92165270c44f576e8fddc4..e6138ac4a16054038275fc81f2f616cd70c26d5d 100644 (file)
@@ -213,6 +213,12 @@ acpi_ns_dump_objects(acpi_object_type type,
                     u8 display_type,
                     u32 max_depth,
                     acpi_owner_id owner_id, acpi_handle start_handle);
+
+void
+acpi_ns_dump_object_paths(acpi_object_type type,
+                         u8 display_type,
+                         u32 max_depth,
+                         acpi_owner_id owner_id, acpi_handle start_handle);
 #endif                         /* ACPI_FUTURE_USAGE */
 
 /*
index d5a62a6182bb96826e5ee7144d8e7be228cd91ea..be8180c17d7e772ec520dae60dc43b514c5295c1 100644 (file)
@@ -628,6 +628,17 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position);
 
 void acpi_ut_repair_name(char *name);
 
+#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION)
+u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source);
+
+u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source);
+
+u8
+acpi_ut_safe_strncat(char *dest,
+                    acpi_size dest_size,
+                    char *source, acpi_size max_transfer_length);
+#endif
+
 /*
  * utmutex - mutex support
  */
@@ -652,12 +663,6 @@ acpi_status
 acpi_ut_initialize_buffer(struct acpi_buffer *buffer,
                          acpi_size required_length);
 
-void *acpi_ut_allocate(acpi_size size,
-                      u32 component, const char *module, u32 line);
-
-void *acpi_ut_allocate_zeroed(acpi_size size,
-                             u32 component, const char *module, u32 line);
-
 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 void *acpi_ut_allocate_and_track(acpi_size size,
                                 u32 component, const char *module, u32 line);
index fb09b08d7080100b250fbf6ffa164bda1ad43b55..afdc6df17abf12fa37311484b48e00ba0ff67bca 100644 (file)
@@ -158,7 +158,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node,
        walk_state->deferred_node = node;
        status = acpi_ps_parse_aml(walk_state);
 
-      cleanup:
+cleanup:
        acpi_ps_delete_parse_tree(op);
        return_ACPI_STATUS(status);
 }
index d4bfe7b7f90a54a5b5cdafb8119f0d60698be171..2d4c07322576c9697ccd8389e822e3e27564fd67 100644 (file)
@@ -259,7 +259,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
                goto cleanup;
        }
 
-      cleanup:
+cleanup:
 
        /* Remove local reference to the object */
 
index a9ffd44c18fe322b0a73b97bbe5c11207464c1ba..81a78ba843112d335613fc55a2d0d2ae39e6bc3f 100644 (file)
@@ -292,9 +292,10 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
         * reentered one more time (even if it is the same thread)
         */
        obj_desc->method.thread_count++;
+       acpi_method_count++;
        return_ACPI_STATUS(status);
 
-      cleanup:
+cleanup:
        /* On error, must release the method mutex (if present) */
 
        if (obj_desc->method.mutex) {
@@ -424,7 +425,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
 
        return_ACPI_STATUS(status);
 
-      cleanup:
+cleanup:
 
        /* On error, we must terminate the method properly */
 
index 63f0d220ca3d99a2da601b1b4571972bf2f71397..b1746a68dad11b8ac3a7b37bdb213f1e7265ee17 100644 (file)
@@ -240,7 +240,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
                return_ACPI_STATUS(status);
        }
 
-      exit:
+exit:
        *obj_desc_ptr = obj_desc;
        return_ACPI_STATUS(status);
 }
index 1fc1ff114f269867bf1a281e584511c00595d960..5205edcf2c019d1936c81af2d77a8f4e732d9c0d 100644 (file)
@@ -257,7 +257,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
            (buffer_desc->common.reference_count +
             obj_desc->common.reference_count);
 
-      cleanup:
+cleanup:
 
        /* Always delete the operands */
 
index c666fc01498795afdb76f6afad8383f75389d1bb..ade44e49deb4b554f78ff49884d010633c507047 100644 (file)
@@ -299,7 +299,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
                goto result_used;
        }
 
-      result_used:
+result_used:
        ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
                          "Result of [%s] used by Parent [%s] Op=%p\n",
                          acpi_ps_get_opcode_name(op->common.aml_opcode),
@@ -308,7 +308,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 
        return_UINT8(TRUE);
 
-      result_not_used:
+result_not_used:
        ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
                          "Result of [%s] not used by Parent [%s] Op=%p\n",
                          acpi_ps_get_opcode_name(op->common.aml_opcode),
@@ -752,7 +752,7 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
 
        return_ACPI_STATUS(status);
 
-      cleanup:
+cleanup:
        /*
         * We must undo everything done above; meaning that we must
         * pop everything off of the operand stack and delete those
@@ -851,7 +851,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
                goto exit;
        }
 
-      push_result:
+push_result:
 
        walk_state->result_obj = new_obj_desc;
 
@@ -863,7 +863,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
                op->common.flags |= ACPI_PARSEOP_IN_STACK;
        }
 
-      exit:
+exit:
 
        return_ACPI_STATUS(status);
 }
index 151d924817e1b2041bfd60cad46aaaf1a5dc9e20..1bbb22fd6fa02f005893fc691eedfb8d0981246e 100644 (file)
@@ -170,7 +170,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
 
        (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE);
 
-      cleanup:
+cleanup:
 
        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
                          walk_state->control_state->common.value,
@@ -335,7 +335,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
 
        return_ACPI_STATUS(status);
 
-      error_exit:
+error_exit:
        status = acpi_ds_method_error(status, walk_state);
        return_ACPI_STATUS(status);
 }
@@ -722,7 +722,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
                walk_state->result_obj = NULL;
        }
 
-      cleanup:
+cleanup:
 
        if (walk_state->result_obj) {
 
index b1f8f4725c230b0d6b0bf9155f13028f42d62667..7f569d57302758dcec3643d489f715f794625f78 100644 (file)
@@ -728,7 +728,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
                break;
        }
 
-      cleanup:
+cleanup:
 
        /* Remove the Node pushed at the very beginning */
 
index fdb0a76e40a3020806cfce8c4e637273e2fc4f2c..4c67193a9fa731f0f616023ffb642547d38795df 100644 (file)
@@ -173,7 +173,7 @@ static u32 acpi_ev_global_lock_handler(void *context)
 
        acpi_gbl_global_lock_pending = FALSE;
 
-      cleanup_and_exit:
+cleanup_and_exit:
 
        acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags);
        return (ACPI_INTERRUPT_HANDLED);
index c8a1f7d5931f518b004cc8311d31e5ad8e5cdaeb..a9cb4a1a4bb8ce6b2c203c7c16360556decd3ada 100644 (file)
@@ -458,7 +458,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
                gpe_block = gpe_block->next;
        }
 
-      unlock_and_exit:
+unlock_and_exit:
 
        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return (int_status);
@@ -522,6 +522,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
 
        status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
        if (ACPI_FAILURE(status)) {
+               ACPI_FREE(local_gpe_event_info);
                return_VOID;
        }
 
index c1aa1eda26c32ec73dc68ac6d5433d783383348b..a9e76bc4ad97f9b6e5e8a8cf67dce7d2beeb8068 100644 (file)
@@ -111,7 +111,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
        gpe_block->xrupt_block = gpe_xrupt_block;
        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 
-      unlock_and_exit:
+unlock_and_exit:
        status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
        return_ACPI_STATUS(status);
 }
@@ -178,7 +178,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
        ACPI_FREE(gpe_block->event_info);
        ACPI_FREE(gpe_block);
 
-      unlock_and_exit:
+unlock_and_exit:
        status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
        return_ACPI_STATUS(status);
 }
@@ -302,7 +302,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
 
        return_ACPI_STATUS(AE_OK);
 
-      error_exit:
+error_exit:
        if (gpe_register_info) {
                ACPI_FREE(gpe_register_info);
        }
index 7842700346a48b0cfa542d46def472ba92643212..a3e2f38aadf64783cd3dfd03f1f6bc0140a87b85 100644 (file)
@@ -203,7 +203,7 @@ acpi_status acpi_ev_gpe_initialize(void)
                goto cleanup;
        }
 
-      cleanup:
+cleanup:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(AE_OK);
 }
index b24dbb80fab8f681dc3089cd8a29c700f5cb57c7..d3f5e1e2a2b14ba699fb78309c7c23e5f0949fab 100644 (file)
@@ -101,7 +101,7 @@ acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context)
                gpe_xrupt_info = gpe_xrupt_info->next;
        }
 
-      unlock_and_exit:
+unlock_and_exit:
        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS(status);
 }
@@ -196,7 +196,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  *
  * FUNCTION:    acpi_ev_get_gpe_xrupt_block
  *
- * PARAMETERS:  interrupt_number     - Interrupt for a GPE block
+ * PARAMETERS:  interrupt_number            - Interrupt for a GPE block
  *
  * RETURN:      A GPE interrupt block
  *
index 068af96134b89787a739cce281f481db82e46e19..e3157313eb2786e2098b7c6fa5f4a3c58c40d293 100644 (file)
@@ -129,7 +129,7 @@ acpi_status acpi_ev_install_region_handlers(void)
                }
        }
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(status);
 }
@@ -531,6 +531,6 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
                                        acpi_ev_install_handler, NULL,
                                        handler_obj, NULL);
 
-      unlock_and_exit:
+unlock_and_exit:
        return_ACPI_STATUS(status);
 }
index 1b111ef74903771f8f9a8f690aef85b752f65c61..a5687540e9a66e5ba20bfeb9772ad5351b20bc61 100644 (file)
@@ -264,13 +264,6 @@ void acpi_ev_terminate(void)
 
                status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
 
-               /* Remove SCI handler */
-
-               status = acpi_ev_remove_sci_handler();
-               if (ACPI_FAILURE(status)) {
-                       ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
-               }
-
                status = acpi_ev_remove_global_lock_handler();
                if (ACPI_FAILURE(status)) {
                        ACPI_ERROR((AE_INFO,
@@ -280,6 +273,13 @@ void acpi_ev_terminate(void)
                acpi_gbl_events_initialized = FALSE;
        }
 
+       /* Remove SCI handlers */
+
+       status = acpi_ev_remove_all_sci_handlers();
+       if (ACPI_FAILURE(status)) {
+               ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
+       }
+
        /* Deallocate all handler objects installed within GPE info structs */
 
        status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL);
index cea14d6fc76c976db580144f93d28d890ff3938f..144cbb9b73bc7238460be80e22a62a95aa2042e3 100644 (file)
@@ -217,16 +217,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
                if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
                        region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
 
-                       if (region_obj2->extra.region_context) {
-
-                               /* The handler for this region was already installed */
-
-                               ACPI_FREE(region_context);
-                       } else {
-                               /*
-                                * Save the returned context for use in all accesses to
-                                * this particular region
-                                */
+                       /*
+                        * Save the returned context for use in all accesses to
+                        * the handler for this particular region
+                        */
+                       if (!(region_obj2->extra.region_context)) {
                                region_obj2->extra.region_context =
                                    region_context;
                        }
@@ -402,6 +397,14 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
                                                 handler_obj->address_space.
                                                 context, region_context);
 
+                               /*
+                                * region_context should have been released by the deactivate
+                                * operation. We don't need access to it anymore here.
+                                */
+                               if (region_context) {
+                                       *region_context = NULL;
+                               }
+
                                /* Init routine may fail, Just ignore errors */
 
                                if (ACPI_FAILURE(status)) {
@@ -570,10 +573,10 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
        status = acpi_ns_evaluate(info);
        acpi_ut_remove_reference(args[1]);
 
-      cleanup2:
+cleanup2:
        acpi_ut_remove_reference(args[0]);
 
-      cleanup1:
+cleanup1:
        ACPI_FREE(info);
        return_ACPI_STATUS(status);
 }
@@ -758,7 +761,7 @@ acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node)
 
        status = acpi_evaluate_object(reg_method, NULL, &args, NULL);
 
-      exit:
+exit:
        /* We ignore all errors from above, don't care */
 
        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
index b905acf7aacdc1d90f9189b9660df28eb6777f08..9e9e3454d8932c9c44f853bbe3d05edffeb38130 100644 (file)
@@ -52,6 +52,50 @@ ACPI_MODULE_NAME("evsci")
 /* Local prototypes */
 static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_sci_dispatch
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status code indicates whether interrupt was handled.
+ *
+ * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
+ *
+ ******************************************************************************/
+
+u32 acpi_ev_sci_dispatch(void)
+{
+       struct acpi_sci_handler_info *sci_handler;
+       acpi_cpu_flags flags;
+       u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
+
+       ACPI_FUNCTION_NAME(ev_sci_dispatch);
+
+       /* Are there any host-installed SCI handlers? */
+
+       if (!acpi_gbl_sci_handler_list) {
+               return (int_status);
+       }
+
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+       /* Invoke all host-installed SCI handlers */
+
+       sci_handler = acpi_gbl_sci_handler_list;
+       while (sci_handler) {
+
+               /* Invoke the installed handler (at interrupt level) */
+
+               int_status |= sci_handler->address(sci_handler->context);
+
+               sci_handler = sci_handler->next;
+       }
+
+       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+       return (int_status);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_sci_xrupt_handler
@@ -89,6 +133,11 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
         */
        interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
 
+       /* Invoke all host-installed SCI handlers */
+
+       interrupt_handled |= acpi_ev_sci_dispatch();
+
+       acpi_sci_count++;
        return_UINT32(interrupt_handled);
 }
 
@@ -112,14 +161,13 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
        ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
 
        /*
-        * We are guaranteed by the ACPI CA initialization/shutdown code that
+        * We are guaranteed by the ACPICA initialization/shutdown code that
         * if this interrupt handler is installed, ACPI is enabled.
         */
 
        /* GPEs: Check for and dispatch any GPEs that have occurred */
 
        interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
-
        return_UINT32(interrupt_handled);
 }
 
@@ -150,15 +198,15 @@ u32 acpi_ev_install_sci_handler(void)
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_ev_remove_sci_handler
+ * FUNCTION:    acpi_ev_remove_all_sci_handlers
  *
  * PARAMETERS:  none
  *
- * RETURN:      E_OK if handler uninstalled OK, E_ERROR if handler was not
+ * RETURN:      AE_OK if handler uninstalled, AE_ERROR if handler was not
  *              installed to begin with
  *
  * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
- *              taken.
+ *              taken. Remove all host-installed SCI handlers.
  *
  * Note:  It doesn't seem important to disable all events or set the event
  *        enable registers to their original values. The OS should disable
@@ -167,11 +215,13 @@ u32 acpi_ev_install_sci_handler(void)
  *
  ******************************************************************************/
 
-acpi_status acpi_ev_remove_sci_handler(void)
+acpi_status acpi_ev_remove_all_sci_handlers(void)
 {
+       struct acpi_sci_handler_info *sci_handler;
+       acpi_cpu_flags flags;
        acpi_status status;
 
-       ACPI_FUNCTION_TRACE(ev_remove_sci_handler);
+       ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers);
 
        /* Just let the OS remove the handler and disable the level */
 
@@ -179,6 +229,21 @@ acpi_status acpi_ev_remove_sci_handler(void)
            acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
                                             acpi_ev_sci_xrupt_handler);
 
+       if (!acpi_gbl_sci_handler_list) {
+               return (status);
+       }
+
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+       /* Free all host-installed SCI handlers */
+
+       while (acpi_gbl_sci_handler_list) {
+               sci_handler = acpi_gbl_sci_handler_list;
+               acpi_gbl_sci_handler_list = sci_handler->next;
+               ACPI_FREE(sci_handler);
+       }
+
+       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS(status);
 }
 
index ca5fba99c33bc82a302f8eb246ca41224a2cbada..23a7fadca4122992c7f652c32674843de13500f9 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
@@ -374,7 +375,7 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
 
        acpi_gbl_exception_handler = handler;
 
-      cleanup:
+cleanup:
        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
        return_ACPI_STATUS(status);
 }
@@ -383,6 +384,144 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
 #endif                         /*  ACPI_FUTURE_USAGE  */
 
 #if (!ACPI_REDUCED_HARDWARE)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_install_sci_handler
+ *
+ * PARAMETERS:  address             - Address of the handler
+ *              context             - Value passed to the handler on each SCI
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install a handler for a System Control Interrupt.
+ *
+ ******************************************************************************/
+acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)
+{
+       struct acpi_sci_handler_info *new_sci_handler;
+       struct acpi_sci_handler_info *sci_handler;
+       acpi_cpu_flags flags;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(acpi_install_sci_handler);
+
+       if (!address) {
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
+       }
+
+       /* Allocate and init a handler object */
+
+       new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info));
+       if (!new_sci_handler) {
+               return_ACPI_STATUS(AE_NO_MEMORY);
+       }
+
+       new_sci_handler->address = address;
+       new_sci_handler->context = context;
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+       if (ACPI_FAILURE(status)) {
+               goto exit;
+       }
+
+       /* Lock list during installation */
+
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+       sci_handler = acpi_gbl_sci_handler_list;
+
+       /* Ensure handler does not already exist */
+
+       while (sci_handler) {
+               if (address == sci_handler->address) {
+                       status = AE_ALREADY_EXISTS;
+                       goto unlock_and_exit;
+               }
+
+               sci_handler = sci_handler->next;
+       }
+
+       /* Install the new handler into the global list (at head) */
+
+       new_sci_handler->next = acpi_gbl_sci_handler_list;
+       acpi_gbl_sci_handler_list = new_sci_handler;
+
+unlock_and_exit:
+
+       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+       (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+exit:
+       if (ACPI_FAILURE(status)) {
+               ACPI_FREE(new_sci_handler);
+       }
+       return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_remove_sci_handler
+ *
+ * PARAMETERS:  address             - Address of the handler
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Remove a handler for a System Control Interrupt.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
+{
+       struct acpi_sci_handler_info *prev_sci_handler;
+       struct acpi_sci_handler_info *next_sci_handler;
+       acpi_cpu_flags flags;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(acpi_remove_sci_handler);
+
+       if (!address) {
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
+       }
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /* Remove the SCI handler with lock */
+
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+       prev_sci_handler = NULL;
+       next_sci_handler = acpi_gbl_sci_handler_list;
+       while (next_sci_handler) {
+               if (next_sci_handler->address == address) {
+
+                       /* Unlink and free the SCI handler info block */
+
+                       if (prev_sci_handler) {
+                               prev_sci_handler->next = next_sci_handler->next;
+                       } else {
+                               acpi_gbl_sci_handler_list =
+                                   next_sci_handler->next;
+                       }
+
+                       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+                       ACPI_FREE(next_sci_handler);
+                       goto unlock_and_exit;
+               }
+
+               prev_sci_handler = next_sci_handler;
+               next_sci_handler = next_sci_handler->next;
+       }
+
+       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+       status = AE_NOT_EXIST;
+
+unlock_and_exit:
+       (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+       return_ACPI_STATUS(status);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_install_global_event_handler
@@ -398,6 +537,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
  *              Can be used to update event counters, etc.
  *
  ******************************************************************************/
+
 acpi_status
 acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
 {
@@ -426,7 +566,7 @@ acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
        acpi_gbl_global_event_handler = handler;
        acpi_gbl_global_event_handler_context = context;
 
-      cleanup:
+cleanup:
        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
        return_ACPI_STATUS(status);
 }
@@ -498,7 +638,7 @@ acpi_install_fixed_event_handler(u32 event,
                                  handler));
        }
 
-      cleanup:
+cleanup:
        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
        return_ACPI_STATUS(status);
 }
index 7039606a0ba8c3a4753cd3aa4703f38b77c7358e..39d06af5e347e234ad285f77848e22b8bef101d6 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "actables.h"
index 7662f1a42ff6bb19513e0f9272f90c921f64ec90..5713da77c665b01a5e9dcdbd91abc70a11f4228a 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acevents.h"
@@ -471,7 +472,7 @@ acpi_get_gpe_status(acpi_handle gpe_device,
        if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
                *event_status |= ACPI_EVENT_FLAG_HANDLE;
 
-      unlock_and_exit:
+unlock_and_exit:
        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS(status);
 }
@@ -624,7 +625,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
 
        obj_desc->device.gpe_block = gpe_block;
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(status);
 }
@@ -679,7 +680,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
                obj_desc->device.gpe_block = NULL;
        }
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(status);
 }
index 80cecf8385917c7ed32ca75eb9afc807dbb6b0b2..02ed75ac56cd5454adc527b09e3ebe63a329ae0e 100644 (file)
@@ -42,7 +42,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
@@ -147,7 +148,7 @@ acpi_install_address_space_handler(acpi_handle device,
 
        status = acpi_ev_execute_reg_methods(node, space_id);
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(status);
 }
@@ -286,7 +287,7 @@ acpi_remove_address_space_handler(acpi_handle device,
 
        status = AE_NOT_EXIST;
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(status);
 }
index 269e81d86ef41c59e7eaa3d61bb7c63ba23457bd..3c2e6dcdad3e6abcbb60e1afacf3e0717c55a0d8 100644 (file)
@@ -193,7 +193,7 @@ acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state)
            acpi_ns_attach_object((struct acpi_namespace_node *)walk_state->
                                  operands[0], obj_desc, ACPI_TYPE_EVENT);
 
-      cleanup:
+cleanup:
        /*
         * Remove local reference to the object (on error, will cause deletion
         * of both object and semaphore if present.)
@@ -248,7 +248,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
            acpi_ns_attach_object(obj_desc->mutex.node, obj_desc,
                                  ACPI_TYPE_MUTEX);
 
-      cleanup:
+cleanup:
        /*
         * Remove local reference to the object (on error, will cause deletion
         * of both object and semaphore if present.)
@@ -347,7 +347,7 @@ acpi_ex_create_region(u8 * aml_start,
 
        status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
 
-      cleanup:
+cleanup:
 
        /* Remove local reference to the object */
 
@@ -520,7 +520,7 @@ acpi_ex_create_method(u8 * aml_start,
 
        acpi_ut_remove_reference(obj_desc);
 
-      exit:
+exit:
        /* Remove a reference to the operand */
 
        acpi_ut_remove_reference(operand[1]);
index c2a65aaf29af006f3be629aab6b9f6b698650b40..cfd875243421473d23ac1f9e0350488041cfc617 100644 (file)
@@ -197,7 +197,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
        status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
        acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
 
-      exit:
+exit:
        if (ACPI_FAILURE(status)) {
                acpi_ut_remove_reference(buffer_desc);
        } else {
index 7e0afe72487ea73ee5504d73891b294b83aceb91..49fb742d61b98b1f18484f6f1783cba553447555 100644 (file)
@@ -123,12 +123,6 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
                }
        }
 
-       /* Exit if Address/Length have been disallowed by the host OS */
-
-       if (rgn_desc->common.flags & AOPOBJ_INVALID) {
-               return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
-       }
-
        /*
         * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
         * address space and the request cannot be directly validated
@@ -1002,7 +996,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
                                                mask, merged_datum,
                                                field_offset);
 
-      exit:
+exit:
        /* Free temporary buffer if we used one */
 
        if (new_buffer) {
index 00bf298775741763054eabd2d3030dcb6494e150..65d93607f3681d845a87a4f721cdddb8728df660 100644 (file)
@@ -388,7 +388,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
 
        *actual_return_desc = return_desc;
 
-      cleanup:
+cleanup:
        if (local_operand1 != operand1) {
                acpi_ut_remove_reference(local_operand1);
        }
@@ -718,7 +718,7 @@ acpi_ex_do_logical_op(u16 opcode,
                }
        }
 
-      cleanup:
+cleanup:
 
        /* New object was created if implicit conversion performed - delete */
 
index 2cdd41d8ade6f6c3ebef1d7a629eba1792aaeedc..d74cea416ca05beaa9af14e9d0af3a1fd0aa3c89 100644 (file)
@@ -115,7 +115,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
                break;
        }
 
-      cleanup:
+cleanup:
 
        /* Delete return object on error */
 
@@ -234,7 +234,7 @@ acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state)
                goto cleanup;
        }
 
-      cleanup:
+cleanup:
 
        return_ACPI_STATUS(status);
 }
@@ -551,7 +551,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
                status = acpi_ex_store(return_desc, operand[1], walk_state);
        }
 
-      cleanup:
+cleanup:
 
        /* Delete return object on error */
 
@@ -1054,7 +1054,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
                goto cleanup;
        }
 
-      cleanup:
+cleanup:
 
        /* Delete return object on error */
 
index d5088f7030c753fb9e36b78b25d894e2c48cf74c..d6fa0fce1fc91e74b197490b0f1f180d386b9545 100644 (file)
@@ -215,7 +215,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
                goto cleanup;
        }
 
-      cleanup:
+cleanup:
        /*
         * Since the remainder is not returned indirectly, remove a reference to
         * it. Only the quotient is returned indirectly.
@@ -445,7 +445,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
                break;
        }
 
-      store_result_to_target:
+store_result_to_target:
 
        if (ACPI_SUCCESS(status)) {
                /*
@@ -462,7 +462,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
                }
        }
 
-      cleanup:
+cleanup:
 
        /* Delete return object on error */
 
@@ -553,7 +553,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
                goto cleanup;
        }
 
-      store_logical_result:
+store_logical_result:
        /*
         * Set return value to according to logical_result. logical TRUE (all ones)
         * Default is FALSE (zero)
@@ -562,7 +562,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
                return_desc->integer.value = ACPI_UINT64_MAX;
        }
 
-      cleanup:
+cleanup:
 
        /* Delete return object on error */
 
index 37656f12f204bcd3b12ae6c1d8384eb392990e1a..bc042adf880496ffce63da79852b574e1a97c9f2 100644 (file)
@@ -124,7 +124,7 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
                goto cleanup;
        }
 
-      cleanup:
+cleanup:
 
        return_ACPI_STATUS(status);
 }
@@ -252,7 +252,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
 
        status = acpi_ex_store(return_desc, operand[3], walk_state);
 
-      cleanup:
+cleanup:
 
        /* Delete return object on error */
 
index 879b6cd8319cdc09023e3852da1efe1b51f84282..4459e32c683d3c9e78bdf6bf807048b05e52a4a4 100644 (file)
@@ -314,7 +314,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
                goto cleanup;
        }
 
-      cleanup:
+cleanup:
 
        /* Delete return object on error */
 
index 303429bb4d5d6631878878a872b3f0c46f82f390..9d28867e60dc8b2c907e8cc76c92d10d95caa68e 100644 (file)
@@ -400,6 +400,7 @@ acpi_ex_pci_config_space_handler(u32 function,
        switch (function) {
        case ACPI_READ:
 
+               *value = 0;
                status = acpi_os_read_pci_configuration(pci_id, pci_register,
                                                        value, bit_width);
                break;
index ac04278ad28f00294d6fc7a3034795bcbb1c0bfb..1606524312e3a4f4219d47f7513390abc9986f75 100644 (file)
@@ -521,7 +521,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
         */
        type = obj_desc->common.type;
 
-      exit:
+exit:
        /* Convert internal types to external types */
 
        switch (type) {
index 00e5af7129c1234338e4c5f0aeddcde5941ce94d..be3f66973ee809637c30ada74e2ca706e0185795 100644 (file)
@@ -683,7 +683,7 @@ acpi_ex_resolve_operands(u16 opcode,
                        return_ACPI_STATUS(status);
                }
 
-             next_operand:
+next_operand:
                /*
                 * If more operands needed, decrement stack_ptr to point
                 * to next operand on stack
index 8d2e866be15f84a301183cf5690205785ec4f2ea..12e6cff54f7885558d898c35c0a7375282139c5c 100644 (file)
@@ -560,7 +560,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value)
                break;
        }
 
-      exit:
+exit:
        return_ACPI_STATUS(status);
 }
 
index 2d7d22ebc782151189a9d76a828cf9948a267603..3c498dc1636ecd27cb439de4e0f72a44c9bb5ec6 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 
index 5ee7a814cd9207db34d42b8945867e415ab733bb..b4b47db2dee271a82ec4f3f6537f194c7c982ef8 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
@@ -83,11 +84,17 @@ acpi_status acpi_reset(void)
                 * For I/O space, write directly to the OSL. This bypasses the port
                 * validation mechanism, which may block a valid write to the reset
                 * register.
-                * Spec section 4.7.3.6 requires register width to be 8.
+                *
+                * NOTE:
+                * The ACPI spec requires the reset register width to be 8, so we
+                * hardcode it here and ignore the FADT value. This maintains
+                * compatibility with other ACPI implementations that have allowed
+                * BIOS code with bad register width values to go unnoticed.
                 */
                status =
                    acpi_os_write_port((acpi_io_address) reset_reg->address,
-                                      acpi_gbl_FADT.reset_value, 8);
+                                      acpi_gbl_FADT.reset_value,
+                                      ACPI_RESET_REGISTER_WIDTH);
        } else {
                /* Write the reset value to the reset register */
 
@@ -119,7 +126,8 @@ ACPI_EXPORT_SYMBOL(acpi_reset)
  ******************************************************************************/
 acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
 {
-       u32 value;
+       u32 value_lo;
+       u32 value_hi;
        u32 width;
        u64 address;
        acpi_status status;
@@ -137,13 +145,8 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
                return (status);
        }
 
-       /* Initialize entire 64-bit return value to zero */
-
-       *return_value = 0;
-       value = 0;
-
        /*
-        * Two address spaces supported: Memory or IO. PCI_Config is
+        * Two address spaces supported: Memory or I/O. PCI_Config is
         * not supported here because the GAS structure is insufficient
         */
        if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
@@ -155,29 +158,35 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
                }
        } else {                /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
 
+               value_lo = 0;
+               value_hi = 0;
+
                width = reg->bit_width;
                if (width == 64) {
                        width = 32;     /* Break into two 32-bit transfers */
                }
 
                status = acpi_hw_read_port((acpi_io_address)
-                                          address, &value, width);
+                                          address, &value_lo, width);
                if (ACPI_FAILURE(status)) {
                        return (status);
                }
-               *return_value = value;
 
                if (reg->bit_width == 64) {
 
                        /* Read the top 32 bits */
 
                        status = acpi_hw_read_port((acpi_io_address)
-                                                  (address + 4), &value, 32);
+                                                  (address + 4), &value_hi,
+                                                  32);
                        if (ACPI_FAILURE(status)) {
                                return (status);
                        }
-                       *return_value |= ((u64)value << 32);
                }
+
+               /* Set the return value only if status is AE_OK */
+
+               *return_value = (value_lo | ((u64)value_hi << 32));
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_IO,
@@ -186,7 +195,7 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
                          ACPI_FORMAT_UINT64(address),
                          acpi_ut_get_region_name(reg->space_id)));
 
-       return (status);
+       return (AE_OK);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_read)
@@ -561,10 +570,10 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b)
                break;
        }
 
-      cleanup1:
+cleanup1:
        acpi_ut_remove_reference(info->return_object);
 
-      cleanup:
+cleanup:
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status,
                                "While evaluating Sleep State [%s]",
index f2e669db8b65e90deddae8ee64a1e2b8ed3bfb39..15dddc10fc9ba5dc1cfd78b5f962ab1c21a45e1f 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 
@@ -166,7 +167,7 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64)
  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
-acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)
+acpi_status acpi_enter_sleep_state_s4bios(void)
 {
        u32 in_value;
        acpi_status status;
@@ -360,7 +361,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
-acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
+acpi_status acpi_enter_sleep_state(u8 sleep_state)
 {
        acpi_status status;
 
index c5316e5bd4abf2efce5aad7d4968708d3bccdb3d..14f65f6345b9a2de465cbe06d6047dc40f2c9576 100644 (file)
@@ -240,7 +240,7 @@ acpi_status acpi_ns_root_initialize(void)
                }
        }
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 
        /* Save a handle to "_GPE", it is always present */
@@ -424,8 +424,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
                                        /* Current scope has no parent scope */
 
                                        ACPI_ERROR((AE_INFO,
-                                                   "ACPI path has too many parent prefixes (^) "
-                                                   "- reached beyond root node"));
+                                                   "%s: Path has too many parent prefixes (^) "
+                                                   "- reached beyond root node",
+                                                   pathname));
                                        return_ACPI_STATUS(AE_NOT_FOUND);
                                }
                        }
index 7418c77fde8c70db88d0d0af9c0c6a8fcad6cad5..48b9c6f1264351b27b7232af13a810c98553eec1 100644 (file)
@@ -59,6 +59,17 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
 #endif
 
 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+
+#ifdef ACPI_FUTURE_USAGE
+static acpi_status
+acpi_ns_dump_one_object_path(acpi_handle obj_handle,
+                            u32 level, void *context, void **return_value);
+
+static acpi_status
+acpi_ns_get_max_depth(acpi_handle obj_handle,
+                     u32 level, void *context, void **return_value);
+#endif                         /* ACPI_FUTURE_USAGE */
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_print_pathname
@@ -609,7 +620,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
                obj_type = ACPI_TYPE_INVALID;   /* Terminate loop after next pass */
        }
 
-      cleanup:
+cleanup:
        acpi_os_printf("\n");
        return (AE_OK);
 }
@@ -671,6 +682,136 @@ acpi_ns_dump_objects(acpi_object_type type,
 }
 #endif                         /* ACPI_FUTURE_USAGE */
 
+#ifdef ACPI_FUTURE_USAGE
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_dump_one_object_path, acpi_ns_get_max_depth
+ *
+ * PARAMETERS:  obj_handle          - Node to be dumped
+ *              level               - Nesting level of the handle
+ *              context             - Passed into walk_namespace
+ *              return_value        - Not used
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Dump the full pathname to a namespace object. acp_ns_get_max_depth
+ *              computes the maximum nesting depth in the namespace tree, in
+ *              order to simplify formatting in acpi_ns_dump_one_object_path.
+ *              These procedures are user_functions called by acpi_ns_walk_namespace.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_dump_one_object_path(acpi_handle obj_handle,
+                            u32 level, void *context, void **return_value)
+{
+       u32 max_level = *((u32 *)context);
+       char *pathname;
+       struct acpi_namespace_node *node;
+       int path_indent;
+
+       if (!obj_handle) {
+               return (AE_OK);
+       }
+
+       node = acpi_ns_validate_handle(obj_handle);
+       if (!node) {
+
+               /* Ignore bad node during namespace walk */
+
+               return (AE_OK);
+       }
+
+       pathname = acpi_ns_get_external_pathname(node);
+
+       path_indent = 1;
+       if (level <= max_level) {
+               path_indent = max_level - level + 1;
+       }
+
+       acpi_os_printf("%2d%*s%-12s%*s",
+                      level, level, " ", acpi_ut_get_type_name(node->type),
+                      path_indent, " ");
+
+       acpi_os_printf("%s\n", &pathname[1]);
+       ACPI_FREE(pathname);
+       return (AE_OK);
+}
+
+static acpi_status
+acpi_ns_get_max_depth(acpi_handle obj_handle,
+                     u32 level, void *context, void **return_value)
+{
+       u32 *max_level = (u32 *)context;
+
+       if (level > *max_level) {
+               *max_level = level;
+       }
+       return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_dump_object_paths
+ *
+ * PARAMETERS:  type                - Object type to be dumped
+ *              display_type        - 0 or ACPI_DISPLAY_SUMMARY
+ *              max_depth           - Maximum depth of dump. Use ACPI_UINT32_MAX
+ *                                    for an effectively unlimited depth.
+ *              owner_id            - Dump only objects owned by this ID. Use
+ *                                    ACPI_UINT32_MAX to match all owners.
+ *              start_handle        - Where in namespace to start/end search
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Dump full object pathnames within the loaded namespace. Uses
+ *              acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object_path.
+ *
+ ******************************************************************************/
+
+void
+acpi_ns_dump_object_paths(acpi_object_type type,
+                         u8 display_type,
+                         u32 max_depth,
+                         acpi_owner_id owner_id, acpi_handle start_handle)
+{
+       acpi_status status;
+       u32 max_level = 0;
+
+       ACPI_FUNCTION_ENTRY();
+
+       /*
+        * Just lock the entire namespace for the duration of the dump.
+        * We don't want any changes to the namespace during this time,
+        * especially the temporary nodes since we are going to display
+        * them also.
+        */
+       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+       if (ACPI_FAILURE(status)) {
+               acpi_os_printf("Could not acquire namespace mutex\n");
+               return;
+       }
+
+       /* Get the max depth of the namespace tree, for formatting later */
+
+       (void)acpi_ns_walk_namespace(type, start_handle, max_depth,
+                                    ACPI_NS_WALK_NO_UNLOCK |
+                                    ACPI_NS_WALK_TEMP_NODES,
+                                    acpi_ns_get_max_depth, NULL,
+                                    (void *)&max_level, NULL);
+
+       /* Now dump the entire namespace */
+
+       (void)acpi_ns_walk_namespace(type, start_handle, max_depth,
+                                    ACPI_NS_WALK_NO_UNLOCK |
+                                    ACPI_NS_WALK_TEMP_NODES,
+                                    acpi_ns_dump_one_object_path, NULL,
+                                    (void *)&max_level, NULL);
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+}
+#endif                         /* ACPI_FUTURE_USAGE */
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_dump_entry
index 409ae80824d1e5a12d030bc67d79d7ec51679cc7..283762511b73abcbb87e0a7aa6c9f21ba3f88dcd 100644 (file)
@@ -69,6 +69,7 @@ static acpi_status
 acpi_ns_dump_one_device(acpi_handle obj_handle,
                        u32 level, void *context, void **return_value)
 {
+       struct acpi_buffer buffer;
        struct acpi_device_info *info;
        acpi_status status;
        u32 i;
@@ -78,15 +79,17 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
        status =
            acpi_ns_dump_one_object(obj_handle, level, context, return_value);
 
-       status = acpi_get_object_info(obj_handle, &info);
+       buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+       status = acpi_get_object_info(obj_handle, &buffer);
        if (ACPI_SUCCESS(status)) {
+               info = buffer.pointer;
                for (i = 0; i < level; i++) {
                        ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " "));
                }
 
                ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES,
                                      "    HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
-                                     info->hardware_id.string,
+                                     info->hardware_id.value,
                                      ACPI_FORMAT_UINT64(info->address),
                                      info->current_status));
                ACPI_FREE(info);
index 18108bc2e51cd76833c42b13d6c6e6e678bcb976..963ceef063f8c0de739da154b3330dd95f809895 100644 (file)
@@ -314,7 +314,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
                          "*** Completed evaluation of object %s ***\n",
                          info->relative_pathname));
 
- cleanup:
+cleanup:
        /*
         * Namespace was unlocked by the handling acpi_ns* function, so we
         * just free the pathname and return
@@ -486,7 +486,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
                parent_node->type = (u8)type;
        }
 
-      exit:
+exit:
        if (parent_obj) {
                acpi_ut_remove_reference(parent_obj);
        }
index dd2ceae3f7177aff169e56391292794c0651a74c..3a0423af968cb7e0e57313d91c4dadcadb1cfaac 100644 (file)
@@ -213,7 +213,7 @@ acpi_status acpi_ns_initialize_devices(void)
 
        return_ACPI_STATUS(status);
 
-      error_exit:
+error_exit:
        ACPI_EXCEPTION((AE_INFO, status, "During device initialization"));
        return_ACPI_STATUS(status);
 }
index 0a7badc3179f089d8f09b886547961f91e16b8d6..89ec645e7730ac6765c8013d82d08c51947da550 100644 (file)
@@ -114,7 +114,7 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
                (void)acpi_tb_release_owner_id(table_index);
        }
 
-      unlock:
+unlock:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 
        if (ACPI_FAILURE(status)) {
index 35dde8151c0d14fdec6cdd68eb55c69506d2b1fb..177857340271c4775a26e772df6e29d2c1e8d5ae 100644 (file)
@@ -140,7 +140,7 @@ acpi_ns_one_complete_parse(u32 pass_number,
                          pass_number));
        status = acpi_ps_parse_aml(walk_state);
 
-      cleanup:
+cleanup:
        acpi_ps_delete_parse_tree(parse_root);
        return_ACPI_STATUS(status);
 }
index 098e7666cbc9450ecae2a92fa605425b3346b9c3..d2855d9857c48e84a0149eaccbd5208dad2a6536 100644 (file)
@@ -271,7 +271,7 @@ acpi_ns_check_object_type(struct acpi_evaluate_info *info,
                return (AE_OK); /* Successful repair */
        }
 
-      type_error_exit:
+type_error_exit:
 
        /* Create a string with all expected types for this predefined object */
 
index 6d55cef7916c4ba4715a9108697073822edc48ec..3d5391f9bcb5561ffa888407271dd64d2fcb026c 100644 (file)
@@ -330,7 +330,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
 
        return (status);
 
-      package_too_small:
+package_too_small:
 
        /* Error exit for the case with an incorrect package count */
 
@@ -555,7 +555,7 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info,
 
        return (AE_OK);
 
-      package_too_small:
+package_too_small:
 
        /* The sub-package count was smaller than required */
 
index f8e71ea60319b21b6c014c88c69efc0b5a2dc751..a05afff50eb9cc6e9e515ef745fb8b0ae8fd7779 100644 (file)
@@ -263,7 +263,7 @@ acpi_ns_simple_repair(struct acpi_evaluate_info *info,
 
        return (AE_AML_OPERAND_TYPE);
 
-      object_repaired:
+object_repaired:
 
        /* Object was successfully repaired */
 
index c84603ee83ae084312f3936324a1bfb524b64f08..6a25d320b169ea9671385a0c825ecf9dadd290d9 100644 (file)
@@ -478,7 +478,7 @@ acpi_ns_repair_CST(struct acpi_evaluate_info *info,
                        removing = TRUE;
                }
 
-             remove_element:
+remove_element:
                if (removing) {
                        acpi_ns_remove_element(return_object, i + 1);
                        outer_element_count--;
index 5d43efc53a6179ccd4a50e5997be84306891412c..47420faef073b4dada9fa8dc26252639c3213849 100644 (file)
@@ -381,7 +381,8 @@ acpi_ns_search_and_enter(u32 target_name,
 
        /* Node is an object defined by an External() statement */
 
-       if (flags & ACPI_NS_EXTERNAL) {
+       if (flags & ACPI_NS_EXTERNAL ||
+           (walk_state && walk_state->opcode == AML_SCOPE_OP)) {
                new_node->flags |= ANOBJ_IS_EXTERNAL;
        }
 #endif
index 08c0b5beec888c65ea0d175f2795bb1be0f95227..cc2fea94c5f0939fcbfe87c676c0e869171a14f5 100644 (file)
@@ -722,7 +722,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
 
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 
-      cleanup:
+cleanup:
        ACPI_FREE(internal_path);
        return_ACPI_STATUS(status);
 }
index b38b4b07f86e31d8920a7b1467ba4fb6604fc6eb..e973e311f856597fcb9474ea9f7eabaa0a76b1da 100644 (file)
@@ -42,7 +42,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
@@ -138,7 +139,7 @@ acpi_evaluate_object_typed(acpi_handle handle,
 
                /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
 
-               ACPI_FREE(return_buffer->pointer);
+               ACPI_FREE_BUFFER(*return_buffer);
                return_buffer->pointer = NULL;
        }
 
@@ -441,7 +442,7 @@ acpi_evaluate_object(acpi_handle handle,
                acpi_ex_exit_interpreter();
        }
 
-      cleanup:
+cleanup:
 
        /* Free the input parameter list (if we created one) */
 
@@ -605,14 +606,22 @@ acpi_walk_namespace(acpi_object_type type,
                goto unlock_and_exit;
        }
 
+       /* Now we can validate the starting node */
+
+       if (!acpi_ns_validate_handle(start_object)) {
+               status = AE_BAD_PARAMETER;
+               goto unlock_and_exit2;
+       }
+
        status = acpi_ns_walk_namespace(type, start_object, max_depth,
                                        ACPI_NS_WALK_UNLOCK,
                                        descending_callback, ascending_callback,
                                        context, return_value);
 
+unlock_and_exit2:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock);
        return_ACPI_STATUS(status);
 }
@@ -856,7 +865,7 @@ acpi_attach_data(acpi_handle obj_handle,
 
        status = acpi_ns_attach_data(node, handler, data);
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return (status);
 }
@@ -902,7 +911,7 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
 
        status = acpi_ns_detach_data(node, handler);
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return (status);
 }
@@ -949,7 +958,7 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
 
        status = acpi_ns_get_attached_data(node, handler, data);
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return (status);
 }
index 83c164434580d3bd12229be0278d6e7e70e0e6b8..3a4bd3ff49a365827f2bc70dff2250c40082ea19 100644 (file)
@@ -42,7 +42,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
@@ -208,7 +209,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
        ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
        status = AE_OK;
 
-      unlock_and_exit:
+unlock_and_exit:
 
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return (status);
@@ -496,7 +497,7 @@ acpi_get_object_info(acpi_handle handle,
        *return_buffer = info;
        status = AE_OK;
 
-      cleanup:
+cleanup:
        if (hid) {
                ACPI_FREE(hid);
        }
index c0853ef294e4749832f429c962de6a2a59348676..0e6d79e462d4f8c7233dc77ad37ad6f893faaea9 100644 (file)
@@ -42,7 +42,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
@@ -200,7 +201,7 @@ acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle)
                status = AE_NULL_ENTRY;
        }
 
-      unlock_and_exit:
+unlock_and_exit:
 
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return (status);
@@ -280,7 +281,7 @@ acpi_get_next_object(acpi_object_type type,
                *ret_handle = ACPI_CAST_PTR(acpi_handle, node);
        }
 
-      unlock_and_exit:
+unlock_and_exit:
 
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return (status);
index 86198a9139b52a653d24d6758ba63ed0d04df800..79d9a28dedefe4fd6c69fdae5291a3c51106e5e6 100644 (file)
@@ -297,7 +297,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
                        }
        }
 
-      cleanup:
+cleanup:
 
        /* Now we can actually delete the subtree rooted at Op */
 
index 11b99ab20bb3a3c1a96cd5322149a4fefe7fbb4a..fcb7a840e996bdee6a3db496a296e44edd54d6f0 100644 (file)
@@ -142,7 +142,7 @@ static void acpi_ps_start_trace(struct acpi_evaluate_info *info)
                acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
        }
 
-      exit:
+exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 }
 
@@ -185,7 +185,7 @@ static void acpi_ps_stop_trace(struct acpi_evaluate_info *info)
        acpi_dbg_level = acpi_gbl_original_dbg_level;
        acpi_dbg_layer = acpi_gbl_original_dbg_layer;
 
-      exit:
+exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 }
 
@@ -323,7 +323,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
 
        /* walk_state was deleted by parse_aml */
 
-      cleanup:
+cleanup:
        acpi_ps_delete_parse_tree(op);
 
        /* End optional tracing */
index 80d12994e0d078f10b8842d6c5ee3d8a4c965c35..c99cec9cefdec4ee20305ed6e5ff578b60960f58 100644 (file)
@@ -440,7 +440,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
                info++;
        }
 
-      exit:
+exit:
        if (!flags_mode) {
 
                /* Round the resource struct length up to the next boundary (32 or 64) */
@@ -783,7 +783,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
                info++;
        }
 
-      exit:
+exit:
        return_ACPI_STATUS(AE_OK);
 }
 
index 480b6b40c5eaa3527ce58b4f76f2b8a23b16db97..aef303d56d86fecc84e397cad3c24280a874dbb4 100644 (file)
@@ -784,7 +784,7 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
 
        acpi_ut_remove_reference(args[0]);
 
-      cleanup:
+cleanup:
        ACPI_FREE(info);
        return_ACPI_STATUS(status);
 }
index 94e3517554f9d52d121dd4f31469ddb4a9ec6567..01e476988aaee38f7529e71d091310cd1e7afae5 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acresrc.h"
index 42a13c0d7015360ab44c684ab9645500fc63f1d8..634357d51fe9b4a30103f5cb1169a97d1da72b7f 100644 (file)
@@ -80,16 +80,10 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
                }
        }
 
-       /* FACS is the odd table, has no standard ACPI header and no checksum */
+       /* Always calculate checksum, ignore bad checksum if requested */
 
-       if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) {
-
-               /* Always calculate checksum, ignore bad checksum if requested */
-
-               status =
-                   acpi_tb_verify_checksum(table_desc->pointer,
-                                           table_desc->length);
-       }
+       status =
+           acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
 
        return_ACPI_STATUS(status);
 }
@@ -237,10 +231,10 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
                goto release;
        }
 
-      print_header:
+print_header:
        acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
 
-      release:
+release:
        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
        return_ACPI_STATUS(status);
 }
@@ -312,7 +306,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
 
        return (NULL);          /* There was no override */
 
-      finish_override:
+finish_override:
 
        ACPI_INFO((AE_INFO,
                   "%4.4s %p %s table override, new table: %p",
index dc963f823d2c094bb204b7baf6734fb6d340c007..6866e767ba90947359ca432bcba8643a92c0069d 100644 (file)
@@ -135,10 +135,10 @@ acpi_tb_print_table_header(acpi_physical_address address,
 
                /* FACS only has signature and length fields */
 
-               ACPI_INFO((AE_INFO, "%4.4s %p %05X",
+               ACPI_INFO((AE_INFO, "%4.4s %p %06X",
                           header->signature, ACPI_CAST_PTR(void, address),
                           header->length));
-       } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) {
+       } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) {
 
                /* RSDP has no common fields */
 
@@ -147,7 +147,7 @@ acpi_tb_print_table_header(acpi_physical_address address,
                                          header)->oem_id, ACPI_OEM_ID_SIZE);
                acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE);
 
-               ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)",
+               ACPI_INFO((AE_INFO, "RSDP %p %06X (v%.2d %6.6s)",
                           ACPI_CAST_PTR(void, address),
                           (ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
                            revision >
@@ -162,7 +162,7 @@ acpi_tb_print_table_header(acpi_physical_address address,
                acpi_tb_cleanup_table_header(&local_header, header);
 
                ACPI_INFO((AE_INFO,
-                          "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)",
+                          "%4.4s %p %06X (v%.2d %6.6s %8.8s %08X %4.4s %08X)",
                           local_header.signature, ACPI_CAST_PTR(void, address),
                           local_header.length, local_header.revision,
                           local_header.oem_id, local_header.oem_table_id,
@@ -190,6 +190,16 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
 {
        u8 checksum;
 
+       /*
+        * FACS/S3PT:
+        * They are the odd tables, have no standard ACPI header and no checksum
+        */
+
+       if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_S3PT) ||
+           ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FACS)) {
+               return (AE_OK);
+       }
+
        /* Compute the checksum on the table */
 
        checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
index bffdfc7b832254068378320a94385abdd359c715..3d6bb83aa7e75559ceb2a87688c273036f48bad8 100644 (file)
@@ -350,7 +350,7 @@ acpi_tb_install_table(acpi_physical_address address,
                acpi_tb_delete_table(table_desc);
        }
 
-      unmap_and_exit:
+unmap_and_exit:
 
        /* Always unmap the table header that we mapped above */
 
@@ -430,8 +430,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
  *
  ******************************************************************************/
 
-acpi_status __init
-acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
+acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
 {
        struct acpi_table_rsdp *rsdp;
        u32 table_entry_size;
index ad11162482ff6825a6983bfa947650618eb0ca84..db826eaadd1c7300a58fde06d0d29df463ad97a8 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "actables.h"
@@ -147,6 +148,8 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
        return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_reallocate_root_table
@@ -161,7 +164,7 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
  *              kernel.
  *
  ******************************************************************************/
-acpi_status acpi_reallocate_root_table(void)
+acpi_status __init acpi_reallocate_root_table(void)
 {
        acpi_status status;
 
@@ -181,6 +184,8 @@ acpi_status acpi_reallocate_root_table(void)
        return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL_INIT(acpi_reallocate_root_table)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_table_header
@@ -356,6 +361,7 @@ acpi_get_table_with_size(char *signature,
 
        return (AE_NOT_FOUND);
 }
+
 ACPI_EXPORT_SYMBOL(acpi_get_table_with_size)
 
 acpi_status
@@ -367,6 +373,7 @@ acpi_get_table(char *signature,
        return acpi_get_table_with_size(signature,
                       instance, out_table, &tbl_size);
 }
+
 ACPI_EXPORT_SYMBOL(acpi_get_table)
 
 /*******************************************************************************
@@ -424,7 +431,6 @@ acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table)
 
 ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
 
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_install_table_handler
@@ -465,7 +471,7 @@ acpi_install_table_handler(acpi_table_handler handler, void *context)
        acpi_gbl_table_handler = handler;
        acpi_gbl_table_handler_context = context;
 
-      cleanup:
+cleanup:
        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
        return_ACPI_STATUS(status);
 }
@@ -506,7 +512,7 @@ acpi_status acpi_remove_table_handler(acpi_table_handler handler)
 
        acpi_gbl_table_handler = NULL;
 
-      cleanup:
+cleanup:
        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
        return_ACPI_STATUS(status);
 }
index 0ba9e328d5d7b0c6fa199f4c7c8bc11ad135c9a1..60b5a871833cce325393e516562d2574476d304b 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
@@ -65,7 +66,7 @@ static acpi_status acpi_tb_load_namespace(void);
  *
  ******************************************************************************/
 
-acpi_status acpi_load_tables(void)
+acpi_status __init acpi_load_tables(void)
 {
        acpi_status status;
 
@@ -82,7 +83,7 @@ acpi_status acpi_load_tables(void)
        return_ACPI_STATUS(status);
 }
 
-ACPI_EXPORT_SYMBOL(acpi_load_tables)
+ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables)
 
 /*******************************************************************************
  *
@@ -200,7 +201,7 @@ static acpi_status acpi_tb_load_namespace(void)
 
        ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired"));
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
        return_ACPI_STATUS(status);
 }
@@ -268,7 +269,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table)
                                             acpi_gbl_table_handler_context);
        }
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
        return_ACPI_STATUS(status);
 }
index 948c95e80d44765f41e82bb62c92bb4c3405bb01..e4e1468877c3a27f2db6899098765ccaa2f42eaa 100644 (file)
@@ -68,8 +68,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
         * Note: Sometimes there exists more than one RSDP in memory; the valid
         * RSDP has a valid checksum, all others have an invalid checksum.
         */
-       if (ACPI_STRNCMP((char *)rsdp->signature, ACPI_SIG_RSDP,
-                        sizeof(ACPI_SIG_RSDP) - 1) != 0) {
+       if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
 
                /* Nope, BAD Signature */
 
@@ -112,7 +111,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
  *
  ******************************************************************************/
 
-acpi_status acpi_find_root_pointer(acpi_size *table_address)
+acpi_status __init acpi_find_root_pointer(acpi_size *table_address)
 {
        u8 *table_ptr;
        u8 *mem_rover;
index e0ffb580f4b06eba27e05ad03bc55e47f9654ff6..814267f52715a406540cebe3fad946cca5f652bc 100644 (file)
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utalloc")
 
+#if !defined (USE_NATIVE_ALLOCATE_ZEROED)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_allocate_zeroed
+ *
+ * PARAMETERS:  size                - Size of the allocation
+ *
+ * RETURN:      Address of the allocated memory on success, NULL on failure.
+ *
+ * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory.
+ *              This is the default implementation. Can be overridden via the
+ *              USE_NATIVE_ALLOCATE_ZEROED flag.
+ *
+ ******************************************************************************/
+void *acpi_os_allocate_zeroed(acpi_size size)
+{
+       void *allocation;
+
+       ACPI_FUNCTION_ENTRY();
+
+       allocation = acpi_os_allocate(size);
+       if (allocation) {
+
+               /* Clear the memory block */
+
+               ACPI_MEMSET(allocation, 0, size);
+       }
+
+       return (allocation);
+}
+
+#endif                         /* !USE_NATIVE_ALLOCATE_ZEROED */
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_create_caches
@@ -59,6 +92,7 @@ ACPI_MODULE_NAME("utalloc")
  * DESCRIPTION: Create all local caches
  *
  ******************************************************************************/
+
 acpi_status acpi_ut_create_caches(void)
 {
        acpi_status status;
@@ -175,10 +209,10 @@ acpi_status acpi_ut_delete_caches(void)
 
        /* Free memory lists */
 
-       ACPI_FREE(acpi_gbl_global_list);
+       acpi_os_free(acpi_gbl_global_list);
        acpi_gbl_global_list = NULL;
 
-       ACPI_FREE(acpi_gbl_ns_node_list);
+       acpi_os_free(acpi_gbl_ns_node_list);
        acpi_gbl_ns_node_list = NULL;
 #endif
 
@@ -302,82 +336,3 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
        ACPI_MEMSET(buffer->pointer, 0, required_length);
        return (AE_OK);
 }
-
-#ifdef NOT_USED_BY_LINUX
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_allocate
- *
- * PARAMETERS:  size                - Size of the allocation
- *              component           - Component type of caller
- *              module              - Source file name of caller
- *              line                - Line number of caller
- *
- * RETURN:      Address of the allocated memory on success, NULL on failure.
- *
- * DESCRIPTION: Subsystem equivalent of malloc.
- *
- ******************************************************************************/
-
-void *acpi_ut_allocate(acpi_size size,
-                      u32 component, const char *module, u32 line)
-{
-       void *allocation;
-
-       ACPI_FUNCTION_TRACE_U32(ut_allocate, size);
-
-       /* Check for an inadvertent size of zero bytes */
-
-       if (!size) {
-               ACPI_WARNING((module, line,
-                             "Attempt to allocate zero bytes, allocating 1 byte"));
-               size = 1;
-       }
-
-       allocation = acpi_os_allocate(size);
-       if (!allocation) {
-
-               /* Report allocation error */
-
-               ACPI_WARNING((module, line,
-                             "Could not allocate size %u", (u32) size));
-
-               return_PTR(NULL);
-       }
-
-       return_PTR(allocation);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_allocate_zeroed
- *
- * PARAMETERS:  size                - Size of the allocation
- *              component           - Component type of caller
- *              module              - Source file name of caller
- *              line                - Line number of caller
- *
- * RETURN:      Address of the allocated memory on success, NULL on failure.
- *
- * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory.
- *
- ******************************************************************************/
-
-void *acpi_ut_allocate_zeroed(acpi_size size,
-                             u32 component, const char *module, u32 line)
-{
-       void *allocation;
-
-       ACPI_FUNCTION_ENTRY();
-
-       allocation = acpi_ut_allocate(size, component, module, line);
-       if (allocation) {
-
-               /* Clear the memory block */
-
-               ACPI_MEMSET(allocation, 0, size);
-       }
-
-       return (allocation);
-}
-#endif
index a877a9647fd97648f64bceea44611cc9f136cdee..366bfec4b77027405635d1a10d99053d981a42d0 100644 (file)
@@ -65,7 +65,7 @@ ACPI_MODULE_NAME("utcache")
 acpi_status
 acpi_os_create_cache(char *cache_name,
                     u16 object_size,
-                    u16 max_depth, struct acpi_memory_list ** return_cache)
+                    u16 max_depth, struct acpi_memory_list **return_cache)
 {
        struct acpi_memory_list *cache;
 
index 1731c27c36a682e5d47beba328096ff9c633043a..edff4e653d9a06f3b9312c6512ca2a937c9ab0e6 100644 (file)
@@ -552,7 +552,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
        *ret_internal_object = internal_object;
        return_ACPI_STATUS(AE_OK);
 
-      error_exit:
+error_exit:
        acpi_ut_remove_reference(internal_object);
        return_ACPI_STATUS(AE_NO_MEMORY);
 }
@@ -899,7 +899,7 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type,
 
        return (status);
 
-      error_exit:
+error_exit:
        acpi_ut_remove_reference(target_object);
        return (status);
 }
index 5796e11a0671d32fad4329262e05b51d038cd38e..1a67b3944b3b8db426fb3edf7b878153785b7631 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 
@@ -190,7 +191,7 @@ acpi_debug_print(u32 requested_debug_level,
         * Display the module name, current line number, thread ID (if requested),
         * current procedure nesting level, and the current procedure name
         */
-       acpi_os_printf("%8s-%04ld ", module_name, line_number);
+       acpi_os_printf("%9s-%04ld ", module_name, line_number);
 
        if (ACPI_LV_THREADS & acpi_dbg_level) {
                acpi_os_printf("[%u] ", (u32)thread_id);
index 11e2e02e1618702dc75b6371d83f6da257edba61..b3f31dd89a45d90f66ab25a617960f56505501d4 100644 (file)
@@ -41,7 +41,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
index d6b33f29d32754a50eef108ce1287b59886b013b..c07d2227ea42587937ecf7bf37d88e91a6f65a66 100644 (file)
@@ -649,7 +649,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
 
        return (AE_OK);
 
-      error_exit:
+error_exit:
 
        ACPI_EXCEPTION((AE_INFO, status,
                        "Could not update object reference count"));
index 4fd68971019bdd69bcdf5ede57e26abaea3bf09f..16fb90506db72ea16d0e9bf81696bba1d9c4ccfa 100644 (file)
@@ -181,7 +181,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
 
        *return_desc = info->return_object;
 
-      cleanup:
+cleanup:
        ACPI_FREE(info);
        return_ACPI_STATUS(status);
 }
index ff6d9e8aa8423ef04ed68ec18023d61ee570493b..3cf7b597edb9357e0e05864cacaa88d55942c609 100644 (file)
@@ -41,8 +41,9 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#define EXPORT_ACPI_INTERFACES
+
 #define ACPI_DEFINE_EXCEPTION_TABLE
-#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 
index d6f26bf8a0626d0d7497baeaf1ce931d3a76c9ba..81f9a958445189b84cad67f491fb5b5c466a9559 100644 (file)
@@ -41,9 +41,9 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#define EXPORT_ACPI_INTERFACES
 #define DEFINE_ACPI_GLOBALS
 
-#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 
@@ -289,9 +289,19 @@ acpi_status acpi_ut_init_globals(void)
 
        acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000;
 
+       /* Event counters */
+
+       acpi_method_count = 0;
+       acpi_sci_count = 0;
+       acpi_gpe_count = 0;
+
+       for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
+               acpi_fixed_event_count[i] = 0;
+       }
+
 #if (!ACPI_REDUCED_HARDWARE)
 
-       /* GPE support */
+       /* GPE/SCI support */
 
        acpi_gbl_all_gpes_initialized = FALSE;
        acpi_gbl_gpe_xrupt_list_head = NULL;
@@ -300,6 +310,7 @@ acpi_status acpi_ut_init_globals(void)
        acpi_current_gpe_count = 0;
 
        acpi_gbl_global_event_handler = NULL;
+       acpi_gbl_sci_handler_list = NULL;
 
 #endif                         /* !ACPI_REDUCED_HARDWARE */
 
@@ -377,6 +388,11 @@ acpi_status acpi_ut_init_globals(void)
 /* Public globals */
 
 ACPI_EXPORT_SYMBOL(acpi_gbl_FADT)
+
 ACPI_EXPORT_SYMBOL(acpi_dbg_level)
+
 ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
+
+ACPI_EXPORT_SYMBOL(acpi_gpe_count)
+
 ACPI_EXPORT_SYMBOL(acpi_current_gpe_count)
index fa69071db4181dc100e3242053756944590679f8..bfca7b4b6731621016b11996d5a8158ecb0f825d 100644 (file)
@@ -184,7 +184,7 @@ acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
        sub->length = length;
        *return_id = sub;
 
-      cleanup:
+cleanup:
 
        /* On exit, we must delete the return object */
 
index aa61f66ee861ed1de71fee8bb72d0e412627382c..13e045025c3366f00e4912aa1063f538d44f4687 100644 (file)
@@ -180,7 +180,7 @@ union acpi_operand_object *acpi_ut_create_package_object(u32 count)
        package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size) count +
                                                 1) * sizeof(void *));
        if (!package_elements) {
-               acpi_ut_remove_reference(package_desc);
+               ACPI_FREE(package_desc);
                return_PTR(NULL);
        }
 
@@ -396,7 +396,6 @@ void *acpi_ut_allocate_object_desc_dbg(const char *module_name,
 
        /* Mark the descriptor type */
 
-       memset(object, 0, sizeof(union acpi_operand_object));
        ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND);
 
        ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p Size %X\n",
@@ -461,25 +460,28 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
 
        ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object);
 
+       /* Start with the length of the (external) Acpi object */
+
+       length = sizeof(union acpi_object);
+
+       /* A NULL object is allowed, can be a legal uninitialized package element */
+
+       if (!internal_object) {
        /*
-        * Handle a null object (Could be a uninitialized package
-        * element -- which is legal)
+                * Object is NULL, just return the length of union acpi_object
+                * (A NULL union acpi_object is an object of all zeroes.)
         */
-       if (!internal_object) {
-               *obj_length = sizeof(union acpi_object);
+               *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length);
                return_ACPI_STATUS(AE_OK);
        }
 
-       /* Start with the length of the Acpi object */
-
-       length = sizeof(union acpi_object);
+       /* A Namespace Node should never appear here */
 
        if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) {
 
-               /* Object is a named object (reference), just return the length */
+               /* A namespace node should never get here */
 
-               *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length);
-               return_ACPI_STATUS(status);
+               return_ACPI_STATUS(AE_AML_INTERNAL);
        }
 
        /*
index 835340b26d3742e8a593557d5e8dd9ed424518e5..eb3aca761369c2ccb30d2d0c4465f107fa5da389 100644 (file)
@@ -148,7 +148,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
        ACPI_ERROR((AE_INFO,
                    "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
 
-      exit:
+exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
        return_ACPI_STATUS(status);
 }
index cb7fa491decf6ab7665091aa56ed0b3ec470ed5a..2c2accb9e53494fde7c60fe580a2cc267e99528c 100644 (file)
@@ -643,7 +643,7 @@ acpi_ut_validate_resource(struct acpi_walk_state *walk_state,
 
        return (AE_OK);
 
-      invalid_resource:
+invalid_resource:
 
        if (walk_state) {
                ACPI_ERROR((AE_INFO,
@@ -652,7 +652,7 @@ acpi_ut_validate_resource(struct acpi_walk_state *walk_state,
        }
        return (AE_AML_INVALID_RESOURCE_TYPE);
 
-      bad_resource_length:
+bad_resource_length:
 
        if (walk_state) {
                ACPI_ERROR((AE_INFO,
index a6b729d4c1dc9c3a3696f8c7ea8fb396c2a8ab7f..03c4c2febd84c54b19eaa0cf397cd5e03549449d 100644 (file)
@@ -161,7 +161,6 @@ union acpi_generic_state *acpi_ut_create_generic_state(void)
        if (state) {
 
                /* Initialize */
-               memset(state, 0, sizeof(union acpi_generic_state));
                state->common.descriptor_type = ACPI_DESC_TYPE_STATE;
        }
 
index cb1e9cc32d5f8d89e7d8ba954d5c0928a0ff5f66..45c0eb26b33d5ade96f7d8d6d4f83fd7747ff88b 100644 (file)
@@ -310,7 +310,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
 
        /* All done, normal exit */
 
-      all_done:
+all_done:
 
        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
                          ACPI_FORMAT_UINT64(return_value)));
@@ -318,7 +318,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
        *ret_integer = return_value;
        return_ACPI_STATUS(AE_OK);
 
-      error_exit:
+error_exit:
        /* Base was set/validated above */
 
        if (base == 10) {
@@ -584,3 +584,65 @@ void ut_convert_backslashes(char *pathname)
        }
 }
 #endif
+
+#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_safe_strcpy, acpi_ut_safe_strcat, acpi_ut_safe_strncat
+ *
+ * PARAMETERS:  Adds a "DestSize" parameter to each of the standard string
+ *              functions. This is the size of the Destination buffer.
+ *
+ * RETURN:      TRUE if the operation would overflow the destination buffer.
+ *
+ * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that
+ *              the result of the operation will not overflow the output string
+ *              buffer.
+ *
+ * NOTE:        These functions are typically only helpful for processing
+ *              user input and command lines. For most ACPICA code, the
+ *              required buffer length is precisely calculated before buffer
+ *              allocation, so the use of these functions is unnecessary.
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source)
+{
+
+       if (ACPI_STRLEN(source) >= dest_size) {
+               return (TRUE);
+       }
+
+       ACPI_STRCPY(dest, source);
+       return (FALSE);
+}
+
+u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source)
+{
+
+       if ((ACPI_STRLEN(dest) + ACPI_STRLEN(source)) >= dest_size) {
+               return (TRUE);
+       }
+
+       ACPI_STRCAT(dest, source);
+       return (FALSE);
+}
+
+u8
+acpi_ut_safe_strncat(char *dest,
+                    acpi_size dest_size,
+                    char *source, acpi_size max_transfer_length)
+{
+       acpi_size actual_transfer_length;
+
+       actual_transfer_length =
+           ACPI_MIN(max_transfer_length, ACPI_STRLEN(source));
+
+       if ((ACPI_STRLEN(dest) + actual_transfer_length) >= dest_size) {
+               return (TRUE);
+       }
+
+       ACPI_STRNCAT(dest, source, max_transfer_length);
+       return (FALSE);
+}
+#endif
index 160f13f4aab51a196200184c60cc625a5de4acc6..c0027773cccb250b4d40ea0f5c7621ec6b98ba98 100644 (file)
@@ -130,10 +130,23 @@ void *acpi_ut_allocate_and_track(acpi_size size,
        struct acpi_debug_mem_block *allocation;
        acpi_status status;
 
+       /* Check for an inadvertent size of zero bytes */
+
+       if (!size) {
+               ACPI_WARNING((module, line,
+                             "Attempt to allocate zero bytes, allocating 1 byte"));
+               size = 1;
+       }
+
        allocation =
-           acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header),
-                            component, module, line);
+           acpi_os_allocate(size + sizeof(struct acpi_debug_mem_header));
        if (!allocation) {
+
+               /* Report allocation error */
+
+               ACPI_WARNING((module, line,
+                             "Could not allocate size %u", (u32)size));
+
                return (NULL);
        }
 
@@ -179,9 +192,17 @@ void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
        struct acpi_debug_mem_block *allocation;
        acpi_status status;
 
+       /* Check for an inadvertent size of zero bytes */
+
+       if (!size) {
+               ACPI_WARNING((module, line,
+                             "Attempt to allocate zero bytes, allocating 1 byte"));
+               size = 1;
+       }
+
        allocation =
-           acpi_ut_allocate_zeroed(size + sizeof(struct acpi_debug_mem_header),
-                                   component, module, line);
+           acpi_os_allocate_zeroed(size +
+                                   sizeof(struct acpi_debug_mem_header));
        if (!allocation) {
 
                /* Report allocation error */
@@ -409,7 +430,7 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
                element->next = allocation;
        }
 
-      unlock_and_exit:
+unlock_and_exit:
        status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
        return_ACPI_STATUS(status);
 }
index 03a211e6e26ab0a3789b7192fc6386ecd456bb1c..be322c83643a832a66a3af591aa0c66b270f7db5 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acdebug.h"
@@ -60,7 +61,7 @@ ACPI_MODULE_NAME("utxface")
  * DESCRIPTION: Shutdown the ACPICA subsystem and release all resources.
  *
  ******************************************************************************/
-acpi_status acpi_terminate(void)
+acpi_status __init acpi_terminate(void)
 {
        acpi_status status;
 
@@ -104,7 +105,7 @@ acpi_status acpi_terminate(void)
        return_ACPI_STATUS(status);
 }
 
-ACPI_EXPORT_SYMBOL(acpi_terminate)
+ACPI_EXPORT_SYMBOL_INIT(acpi_terminate)
 
 #ifndef ACPI_ASL_COMPILER
 #ifdef ACPI_FUTURE_USAGE
@@ -207,6 +208,44 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer)
 
 ACPI_EXPORT_SYMBOL(acpi_get_system_info)
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_get_statistics
+ *
+ * PARAMETERS:  stats           - Where the statistics are returned
+ *
+ * RETURN:      status          - the status of the call
+ *
+ * DESCRIPTION: Get the contents of the various system counters
+ *
+ ******************************************************************************/
+acpi_status acpi_get_statistics(struct acpi_statistics *stats)
+{
+       ACPI_FUNCTION_TRACE(acpi_get_statistics);
+
+       /* Parameter validation */
+
+       if (!stats) {
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
+       }
+
+       /* Various interrupt-based event counters */
+
+       stats->sci_count = acpi_sci_count;
+       stats->gpe_count = acpi_gpe_count;
+
+       ACPI_MEMCPY(stats->fixed_event_count, acpi_fixed_event_count,
+                   sizeof(acpi_fixed_event_count));
+
+       /* Other counters */
+
+       stats->method_count = acpi_method_count;
+
+       return_ACPI_STATUS(AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_get_statistics)
+
 /*****************************************************************************
  *
  * FUNCTION:    acpi_install_initialization_handler
index e966a2e47b765e6c097ca7973b54fa2d987ab6cd..f7edb88f60544b57f6a4097a93bd5d2f2e783a9a 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 
index 41ebaaf8bb1a4e08601bf58acd9043103f8c64a5..75efea0539c1d224376fbf079c4f22e672a633ff 100644 (file)
@@ -41,7 +41,8 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/export.h>
+#define EXPORT_ACPI_INTERFACES
+
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acevents.h"
@@ -64,7 +65,7 @@ ACPI_MODULE_NAME("utxfinit")
  *              called, so any early initialization belongs here.
  *
  ******************************************************************************/
-acpi_status acpi_initialize_subsystem(void)
+acpi_status __init acpi_initialize_subsystem(void)
 {
        acpi_status status;
 
@@ -124,7 +125,8 @@ acpi_status acpi_initialize_subsystem(void)
        ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
        return_ACPI_STATUS(status);
 }
-ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem)
+
+ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_subsystem)
 
 /*******************************************************************************
  *
@@ -138,7 +140,7 @@ ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem)
  *              Puts system into ACPI mode if it isn't already.
  *
  ******************************************************************************/
-acpi_status acpi_enable_subsystem(u32 flags)
+acpi_status __init acpi_enable_subsystem(u32 flags)
 {
        acpi_status status = AE_OK;
 
@@ -228,7 +230,8 @@ acpi_status acpi_enable_subsystem(u32 flags)
 
        return_ACPI_STATUS(status);
 }
-ACPI_EXPORT_SYMBOL(acpi_enable_subsystem)
+
+ACPI_EXPORT_SYMBOL_INIT(acpi_enable_subsystem)
 
 /*******************************************************************************
  *
@@ -242,7 +245,7 @@ ACPI_EXPORT_SYMBOL(acpi_enable_subsystem)
  *              objects and executing AML code for Regions, buffers, etc.
  *
  ******************************************************************************/
-acpi_status acpi_initialize_objects(u32 flags)
+acpi_status __init acpi_initialize_objects(u32 flags)
 {
        acpi_status status = AE_OK;
 
@@ -314,4 +317,5 @@ acpi_status acpi_initialize_objects(u32 flags)
        acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK;
        return_ACPI_STATUS(status);
 }
-ACPI_EXPORT_SYMBOL(acpi_initialize_objects)
+
+ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_objects)
index 2c9958cd7a4350ae675b76ad338904999ae149c1..fbf1aceda8b8ab915a7d2476d78db2b6e2b94e68 100644 (file)
 #include <linux/suspend.h>
 #include <asm/unaligned.h>
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <asm/uaccess.h>
-#endif
-
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/power_supply.h>
@@ -72,19 +66,6 @@ static unsigned int cache_time = 1000;
 module_param(cache_time, uint, 0644);
 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-extern struct proc_dir_entry *acpi_lock_battery_dir(void);
-extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
-
-enum acpi_battery_files {
-       info_tag = 0,
-       state_tag,
-       alarm_tag,
-       ACPI_BATTERY_NUMFILES,
-};
-
-#endif
-
 static const struct acpi_device_id battery_device_ids[] = {
        {"PNP0C0A", 0},
        {"", 0},
@@ -320,14 +301,6 @@ static enum power_supply_property energy_battery_props[] = {
        POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-inline char *acpi_battery_units(struct acpi_battery *battery)
-{
-       return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
-               "mA" : "mW";
-}
-#endif
-
 /* --------------------------------------------------------------------------
                                Battery Management
    -------------------------------------------------------------------------- */
@@ -740,279 +713,6 @@ static void acpi_battery_refresh(struct acpi_battery *battery)
        sysfs_add_battery(battery);
 }
 
-/* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ACPI_PROCFS_POWER
-static struct proc_dir_entry *acpi_battery_dir;
-
-static int acpi_battery_print_info(struct seq_file *seq, int result)
-{
-       struct acpi_battery *battery = seq->private;
-
-       if (result)
-               goto end;
-
-       seq_printf(seq, "present:                 %s\n",
-                  acpi_battery_present(battery) ? "yes" : "no");
-       if (!acpi_battery_present(battery))
-               goto end;
-       if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "design capacity:         unknown\n");
-       else
-               seq_printf(seq, "design capacity:         %d %sh\n",
-                          battery->design_capacity,
-                          acpi_battery_units(battery));
-
-       if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "last full capacity:      unknown\n");
-       else
-               seq_printf(seq, "last full capacity:      %d %sh\n",
-                          battery->full_charge_capacity,
-                          acpi_battery_units(battery));
-
-       seq_printf(seq, "battery technology:      %srechargeable\n",
-                  (!battery->technology)?"non-":"");
-
-       if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "design voltage:          unknown\n");
-       else
-               seq_printf(seq, "design voltage:          %d mV\n",
-                          battery->design_voltage);
-       seq_printf(seq, "design capacity warning: %d %sh\n",
-                  battery->design_capacity_warning,
-                  acpi_battery_units(battery));
-       seq_printf(seq, "design capacity low:     %d %sh\n",
-                  battery->design_capacity_low,
-                  acpi_battery_units(battery));
-       seq_printf(seq, "cycle count:             %i\n", battery->cycle_count);
-       seq_printf(seq, "capacity granularity 1:  %d %sh\n",
-                  battery->capacity_granularity_1,
-                  acpi_battery_units(battery));
-       seq_printf(seq, "capacity granularity 2:  %d %sh\n",
-                  battery->capacity_granularity_2,
-                  acpi_battery_units(battery));
-       seq_printf(seq, "model number:            %s\n", battery->model_number);
-       seq_printf(seq, "serial number:           %s\n", battery->serial_number);
-       seq_printf(seq, "battery type:            %s\n", battery->type);
-       seq_printf(seq, "OEM info:                %s\n", battery->oem_info);
-      end:
-       if (result)
-               seq_printf(seq, "ERROR: Unable to read battery info\n");
-       return result;
-}
-
-static int acpi_battery_print_state(struct seq_file *seq, int result)
-{
-       struct acpi_battery *battery = seq->private;
-
-       if (result)
-               goto end;
-
-       seq_printf(seq, "present:                 %s\n",
-                  acpi_battery_present(battery) ? "yes" : "no");
-       if (!acpi_battery_present(battery))
-               goto end;
-
-       seq_printf(seq, "capacity state:          %s\n",
-                       (battery->state & 0x04) ? "critical" : "ok");
-       if ((battery->state & 0x01) && (battery->state & 0x02))
-               seq_printf(seq,
-                          "charging state:          charging/discharging\n");
-       else if (battery->state & 0x01)
-               seq_printf(seq, "charging state:          discharging\n");
-       else if (battery->state & 0x02)
-               seq_printf(seq, "charging state:          charging\n");
-       else
-               seq_printf(seq, "charging state:          charged\n");
-
-       if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "present rate:            unknown\n");
-       else
-               seq_printf(seq, "present rate:            %d %s\n",
-                          battery->rate_now, acpi_battery_units(battery));
-
-       if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "remaining capacity:      unknown\n");
-       else
-               seq_printf(seq, "remaining capacity:      %d %sh\n",
-                          battery->capacity_now, acpi_battery_units(battery));
-       if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "present voltage:         unknown\n");
-       else
-               seq_printf(seq, "present voltage:         %d mV\n",
-                          battery->voltage_now);
-      end:
-       if (result)
-               seq_printf(seq, "ERROR: Unable to read battery state\n");
-
-       return result;
-}
-
-static int acpi_battery_print_alarm(struct seq_file *seq, int result)
-{
-       struct acpi_battery *battery = seq->private;
-
-       if (result)
-               goto end;
-
-       if (!acpi_battery_present(battery)) {
-               seq_printf(seq, "present:                 no\n");
-               goto end;
-       }
-       seq_printf(seq, "alarm:                   ");
-       if (!battery->alarm)
-               seq_printf(seq, "unsupported\n");
-       else
-               seq_printf(seq, "%u %sh\n", battery->alarm,
-                               acpi_battery_units(battery));
-      end:
-       if (result)
-               seq_printf(seq, "ERROR: Unable to read battery alarm\n");
-       return result;
-}
-
-static ssize_t acpi_battery_write_alarm(struct file *file,
-                                       const char __user * buffer,
-                                       size_t count, loff_t * ppos)
-{
-       int result = 0;
-       char alarm_string[12] = { '\0' };
-       struct seq_file *m = file->private_data;
-       struct acpi_battery *battery = m->private;
-
-       if (!battery || (count > sizeof(alarm_string) - 1))
-               return -EINVAL;
-       if (!acpi_battery_present(battery)) {
-               result = -ENODEV;
-               goto end;
-       }
-       if (copy_from_user(alarm_string, buffer, count)) {
-               result = -EFAULT;
-               goto end;
-       }
-       alarm_string[count] = '\0';
-       battery->alarm = simple_strtol(alarm_string, NULL, 0);
-       result = acpi_battery_set_alarm(battery);
-      end:
-       if (!result)
-               return count;
-       return result;
-}
-
-typedef int(*print_func)(struct seq_file *seq, int result);
-
-static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
-       acpi_battery_print_info,
-       acpi_battery_print_state,
-       acpi_battery_print_alarm,
-};
-
-static int acpi_battery_read(int fid, struct seq_file *seq)
-{
-       struct acpi_battery *battery = seq->private;
-       int result = acpi_battery_update(battery);
-       return acpi_print_funcs[fid](seq, result);
-}
-
-#define DECLARE_FILE_FUNCTIONS(_name) \
-static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
-{ \
-       return acpi_battery_read(_name##_tag, seq); \
-} \
-static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
-{ \
-       return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
-}
-
-DECLARE_FILE_FUNCTIONS(info);
-DECLARE_FILE_FUNCTIONS(state);
-DECLARE_FILE_FUNCTIONS(alarm);
-
-#undef DECLARE_FILE_FUNCTIONS
-
-#define FILE_DESCRIPTION_RO(_name) \
-       { \
-       .name = __stringify(_name), \
-       .mode = S_IRUGO, \
-       .ops = { \
-               .open = acpi_battery_##_name##_open_fs, \
-               .read = seq_read, \
-               .llseek = seq_lseek, \
-               .release = single_release, \
-               .owner = THIS_MODULE, \
-               }, \
-       }
-
-#define FILE_DESCRIPTION_RW(_name) \
-       { \
-       .name = __stringify(_name), \
-       .mode = S_IFREG | S_IRUGO | S_IWUSR, \
-       .ops = { \
-               .open = acpi_battery_##_name##_open_fs, \
-               .read = seq_read, \
-               .llseek = seq_lseek, \
-               .write = acpi_battery_write_##_name, \
-               .release = single_release, \
-               .owner = THIS_MODULE, \
-               }, \
-       }
-
-static const struct battery_file {
-       struct file_operations ops;
-       umode_t mode;
-       const char *name;
-} acpi_battery_file[] = {
-       FILE_DESCRIPTION_RO(info),
-       FILE_DESCRIPTION_RO(state),
-       FILE_DESCRIPTION_RW(alarm),
-};
-
-#undef FILE_DESCRIPTION_RO
-#undef FILE_DESCRIPTION_RW
-
-static int acpi_battery_add_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *entry = NULL;
-       int i;
-
-       printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
-                       " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
-       if (!acpi_device_dir(device)) {
-               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-                                                    acpi_battery_dir);
-               if (!acpi_device_dir(device))
-                       return -ENODEV;
-       }
-
-       for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
-               entry = proc_create_data(acpi_battery_file[i].name,
-                                        acpi_battery_file[i].mode,
-                                        acpi_device_dir(device),
-                                        &acpi_battery_file[i].ops,
-                                        acpi_driver_data(device));
-               if (!entry)
-                       return -ENODEV;
-       }
-       return 0;
-}
-
-static void acpi_battery_remove_fs(struct acpi_device *device)
-{
-       int i;
-       if (!acpi_device_dir(device))
-               return;
-       for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
-               remove_proc_entry(acpi_battery_file[i].name,
-                                 acpi_device_dir(device));
-
-       remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
-       acpi_device_dir(device) = NULL;
-}
-
-#endif
-
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -1075,15 +775,6 @@ static int acpi_battery_add(struct acpi_device *device)
        result = acpi_battery_update(battery);
        if (result)
                goto fail;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       result = acpi_battery_add_fs(device);
-#endif
-       if (result) {
-#ifdef CONFIG_ACPI_PROCFS_POWER
-               acpi_battery_remove_fs(device);
-#endif
-               goto fail;
-       }
 
        printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
                ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
@@ -1110,9 +801,6 @@ static int acpi_battery_remove(struct acpi_device *device)
                return -EINVAL;
        battery = acpi_driver_data(device);
        unregister_pm_notifier(&battery->pm_nb);
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_battery_remove_fs(device);
-#endif
        sysfs_remove_battery(battery);
        mutex_destroy(&battery->lock);
        mutex_destroy(&battery->sysfs_lock);
@@ -1158,18 +846,7 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
 {
        if (acpi_disabled)
                return;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_battery_dir = acpi_lock_battery_dir();
-       if (!acpi_battery_dir)
-               return;
-#endif
-       if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
-#ifdef CONFIG_ACPI_PROCFS_POWER
-               acpi_unlock_battery_dir(acpi_battery_dir);
-#endif
-               return;
-       }
-       return;
+       acpi_bus_register_driver(&acpi_battery_driver);
 }
 
 static int __init acpi_battery_init(void)
@@ -1181,9 +858,6 @@ static int __init acpi_battery_init(void)
 static void __exit acpi_battery_exit(void)
 {
        acpi_bus_unregister_driver(&acpi_battery_driver);
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_unlock_battery_dir(acpi_battery_dir);
-#endif
 }
 
 module_init(acpi_battery_init);
index 9515f18898b2b578053c58309185daa7934cfdda..fb848378d5824691af9e84b4f100a01e47df7d39 100644 (file)
@@ -274,6 +274,19 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                },
        },
        {
+       .callback = dmi_disable_osi_vista,
+       .ident = "Toshiba NB100",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "NB100"),
+               },
+       },
+
+       /*
+        * The following machines have broken backlight support when reporting
+        * the Windows 2012 OSI, so disable it until their support is fixed.
+        */
+       {
        .callback = dmi_disable_osi_win8,
        .ident = "ASUS Zenbook Prime UX31A",
        .matches = {
@@ -291,12 +304,60 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
        },
        {
        .callback = dmi_disable_osi_win8,
-       .ident = "Lenovo ThinkPad Edge E530",
+       .ident = "ThinkPad Edge E530",
        .matches = {
                     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
                     DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
                },
        },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "ThinkPad Edge E530",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "ThinkPad Edge E530",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "Acer Aspire V5-573G",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "Acer Aspire V5-572G",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "ThinkPad T431s",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "ThinkPad T430",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
+               },
+       },
 
        /*
         * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
index a55773801c5f1fb739df9597dbbde86d272b092c..c971929d75c20090b69afda2ab65b073bc95b140 100644 (file)
@@ -383,18 +383,15 @@ static int acpi_button_add(struct acpi_device *device)
 
        switch (button->type) {
        case ACPI_BUTTON_TYPE_POWER:
-               input->evbit[0] = BIT_MASK(EV_KEY);
-               set_bit(KEY_POWER, input->keybit);
+               input_set_capability(input, EV_KEY, KEY_POWER);
                break;
 
        case ACPI_BUTTON_TYPE_SLEEP:
-               input->evbit[0] = BIT_MASK(EV_KEY);
-               set_bit(KEY_SLEEP, input->keybit);
+               input_set_capability(input, EV_KEY, KEY_SLEEP);
                break;
 
        case ACPI_BUTTON_TYPE_LID:
-               input->evbit[0] = BIT_MASK(EV_SW);
-               set_bit(SW_LID, input->swbit);
+               input_set_capability(input, EV_SW, SW_LID);
                break;
        }
 
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
deleted file mode 100644 (file)
index 6c9ee68..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  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.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
-#define PREFIX "ACPI: "
-
-ACPI_MODULE_NAME("cm_sbs");
-#define ACPI_AC_CLASS          "ac_adapter"
-#define ACPI_BATTERY_CLASS     "battery"
-#define _COMPONENT             ACPI_SBS_COMPONENT
-static struct proc_dir_entry *acpi_ac_dir;
-static struct proc_dir_entry *acpi_battery_dir;
-
-static DEFINE_MUTEX(cm_sbs_mutex);
-
-static int lock_ac_dir_cnt;
-static int lock_battery_dir_cnt;
-
-struct proc_dir_entry *acpi_lock_ac_dir(void)
-{
-       mutex_lock(&cm_sbs_mutex);
-       if (!acpi_ac_dir)
-               acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
-       if (acpi_ac_dir) {
-               lock_ac_dir_cnt++;
-       } else {
-               printk(KERN_ERR PREFIX
-                                 "Cannot create %s\n", ACPI_AC_CLASS);
-       }
-       mutex_unlock(&cm_sbs_mutex);
-       return acpi_ac_dir;
-}
-EXPORT_SYMBOL(acpi_lock_ac_dir);
-
-void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param)
-{
-       mutex_lock(&cm_sbs_mutex);
-       if (acpi_ac_dir_param)
-               lock_ac_dir_cnt--;
-       if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) {
-               remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
-               acpi_ac_dir = NULL;
-       }
-       mutex_unlock(&cm_sbs_mutex);
-}
-EXPORT_SYMBOL(acpi_unlock_ac_dir);
-
-struct proc_dir_entry *acpi_lock_battery_dir(void)
-{
-       mutex_lock(&cm_sbs_mutex);
-       if (!acpi_battery_dir) {
-               acpi_battery_dir =
-                   proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
-       }
-       if (acpi_battery_dir) {
-               lock_battery_dir_cnt++;
-       } else {
-               printk(KERN_ERR PREFIX
-                                 "Cannot create %s\n", ACPI_BATTERY_CLASS);
-       }
-       mutex_unlock(&cm_sbs_mutex);
-       return acpi_battery_dir;
-}
-EXPORT_SYMBOL(acpi_lock_battery_dir);
-
-void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param)
-{
-       mutex_lock(&cm_sbs_mutex);
-       if (acpi_battery_dir_param)
-               lock_battery_dir_cnt--;
-       if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param
-           && acpi_battery_dir) {
-               remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
-               acpi_battery_dir = NULL;
-       }
-       mutex_unlock(&cm_sbs_mutex);
-       return;
-}
-EXPORT_SYMBOL(acpi_unlock_battery_dir);
index 59d3202f6b36fc197afe259b343764cb2a9621aa..d42b2fb5a7e94131ce2633ef95f4d7631729325f 100644 (file)
@@ -118,9 +118,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state)
        /*
         * If we were unsure about the device parent's power state up to this
         * point, the fact that the device is in D0 implies that the parent has
-        * to be in D0 too.
+        * to be in D0 too, except if ignore_parent is set.
         */
-       if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN
+       if (!device->power.flags.ignore_parent && device->parent
+           && device->parent->power.state == ACPI_STATE_UNKNOWN
            && result == ACPI_STATE_D0)
                device->parent->power.state = ACPI_STATE_D0;
 
@@ -177,7 +178,8 @@ int acpi_device_set_power(struct acpi_device *device, int state)
                         acpi_power_state_string(state));
                return -ENODEV;
        }
-       if (device->parent && (state < device->parent->power.state)) {
+       if (!device->power.flags.ignore_parent &&
+           device->parent && (state < device->parent->power.state)) {
                dev_warn(&device->dev,
                         "Cannot transition to power state %s for parent in %s\n",
                         acpi_power_state_string(state),
@@ -1025,60 +1027,4 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off)
        }
 }
 EXPORT_SYMBOL_GPL(acpi_dev_pm_detach);
-
-/**
- * acpi_dev_pm_add_dependent - Add physical device depending for PM.
- * @handle: Handle of ACPI device node.
- * @depdev: Device depending on that node for PM.
- */
-void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev)
-{
-       struct acpi_device_physical_node *dep;
-       struct acpi_device *adev;
-
-       if (!depdev || acpi_bus_get_device(handle, &adev))
-               return;
-
-       mutex_lock(&adev->physical_node_lock);
-
-       list_for_each_entry(dep, &adev->power_dependent, node)
-               if (dep->dev == depdev)
-                       goto out;
-
-       dep = kzalloc(sizeof(*dep), GFP_KERNEL);
-       if (dep) {
-               dep->dev = depdev;
-               list_add_tail(&dep->node, &adev->power_dependent);
-       }
-
- out:
-       mutex_unlock(&adev->physical_node_lock);
-}
-EXPORT_SYMBOL_GPL(acpi_dev_pm_add_dependent);
-
-/**
- * acpi_dev_pm_remove_dependent - Remove physical device depending for PM.
- * @handle: Handle of ACPI device node.
- * @depdev: Device depending on that node for PM.
- */
-void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev)
-{
-       struct acpi_device_physical_node *dep;
-       struct acpi_device *adev;
-
-       if (!depdev || acpi_bus_get_device(handle, &adev))
-               return;
-
-       mutex_lock(&adev->physical_node_lock);
-
-       list_for_each_entry(dep, &adev->power_dependent, node)
-               if (dep->dev == depdev) {
-                       list_del(&dep->node);
-                       kfree(dep);
-                       break;
-               }
-
-       mutex_unlock(&adev->physical_node_lock);
-}
-EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent);
 #endif /* CONFIG_PM */
index 05ea4be01a832ccb3d8b38e4318c66fee0f83a89..ca86c1ce7c8a1b5d06713e6a5264e25bd05e99e5 100644 (file)
@@ -441,7 +441,7 @@ static void handle_dock(struct dock_station *ds, int dock)
        acpi_status status;
        struct acpi_object_list arg_list;
        union acpi_object arg;
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       unsigned long long value;
 
        acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking");
 
@@ -450,12 +450,10 @@ static void handle_dock(struct dock_station *ds, int dock)
        arg_list.pointer = &arg;
        arg.type = ACPI_TYPE_INTEGER;
        arg.integer.value = dock;
-       status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
+       status = acpi_evaluate_integer(ds->handle, "_DCK", &arg_list, &value);
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
                acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n",
                                status);
-
-       kfree(buffer.pointer);
 }
 
 static inline void dock(struct dock_station *ds)
index a06d9837470585aaf0298b3f3f96f7e94bd64724..d5309fd494589b4d1596cb1c03576ed1e7ef252e 100644 (file)
@@ -28,6 +28,7 @@
 
 /* Uncomment next line to get verbose printout */
 /* #define DEBUG */
+#define pr_fmt(fmt) "ACPI : EC: " fmt
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -49,9 +50,6 @@
 #define ACPI_EC_DEVICE_NAME            "Embedded Controller"
 #define ACPI_EC_FILE_INFO              "info"
 
-#undef PREFIX
-#define PREFIX                         "ACPI: EC: "
-
 /* EC status register */
 #define ACPI_EC_FLAG_OBF       0x01    /* Output buffer full */
 #define ACPI_EC_FLAG_IBF       0x02    /* Input buffer full */
@@ -131,26 +129,26 @@ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
 static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
 {
        u8 x = inb(ec->command_addr);
-       pr_debug(PREFIX "---> status = 0x%2.2x\n", x);
+       pr_debug("---> status = 0x%2.2x\n", x);
        return x;
 }
 
 static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
 {
        u8 x = inb(ec->data_addr);
-       pr_debug(PREFIX "---> data = 0x%2.2x\n", x);
+       pr_debug("---> data = 0x%2.2x\n", x);
        return x;
 }
 
 static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
 {
-       pr_debug(PREFIX "<--- command = 0x%2.2x\n", command);
+       pr_debug("<--- command = 0x%2.2x\n", command);
        outb(command, ec->command_addr);
 }
 
 static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
 {
-       pr_debug(PREFIX "<--- data = 0x%2.2x\n", data);
+       pr_debug("<--- data = 0x%2.2x\n", data);
        outb(data, ec->data_addr);
 }
 
@@ -241,7 +239,7 @@ static int ec_poll(struct acpi_ec *ec)
                        }
                        advance_transaction(ec, acpi_ec_read_status(ec));
                } while (time_before(jiffies, delay));
-               pr_debug(PREFIX "controller reset, restart transaction\n");
+               pr_debug("controller reset, restart transaction\n");
                spin_lock_irqsave(&ec->lock, flags);
                start_transaction(ec);
                spin_unlock_irqrestore(&ec->lock, flags);
@@ -309,12 +307,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
                }
        }
        if (ec_wait_ibf0(ec)) {
-               pr_err(PREFIX "input buffer is not empty, "
+               pr_err("input buffer is not empty, "
                                "aborting transaction\n");
                status = -ETIME;
                goto end;
        }
-       pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n",
+       pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n",
                        t->command, t->wdata ? t->wdata[0] : 0);
        /* disable GPE during transaction if storm is detected */
        if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
@@ -331,12 +329,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
                /* It is safe to enable the GPE outside of the transaction. */
                acpi_enable_gpe(NULL, ec->gpe);
        } else if (t->irq_count > ec_storm_threshold) {
-               pr_info(PREFIX "GPE storm detected(%d GPEs), "
+               pr_info("GPE storm detected(%d GPEs), "
                        "transactions will use polling mode\n",
                        t->irq_count);
                set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
        }
-       pr_debug(PREFIX "transaction end\n");
+       pr_debug("transaction end\n");
 end:
        if (ec->global_lock)
                acpi_release_global_lock(glk);
@@ -570,12 +568,12 @@ static void acpi_ec_run(void *cxt)
        struct acpi_ec_query_handler *handler = cxt;
        if (!handler)
                return;
-       pr_debug(PREFIX "start query execution\n");
+       pr_debug("start query execution\n");
        if (handler->func)
                handler->func(handler->data);
        else if (handler->handle)
                acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
-       pr_debug(PREFIX "stop query execution\n");
+       pr_debug("stop query execution\n");
        kfree(handler);
 }
 
@@ -593,7 +591,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec)
                        if (!copy)
                                return -ENOMEM;
                        memcpy(copy, handler, sizeof(*copy));
-                       pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value);
+                       pr_debug("push query execution (0x%2x) on queue\n",
+                               value);
                        return acpi_os_execute((copy->func) ?
                                OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
                                acpi_ec_run, copy);
@@ -616,7 +615,7 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
 {
        if (state & ACPI_EC_FLAG_SCI) {
                if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
-                       pr_debug(PREFIX "push gpe query to the queue\n");
+                       pr_debug("push gpe query to the queue\n");
                        return acpi_os_execute(OSL_NOTIFY_HANDLER,
                                acpi_ec_gpe_query, ec);
                }
@@ -630,7 +629,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
        struct acpi_ec *ec = data;
        u8 status = acpi_ec_read_status(ec);
 
-       pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status);
+       pr_debug("~~~> interrupt, status:0x%02x\n", status);
 
        advance_transaction(ec, status);
        if (ec_transaction_done(ec) &&
@@ -776,7 +775,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
                         * The AE_NOT_FOUND error will be ignored and OS
                         * continue to initialize EC.
                         */
-                       printk(KERN_ERR "Fail in evaluating the _REG object"
+                       pr_err("Fail in evaluating the _REG object"
                                " of EC device. Broken bios is suspected.\n");
                } else {
                        acpi_remove_gpe_handler(NULL, ec->gpe,
@@ -795,10 +794,10 @@ static void ec_remove_handlers(struct acpi_ec *ec)
        acpi_disable_gpe(NULL, ec->gpe);
        if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
                                ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
-               pr_err(PREFIX "failed to remove space handler\n");
+               pr_err("failed to remove space handler\n");
        if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
                                &acpi_ec_gpe_handler)))
-               pr_err(PREFIX "failed to remove gpe handler\n");
+               pr_err("failed to remove gpe handler\n");
        clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
 }
 
@@ -840,7 +839,7 @@ static int acpi_ec_add(struct acpi_device *device)
        ret = !!request_region(ec->command_addr, 1, "EC cmd");
        WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr);
 
-       pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
+       pr_info("GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
                          ec->gpe, ec->command_addr, ec->data_addr);
 
        ret = ec_install_handlers(ec);
@@ -931,7 +930,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id)
 /* MSI EC needs special treatment, enable it */
 static int ec_flag_msi(const struct dmi_system_id *id)
 {
-       printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n");
+       pr_debug("Detected MSI hardware, enabling workarounds.\n");
        EC_FLAGS_MSI = 1;
        EC_FLAGS_VALIDATE_ECDT = 1;
        return 0;
@@ -1010,7 +1009,7 @@ int __init acpi_ec_ecdt_probe(void)
        status = acpi_get_table(ACPI_SIG_ECDT, 1,
                                (struct acpi_table_header **)&ecdt_ptr);
        if (ACPI_SUCCESS(status)) {
-               pr_info(PREFIX "EC description table is found, configuring boot EC\n");
+               pr_info("EC description table is found, configuring boot EC\n");
                boot_ec->command_addr = ecdt_ptr->control.address;
                boot_ec->data_addr = ecdt_ptr->data.address;
                boot_ec->gpe = ecdt_ptr->gpe;
@@ -1030,7 +1029,7 @@ int __init acpi_ec_ecdt_probe(void)
 
        /* This workaround is needed only on some broken machines,
         * which require early EC, but fail to provide ECDT */
-       printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
+       pr_debug("Look up EC in DSDT\n");
        status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
                                        boot_ec, NULL);
        /* Check that acpi_get_devices actually find something */
@@ -1042,7 +1041,7 @@ int __init acpi_ec_ecdt_probe(void)
                    saved_ec->data_addr != boot_ec->data_addr ||
                    saved_ec->gpe != boot_ec->gpe ||
                    saved_ec->handle != boot_ec->handle)
-                       pr_info(PREFIX "ASUSTek keeps feeding us with broken "
+                       pr_info("ASUSTek keeps feeding us with broken "
                        "ECDT tables, which are very hard to workaround. "
                        "Trying to use DSDT EC info instead. Please send "
                        "output of acpidump to linux-acpi@vger.kernel.org\n");
index 8247fcdde0795b37377bdec44d6271ca16ad225d..fdef416c0ff6f0384e107466b47b1ff8f2bac9aa 100644 (file)
@@ -127,11 +127,6 @@ int acpi_bus_generate_netlink_event(const char *device_class,
        }
 
        event = nla_data(attr);
-       if (!event) {
-               nlmsg_free(skb);
-               return -EINVAL;
-       }
-
        memset(event, 0, sizeof(struct acpi_genl_event));
 
        strcpy(event->device_class, device_class);
index 41ade6570bc07c22c3c40445d696aea26e4e4c41..ba3da88cee45a20479df62023ee560aa422dff22 100644 (file)
@@ -168,7 +168,7 @@ static int acpi_fan_add(struct acpi_device *device)
               acpi_device_name(device), acpi_device_bid(device),
               !device->power.state ? "on" : "off");
 
-      end:
+end:
        return result;
 }
 
index 20f423337e1fb73c66379a3771954741860c6d7d..e9304dc7ebfa0dc40c37dcc3be270cc299b94170 100644 (file)
@@ -169,9 +169,7 @@ int acpi_create_platform_device(struct acpi_device *adev,
                                        Video
   -------------------------------------------------------------------------- */
 #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE)
-bool acpi_video_backlight_quirks(void);
-#else
-static inline bool acpi_video_backlight_quirks(void) { return false; }
+bool acpi_osi_is_win8(void);
 #endif
 
 #endif /* _ACPI_INTERNAL_H_ */
index 2e82e5d7693016676ad6afdf69ce3b553e968d44..a2343a1d9e0b1a0e77f3b7a7caf6676499c5f989 100644 (file)
@@ -73,7 +73,7 @@ int acpi_map_pxm_to_node(int pxm)
 {
        int node = pxm_to_node_map[pxm];
 
-       if (node < 0) {
+       if (node == NUMA_NO_NODE) {
                if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
                        return NUMA_NO_NODE;
                node = first_unset_node(nodes_found_map);
@@ -334,7 +334,7 @@ int acpi_get_pxm(acpi_handle h)
 
 int acpi_get_node(acpi_handle *handle)
 {
-       int pxm, node = -1;
+       int pxm, node = NUMA_NO_NODE;
 
        pxm = acpi_get_pxm(handle);
        if (pxm >= 0 && pxm < MAX_PXM_DOMAINS)
index e5f416c7f66e9e92e1ed988c3a709bc2820d56f4..a0c09adf7e7d2043587dad0384ba1374353989c7 100644 (file)
@@ -569,8 +569,10 @@ static const char * const table_sigs[] = {
 
 #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
 
-/* Must not increase 10 or needs code modification below */
-#define ACPI_OVERRIDE_TABLES 10
+#define ACPI_OVERRIDE_TABLES 64
+static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES];
+
+#define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
 
 void __init acpi_initrd_override(void *data, size_t size)
 {
@@ -579,8 +581,6 @@ void __init acpi_initrd_override(void *data, size_t size)
        struct acpi_table_header *table;
        char cpio_path[32] = "kernel/firmware/acpi/";
        struct cpio_data file;
-       struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES];
-       char *p;
 
        if (data == NULL || size == 0)
                return;
@@ -625,8 +625,8 @@ void __init acpi_initrd_override(void *data, size_t size)
                        table->signature, cpio_path, file.name, table->length);
 
                all_tables_size += table->length;
-               early_initrd_files[table_nr].data = file.data;
-               early_initrd_files[table_nr].size = file.size;
+               acpi_initrd_files[table_nr].data = file.data;
+               acpi_initrd_files[table_nr].size = file.size;
                table_nr++;
        }
        if (table_nr == 0)
@@ -652,14 +652,34 @@ void __init acpi_initrd_override(void *data, size_t size)
        memblock_reserve(acpi_tables_addr, all_tables_size);
        arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
-       p = early_ioremap(acpi_tables_addr, all_tables_size);
-
+       /*
+        * early_ioremap only can remap 256k one time. If we map all
+        * tables one time, we will hit the limit. Need to map chunks
+        * one by one during copying the same as that in relocate_initrd().
+        */
        for (no = 0; no < table_nr; no++) {
-               memcpy(p + total_offset, early_initrd_files[no].data,
-                      early_initrd_files[no].size);
-               total_offset += early_initrd_files[no].size;
+               unsigned char *src_p = acpi_initrd_files[no].data;
+               phys_addr_t size = acpi_initrd_files[no].size;
+               phys_addr_t dest_addr = acpi_tables_addr + total_offset;
+               phys_addr_t slop, clen;
+               char *dest_p;
+
+               total_offset += size;
+
+               while (size) {
+                       slop = dest_addr & ~PAGE_MASK;
+                       clen = size;
+                       if (clen > MAP_CHUNK_SIZE - slop)
+                               clen = MAP_CHUNK_SIZE - slop;
+                       dest_p = early_ioremap(dest_addr & PAGE_MASK,
+                                                clen + slop);
+                       memcpy(dest_p + slop, src_p, clen);
+                       early_iounmap(dest_p, clen + slop);
+                       src_p += clen;
+                       dest_addr += clen;
+                       size -= clen;
+               }
        }
-       early_iounmap(p, all_tables_size);
 }
 #endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
 
@@ -820,7 +840,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
 
 void acpi_os_sleep(u64 ms)
 {
-       schedule_timeout_interruptible(msecs_to_jiffies(ms));
+       msleep(ms);
 }
 
 void acpi_os_stall(u32 us)
@@ -1335,7 +1355,7 @@ static int __init acpi_os_name_setup(char *str)
        if (!str || !*str)
                return 0;
 
-       for (; count-- && str && *str; str++) {
+       for (; count-- && *str; str++) {
                if (isalnum(*str) || *str == ' ' || *str == ':')
                        *p++ = *str;
                else if (*str == '\'' || *str == '"')
index 0dbe5cdf3396e5f53b23c84bb30041329544774d..c2ad391d8041ecb6a354e2df07b9d813d817a744 100644 (file)
@@ -59,16 +59,9 @@ ACPI_MODULE_NAME("power");
 #define ACPI_POWER_RESOURCE_STATE_ON   0x01
 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
 
-struct acpi_power_dependent_device {
-       struct list_head node;
-       struct acpi_device *adev;
-       struct work_struct work;
-};
-
 struct acpi_power_resource {
        struct acpi_device device;
        struct list_head list_node;
-       struct list_head dependent;
        char *name;
        u32 system_level;
        u32 order;
@@ -233,32 +226,6 @@ static int acpi_power_get_list_state(struct list_head *list, int *state)
        return 0;
 }
 
-static void acpi_power_resume_dependent(struct work_struct *work)
-{
-       struct acpi_power_dependent_device *dep;
-       struct acpi_device_physical_node *pn;
-       struct acpi_device *adev;
-       int state;
-
-       dep = container_of(work, struct acpi_power_dependent_device, work);
-       adev = dep->adev;
-       if (acpi_power_get_inferred_state(adev, &state))
-               return;
-
-       if (state > ACPI_STATE_D0)
-               return;
-
-       mutex_lock(&adev->physical_node_lock);
-
-       list_for_each_entry(pn, &adev->physical_node_list, node)
-               pm_request_resume(pn->dev);
-
-       list_for_each_entry(pn, &adev->power_dependent, node)
-               pm_request_resume(pn->dev);
-
-       mutex_unlock(&adev->physical_node_lock);
-}
-
 static int __acpi_power_on(struct acpi_power_resource *resource)
 {
        acpi_status status = AE_OK;
@@ -283,14 +250,8 @@ static int acpi_power_on_unlocked(struct acpi_power_resource *resource)
                                  resource->name));
        } else {
                result = __acpi_power_on(resource);
-               if (result) {
+               if (result)
                        resource->ref_count--;
-               } else {
-                       struct acpi_power_dependent_device *dep;
-
-                       list_for_each_entry(dep, &resource->dependent, node)
-                               schedule_work(&dep->work);
-               }
        }
        return result;
 }
@@ -390,52 +351,6 @@ static int acpi_power_on_list(struct list_head *list)
        return result;
 }
 
-static void acpi_power_add_dependent(struct acpi_power_resource *resource,
-                                    struct acpi_device *adev)
-{
-       struct acpi_power_dependent_device *dep;
-
-       mutex_lock(&resource->resource_lock);
-
-       list_for_each_entry(dep, &resource->dependent, node)
-               if (dep->adev == adev)
-                       goto out;
-
-       dep = kzalloc(sizeof(*dep), GFP_KERNEL);
-       if (!dep)
-               goto out;
-
-       dep->adev = adev;
-       INIT_WORK(&dep->work, acpi_power_resume_dependent);
-       list_add_tail(&dep->node, &resource->dependent);
-
- out:
-       mutex_unlock(&resource->resource_lock);
-}
-
-static void acpi_power_remove_dependent(struct acpi_power_resource *resource,
-                                       struct acpi_device *adev)
-{
-       struct acpi_power_dependent_device *dep;
-       struct work_struct *work = NULL;
-
-       mutex_lock(&resource->resource_lock);
-
-       list_for_each_entry(dep, &resource->dependent, node)
-               if (dep->adev == adev) {
-                       list_del(&dep->node);
-                       work = &dep->work;
-                       break;
-               }
-
-       mutex_unlock(&resource->resource_lock);
-
-       if (work) {
-               cancel_work_sync(work);
-               kfree(dep);
-       }
-}
-
 static struct attribute *attrs[] = {
        NULL,
 };
@@ -524,8 +439,6 @@ static void acpi_power_expose_hide(struct acpi_device *adev,
 
 void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
 {
-       struct acpi_device_power_state *ps;
-       struct acpi_power_resource_entry *entry;
        int state;
 
        if (adev->wakeup.flags.valid)
@@ -535,16 +448,6 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
        if (!adev->power.flags.power_resources)
                return;
 
-       ps = &adev->power.states[ACPI_STATE_D0];
-       list_for_each_entry(entry, &ps->resources, node) {
-               struct acpi_power_resource *resource = entry->resource;
-
-               if (add)
-                       acpi_power_add_dependent(resource, adev);
-               else
-                       acpi_power_remove_dependent(resource, adev);
-       }
-
        for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++)
                acpi_power_expose_hide(adev,
                                       &adev->power.states[state].resources,
@@ -882,7 +785,6 @@ int acpi_add_power_resource(acpi_handle handle)
        acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
                                ACPI_STA_DEFAULT);
        mutex_init(&resource->resource_lock);
-       INIT_LIST_HEAD(&resource->dependent);
        INIT_LIST_HEAD(&resource->list_node);
        resource->name = device->pnp.bus_id;
        strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
@@ -936,8 +838,10 @@ void acpi_resume_power_resources(void)
                mutex_lock(&resource->resource_lock);
 
                result = acpi_power_get_state(resource->device.handle, &state);
-               if (result)
+               if (result) {
+                       mutex_unlock(&resource->resource_lock);
                        continue;
+               }
 
                if (state == ACPI_POWER_RESOURCE_STATE_OFF
                    && resource->ref_count) {
index 04a13784dd20a4a7e42b15b98eedcff90cb67299..6a5b152ad4d070511d08d74439155fa17a83ed8a 100644 (file)
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
-#ifdef CONFIG_X86
-#include <linux/mc146818rtc.h>
-#endif
-
 #include "sleep.h"
 
 #define _COMPONENT             ACPI_SYSTEM_COMPONENT
 
 /*
  * this file provides support for:
- * /proc/acpi/alarm
  * /proc/acpi/wakeup
  */
 
 ACPI_MODULE_NAME("sleep")
 
-#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86)
-/* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */
-#else
-#define        HAVE_ACPI_LEGACY_ALARM
-#endif
-
-#ifdef HAVE_ACPI_LEGACY_ALARM
-
-static u32 cmos_bcd_read(int offset, int rtc_control);
-
-static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
-{
-       u32 sec, min, hr;
-       u32 day, mo, yr, cent = 0;
-       u32 today = 0;
-       unsigned char rtc_control = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-
-       rtc_control = CMOS_READ(RTC_CONTROL);
-       sec = cmos_bcd_read(RTC_SECONDS_ALARM, rtc_control);
-       min = cmos_bcd_read(RTC_MINUTES_ALARM, rtc_control);
-       hr = cmos_bcd_read(RTC_HOURS_ALARM, rtc_control);
-
-       /* If we ever get an FACP with proper values... */
-       if (acpi_gbl_FADT.day_alarm) {
-               /* ACPI spec: only low 6 its should be cared */
-               day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F;
-               if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-                       day = bcd2bin(day);
-       } else
-               day = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
-       if (acpi_gbl_FADT.month_alarm)
-               mo = cmos_bcd_read(acpi_gbl_FADT.month_alarm, rtc_control);
-       else {
-               mo = cmos_bcd_read(RTC_MONTH, rtc_control);
-               today = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
-       }
-       if (acpi_gbl_FADT.century)
-               cent = cmos_bcd_read(acpi_gbl_FADT.century, rtc_control);
-
-       yr = cmos_bcd_read(RTC_YEAR, rtc_control);
-
-       spin_unlock_irqrestore(&rtc_lock, flags);
-
-       /* we're trusting the FADT (see above) */
-       if (!acpi_gbl_FADT.century)
-               /* If we're not trusting the FADT, we should at least make it
-                * right for _this_ century... ehm, what is _this_ century?
-                *
-                * TBD:
-                *  ASAP: find piece of code in the kernel, e.g. star tracker driver,
-                *        which we can trust to determine the century correctly. Atom
-                *        watch driver would be nice, too...
-                *
-                *  if that has not happened, change for first release in 2050:
-                *        if (yr<50)
-                *                yr += 2100;
-                *        else
-                *                yr += 2000;   // current line of code
-                *
-                *  if that has not happened either, please do on 2099/12/31:23:59:59
-                *        s/2000/2100
-                *
-                */
-               yr += 2000;
-       else
-               yr += cent * 100;
-
-       /*
-        * Show correct dates for alarms up to a month into the future.
-        * This solves issues for nearly all situations with the common
-        * 30-day alarm clocks in PC hardware.
-        */
-       if (day < today) {
-               if (mo < 12) {
-                       mo += 1;
-               } else {
-                       mo = 1;
-                       yr += 1;
-               }
-       }
-
-       seq_printf(seq, "%4.4u-", yr);
-       (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo);
-       (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day);
-       (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr);
-       (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min);
-       (sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec);
-
-       return 0;
-}
-
-static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_system_alarm_seq_show, PDE_DATA(inode));
-}
-
-static int get_date_field(char **p, u32 * value)
-{
-       char *next = NULL;
-       char *string_end = NULL;
-       int result = -EINVAL;
-
-       /*
-        * Try to find delimeter, only to insert null.  The end of the
-        * string won't have one, but is still valid.
-        */
-       if (*p == NULL)
-               return result;
-
-       next = strpbrk(*p, "- :");
-       if (next)
-               *next++ = '\0';
-
-       *value = simple_strtoul(*p, &string_end, 10);
-
-       /* Signal success if we got a good digit */
-       if (string_end != *p)
-               result = 0;
-
-       if (next)
-               *p = next;
-       else
-               *p = NULL;
-
-       return result;
-}
-
-/* Read a possibly BCD register, always return binary */
-static u32 cmos_bcd_read(int offset, int rtc_control)
-{
-       u32 val = CMOS_READ(offset);
-       if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               val = bcd2bin(val);
-       return val;
-}
-
-/* Write binary value into possibly BCD register */
-static void cmos_bcd_write(u32 val, int offset, int rtc_control)
-{
-       if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               val = bin2bcd(val);
-       CMOS_WRITE(val, offset);
-}
-
-static ssize_t
-acpi_system_write_alarm(struct file *file,
-                       const char __user * buffer, size_t count, loff_t * ppos)
-{
-       int result = 0;
-       char alarm_string[30] = { '\0' };
-       char *p = alarm_string;
-       u32 sec, min, hr, day, mo, yr;
-       int adjust = 0;
-       unsigned char rtc_control = 0;
-
-       if (count > sizeof(alarm_string) - 1)
-               return -EINVAL;
-
-       if (copy_from_user(alarm_string, buffer, count))
-               return -EFAULT;
-
-       alarm_string[count] = '\0';
-
-       /* check for time adjustment */
-       if (alarm_string[0] == '+') {
-               p++;
-               adjust = 1;
-       }
-
-       if ((result = get_date_field(&p, &yr)))
-               goto end;
-       if ((result = get_date_field(&p, &mo)))
-               goto end;
-       if ((result = get_date_field(&p, &day)))
-               goto end;
-       if ((result = get_date_field(&p, &hr)))
-               goto end;
-       if ((result = get_date_field(&p, &min)))
-               goto end;
-       if ((result = get_date_field(&p, &sec)))
-               goto end;
-
-       spin_lock_irq(&rtc_lock);
-
-       rtc_control = CMOS_READ(RTC_CONTROL);
-
-       if (adjust) {
-               yr += cmos_bcd_read(RTC_YEAR, rtc_control);
-               mo += cmos_bcd_read(RTC_MONTH, rtc_control);
-               day += cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
-               hr += cmos_bcd_read(RTC_HOURS, rtc_control);
-               min += cmos_bcd_read(RTC_MINUTES, rtc_control);
-               sec += cmos_bcd_read(RTC_SECONDS, rtc_control);
-       }
-
-       spin_unlock_irq(&rtc_lock);
-
-       if (sec > 59) {
-               min += sec/60;
-               sec = sec%60;
-       }
-       if (min > 59) {
-               hr += min/60;
-               min = min%60;
-       }
-       if (hr > 23) {
-               day += hr/24;
-               hr = hr%24;
-       }
-       if (day > 31) {
-               mo += day/32;
-               day = day%32;
-       }
-       if (mo > 12) {
-               yr += mo/13;
-               mo = mo%13;
-       }
-
-       spin_lock_irq(&rtc_lock);
-       /*
-        * Disable alarm interrupt before setting alarm timer or else
-        * when ACPI_EVENT_RTC is enabled, a spurious ACPI interrupt occurs
-        */
-       rtc_control &= ~RTC_AIE;
-       CMOS_WRITE(rtc_control, RTC_CONTROL);
-       CMOS_READ(RTC_INTR_FLAGS);
-
-       /* write the fields the rtc knows about */
-       cmos_bcd_write(hr, RTC_HOURS_ALARM, rtc_control);
-       cmos_bcd_write(min, RTC_MINUTES_ALARM, rtc_control);
-       cmos_bcd_write(sec, RTC_SECONDS_ALARM, rtc_control);
-
-       /*
-        * If the system supports an enhanced alarm it will have non-zero
-        * offsets into the CMOS RAM here -- which for some reason are pointing
-        * to the RTC area of memory.
-        */
-       if (acpi_gbl_FADT.day_alarm)
-               cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control);
-       if (acpi_gbl_FADT.month_alarm)
-               cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control);
-       if (acpi_gbl_FADT.century) {
-               if (adjust)
-                       yr += cmos_bcd_read(acpi_gbl_FADT.century, rtc_control) * 100;
-               cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control);
-       }
-       /* enable the rtc alarm interrupt */
-       rtc_control |= RTC_AIE;
-       CMOS_WRITE(rtc_control, RTC_CONTROL);
-       CMOS_READ(RTC_INTR_FLAGS);
-
-       spin_unlock_irq(&rtc_lock);
-
-       acpi_clear_event(ACPI_EVENT_RTC);
-       acpi_enable_event(ACPI_EVENT_RTC, 0);
-
-       *ppos += count;
-
-       result = 0;
-      end:
-       return result ? result : count;
-}
-#endif                         /* HAVE_ACPI_LEGACY_ALARM */
-
 static int
 acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
 {
@@ -417,41 +145,8 @@ static const struct file_operations acpi_system_wakeup_device_fops = {
        .release = single_release,
 };
 
-#ifdef HAVE_ACPI_LEGACY_ALARM
-static const struct file_operations acpi_system_alarm_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_system_alarm_open_fs,
-       .read = seq_read,
-       .write = acpi_system_write_alarm,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static u32 rtc_handler(void *context)
-{
-       acpi_clear_event(ACPI_EVENT_RTC);
-       acpi_disable_event(ACPI_EVENT_RTC, 0);
-
-       return ACPI_INTERRUPT_HANDLED;
-}
-#endif                         /* HAVE_ACPI_LEGACY_ALARM */
-
 int __init acpi_sleep_proc_init(void)
 {
-#ifdef HAVE_ACPI_LEGACY_ALARM
-       /* 'alarm' [R/W] */
-       proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR,
-                   acpi_root_dir, &acpi_system_alarm_fops);
-
-       acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
-       /*
-        * Disable the RTC event after installing RTC handler.
-        * Only when RTC alarm is set will it be enabled.
-        */
-       acpi_clear_event(ACPI_EVENT_RTC);
-       acpi_disable_event(ACPI_EVENT_RTC, 0);
-#endif                         /* HAVE_ACPI_LEGACY_ALARM */
-
        /* 'wakeup device' [R/W] */
        proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
                    acpi_root_dir, &acpi_system_wakeup_device_fops);
index cf34d903f4fb4a45b7975fc5fce60d141de2b7a9..b3171f30b319c1244007e686a0b516833443191d 100644 (file)
@@ -162,16 +162,23 @@ exit:
        return apic_id;
 }
 
-int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
+int acpi_get_apicid(acpi_handle handle, int type, u32 acpi_id)
 {
-#ifdef CONFIG_SMP
-       int i;
-#endif
-       int apic_id = -1;
+       int apic_id;
 
        apic_id = map_mat_entry(handle, type, acpi_id);
        if (apic_id == -1)
                apic_id = map_madt_entry(type, acpi_id);
+
+       return apic_id;
+}
+
+int acpi_map_cpuid(int apic_id, u32 acpi_id)
+{
+#ifdef CONFIG_SMP
+       int i;
+#endif
+
        if (apic_id == -1) {
                /*
                 * On UP processor, there is no _MAT or MADT table.
@@ -211,6 +218,15 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
 #endif
        return -1;
 }
+
+int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
+{
+       int apic_id;
+
+       apic_id = acpi_get_apicid(handle, type, acpi_id);
+
+       return acpi_map_cpuid(apic_id, acpi_id);
+}
 EXPORT_SYMBOL_GPL(acpi_get_cpuid);
 
 static bool __init processor_physically_present(acpi_handle handle)
index e534ba66d5b80861849ae705bf941ac570720607..146ab7e2b81d71949908ce43754e7b08bcaee022 100644 (file)
@@ -153,8 +153,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
        return NOTIFY_OK;
 }
 
-static struct notifier_block __refdata acpi_cpu_notifier =
-{
+static struct notifier_block __refdata acpi_cpu_notifier = {
            .notifier_call = acpi_cpu_soft_notify,
 };
 
@@ -172,7 +171,6 @@ static int __acpi_processor_start(struct acpi_device *device)
 
 #ifdef CONFIG_CPU_FREQ
        acpi_processor_ppc_has_changed(pr, 0);
-       acpi_processor_load_module(pr);
 #endif
        acpi_processor_get_throttling_info(pr);
 
index f98dd00b51a94b2d7e2d7dc9cd15f3e941e81bff..35c8f2bbcc40b45510ea7d1b67ee294efc33471b 100644 (file)
@@ -272,9 +272,6 @@ static void tsc_check_state(int state) { return; }
 static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
 {
 
-       if (!pr)
-               return -EINVAL;
-
        if (!pr->pblk)
                return -ENODEV;
 
@@ -1076,12 +1073,8 @@ int acpi_processor_hotplug(struct acpi_processor *pr)
        if (disabled_by_idle_boot_param())
                return 0;
 
-       if (!pr)
-               return -EINVAL;
-
-       if (nocst) {
+       if (nocst)
                return -ENODEV;
-       }
 
        if (!pr->flags.power_setup_done)
                return -ENODEV;
@@ -1108,9 +1101,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
        if (disabled_by_idle_boot_param())
                return 0;
 
-       if (!pr)
-               return -EINVAL;
-
        if (nocst)
                return -ENODEV;
 
@@ -1183,9 +1173,6 @@ int acpi_processor_power_init(struct acpi_processor *pr)
                first_run++;
        }
 
-       if (!pr)
-               return -EINVAL;
-
        if (acpi_gbl_FADT.cst_control && !nocst) {
                status =
                    acpi_os_write_port(acpi_gbl_FADT.smi_command, acpi_gbl_FADT.cst_control, 8);
index 51d7948611da0ece22a9aedb6ecd598ba4e4526e..60a7c28fc1674cc21bc38802fed869dc7daf0608 100644 (file)
@@ -235,28 +235,6 @@ void acpi_processor_ppc_exit(void)
        acpi_processor_ppc_status &= ~PPC_REGISTERED;
 }
 
-/*
- * Do a quick check if the systems looks like it should use ACPI
- * cpufreq. We look at a _PCT method being available, but don't
- * do a whole lot of sanity checks.
- */
-void acpi_processor_load_module(struct acpi_processor *pr)
-{
-       static int requested;
-       acpi_status status = 0;
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
-       if (!arch_has_acpi_pdc() || requested)
-               return;
-       status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
-       if (!ACPI_FAILURE(status)) {
-               printk(KERN_INFO PREFIX "Requesting acpi_cpufreq\n");
-               request_module_nowait("acpi_cpufreq");
-               requested = 1;
-       }
-       kfree(buffer.pointer);
-}
-
 static int acpi_processor_get_performance_control(struct acpi_processor *pr)
 {
        int result = 0;
index aef7e1cd1e5d62f95512484935e4fea9b11af961..d465ae6cdd004b9813cc333529c54ef29abcb16f 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <asm/uaccess.h>
-#endif
-
 #include <linux/acpi.h>
 #include <linux/timer.h>
 #include <linux/jiffies.h>
@@ -67,11 +61,6 @@ static unsigned int cache_time = 1000;
 module_param(cache_time, uint, 0644);
 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
 
-extern struct proc_dir_entry *acpi_lock_ac_dir(void);
-extern struct proc_dir_entry *acpi_lock_battery_dir(void);
-extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
-extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
-
 #define MAX_SBS_BAT                    4
 #define ACPI_SBS_BLOCK_MAX             32
 
@@ -84,9 +73,6 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
 struct acpi_battery {
        struct power_supply bat;
        struct acpi_sbs *sbs;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       struct proc_dir_entry *proc_entry;
-#endif
        unsigned long update_time;
        char name[8];
        char manufacturer_name[ACPI_SBS_BLOCK_MAX];
@@ -119,9 +105,6 @@ struct acpi_sbs {
        struct acpi_device *device;
        struct acpi_smb_hc *hc;
        struct mutex lock;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       struct proc_dir_entry *charger_entry;
-#endif
        struct acpi_battery battery[MAX_SBS_BAT];
        u8 batteries_supported:4;
        u8 manager_present:1;
@@ -481,261 +464,6 @@ static struct device_attribute alarm_attr = {
        .store = acpi_battery_alarm_store,
 };
 
-/* --------------------------------------------------------------------------
-                              FS Interface (/proc/acpi)
-   -------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ACPI_PROCFS_POWER
-/* Generic Routines */
-static int
-acpi_sbs_add_fs(struct proc_dir_entry **dir,
-               struct proc_dir_entry *parent_dir,
-               char *dir_name,
-               const struct file_operations *info_fops,
-               const struct file_operations *state_fops,
-               const struct file_operations *alarm_fops, void *data)
-{
-       printk(KERN_WARNING PREFIX "Deprecated procfs I/F for SBS is loaded,"
-                       " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
-       if (!*dir) {
-               *dir = proc_mkdir(dir_name, parent_dir);
-               if (!*dir) {
-                       return -ENODEV;
-               }
-       }
-
-       /* 'info' [R] */
-       if (info_fops)
-               proc_create_data(ACPI_SBS_FILE_INFO, S_IRUGO, *dir,
-                                info_fops, data);
-
-       /* 'state' [R] */
-       if (state_fops)
-               proc_create_data(ACPI_SBS_FILE_STATE, S_IRUGO, *dir,
-                                state_fops, data);
-
-       /* 'alarm' [R/W] */
-       if (alarm_fops)
-               proc_create_data(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir,
-                                alarm_fops, data);
-       return 0;
-}
-
-/* Smart Battery Interface */
-static struct proc_dir_entry *acpi_battery_dir = NULL;
-
-static inline char *acpi_battery_units(struct acpi_battery *battery)
-{
-       return acpi_battery_mode(battery) ? " mW" : " mA";
-}
-
-
-static int acpi_battery_read_info(struct seq_file *seq, void *offset)
-{
-       struct acpi_battery *battery = seq->private;
-       struct acpi_sbs *sbs = battery->sbs;
-       int result = 0;
-
-       mutex_lock(&sbs->lock);
-
-       seq_printf(seq, "present:                 %s\n",
-                  (battery->present) ? "yes" : "no");
-       if (!battery->present)
-               goto end;
-
-       seq_printf(seq, "design capacity:         %i%sh\n",
-                  battery->design_capacity * acpi_battery_scale(battery),
-                  acpi_battery_units(battery));
-       seq_printf(seq, "last full capacity:      %i%sh\n",
-                  battery->full_charge_capacity * acpi_battery_scale(battery),
-                  acpi_battery_units(battery));
-       seq_printf(seq, "battery technology:      rechargeable\n");
-       seq_printf(seq, "design voltage:          %i mV\n",
-                  battery->design_voltage * acpi_battery_vscale(battery));
-       seq_printf(seq, "design capacity warning: unknown\n");
-       seq_printf(seq, "design capacity low:     unknown\n");
-       seq_printf(seq, "cycle count:             %i\n", battery->cycle_count);
-       seq_printf(seq, "capacity granularity 1:  unknown\n");
-       seq_printf(seq, "capacity granularity 2:  unknown\n");
-       seq_printf(seq, "model number:            %s\n", battery->device_name);
-       seq_printf(seq, "serial number:           %i\n",
-                  battery->serial_number);
-       seq_printf(seq, "battery type:            %s\n",
-                  battery->device_chemistry);
-       seq_printf(seq, "OEM info:                %s\n",
-                  battery->manufacturer_name);
-      end:
-       mutex_unlock(&sbs->lock);
-       return result;
-}
-
-static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_battery_read_info, PDE_DATA(inode));
-}
-
-static int acpi_battery_read_state(struct seq_file *seq, void *offset)
-{
-       struct acpi_battery *battery = seq->private;
-       struct acpi_sbs *sbs = battery->sbs;
-       int rate;
-
-       mutex_lock(&sbs->lock);
-       seq_printf(seq, "present:                 %s\n",
-                  (battery->present) ? "yes" : "no");
-       if (!battery->present)
-               goto end;
-
-       acpi_battery_get_state(battery);
-       seq_printf(seq, "capacity state:          %s\n",
-                  (battery->state & 0x0010) ? "critical" : "ok");
-       seq_printf(seq, "charging state:          %s\n",
-                  (battery->rate_now < 0) ? "discharging" :
-                  ((battery->rate_now > 0) ? "charging" : "charged"));
-       rate = abs(battery->rate_now) * acpi_battery_ipscale(battery);
-       rate *= (acpi_battery_mode(battery))?(battery->voltage_now *
-                       acpi_battery_vscale(battery)/1000):1;
-       seq_printf(seq, "present rate:            %d%s\n", rate,
-                  acpi_battery_units(battery));
-       seq_printf(seq, "remaining capacity:      %i%sh\n",
-                  battery->capacity_now * acpi_battery_scale(battery),
-                  acpi_battery_units(battery));
-       seq_printf(seq, "present voltage:         %i mV\n",
-                  battery->voltage_now * acpi_battery_vscale(battery));
-
-      end:
-       mutex_unlock(&sbs->lock);
-       return 0;
-}
-
-static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_battery_read_state, PDE_DATA(inode));
-}
-
-static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
-{
-       struct acpi_battery *battery = seq->private;
-       struct acpi_sbs *sbs = battery->sbs;
-       int result = 0;
-
-       mutex_lock(&sbs->lock);
-
-       if (!battery->present) {
-               seq_printf(seq, "present:                 no\n");
-               goto end;
-       }
-
-       acpi_battery_get_alarm(battery);
-       seq_printf(seq, "alarm:                   ");
-       if (battery->alarm_capacity)
-               seq_printf(seq, "%i%sh\n",
-                          battery->alarm_capacity *
-                          acpi_battery_scale(battery),
-                          acpi_battery_units(battery));
-       else
-               seq_printf(seq, "disabled\n");
-      end:
-       mutex_unlock(&sbs->lock);
-       return result;
-}
-
-static ssize_t
-acpi_battery_write_alarm(struct file *file, const char __user * buffer,
-                        size_t count, loff_t * ppos)
-{
-       struct seq_file *seq = file->private_data;
-       struct acpi_battery *battery = seq->private;
-       struct acpi_sbs *sbs = battery->sbs;
-       char alarm_string[12] = { '\0' };
-       int result = 0;
-       mutex_lock(&sbs->lock);
-       if (!battery->present) {
-               result = -ENODEV;
-               goto end;
-       }
-       if (count > sizeof(alarm_string) - 1) {
-               result = -EINVAL;
-               goto end;
-       }
-       if (copy_from_user(alarm_string, buffer, count)) {
-               result = -EFAULT;
-               goto end;
-       }
-       alarm_string[count] = 0;
-       battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) /
-                                       acpi_battery_scale(battery);
-       acpi_battery_set_alarm(battery);
-      end:
-       mutex_unlock(&sbs->lock);
-       if (result)
-               return result;
-       return count;
-}
-
-static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_battery_read_alarm, PDE_DATA(inode));
-}
-
-static const struct file_operations acpi_battery_info_fops = {
-       .open = acpi_battery_info_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-static const struct file_operations acpi_battery_state_fops = {
-       .open = acpi_battery_state_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-static const struct file_operations acpi_battery_alarm_fops = {
-       .open = acpi_battery_alarm_open_fs,
-       .read = seq_read,
-       .write = acpi_battery_write_alarm,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-/* Legacy AC Adapter Interface */
-
-static struct proc_dir_entry *acpi_ac_dir = NULL;
-
-static int acpi_ac_read_state(struct seq_file *seq, void *offset)
-{
-
-       struct acpi_sbs *sbs = seq->private;
-
-       mutex_lock(&sbs->lock);
-
-       seq_printf(seq, "state:                   %s\n",
-                  sbs->charger_present ? "on-line" : "off-line");
-
-       mutex_unlock(&sbs->lock);
-       return 0;
-}
-
-static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_ac_read_state, PDE_DATA(inode));
-}
-
-static const struct file_operations acpi_ac_state_fops = {
-       .open = acpi_ac_state_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-#endif
-
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -781,12 +509,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
                return result;
 
        sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
-                       battery->name, &acpi_battery_info_fops,
-                       &acpi_battery_state_fops, &acpi_battery_alarm_fops,
-                       battery);
-#endif
        battery->bat.name = battery->name;
        battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
        if (!acpi_battery_mode(battery)) {
@@ -822,10 +544,6 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
                        device_remove_file(battery->bat.dev, &alarm_attr);
                power_supply_unregister(&battery->bat);
        }
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       proc_remove(battery->proc_entry);
-       battery->proc_entry = NULL;
-#endif
 }
 
 static int acpi_charger_add(struct acpi_sbs *sbs)
@@ -835,13 +553,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
        result = acpi_ac_get_present(sbs);
        if (result)
                goto end;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
-                                ACPI_AC_DIR_NAME, NULL,
-                                &acpi_ac_state_fops, NULL, sbs);
-       if (result)
-               goto end;
-#endif
+
        sbs->charger.name = "sbs-charger";
        sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
        sbs->charger.properties = sbs_ac_props;
@@ -859,10 +571,6 @@ static void acpi_charger_remove(struct acpi_sbs *sbs)
 {
        if (sbs->charger.dev)
                power_supply_unregister(&sbs->charger);
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       proc_remove(sbs->charger_entry);
-       sbs->charger_entry = NULL;
-#endif
 }
 
 static void acpi_sbs_callback(void *context)
@@ -950,20 +658,6 @@ static int acpi_sbs_remove(struct acpi_device *device)
        return 0;
 }
 
-static void acpi_sbs_rmdirs(void)
-{
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       if (acpi_ac_dir) {
-               acpi_unlock_ac_dir(acpi_ac_dir);
-               acpi_ac_dir = NULL;
-       }
-       if (acpi_battery_dir) {
-               acpi_unlock_battery_dir(acpi_battery_dir);
-               acpi_battery_dir = NULL;
-       }
-#endif
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int acpi_sbs_resume(struct device *dev)
 {
@@ -995,28 +689,17 @@ static int __init acpi_sbs_init(void)
 
        if (acpi_disabled)
                return -ENODEV;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_ac_dir = acpi_lock_ac_dir();
-       if (!acpi_ac_dir)
-               return -ENODEV;
-       acpi_battery_dir = acpi_lock_battery_dir();
-       if (!acpi_battery_dir) {
-               acpi_sbs_rmdirs();
-               return -ENODEV;
-       }
-#endif
+
        result = acpi_bus_register_driver(&acpi_sbs_driver);
-       if (result < 0) {
-               acpi_sbs_rmdirs();
+       if (result < 0)
                return -ENODEV;
-       }
+
        return 0;
 }
 
 static void __exit acpi_sbs_exit(void)
 {
        acpi_bus_unregister_driver(&acpi_sbs_driver);
-       acpi_sbs_rmdirs();
        return;
 }
 
index 407ad13cac2f27945c3b812f791a4f615c2db492..fee8a297c7d95310caa64492b75e6c2fae0c280e 100644 (file)
@@ -999,7 +999,6 @@ int acpi_device_add(struct acpi_device *device,
        INIT_LIST_HEAD(&device->wakeup_list);
        INIT_LIST_HEAD(&device->physical_node_list);
        mutex_init(&device->physical_node_lock);
-       INIT_LIST_HEAD(&device->power_dependent);
 
        new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
        if (!new_bus_id) {
index 05306a59aedc18b45dd89f636d907def41d67d11..db5293650f622108e80a09124097f469c727547f 100644 (file)
@@ -564,6 +564,7 @@ static ssize_t counter_set(struct kobject *kobj,
        acpi_event_status status;
        acpi_handle handle;
        int result = 0;
+       unsigned long tmp;
 
        if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
                int i;
@@ -596,8 +597,10 @@ static ssize_t counter_set(struct kobject *kobj,
                else if (!strcmp(buf, "clear\n") &&
                         (status & ACPI_EVENT_FLAG_SET))
                        result = acpi_clear_gpe(handle, index);
+               else if (!kstrtoul(buf, 0, &tmp))
+                       all_counters[index].count = tmp;
                else
-                       all_counters[index].count = strtoul(buf, NULL, 0);
+                       result = -EINVAL;
        } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
                int event = index - num_gpes;
                if (!strcmp(buf, "disable\n") &&
@@ -609,8 +612,10 @@ static ssize_t counter_set(struct kobject *kobj,
                else if (!strcmp(buf, "clear\n") &&
                         (status & ACPI_EVENT_FLAG_SET))
                        result = acpi_clear_event(event);
+               else if (!kstrtoul(buf, 0, &tmp))
+                       all_counters[index].count = tmp;
                else
-                       all_counters[index].count = strtoul(buf, NULL, 0);
+                       result = -EINVAL;
        } else
                all_counters[index].count = strtoul(buf, NULL, 0);
 
@@ -762,13 +767,8 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
        if (!hotplug_kobj)
                goto err_out;
 
-       kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype);
-       error = kobject_set_name(&hotplug->kobj, "%s", name);
-       if (error)
-               goto err_out;
-
-       hotplug->kobj.parent = hotplug_kobj;
-       error = kobject_add(&hotplug->kobj, hotplug_kobj, NULL);
+       error = kobject_init_and_add(&hotplug->kobj,
+               &acpi_hotplug_profile_ktype, hotplug_kobj, "%s", name);
        if (error)
                goto err_out;
 
index 6a0329340b42ad188add760db66ebcc17ba9ab22..e600b5dbfcb6028e7aa49953d53d60e14b167043 100644 (file)
@@ -299,8 +299,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                          "No critical threshold\n"));
                } else if (tmp <= 2732) {
-                       printk(KERN_WARNING FW_BUG "Invalid critical threshold "
-                              "(%llu)\n", tmp);
+                       pr_warn(FW_BUG "Invalid critical threshold (%llu)\n",
+                               tmp);
                        tz->trips.critical.flags.valid = 0;
                } else {
                        tz->trips.critical.flags.valid = 1;
@@ -317,8 +317,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                                 * Allow override critical threshold
                                 */
                                if (crt_k > tz->trips.critical.temperature)
-                                       printk(KERN_WARNING PREFIX
-                                               "Critical threshold %d C\n", crt);
+                                       pr_warn(PREFIX "Critical threshold %d C\n",
+                                               crt);
                                tz->trips.critical.temperature = crt_k;
                        }
                }
@@ -390,8 +390,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                status = acpi_evaluate_reference(tz->device->handle, "_PSL",
                                                        NULL, &devices);
                if (ACPI_FAILURE(status)) {
-                       printk(KERN_WARNING PREFIX
-                               "Invalid passive threshold\n");
+                       pr_warn(PREFIX "Invalid passive threshold\n");
                        tz->trips.passive.flags.valid = 0;
                }
                else
@@ -453,8 +452,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                        status = acpi_evaluate_reference(tz->device->handle,
                                                name, NULL, &devices);
                        if (ACPI_FAILURE(status)) {
-                               printk(KERN_WARNING PREFIX
-                                       "Invalid active%d threshold\n", i);
+                               pr_warn(PREFIX "Invalid active%d threshold\n",
+                                       i);
                                tz->trips.active[i].flags.valid = 0;
                        }
                        else
@@ -505,7 +504,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
                valid |= tz->trips.active[i].flags.valid;
 
        if (!valid) {
-               printk(KERN_WARNING FW_BUG "No valid trip found\n");
+               pr_warn(FW_BUG "No valid trip found\n");
                return -ENODEV;
        }
        return 0;
@@ -923,8 +922,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
                                  acpi_bus_private_data_handler,
                                  tz->thermal_zone);
        if (ACPI_FAILURE(status)) {
-               printk(KERN_ERR PREFIX
-                               "Error attaching device data\n");
+               pr_err(PREFIX "Error attaching device data\n");
                return -ENODEV;
        }
 
@@ -1094,9 +1092,8 @@ static int acpi_thermal_add(struct acpi_device *device)
        if (result)
                goto free_memory;
 
-       printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
-              acpi_device_name(device), acpi_device_bid(device),
-              KELVIN_TO_CELSIUS(tz->temperature));
+       pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
+               acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature));
        goto end;
 
 free_memory:
@@ -1159,24 +1156,24 @@ static int acpi_thermal_resume(struct device *dev)
 static int thermal_act(const struct dmi_system_id *d) {
 
        if (act == 0) {
-               printk(KERN_NOTICE "ACPI: %s detected: "
-                       "disabling all active thermal trip points\n", d->ident);
+               pr_notice(PREFIX "%s detected: "
+                         "disabling all active thermal trip points\n", d->ident);
                act = -1;
        }
        return 0;
 }
 static int thermal_nocrt(const struct dmi_system_id *d) {
 
-       printk(KERN_NOTICE "ACPI: %s detected: "
-               "disabling all critical thermal trip point actions.\n", d->ident);
+       pr_notice(PREFIX "%s detected: "
+                 "disabling all critical thermal trip point actions.\n", d->ident);
        nocrt = 1;
        return 0;
 }
 static int thermal_tzp(const struct dmi_system_id *d) {
 
        if (tzp == 0) {
-               printk(KERN_NOTICE "ACPI: %s detected: "
-                       "enabling thermal zone polling\n", d->ident);
+               pr_notice(PREFIX "%s detected: "
+                         "enabling thermal zone polling\n", d->ident);
                tzp = 300;      /* 300 dS = 30 Seconds */
        }
        return 0;
@@ -1184,8 +1181,8 @@ static int thermal_tzp(const struct dmi_system_id *d) {
 static int thermal_psv(const struct dmi_system_id *d) {
 
        if (psv == 0) {
-               printk(KERN_NOTICE "ACPI: %s detected: "
-                       "disabling all passive thermal trip points\n", d->ident);
+               pr_notice(PREFIX "%s detected: "
+                         "disabling all passive thermal trip points\n", d->ident);
                psv = -1;
        }
        return 0;
@@ -1238,7 +1235,7 @@ static int __init acpi_thermal_init(void)
        dmi_check_system(thermal_dmi_table);
 
        if (off) {
-               printk(KERN_NOTICE "ACPI: thermal control disabled\n");
+               pr_notice(PREFIX "thermal control disabled\n");
                return -ENODEV;
        }
 
index 552248b0005b01a241ab511e52eef08a1c15d244..6d408bfbbb1d0c66dbef28d02137dbda0777d9f4 100644 (file)
@@ -121,7 +121,7 @@ acpi_extract_package(union acpi_object *package,
                                break;
                        default:
                                printk(KERN_WARNING PREFIX "Invalid package element"
-                                             " [%d]: got number, expecing"
+                                             " [%d]: got number, expecting"
                                              " [%c]\n",
                                              i, format_string[i]);
                                return AE_BAD_DATA;
@@ -148,7 +148,7 @@ acpi_extract_package(union acpi_object *package,
                        default:
                                printk(KERN_WARNING PREFIX "Invalid package element"
                                              " [%d] got string/buffer,"
-                                             " expecing [%c]\n",
+                                             " expecting [%c]\n",
                                              i, format_string[i]);
                                return AE_BAD_DATA;
                                break;
@@ -169,11 +169,20 @@ acpi_extract_package(union acpi_object *package,
        /*
         * Validate output buffer.
         */
-       if (buffer->length < size_required) {
+       if (buffer->length == ACPI_ALLOCATE_BUFFER) {
+               buffer->pointer = ACPI_ALLOCATE(size_required);
+               if (!buffer->pointer)
+                       return AE_NO_MEMORY;
                buffer->length = size_required;
-               return AE_BUFFER_OVERFLOW;
-       } else if (buffer->length != size_required || !buffer->pointer) {
-               return AE_BAD_PARAMETER;
+               memset(buffer->pointer, 0, size_required);
+       } else {
+               if (buffer->length < size_required) {
+                       buffer->length = size_required;
+                       return AE_BUFFER_OVERFLOW;
+               } else if (buffer->length != size_required ||
+                          !buffer->pointer) {
+                       return AE_BAD_PARAMETER;
+               }
        }
 
        head = buffer->pointer;
index aebcf6355df467e3c394c00fa5c48731e42cc18d..18dbdff4656e7d6c6b8f665e9fcdb2e22067cf98 100644 (file)
@@ -88,7 +88,16 @@ module_param(allow_duplicates, bool, 0644);
 static bool use_bios_initial_backlight = 1;
 module_param(use_bios_initial_backlight, bool, 0644);
 
+/*
+ * For Windows 8 systems: if set ture and the GPU driver has
+ * registered a backlight interface, skip registering ACPI video's.
+ */
+static bool use_native_backlight = false;
+module_param(use_native_backlight, bool, 0644);
+
 static int register_count;
+static struct mutex video_list_lock;
+static struct list_head video_bus_head;
 static int acpi_video_bus_add(struct acpi_device *device);
 static int acpi_video_bus_remove(struct acpi_device *device);
 static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
@@ -157,6 +166,7 @@ struct acpi_video_bus {
        struct acpi_video_bus_flags flags;
        struct list_head video_device_list;
        struct mutex device_list_lock;  /* protects video_device_list */
+       struct list_head entry;
        struct input_dev *input;
        char phys[32];  /* for input device */
        struct notifier_block pm_nb;
@@ -229,6 +239,14 @@ static int acpi_video_get_next_level(struct acpi_video_device *device,
 static int acpi_video_switch_brightness(struct acpi_video_device *device,
                                         int event);
 
+static bool acpi_video_verify_backlight_support(void)
+{
+       if (acpi_osi_is_win8() && use_native_backlight &&
+           backlight_device_registered(BACKLIGHT_RAW))
+               return false;
+       return acpi_video_backlight_support();
+}
+
 /* backlight device sysfs support */
 static int acpi_video_get_brightness(struct backlight_device *bd)
 {
@@ -830,9 +848,9 @@ acpi_video_init_brightness(struct acpi_video_device *device)
                 * or an index). Set the backlight to max_level in this case.
                 */
                for (i = 2; i < br->count; i++)
-                       if (level_old == br->levels[i])
+                       if (level == br->levels[i])
                                break;
-               if (i == br->count)
+               if (i == br->count || !level)
                        level = max_level;
        }
 
@@ -884,79 +902,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 
        if (acpi_has_method(device->dev->handle, "_DDC"))
                device->cap._DDC = 1;
-
-       if (acpi_video_backlight_support()) {
-               struct backlight_properties props;
-               struct pci_dev *pdev;
-               acpi_handle acpi_parent;
-               struct device *parent = NULL;
-               int result;
-               static int count;
-               char *name;
-
-               result = acpi_video_init_brightness(device);
-               if (result)
-                       return;
-               name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
-               if (!name)
-                       return;
-               count++;
-
-               acpi_get_parent(device->dev->handle, &acpi_parent);
-
-               pdev = acpi_get_pci_dev(acpi_parent);
-               if (pdev) {
-                       parent = &pdev->dev;
-                       pci_dev_put(pdev);
-               }
-
-               memset(&props, 0, sizeof(struct backlight_properties));
-               props.type = BACKLIGHT_FIRMWARE;
-               props.max_brightness = device->brightness->count - 3;
-               device->backlight = backlight_device_register(name,
-                                                             parent,
-                                                             device,
-                                                             &acpi_backlight_ops,
-                                                             &props);
-               kfree(name);
-               if (IS_ERR(device->backlight))
-                       return;
-
-               /*
-                * Save current brightness level in case we have to restore it
-                * before acpi_video_device_lcd_set_level() is called next time.
-                */
-               device->backlight->props.brightness =
-                               acpi_video_get_brightness(device->backlight);
-
-               device->cooling_dev = thermal_cooling_device_register("LCD",
-                                       device->dev, &video_cooling_ops);
-               if (IS_ERR(device->cooling_dev)) {
-                       /*
-                        * Set cooling_dev to NULL so we don't crash trying to
-                        * free it.
-                        * Also, why the hell we are returning early and
-                        * not attempt to register video output if cooling
-                        * device registration failed?
-                        * -- dtor
-                        */
-                       device->cooling_dev = NULL;
-                       return;
-               }
-
-               dev_info(&device->dev->dev, "registered as cooling_device%d\n",
-                        device->cooling_dev->id);
-               result = sysfs_create_link(&device->dev->dev.kobj,
-                               &device->cooling_dev->device.kobj,
-                               "thermal_cooling");
-               if (result)
-                       printk(KERN_ERR PREFIX "Create sysfs link\n");
-               result = sysfs_create_link(&device->cooling_dev->device.kobj,
-                               &device->dev->dev.kobj, "device");
-               if (result)
-                       printk(KERN_ERR PREFIX "Create sysfs link\n");
-
-       }
 }
 
 /*
@@ -1143,13 +1088,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
        acpi_video_device_bind(video, data);
        acpi_video_device_find_cap(data);
 
-       status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
-                                            acpi_video_device_notify, data);
-       if (ACPI_FAILURE(status))
-               dev_err(&device->dev, "Error installing notify handler\n");
-       else
-               data->flags.notify = 1;
-
        mutex_lock(&video->device_list_lock);
        list_add_tail(&data->entry, &video->video_device_list);
        mutex_unlock(&video->device_list_lock);
@@ -1333,8 +1271,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
        unsigned long long level_current, level_next;
        int result = -EINVAL;
 
-       /* no warning message if acpi_backlight=vendor is used */
-       if (!acpi_video_backlight_support())
+       /* no warning message if acpi_backlight=vendor or a quirk is used */
+       if (!acpi_video_verify_backlight_support())
                return 0;
 
        if (!device->brightness)
@@ -1454,64 +1392,6 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
        return status;
 }
 
-static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
-{
-       acpi_status status;
-
-       if (!device || !device->video)
-               return -ENOENT;
-
-       if (device->flags.notify) {
-               status = acpi_remove_notify_handler(device->dev->handle,
-                               ACPI_DEVICE_NOTIFY, acpi_video_device_notify);
-               if (ACPI_FAILURE(status))
-                       dev_err(&device->dev->dev,
-                                       "Can't remove video notify handler\n");
-       }
-
-       if (device->backlight) {
-               backlight_device_unregister(device->backlight);
-               device->backlight = NULL;
-       }
-       if (device->cooling_dev) {
-               sysfs_remove_link(&device->dev->dev.kobj,
-                                 "thermal_cooling");
-               sysfs_remove_link(&device->cooling_dev->device.kobj,
-                                 "device");
-               thermal_cooling_device_unregister(device->cooling_dev);
-               device->cooling_dev = NULL;
-       }
-
-       return 0;
-}
-
-static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
-{
-       int status;
-       struct acpi_video_device *dev, *next;
-
-       mutex_lock(&video->device_list_lock);
-
-       list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
-
-               status = acpi_video_bus_put_one_device(dev);
-               if (ACPI_FAILURE(status))
-                       printk(KERN_WARNING PREFIX
-                              "hhuuhhuu bug in acpi video driver.\n");
-
-               if (dev->brightness) {
-                       kfree(dev->brightness->levels);
-                       kfree(dev->brightness);
-               }
-               list_del(&dev->entry);
-               kfree(dev);
-       }
-
-       mutex_unlock(&video->device_list_lock);
-
-       return 0;
-}
-
 /* acpi_video interface */
 
 /*
@@ -1521,13 +1401,13 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
 static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
 {
        return acpi_video_bus_DOS(video, 0,
-                                 acpi_video_backlight_quirks() ? 1 : 0);
+                                 acpi_osi_is_win8() ? 1 : 0);
 }
 
 static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
 {
        return acpi_video_bus_DOS(video, 0,
-                                 acpi_video_backlight_quirks() ? 0 : 1);
+                                 acpi_osi_is_win8() ? 0 : 1);
 }
 
 static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
@@ -1536,7 +1416,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
        struct input_dev *input;
        int keycode = 0;
 
-       if (!video)
+       if (!video || !video->input)
                return;
 
        input = video->input;
@@ -1691,12 +1571,236 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
        return AE_OK;
 }
 
+static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
+{
+       if (acpi_video_verify_backlight_support()) {
+               struct backlight_properties props;
+               struct pci_dev *pdev;
+               acpi_handle acpi_parent;
+               struct device *parent = NULL;
+               int result;
+               static int count;
+               char *name;
+
+               result = acpi_video_init_brightness(device);
+               if (result)
+                       return;
+               name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
+               if (!name)
+                       return;
+               count++;
+
+               acpi_get_parent(device->dev->handle, &acpi_parent);
+
+               pdev = acpi_get_pci_dev(acpi_parent);
+               if (pdev) {
+                       parent = &pdev->dev;
+                       pci_dev_put(pdev);
+               }
+
+               memset(&props, 0, sizeof(struct backlight_properties));
+               props.type = BACKLIGHT_FIRMWARE;
+               props.max_brightness = device->brightness->count - 3;
+               device->backlight = backlight_device_register(name,
+                                                             parent,
+                                                             device,
+                                                             &acpi_backlight_ops,
+                                                             &props);
+               kfree(name);
+               if (IS_ERR(device->backlight))
+                       return;
+
+               /*
+                * Save current brightness level in case we have to restore it
+                * before acpi_video_device_lcd_set_level() is called next time.
+                */
+               device->backlight->props.brightness =
+                               acpi_video_get_brightness(device->backlight);
+
+               device->cooling_dev = thermal_cooling_device_register("LCD",
+                                       device->dev, &video_cooling_ops);
+               if (IS_ERR(device->cooling_dev)) {
+                       /*
+                        * Set cooling_dev to NULL so we don't crash trying to
+                        * free it.
+                        * Also, why the hell we are returning early and
+                        * not attempt to register video output if cooling
+                        * device registration failed?
+                        * -- dtor
+                        */
+                       device->cooling_dev = NULL;
+                       return;
+               }
+
+               dev_info(&device->dev->dev, "registered as cooling_device%d\n",
+                        device->cooling_dev->id);
+               result = sysfs_create_link(&device->dev->dev.kobj,
+                               &device->cooling_dev->device.kobj,
+                               "thermal_cooling");
+               if (result)
+                       printk(KERN_ERR PREFIX "Create sysfs link\n");
+               result = sysfs_create_link(&device->cooling_dev->device.kobj,
+                               &device->dev->dev.kobj, "device");
+               if (result)
+                       printk(KERN_ERR PREFIX "Create sysfs link\n");
+       }
+}
+
+static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
+{
+       struct acpi_video_device *dev;
+
+       mutex_lock(&video->device_list_lock);
+       list_for_each_entry(dev, &video->video_device_list, entry)
+               acpi_video_dev_register_backlight(dev);
+       mutex_unlock(&video->device_list_lock);
+
+       video->pm_nb.notifier_call = acpi_video_resume;
+       video->pm_nb.priority = 0;
+       return register_pm_notifier(&video->pm_nb);
+}
+
+static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device)
+{
+       if (device->backlight) {
+               backlight_device_unregister(device->backlight);
+               device->backlight = NULL;
+       }
+       if (device->brightness) {
+               kfree(device->brightness->levels);
+               kfree(device->brightness);
+               device->brightness = NULL;
+       }
+       if (device->cooling_dev) {
+               sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling");
+               sysfs_remove_link(&device->cooling_dev->device.kobj, "device");
+               thermal_cooling_device_unregister(device->cooling_dev);
+               device->cooling_dev = NULL;
+       }
+}
+
+static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video)
+{
+       struct acpi_video_device *dev;
+       int error = unregister_pm_notifier(&video->pm_nb);
+
+       mutex_lock(&video->device_list_lock);
+       list_for_each_entry(dev, &video->video_device_list, entry)
+               acpi_video_dev_unregister_backlight(dev);
+       mutex_unlock(&video->device_list_lock);
+
+       return error;
+}
+
+static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device)
+{
+       acpi_status status;
+       struct acpi_device *adev = device->dev;
+
+       status = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
+                                            acpi_video_device_notify, device);
+       if (ACPI_FAILURE(status))
+               dev_err(&adev->dev, "Error installing notify handler\n");
+       else
+               device->flags.notify = 1;
+}
+
+static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video)
+{
+       struct input_dev *input;
+       struct acpi_video_device *dev;
+       int error;
+
+       video->input = input = input_allocate_device();
+       if (!input) {
+               error = -ENOMEM;
+               goto out;
+       }
+
+       error = acpi_video_bus_start_devices(video);
+       if (error)
+               goto err_free_input;
+
+       snprintf(video->phys, sizeof(video->phys),
+                       "%s/video/input0", acpi_device_hid(video->device));
+
+       input->name = acpi_device_name(video->device);
+       input->phys = video->phys;
+       input->id.bustype = BUS_HOST;
+       input->id.product = 0x06;
+       input->dev.parent = &video->device->dev;
+       input->evbit[0] = BIT(EV_KEY);
+       set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
+       set_bit(KEY_VIDEO_NEXT, input->keybit);
+       set_bit(KEY_VIDEO_PREV, input->keybit);
+       set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit);
+       set_bit(KEY_BRIGHTNESSUP, input->keybit);
+       set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
+       set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
+       set_bit(KEY_DISPLAY_OFF, input->keybit);
+
+       error = input_register_device(input);
+       if (error)
+               goto err_stop_dev;
+
+       mutex_lock(&video->device_list_lock);
+       list_for_each_entry(dev, &video->video_device_list, entry)
+               acpi_video_dev_add_notify_handler(dev);
+       mutex_unlock(&video->device_list_lock);
+
+       return 0;
+
+err_stop_dev:
+       acpi_video_bus_stop_devices(video);
+err_free_input:
+       input_free_device(input);
+       video->input = NULL;
+out:
+       return error;
+}
+
+static void acpi_video_dev_remove_notify_handler(struct acpi_video_device *dev)
+{
+       if (dev->flags.notify) {
+               acpi_remove_notify_handler(dev->dev->handle, ACPI_DEVICE_NOTIFY,
+                                          acpi_video_device_notify);
+               dev->flags.notify = 0;
+       }
+}
+
+static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video)
+{
+       struct acpi_video_device *dev;
+
+       mutex_lock(&video->device_list_lock);
+       list_for_each_entry(dev, &video->video_device_list, entry)
+               acpi_video_dev_remove_notify_handler(dev);
+       mutex_unlock(&video->device_list_lock);
+
+       acpi_video_bus_stop_devices(video);
+       input_unregister_device(video->input);
+       video->input = NULL;
+}
+
+static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
+{
+       struct acpi_video_device *dev, *next;
+
+       mutex_lock(&video->device_list_lock);
+       list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
+               list_del(&dev->entry);
+               kfree(dev);
+       }
+       mutex_unlock(&video->device_list_lock);
+
+       return 0;
+}
+
 static int instance;
 
 static int acpi_video_bus_add(struct acpi_device *device)
 {
        struct acpi_video_bus *video;
-       struct input_dev *input;
        int error;
        acpi_status status;
 
@@ -1748,62 +1852,24 @@ static int acpi_video_bus_add(struct acpi_device *device)
        if (error)
                goto err_put_video;
 
-       video->input = input = input_allocate_device();
-       if (!input) {
-               error = -ENOMEM;
-               goto err_put_video;
-       }
-
-       error = acpi_video_bus_start_devices(video);
-       if (error)
-               goto err_free_input_dev;
-
-       snprintf(video->phys, sizeof(video->phys),
-               "%s/video/input0", acpi_device_hid(video->device));
-
-       input->name = acpi_device_name(video->device);
-       input->phys = video->phys;
-       input->id.bustype = BUS_HOST;
-       input->id.product = 0x06;
-       input->dev.parent = &device->dev;
-       input->evbit[0] = BIT(EV_KEY);
-       set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
-       set_bit(KEY_VIDEO_NEXT, input->keybit);
-       set_bit(KEY_VIDEO_PREV, input->keybit);
-       set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit);
-       set_bit(KEY_BRIGHTNESSUP, input->keybit);
-       set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
-       set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
-       set_bit(KEY_DISPLAY_OFF, input->keybit);
-
        printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s  rom: %s  post: %s)\n",
               ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
               video->flags.multihead ? "yes" : "no",
               video->flags.rom ? "yes" : "no",
               video->flags.post ? "yes" : "no");
+       mutex_lock(&video_list_lock);
+       list_add_tail(&video->entry, &video_bus_head);
+       mutex_unlock(&video_list_lock);
 
-       video->pm_nb.notifier_call = acpi_video_resume;
-       video->pm_nb.priority = 0;
-       error = register_pm_notifier(&video->pm_nb);
-       if (error)
-               goto err_stop_video;
-
-       error = input_register_device(input);
-       if (error)
-               goto err_unregister_pm_notifier;
+       acpi_video_bus_register_backlight(video);
+       acpi_video_bus_add_notify_handler(video);
 
        return 0;
 
- err_unregister_pm_notifier:
-       unregister_pm_notifier(&video->pm_nb);
- err_stop_video:
-       acpi_video_bus_stop_devices(video);
- err_free_input_dev:
-       input_free_device(input);
- err_put_video:
+err_put_video:
        acpi_video_bus_put_devices(video);
        kfree(video->attached_array);
- err_free_video:
+err_free_video:
        kfree(video);
        device->driver_data = NULL;
 
@@ -1820,12 +1886,14 @@ static int acpi_video_bus_remove(struct acpi_device *device)
 
        video = acpi_driver_data(device);
 
-       unregister_pm_notifier(&video->pm_nb);
-
-       acpi_video_bus_stop_devices(video);
+       acpi_video_bus_remove_notify_handler(video);
+       acpi_video_bus_unregister_backlight(video);
        acpi_video_bus_put_devices(video);
 
-       input_unregister_device(video->input);
+       mutex_lock(&video_list_lock);
+       list_del(&video->entry);
+       mutex_unlock(&video_list_lock);
+
        kfree(video->attached_array);
        kfree(video);
 
@@ -1874,6 +1942,9 @@ int acpi_video_register(void)
                return 0;
        }
 
+       mutex_init(&video_list_lock);
+       INIT_LIST_HEAD(&video_bus_head);
+
        result = acpi_bus_register_driver(&acpi_video_bus);
        if (result < 0)
                return -ENODEV;
index 940edbf2fe8f4460b27fceb1e7fe5fdb7cbacfc3..84875fd4c74f9fbd100106ea3615ffcde2daf6cf 100644 (file)
@@ -168,6 +168,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
                },
        },
+       {
+       .callback = video_detect_force_vendor,
+       .ident = "Lenovo Yoga 13",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
+               },
+       },
        { },
 };
 
@@ -233,11 +241,11 @@ static void acpi_video_caps_check(void)
                acpi_video_get_capabilities(NULL);
 }
 
-bool acpi_video_backlight_quirks(void)
+bool acpi_osi_is_win8(void)
 {
        return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
 }
-EXPORT_SYMBOL(acpi_video_backlight_quirks);
+EXPORT_SYMBOL(acpi_osi_is_win8);
 
 /* Promote the vendor interface instead of the generic video module.
  * This function allow DMI blacklists to be implemented by externals
index 9d715ae5ff6b73b6bd09690b95e9686f196e9cdb..8e28f923cf7f3a221104eb625e4d3a89b5ab79ca 100644 (file)
@@ -1343,7 +1343,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
                host->flags |= ATA_HOST_PARALLEL_SCAN;
        else
-               printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
+               dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
 
        if (pi.flags & ATA_FLAG_EM)
                ahci_reset_em(host);
index 2daaee05cab12d629502c913ef7102a793cdf27f..7d3b85385bfc16b92ffe303acf38f343331dfc2e 100644 (file)
@@ -184,7 +184,7 @@ static int ahci_probe(struct platform_device *pdev)
        if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
                host->flags |= ATA_HOST_PARALLEL_SCAN;
        else
-               printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
+               dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
 
        if (pi.flags & ATA_FLAG_EM)
                ahci_reset_em(host);
index acfd0f711069e9da304c95179b14127e20ae1c9c..aaac4fb0d5645f8d52782fc55cb6f39da04830e7 100644 (file)
@@ -778,8 +778,16 @@ static void ahci_start_port(struct ata_port *ap)
                                rc = ap->ops->transmit_led_message(ap,
                                                               emp->led_state,
                                                               4);
+                               /*
+                                * If busy, give a breather but do not
+                                * release EH ownership by using msleep()
+                                * instead of ata_msleep().  EM Transmit
+                                * bit is busy for the whole host and
+                                * releasing ownership will cause other
+                                * ports to fail the same way.
+                                */
                                if (rc == -EBUSY)
-                                       ata_msleep(ap, 1);
+                                       msleep(1);
                                else
                                        break;
                        }
index 4ba8b04055728d49a0ac147a608d1ad27391d62a..ab714d2ad978644752ca3c9bdff74ae1c9f63934 100644 (file)
@@ -1035,17 +1035,3 @@ void ata_acpi_on_disable(struct ata_device *dev)
 {
        ata_acpi_clear_gtf(dev);
 }
-
-void ata_scsi_acpi_bind(struct ata_device *dev)
-{
-       acpi_handle handle = ata_dev_acpi_handle(dev);
-       if (handle)
-               acpi_dev_pm_add_dependent(handle, &dev->sdev->sdev_gendev);
-}
-
-void ata_scsi_acpi_unbind(struct ata_device *dev)
-{
-       acpi_handle handle = ata_dev_acpi_handle(dev);
-       if (handle)
-               acpi_dev_pm_remove_dependent(handle, &dev->sdev->sdev_gendev);
-}
index c69fcce505c03d06c7b20ae333ff9708a228f869..370462fa8e01addd3387befee8f4ea78486b2cc0 100644 (file)
@@ -1322,14 +1322,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);
 }
 
index 97a0cef1295916223202058b83e80a20de74c7de..db6dfcfa3e2ee932190069290814f2a71bc8f3f6 100644 (file)
@@ -3679,7 +3679,6 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
                        if (!IS_ERR(sdev)) {
                                dev->sdev = sdev;
                                scsi_device_put(sdev);
-                               ata_scsi_acpi_bind(dev);
                        } else {
                                dev->sdev = NULL;
                        }
@@ -3767,8 +3766,6 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
        struct scsi_device *sdev;
        unsigned long flags;
 
-       ata_scsi_acpi_unbind(dev);
-
        /* Alas, we need to grab scan_mutex to ensure SCSI device
         * state doesn't change underneath us and thus
         * scsi_device_get() always succeeds.  The mutex locking can
index eeeb77845d48574e3f43b4b6e456302e5f3926d9..45b5ab3a95d51158c9ef0e618d6c8ae0fdeb373b 100644 (file)
@@ -121,8 +121,6 @@ extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
 extern void ata_acpi_bind_port(struct ata_port *ap);
 extern void ata_acpi_bind_dev(struct ata_device *dev);
 extern acpi_handle ata_dev_acpi_handle(struct ata_device *dev);
-extern void ata_scsi_acpi_bind(struct ata_device *dev);
-extern void ata_scsi_acpi_unbind(struct ata_device *dev);
 #else
 static inline void ata_acpi_dissociate(struct ata_host *host) { }
 static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
@@ -133,8 +131,6 @@ static inline void ata_acpi_set_state(struct ata_port *ap,
                                      pm_message_t state) { }
 static inline void ata_acpi_bind_port(struct ata_port *ap) {}
 static inline void ata_acpi_bind_dev(struct ata_device *dev) {}
-static inline void ata_scsi_acpi_bind(struct ata_device *dev) {}
-static inline void ata_scsi_acpi_unbind(struct ata_device *dev) {}
 #endif
 
 /* libata-scsi.c */
index 4bceb8803a10f50baee31c9c39233282ebbc6e91..b33d1f99b3a44bb40e76a529a8eddbc2268bdc20 100644 (file)
@@ -78,7 +78,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
 
        ap->ioaddr.cmd_addr = cmd_addr;
 
-       if (pnp_port_valid(idev, 1) == 0) {
+       if (pnp_port_valid(idev, 1)) {
                ctl_addr = devm_ioport_map(&idev->dev,
                                           pnp_port_start(idev, 1), 1);
                ap->ioaddr.altstatus_addr = ctl_addr;
index 848ebbd25717269fa0ef34e1632e502eb29f4aeb..f48370dfc908e19a73a86cf817ad05128c0ed034 100644 (file)
@@ -44,13 +44,11 @@ static int __ref cpu_subsys_online(struct device *dev)
        struct cpu *cpu = container_of(dev, struct cpu, dev);
        int cpuid = dev->id;
        int from_nid, to_nid;
-       int ret = -ENODEV;
-
-       cpu_hotplug_driver_lock();
+       int ret;
 
        from_nid = cpu_to_node(cpuid);
        if (from_nid == NUMA_NO_NODE)
-               goto out;
+               return -ENODEV;
 
        ret = cpu_up(cpuid);
        /*
@@ -61,19 +59,12 @@ static int __ref cpu_subsys_online(struct device *dev)
        if (from_nid != to_nid)
                change_cpu_under_node(cpu, from_nid, to_nid);
 
- out:
-       cpu_hotplug_driver_unlock();
        return ret;
 }
 
 static int cpu_subsys_offline(struct device *dev)
 {
-       int ret;
-
-       cpu_hotplug_driver_lock();
-       ret = cpu_down(dev->id);
-       cpu_hotplug_driver_unlock();
-       return ret;
+       return cpu_down(dev->id);
 }
 
 void unregister_cpu(struct cpu *cpu)
@@ -93,7 +84,17 @@ static ssize_t cpu_probe_store(struct device *dev,
                               const char *buf,
                               size_t count)
 {
-       return arch_cpu_probe(buf, count);
+       ssize_t cnt;
+       int ret;
+
+       ret = lock_device_hotplug_sysfs();
+       if (ret)
+               return ret;
+
+       cnt = arch_cpu_probe(buf, count);
+
+       unlock_device_hotplug();
+       return cnt;
 }
 
 static ssize_t cpu_release_store(struct device *dev,
@@ -101,7 +102,17 @@ static ssize_t cpu_release_store(struct device *dev,
                                 const char *buf,
                                 size_t count)
 {
-       return arch_cpu_release(buf, count);
+       ssize_t cnt;
+       int ret;
+
+       ret = lock_device_hotplug_sysfs();
+       if (ret)
+               return ret;
+
+       cnt = arch_cpu_release(buf, count);
+
+       unlock_device_hotplug();
+       return cnt;
 }
 
 static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
index 9e59f6535c442bbb26d6ad055b93a4b0cf5bef5d..bece691cb5d99d79f761b9400eebf1e9a78c55a2 100644 (file)
@@ -333,8 +333,10 @@ store_mem_state(struct device *dev,
                online_type = ONLINE_KEEP;
        else if (!strncmp(buf, "offline", min_t(int, count, 7)))
                online_type = -1;
-       else
-               return -EINVAL;
+       else {
+               ret = -EINVAL;
+               goto err;
+       }
 
        switch (online_type) {
        case ONLINE_KERNEL:
@@ -357,6 +359,7 @@ store_mem_state(struct device *dev,
                ret = -EINVAL; /* should never happen */
        }
 
+err:
        unlock_device_hotplug();
 
        if (ret)
index 9f098a82cf04b061edb203fff718ef0ca70e6328..ee039afe90786510eb19e0a536beb30413b27a38 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/suspend.h>
 #include <trace/events/power.h>
 #include <linux/cpuidle.h>
+#include <linux/timer.h>
+
 #include "../base.h"
 #include "power.h"
 
@@ -390,6 +392,71 @@ static int dpm_run_callback(pm_callback_t cb, struct device *dev,
        return error;
 }
 
+#ifdef CONFIG_DPM_WATCHDOG
+struct dpm_watchdog {
+       struct device           *dev;
+       struct task_struct      *tsk;
+       struct timer_list       timer;
+};
+
+#define DECLARE_DPM_WATCHDOG_ON_STACK(wd) \
+       struct dpm_watchdog wd
+
+/**
+ * dpm_watchdog_handler - Driver suspend / resume watchdog handler.
+ * @data: Watchdog object address.
+ *
+ * Called when a driver has timed out suspending or resuming.
+ * There's not much we can do here to recover so panic() to
+ * capture a crash-dump in pstore.
+ */
+static void dpm_watchdog_handler(unsigned long data)
+{
+       struct dpm_watchdog *wd = (void *)data;
+
+       dev_emerg(wd->dev, "**** DPM device timeout ****\n");
+       show_stack(wd->tsk, NULL);
+       panic("%s %s: unrecoverable failure\n",
+               dev_driver_string(wd->dev), dev_name(wd->dev));
+}
+
+/**
+ * dpm_watchdog_set - Enable pm watchdog for given device.
+ * @wd: Watchdog. Must be allocated on the stack.
+ * @dev: Device to handle.
+ */
+static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
+{
+       struct timer_list *timer = &wd->timer;
+
+       wd->dev = dev;
+       wd->tsk = current;
+
+       init_timer_on_stack(timer);
+       /* use same timeout value for both suspend and resume */
+       timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_TIMEOUT;
+       timer->function = dpm_watchdog_handler;
+       timer->data = (unsigned long)wd;
+       add_timer(timer);
+}
+
+/**
+ * dpm_watchdog_clear - Disable suspend/resume watchdog.
+ * @wd: Watchdog to disable.
+ */
+static void dpm_watchdog_clear(struct dpm_watchdog *wd)
+{
+       struct timer_list *timer = &wd->timer;
+
+       del_timer_sync(timer);
+       destroy_timer_on_stack(timer);
+}
+#else
+#define DECLARE_DPM_WATCHDOG_ON_STACK(wd)
+#define dpm_watchdog_set(x, y)
+#define dpm_watchdog_clear(x)
+#endif
+
 /*------------------------- Resume routines -------------------------*/
 
 /**
@@ -576,6 +643,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
        pm_callback_t callback = NULL;
        char *info = NULL;
        int error = 0;
+       DECLARE_DPM_WATCHDOG_ON_STACK(wd);
 
        TRACE_DEVICE(dev);
        TRACE_RESUME(0);
@@ -584,6 +652,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
                goto Complete;
 
        dpm_wait(dev->parent, async);
+       dpm_watchdog_set(&wd, dev);
        device_lock(dev);
 
        /*
@@ -642,6 +711,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
 
  Unlock:
        device_unlock(dev);
+       dpm_watchdog_clear(&wd);
 
  Complete:
        complete_all(&dev->power.completion);
@@ -1060,6 +1130,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        pm_callback_t callback = NULL;
        char *info = NULL;
        int error = 0;
+       DECLARE_DPM_WATCHDOG_ON_STACK(wd);
 
        dpm_wait_for_children(dev, async);
 
@@ -1083,6 +1154,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        if (dev->power.syscore)
                goto Complete;
 
+       dpm_watchdog_set(&wd, dev);
        device_lock(dev);
 
        if (dev->pm_domain) {
@@ -1139,6 +1211,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        }
 
        device_unlock(dev);
+       dpm_watchdog_clear(&wd);
 
  Complete:
        complete_all(&dev->power.completion);
index ef89897c6043eec57ed2d8d1f4c6db464cfd92d1..fa41874184401cd46c155526102fb72aed99e329 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/list.h>
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/of.h>
 #include <linux/export.h>
 
@@ -42,7 +42,7 @@
  */
 
 /**
- * struct opp - Generic OPP description structure
+ * struct dev_pm_opp - Generic OPP description structure
  * @node:      opp list node. The nodes are maintained throughout the lifetime
  *             of boot. It is expected only an optimal set of OPPs are
  *             added to the library by the SoC framework.
@@ -59,7 +59,7 @@
  *
  * This structure stores the OPP information for a given device.
  */
-struct opp {
+struct dev_pm_opp {
        struct list_head node;
 
        bool available;
@@ -136,7 +136,7 @@ static struct device_opp *find_device_opp(struct device *dev)
 }
 
 /**
- * opp_get_voltage() - Gets the voltage corresponding to an available opp
+ * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an available opp
  * @opp:       opp for which voltage has to be returned for
  *
  * Return voltage in micro volt corresponding to the opp, else
@@ -150,9 +150,9 @@ static struct device_opp *find_device_opp(struct device *dev)
  * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
  * pointer.
  */
-unsigned long opp_get_voltage(struct opp *opp)
+unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
 {
-       struct opp *tmp_opp;
+       struct dev_pm_opp *tmp_opp;
        unsigned long v = 0;
 
        tmp_opp = rcu_dereference(opp);
@@ -163,10 +163,10 @@ unsigned long opp_get_voltage(struct opp *opp)
 
        return v;
 }
-EXPORT_SYMBOL_GPL(opp_get_voltage);
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_voltage);
 
 /**
- * opp_get_freq() - Gets the frequency corresponding to an available opp
+ * dev_pm_opp_get_freq() - Gets the frequency corresponding to an available opp
  * @opp:       opp for which frequency has to be returned for
  *
  * Return frequency in hertz corresponding to the opp, else
@@ -180,9 +180,9 @@ EXPORT_SYMBOL_GPL(opp_get_voltage);
  * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
  * pointer.
  */
-unsigned long opp_get_freq(struct opp *opp)
+unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 {
-       struct opp *tmp_opp;
+       struct dev_pm_opp *tmp_opp;
        unsigned long f = 0;
 
        tmp_opp = rcu_dereference(opp);
@@ -193,10 +193,10 @@ unsigned long opp_get_freq(struct opp *opp)
 
        return f;
 }
-EXPORT_SYMBOL_GPL(opp_get_freq);
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 /**
- * opp_get_opp_count() - Get number of opps available in the opp list
+ * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list
  * @dev:       device for which we do this operation
  *
  * This function returns the number of available opps if there are any,
@@ -206,10 +206,10 @@ EXPORT_SYMBOL_GPL(opp_get_freq);
  * internally references two RCU protected structures: device_opp and opp which
  * are safe as long as we are under a common RCU locked section.
  */
-int opp_get_opp_count(struct device *dev)
+int dev_pm_opp_get_opp_count(struct device *dev)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp;
+       struct dev_pm_opp *temp_opp;
        int count = 0;
 
        dev_opp = find_device_opp(dev);
@@ -226,10 +226,10 @@ int opp_get_opp_count(struct device *dev)
 
        return count;
 }
-EXPORT_SYMBOL_GPL(opp_get_opp_count);
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count);
 
 /**
- * opp_find_freq_exact() - search for an exact frequency
+ * dev_pm_opp_find_freq_exact() - search for an exact frequency
  * @dev:               device for which we do this operation
  * @freq:              frequency to search for
  * @available:         true/false - match for available opp
@@ -254,11 +254,12 @@ EXPORT_SYMBOL_GPL(opp_get_opp_count);
  * under the locked area. The pointer returned must be used prior to unlocking
  * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
-struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
-                               bool available)
+struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
+                                             unsigned long freq,
+                                             bool available)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
+       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        dev_opp = find_device_opp(dev);
        if (IS_ERR(dev_opp)) {
@@ -277,10 +278,10 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
 
        return opp;
 }
-EXPORT_SYMBOL_GPL(opp_find_freq_exact);
+EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact);
 
 /**
- * opp_find_freq_ceil() - Search for an rounded ceil freq
+ * dev_pm_opp_find_freq_ceil() - Search for an rounded ceil freq
  * @dev:       device for which we do this operation
  * @freq:      Start frequency
  *
@@ -300,10 +301,11 @@ EXPORT_SYMBOL_GPL(opp_find_freq_exact);
  * under the locked area. The pointer returned must be used prior to unlocking
  * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
-struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
+struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
+                                            unsigned long *freq)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
+       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        if (!dev || !freq) {
                dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -324,10 +326,10 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
 
        return opp;
 }
-EXPORT_SYMBOL_GPL(opp_find_freq_ceil);
+EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil);
 
 /**
- * opp_find_freq_floor() - Search for a rounded floor freq
+ * dev_pm_opp_find_freq_floor() - Search for a rounded floor freq
  * @dev:       device for which we do this operation
  * @freq:      Start frequency
  *
@@ -347,10 +349,11 @@ EXPORT_SYMBOL_GPL(opp_find_freq_ceil);
  * under the locked area. The pointer returned must be used prior to unlocking
  * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
-struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
+struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
+                                             unsigned long *freq)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
+       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        if (!dev || !freq) {
                dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -375,17 +378,17 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
 
        return opp;
 }
-EXPORT_SYMBOL_GPL(opp_find_freq_floor);
+EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
 /**
- * opp_add()  - Add an OPP table from a table definitions
+ * dev_pm_opp_add()  - Add an OPP table from a table definitions
  * @dev:       device for which we do this operation
  * @freq:      Frequency in Hz for this OPP
  * @u_volt:    Voltage in uVolts for this OPP
  *
  * This function adds an opp definition to the opp list and returns status.
  * The opp is made available by default and it can be controlled using
- * opp_enable/disable functions.
+ * dev_pm_opp_enable/disable functions.
  *
  * Locking: The internal device_opp and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
@@ -393,14 +396,14 @@ EXPORT_SYMBOL_GPL(opp_find_freq_floor);
  * that this function is *NOT* called under RCU protection or in contexts where
  * mutex cannot be locked.
  */
-int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
+int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 {
        struct device_opp *dev_opp = NULL;
-       struct opp *opp, *new_opp;
+       struct dev_pm_opp *opp, *new_opp;
        struct list_head *head;
 
        /* allocate new OPP node */
-       new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL);
+       new_opp = kzalloc(sizeof(*new_opp), GFP_KERNEL);
        if (!new_opp) {
                dev_warn(dev, "%s: Unable to create new OPP node\n", __func__);
                return -ENOMEM;
@@ -460,7 +463,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
        srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp);
        return 0;
 }
-EXPORT_SYMBOL_GPL(opp_add);
+EXPORT_SYMBOL_GPL(dev_pm_opp_add);
 
 /**
  * opp_set_availability() - helper to set the availability of an opp
@@ -485,11 +488,11 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
                bool availability_req)
 {
        struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
-       struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+       struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
        int r = 0;
 
        /* keep the node allocated */
-       new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL);
+       new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL);
        if (!new_opp) {
                dev_warn(dev, "%s: Unable to create OPP\n", __func__);
                return -ENOMEM;
@@ -552,13 +555,13 @@ unlock:
 }
 
 /**
- * opp_enable() - Enable a specific OPP
+ * dev_pm_opp_enable() - Enable a specific OPP
  * @dev:       device for which we do this operation
  * @freq:      OPP frequency to enable
  *
  * Enables a provided opp. If the operation is valid, this returns 0, else the
  * corresponding error value. It is meant to be used for users an OPP available
- * after being temporarily made unavailable with opp_disable.
+ * after being temporarily made unavailable with dev_pm_opp_disable.
  *
  * Locking: The internal device_opp and opp structures are RCU protected.
  * Hence this function indirectly uses RCU and mutex locks to keep the
@@ -566,21 +569,21 @@ unlock:
  * this function is *NOT* called under RCU protection or in contexts where
  * mutex locking or synchronize_rcu() blocking calls cannot be used.
  */
-int opp_enable(struct device *dev, unsigned long freq)
+int dev_pm_opp_enable(struct device *dev, unsigned long freq)
 {
        return opp_set_availability(dev, freq, true);
 }
-EXPORT_SYMBOL_GPL(opp_enable);
+EXPORT_SYMBOL_GPL(dev_pm_opp_enable);
 
 /**
- * opp_disable() - Disable a specific OPP
+ * dev_pm_opp_disable() - Disable a specific OPP
  * @dev:       device for which we do this operation
  * @freq:      OPP frequency to disable
  *
  * Disables a provided opp. If the operation is valid, this returns
  * 0, else the corresponding error value. It is meant to be a temporary
  * control by users to make this OPP not available until the circumstances are
- * right to make it available again (with a call to opp_enable).
+ * right to make it available again (with a call to dev_pm_opp_enable).
  *
  * Locking: The internal device_opp and opp structures are RCU protected.
  * Hence this function indirectly uses RCU and mutex locks to keep the
@@ -588,15 +591,15 @@ EXPORT_SYMBOL_GPL(opp_enable);
  * this function is *NOT* called under RCU protection or in contexts where
  * mutex locking or synchronize_rcu() blocking calls cannot be used.
  */
-int opp_disable(struct device *dev, unsigned long freq)
+int dev_pm_opp_disable(struct device *dev, unsigned long freq)
 {
        return opp_set_availability(dev, freq, false);
 }
-EXPORT_SYMBOL_GPL(opp_disable);
+EXPORT_SYMBOL_GPL(dev_pm_opp_disable);
 
 #ifdef CONFIG_CPU_FREQ
 /**
- * opp_init_cpufreq_table() - create a cpufreq table for a device
+ * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device
  * @dev:       device for which we do this operation
  * @table:     Cpufreq table returned back to caller
  *
@@ -619,11 +622,11 @@ EXPORT_SYMBOL_GPL(opp_disable);
  * Callers should ensure that this function is *NOT* called under RCU protection
  * or in contexts where mutex locking cannot be used.
  */
-int opp_init_cpufreq_table(struct device *dev,
+int dev_pm_opp_init_cpufreq_table(struct device *dev,
                            struct cpufreq_frequency_table **table)
 {
        struct device_opp *dev_opp;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        struct cpufreq_frequency_table *freq_table;
        int i = 0;
 
@@ -639,7 +642,7 @@ int opp_init_cpufreq_table(struct device *dev,
        }
 
        freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
-                            (opp_get_opp_count(dev) + 1), GFP_KERNEL);
+                            (dev_pm_opp_get_opp_count(dev) + 1), GFP_KERNEL);
        if (!freq_table) {
                mutex_unlock(&dev_opp_list_lock);
                dev_warn(dev, "%s: Unable to allocate frequency table\n",
@@ -663,16 +666,16 @@ int opp_init_cpufreq_table(struct device *dev,
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(opp_init_cpufreq_table);
+EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table);
 
 /**
- * opp_free_cpufreq_table() - free the cpufreq table
+ * dev_pm_opp_free_cpufreq_table() - free the cpufreq table
  * @dev:       device for which we do this operation
  * @table:     table to free
  *
- * Free up the table allocated by opp_init_cpufreq_table
+ * Free up the table allocated by dev_pm_opp_init_cpufreq_table
  */
-void opp_free_cpufreq_table(struct device *dev,
+void dev_pm_opp_free_cpufreq_table(struct device *dev,
                                struct cpufreq_frequency_table **table)
 {
        if (!table)
@@ -681,14 +684,14 @@ void opp_free_cpufreq_table(struct device *dev,
        kfree(*table);
        *table = NULL;
 }
-EXPORT_SYMBOL_GPL(opp_free_cpufreq_table);
+EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
 #endif         /* CONFIG_CPU_FREQ */
 
 /**
- * opp_get_notifier() - find notifier_head of the device with opp
+ * dev_pm_opp_get_notifier() - find notifier_head of the device with opp
  * @dev:       device pointer used to lookup device OPPs.
  */
-struct srcu_notifier_head *opp_get_notifier(struct device *dev)
+struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev)
 {
        struct device_opp *dev_opp = find_device_opp(dev);
 
@@ -732,7 +735,7 @@ int of_init_opp_table(struct device *dev)
                unsigned long freq = be32_to_cpup(val++) * 1000;
                unsigned long volt = be32_to_cpup(val++);
 
-               if (opp_add(dev, freq, volt)) {
+               if (dev_pm_opp_add(dev, freq, volt)) {
                        dev_warn(dev, "%s: Failed to add OPP %ld\n",
                                 __func__, freq);
                        continue;
index 06189e55b4e5a0479d2eaab0a31610ef91bf472f..94c280d36e8b3bfaea00ee36c4fe3215818b3c86 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
+#include <xen/xen.h>
 #include <xen/events.h>
 #include <xen/interface/io/tpmif.h>
 #include <xen/grant_table.h>
index 08ae128cce9be2e930454088c1041478bce8d8f5..c73fc2b74de2a1dd0665bde5693b1fce03f6d6c5 100644 (file)
@@ -65,6 +65,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);
@@ -80,6 +81,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);
 }
@@ -96,6 +98,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);
@@ -106,6 +109,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);
 }
 
@@ -122,6 +126,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;
@@ -145,6 +150,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);
 }
 
@@ -160,6 +166,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);
@@ -170,6 +177,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);
 }
 
@@ -185,6 +193,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);
@@ -203,6 +212,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);
 }
 
@@ -218,6 +228,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);
@@ -229,6 +240,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);
 }
 
@@ -244,6 +256,7 @@ void proc_coredump_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);
@@ -254,6 +267,7 @@ void proc_coredump_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);
 }
 
@@ -269,6 +283,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);
@@ -281,6 +296,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);
 }
 
@@ -304,6 +320,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);
@@ -313,6 +330,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);
 }
 
index 6ecfa758942c50a4b33ebd399cd831ac1420277d..a36749f1e44a869418e1bcab6481334948618391 100644 (file)
@@ -109,7 +109,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
 
        data = nlmsg_data(nlh);
 
-       memcpy(data, msg, sizeof(*data) + msg->len);
+       memcpy(data, msg, size);
 
        NETLINK_CB(skb).dst_group = group;
 
@@ -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_HDRLEN) {
                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;
                }
index 534fcb8251538a31d2695313b1d565990f8d51d4..38093e272377b2729939400c581aeb9706424011 100644 (file)
@@ -17,15 +17,11 @@ config CPU_FREQ
 
 if CPU_FREQ
 
-config CPU_FREQ_TABLE
-       tristate
-
 config CPU_FREQ_GOV_COMMON
        bool
 
 config CPU_FREQ_STAT
        tristate "CPU frequency translation statistics"
-       select CPU_FREQ_TABLE
        default y
        help
          This driver exports CPU frequency statistics information through sysfs
@@ -143,7 +139,6 @@ config CPU_FREQ_GOV_USERSPACE
 
 config CPU_FREQ_GOV_ONDEMAND
        tristate "'ondemand' cpufreq policy governor"
-       select CPU_FREQ_TABLE
        select CPU_FREQ_GOV_COMMON
        help
          'ondemand' - This driver adds a dynamic cpufreq policy governor.
@@ -187,7 +182,6 @@ config CPU_FREQ_GOV_CONSERVATIVE
 config GENERIC_CPUFREQ_CPU0
        tristate "Generic CPU0 cpufreq driver"
        depends on HAVE_CLK && REGULATOR && PM_OPP && OF
-       select CPU_FREQ_TABLE
        help
          This adds a generic cpufreq driver for CPU0 frequency management.
          It supports both uniprocessor (UP) and symmetric multiprocessor (SMP)
@@ -223,7 +217,6 @@ depends on IA64
 
 config IA64_ACPI_CPUFREQ
        tristate "ACPI Processor P-States driver"
-       select CPU_FREQ_TABLE
        depends on ACPI_PROCESSOR
        help
        This driver adds a CPUFreq driver which utilizes the ACPI
@@ -240,7 +233,6 @@ depends on MIPS
 
 config LOONGSON2_CPUFREQ
        tristate "Loongson2 CPUFreq Driver"
-       select CPU_FREQ_TABLE
        help
          This option adds a CPUFreq driver for loongson processors which
          support software configurable cpu frequency.
@@ -262,7 +254,6 @@ menu "SPARC CPU frequency scaling drivers"
 depends on SPARC64
 config SPARC_US3_CPUFREQ
        tristate "UltraSPARC-III CPU Frequency driver"
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for UltraSPARC-III processors.
 
@@ -272,7 +263,6 @@ config SPARC_US3_CPUFREQ
 
 config SPARC_US2E_CPUFREQ
        tristate "UltraSPARC-IIe CPU Frequency driver"
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for UltraSPARC-IIe processors.
 
@@ -285,7 +275,6 @@ menu "SH CPU Frequency scaling"
 depends on SUPERH
 config SH_CPU_FREQ
        tristate "SuperH CPU Frequency driver"
-       select CPU_FREQ_TABLE
        help
          This adds the cpufreq driver for SuperH. Any CPU that supports
          clock rate rounding through the clock framework can use this
index 0fa204b244bd2df52974a50fc4290e9fa77d287c..ce52ed949249bc8b63f9fd7e17d2087d5c3e8ddd 100644 (file)
@@ -5,7 +5,6 @@
 config ARM_BIG_LITTLE_CPUFREQ
        tristate "Generic ARM big LITTLE CPUfreq driver"
        depends on ARM_CPU_TOPOLOGY && PM_OPP && HAVE_CLK
-       select CPU_FREQ_TABLE
        help
          This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
 
@@ -18,7 +17,6 @@ config ARM_DT_BL_CPUFREQ
 
 config ARM_EXYNOS_CPUFREQ
        bool
-       select CPU_FREQ_TABLE
 
 config ARM_EXYNOS4210_CPUFREQ
        bool "SAMSUNG EXYNOS4210"
@@ -58,7 +56,6 @@ config ARM_EXYNOS5440_CPUFREQ
        depends on SOC_EXYNOS5440
        depends on HAVE_CLK && PM_OPP && OF
        default y
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for Samsung EXYNOS5440
          SoC. The nature of exynos5440 clock controller is
@@ -85,7 +82,6 @@ config ARM_IMX6Q_CPUFREQ
        tristate "Freescale i.MX6Q cpufreq support"
        depends on SOC_IMX6Q
        depends on REGULATOR_ANATOP
-       select CPU_FREQ_TABLE
        help
          This adds cpufreq driver support for Freescale i.MX6Q SOC.
 
@@ -101,7 +97,6 @@ config ARM_INTEGRATOR
 
 config ARM_KIRKWOOD_CPUFREQ
        def_bool ARCH_KIRKWOOD && OF
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for Marvell Kirkwood
          SoCs.
@@ -110,7 +105,6 @@ config ARM_OMAP2PLUS_CPUFREQ
        bool "TI OMAP2+"
        depends on ARCH_OMAP2PLUS
        default ARCH_OMAP2PLUS
-       select CPU_FREQ_TABLE
 
 config ARM_S3C_CPUFREQ
        bool
@@ -165,7 +159,6 @@ config ARM_S3C2412_CPUFREQ
 config ARM_S3C2416_CPUFREQ
        bool "S3C2416 CPU Frequency scaling support"
        depends on CPU_S3C2416
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for the Samsung S3C2416 and
          S3C2450 SoC. The S3C2416 supports changing the rate of the
@@ -196,7 +189,6 @@ config ARM_S3C2440_CPUFREQ
 config ARM_S3C64XX_CPUFREQ
        bool "Samsung S3C64XX"
        depends on CPU_S3C6410
-       select CPU_FREQ_TABLE
        default y
        help
          This adds the CPUFreq driver for Samsung S3C6410 SoC.
@@ -206,7 +198,6 @@ config ARM_S3C64XX_CPUFREQ
 config ARM_S5PV210_CPUFREQ
        bool "Samsung S5PV210 and S5PC110"
        depends on CPU_S5PV210
-       select CPU_FREQ_TABLE
        default y
        help
          This adds the CPUFreq driver for Samsung S5PV210 and
@@ -223,7 +214,6 @@ config ARM_SA1110_CPUFREQ
 config ARM_SPEAR_CPUFREQ
        bool "SPEAr CPUFreq support"
        depends on PLAT_SPEAR
-       select CPU_FREQ_TABLE
        default y
        help
          This adds the CPUFreq driver support for SPEAr SOCs.
@@ -231,7 +221,14 @@ config ARM_SPEAR_CPUFREQ
 config ARM_TEGRA_CPUFREQ
        bool "TEGRA CPUFreq support"
        depends on ARCH_TEGRA
-       select CPU_FREQ_TABLE
        default y
        help
          This adds the CPUFreq driver support for TEGRA SOCs.
+
+config ARM_VEXPRESS_SPC_CPUFREQ
+        tristate "Versatile Express SPC based CPUfreq driver"
+        select ARM_BIG_LITTLE_CPUFREQ
+        depends on ARCH_VEXPRESS_SPC
+        help
+          This add the CPUfreq driver support for Versatile Express
+         big.LITTLE platforms using SPC for power management.
index 25ca9db62e090d6b49e20d6744c3cd4027a16bfb..ca0021a96e19738abefa9538bcb590e3e2c3faa7 100644 (file)
@@ -1,7 +1,6 @@
 config CPU_FREQ_CBE
        tristate "CBE frequency scaling"
        depends on CBE_RAS && PPC_CELL
-       select CPU_FREQ_TABLE
        default m
        help
          This adds the cpufreq driver for Cell BE processors.
@@ -20,7 +19,6 @@ config CPU_FREQ_CBE_PMI
 config CPU_FREQ_MAPLE
        bool "Support for Maple 970FX Evaluation Board"
        depends on PPC_MAPLE
-       select CPU_FREQ_TABLE
        help
          This adds support for frequency switching on Maple 970FX
          Evaluation Board and compatible boards (IBM JS2x blades).
@@ -28,7 +26,6 @@ config CPU_FREQ_MAPLE
 config PPC_CORENET_CPUFREQ
        tristate "CPU frequency scaling driver for Freescale E500MC SoCs"
        depends on PPC_E500MC && OF && COMMON_CLK
-       select CPU_FREQ_TABLE
        select CLK_PPC_CORENET
        help
          This adds the CPUFreq driver support for Freescale e500mc,
@@ -38,7 +35,6 @@ config PPC_CORENET_CPUFREQ
 config CPU_FREQ_PMAC
        bool "Support for Apple PowerBooks"
        depends on ADB_PMU && PPC32
-       select CPU_FREQ_TABLE
        help
          This adds support for frequency switching on Apple PowerBooks,
          this currently includes some models of iBook & Titanium
@@ -47,7 +43,6 @@ config CPU_FREQ_PMAC
 config CPU_FREQ_PMAC64
        bool "Support for some Apple G5s"
        depends on PPC_PMAC && PPC64
-       select CPU_FREQ_TABLE
        help
          This adds support for frequency switching on Apple iMac G5,
          and some of the more recent desktop G5 machines as well.
@@ -55,7 +50,6 @@ config CPU_FREQ_PMAC64
 config PPC_PASEMI_CPUFREQ
        bool "Support for PA Semi PWRficient"
        depends on PPC_PASEMI
-       select CPU_FREQ_TABLE
        default y
        help
          This adds the support for frequency switching on PA Semi
index e2b6eabef2218d4e1e392ed523b3451553e196cb..6897ad85b0467a8200c3a529e5dee14344c2afbf 100644 (file)
@@ -31,7 +31,6 @@ config X86_PCC_CPUFREQ
 
 config X86_ACPI_CPUFREQ
        tristate "ACPI Processor P-States driver"
-       select CPU_FREQ_TABLE
        depends on ACPI_PROCESSOR
        help
          This driver adds a CPUFreq driver which utilizes the ACPI
@@ -60,7 +59,6 @@ config X86_ACPI_CPUFREQ_CPB
 
 config ELAN_CPUFREQ
        tristate "AMD Elan SC400 and SC410"
-       select CPU_FREQ_TABLE
        depends on MELAN
        ---help---
          This adds the CPUFreq driver for AMD Elan SC400 and SC410
@@ -76,7 +74,6 @@ config ELAN_CPUFREQ
 
 config SC520_CPUFREQ
        tristate "AMD Elan SC520"
-       select CPU_FREQ_TABLE
        depends on MELAN
        ---help---
          This adds the CPUFreq driver for AMD Elan SC520 processor.
@@ -88,7 +85,6 @@ config SC520_CPUFREQ
 
 config X86_POWERNOW_K6
        tristate "AMD Mobile K6-2/K6-3 PowerNow!"
-       select CPU_FREQ_TABLE
        depends on X86_32
        help
          This adds the CPUFreq driver for mobile AMD K6-2+ and mobile
@@ -100,7 +96,6 @@ config X86_POWERNOW_K6
 
 config X86_POWERNOW_K7
        tristate "AMD Mobile Athlon/Duron PowerNow!"
-       select CPU_FREQ_TABLE
        depends on X86_32
        help
          This adds the CPUFreq driver for mobile AMD K7 mobile processors.
@@ -118,7 +113,6 @@ config X86_POWERNOW_K7_ACPI
 
 config X86_POWERNOW_K8
        tristate "AMD Opteron/Athlon64 PowerNow!"
-       select CPU_FREQ_TABLE
        depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ
        help
          This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors.
@@ -132,7 +126,6 @@ config X86_POWERNOW_K8
 config X86_AMD_FREQ_SENSITIVITY
        tristate "AMD frequency sensitivity feedback powersave bias"
        depends on CPU_FREQ_GOV_ONDEMAND && X86_ACPI_CPUFREQ && CPU_SUP_AMD
-       select CPU_FREQ_TABLE
        help
          This adds AMD-specific powersave bias function to the ondemand
          governor, which allows it to make more power-conscious frequency
@@ -160,7 +153,6 @@ config X86_GX_SUSPMOD
 
 config X86_SPEEDSTEP_CENTRINO
        tristate "Intel Enhanced SpeedStep (deprecated)"
-       select CPU_FREQ_TABLE
        select X86_SPEEDSTEP_CENTRINO_TABLE if X86_32
        depends on X86_32 || (X86_64 && ACPI_PROCESSOR)
        help
@@ -190,7 +182,6 @@ config X86_SPEEDSTEP_CENTRINO_TABLE
 
 config X86_SPEEDSTEP_ICH
        tristate "Intel Speedstep on ICH-M chipsets (ioport interface)"
-       select CPU_FREQ_TABLE
        depends on X86_32
        help
          This adds the CPUFreq driver for certain mobile Intel Pentium III
@@ -204,7 +195,6 @@ config X86_SPEEDSTEP_ICH
 
 config X86_SPEEDSTEP_SMI
        tristate "Intel SpeedStep on 440BX/ZX/MX chipsets (SMI interface)"
-       select CPU_FREQ_TABLE
        depends on X86_32
        help
          This adds the CPUFreq driver for certain mobile Intel Pentium III
@@ -217,7 +207,6 @@ config X86_SPEEDSTEP_SMI
 
 config X86_P4_CLOCKMOD
        tristate "Intel Pentium 4 clock modulation"
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for Intel Pentium 4 / XEON
          processors.  When enabled it will lower CPU temperature by skipping
@@ -259,7 +248,6 @@ config X86_LONGRUN
 
 config X86_LONGHAUL
        tristate "VIA Cyrix III Longhaul"
-       select CPU_FREQ_TABLE
        depends on X86_32 && ACPI_PROCESSOR
        help
          This adds the CPUFreq driver for VIA Samuel/CyrixIII,
@@ -272,7 +260,6 @@ config X86_LONGHAUL
 
 config X86_E_POWERSAVER
        tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
-       select CPU_FREQ_TABLE
        depends on X86_32 && ACPI_PROCESSOR
        help
          This adds the CPUFreq driver for VIA C7 processors.  However, this driver
index ad5866c2ada0a5bd219305954682dbc7aae4f5a2..74945652dd7af595ca3498c3064944abdd73e9fe 100644 (file)
@@ -1,5 +1,5 @@
 # CPUfreq core
-obj-$(CONFIG_CPU_FREQ)                 += cpufreq.o
+obj-$(CONFIG_CPU_FREQ)                 += cpufreq.o freq_table.o
 # CPUfreq stats
 obj-$(CONFIG_CPU_FREQ_STAT)             += cpufreq_stats.o
 
@@ -11,9 +11,6 @@ obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)   += cpufreq_ondemand.o
 obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)        += cpufreq_conservative.o
 obj-$(CONFIG_CPU_FREQ_GOV_COMMON)              += cpufreq_governor.o
 
-# CPUfreq cross-arch helpers
-obj-$(CONFIG_CPU_FREQ_TABLE)           += freq_table.o
-
 obj-$(CONFIG_GENERIC_CPUFREQ_CPU0)     += cpufreq-cpu0.o
 
 ##################################################################################
@@ -77,6 +74,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ)      += sa1100-cpufreq.o
 obj-$(CONFIG_ARM_SA1110_CPUFREQ)       += sa1110-cpufreq.o
 obj-$(CONFIG_ARM_SPEAR_CPUFREQ)                += spear-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA_CPUFREQ)                += tegra-cpufreq.o
+obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
 
 ##################################################################################
 # PowerPC platform drivers
index d2c3253e015ee23f107d2d34333c6afa533ab7cf..caf41ebea18471b9a9dea285f8887bf521e51da9 100644 (file)
@@ -424,34 +424,21 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,
 }
 
 static int acpi_cpufreq_target(struct cpufreq_policy *policy,
-                              unsigned int target_freq, unsigned int relation)
+                              unsigned int index)
 {
        struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
        struct acpi_processor_performance *perf;
-       struct cpufreq_freqs freqs;
        struct drv_cmd cmd;
-       unsigned int next_state = 0; /* Index into freq_table */
        unsigned int next_perf_state = 0; /* Index into perf table */
        int result = 0;
 
-       pr_debug("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu);
-
        if (unlikely(data == NULL ||
             data->acpi_data == NULL || data->freq_table == NULL)) {
                return -ENODEV;
        }
 
        perf = data->acpi_data;
-       result = cpufreq_frequency_table_target(policy,
-                                               data->freq_table,
-                                               target_freq,
-                                               relation, &next_state);
-       if (unlikely(result)) {
-               result = -ENODEV;
-               goto out;
-       }
-
-       next_perf_state = data->freq_table[next_state].driver_data;
+       next_perf_state = data->freq_table[index].driver_data;
        if (perf->state == next_perf_state) {
                if (unlikely(data->resume)) {
                        pr_debug("Called after resume, resetting to P%d\n",
@@ -492,23 +479,17 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
        else
                cmd.mask = cpumask_of(policy->cpu);
 
-       freqs.old = perf->states[perf->state].core_frequency * 1000;
-       freqs.new = data->freq_table[next_state].frequency;
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        drv_write(&cmd);
 
        if (acpi_pstate_strict) {
-               if (!check_freqs(cmd.mask, freqs.new, data)) {
+               if (!check_freqs(cmd.mask, data->freq_table[index].frequency,
+                                       data)) {
                        pr_debug("acpi_cpufreq_target failed (%d)\n",
                                policy->cpu);
                        result = -EAGAIN;
-                       freqs.new = freqs.old;
                }
        }
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
        if (!result)
                perf->state = next_perf_state;
 
@@ -516,15 +497,6 @@ out:
        return result;
 }
 
-static int acpi_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
-
-       pr_debug("acpi_cpufreq_verify\n");
-
-       return cpufreq_frequency_table_verify(policy, data->freq_table);
-}
-
 static unsigned long
 acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
 {
@@ -837,7 +809,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
        data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
        perf->state = 0;
 
-       result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
+       result = cpufreq_table_validate_and_show(policy, data->freq_table);
        if (result)
                goto err_freqfree;
 
@@ -846,12 +818,16 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
        switch (perf->control_register.space_id) {
        case ACPI_ADR_SPACE_SYSTEM_IO:
-               /* Current speed is unknown and not detectable by IO port */
+               /*
+                * The core will not set policy->cur, because
+                * cpufreq_driver->get is NULL, so we need to set it here.
+                * However, we have to guess it, because the current speed is
+                * unknown and not detectable via IO ports.
+                */
                policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
                break;
        case ACPI_ADR_SPACE_FIXED_HARDWARE:
                acpi_cpufreq_driver.get = get_cur_freq_on_cpu;
-               policy->cur = get_cur_freq_on_cpu(cpu);
                break;
        default:
                break;
@@ -868,8 +844,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
                        (u32) perf->states[i].power,
                        (u32) perf->states[i].transition_latency);
 
-       cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
-
        /*
         * the first call to ->target() should result in us actually
         * writing something to the appropriate registers.
@@ -929,8 +903,8 @@ static struct freq_attr *acpi_cpufreq_attr[] = {
 };
 
 static struct cpufreq_driver acpi_cpufreq_driver = {
-       .verify         = acpi_cpufreq_verify,
-       .target         = acpi_cpufreq_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = acpi_cpufreq_target,
        .bios_limit     = acpi_processor_get_bios_limit,
        .init           = acpi_cpufreq_cpu_init,
        .exit           = acpi_cpufreq_cpu_exit,
@@ -986,12 +960,12 @@ static int __init acpi_cpufreq_init(void)
 {
        int ret;
 
+       if (acpi_disabled)
+               return -ENODEV;
+
        /* don't keep reloading if cpufreq_driver exists */
        if (cpufreq_get_current_driver())
-               return 0;
-
-       if (acpi_disabled)
-               return 0;
+               return -EEXIST;
 
        pr_debug("acpi_cpufreq_init\n");
 
index 3549f0784af176d07ee17dd60d02ec85859d6bd1..5519933813ea4996c4dd7b378a1c22d00810811d 100644 (file)
 #include <linux/cpufreq.h>
 #include <linux/cpumask.h>
 #include <linux/export.h>
+#include <linux/mutex.h>
 #include <linux/of_platform.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/slab.h>
 #include <linux/topology.h>
 #include <linux/types.h>
+#include <asm/bL_switcher.h>
 
 #include "arm_big_little.h"
 
 /* Currently we support only two clusters */
+#define A15_CLUSTER    0
+#define A7_CLUSTER     1
 #define MAX_CLUSTERS   2
 
+#ifdef CONFIG_BL_SWITCHER
+static bool bL_switching_enabled;
+#define is_bL_switching_enabled()      bL_switching_enabled
+#define set_switching_enabled(x)       (bL_switching_enabled = (x))
+#else
+#define is_bL_switching_enabled()      false
+#define set_switching_enabled(x)       do { } while (0)
+#endif
+
+#define ACTUAL_FREQ(cluster, freq)  ((cluster == A7_CLUSTER) ? freq << 1 : freq)
+#define VIRT_FREQ(cluster, freq)    ((cluster == A7_CLUSTER) ? freq >> 1 : freq)
+
 static struct cpufreq_arm_bL_ops *arm_bL_ops;
 static struct clk *clk[MAX_CLUSTERS];
-static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS];
-static atomic_t cluster_usage[MAX_CLUSTERS] = {ATOMIC_INIT(0), ATOMIC_INIT(0)};
+static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1];
+static atomic_t cluster_usage[MAX_CLUSTERS + 1];
+
+static unsigned int clk_big_min;       /* (Big) clock frequencies */
+static unsigned int clk_little_max;    /* Maximum clock frequency (Little) */
+
+static DEFINE_PER_CPU(unsigned int, physical_cluster);
+static DEFINE_PER_CPU(unsigned int, cpu_last_req_freq);
 
-static unsigned int bL_cpufreq_get(unsigned int cpu)
+static struct mutex cluster_lock[MAX_CLUSTERS];
+
+static inline int raw_cpu_to_cluster(int cpu)
 {
-       u32 cur_cluster = cpu_to_cluster(cpu);
+       return topology_physical_package_id(cpu);
+}
 
-       return clk_get_rate(clk[cur_cluster]) / 1000;
+static inline int cpu_to_cluster(int cpu)
+{
+       return is_bL_switching_enabled() ?
+               MAX_CLUSTERS : raw_cpu_to_cluster(cpu);
 }
 
-/* Validate policy frequency range */
-static int bL_cpufreq_verify_policy(struct cpufreq_policy *policy)
+static unsigned int find_cluster_maxfreq(int cluster)
 {
-       u32 cur_cluster = cpu_to_cluster(policy->cpu);
+       int j;
+       u32 max_freq = 0, cpu_freq;
+
+       for_each_online_cpu(j) {
+               cpu_freq = per_cpu(cpu_last_req_freq, j);
+
+               if ((cluster == per_cpu(physical_cluster, j)) &&
+                               (max_freq < cpu_freq))
+                       max_freq = cpu_freq;
+       }
+
+       pr_debug("%s: cluster: %d, max freq: %d\n", __func__, cluster,
+                       max_freq);
+
+       return max_freq;
+}
+
+static unsigned int clk_get_cpu_rate(unsigned int cpu)
+{
+       u32 cur_cluster = per_cpu(physical_cluster, cpu);
+       u32 rate = clk_get_rate(clk[cur_cluster]) / 1000;
+
+       /* For switcher we use virtual A7 clock rates */
+       if (is_bL_switching_enabled())
+               rate = VIRT_FREQ(cur_cluster, rate);
+
+       pr_debug("%s: cpu: %d, cluster: %d, freq: %u\n", __func__, cpu,
+                       cur_cluster, rate);
+
+       return rate;
+}
+
+static unsigned int bL_cpufreq_get_rate(unsigned int cpu)
+{
+       if (is_bL_switching_enabled()) {
+               pr_debug("%s: freq: %d\n", __func__, per_cpu(cpu_last_req_freq,
+                                       cpu));
+
+               return per_cpu(cpu_last_req_freq, cpu);
+       } else {
+               return clk_get_cpu_rate(cpu);
+       }
+}
+
+static unsigned int
+bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
+{
+       u32 new_rate, prev_rate;
+       int ret;
+       bool bLs = is_bL_switching_enabled();
+
+       mutex_lock(&cluster_lock[new_cluster]);
 
-       return cpufreq_frequency_table_verify(policy, freq_table[cur_cluster]);
+       if (bLs) {
+               prev_rate = per_cpu(cpu_last_req_freq, cpu);
+               per_cpu(cpu_last_req_freq, cpu) = rate;
+               per_cpu(physical_cluster, cpu) = new_cluster;
+
+               new_rate = find_cluster_maxfreq(new_cluster);
+               new_rate = ACTUAL_FREQ(new_cluster, new_rate);
+       } else {
+               new_rate = rate;
+       }
+
+       pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d, freq: %d\n",
+                       __func__, cpu, old_cluster, new_cluster, new_rate);
+
+       ret = clk_set_rate(clk[new_cluster], new_rate * 1000);
+       if (WARN_ON(ret)) {
+               pr_err("clk_set_rate failed: %d, new cluster: %d\n", ret,
+                               new_cluster);
+               if (bLs) {
+                       per_cpu(cpu_last_req_freq, cpu) = prev_rate;
+                       per_cpu(physical_cluster, cpu) = old_cluster;
+               }
+
+               mutex_unlock(&cluster_lock[new_cluster]);
+
+               return ret;
+       }
+
+       mutex_unlock(&cluster_lock[new_cluster]);
+
+       /* Recalc freq for old cluster when switching clusters */
+       if (old_cluster != new_cluster) {
+               pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d\n",
+                               __func__, cpu, old_cluster, new_cluster);
+
+               /* Switch cluster */
+               bL_switch_request(cpu, new_cluster);
+
+               mutex_lock(&cluster_lock[old_cluster]);
+
+               /* Set freq of old cluster if there are cpus left on it */
+               new_rate = find_cluster_maxfreq(old_cluster);
+               new_rate = ACTUAL_FREQ(old_cluster, new_rate);
+
+               if (new_rate) {
+                       pr_debug("%s: Updating rate of old cluster: %d, to freq: %d\n",
+                                       __func__, old_cluster, new_rate);
+
+                       if (clk_set_rate(clk[old_cluster], new_rate * 1000))
+                               pr_err("%s: clk_set_rate failed: %d, old cluster: %d\n",
+                                               __func__, ret, old_cluster);
+               }
+               mutex_unlock(&cluster_lock[old_cluster]);
+       }
+
+       return 0;
 }
 
 /* Set clock frequency */
 static int bL_cpufreq_set_target(struct cpufreq_policy *policy,
-               unsigned int target_freq, unsigned int relation)
+               unsigned int index)
 {
-       struct cpufreq_freqs freqs;
-       u32 cpu = policy->cpu, freq_tab_idx, cur_cluster;
-       int ret = 0;
+       u32 cpu = policy->cpu, cur_cluster, new_cluster, actual_cluster;
+       unsigned int freqs_new;
+
+       cur_cluster = cpu_to_cluster(cpu);
+       new_cluster = actual_cluster = per_cpu(physical_cluster, cpu);
+
+       freqs_new = freq_table[cur_cluster][index].frequency;
+
+       if (is_bL_switching_enabled()) {
+               if ((actual_cluster == A15_CLUSTER) &&
+                               (freqs_new < clk_big_min)) {
+                       new_cluster = A7_CLUSTER;
+               } else if ((actual_cluster == A7_CLUSTER) &&
+                               (freqs_new > clk_little_max)) {
+                       new_cluster = A15_CLUSTER;
+               }
+       }
 
-       cur_cluster = cpu_to_cluster(policy->cpu);
+       return bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs_new);
+}
 
-       freqs.old = bL_cpufreq_get(policy->cpu);
+static inline u32 get_table_count(struct cpufreq_frequency_table *table)
+{
+       int count;
 
-       /* Determine valid target frequency using freq_table */
-       cpufreq_frequency_table_target(policy, freq_table[cur_cluster],
-                       target_freq, relation, &freq_tab_idx);
-       freqs.new = freq_table[cur_cluster][freq_tab_idx].frequency;
+       for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++)
+               ;
 
-       pr_debug("%s: cpu: %d, cluster: %d, oldfreq: %d, target freq: %d, new freq: %d\n",
-                       __func__, cpu, cur_cluster, freqs.old, target_freq,
-                       freqs.new);
+       return count;
+}
 
-       if (freqs.old == freqs.new)
-               return 0;
+/* get the minimum frequency in the cpufreq_frequency_table */
+static inline u32 get_table_min(struct cpufreq_frequency_table *table)
+{
+       int i;
+       uint32_t min_freq = ~0;
+       for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++)
+               if (table[i].frequency < min_freq)
+                       min_freq = table[i].frequency;
+       return min_freq;
+}
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+/* get the maximum frequency in the cpufreq_frequency_table */
+static inline u32 get_table_max(struct cpufreq_frequency_table *table)
+{
+       int i;
+       uint32_t max_freq = 0;
+       for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++)
+               if (table[i].frequency > max_freq)
+                       max_freq = table[i].frequency;
+       return max_freq;
+}
 
-       ret = clk_set_rate(clk[cur_cluster], freqs.new * 1000);
-       if (ret) {
-               pr_err("clk_set_rate failed: %d\n", ret);
-               freqs.new = freqs.old;
+static int merge_cluster_tables(void)
+{
+       int i, j, k = 0, count = 1;
+       struct cpufreq_frequency_table *table;
+
+       for (i = 0; i < MAX_CLUSTERS; i++)
+               count += get_table_count(freq_table[i]);
+
+       table = kzalloc(sizeof(*table) * count, GFP_KERNEL);
+       if (!table)
+               return -ENOMEM;
+
+       freq_table[MAX_CLUSTERS] = table;
+
+       /* Add in reverse order to get freqs in increasing order */
+       for (i = MAX_CLUSTERS - 1; i >= 0; i--) {
+               for (j = 0; freq_table[i][j].frequency != CPUFREQ_TABLE_END;
+                               j++) {
+                       table[k].frequency = VIRT_FREQ(i,
+                                       freq_table[i][j].frequency);
+                       pr_debug("%s: index: %d, freq: %d\n", __func__, k,
+                                       table[k].frequency);
+                       k++;
+               }
        }
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+       table[k].driver_data = k;
+       table[k].frequency = CPUFREQ_TABLE_END;
 
-       return ret;
+       pr_debug("%s: End, table: %p, count: %d\n", __func__, table, k);
+
+       return 0;
+}
+
+static void _put_cluster_clk_and_freq_table(struct device *cpu_dev)
+{
+       u32 cluster = raw_cpu_to_cluster(cpu_dev->id);
+
+       if (!freq_table[cluster])
+               return;
+
+       clk_put(clk[cluster]);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
+       dev_dbg(cpu_dev, "%s: cluster: %d\n", __func__, cluster);
 }
 
 static void put_cluster_clk_and_freq_table(struct device *cpu_dev)
 {
        u32 cluster = cpu_to_cluster(cpu_dev->id);
+       int i;
+
+       if (atomic_dec_return(&cluster_usage[cluster]))
+               return;
+
+       if (cluster < MAX_CLUSTERS)
+               return _put_cluster_clk_and_freq_table(cpu_dev);
 
-       if (!atomic_dec_return(&cluster_usage[cluster])) {
-               clk_put(clk[cluster]);
-               opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
-               dev_dbg(cpu_dev, "%s: cluster: %d\n", __func__, cluster);
+       for_each_present_cpu(i) {
+               struct device *cdev = get_cpu_device(i);
+               if (!cdev) {
+                       pr_err("%s: failed to get cpu%d device\n", __func__, i);
+                       return;
+               }
+
+               _put_cluster_clk_and_freq_table(cdev);
        }
+
+       /* free virtual table */
+       kfree(freq_table[cluster]);
 }
 
-static int get_cluster_clk_and_freq_table(struct device *cpu_dev)
+static int _get_cluster_clk_and_freq_table(struct device *cpu_dev)
 {
-       u32 cluster = cpu_to_cluster(cpu_dev->id);
+       u32 cluster = raw_cpu_to_cluster(cpu_dev->id);
        char name[14] = "cpu-cluster.";
        int ret;
 
-       if (atomic_inc_return(&cluster_usage[cluster]) != 1)
+       if (freq_table[cluster])
                return 0;
 
        ret = arm_bL_ops->init_opp_table(cpu_dev);
        if (ret) {
                dev_err(cpu_dev, "%s: init_opp_table failed, cpu: %d, err: %d\n",
                                __func__, cpu_dev->id, ret);
-               goto atomic_dec;
+               goto out;
        }
 
-       ret = opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]);
+       ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]);
        if (ret) {
                dev_err(cpu_dev, "%s: failed to init cpufreq table, cpu: %d, err: %d\n",
                                __func__, cpu_dev->id, ret);
-               goto atomic_dec;
+               goto out;
        }
 
        name[12] = cluster + '0';
-       clk[cluster] = clk_get_sys(name, NULL);
+       clk[cluster] = clk_get(cpu_dev, name);
        if (!IS_ERR(clk[cluster])) {
                dev_dbg(cpu_dev, "%s: clk: %p & freq table: %p, cluster: %d\n",
                                __func__, clk[cluster], freq_table[cluster],
@@ -138,15 +351,74 @@ static int get_cluster_clk_and_freq_table(struct device *cpu_dev)
        dev_err(cpu_dev, "%s: Failed to get clk for cpu: %d, cluster: %d\n",
                        __func__, cpu_dev->id, cluster);
        ret = PTR_ERR(clk[cluster]);
-       opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
 
-atomic_dec:
-       atomic_dec(&cluster_usage[cluster]);
+out:
        dev_err(cpu_dev, "%s: Failed to get data for cluster: %d\n", __func__,
                        cluster);
        return ret;
 }
 
+static int get_cluster_clk_and_freq_table(struct device *cpu_dev)
+{
+       u32 cluster = cpu_to_cluster(cpu_dev->id);
+       int i, ret;
+
+       if (atomic_inc_return(&cluster_usage[cluster]) != 1)
+               return 0;
+
+       if (cluster < MAX_CLUSTERS) {
+               ret = _get_cluster_clk_and_freq_table(cpu_dev);
+               if (ret)
+                       atomic_dec(&cluster_usage[cluster]);
+               return ret;
+       }
+
+       /*
+        * Get data for all clusters and fill virtual cluster with a merge of
+        * both
+        */
+       for_each_present_cpu(i) {
+               struct device *cdev = get_cpu_device(i);
+               if (!cdev) {
+                       pr_err("%s: failed to get cpu%d device\n", __func__, i);
+                       return -ENODEV;
+               }
+
+               ret = _get_cluster_clk_and_freq_table(cdev);
+               if (ret)
+                       goto put_clusters;
+       }
+
+       ret = merge_cluster_tables();
+       if (ret)
+               goto put_clusters;
+
+       /* Assuming 2 cluster, set clk_big_min and clk_little_max */
+       clk_big_min = get_table_min(freq_table[0]);
+       clk_little_max = VIRT_FREQ(1, get_table_max(freq_table[1]));
+
+       pr_debug("%s: cluster: %d, clk_big_min: %d, clk_little_max: %d\n",
+                       __func__, cluster, clk_big_min, clk_little_max);
+
+       return 0;
+
+put_clusters:
+       for_each_present_cpu(i) {
+               struct device *cdev = get_cpu_device(i);
+               if (!cdev) {
+                       pr_err("%s: failed to get cpu%d device\n", __func__, i);
+                       return -ENODEV;
+               }
+
+               _put_cluster_clk_and_freq_table(cdev);
+       }
+
+       atomic_dec(&cluster_usage[cluster]);
+
+       return ret;
+}
+
 /* Per-CPU initialization */
 static int bL_cpufreq_init(struct cpufreq_policy *policy)
 {
@@ -165,7 +437,7 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
        if (ret)
                return ret;
 
-       ret = cpufreq_frequency_table_cpuinfo(policy, freq_table[cur_cluster]);
+       ret = cpufreq_table_validate_and_show(policy, freq_table[cur_cluster]);
        if (ret) {
                dev_err(cpu_dev, "CPU %d, cluster: %d invalid freq table\n",
                                policy->cpu, cur_cluster);
@@ -173,7 +445,14 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
                return ret;
        }
 
-       cpufreq_frequency_table_get_attr(freq_table[cur_cluster], policy->cpu);
+       if (cur_cluster < MAX_CLUSTERS) {
+               cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
+
+               per_cpu(physical_cluster, policy->cpu) = cur_cluster;
+       } else {
+               /* Assumption: during init, we are always running on A15 */
+               per_cpu(physical_cluster, policy->cpu) = A15_CLUSTER;
+       }
 
        if (arm_bL_ops->get_transition_latency)
                policy->cpuinfo.transition_latency =
@@ -181,9 +460,8 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
        else
                policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 
-       policy->cur = bL_cpufreq_get(policy->cpu);
-
-       cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
+       if (is_bL_switching_enabled())
+               per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu);
 
        dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu);
        return 0;
@@ -200,33 +478,60 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
                return -ENODEV;
        }
 
+       cpufreq_frequency_table_put_attr(policy->cpu);
        put_cluster_clk_and_freq_table(cpu_dev);
        dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu);
 
        return 0;
 }
 
-/* Export freq_table to sysfs */
-static struct freq_attr *bL_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver bL_cpufreq_driver = {
        .name                   = "arm-big-little",
-       .flags                  = CPUFREQ_STICKY,
-       .verify                 = bL_cpufreq_verify_policy,
-       .target                 = bL_cpufreq_set_target,
-       .get                    = bL_cpufreq_get,
+       .flags                  = CPUFREQ_STICKY |
+                                       CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
+       .verify                 = cpufreq_generic_frequency_table_verify,
+       .target_index           = bL_cpufreq_set_target,
+       .get                    = bL_cpufreq_get_rate,
        .init                   = bL_cpufreq_init,
        .exit                   = bL_cpufreq_exit,
-       .have_governor_per_policy = true,
-       .attr                   = bL_cpufreq_attr,
+       .attr                   = cpufreq_generic_attr,
+};
+
+static int bL_cpufreq_switcher_notifier(struct notifier_block *nfb,
+                                       unsigned long action, void *_arg)
+{
+       pr_debug("%s: action: %ld\n", __func__, action);
+
+       switch (action) {
+       case BL_NOTIFY_PRE_ENABLE:
+       case BL_NOTIFY_PRE_DISABLE:
+               cpufreq_unregister_driver(&bL_cpufreq_driver);
+               break;
+
+       case BL_NOTIFY_POST_ENABLE:
+               set_switching_enabled(true);
+               cpufreq_register_driver(&bL_cpufreq_driver);
+               break;
+
+       case BL_NOTIFY_POST_DISABLE:
+               set_switching_enabled(false);
+               cpufreq_register_driver(&bL_cpufreq_driver);
+               break;
+
+       default:
+               return NOTIFY_DONE;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block bL_switcher_notifier = {
+       .notifier_call = bL_cpufreq_switcher_notifier,
 };
 
 int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
 {
-       int ret;
+       int ret, i;
 
        if (arm_bL_ops) {
                pr_debug("%s: Already registered: %s, exiting\n", __func__,
@@ -241,16 +546,29 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
 
        arm_bL_ops = ops;
 
+       ret = bL_switcher_get_enabled();
+       set_switching_enabled(ret);
+
+       for (i = 0; i < MAX_CLUSTERS; i++)
+               mutex_init(&cluster_lock[i]);
+
        ret = cpufreq_register_driver(&bL_cpufreq_driver);
        if (ret) {
                pr_info("%s: Failed registering platform driver: %s, err: %d\n",
                                __func__, ops->name, ret);
                arm_bL_ops = NULL;
        } else {
-               pr_info("%s: Registered platform driver: %s\n", __func__,
-                               ops->name);
+               ret = bL_switcher_register_notifier(&bL_switcher_notifier);
+               if (ret) {
+                       cpufreq_unregister_driver(&bL_cpufreq_driver);
+                       arm_bL_ops = NULL;
+               } else {
+                       pr_info("%s: Registered platform driver: %s\n",
+                                       __func__, ops->name);
+               }
        }
 
+       bL_switcher_put_enabled();
        return ret;
 }
 EXPORT_SYMBOL_GPL(bL_cpufreq_register);
@@ -263,7 +581,10 @@ void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops)
                return;
        }
 
+       bL_switcher_get_enabled();
+       bL_switcher_unregister_notifier(&bL_switcher_notifier);
        cpufreq_unregister_driver(&bL_cpufreq_driver);
+       bL_switcher_put_enabled();
        pr_info("%s: Un-registered platform driver: %s\n", __func__,
                        arm_bL_ops->name);
        arm_bL_ops = NULL;
index 79b2ce17884dd9cc645cb5a34c33e90290bba10a..70f18fc12d4ad2a1a2c14f00ae1844e5378cdaee 100644 (file)
@@ -34,11 +34,6 @@ struct cpufreq_arm_bL_ops {
        int (*init_opp_table)(struct device *cpu_dev);
 };
 
-static inline int cpu_to_cluster(int cpu)
-{
-       return topology_physical_package_id(cpu);
-}
-
 int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops);
 void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops);
 
index 480c0bd0468d7c0fbbed9e0872cd9adb4fb77244..8d9d5910890689e58d5994d6aeebfccf03215c59 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/export.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/types.h>
index e0c38d9389979b2f1b9a503d36c8e12364ecc188..856ad80418ae5b92610e23e98922f0ff6505d34e 100644 (file)
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/export.h>
+#include <linux/slab.h>
 
 static struct clk *cpuclk;
-
-static int at32_verify_speed(struct cpufreq_policy *policy)
-{
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                       policy->cpuinfo.max_freq);
-       return 0;
-}
+static struct cpufreq_frequency_table *freq_table;
 
 static unsigned int at32_get_speed(unsigned int cpu)
 {
@@ -43,74 +35,94 @@ static unsigned int at32_get_speed(unsigned int cpu)
 static unsigned int    ref_freq;
 static unsigned long   loops_per_jiffy_ref;
 
-static int at32_set_target(struct cpufreq_policy *policy,
-                         unsigned int target_freq,
-                         unsigned int relation)
+static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       struct cpufreq_freqs freqs;
-       long freq;
-
-       /* Convert target_freq from kHz to Hz */
-       freq = clk_round_rate(cpuclk, target_freq * 1000);
-
-       /* Check if policy->min <= new_freq <= policy->max */
-       if(freq < (policy->min * 1000) || freq > (policy->max * 1000))
-               return -EINVAL;
-
-       pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
+       unsigned int old_freq, new_freq;
 
-       freqs.old = at32_get_speed(0);
-       freqs.new = (freq + 500) / 1000;
-       freqs.flags = 0;
+       old_freq = at32_get_speed(0);
+       new_freq = freq_table[index].frequency;
 
        if (!ref_freq) {
-               ref_freq = freqs.old;
+               ref_freq = old_freq;
                loops_per_jiffy_ref = boot_cpu_data.loops_per_jiffy;
        }
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-       if (freqs.old < freqs.new)
+       if (old_freq < new_freq)
                boot_cpu_data.loops_per_jiffy = cpufreq_scale(
-                               loops_per_jiffy_ref, ref_freq, freqs.new);
-       clk_set_rate(cpuclk, freq);
-       if (freqs.new < freqs.old)
+                               loops_per_jiffy_ref, ref_freq, new_freq);
+       clk_set_rate(cpuclk, new_freq * 1000);
+       if (new_freq < old_freq)
                boot_cpu_data.loops_per_jiffy = cpufreq_scale(
-                               loops_per_jiffy_ref, ref_freq, freqs.new);
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       pr_debug("cpufreq: set frequency %lu Hz\n", freq);
+                               loops_per_jiffy_ref, ref_freq, new_freq);
 
        return 0;
 }
 
 static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
 {
+       unsigned int frequency, rate, min_freq;
+       int retval, steps, i;
+
        if (policy->cpu != 0)
                return -EINVAL;
 
        cpuclk = clk_get(NULL, "cpu");
        if (IS_ERR(cpuclk)) {
                pr_debug("cpufreq: could not get CPU clk\n");
-               return PTR_ERR(cpuclk);
+               retval = PTR_ERR(cpuclk);
+               goto out_err;
        }
 
-       policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000;
-       policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
+       min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000;
+       frequency = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
        policy->cpuinfo.transition_latency = 0;
-       policy->cur = at32_get_speed(0);
-       policy->min = policy->cpuinfo.min_freq;
-       policy->max = policy->cpuinfo.max_freq;
 
-       printk("cpufreq: AT32AP CPU frequency driver\n");
+       /*
+        * AVR32 CPU frequency rate scales in power of two between maximum and
+        * minimum, also add space for the table end marker.
+        *
+        * Further validate that the frequency is usable, and append it to the
+        * frequency table.
+        */
+       steps = fls(frequency / min_freq) + 1;
+       freq_table = kzalloc(steps * sizeof(struct cpufreq_frequency_table),
+                       GFP_KERNEL);
+       if (!freq_table) {
+               retval = -ENOMEM;
+               goto out_err_put_clk;
+       }
 
-       return 0;
+       for (i = 0; i < (steps - 1); i++) {
+               rate = clk_round_rate(cpuclk, frequency * 1000) / 1000;
+
+               if (rate != frequency)
+                       freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+               else
+                       freq_table[i].frequency = frequency;
+
+               frequency /= 2;
+       }
+
+       freq_table[steps - 1].frequency = CPUFREQ_TABLE_END;
+
+       retval = cpufreq_table_validate_and_show(policy, freq_table);
+       if (!retval) {
+               printk("cpufreq: AT32AP CPU frequency driver\n");
+               return 0;
+       }
+
+       kfree(freq_table);
+out_err_put_clk:
+       clk_put(cpuclk);
+out_err:
+       return retval;
 }
 
 static struct cpufreq_driver at32_driver = {
        .name           = "at32ap",
        .init           = at32_cpufreq_driver_init,
-       .verify         = at32_verify_speed,
-       .target         = at32_set_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = at32_set_target,
        .get            = at32_get_speed,
        .flags          = CPUFREQ_STICKY,
 };
index ef05978a723702de29da757eda20edec7d21c3d6..e9e63fc9c2c9d09b7710f61d3c8769ac77584bcc 100644 (file)
@@ -127,41 +127,28 @@ unsigned long cpu_set_cclk(int cpu, unsigned long new)
 }
 #endif
 
-static int bfin_target(struct cpufreq_policy *policy,
-                       unsigned int target_freq, unsigned int relation)
+static int bfin_target(struct cpufreq_policy *policy, unsigned int index)
 {
 #ifndef CONFIG_BF60x
        unsigned int plldiv;
 #endif
-       unsigned int index;
-       unsigned long cclk_hz;
-       struct cpufreq_freqs freqs;
        static unsigned long lpj_ref;
        static unsigned int  lpj_ref_freq;
+       unsigned int old_freq, new_freq;
        int ret = 0;
 
 #if defined(CONFIG_CYCLES_CLOCKSOURCE)
        cycles_t cycles;
 #endif
 
-       if (cpufreq_frequency_table_target(policy, bfin_freq_table, target_freq,
-                               relation, &index))
-               return -EINVAL;
+       old_freq = bfin_getfreq_khz(0);
+       new_freq = bfin_freq_table[index].frequency;
 
-       cclk_hz = bfin_freq_table[index].frequency;
-
-       freqs.old = bfin_getfreq_khz(0);
-       freqs.new = cclk_hz;
-
-       pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n",
-                       cclk_hz, target_freq, freqs.old);
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 #ifndef CONFIG_BF60x
        plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel;
        bfin_write_PLL_DIV(plldiv);
 #else
-       ret = cpu_set_cclk(policy->cpu, freqs.new * 1000);
+       ret = cpu_set_cclk(policy->cpu, new_freq * 1000);
        if (ret != 0) {
                WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret);
                return ret;
@@ -177,25 +164,16 @@ static int bfin_target(struct cpufreq_policy *policy,
 #endif
        if (!lpj_ref_freq) {
                lpj_ref = loops_per_jiffy;
-               lpj_ref_freq = freqs.old;
+               lpj_ref_freq = old_freq;
        }
-       if (freqs.new != freqs.old) {
+       if (new_freq != old_freq) {
                loops_per_jiffy = cpufreq_scale(lpj_ref,
-                               lpj_ref_freq, freqs.new);
+                               lpj_ref_freq, new_freq);
        }
 
-       /* TODO: just test case for cycles clock source, remove later */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       pr_debug("cpufreq: done\n");
        return ret;
 }
 
-static int bfin_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, bfin_freq_table);
-}
-
 static int __bfin_cpu_init(struct cpufreq_policy *policy)
 {
 
@@ -209,23 +187,17 @@ static int __bfin_cpu_init(struct cpufreq_policy *policy)
 
        policy->cpuinfo.transition_latency = 50000; /* 50us assumed */
 
-       policy->cur = cclk;
-       cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu);
-       return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table);
+       return cpufreq_table_validate_and_show(policy, bfin_freq_table);
 }
 
-static struct freq_attr *bfin_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver bfin_driver = {
-       .verify = bfin_verify_speed,
-       .target = bfin_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = bfin_target,
        .get = bfin_getfreq_khz,
        .init = __bfin_cpu_init,
+       .exit = cpufreq_generic_exit,
        .name = "bfin cpufreq",
-       .attr = bfin_freq_attr,
+       .attr = cpufreq_generic_attr,
 };
 
 static int __init bfin_cpu_init(void)
index c522a95c0e168ae30e4a347f189f89c27173c427..d4585ce2346cf187a0c5511fafdd7ac08204f1bb 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
@@ -30,73 +30,51 @@ static struct clk *cpu_clk;
 static struct regulator *cpu_reg;
 static struct cpufreq_frequency_table *freq_table;
 
-static int cpu0_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
 static unsigned int cpu0_get_speed(unsigned int cpu)
 {
        return clk_get_rate(cpu_clk) / 1000;
 }
 
-static int cpu0_set_target(struct cpufreq_policy *policy,
-                          unsigned int target_freq, unsigned int relation)
+static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       struct cpufreq_freqs freqs;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long volt = 0, volt_old = 0, tol = 0;
+       unsigned int old_freq, new_freq;
        long freq_Hz, freq_exact;
-       unsigned int index;
        int ret;
 
-       ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
-                                            relation, &index);
-       if (ret) {
-               pr_err("failed to match target freqency %d: %d\n",
-                      target_freq, ret);
-               return ret;
-       }
-
        freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
        if (freq_Hz < 0)
                freq_Hz = freq_table[index].frequency * 1000;
-       freq_exact = freq_Hz;
-       freqs.new = freq_Hz / 1000;
-       freqs.old = clk_get_rate(cpu_clk) / 1000;
 
-       if (freqs.old == freqs.new)
-               return 0;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+       freq_exact = freq_Hz;
+       new_freq = freq_Hz / 1000;
+       old_freq = clk_get_rate(cpu_clk) / 1000;
 
        if (!IS_ERR(cpu_reg)) {
                rcu_read_lock();
-               opp = opp_find_freq_ceil(cpu_dev, &freq_Hz);
+               opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
                if (IS_ERR(opp)) {
                        rcu_read_unlock();
                        pr_err("failed to find OPP for %ld\n", freq_Hz);
-                       freqs.new = freqs.old;
-                       ret = PTR_ERR(opp);
-                       goto post_notify;
+                       return PTR_ERR(opp);
                }
-               volt = opp_get_voltage(opp);
+               volt = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
                tol = volt * voltage_tolerance / 100;
                volt_old = regulator_get_voltage(cpu_reg);
        }
 
        pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n",
-                freqs.old / 1000, volt_old ? volt_old / 1000 : -1,
-                freqs.new / 1000, volt ? volt / 1000 : -1);
+                old_freq / 1000, volt_old ? volt_old / 1000 : -1,
+                new_freq / 1000, volt ? volt / 1000 : -1);
 
        /* scaling up?  scale voltage before frequency */
-       if (!IS_ERR(cpu_reg) && freqs.new > freqs.old) {
+       if (!IS_ERR(cpu_reg) && new_freq > old_freq) {
                ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
                if (ret) {
                        pr_err("failed to scale voltage up: %d\n", ret);
-                       freqs.new = freqs.old;
-                       goto post_notify;
+                       return ret;
                }
        }
 
@@ -105,72 +83,35 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
                pr_err("failed to set clock rate: %d\n", ret);
                if (!IS_ERR(cpu_reg))
                        regulator_set_voltage_tol(cpu_reg, volt_old, tol);
-               freqs.new = freqs.old;
-               goto post_notify;
+               return ret;
        }
 
        /* scaling down?  scale voltage after frequency */
-       if (!IS_ERR(cpu_reg) && freqs.new < freqs.old) {
+       if (!IS_ERR(cpu_reg) && new_freq < old_freq) {
                ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
                if (ret) {
                        pr_err("failed to scale voltage down: %d\n", ret);
-                       clk_set_rate(cpu_clk, freqs.old * 1000);
-                       freqs.new = freqs.old;
+                       clk_set_rate(cpu_clk, old_freq * 1000);
                }
        }
 
-post_notify:
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
        return ret;
 }
 
 static int cpu0_cpufreq_init(struct cpufreq_policy *policy)
 {
-       int ret;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       if (ret) {
-               pr_err("invalid frequency table: %d\n", ret);
-               return ret;
-       }
-
-       policy->cpuinfo.transition_latency = transition_latency;
-       policy->cur = clk_get_rate(cpu_clk) / 1000;
-
-       /*
-        * The driver only supports the SMP configuartion where all processors
-        * share the clock and voltage and clock.  Use cpufreq affected_cpus
-        * interface to have all CPUs scaled together.
-        */
-       cpumask_setall(policy->cpus);
-
-       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-
-       return 0;
+       return cpufreq_generic_init(policy, freq_table, transition_latency);
 }
 
-static int cpu0_cpufreq_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-
-       return 0;
-}
-
-static struct freq_attr *cpu0_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver cpu0_cpufreq_driver = {
        .flags = CPUFREQ_STICKY,
-       .verify = cpu0_verify_speed,
-       .target = cpu0_set_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = cpu0_set_target,
        .get = cpu0_get_speed,
        .init = cpu0_cpufreq_init,
-       .exit = cpu0_cpufreq_exit,
+       .exit = cpufreq_generic_exit,
        .name = "generic_cpu0",
-       .attr = cpu0_cpufreq_attr,
+       .attr = cpufreq_generic_attr,
 };
 
 static int cpu0_cpufreq_probe(struct platform_device *pdev)
@@ -218,7 +159,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
                goto out_put_node;
        }
 
-       ret = opp_init_cpufreq_table(cpu_dev, &freq_table);
+       ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
        if (ret) {
                pr_err("failed to init cpufreq table: %d\n", ret);
                goto out_put_node;
@@ -230,7 +171,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
                transition_latency = CPUFREQ_ETERNAL;
 
        if (!IS_ERR(cpu_reg)) {
-               struct opp *opp;
+               struct dev_pm_opp *opp;
                unsigned long min_uV, max_uV;
                int i;
 
@@ -242,12 +183,12 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
                for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
                        ;
                rcu_read_lock();
-               opp = opp_find_freq_exact(cpu_dev,
+               opp = dev_pm_opp_find_freq_exact(cpu_dev,
                                freq_table[0].frequency * 1000, true);
-               min_uV = opp_get_voltage(opp);
-               opp = opp_find_freq_exact(cpu_dev,
+               min_uV = dev_pm_opp_get_voltage(opp);
+               opp = dev_pm_opp_find_freq_exact(cpu_dev,
                                freq_table[i-1].frequency * 1000, true);
-               max_uV = opp_get_voltage(opp);
+               max_uV = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
                ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
                if (ret > 0)
@@ -264,7 +205,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
        return 0;
 
 out_free_table:
-       opp_free_cpufreq_table(cpu_dev, &freq_table);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
 out_put_node:
        of_node_put(np);
        return ret;
@@ -273,7 +214,7 @@ out_put_node:
 static int cpu0_cpufreq_remove(struct platform_device *pdev)
 {
        cpufreq_unregister_driver(&cpu0_cpufreq_driver);
-       opp_free_cpufreq_table(cpu_dev, &freq_table);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
 
        return 0;
 }
index b83d45f6857495083163e13336027ef4449b5da2..a05b876f375e5672c00b05412782c23ead83a773 100644 (file)
@@ -303,9 +303,7 @@ static int nforce2_verify(struct cpufreq_policy *policy)
        if (policy->min < (fsb_pol_max * fid * 100))
                policy->max = (fsb_pol_max + 1) * fid * 100;
 
-       cpufreq_verify_within_limits(policy,
-                                    policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
        return 0;
 }
 
@@ -362,7 +360,6 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy)
        policy->min = policy->cpuinfo.min_freq = min_fsb * fid * 100;
        policy->max = policy->cpuinfo.max_freq = max_fsb * fid * 100;
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       policy->cur = nforce2_get(policy->cpu);
 
        return 0;
 }
index 04548f7023af68dee6b36fc590ec59f02c0216f7..02d534da22dda0bb22277c4f80f7c1d27f24cd65 100644 (file)
@@ -47,49 +47,11 @@ static LIST_HEAD(cpufreq_policy_list);
 static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
 #endif
 
-/*
- * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
- * all cpufreq/hotplug/workqueue/etc related lock issues.
- *
- * The rules for this semaphore:
- * - Any routine that wants to read from the policy structure will
- *   do a down_read on this semaphore.
- * - Any routine that will write to the policy structure and/or may take away
- *   the policy altogether (eg. CPU hotplug), will hold this lock in write
- *   mode before doing so.
- *
- * Additional rules:
- * - Governor routines that can be called in cpufreq hotplug path should not
- *   take this sem as top level hotplug notifier handler takes this.
- * - Lock should not be held across
- *     __cpufreq_governor(data, CPUFREQ_GOV_STOP);
- */
-static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem);
-
-#define lock_policy_rwsem(mode, cpu)                                   \
-static int lock_policy_rwsem_##mode(int cpu)                           \
-{                                                                      \
-       struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); \
-       BUG_ON(!policy);                                                \
-       down_##mode(&per_cpu(cpu_policy_rwsem, policy->cpu));           \
-                                                                       \
-       return 0;                                                       \
-}
-
-lock_policy_rwsem(read, cpu);
-lock_policy_rwsem(write, cpu);
-
-#define unlock_policy_rwsem(mode, cpu)                                 \
-static void unlock_policy_rwsem_##mode(int cpu)                                \
-{                                                                      \
-       struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); \
-       BUG_ON(!policy);                                                \
-       up_##mode(&per_cpu(cpu_policy_rwsem, policy->cpu));             \
+static inline bool has_target(void)
+{
+       return cpufreq_driver->target_index || cpufreq_driver->target;
 }
 
-unlock_policy_rwsem(read, cpu);
-unlock_policy_rwsem(write, cpu);
-
 /*
  * rwsem to guarantee that cpufreq driver module doesn't unload during critical
  * sections
@@ -135,7 +97,7 @@ static DEFINE_MUTEX(cpufreq_governor_mutex);
 
 bool have_governor_per_policy(void)
 {
-       return cpufreq_driver->have_governor_per_policy;
+       return !!(cpufreq_driver->flags & CPUFREQ_HAVE_GOVERNOR_PER_POLICY);
 }
 EXPORT_SYMBOL_GPL(have_governor_per_policy);
 
@@ -183,6 +145,37 @@ u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy)
 }
 EXPORT_SYMBOL_GPL(get_cpu_idle_time);
 
+/*
+ * This is a generic cpufreq init() routine which can be used by cpufreq
+ * drivers of SMP systems. It will do following:
+ * - validate & show freq table passed
+ * - set policies transition latency
+ * - policy->cpus with all possible CPUs
+ */
+int cpufreq_generic_init(struct cpufreq_policy *policy,
+               struct cpufreq_frequency_table *table,
+               unsigned int transition_latency)
+{
+       int ret;
+
+       ret = cpufreq_table_validate_and_show(policy, table);
+       if (ret) {
+               pr_err("%s: invalid frequency table: %d\n", __func__, ret);
+               return ret;
+       }
+
+       policy->cpuinfo.transition_latency = transition_latency;
+
+       /*
+        * The driver only supports the SMP configuartion where all processors
+        * share the clock and voltage and clock.
+        */
+       cpumask_setall(policy->cpus);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_generic_init);
+
 struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
 {
        struct cpufreq_policy *policy = NULL;
@@ -363,7 +356,7 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy,
                        *policy = CPUFREQ_POLICY_POWERSAVE;
                        err = 0;
                }
-       } else if (cpufreq_driver->target) {
+       } else if (has_target()) {
                struct cpufreq_governor *t;
 
                mutex_lock(&cpufreq_governor_mutex);
@@ -414,7 +407,7 @@ show_one(scaling_min_freq, min);
 show_one(scaling_max_freq, max);
 show_one(scaling_cur_freq, cur);
 
-static int __cpufreq_set_policy(struct cpufreq_policy *policy,
+static int cpufreq_set_policy(struct cpufreq_policy *policy,
                                struct cpufreq_policy *new_policy);
 
 /**
@@ -435,7 +428,7 @@ static ssize_t store_##file_name                                    \
        if (ret != 1)                                                   \
                return -EINVAL;                                         \
                                                                        \
-       ret = __cpufreq_set_policy(policy, &new_policy);                \
+       ret = cpufreq_set_policy(policy, &new_policy);          \
        policy->user_policy.object = policy->object;                    \
                                                                        \
        return ret ? ret : count;                                       \
@@ -493,11 +486,7 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
                                                &new_policy.governor))
                return -EINVAL;
 
-       /*
-        * Do not use cpufreq_set_policy here or the user_policy.max
-        * will be wrongly overridden
-        */
-       ret = __cpufreq_set_policy(policy, &new_policy);
+       ret = cpufreq_set_policy(policy, &new_policy);
 
        policy->user_policy.policy = policy->policy;
        policy->user_policy.governor = policy->governor;
@@ -525,7 +514,7 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
        ssize_t i = 0;
        struct cpufreq_governor *t;
 
-       if (!cpufreq_driver->target) {
+       if (!has_target()) {
                i += sprintf(buf, "performance powersave");
                goto out;
        }
@@ -653,24 +642,21 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
 {
        struct cpufreq_policy *policy = to_policy(kobj);
        struct freq_attr *fattr = to_attr(attr);
-       ssize_t ret = -EINVAL;
+       ssize_t ret;
 
        if (!down_read_trylock(&cpufreq_rwsem))
-               goto exit;
+               return -EINVAL;
 
-       if (lock_policy_rwsem_read(policy->cpu) < 0)
-               goto up_read;
+       down_read(&policy->rwsem);
 
        if (fattr->show)
                ret = fattr->show(policy, buf);
        else
                ret = -EIO;
 
-       unlock_policy_rwsem_read(policy->cpu);
-
-up_read:
+       up_read(&policy->rwsem);
        up_read(&cpufreq_rwsem);
-exit:
+
        return ret;
 }
 
@@ -689,17 +675,15 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
        if (!down_read_trylock(&cpufreq_rwsem))
                goto unlock;
 
-       if (lock_policy_rwsem_write(policy->cpu) < 0)
-               goto up_read;
+       down_write(&policy->rwsem);
 
        if (fattr->store)
                ret = fattr->store(policy, buf, count);
        else
                ret = -EIO;
 
-       unlock_policy_rwsem_write(policy->cpu);
+       up_write(&policy->rwsem);
 
-up_read:
        up_read(&cpufreq_rwsem);
 unlock:
        put_online_cpus();
@@ -815,7 +799,7 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
                if (ret)
                        goto err_out_kobj_put;
        }
-       if (cpufreq_driver->target) {
+       if (has_target()) {
                ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
                if (ret)
                        goto err_out_kobj_put;
@@ -844,11 +828,11 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
        int ret = 0;
 
        memcpy(&new_policy, policy, sizeof(*policy));
-       /* assure that the starting sequence is run in __cpufreq_set_policy */
+       /* assure that the starting sequence is run in cpufreq_set_policy */
        policy->governor = NULL;
 
        /* set default policy */
-       ret = __cpufreq_set_policy(policy, &new_policy);
+       ret = cpufreq_set_policy(policy, &new_policy);
        policy->user_policy.policy = policy->policy;
        policy->user_policy.governor = policy->governor;
 
@@ -864,10 +848,10 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
                                  unsigned int cpu, struct device *dev,
                                  bool frozen)
 {
-       int ret = 0, has_target = !!cpufreq_driver->target;
+       int ret = 0;
        unsigned long flags;
 
-       if (has_target) {
+       if (has_target()) {
                ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
                if (ret) {
                        pr_err("%s: Failed to stop governor\n", __func__);
@@ -875,7 +859,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
                }
        }
 
-       lock_policy_rwsem_write(policy->cpu);
+       down_write(&policy->rwsem);
 
        write_lock_irqsave(&cpufreq_driver_lock, flags);
 
@@ -883,9 +867,9 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
        per_cpu(cpufreq_cpu_data, cpu) = policy;
        write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
-       unlock_policy_rwsem_write(policy->cpu);
+       up_write(&policy->rwsem);
 
-       if (has_target) {
+       if (has_target()) {
                if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) ||
                        (ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) {
                        pr_err("%s: Failed to start governor\n", __func__);
@@ -930,6 +914,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(void)
                goto err_free_cpumask;
 
        INIT_LIST_HEAD(&policy->policy_list);
+       init_rwsem(&policy->rwsem);
+
        return policy;
 
 err_free_cpumask:
@@ -949,26 +935,17 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
 
 static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
 {
-       if (cpu == policy->cpu)
+       if (WARN_ON(cpu == policy->cpu))
                return;
 
-       /*
-        * Take direct locks as lock_policy_rwsem_write wouldn't work here.
-        * Also lock for last cpu is enough here as contention will happen only
-        * after policy->cpu is changed and after it is changed, other threads
-        * will try to acquire lock for new cpu. And policy is already updated
-        * by then.
-        */
-       down_write(&per_cpu(cpu_policy_rwsem, policy->cpu));
+       down_write(&policy->rwsem);
 
        policy->last_cpu = policy->cpu;
        policy->cpu = cpu;
 
-       up_write(&per_cpu(cpu_policy_rwsem, policy->last_cpu));
+       up_write(&policy->rwsem);
 
-#ifdef CONFIG_CPU_FREQ_TABLE
        cpufreq_frequency_table_update_policy_cpu(policy);
-#endif
        blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                        CPUFREQ_UPDATE_POLICY_CPU, policy);
 }
@@ -1053,6 +1030,14 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
                goto err_set_policy_cpu;
        }
 
+       if (cpufreq_driver->get) {
+               policy->cur = cpufreq_driver->get(policy->cpu);
+               if (!policy->cur) {
+                       pr_err("%s: ->get() failed\n", __func__);
+                       goto err_get_freq;
+               }
+       }
+
        /* related cpus should atleast have policy->cpus */
        cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
 
@@ -1107,6 +1092,9 @@ err_out_unregister:
                per_cpu(cpufreq_cpu_data, j) = NULL;
        write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
+err_get_freq:
+       if (cpufreq_driver->exit)
+               cpufreq_driver->exit(policy);
 err_set_policy_cpu:
        cpufreq_policy_free(policy);
 nomem_out:
@@ -1147,9 +1135,9 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
        if (ret) {
                pr_err("%s: Failed to move kobj: %d", __func__, ret);
 
-               WARN_ON(lock_policy_rwsem_write(old_cpu));
+               down_write(&policy->rwsem);
                cpumask_set_cpu(old_cpu, policy->cpus);
-               unlock_policy_rwsem_write(old_cpu);
+               up_write(&policy->rwsem);
 
                ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
                                        "cpufreq");
@@ -1186,7 +1174,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
                return -EINVAL;
        }
 
-       if (cpufreq_driver->target) {
+       if (has_target()) {
                ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
                if (ret) {
                        pr_err("%s: Failed to stop governor\n", __func__);
@@ -1200,22 +1188,21 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
                        policy->governor->name, CPUFREQ_NAME_LEN);
 #endif
 
-       lock_policy_rwsem_read(cpu);
+       down_read(&policy->rwsem);
        cpus = cpumask_weight(policy->cpus);
-       unlock_policy_rwsem_read(cpu);
+       up_read(&policy->rwsem);
 
        if (cpu != policy->cpu) {
                if (!frozen)
                        sysfs_remove_link(&dev->kobj, "cpufreq");
        } else if (cpus > 1) {
-
                new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
                if (new_cpu >= 0) {
                        update_policy_cpu(policy, new_cpu);
 
                        if (!frozen) {
-                               pr_debug("%s: policy Kobject moved to cpu: %d "
-                                        "from: %d\n",__func__, new_cpu, cpu);
+                               pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
+                                               __func__, new_cpu, cpu);
                        }
                }
        }
@@ -1243,16 +1230,16 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
                return -EINVAL;
        }
 
-       WARN_ON(lock_policy_rwsem_write(cpu));
+       down_write(&policy->rwsem);
        cpus = cpumask_weight(policy->cpus);
 
        if (cpus > 1)
                cpumask_clear_cpu(cpu, policy->cpus);
-       unlock_policy_rwsem_write(cpu);
+       up_write(&policy->rwsem);
 
        /* If cpu is last user of policy, free policy */
        if (cpus == 1) {
-               if (cpufreq_driver->target) {
+               if (has_target()) {
                        ret = __cpufreq_governor(policy,
                                        CPUFREQ_GOV_POLICY_EXIT);
                        if (ret) {
@@ -1263,10 +1250,10 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
                }
 
                if (!frozen) {
-                       lock_policy_rwsem_read(cpu);
+                       down_read(&policy->rwsem);
                        kobj = &policy->kobj;
                        cmp = &policy->kobj_unregister;
-                       unlock_policy_rwsem_read(cpu);
+                       up_read(&policy->rwsem);
                        kobject_put(kobj);
 
                        /*
@@ -1295,7 +1282,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
                if (!frozen)
                        cpufreq_policy_free(policy);
        } else {
-               if (cpufreq_driver->target) {
+               if (has_target()) {
                        if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) ||
                                        (ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) {
                                pr_err("%s: Failed to start governor\n",
@@ -1310,36 +1297,24 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
 }
 
 /**
- * __cpufreq_remove_dev - remove a CPU device
+ * cpufreq_remove_dev - remove a CPU device
  *
  * Removes the cpufreq interface for a CPU device.
- * Caller should already have policy_rwsem in write mode for this CPU.
- * This routine frees the rwsem before returning.
  */
-static inline int __cpufreq_remove_dev(struct device *dev,
-                                      struct subsys_interface *sif,
-                                      bool frozen)
-{
-       int ret;
-
-       ret = __cpufreq_remove_dev_prepare(dev, sif, frozen);
-
-       if (!ret)
-               ret = __cpufreq_remove_dev_finish(dev, sif, frozen);
-
-       return ret;
-}
-
 static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
 {
        unsigned int cpu = dev->id;
-       int retval;
+       int ret;
 
        if (cpu_is_offline(cpu))
                return 0;
 
-       retval = __cpufreq_remove_dev(dev, sif, false);
-       return retval;
+       ret = __cpufreq_remove_dev_prepare(dev, sif, false);
+
+       if (!ret)
+               ret = __cpufreq_remove_dev_finish(dev, sif, false);
+
+       return ret;
 }
 
 static void handle_update(struct work_struct *work)
@@ -1458,22 +1433,22 @@ static unsigned int __cpufreq_get(unsigned int cpu)
  */
 unsigned int cpufreq_get(unsigned int cpu)
 {
+       struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
        unsigned int ret_freq = 0;
 
        if (cpufreq_disabled() || !cpufreq_driver)
                return -ENOENT;
 
+       BUG_ON(!policy);
+
        if (!down_read_trylock(&cpufreq_rwsem))
                return 0;
 
-       if (unlikely(lock_policy_rwsem_read(cpu)))
-               goto out_policy;
+       down_read(&policy->rwsem);
 
        ret_freq = __cpufreq_get(cpu);
 
-       unlock_policy_rwsem_read(cpu);
-
-out_policy:
+       up_read(&policy->rwsem);
        up_read(&cpufreq_rwsem);
 
        return ret_freq;
@@ -1681,12 +1656,75 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
        pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
                        policy->cpu, target_freq, relation, old_target_freq);
 
+       /*
+        * This might look like a redundant call as we are checking it again
+        * after finding index. But it is left intentionally for cases where
+        * exactly same freq is called again and so we can save on few function
+        * calls.
+        */
        if (target_freq == policy->cur)
                return 0;
 
        if (cpufreq_driver->target)
                retval = cpufreq_driver->target(policy, target_freq, relation);
+       else if (cpufreq_driver->target_index) {
+               struct cpufreq_frequency_table *freq_table;
+               struct cpufreq_freqs freqs;
+               bool notify;
+               int index;
+
+               freq_table = cpufreq_frequency_get_table(policy->cpu);
+               if (unlikely(!freq_table)) {
+                       pr_err("%s: Unable to find freq_table\n", __func__);
+                       goto out;
+               }
+
+               retval = cpufreq_frequency_table_target(policy, freq_table,
+                               target_freq, relation, &index);
+               if (unlikely(retval)) {
+                       pr_err("%s: Unable to find matching freq\n", __func__);
+                       goto out;
+               }
+
+               if (freq_table[index].frequency == policy->cur) {
+                       retval = 0;
+                       goto out;
+               }
+
+               notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION);
+
+               if (notify) {
+                       freqs.old = policy->cur;
+                       freqs.new = freq_table[index].frequency;
+                       freqs.flags = 0;
+
+                       pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
+                                       __func__, policy->cpu, freqs.old,
+                                       freqs.new);
+
+                       cpufreq_notify_transition(policy, &freqs,
+                                       CPUFREQ_PRECHANGE);
+               }
+
+               retval = cpufreq_driver->target_index(policy, index);
+               if (retval)
+                       pr_err("%s: Failed to change cpu frequency: %d\n",
+                                       __func__, retval);
+
+               if (notify) {
+                       /*
+                        * Notify with old freq in case we failed to change
+                        * frequency
+                        */
+                       if (retval)
+                               freqs.new = freqs.old;
+
+                       cpufreq_notify_transition(policy, &freqs,
+                                       CPUFREQ_POSTCHANGE);
+               }
+       }
 
+out:
        return retval;
 }
 EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
@@ -1697,14 +1735,12 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
 {
        int ret = -EINVAL;
 
-       if (unlikely(lock_policy_rwsem_write(policy->cpu)))
-               goto fail;
+       down_write(&policy->rwsem);
 
        ret = __cpufreq_driver_target(policy, target_freq, relation);
 
-       unlock_policy_rwsem_write(policy->cpu);
+       up_write(&policy->rwsem);
 
-fail:
        return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
@@ -1871,10 +1907,10 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
 EXPORT_SYMBOL(cpufreq_get_policy);
 
 /*
- * data   : current policy.
- * policy : policy to be set.
+ * policy : current policy.
+ * new_policy: policy to be set.
  */
-static int __cpufreq_set_policy(struct cpufreq_policy *policy,
+static int cpufreq_set_policy(struct cpufreq_policy *policy,
                                struct cpufreq_policy *new_policy)
 {
        int ret = 0, failed = 1;
@@ -1934,10 +1970,10 @@ static int __cpufreq_set_policy(struct cpufreq_policy *policy,
                        /* end old governor */
                        if (policy->governor) {
                                __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
-                               unlock_policy_rwsem_write(new_policy->cpu);
+                               up_write(&policy->rwsem);
                                __cpufreq_governor(policy,
                                                CPUFREQ_GOV_POLICY_EXIT);
-                               lock_policy_rwsem_write(new_policy->cpu);
+                               down_write(&policy->rwsem);
                        }
 
                        /* start new governor */
@@ -1946,10 +1982,10 @@ static int __cpufreq_set_policy(struct cpufreq_policy *policy,
                                if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) {
                                        failed = 0;
                                } else {
-                                       unlock_policy_rwsem_write(new_policy->cpu);
+                                       up_write(&policy->rwsem);
                                        __cpufreq_governor(policy,
                                                        CPUFREQ_GOV_POLICY_EXIT);
-                                       lock_policy_rwsem_write(new_policy->cpu);
+                                       down_write(&policy->rwsem);
                                }
                        }
 
@@ -1995,10 +2031,7 @@ int cpufreq_update_policy(unsigned int cpu)
                goto no_policy;
        }
 
-       if (unlikely(lock_policy_rwsem_write(cpu))) {
-               ret = -EINVAL;
-               goto fail;
-       }
+       down_write(&policy->rwsem);
 
        pr_debug("updating policy for CPU %u\n", cpu);
        memcpy(&new_policy, policy, sizeof(*policy));
@@ -2017,17 +2050,16 @@ int cpufreq_update_policy(unsigned int cpu)
                        pr_debug("Driver did not initialize current freq");
                        policy->cur = new_policy.cur;
                } else {
-                       if (policy->cur != new_policy.cur && cpufreq_driver->target)
+                       if (policy->cur != new_policy.cur && has_target())
                                cpufreq_out_of_sync(cpu, policy->cur,
                                                                new_policy.cur);
                }
        }
 
-       ret = __cpufreq_set_policy(policy, &new_policy);
+       ret = cpufreq_set_policy(policy, &new_policy);
 
-       unlock_policy_rwsem_write(cpu);
+       up_write(&policy->rwsem);
 
-fail:
        cpufreq_cpu_put(policy);
 no_policy:
        return ret;
@@ -2096,7 +2128,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
                return -ENODEV;
 
        if (!driver_data || !driver_data->verify || !driver_data->init ||
-           ((!driver_data->setpolicy) && (!driver_data->target)))
+           !(driver_data->setpolicy || driver_data->target_index ||
+                   driver_data->target))
                return -EINVAL;
 
        pr_debug("trying to register driver %s\n", driver_data->name);
@@ -2183,14 +2216,9 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
 
 static int __init cpufreq_core_init(void)
 {
-       int cpu;
-
        if (cpufreq_disabled())
                return -ENODEV;
 
-       for_each_possible_cpu(cpu)
-               init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
-
        cpufreq_global_kobject = kobject_create();
        BUG_ON(!cpufreq_global_kobject);
        register_syscore_ops(&cpufreq_syscore_ops);
index 88cd39f7b0e9573b4fc7e5ca13ac0126cf6ede9d..b5f2b8618949dc75d55202d7b76e56e1e0c52a5f 100644 (file)
@@ -191,7 +191,10 @@ struct common_dbs_data {
        struct attribute_group *attr_group_gov_sys; /* one governor - system */
        struct attribute_group *attr_group_gov_pol; /* one governor - policy */
 
-       /* Common data for platforms that don't set have_governor_per_policy */
+       /*
+        * Common data for platforms that don't set
+        * CPUFREQ_HAVE_GOVERNOR_PER_POLICY
+        */
        struct dbs_data *gdbs_data;
 
        struct cpu_dbs_common_info *(*get_cpu_cdbs)(int cpu);
index 32f26f6e17c54cffb25d26383e6cc78cd3af7cec..18d4091890920048f8ad0301bd784ee29cfca074 100644 (file)
@@ -168,7 +168,6 @@ static void od_check_cpu(int cpu, unsigned int load)
                        dbs_info->rate_mult =
                                od_tuners->sampling_down_factor;
                dbs_freq_increase(policy, policy->max);
-               return;
        } else {
                /* Calculate the next frequency proportional to load */
                unsigned int freq_next;
index 03078090b5f76e15d263f3a035f575f9e7901342..4dbf1db16aca0e5d29d44b002a6d4ad0cae6d139 100644 (file)
@@ -38,18 +38,7 @@ static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
        if (!per_cpu(cpu_is_managed, policy->cpu))
                goto err;
 
-       /*
-        * We're safe from concurrent calls to ->target() here
-        * as we hold the userspace_mutex lock. If we were calling
-        * cpufreq_driver_target, a deadlock situation might occur:
-        * A: cpufreq_set (lock userspace_mutex) ->
-        *      cpufreq_driver_target(lock policy->lock)
-        * B: cpufreq_set_policy(lock policy->lock) ->
-        *      __cpufreq_governor ->
-        *         cpufreq_governor_userspace (lock userspace_mutex)
-        */
        ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
-
  err:
        mutex_unlock(&userspace_mutex);
        return ret;
index cb8276dd19caee0a5e2756883148a2d70a7132f2..86559040c54c83daad0778160cccdb7b19f43c22 100644 (file)
@@ -27,18 +27,11 @@ static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
        return clk_ctrl.pll ? 200000 : 6000;
 }
 
-static void cris_freq_set_cpu_state(struct cpufreq_policy *policy,
-               unsigned int state)
+static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state)
 {
-       struct cpufreq_freqs freqs;
        reg_clkgen_rw_clk_ctrl clk_ctrl;
        clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
 
-       freqs.old = cris_freq_get_cpu_frequency(policy->cpu);
-       freqs.new = cris_freq_table[state].frequency;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        local_irq_disable();
 
        /* Even though we may be SMP they will share the same clock
@@ -51,67 +44,22 @@ static void cris_freq_set_cpu_state(struct cpufreq_policy *policy,
 
        local_irq_enable();
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-};
-
-static int cris_freq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]);
-}
-
-static int cris_freq_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq,
-                           unsigned int relation)
-{
-       unsigned int newstate = 0;
-
-       if (cpufreq_frequency_table_target(policy, cris_freq_table,
-                       target_freq, relation, &newstate))
-               return -EINVAL;
-
-       cris_freq_set_cpu_state(policy, newstate);
-
        return 0;
 }
 
 static int cris_freq_cpu_init(struct cpufreq_policy *policy)
 {
-       int result;
-
-       /* cpuinfo and default policy values */
-       policy->cpuinfo.transition_latency = 1000000; /* 1ms */
-       policy->cur = cris_freq_get_cpu_frequency(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table);
-       if (result)
-               return (result);
-
-       cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu);
-
-       return 0;
-}
-
-
-static int cris_freq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_generic_init(policy, cris_freq_table, 1000000);
 }
 
-
-static struct freq_attr *cris_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver cris_freq_driver = {
        .get    = cris_freq_get_cpu_frequency,
-       .verify = cris_freq_verify,
-       .target = cris_freq_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = cris_freq_target,
        .init   = cris_freq_cpu_init,
-       .exit   = cris_freq_cpu_exit,
+       .exit   = cpufreq_generic_exit,
        .name   = "cris_freq",
-       .attr   = cris_freq_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static int __init cris_freq_init(void)
index 72328f77dc53bdef993173a1832d3159ac3fd03c..26d940d40b1dcb1e19208a17176afe88e5632f35 100644 (file)
@@ -27,18 +27,11 @@ static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
        return clk_ctrl.pll ? 200000 : 6000;
 }
 
-static void cris_freq_set_cpu_state(struct cpufreq_policy *policy,
-               unsigned int state)
+static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state)
 {
-       struct cpufreq_freqs freqs;
        reg_config_rw_clk_ctrl clk_ctrl;
        clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl);
 
-       freqs.old = cris_freq_get_cpu_frequency(policy->cpu);
-       freqs.new = cris_freq_table[state].frequency;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        local_irq_disable();
 
        /* Even though we may be SMP they will share the same clock
@@ -51,64 +44,22 @@ static void cris_freq_set_cpu_state(struct cpufreq_policy *policy,
 
        local_irq_enable();
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-};
-
-static int cris_freq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]);
-}
-
-static int cris_freq_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq, unsigned int relation)
-{
-       unsigned int newstate = 0;
-
-       if (cpufreq_frequency_table_target
-           (policy, cris_freq_table, target_freq, relation, &newstate))
-               return -EINVAL;
-
-       cris_freq_set_cpu_state(policy, newstate);
-
        return 0;
 }
 
 static int cris_freq_cpu_init(struct cpufreq_policy *policy)
 {
-       int result;
-
-       /* cpuinfo and default policy values */
-       policy->cpuinfo.transition_latency = 1000000;   /* 1ms */
-       policy->cur = cris_freq_get_cpu_frequency(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table);
-       if (result)
-               return (result);
-
-       cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu);
-
-       return 0;
+       return cpufreq_generic_init(policy, cris_freq_table, 1000000);
 }
 
-static int cris_freq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
-static struct freq_attr *cris_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver cris_freq_driver = {
        .get = cris_freq_get_cpu_frequency,
-       .verify = cris_freq_verify,
-       .target = cris_freq_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = cris_freq_target,
        .init = cris_freq_cpu_init,
-       .exit = cris_freq_cpu_exit,
+       .exit = cpufreq_generic_exit,
        .name = "cris_freq",
-       .attr = cris_freq_attr,
+       .attr = cpufreq_generic_attr,
 };
 
 static int __init cris_freq_init(void)
index 551dd655c6f2ac1d49fb1238ee20f38c213e3f36..5e8a854381b781876eb6ae3658e0a40ce632195a 100644 (file)
@@ -50,9 +50,7 @@ static int davinci_verify_speed(struct cpufreq_policy *policy)
        if (policy->cpu)
                return -EINVAL;
 
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
-
+       cpufreq_verify_within_cpu_limits(policy);
        policy->min = clk_round_rate(armclk, policy->min * 1000) / 1000;
        policy->max = clk_round_rate(armclk, policy->max * 1000) / 1000;
        cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
@@ -68,58 +66,38 @@ static unsigned int davinci_getspeed(unsigned int cpu)
        return clk_get_rate(cpufreq.armclk) / 1000;
 }
 
-static int davinci_target(struct cpufreq_policy *policy,
-                               unsigned int target_freq, unsigned int relation)
+static int davinci_target(struct cpufreq_policy *policy, unsigned int idx)
 {
-       int ret = 0;
-       unsigned int idx;
-       struct cpufreq_freqs freqs;
        struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
        struct clk *armclk = cpufreq.armclk;
+       unsigned int old_freq, new_freq;
+       int ret = 0;
 
-       freqs.old = davinci_getspeed(0);
-       freqs.new = clk_round_rate(armclk, target_freq * 1000) / 1000;
-
-       if (freqs.old == freqs.new)
-               return ret;
-
-       dev_dbg(cpufreq.dev, "transition: %u --> %u\n", freqs.old, freqs.new);
-
-       ret = cpufreq_frequency_table_target(policy, pdata->freq_table,
-                                               freqs.new, relation, &idx);
-       if (ret)
-               return -EINVAL;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+       old_freq = davinci_getspeed(0);
+       new_freq = pdata->freq_table[idx].frequency;
 
        /* if moving to higher frequency, up the voltage beforehand */
-       if (pdata->set_voltage && freqs.new > freqs.old) {
+       if (pdata->set_voltage && new_freq > old_freq) {
                ret = pdata->set_voltage(idx);
                if (ret)
-                       goto out;
+                       return ret;
        }
 
        ret = clk_set_rate(armclk, idx);
        if (ret)
-               goto out;
+               return ret;
 
        if (cpufreq.asyncclk) {
                ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate);
                if (ret)
-                       goto out;
+                       return ret;
        }
 
        /* if moving to lower freq, lower the voltage after lowering freq */
-       if (pdata->set_voltage && freqs.new < freqs.old)
+       if (pdata->set_voltage && new_freq < old_freq)
                pdata->set_voltage(idx);
 
-out:
-       if (ret)
-               freqs.new = freqs.old;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       return ret;
+       return 0;
 }
 
 static int davinci_cpu_init(struct cpufreq_policy *policy)
@@ -138,47 +116,24 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
                        return result;
        }
 
-       policy->cur = davinci_getspeed(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       if (result) {
-               pr_err("%s: cpufreq_frequency_table_cpuinfo() failed",
-                               __func__);
-               return result;
-       }
-
-       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-
        /*
         * Time measurement across the target() function yields ~1500-1800us
         * time taken with no drivers on notification list.
         * Setting the latency to 2000 us to accommodate addition of drivers
         * to pre/post change notification list.
         */
-       policy->cpuinfo.transition_latency = 2000 * 1000;
-       return 0;
+       return cpufreq_generic_init(policy, freq_table, 2000 * 1000);
 }
 
-static int davinci_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
-static struct freq_attr *davinci_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver davinci_driver = {
        .flags          = CPUFREQ_STICKY,
        .verify         = davinci_verify_speed,
-       .target         = davinci_target,
+       .target_index   = davinci_target,
        .get            = davinci_getspeed,
        .init           = davinci_cpu_init,
-       .exit           = davinci_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .name           = "davinci",
-       .attr           = davinci_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init davinci_cpufreq_probe(struct platform_device *pdev)
index 26321cdc19464f1cd3b23f7bf6575d5d97fa6ffc..0e67ab96321a7aa999802de779d6a65c16a468b0 100644 (file)
 static struct cpufreq_frequency_table *freq_table;
 static struct clk *armss_clk;
 
-static struct freq_attr *dbx500_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-static int dbx500_cpufreq_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
 static int dbx500_cpufreq_target(struct cpufreq_policy *policy,
-                               unsigned int target_freq,
-                               unsigned int relation)
+                               unsigned int index)
 {
-       struct cpufreq_freqs freqs;
-       unsigned int idx;
-       int ret;
-
-       /* Lookup the next frequency */
-       if (cpufreq_frequency_table_target(policy, freq_table, target_freq,
-                                       relation, &idx))
-               return -EINVAL;
-
-       freqs.old = policy->cur;
-       freqs.new = freq_table[idx].frequency;
-
-       if (freqs.old == freqs.new)
-               return 0;
-
-       /* pre-change notification */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        /* update armss clk frequency */
-       ret = clk_set_rate(armss_clk, freqs.new * 1000);
-
-       if (ret) {
-               pr_err("dbx500-cpufreq: Failed to set armss_clk to %d Hz: error %d\n",
-                      freqs.new * 1000, ret);
-               freqs.new = freqs.old;
-       }
-
-       /* post change notification */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       return ret;
+       return clk_set_rate(armss_clk, freq_table[index].frequency * 1000);
 }
 
 static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu)
@@ -84,43 +44,17 @@ static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu)
 
 static int dbx500_cpufreq_init(struct cpufreq_policy *policy)
 {
-       int res;
-
-       /* get policy fields based on the table */
-       res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       if (!res)
-               cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-       else {
-               pr_err("dbx500-cpufreq: Failed to read policy table\n");
-               return res;
-       }
-
-       policy->min = policy->cpuinfo.min_freq;
-       policy->max = policy->cpuinfo.max_freq;
-       policy->cur = dbx500_cpufreq_getspeed(policy->cpu);
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-
-       /*
-        * FIXME : Need to take time measurement across the target()
-        *         function with no/some/all drivers in the notification
-        *         list.
-        */
-       policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */
-
-       /* policy sharing between dual CPUs */
-       cpumask_setall(policy->cpus);
-
-       return 0;
+       return cpufreq_generic_init(policy, freq_table, 20 * 1000);
 }
 
 static struct cpufreq_driver dbx500_cpufreq_driver = {
        .flags  = CPUFREQ_STICKY | CPUFREQ_CONST_LOOPS,
-       .verify = dbx500_cpufreq_verify_speed,
-       .target = dbx500_cpufreq_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = dbx500_cpufreq_target,
        .get    = dbx500_cpufreq_getspeed,
        .init   = dbx500_cpufreq_init,
        .name   = "DBX500",
-       .attr   = dbx500_cpufreq_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static int dbx500_cpufreq_probe(struct platform_device *pdev)
index 09f64cc830197fc1f80f605e41d73be6b0441435..9012b8bb6b649abc18e6e1a623df56de69249a38 100644 (file)
@@ -107,15 +107,9 @@ static int eps_set_state(struct eps_cpu_data *centaur,
                         struct cpufreq_policy *policy,
                         u32 dest_state)
 {
-       struct cpufreq_freqs freqs;
        u32 lo, hi;
-       int err = 0;
        int i;
 
-       freqs.old = eps_get(policy->cpu);
-       freqs.new = centaur->fsb * ((dest_state >> 8) & 0xff);
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        /* Wait while CPU is busy */
        rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
        i = 0;
@@ -124,8 +118,7 @@ static int eps_set_state(struct eps_cpu_data *centaur,
                rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
                i++;
                if (unlikely(i > 64)) {
-                       err = -ENODEV;
-                       goto postchange;
+                       return -ENODEV;
                }
        }
        /* Set new multiplier and voltage */
@@ -137,16 +130,10 @@ static int eps_set_state(struct eps_cpu_data *centaur,
                rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
                i++;
                if (unlikely(i > 64)) {
-                       err = -ENODEV;
-                       goto postchange;
+                       return -ENODEV;
                }
        } while (lo & ((1 << 16) | (1 << 17)));
 
-       /* Return current frequency */
-postchange:
-       rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
-       freqs.new = centaur->fsb * ((lo >> 8) & 0xff);
-
 #ifdef DEBUG
        {
        u8 current_multiplier, current_voltage;
@@ -161,19 +148,12 @@ postchange:
                current_multiplier);
        }
 #endif
-       if (err)
-               freqs.new = freqs.old;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-       return err;
+       return 0;
 }
 
-static int eps_target(struct cpufreq_policy *policy,
-                              unsigned int target_freq,
-                              unsigned int relation)
+static int eps_target(struct cpufreq_policy *policy, unsigned int index)
 {
        struct eps_cpu_data *centaur;
-       unsigned int newstate = 0;
        unsigned int cpu = policy->cpu;
        unsigned int dest_state;
        int ret;
@@ -182,28 +162,14 @@ static int eps_target(struct cpufreq_policy *policy,
                return -ENODEV;
        centaur = eps_cpu[cpu];
 
-       if (unlikely(cpufreq_frequency_table_target(policy,
-                       &eps_cpu[cpu]->freq_table[0],
-                       target_freq,
-                       relation,
-                       &newstate))) {
-               return -EINVAL;
-       }
-
        /* Make frequency transition */
-       dest_state = centaur->freq_table[newstate].driver_data & 0xffff;
+       dest_state = centaur->freq_table[index].driver_data & 0xffff;
        ret = eps_set_state(centaur, policy, dest_state);
        if (ret)
                printk(KERN_ERR "eps: Timeout!\n");
        return ret;
 }
 
-static int eps_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                       &eps_cpu[policy->cpu]->freq_table[0]);
-}
-
 static int eps_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int i;
@@ -401,15 +367,13 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
        }
 
        policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */
-       policy->cur = fsb * current_multiplier;
 
-       ret = cpufreq_frequency_table_cpuinfo(policy, &centaur->freq_table[0]);
+       ret = cpufreq_table_validate_and_show(policy, &centaur->freq_table[0]);
        if (ret) {
                kfree(centaur);
                return ret;
        }
 
-       cpufreq_frequency_table_get_attr(&centaur->freq_table[0], policy->cpu);
        return 0;
 }
 
@@ -424,19 +388,14 @@ static int eps_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-static struct freq_attr *eps_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver eps_driver = {
-       .verify         = eps_verify,
-       .target         = eps_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = eps_target,
        .init           = eps_cpu_init,
        .exit           = eps_cpu_exit,
        .get            = eps_get,
        .name           = "e_powersaver",
-       .attr           = eps_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 
index 823a400d98fd6bc5f8c627db8151df572ffc68b9..de08acff5101dd64b93a913905a8961bfd08c69f 100644 (file)
@@ -105,32 +105,9 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
 }
 
 
-/**
- *     elanfreq_set_cpu_frequency: Change the CPU core frequency
- *     @cpu: cpu number
- *     @freq: frequency in kHz
- *
- *     This function takes a frequency value and changes the CPU frequency
- *     according to this. Note that the frequency has to be checked by
- *     elanfreq_validatespeed() for correctness!
- *
- *     There is no return value.
- */
-
-static void elanfreq_set_cpu_state(struct cpufreq_policy *policy,
-               unsigned int state)
+static int elanfreq_target(struct cpufreq_policy *policy,
+                           unsigned int state)
 {
-       struct cpufreq_freqs    freqs;
-
-       freqs.old = elanfreq_get_cpu_frequency(0);
-       freqs.new = elan_multiplier[state].clock;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
-       printk(KERN_INFO "elanfreq: attempting to set frequency to %i kHz\n",
-                       elan_multiplier[state].clock);
-
-
        /*
         * Access to the Elan's internal registers is indexed via
         * 0x22: Chip Setup & Control Register Index Register (CSCI)
@@ -161,39 +138,8 @@ static void elanfreq_set_cpu_state(struct cpufreq_policy *policy,
        udelay(10000);
        local_irq_enable();
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-};
-
-
-/**
- *     elanfreq_validatespeed: test if frequency range is valid
- *     @policy: the policy to validate
- *
- *     This function checks if a given frequency range in kHz is valid
- *     for the hardware supported by the driver.
- */
-
-static int elanfreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]);
-}
-
-static int elanfreq_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq,
-                           unsigned int relation)
-{
-       unsigned int newstate = 0;
-
-       if (cpufreq_frequency_table_target(policy, &elanfreq_table[0],
-                               target_freq, relation, &newstate))
-               return -EINVAL;
-
-       elanfreq_set_cpu_state(policy, newstate);
-
        return 0;
 }
-
-
 /*
  *     Module init and exit code
  */
@@ -202,7 +148,6 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
        unsigned int i;
-       int result;
 
        /* capability check */
        if ((c->x86_vendor != X86_VENDOR_AMD) ||
@@ -221,21 +166,8 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       policy->cur = elanfreq_get_cpu_frequency(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table);
-       if (result)
-               return result;
 
-       cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu);
-       return 0;
-}
-
-
-static int elanfreq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_table_validate_and_show(policy, elanfreq_table);
 }
 
 
@@ -261,20 +193,14 @@ __setup("elanfreq=", elanfreq_setup);
 #endif
 
 
-static struct freq_attr *elanfreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-
 static struct cpufreq_driver elanfreq_driver = {
        .get            = elanfreq_get_cpu_frequency,
-       .verify         = elanfreq_verify,
-       .target         = elanfreq_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = elanfreq_target,
        .init           = elanfreq_cpu_init,
-       .exit           = elanfreq_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .name           = "elanfreq",
-       .attr           = elanfreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id elan_id[] = {
index 0fac34439e3171dbc97b8f717a935b691657cba9..7b6dc06b1bd4958bea2be16b6a13e5c209953346 100644 (file)
 static struct exynos_dvfs_info *exynos_info;
 
 static struct regulator *arm_regulator;
-static struct cpufreq_freqs freqs;
 
 static unsigned int locking_frequency;
 static bool frequency_locked;
 static DEFINE_MUTEX(cpufreq_lock);
 
-static int exynos_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                                             exynos_info->freq_table);
-}
-
 static unsigned int exynos_getspeed(unsigned int cpu)
 {
        return clk_get_rate(exynos_info->cpu_clk) / 1000;
@@ -65,21 +58,18 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
        struct cpufreq_policy *policy = cpufreq_cpu_get(0);
        unsigned int arm_volt, safe_arm_volt = 0;
        unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz;
+       unsigned int old_freq;
        int index, old_index;
        int ret = 0;
 
-       freqs.old = policy->cur;
-       freqs.new = target_freq;
-
-       if (freqs.new == freqs.old)
-               goto out;
+       old_freq = policy->cur;
 
        /*
         * The policy max have been changed so that we cannot get proper
         * old_index with cpufreq_frequency_table_target(). Thus, ignore
         * policy and get the index from the raw freqeuncy table.
         */
-       old_index = exynos_cpufreq_get_index(freqs.old);
+       old_index = exynos_cpufreq_get_index(old_freq);
        if (old_index < 0) {
                ret = old_index;
                goto out;
@@ -104,17 +94,14 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
        }
        arm_volt = volt_table[index];
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        /* When the new frequency is higher than current frequency */
-       if ((freqs.new > freqs.old) && !safe_arm_volt) {
+       if ((target_freq > old_freq) && !safe_arm_volt) {
                /* Firstly, voltage up to increase frequency */
                ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
                if (ret) {
                        pr_err("%s: failed to set cpu voltage to %d\n",
                                __func__, arm_volt);
-                       freqs.new = freqs.old;
-                       goto post_notify;
+                       return ret;
                }
        }
 
@@ -124,24 +111,17 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
                if (ret) {
                        pr_err("%s: failed to set cpu voltage to %d\n",
                                __func__, safe_arm_volt);
-                       freqs.new = freqs.old;
-                       goto post_notify;
+                       return ret;
                }
        }
 
        exynos_info->set_freq(old_index, index);
 
-post_notify:
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       if (ret)
-               goto out;
-
        /* When the new frequency is lower than current frequency */
-       if ((freqs.new < freqs.old) ||
-          ((freqs.new > freqs.old) && safe_arm_volt)) {
+       if ((target_freq < old_freq) ||
+          ((target_freq > old_freq) && safe_arm_volt)) {
                /* down the voltage after frequency change */
-               regulator_set_voltage(arm_regulator, arm_volt,
+               ret = regulator_set_voltage(arm_regulator, arm_volt,
                                arm_volt);
                if (ret) {
                        pr_err("%s: failed to set cpu voltage to %d\n",
@@ -151,19 +131,14 @@ post_notify:
        }
 
 out:
-
        cpufreq_cpu_put(policy);
 
        return ret;
 }
 
-static int exynos_target(struct cpufreq_policy *policy,
-                         unsigned int target_freq,
-                         unsigned int relation)
+static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
 {
        struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
-       unsigned int index;
-       unsigned int new_freq;
        int ret = 0;
 
        mutex_lock(&cpufreq_lock);
@@ -171,15 +146,7 @@ static int exynos_target(struct cpufreq_policy *policy,
        if (frequency_locked)
                goto out;
 
-       if (cpufreq_frequency_table_target(policy, freq_table,
-                                          target_freq, relation, &index)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       new_freq = freq_table[index].frequency;
-
-       ret = exynos_cpufreq_scale(new_freq);
+       ret = exynos_cpufreq_scale(freq_table[index].frequency);
 
 out:
        mutex_unlock(&cpufreq_lock);
@@ -247,38 +214,18 @@ static struct notifier_block exynos_cpufreq_nb = {
 
 static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu);
-
-       cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
-
-       /* set the transition latency value */
-       policy->cpuinfo.transition_latency = 100000;
-
-       cpumask_setall(policy->cpus);
-
-       return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
-}
-
-static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
 }
 
-static struct freq_attr *exynos_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver exynos_driver = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = exynos_verify_speed,
-       .target         = exynos_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = exynos_target,
        .get            = exynos_getspeed,
        .init           = exynos_cpufreq_cpu_init,
-       .exit           = exynos_cpufreq_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .name           = "exynos_cpufreq",
-       .attr           = exynos_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 #ifdef CONFIG_PM
        .suspend        = exynos_cpufreq_suspend,
        .resume         = exynos_cpufreq_resume,
index add7fbec4fc9af5ca3060e925cfe662a25d21eb4..f2c75065ce198694428d631baef388ad8e9aa6c6 100644 (file)
@@ -81,9 +81,9 @@ static void exynos4210_set_clkdiv(unsigned int div_index)
 
 static void exynos4210_set_apll(unsigned int index)
 {
-       unsigned int tmp;
+       unsigned int tmp, freq = apll_freq_4210[index].freq;
 
-       /* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
+       /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
        clk_set_parent(moutcore, mout_mpll);
 
        do {
@@ -92,21 +92,9 @@ static void exynos4210_set_apll(unsigned int index)
                tmp &= 0x7;
        } while (tmp != 0x2);
 
-       /* 2. Set APLL Lock time */
-       __raw_writel(EXYNOS4_APLL_LOCKTIME, EXYNOS4_APLL_LOCK);
-
-       /* 3. Change PLL PMS values */
-       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-       tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
-       tmp |= apll_freq_4210[index].mps;
-       __raw_writel(tmp, EXYNOS4_APLL_CON0);
+       clk_set_rate(mout_apll, freq * 1000);
 
-       /* 4. wait_lock_time */
-       do {
-               tmp = __raw_readl(EXYNOS4_APLL_CON0);
-       } while (!(tmp & (0x1 << EXYNOS4_APLLCON0_LOCKED_SHIFT)));
-
-       /* 5. MUX_CORE_SEL = APLL */
+       /* MUX_CORE_SEL = APLL */
        clk_set_parent(moutcore, mout_apll);
 
        do {
@@ -115,53 +103,15 @@ static void exynos4210_set_apll(unsigned int index)
        } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
 }
 
-static bool exynos4210_pms_change(unsigned int old_index, unsigned int new_index)
-{
-       unsigned int old_pm = apll_freq_4210[old_index].mps >> 8;
-       unsigned int new_pm = apll_freq_4210[new_index].mps >> 8;
-
-       return (old_pm == new_pm) ? 0 : 1;
-}
-
 static void exynos4210_set_frequency(unsigned int old_index,
                                     unsigned int new_index)
 {
-       unsigned int tmp;
-
        if (old_index > new_index) {
-               if (!exynos4210_pms_change(old_index, new_index)) {
-                       /* 1. Change the system clock divider values */
-                       exynos4210_set_clkdiv(new_index);
-
-                       /* 2. Change just s value in apll m,p,s value */
-                       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-                       tmp &= ~(0x7 << 0);
-                       tmp |= apll_freq_4210[new_index].mps & 0x7;
-                       __raw_writel(tmp, EXYNOS4_APLL_CON0);
-               } else {
-                       /* Clock Configuration Procedure */
-                       /* 1. Change the system clock divider values */
-                       exynos4210_set_clkdiv(new_index);
-                       /* 2. Change the apll m,p,s value */
-                       exynos4210_set_apll(new_index);
-               }
+               exynos4210_set_clkdiv(new_index);
+               exynos4210_set_apll(new_index);
        } else if (old_index < new_index) {
-               if (!exynos4210_pms_change(old_index, new_index)) {
-                       /* 1. Change just s value in apll m,p,s value */
-                       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-                       tmp &= ~(0x7 << 0);
-                       tmp |= apll_freq_4210[new_index].mps & 0x7;
-                       __raw_writel(tmp, EXYNOS4_APLL_CON0);
-
-                       /* 2. Change the system clock divider values */
-                       exynos4210_set_clkdiv(new_index);
-               } else {
-                       /* Clock Configuration Procedure */
-                       /* 1. Change the apll m,p,s value */
-                       exynos4210_set_apll(new_index);
-                       /* 2. Change the system clock divider values */
-                       exynos4210_set_clkdiv(new_index);
-               }
+               exynos4210_set_apll(new_index);
+               exynos4210_set_clkdiv(new_index);
        }
 }
 
@@ -194,7 +144,6 @@ int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
        info->volt_table = exynos4210_volt_table;
        info->freq_table = exynos4210_freq_table;
        info->set_freq = exynos4210_set_frequency;
-       info->need_apll_change = exynos4210_pms_change;
 
        return 0;
 
index 08b7477b0aa23ea139faa00aef4d6eca601d173c..8683304ce62cc4dba0c947e2be6049e1b94ffcaf 100644 (file)
@@ -128,9 +128,9 @@ static void exynos4x12_set_clkdiv(unsigned int div_index)
 
 static void exynos4x12_set_apll(unsigned int index)
 {
-       unsigned int tmp, pdiv;
+       unsigned int tmp, freq = apll_freq_4x12[index].freq;
 
-       /* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
+       /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
        clk_set_parent(moutcore, mout_mpll);
 
        do {
@@ -140,24 +140,9 @@ static void exynos4x12_set_apll(unsigned int index)
                tmp &= 0x7;
        } while (tmp != 0x2);
 
-       /* 2. Set APLL Lock time */
-       pdiv = ((apll_freq_4x12[index].mps >> 8) & 0x3f);
+       clk_set_rate(mout_apll, freq * 1000);
 
-       __raw_writel((pdiv * 250), EXYNOS4_APLL_LOCK);
-
-       /* 3. Change PLL PMS values */
-       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-       tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
-       tmp |= apll_freq_4x12[index].mps;
-       __raw_writel(tmp, EXYNOS4_APLL_CON0);
-
-       /* 4. wait_lock_time */
-       do {
-               cpu_relax();
-               tmp = __raw_readl(EXYNOS4_APLL_CON0);
-       } while (!(tmp & (0x1 << EXYNOS4_APLLCON0_LOCKED_SHIFT)));
-
-       /* 5. MUX_CORE_SEL = APLL */
+       /* MUX_CORE_SEL = APLL */
        clk_set_parent(moutcore, mout_apll);
 
        do {
@@ -167,52 +152,15 @@ static void exynos4x12_set_apll(unsigned int index)
        } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
 }
 
-static bool exynos4x12_pms_change(unsigned int old_index, unsigned int new_index)
-{
-       unsigned int old_pm = apll_freq_4x12[old_index].mps >> 8;
-       unsigned int new_pm = apll_freq_4x12[new_index].mps >> 8;
-
-       return (old_pm == new_pm) ? 0 : 1;
-}
-
 static void exynos4x12_set_frequency(unsigned int old_index,
                                  unsigned int new_index)
 {
-       unsigned int tmp;
-
        if (old_index > new_index) {
-               if (!exynos4x12_pms_change(old_index, new_index)) {
-                       /* 1. Change the system clock divider values */
-                       exynos4x12_set_clkdiv(new_index);
-                       /* 2. Change just s value in apll m,p,s value */
-                       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-                       tmp &= ~(0x7 << 0);
-                       tmp |= apll_freq_4x12[new_index].mps & 0x7;
-                       __raw_writel(tmp, EXYNOS4_APLL_CON0);
-
-               } else {
-                       /* Clock Configuration Procedure */
-                       /* 1. Change the system clock divider values */
-                       exynos4x12_set_clkdiv(new_index);
-                       /* 2. Change the apll m,p,s value */
-                       exynos4x12_set_apll(new_index);
-               }
+               exynos4x12_set_clkdiv(new_index);
+               exynos4x12_set_apll(new_index);
        } else if (old_index < new_index) {
-               if (!exynos4x12_pms_change(old_index, new_index)) {
-                       /* 1. Change just s value in apll m,p,s value */
-                       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-                       tmp &= ~(0x7 << 0);
-                       tmp |= apll_freq_4x12[new_index].mps & 0x7;
-                       __raw_writel(tmp, EXYNOS4_APLL_CON0);
-                       /* 2. Change the system clock divider values */
-                       exynos4x12_set_clkdiv(new_index);
-               } else {
-                       /* Clock Configuration Procedure */
-                       /* 1. Change the apll m,p,s value */
-                       exynos4x12_set_apll(new_index);
-                       /* 2. Change the system clock divider values */
-                       exynos4x12_set_clkdiv(new_index);
-               }
+               exynos4x12_set_apll(new_index);
+               exynos4x12_set_clkdiv(new_index);
        }
 }
 
@@ -250,7 +198,6 @@ int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info)
        info->volt_table = exynos4x12_volt_table;
        info->freq_table = exynos4x12_freq_table;
        info->set_freq = exynos4x12_set_frequency;
-       info->need_apll_change = exynos4x12_pms_change;
 
        return 0;
 
index be5380ecdcd43f95c4aa88a62389c184597f3971..76bef8b078cbfa7c2d1364375063c344ae00fcd0 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
@@ -118,12 +118,12 @@ static int init_div_table(void)
        struct cpufreq_frequency_table *freq_tbl = dvfs_info->freq_table;
        unsigned int tmp, clk_div, ema_div, freq, volt_id;
        int i = 0;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
 
        rcu_read_lock();
        for (i = 0; freq_tbl[i].frequency != CPUFREQ_TABLE_END; i++) {
 
-               opp = opp_find_freq_exact(dvfs_info->dev,
+               opp = dev_pm_opp_find_freq_exact(dvfs_info->dev,
                                        freq_tbl[i].frequency * 1000, true);
                if (IS_ERR(opp)) {
                        rcu_read_unlock();
@@ -142,7 +142,7 @@ static int init_div_table(void)
                                        << P0_7_CSCLKDEV_SHIFT;
 
                /* Calculate EMA */
-               volt_id = opp_get_voltage(opp);
+               volt_id = dev_pm_opp_get_voltage(opp);
                volt_id = (MAX_VOLTAGE - volt_id) / VOLTAGE_STEP;
                if (volt_id < PMIC_HIGH_VOLT) {
                        ema_div = (CPUEMA_HIGH << P0_7_CPUEMA_SHIFT) |
@@ -209,38 +209,22 @@ static void exynos_enable_dvfs(void)
                                dvfs_info->base + XMU_DVFS_CTRL);
 }
 
-static int exynos_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                                             dvfs_info->freq_table);
-}
-
 static unsigned int exynos_getspeed(unsigned int cpu)
 {
        return dvfs_info->cur_frequency;
 }
 
-static int exynos_target(struct cpufreq_policy *policy,
-                         unsigned int target_freq,
-                         unsigned int relation)
+static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       unsigned int index, tmp;
-       int ret = 0, i;
+       unsigned int tmp;
+       int i;
        struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
 
        mutex_lock(&cpufreq_lock);
 
-       ret = cpufreq_frequency_table_target(policy, freq_table,
-                                          target_freq, relation, &index);
-       if (ret)
-               goto out;
-
        freqs.old = dvfs_info->cur_frequency;
        freqs.new = freq_table[index].frequency;
 
-       if (freqs.old == freqs.new)
-               goto out;
-
        cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
        /* Set the target frequency in all C0_3_PSTATE register */
@@ -251,9 +235,8 @@ static int exynos_target(struct cpufreq_policy *policy,
 
                __raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + i * 4);
        }
-out:
        mutex_unlock(&cpufreq_lock);
-       return ret;
+       return 0;
 }
 
 static void exynos_cpufreq_work(struct work_struct *work)
@@ -324,30 +307,19 @@ static void exynos_sort_descend_freq_table(void)
 
 static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       int ret;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, dvfs_info->freq_table);
-       if (ret) {
-               dev_err(dvfs_info->dev, "Invalid frequency table: %d\n", ret);
-               return ret;
-       }
-
-       policy->cur = dvfs_info->cur_frequency;
-       policy->cpuinfo.transition_latency = dvfs_info->latency;
-       cpumask_setall(policy->cpus);
-
-       cpufreq_frequency_table_get_attr(dvfs_info->freq_table, policy->cpu);
-
-       return 0;
+       return cpufreq_generic_init(policy, dvfs_info->freq_table,
+                       dvfs_info->latency);
 }
 
 static struct cpufreq_driver exynos_driver = {
-       .flags          = CPUFREQ_STICKY,
-       .verify         = exynos_verify_speed,
-       .target         = exynos_target,
+       .flags          = CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = exynos_target,
        .get            = exynos_getspeed,
        .init           = exynos_cpufreq_cpu_init,
+       .exit           = cpufreq_generic_exit,
        .name           = CPUFREQ_NAME,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct of_device_id exynos_cpufreq_match[] = {
@@ -399,13 +371,14 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
                goto err_put_node;
        }
 
-       ret = opp_init_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
+       ret = dev_pm_opp_init_cpufreq_table(dvfs_info->dev,
+                                           &dvfs_info->freq_table);
        if (ret) {
                dev_err(dvfs_info->dev,
                        "failed to init cpufreq table: %d\n", ret);
                goto err_put_node;
        }
-       dvfs_info->freq_count = opp_get_opp_count(dvfs_info->dev);
+       dvfs_info->freq_count = dev_pm_opp_get_opp_count(dvfs_info->dev);
        exynos_sort_descend_freq_table();
 
        if (of_property_read_u32(np, "clock-latency", &dvfs_info->latency))
@@ -454,7 +427,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
        return 0;
 
 err_free_table:
-       opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
+       dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
 err_put_node:
        of_node_put(np);
        dev_err(&pdev->dev, "%s: failed initialization\n", __func__);
@@ -464,7 +437,7 @@ err_put_node:
 static int exynos_cpufreq_remove(struct platform_device *pdev)
 {
        cpufreq_unregister_driver(&exynos_driver);
-       opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
+       dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
        return 0;
 }
 
index f111454a7aeace94454e3c8eff6e7e45360380d7..3458d27f63b409e03b866e6b20e541a7de8cc769 100644 (file)
@@ -54,31 +54,30 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
 int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table)
 {
-       unsigned int next_larger = ~0;
-       unsigned int i;
-       unsigned int count = 0;
+       unsigned int next_larger = ~0, freq, i = 0;
+       bool found = false;
 
        pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n",
                                        policy->min, policy->max, policy->cpu);
 
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
 
-       for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-               unsigned int freq = table[i].frequency;
+       for (; freq = table[i].frequency, freq != CPUFREQ_TABLE_END; i++) {
                if (freq == CPUFREQ_ENTRY_INVALID)
                        continue;
-               if ((freq >= policy->min) && (freq <= policy->max))
-                       count++;
-               else if ((next_larger > freq) && (freq > policy->max))
+               if ((freq >= policy->min) && (freq <= policy->max)) {
+                       found = true;
+                       break;
+               }
+
+               if ((next_larger > freq) && (freq > policy->max))
                        next_larger = freq;
        }
 
-       if (!count)
+       if (!found) {
                policy->max = next_larger;
-
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
+               cpufreq_verify_within_cpu_limits(policy);
+       }
 
        pr_debug("verification lead to (%u - %u kHz) for cpu %u\n",
                                policy->min, policy->max, policy->cpu);
@@ -87,6 +86,20 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
 
+/*
+ * Generic routine to verify policy & frequency table, requires driver to call
+ * cpufreq_frequency_table_get_attr() prior to it.
+ */
+int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
+{
+       struct cpufreq_frequency_table *table =
+               cpufreq_frequency_get_table(policy->cpu);
+       if (!table)
+               return -ENODEV;
+
+       return cpufreq_frequency_table_verify(policy, table);
+}
+EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify);
 
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table,
@@ -200,6 +213,12 @@ struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
 };
 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
 
+struct freq_attr *cpufreq_generic_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+EXPORT_SYMBOL_GPL(cpufreq_generic_attr);
+
 /*
  * if you use these, you must assure that the frequency table is valid
  * all the time between get_attr and put_attr!
@@ -219,6 +238,18 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu)
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
 
+int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
+                                     struct cpufreq_frequency_table *table)
+{
+       int ret = cpufreq_frequency_table_cpuinfo(policy, table);
+
+       if (!ret)
+               cpufreq_frequency_table_get_attr(table, policy->cpu);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
+
 void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy)
 {
        pr_debug("Updating show_table for new_cpu %u from last_cpu %u\n",
index 70442c7b5e71aed7e57ce61b20893e42dc36a215..d83e8266a58e2eddf824696c80240ced024bab57 100644 (file)
@@ -401,7 +401,7 @@ static int cpufreq_gx_target(struct cpufreq_policy *policy,
 
 static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
 {
-       unsigned int maxfreq, curfreq;
+       unsigned int maxfreq;
 
        if (!policy || policy->cpu != 0)
                return -ENODEV;
@@ -415,10 +415,8 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
                maxfreq = 30000 * gx_freq_mult[getCx86(CX86_DIR1) & 0x0f];
 
        stock_freq = maxfreq;
-       curfreq = gx_get_cpuspeed(0);
 
        pr_debug("cpu max frequency is %d.\n", maxfreq);
-       pr_debug("cpu current frequency is %dkHz.\n", curfreq);
 
        /* setup basic struct for cpufreq API */
        policy->cpu = 0;
@@ -428,7 +426,6 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
        else
                policy->min = maxfreq / POLICY_MIN_DIV;
        policy->max = maxfreq;
-       policy->cur = curfreq;
        policy->cpuinfo.min_freq = maxfreq / max_duration;
        policy->cpuinfo.max_freq = maxfreq;
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
index 794123fcf3e3ebce87cdbcbf0a66b60f4b70db2c..bf8902a0866dd4d767cdab4ba45d84ca397033fe 100644 (file)
@@ -66,7 +66,8 @@ static int hb_cpufreq_driver_init(void)
        struct device_node *np;
        int ret;
 
-       if (!of_machine_is_compatible("calxeda,highbank"))
+       if ((!of_machine_is_compatible("calxeda,highbank")) &&
+               (!of_machine_is_compatible("calxeda,ecx-2000")))
                return -ENODEV;
 
        cpu_dev = get_cpu_device(0);
index 3e14f03171759bcdbd8a0501bc1ff38fee86d4c0..53c6ac637e10c437e12570d77c39e496b273276a 100644 (file)
@@ -141,7 +141,6 @@ processor_set_freq (
 {
        int                     ret = 0;
        u32                     value = 0;
-       struct cpufreq_freqs    cpufreq_freqs;
        cpumask_t               saved_mask;
        int                     retval;
 
@@ -168,13 +167,6 @@ processor_set_freq (
        pr_debug("Transitioning from P%d to P%d\n",
                data->acpi_data.state, state);
 
-       /* cpufreq frequency struct */
-       cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
-       cpufreq_freqs.new = data->freq_table[state].frequency;
-
-       /* notify cpufreq */
-       cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_PRECHANGE);
-
        /*
         * First we write the target state's 'control' value to the
         * control_register.
@@ -186,22 +178,11 @@ processor_set_freq (
 
        ret = processor_set_pstate(value);
        if (ret) {
-               unsigned int tmp = cpufreq_freqs.new;
-               cpufreq_notify_transition(policy, &cpufreq_freqs,
-                               CPUFREQ_POSTCHANGE);
-               cpufreq_freqs.new = cpufreq_freqs.old;
-               cpufreq_freqs.old = tmp;
-               cpufreq_notify_transition(policy, &cpufreq_freqs,
-                               CPUFREQ_PRECHANGE);
-               cpufreq_notify_transition(policy, &cpufreq_freqs,
-                               CPUFREQ_POSTCHANGE);
                printk(KERN_WARNING "Transition failed with error %d\n", ret);
                retval = -ENODEV;
                goto migrate_end;
        }
 
-       cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_POSTCHANGE);
-
        data->acpi_data.state = state;
 
        retval = 0;
@@ -227,42 +208,11 @@ acpi_cpufreq_get (
 static int
 acpi_cpufreq_target (
        struct cpufreq_policy   *policy,
-       unsigned int target_freq,
-       unsigned int relation)
-{
-       struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-       unsigned int next_state = 0;
-       unsigned int result = 0;
-
-       pr_debug("acpi_cpufreq_setpolicy\n");
-
-       result = cpufreq_frequency_table_target(policy,
-                       data->freq_table, target_freq, relation, &next_state);
-       if (result)
-               return (result);
-
-       result = processor_set_freq(data, policy, next_state);
-
-       return (result);
-}
-
-
-static int
-acpi_cpufreq_verify (
-       struct cpufreq_policy   *policy)
+       unsigned int index)
 {
-       unsigned int result = 0;
-       struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-
-       pr_debug("acpi_cpufreq_verify\n");
-
-       result = cpufreq_frequency_table_verify(policy,
-                       data->freq_table);
-
-       return (result);
+       return processor_set_freq(acpi_io_data[policy->cpu], policy, index);
 }
 
-
 static int
 acpi_cpufreq_cpu_init (
        struct cpufreq_policy   *policy)
@@ -321,7 +271,6 @@ acpi_cpufreq_cpu_init (
                            data->acpi_data.states[i].transition_latency * 1000;
                }
        }
-       policy->cur = processor_get_freq(data, policy->cpu);
 
        /* table init */
        for (i = 0; i <= data->acpi_data.state_count; i++)
@@ -335,7 +284,7 @@ acpi_cpufreq_cpu_init (
                }
        }
 
-       result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
+       result = cpufreq_table_validate_and_show(policy, data->freq_table);
        if (result) {
                goto err_freqfree;
        }
@@ -356,8 +305,6 @@ acpi_cpufreq_cpu_init (
                        (u32) data->acpi_data.states[i].status,
                        (u32) data->acpi_data.states[i].control);
 
-       cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
-
        /* the first call to ->target() should result in us actually
         * writing something to the appropriate registers. */
        data->resume = 1;
@@ -396,20 +343,14 @@ acpi_cpufreq_cpu_exit (
 }
 
 
-static struct freq_attr* acpi_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-
 static struct cpufreq_driver acpi_cpufreq_driver = {
-       .verify         = acpi_cpufreq_verify,
-       .target         = acpi_cpufreq_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = acpi_cpufreq_target,
        .get            = acpi_cpufreq_get,
        .init           = acpi_cpufreq_cpu_init,
        .exit           = acpi_cpufreq_cpu_exit,
        .name           = "acpi-cpufreq",
-       .attr           = acpi_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 
index c3fd2a101ca02852c677d021c567b27ee74b075a..4b3f18e5f36b23a5e6d02f6389eac363d96fe786 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 
@@ -35,73 +35,52 @@ static struct device *cpu_dev;
 static struct cpufreq_frequency_table *freq_table;
 static unsigned int transition_latency;
 
-static int imx6q_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
 static unsigned int imx6q_get_speed(unsigned int cpu)
 {
        return clk_get_rate(arm_clk) / 1000;
 }
 
-static int imx6q_set_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq, unsigned int relation)
+static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       struct cpufreq_freqs freqs;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long freq_hz, volt, volt_old;
-       unsigned int index;
+       unsigned int old_freq, new_freq;
        int ret;
 
-       ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
-                                            relation, &index);
-       if (ret) {
-               dev_err(cpu_dev, "failed to match target frequency %d: %d\n",
-                       target_freq, ret);
-               return ret;
-       }
-
-       freqs.new = freq_table[index].frequency;
-       freq_hz = freqs.new * 1000;
-       freqs.old = clk_get_rate(arm_clk) / 1000;
-
-       if (freqs.old == freqs.new)
-               return 0;
+       new_freq = freq_table[index].frequency;
+       freq_hz = new_freq * 1000;
+       old_freq = clk_get_rate(arm_clk) / 1000;
 
        rcu_read_lock();
-       opp = opp_find_freq_ceil(cpu_dev, &freq_hz);
+       opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
        if (IS_ERR(opp)) {
                rcu_read_unlock();
                dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
                return PTR_ERR(opp);
        }
 
-       volt = opp_get_voltage(opp);
+       volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
        volt_old = regulator_get_voltage(arm_reg);
 
        dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
-               freqs.old / 1000, volt_old / 1000,
-               freqs.new / 1000, volt / 1000);
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+               old_freq / 1000, volt_old / 1000,
+               new_freq / 1000, volt / 1000);
 
        /* scaling up?  scale voltage before frequency */
-       if (freqs.new > freqs.old) {
+       if (new_freq > old_freq) {
                ret = regulator_set_voltage_tol(arm_reg, volt, 0);
                if (ret) {
                        dev_err(cpu_dev,
                                "failed to scale vddarm up: %d\n", ret);
-                       freqs.new = freqs.old;
-                       goto post_notify;
+                       return ret;
                }
 
                /*
                 * Need to increase vddpu and vddsoc for safety
                 * if we are about to run at 1.2 GHz.
                 */
-               if (freqs.new == FREQ_1P2_GHZ / 1000) {
+               if (new_freq == FREQ_1P2_GHZ / 1000) {
                        regulator_set_voltage_tol(pu_reg,
                                        PU_SOC_VOLTAGE_HIGH, 0);
                        regulator_set_voltage_tol(soc_reg,
@@ -121,21 +100,20 @@ static int imx6q_set_target(struct cpufreq_policy *policy,
        clk_set_parent(step_clk, pll2_pfd2_396m_clk);
        clk_set_parent(pll1_sw_clk, step_clk);
        if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
-               clk_set_rate(pll1_sys_clk, freqs.new * 1000);
+               clk_set_rate(pll1_sys_clk, new_freq * 1000);
                clk_set_parent(pll1_sw_clk, pll1_sys_clk);
        }
 
        /* Ensure the arm clock divider is what we expect */
-       ret = clk_set_rate(arm_clk, freqs.new * 1000);
+       ret = clk_set_rate(arm_clk, new_freq * 1000);
        if (ret) {
                dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
                regulator_set_voltage_tol(arm_reg, volt_old, 0);
-               freqs.new = freqs.old;
-               goto post_notify;
+               return ret;
        }
 
        /* scaling down?  scale voltage after frequency */
-       if (freqs.new < freqs.old) {
+       if (new_freq < old_freq) {
                ret = regulator_set_voltage_tol(arm_reg, volt, 0);
                if (ret) {
                        dev_warn(cpu_dev,
@@ -143,7 +121,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy,
                        ret = 0;
                }
 
-               if (freqs.old == FREQ_1P2_GHZ / 1000) {
+               if (old_freq == FREQ_1P2_GHZ / 1000) {
                        regulator_set_voltage_tol(pu_reg,
                                        PU_SOC_VOLTAGE_NORMAL, 0);
                        regulator_set_voltage_tol(soc_reg,
@@ -151,55 +129,28 @@ static int imx6q_set_target(struct cpufreq_policy *policy,
                }
        }
 
-post_notify:
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       return ret;
-}
-
-static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
-{
-       int ret;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       if (ret) {
-               dev_err(cpu_dev, "invalid frequency table: %d\n", ret);
-               return ret;
-       }
-
-       policy->cpuinfo.transition_latency = transition_latency;
-       policy->cur = clk_get_rate(arm_clk) / 1000;
-       cpumask_setall(policy->cpus);
-       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-
        return 0;
 }
 
-static int imx6q_cpufreq_exit(struct cpufreq_policy *policy)
+static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
 {
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_generic_init(policy, freq_table, transition_latency);
 }
 
-static struct freq_attr *imx6q_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver imx6q_cpufreq_driver = {
-       .verify = imx6q_verify_speed,
-       .target = imx6q_set_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = imx6q_set_target,
        .get = imx6q_get_speed,
        .init = imx6q_cpufreq_init,
-       .exit = imx6q_cpufreq_exit,
+       .exit = cpufreq_generic_exit,
        .name = "imx6q-cpufreq",
-       .attr = imx6q_cpufreq_attr,
+       .attr = cpufreq_generic_attr,
 };
 
 static int imx6q_cpufreq_probe(struct platform_device *pdev)
 {
        struct device_node *np;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long min_volt, max_volt;
        int num, ret;
 
@@ -237,14 +188,14 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
        }
 
        /* We expect an OPP table supplied by platform */
-       num = opp_get_opp_count(cpu_dev);
+       num = dev_pm_opp_get_opp_count(cpu_dev);
        if (num < 0) {
                ret = num;
                dev_err(cpu_dev, "no OPP table is found: %d\n", ret);
                goto put_node;
        }
 
-       ret = opp_init_cpufreq_table(cpu_dev, &freq_table);
+       ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
        if (ret) {
                dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
                goto put_node;
@@ -259,12 +210,12 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
         * same order.
         */
        rcu_read_lock();
-       opp = opp_find_freq_exact(cpu_dev,
+       opp = dev_pm_opp_find_freq_exact(cpu_dev,
                                  freq_table[0].frequency * 1000, true);
-       min_volt = opp_get_voltage(opp);
-       opp = opp_find_freq_exact(cpu_dev,
+       min_volt = dev_pm_opp_get_voltage(opp);
+       opp = dev_pm_opp_find_freq_exact(cpu_dev,
                                  freq_table[--num].frequency * 1000, true);
-       max_volt = opp_get_voltage(opp);
+       max_volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
        ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt);
        if (ret > 0)
@@ -292,7 +243,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
        return 0;
 
 free_freq_table:
-       opp_free_cpufreq_table(cpu_dev, &freq_table);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
 put_node:
        of_node_put(np);
        return ret;
@@ -301,7 +252,7 @@ put_node:
 static int imx6q_cpufreq_remove(struct platform_device *pdev)
 {
        cpufreq_unregister_driver(&imx6q_cpufreq_driver);
-       opp_free_cpufreq_table(cpu_dev, &freq_table);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
 
        return 0;
 }
index f7c99df0880b4d396fee72860b904b5764f943f3..babf3e40e9fa5030be4420f7038681954ebc5bb8 100644 (file)
@@ -59,9 +59,7 @@ static int integrator_verify_policy(struct cpufreq_policy *policy)
 {
        struct icst_vco vco;
 
-       cpufreq_verify_within_limits(policy, 
-                                    policy->cpuinfo.min_freq, 
-                                    policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
 
        vco = icst_hz_to_vco(&cclk_params, policy->max * 1000);
        policy->max = icst_hz(&cclk_params, vco) / 1000;
@@ -69,10 +67,7 @@ static int integrator_verify_policy(struct cpufreq_policy *policy)
        vco = icst_hz_to_vco(&cclk_params, policy->min * 1000);
        policy->min = icst_hz(&cclk_params, vco) / 1000;
 
-       cpufreq_verify_within_limits(policy, 
-                                    policy->cpuinfo.min_freq, 
-                                    policy->cpuinfo.max_freq);
-
+       cpufreq_verify_within_cpu_limits(policy);
        return 0;
 }
 
@@ -186,10 +181,9 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
 {
 
        /* set default policy and cpuinfo */
-       policy->cpuinfo.max_freq = 160000;
-       policy->cpuinfo.min_freq = 12000;
+       policy->max = policy->cpuinfo.max_freq = 160000;
+       policy->min = policy->cpuinfo.min_freq = 12000;
        policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
-       policy->cur = policy->min = policy->max = integrator_get(policy->cpu);
 
        return 0;
 }
index 32b3479a24051d09a0c1c53647b74848fcb3c967..5f1cbae369611062c18ee50982ffa5c6f724d30f 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/debugfs.h>
+#include <linux/acpi.h>
 #include <trace/events/power.h>
 
 #include <asm/div64.h>
@@ -33,6 +34,8 @@
 
 #define SAMPLE_COUNT           3
 
+#define BYT_RATIOS     0x66a
+
 #define FRAC_BITS 8
 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
 #define fp_toint(X) ((X) >> FRAC_BITS)
@@ -48,7 +51,7 @@ static inline int32_t div_fp(int32_t x, int32_t y)
 }
 
 struct sample {
-       int core_pct_busy;
+       int32_t core_pct_busy;
        u64 aperf;
        u64 mperf;
        int freq;
@@ -68,7 +71,7 @@ struct _pid {
        int32_t i_gain;
        int32_t d_gain;
        int deadband;
-       int last_err;
+       int32_t last_err;
 };
 
 struct cpudata {
@@ -78,7 +81,6 @@ struct cpudata {
 
        struct timer_list timer;
 
-       struct pstate_adjust_policy *pstate_policy;
        struct pstate_data pstate;
        struct _pid pid;
 
@@ -100,15 +102,21 @@ struct pstate_adjust_policy {
        int i_gain_pct;
 };
 
-static struct pstate_adjust_policy default_policy = {
-       .sample_rate_ms = 10,
-       .deadband = 0,
-       .setpoint = 97,
-       .p_gain_pct = 20,
-       .d_gain_pct = 0,
-       .i_gain_pct = 0,
+struct pstate_funcs {
+       int (*get_max)(void);
+       int (*get_min)(void);
+       int (*get_turbo)(void);
+       void (*set)(int pstate);
+};
+
+struct cpu_defaults {
+       struct pstate_adjust_policy pid_policy;
+       struct pstate_funcs funcs;
 };
 
+static struct pstate_adjust_policy pid_params;
+static struct pstate_funcs pstate_funcs;
+
 struct perf_limits {
        int no_turbo;
        int max_perf_pct;
@@ -153,16 +161,15 @@ static inline void pid_d_gain_set(struct _pid *pid, int percent)
        pid->d_gain = div_fp(int_tofp(percent), int_tofp(100));
 }
 
-static signed int pid_calc(struct _pid *pid, int busy)
+static signed int pid_calc(struct _pid *pid, int32_t busy)
 {
-       signed int err, result;
+       signed int result;
        int32_t pterm, dterm, fp_error;
        int32_t integral_limit;
 
-       err = pid->setpoint - busy;
-       fp_error = int_tofp(err);
+       fp_error = int_tofp(pid->setpoint) - busy;
 
-       if (abs(err) <= pid->deadband)
+       if (abs(fp_error) <= int_tofp(pid->deadband))
                return 0;
 
        pterm = mul_fp(pid->p_gain, fp_error);
@@ -176,8 +183,8 @@ static signed int pid_calc(struct _pid *pid, int busy)
        if (pid->integral < -integral_limit)
                pid->integral = -integral_limit;
 
-       dterm = mul_fp(pid->d_gain, (err - pid->last_err));
-       pid->last_err = err;
+       dterm = mul_fp(pid->d_gain, fp_error - pid->last_err);
+       pid->last_err = fp_error;
 
        result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm;
 
@@ -186,14 +193,14 @@ static signed int pid_calc(struct _pid *pid, int busy)
 
 static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu)
 {
-       pid_p_gain_set(&cpu->pid, cpu->pstate_policy->p_gain_pct);
-       pid_d_gain_set(&cpu->pid, cpu->pstate_policy->d_gain_pct);
-       pid_i_gain_set(&cpu->pid, cpu->pstate_policy->i_gain_pct);
+       pid_p_gain_set(&cpu->pid, pid_params.p_gain_pct);
+       pid_d_gain_set(&cpu->pid, pid_params.d_gain_pct);
+       pid_i_gain_set(&cpu->pid, pid_params.i_gain_pct);
 
        pid_reset(&cpu->pid,
-               cpu->pstate_policy->setpoint,
+               pid_params.setpoint,
                100,
-               cpu->pstate_policy->deadband,
+               pid_params.deadband,
                0);
 }
 
@@ -227,12 +234,12 @@ struct pid_param {
 };
 
 static struct pid_param pid_files[] = {
-       {"sample_rate_ms", &default_policy.sample_rate_ms},
-       {"d_gain_pct", &default_policy.d_gain_pct},
-       {"i_gain_pct", &default_policy.i_gain_pct},
-       {"deadband", &default_policy.deadband},
-       {"setpoint", &default_policy.setpoint},
-       {"p_gain_pct", &default_policy.p_gain_pct},
+       {"sample_rate_ms", &pid_params.sample_rate_ms},
+       {"d_gain_pct", &pid_params.d_gain_pct},
+       {"i_gain_pct", &pid_params.i_gain_pct},
+       {"deadband", &pid_params.deadband},
+       {"setpoint", &pid_params.setpoint},
+       {"p_gain_pct", &pid_params.p_gain_pct},
        {NULL, NULL}
 };
 
@@ -337,42 +344,102 @@ static void intel_pstate_sysfs_expose_params(void)
 }
 
 /************************** sysfs end ************************/
+static int byt_get_min_pstate(void)
+{
+       u64 value;
+       rdmsrl(BYT_RATIOS, value);
+       return value & 0xFF;
+}
+
+static int byt_get_max_pstate(void)
+{
+       u64 value;
+       rdmsrl(BYT_RATIOS, value);
+       return (value >> 16) & 0xFF;
+}
 
-static int intel_pstate_min_pstate(void)
+static int core_get_min_pstate(void)
 {
        u64 value;
        rdmsrl(MSR_PLATFORM_INFO, value);
        return (value >> 40) & 0xFF;
 }
 
-static int intel_pstate_max_pstate(void)
+static int core_get_max_pstate(void)
 {
        u64 value;
        rdmsrl(MSR_PLATFORM_INFO, value);
        return (value >> 8) & 0xFF;
 }
 
-static int intel_pstate_turbo_pstate(void)
+static int core_get_turbo_pstate(void)
 {
        u64 value;
        int nont, ret;
        rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value);
-       nont = intel_pstate_max_pstate();
+       nont = core_get_max_pstate();
        ret = ((value) & 255);
        if (ret <= nont)
                ret = nont;
        return ret;
 }
 
+static void core_set_pstate(int pstate)
+{
+       u64 val;
+
+       val = pstate << 8;
+       if (limits.no_turbo)
+               val |= (u64)1 << 32;
+
+       wrmsrl(MSR_IA32_PERF_CTL, val);
+}
+
+static struct cpu_defaults core_params = {
+       .pid_policy = {
+               .sample_rate_ms = 10,
+               .deadband = 0,
+               .setpoint = 97,
+               .p_gain_pct = 20,
+               .d_gain_pct = 0,
+               .i_gain_pct = 0,
+       },
+       .funcs = {
+               .get_max = core_get_max_pstate,
+               .get_min = core_get_min_pstate,
+               .get_turbo = core_get_turbo_pstate,
+               .set = core_set_pstate,
+       },
+};
+
+static struct cpu_defaults byt_params = {
+       .pid_policy = {
+               .sample_rate_ms = 10,
+               .deadband = 0,
+               .setpoint = 97,
+               .p_gain_pct = 14,
+               .d_gain_pct = 0,
+               .i_gain_pct = 4,
+       },
+       .funcs = {
+               .get_max = byt_get_max_pstate,
+               .get_min = byt_get_min_pstate,
+               .get_turbo = byt_get_max_pstate,
+               .set = core_set_pstate,
+       },
+};
+
+
 static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
 {
        int max_perf = cpu->pstate.turbo_pstate;
+       int max_perf_adj;
        int min_perf;
        if (limits.no_turbo)
                max_perf = cpu->pstate.max_pstate;
 
-       max_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf));
-       *max = clamp_t(int, max_perf,
+       max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf));
+       *max = clamp_t(int, max_perf_adj,
                        cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
 
        min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf));
@@ -394,11 +461,8 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
        trace_cpu_frequency(pstate * 100000, cpu->cpu);
 
        cpu->pstate.current_pstate = pstate;
-       if (limits.no_turbo)
-               wrmsrl(MSR_IA32_PERF_CTL, BIT(32) | (pstate << 8));
-       else
-               wrmsrl(MSR_IA32_PERF_CTL, pstate << 8);
 
+       pstate_funcs.set(pstate);
 }
 
 static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps)
@@ -420,9 +484,9 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
 {
        sprintf(cpu->name, "Intel 2nd generation core");
 
-       cpu->pstate.min_pstate = intel_pstate_min_pstate();
-       cpu->pstate.max_pstate = intel_pstate_max_pstate();
-       cpu->pstate.turbo_pstate = intel_pstate_turbo_pstate();
+       cpu->pstate.min_pstate = pstate_funcs.get_min();
+       cpu->pstate.max_pstate = pstate_funcs.get_max();
+       cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
 
        /*
         * goto max pstate so we don't slow up boot if we are built-in if we are
@@ -435,8 +499,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu,
                                        struct sample *sample)
 {
        u64 core_pct;
-       core_pct = div64_u64(sample->aperf * 100, sample->mperf);
-       sample->freq = cpu->pstate.max_pstate * core_pct * 1000;
+       core_pct = div64_u64(int_tofp(sample->aperf * 100),
+                            sample->mperf);
+       sample->freq = fp_toint(cpu->pstate.max_pstate * core_pct * 1000);
 
        sample->core_pct_busy = core_pct;
 }
@@ -463,27 +528,24 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
 {
        int sample_time, delay;
 
-       sample_time = cpu->pstate_policy->sample_rate_ms;
+       sample_time = pid_params.sample_rate_ms;
        delay = msecs_to_jiffies(sample_time);
        mod_timer_pinned(&cpu->timer, jiffies + delay);
 }
 
-static inline int intel_pstate_get_scaled_busy(struct cpudata *cpu)
+static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
 {
-       int32_t busy_scaled;
        int32_t core_busy, max_pstate, current_pstate;
 
-       core_busy = int_tofp(cpu->samples[cpu->sample_ptr].core_pct_busy);
+       core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy;
        max_pstate = int_tofp(cpu->pstate.max_pstate);
        current_pstate = int_tofp(cpu->pstate.current_pstate);
-       busy_scaled = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
-
-       return fp_toint(busy_scaled);
+       return mul_fp(core_busy, div_fp(max_pstate, current_pstate));
 }
 
 static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
 {
-       int busy_scaled;
+       int32_t busy_scaled;
        struct _pid *pid;
        signed int ctl = 0;
        int steps;
@@ -522,14 +584,15 @@ static void intel_pstate_timer_func(unsigned long __data)
        { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&policy }
 
 static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
-       ICPU(0x2a, default_policy),
-       ICPU(0x2d, default_policy),
-       ICPU(0x3a, default_policy),
-       ICPU(0x3c, default_policy),
-       ICPU(0x3e, default_policy),
-       ICPU(0x3f, default_policy),
-       ICPU(0x45, default_policy),
-       ICPU(0x46, default_policy),
+       ICPU(0x2a, core_params),
+       ICPU(0x2d, core_params),
+       ICPU(0x37, byt_params),
+       ICPU(0x3a, core_params),
+       ICPU(0x3c, core_params),
+       ICPU(0x3e, core_params),
+       ICPU(0x3f, core_params),
+       ICPU(0x45, core_params),
+       ICPU(0x46, core_params),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
@@ -553,8 +616,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
        intel_pstate_get_cpu_pstates(cpu);
 
        cpu->cpu = cpunum;
-       cpu->pstate_policy =
-               (struct pstate_adjust_policy *)id->driver_data;
+
        init_timer_deferrable(&cpu->timer);
        cpu->timer.function = intel_pstate_timer_func;
        cpu->timer.data =
@@ -614,9 +676,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 
 static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
 {
-       cpufreq_verify_within_limits(policy,
-                               policy->cpuinfo.min_freq,
-                               policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
 
        if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
                (policy->policy != CPUFREQ_POLICY_PERFORMANCE))
@@ -637,8 +697,8 @@ static int intel_pstate_cpu_exit(struct cpufreq_policy *policy)
 
 static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
 {
-       int rc, min_pstate, max_pstate;
        struct cpudata *cpu;
+       int rc;
 
        rc = intel_pstate_init_cpu(policy->cpu);
        if (rc)
@@ -652,9 +712,8 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
        else
                policy->policy = CPUFREQ_POLICY_POWERSAVE;
 
-       intel_pstate_get_min_max(cpu, &min_pstate, &max_pstate);
-       policy->min = min_pstate * 100000;
-       policy->max = max_pstate * 100000;
+       policy->min = cpu->pstate.min_pstate * 100000;
+       policy->max = cpu->pstate.turbo_pstate * 100000;
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000;
@@ -685,9 +744,9 @@ static int intel_pstate_msrs_not_valid(void)
        rdmsrl(MSR_IA32_APERF, aperf);
        rdmsrl(MSR_IA32_MPERF, mperf);
 
-       if (!intel_pstate_min_pstate() ||
-               !intel_pstate_max_pstate() ||
-               !intel_pstate_turbo_pstate())
+       if (!pstate_funcs.get_max() ||
+               !pstate_funcs.get_min() ||
+               !pstate_funcs.get_turbo())
                return -ENODEV;
 
        rdmsrl(MSR_IA32_APERF, tmp);
@@ -700,10 +759,96 @@ static int intel_pstate_msrs_not_valid(void)
 
        return 0;
 }
+
+static void copy_pid_params(struct pstate_adjust_policy *policy)
+{
+       pid_params.sample_rate_ms = policy->sample_rate_ms;
+       pid_params.p_gain_pct = policy->p_gain_pct;
+       pid_params.i_gain_pct = policy->i_gain_pct;
+       pid_params.d_gain_pct = policy->d_gain_pct;
+       pid_params.deadband = policy->deadband;
+       pid_params.setpoint = policy->setpoint;
+}
+
+static void copy_cpu_funcs(struct pstate_funcs *funcs)
+{
+       pstate_funcs.get_max   = funcs->get_max;
+       pstate_funcs.get_min   = funcs->get_min;
+       pstate_funcs.get_turbo = funcs->get_turbo;
+       pstate_funcs.set       = funcs->set;
+}
+
+#if IS_ENABLED(CONFIG_ACPI)
+#include <acpi/processor.h>
+
+static bool intel_pstate_no_acpi_pss(void)
+{
+       int i;
+
+       for_each_possible_cpu(i) {
+               acpi_status status;
+               union acpi_object *pss;
+               struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+               struct acpi_processor *pr = per_cpu(processors, i);
+
+               if (!pr)
+                       continue;
+
+               status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
+               if (ACPI_FAILURE(status))
+                       continue;
+
+               pss = buffer.pointer;
+               if (pss && pss->type == ACPI_TYPE_PACKAGE) {
+                       kfree(pss);
+                       return false;
+               }
+
+               kfree(pss);
+       }
+
+       return true;
+}
+
+struct hw_vendor_info {
+       u16  valid;
+       char oem_id[ACPI_OEM_ID_SIZE];
+       char oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
+};
+
+/* Hardware vendor-specific info that has its own power management modes */
+static struct hw_vendor_info vendor_info[] = {
+       {1, "HP    ", "ProLiant"},
+       {0, "", ""},
+};
+
+static bool intel_pstate_platform_pwr_mgmt_exists(void)
+{
+       struct acpi_table_header hdr;
+       struct hw_vendor_info *v_info;
+
+       if (acpi_disabled
+           || ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr)))
+               return false;
+
+       for (v_info = vendor_info; v_info->valid; v_info++) {
+               if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE)
+                   && !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE)
+                   && intel_pstate_no_acpi_pss())
+                       return true;
+       }
+
+       return false;
+}
+#else /* CONFIG_ACPI not enabled */
+static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; }
+#endif /* CONFIG_ACPI */
+
 static int __init intel_pstate_init(void)
 {
        int cpu, rc = 0;
        const struct x86_cpu_id *id;
+       struct cpu_defaults *cpu_info;
 
        if (no_load)
                return -ENODEV;
@@ -712,6 +857,18 @@ static int __init intel_pstate_init(void)
        if (!id)
                return -ENODEV;
 
+       /*
+        * The Intel pstate driver will be ignored if the platform
+        * firmware has its own power management modes.
+        */
+       if (intel_pstate_platform_pwr_mgmt_exists())
+               return -ENODEV;
+
+       cpu_info = (struct cpu_defaults *)id->driver_data;
+
+       copy_pid_params(&cpu_info->pid_policy);
+       copy_cpu_funcs(&cpu_info->funcs);
+
        if (intel_pstate_msrs_not_valid())
                return -ENODEV;
 
index ba10658a93949fe9adca0863c7c8926a11fe1676..0767a4e29dfe2cc3f27ec691558657b7c342d0df 100644 (file)
@@ -55,69 +55,37 @@ static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
        return kirkwood_freq_table[0].frequency;
 }
 
-static void kirkwood_cpufreq_set_cpu_state(struct cpufreq_policy *policy,
-               unsigned int index)
+static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
+                           unsigned int index)
 {
-       struct cpufreq_freqs freqs;
        unsigned int state = kirkwood_freq_table[index].driver_data;
        unsigned long reg;
 
-       freqs.old = kirkwood_cpufreq_get_cpu_frequency(0);
-       freqs.new = kirkwood_freq_table[index].frequency;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
-       dev_dbg(priv.dev, "Attempting to set frequency to %i KHz\n",
-               kirkwood_freq_table[index].frequency);
-       dev_dbg(priv.dev, "old frequency was %i KHz\n",
-               kirkwood_cpufreq_get_cpu_frequency(0));
-
-       if (freqs.old != freqs.new) {
-               local_irq_disable();
-
-               /* Disable interrupts to the CPU */
-               reg = readl_relaxed(priv.base);
-               reg |= CPU_SW_INT_BLK;
-               writel_relaxed(reg, priv.base);
-
-               switch (state) {
-               case STATE_CPU_FREQ:
-                       clk_disable(priv.powersave_clk);
-                       break;
-               case STATE_DDR_FREQ:
-                       clk_enable(priv.powersave_clk);
-                       break;
-               }
+       local_irq_disable();
 
-               /* Wait-for-Interrupt, while the hardware changes frequency */
-               cpu_do_idle();
+       /* Disable interrupts to the CPU */
+       reg = readl_relaxed(priv.base);
+       reg |= CPU_SW_INT_BLK;
+       writel_relaxed(reg, priv.base);
 
-               /* Enable interrupts to the CPU */
-               reg = readl_relaxed(priv.base);
-               reg &= ~CPU_SW_INT_BLK;
-               writel_relaxed(reg, priv.base);
-
-               local_irq_enable();
+       switch (state) {
+       case STATE_CPU_FREQ:
+               clk_disable(priv.powersave_clk);
+               break;
+       case STATE_DDR_FREQ:
+               clk_enable(priv.powersave_clk);
+               break;
        }
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-};
-
-static int kirkwood_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, kirkwood_freq_table);
-}
 
-static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq,
-                           unsigned int relation)
-{
-       unsigned int index = 0;
+       /* Wait-for-Interrupt, while the hardware changes frequency */
+       cpu_do_idle();
 
-       if (cpufreq_frequency_table_target(policy, kirkwood_freq_table,
-                               target_freq, relation, &index))
-               return -EINVAL;
+       /* Enable interrupts to the CPU */
+       reg = readl_relaxed(priv.base);
+       reg &= ~CPU_SW_INT_BLK;
+       writel_relaxed(reg, priv.base);
 
-       kirkwood_cpufreq_set_cpu_state(policy, index);
+       local_irq_enable();
 
        return 0;
 }
@@ -125,40 +93,17 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
 /* Module init and exit code */
 static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       int result;
-
-       /* cpuinfo and default policy values */
-       policy->cpuinfo.transition_latency = 5000; /* 5uS */
-       policy->cur = kirkwood_cpufreq_get_cpu_frequency(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, kirkwood_freq_table);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(kirkwood_freq_table, policy->cpu);
-
-       return 0;
-}
-
-static int kirkwood_cpufreq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_generic_init(policy, kirkwood_freq_table, 5000);
 }
 
-static struct freq_attr *kirkwood_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver kirkwood_cpufreq_driver = {
        .get    = kirkwood_cpufreq_get_cpu_frequency,
-       .verify = kirkwood_cpufreq_verify,
-       .target = kirkwood_cpufreq_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = kirkwood_cpufreq_target,
        .init   = kirkwood_cpufreq_cpu_init,
-       .exit   = kirkwood_cpufreq_cpu_exit,
+       .exit   = cpufreq_generic_exit,
        .name   = "kirkwood-cpufreq",
-       .attr   = kirkwood_cpufreq_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static int kirkwood_cpufreq_probe(struct platform_device *pdev)
index 4ada1cccb0523632e72c016e9a511dd38b08d33d..45bafddfd8ea488ba24362b44a8aa58bf58304eb 100644 (file)
@@ -625,28 +625,13 @@ static void longhaul_setup_voltagescaling(void)
 }
 
 
-static int longhaul_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, longhaul_table);
-}
-
-
 static int longhaul_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq, unsigned int relation)
+                           unsigned int table_index)
 {
-       unsigned int table_index = 0;
        unsigned int i;
        unsigned int dir = 0;
        u8 vid, current_vid;
 
-       if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq,
-                               relation, &table_index))
-               return -EINVAL;
-
-       /* Don't set same frequency again */
-       if (longhaul_index == table_index)
-               return 0;
-
        if (!can_scale_voltage)
                longhaul_setstate(policy, table_index);
        else {
@@ -919,36 +904,18 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy)
                longhaul_setup_voltagescaling();
 
        policy->cpuinfo.transition_latency = 200000;    /* nsec */
-       policy->cur = calc_speed(longhaul_get_cpu_mult());
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
-       if (ret)
-               return ret;
-
-       cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu);
 
-       return 0;
+       return cpufreq_table_validate_and_show(policy, longhaul_table);
 }
 
-static int longhaul_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
-static struct freq_attr *longhaul_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver longhaul_driver = {
-       .verify = longhaul_verify,
-       .target = longhaul_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = longhaul_target,
        .get    = longhaul_get,
        .init   = longhaul_cpu_init,
-       .exit   = longhaul_cpu_exit,
+       .exit   = cpufreq_generic_exit,
        .name   = "longhaul",
-       .attr   = longhaul_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id longhaul_id[] = {
index 5aa031612d5393ff08d196f83b8701ac8c8f5e12..074971b12635af04b7214f510c70e7e8c37ebcbf 100644 (file)
@@ -129,9 +129,7 @@ static int longrun_verify_policy(struct cpufreq_policy *policy)
                return -EINVAL;
 
        policy->cpu = 0;
-       cpufreq_verify_within_limits(policy,
-               policy->cpuinfo.min_freq,
-               policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
 
        if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
            (policy->policy != CPUFREQ_POLICY_PERFORMANCE))
index 7bc3c44d34e2f0ec5493ad9fdf0c8467ccd8a037..a4360921810572dc8f3608c2edc68369ea9ca18c 100644 (file)
@@ -53,51 +53,24 @@ static unsigned int loongson2_cpufreq_get(unsigned int cpu)
  * Here we notify other drivers of the proposed change and the final change.
  */
 static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
-                                    unsigned int target_freq,
-                                    unsigned int relation)
+                                    unsigned int index)
 {
        unsigned int cpu = policy->cpu;
-       unsigned int newstate = 0;
        cpumask_t cpus_allowed;
-       struct cpufreq_freqs freqs;
        unsigned int freq;
 
        cpus_allowed = current->cpus_allowed;
        set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
-       if (cpufreq_frequency_table_target
-           (policy, &loongson2_clockmod_table[0], target_freq, relation,
-            &newstate))
-               return -EINVAL;
-
        freq =
            ((cpu_clock_freq / 1000) *
-            loongson2_clockmod_table[newstate].driver_data) / 8;
-       if (freq < policy->min || freq > policy->max)
-               return -EINVAL;
-
-       pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
-
-       freqs.old = loongson2_cpufreq_get(cpu);
-       freqs.new = freq;
-       freqs.flags = 0;
-
-       if (freqs.new == freqs.old)
-               return 0;
-
-       /* notifiers */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+            loongson2_clockmod_table[index].driver_data) / 8;
 
        set_cpus_allowed_ptr(current, &cpus_allowed);
 
        /* setting the cpu frequency */
        clk_set_rate(cpuclk, freq);
 
-       /* notifiers */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       pr_debug("cpufreq: set frequency %u kHz\n", freq);
-
        return 0;
 }
 
@@ -131,40 +104,24 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
                return ret;
        }
 
-       policy->cur = loongson2_cpufreq_get(policy->cpu);
-
-       cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0],
-                                        policy->cpu);
-
-       return cpufreq_frequency_table_cpuinfo(policy,
-                                           &loongson2_clockmod_table[0]);
-}
-
-static int loongson2_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                                             &loongson2_clockmod_table[0]);
+       return cpufreq_generic_init(policy, &loongson2_clockmod_table[0], 0);
 }
 
 static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
 {
+       cpufreq_frequency_table_put_attr(policy->cpu);
        clk_put(cpuclk);
        return 0;
 }
 
-static struct freq_attr *loongson2_table_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver loongson2_cpufreq_driver = {
        .name = "loongson2",
        .init = loongson2_cpufreq_cpu_init,
-       .verify = loongson2_cpufreq_verify,
-       .target = loongson2_cpufreq_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = loongson2_cpufreq_target,
        .get = loongson2_cpufreq_get,
        .exit = loongson2_cpufreq_exit,
-       .attr = loongson2_table_attr,
+       .attr = cpufreq_generic_attr,
 };
 
 static struct platform_device_id platform_device_ids[] = {
index 6168d77b296d78b7d1a452bae6f3ae34c7e036c3..c4dfa42a75acc6663de5b0c4aabd7db3705de954 100644 (file)
@@ -64,18 +64,11 @@ static struct cpufreq_frequency_table maple_cpu_freqs[] = {
        {0,                     CPUFREQ_TABLE_END},
 };
 
-static struct freq_attr *maple_cpu_freqs_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 /* Power mode data is an array of the 32 bits PCR values to use for
  * the various frequencies, retrieved from the device-tree
  */
 static int maple_pmode_cur;
 
-static DEFINE_MUTEX(maple_switch_mutex);
-
 static const u32 *maple_pmode_data;
 static int maple_pmode_max;
 
@@ -135,37 +128,10 @@ static int maple_scom_query_freq(void)
  * Common interface to the cpufreq core
  */
 
-static int maple_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, maple_cpu_freqs);
-}
-
 static int maple_cpufreq_target(struct cpufreq_policy *policy,
-       unsigned int target_freq, unsigned int relation)
+       unsigned int index)
 {
-       unsigned int newstate = 0;
-       struct cpufreq_freqs freqs;
-       int rc;
-
-       if (cpufreq_frequency_table_target(policy, maple_cpu_freqs,
-                       target_freq, relation, &newstate))
-               return -EINVAL;
-
-       if (maple_pmode_cur == newstate)
-               return 0;
-
-       mutex_lock(&maple_switch_mutex);
-
-       freqs.old = maple_cpu_freqs[maple_pmode_cur].frequency;
-       freqs.new = maple_cpu_freqs[newstate].frequency;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-       rc = maple_scom_switch_freq(newstate);
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       mutex_unlock(&maple_switch_mutex);
-
-       return rc;
+       return maple_scom_switch_freq(index);
 }
 
 static unsigned int maple_cpufreq_get_speed(unsigned int cpu)
@@ -175,27 +141,17 @@ static unsigned int maple_cpufreq_get_speed(unsigned int cpu)
 
 static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       policy->cpuinfo.transition_latency = 12000;
-       policy->cur = maple_cpu_freqs[maple_scom_query_freq()].frequency;
-       /* secondary CPUs are tied to the primary one by the
-        * cpufreq core if in the secondary policy we tell it that
-        * it actually must be one policy together with all others. */
-       cpumask_setall(policy->cpus);
-       cpufreq_frequency_table_get_attr(maple_cpu_freqs, policy->cpu);
-
-       return cpufreq_frequency_table_cpuinfo(policy,
-               maple_cpu_freqs);
+       return cpufreq_generic_init(policy, maple_cpu_freqs, 12000);
 }
 
-
 static struct cpufreq_driver maple_cpufreq_driver = {
        .name           = "maple",
        .flags          = CPUFREQ_CONST_LOOPS,
        .init           = maple_cpufreq_cpu_init,
-       .verify         = maple_cpufreq_verify,
-       .target         = maple_cpufreq_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = maple_cpufreq_target,
        .get            = maple_cpufreq_get_speed,
-       .attr           = maple_cpu_freqs_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init maple_cpufreq_init(void)
index f31fcfcad514330ca856bcfd015aba3927de8241..be6d14307aa81a7fa3e3626953b5a43b514933e2 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -40,13 +40,6 @@ static struct clk *mpu_clk;
 static struct device *mpu_dev;
 static struct regulator *mpu_reg;
 
-static int omap_verify_speed(struct cpufreq_policy *policy)
-{
-       if (!freq_table)
-               return -EINVAL;
-       return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
 static unsigned int omap_getspeed(unsigned int cpu)
 {
        unsigned long rate;
@@ -58,42 +51,16 @@ static unsigned int omap_getspeed(unsigned int cpu)
        return rate;
 }
 
-static int omap_target(struct cpufreq_policy *policy,
-                      unsigned int target_freq,
-                      unsigned int relation)
+static int omap_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       unsigned int i;
-       int r, ret = 0;
-       struct cpufreq_freqs freqs;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long freq, volt = 0, volt_old = 0, tol = 0;
+       unsigned int old_freq, new_freq;
 
-       if (!freq_table) {
-               dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__,
-                               policy->cpu);
-               return -EINVAL;
-       }
+       old_freq = omap_getspeed(policy->cpu);
+       new_freq = freq_table[index].frequency;
 
-       ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
-                       relation, &i);
-       if (ret) {
-               dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n",
-                       __func__, policy->cpu, target_freq, ret);
-               return ret;
-       }
-       freqs.new = freq_table[i].frequency;
-       if (!freqs.new) {
-               dev_err(mpu_dev, "%s: cpu%d: no match for freq %d\n", __func__,
-                       policy->cpu, target_freq);
-               return -EINVAL;
-       }
-
-       freqs.old = omap_getspeed(policy->cpu);
-
-       if (freqs.old == freqs.new && policy->cur == freqs.new)
-               return ret;
-
-       freq = freqs.new * 1000;
+       freq = new_freq * 1000;
        ret = clk_round_rate(mpu_clk, freq);
        if (IS_ERR_VALUE(ret)) {
                dev_warn(mpu_dev,
@@ -105,143 +72,103 @@ static int omap_target(struct cpufreq_policy *policy,
 
        if (mpu_reg) {
                rcu_read_lock();
-               opp = opp_find_freq_ceil(mpu_dev, &freq);
+               opp = dev_pm_opp_find_freq_ceil(mpu_dev, &freq);
                if (IS_ERR(opp)) {
                        rcu_read_unlock();
                        dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n",
-                               __func__, freqs.new);
+                               __func__, new_freq);
                        return -EINVAL;
                }
-               volt = opp_get_voltage(opp);
+               volt = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
                tol = volt * OPP_TOLERANCE / 100;
                volt_old = regulator_get_voltage(mpu_reg);
        }
 
        dev_dbg(mpu_dev, "cpufreq-omap: %u MHz, %ld mV --> %u MHz, %ld mV\n", 
-               freqs.old / 1000, volt_old ? volt_old / 1000 : -1,
-               freqs.new / 1000, volt ? volt / 1000 : -1);
-
-       /* notifiers */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+               old_freq / 1000, volt_old ? volt_old / 1000 : -1,
+               new_freq / 1000, volt ? volt / 1000 : -1);
 
        /* scaling up?  scale voltage before frequency */
-       if (mpu_reg && (freqs.new > freqs.old)) {
+       if (mpu_reg && (new_freq > old_freq)) {
                r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol);
                if (r < 0) {
                        dev_warn(mpu_dev, "%s: unable to scale voltage up.\n",
                                 __func__);
-                       freqs.new = freqs.old;
-                       goto done;
+                       return r;
                }
        }
 
-       ret = clk_set_rate(mpu_clk, freqs.new * 1000);
+       ret = clk_set_rate(mpu_clk, new_freq * 1000);
 
        /* scaling down?  scale voltage after frequency */
-       if (mpu_reg && (freqs.new < freqs.old)) {
+       if (mpu_reg && (new_freq < old_freq)) {
                r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol);
                if (r < 0) {
                        dev_warn(mpu_dev, "%s: unable to scale voltage down.\n",
                                 __func__);
-                       ret = clk_set_rate(mpu_clk, freqs.old * 1000);
-                       freqs.new = freqs.old;
-                       goto done;
+                       clk_set_rate(mpu_clk, old_freq * 1000);
+                       return r;
                }
        }
 
-       freqs.new = omap_getspeed(policy->cpu);
-
-done:
-       /* notifiers */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
        return ret;
 }
 
 static inline void freq_table_free(void)
 {
        if (atomic_dec_and_test(&freq_table_users))
-               opp_free_cpufreq_table(mpu_dev, &freq_table);
+               dev_pm_opp_free_cpufreq_table(mpu_dev, &freq_table);
 }
 
 static int omap_cpu_init(struct cpufreq_policy *policy)
 {
-       int result = 0;
+       int result;
 
        mpu_clk = clk_get(NULL, "cpufreq_ck");
        if (IS_ERR(mpu_clk))
                return PTR_ERR(mpu_clk);
 
-       if (policy->cpu >= NR_CPUS) {
-               result = -EINVAL;
-               goto fail_ck;
-       }
-
-       policy->cur = omap_getspeed(policy->cpu);
-
-       if (!freq_table)
-               result = opp_init_cpufreq_table(mpu_dev, &freq_table);
-
-       if (result) {
-               dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
+       if (!freq_table) {
+               result = dev_pm_opp_init_cpufreq_table(mpu_dev, &freq_table);
+               if (result) {
+                       dev_err(mpu_dev,
+                               "%s: cpu%d: failed creating freq table[%d]\n",
                                __func__, policy->cpu, result);
-               goto fail_ck;
+                       goto fail;
+               }
        }
 
        atomic_inc_return(&freq_table_users);
 
-       result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       if (result)
-               goto fail_table;
-
-       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-
-       policy->cur = omap_getspeed(policy->cpu);
-
-       /*
-        * On OMAP SMP configuartion, both processors share the voltage
-        * and clock. So both CPUs needs to be scaled together and hence
-        * needs software co-ordination. Use cpufreq affected_cpus
-        * interface to handle this scenario. Additional is_smp() check
-        * is to keep SMP_ON_UP build working.
-        */
-       if (is_smp())
-               cpumask_setall(policy->cpus);
-
        /* FIXME: what's the actual transition time? */
-       policy->cpuinfo.transition_latency = 300 * 1000;
-
-       return 0;
+       result = cpufreq_generic_init(policy, freq_table, 300 * 1000);
+       if (!result)
+               return 0;
 
-fail_table:
        freq_table_free();
-fail_ck:
+fail:
        clk_put(mpu_clk);
        return result;
 }
 
 static int omap_cpu_exit(struct cpufreq_policy *policy)
 {
+       cpufreq_frequency_table_put_attr(policy->cpu);
        freq_table_free();
        clk_put(mpu_clk);
        return 0;
 }
 
-static struct freq_attr *omap_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver omap_driver = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = omap_verify_speed,
-       .target         = omap_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = omap_target,
        .get            = omap_getspeed,
        .init           = omap_cpu_init,
        .exit           = omap_cpu_exit,
        .name           = "omap",
-       .attr           = omap_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int omap_cpufreq_probe(struct platform_device *pdev)
index 2f0a2a65c37f67eeae9789ed12afa20627fd3503..3d1cba9fd5f93525d7e5117fe90e537fa019fae7 100644 (file)
@@ -105,47 +105,21 @@ static struct cpufreq_frequency_table p4clockmod_table[] = {
 };
 
 
-static int cpufreq_p4_target(struct cpufreq_policy *policy,
-                            unsigned int target_freq,
-                            unsigned int relation)
+static int cpufreq_p4_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       unsigned int    newstate = DC_RESV;
-       struct cpufreq_freqs freqs;
        int i;
 
-       if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0],
-                               target_freq, relation, &newstate))
-               return -EINVAL;
-
-       freqs.old = cpufreq_p4_get(policy->cpu);
-       freqs.new = stock_freq * p4clockmod_table[newstate].driver_data / 8;
-
-       if (freqs.new == freqs.old)
-               return 0;
-
-       /* notifiers */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        /* run on each logical CPU,
         * see section 13.15.3 of IA32 Intel Architecture Software
         * Developer's Manual, Volume 3
         */
        for_each_cpu(i, policy->cpus)
-               cpufreq_p4_setdc(i, p4clockmod_table[newstate].driver_data);
-
-       /* notifiers */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+               cpufreq_p4_setdc(i, p4clockmod_table[index].driver_data);
 
        return 0;
 }
 
 
-static int cpufreq_p4_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]);
-}
-
-
 static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
 {
        if (c->x86 == 0x06) {
@@ -230,25 +204,17 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
                else
                        p4clockmod_table[i].frequency = (stock_freq * i)/8;
        }
-       cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
 
        /* cpuinfo and default policy values */
 
        /* the transition latency is set to be 1 higher than the maximum
         * transition latency of the ondemand governor */
        policy->cpuinfo.transition_latency = 10000001;
-       policy->cur = stock_freq;
 
-       return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]);
+       return cpufreq_table_validate_and_show(policy, &p4clockmod_table[0]);
 }
 
 
-static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
 static unsigned int cpufreq_p4_get(unsigned int cpu)
 {
        u32 l, h;
@@ -267,19 +233,14 @@ static unsigned int cpufreq_p4_get(unsigned int cpu)
        return stock_freq;
 }
 
-static struct freq_attr *p4clockmod_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver p4clockmod_driver = {
-       .verify         = cpufreq_p4_verify,
-       .target         = cpufreq_p4_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = cpufreq_p4_target,
        .init           = cpufreq_p4_cpu_init,
-       .exit           = cpufreq_p4_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .get            = cpufreq_p4_get,
        .name           = "p4-clockmod",
-       .attr           = p4clockmod_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id cpufreq_p4_id[] = {
index 534e43a60d1f9a80b2a952abe254fb01e06c0f12..1c331369b15b850a7ef491da27cc155b27bbbaf0 100644 (file)
@@ -51,8 +51,6 @@
 static void __iomem *sdcpwr_mapbase;
 static void __iomem *sdcasr_mapbase;
 
-static DEFINE_MUTEX(pas_switch_mutex);
-
 /* Current astate, is used when waking up from power savings on
  * one core, in case the other core has switched states during
  * the idle time.
@@ -69,11 +67,6 @@ static struct cpufreq_frequency_table pas_freqs[] = {
        {0,     CPUFREQ_TABLE_END},
 };
 
-static struct freq_attr *pas_cpu_freqs_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 /*
  * hardware specific functions
  */
@@ -209,22 +202,13 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
                pr_debug("%d: %d\n", i, pas_freqs[i].frequency);
        }
 
-       policy->cpuinfo.transition_latency = get_gizmo_latency();
-
        cur_astate = get_cur_astate(policy->cpu);
        pr_debug("current astate is at %d\n",cur_astate);
 
        policy->cur = pas_freqs[cur_astate].frequency;
-       cpumask_copy(policy->cpus, cpu_online_mask);
-
        ppc_proc_freq = policy->cur * 1000ul;
 
-       cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu);
-
-       /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max
-        * are set correctly
-        */
-       return cpufreq_frequency_table_cpuinfo(policy, pas_freqs);
+       return cpufreq_generic_init(policy, pas_freqs, get_gizmo_latency());
 
 out_unmap_sdcpwr:
        iounmap(sdcpwr_mapbase);
@@ -253,31 +237,11 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-static int pas_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, pas_freqs);
-}
-
 static int pas_cpufreq_target(struct cpufreq_policy *policy,
-                             unsigned int target_freq,
-                             unsigned int relation)
+                             unsigned int pas_astate_new)
 {
-       struct cpufreq_freqs freqs;
-       int pas_astate_new;
        int i;
 
-       cpufreq_frequency_table_target(policy,
-                                      pas_freqs,
-                                      target_freq,
-                                      relation,
-                                      &pas_astate_new);
-
-       freqs.old = policy->cur;
-       freqs.new = pas_freqs[pas_astate_new].frequency;
-
-       mutex_lock(&pas_switch_mutex);
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n",
                 policy->cpu,
                 pas_freqs[pas_astate_new].frequency,
@@ -288,10 +252,7 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy,
        for_each_online_cpu(i)
                set_astate(i, pas_astate_new);
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-       mutex_unlock(&pas_switch_mutex);
-
-       ppc_proc_freq = freqs.new * 1000ul;
+       ppc_proc_freq = pas_freqs[pas_astate_new].frequency * 1000ul;
        return 0;
 }
 
@@ -300,9 +261,9 @@ static struct cpufreq_driver pas_cpufreq_driver = {
        .flags          = CPUFREQ_CONST_LOOPS,
        .init           = pas_cpufreq_cpu_init,
        .exit           = pas_cpufreq_cpu_exit,
-       .verify         = pas_cpufreq_verify,
-       .target         = pas_cpufreq_target,
-       .attr           = pas_cpu_freqs_attr,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = pas_cpufreq_target,
+       .attr           = cpufreq_generic_attr,
 };
 
 /*
index d81c4e5ea0ada8c49afac790f1107bc5ce8f11e6..e2b4f40ff69acaaff51f6461caafd4c8a23bdd16 100644 (file)
@@ -111,8 +111,7 @@ static struct pcc_cpu __percpu *pcc_cpu_info;
 
 static int pcc_cpufreq_verify(struct cpufreq_policy *policy)
 {
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
        return 0;
 }
 
@@ -396,15 +395,14 @@ static int __init pcc_cpufreq_probe(void)
        struct pcc_memory_resource *mem_resource;
        struct pcc_register_resource *reg_resource;
        union acpi_object *out_obj, *member;
-       acpi_handle handle, osc_handle, pcch_handle;
+       acpi_handle handle, osc_handle;
        int ret = 0;
 
        status = acpi_get_handle(NULL, "\\_SB", &handle);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
-       status = acpi_get_handle(handle, "PCCH", &pcch_handle);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(handle, "PCCH"))
                return -ENODEV;
 
        status = acpi_get_handle(handle, "_OSC", &osc_handle);
@@ -560,13 +558,6 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
                ioread32(&pcch_hdr->nominal) * 1000;
        policy->min = policy->cpuinfo.min_freq =
                ioread32(&pcch_hdr->minimum_frequency) * 1000;
-       policy->cur = pcc_get_freq(cpu);
-
-       if (!policy->cur) {
-               pr_debug("init: Unable to get current CPU frequency\n");
-               result = -EINVAL;
-               goto out;
-       }
 
        pr_debug("init: policy->max is %d, policy->min is %d\n",
                policy->max, policy->min);
index a096cd3fa23d1aaef19b3ae27ecd87037f01ba6f..cf55d202f332be36322d7e645ed596b2f2669d16 100644 (file)
@@ -86,11 +86,6 @@ static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
        {0,                     CPUFREQ_TABLE_END},
 };
 
-static struct freq_attr* pmac_cpu_freqs_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static inline void local_delay(unsigned long ms)
 {
        if (no_schedule)
@@ -336,21 +331,11 @@ static int pmu_set_cpu_speed(int low_speed)
        return 0;
 }
 
-static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode,
-               int notify)
+static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode)
 {
-       struct cpufreq_freqs freqs;
        unsigned long l3cr;
        static unsigned long prev_l3cr;
 
-       freqs.old = cur_freq;
-       freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
-
-       if (freqs.old == freqs.new)
-               return 0;
-
-       if (notify)
-               cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
        if (speed_mode == CPUFREQ_LOW &&
            cpu_has_feature(CPU_FTR_L3CR)) {
                l3cr = _get_L3CR();
@@ -366,8 +351,6 @@ static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode,
                if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
                        _set_L3CR(prev_l3cr);
        }
-       if (notify)
-               cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
        cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
 
        return 0;
@@ -378,23 +361,12 @@ static unsigned int pmac_cpufreq_get_speed(unsigned int cpu)
        return cur_freq;
 }
 
-static int pmac_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);
-}
-
 static int pmac_cpufreq_target(        struct cpufreq_policy *policy,
-                                       unsigned int target_freq,
-                                       unsigned int relation)
+                                       unsigned int index)
 {
-       unsigned int    newstate = 0;
        int             rc;
 
-       if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs,
-                       target_freq, relation, &newstate))
-               return -EINVAL;
-
-       rc = do_set_cpu_speed(policy, newstate, 1);
+       rc = do_set_cpu_speed(policy, index);
 
        ppc_proc_freq = cur_freq * 1000ul;
        return rc;
@@ -402,14 +374,7 @@ static int pmac_cpufreq_target(    struct cpufreq_policy *policy,
 
 static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       if (policy->cpu != 0)
-               return -ENODEV;
-
-       policy->cpuinfo.transition_latency      = transition_latency;
-       policy->cur = cur_freq;
-
-       cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
-       return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
+       return cpufreq_generic_init(policy, pmac_cpu_freqs, transition_latency);
 }
 
 static u32 read_gpio(struct device_node *np)
@@ -443,7 +408,7 @@ static int pmac_cpufreq_suspend(struct cpufreq_policy *policy)
        no_schedule = 1;
        sleep_freq = cur_freq;
        if (cur_freq == low_freq && !is_pmu_based)
-               do_set_cpu_speed(policy, CPUFREQ_HIGH, 0);
+               do_set_cpu_speed(policy, CPUFREQ_HIGH);
        return 0;
 }
 
@@ -460,7 +425,7 @@ static int pmac_cpufreq_resume(struct cpufreq_policy *policy)
         * probably high speed due to our suspend() routine
         */
        do_set_cpu_speed(policy, sleep_freq == low_freq ?
-                        CPUFREQ_LOW : CPUFREQ_HIGH, 0);
+                        CPUFREQ_LOW : CPUFREQ_HIGH);
 
        ppc_proc_freq = cur_freq * 1000ul;
 
@@ -469,14 +434,14 @@ static int pmac_cpufreq_resume(struct cpufreq_policy *policy)
 }
 
 static struct cpufreq_driver pmac_cpufreq_driver = {
-       .verify         = pmac_cpufreq_verify,
-       .target         = pmac_cpufreq_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = pmac_cpufreq_target,
        .get            = pmac_cpufreq_get_speed,
        .init           = pmac_cpufreq_cpu_init,
        .suspend        = pmac_cpufreq_suspend,
        .resume         = pmac_cpufreq_resume,
        .flags          = CPUFREQ_PM_NO_WARN,
-       .attr           = pmac_cpu_freqs_attr,
+       .attr           = cpufreq_generic_attr,
        .name           = "powermac",
 };
 
index 3a51ad7e47c8c67c95da5f3691d7f89e397c34a6..6a338f8c386096eb22929c7228a7c38723229a5b 100644 (file)
@@ -70,11 +70,6 @@ static struct cpufreq_frequency_table g5_cpu_freqs[] = {
        {0,                     CPUFREQ_TABLE_END},
 };
 
-static struct freq_attr* g5_cpu_freqs_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 /* Power mode data is an array of the 32 bits PCR values to use for
  * the various frequencies, retrieved from the device-tree
  */
@@ -84,8 +79,6 @@ static void (*g5_switch_volt)(int speed_mode);
 static int (*g5_switch_freq)(int speed_mode);
 static int (*g5_query_freq)(void);
 
-static DEFINE_MUTEX(g5_switch_mutex);
-
 static unsigned long transition_latency;
 
 #ifdef CONFIG_PMAC_SMU
@@ -142,7 +135,7 @@ static void g5_vdnap_switch_volt(int speed_mode)
                pmf_call_one(pfunc_vdnap0_complete, &args);
                if (done)
                        break;
-               msleep(1);
+               usleep_range(1000, 1000);
        }
        if (done == 0)
                printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n");
@@ -241,7 +234,7 @@ static void g5_pfunc_switch_volt(int speed_mode)
                if (pfunc_cpu1_volt_low)
                        pmf_call_one(pfunc_cpu1_volt_low, NULL);
        }
-       msleep(10); /* should be faster , to fix */
+       usleep_range(10000, 10000); /* should be faster , to fix */
 }
 
 /*
@@ -286,7 +279,7 @@ static int g5_pfunc_switch_freq(int speed_mode)
                pmf_call_one(pfunc_slewing_done, &args);
                if (done)
                        break;
-               msleep(1);
+               usleep_range(500, 500);
        }
        if (done == 0)
                printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n");
@@ -317,37 +310,9 @@ static int g5_pfunc_query_freq(void)
  * Common interface to the cpufreq core
  */
 
-static int g5_cpufreq_verify(struct cpufreq_policy *policy)
+static int g5_cpufreq_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       return cpufreq_frequency_table_verify(policy, g5_cpu_freqs);
-}
-
-static int g5_cpufreq_target(struct cpufreq_policy *policy,
-       unsigned int target_freq, unsigned int relation)
-{
-       unsigned int newstate = 0;
-       struct cpufreq_freqs freqs;
-       int rc;
-
-       if (cpufreq_frequency_table_target(policy, g5_cpu_freqs,
-                       target_freq, relation, &newstate))
-               return -EINVAL;
-
-       if (g5_pmode_cur == newstate)
-               return 0;
-
-       mutex_lock(&g5_switch_mutex);
-
-       freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency;
-       freqs.new = g5_cpu_freqs[newstate].frequency;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-       rc = g5_switch_freq(newstate);
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       mutex_unlock(&g5_switch_mutex);
-
-       return rc;
+       return g5_switch_freq(index);
 }
 
 static unsigned int g5_cpufreq_get_speed(unsigned int cpu)
@@ -357,27 +322,17 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu)
 
 static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       policy->cpuinfo.transition_latency = transition_latency;
-       policy->cur = g5_cpu_freqs[g5_query_freq()].frequency;
-       /* secondary CPUs are tied to the primary one by the
-        * cpufreq core if in the secondary policy we tell it that
-        * it actually must be one policy together with all others. */
-       cpumask_copy(policy->cpus, cpu_online_mask);
-       cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu);
-
-       return cpufreq_frequency_table_cpuinfo(policy,
-               g5_cpu_freqs);
+       return cpufreq_generic_init(policy, g5_cpu_freqs, transition_latency);
 }
 
-
 static struct cpufreq_driver g5_cpufreq_driver = {
        .name           = "powermac",
        .flags          = CPUFREQ_CONST_LOOPS,
        .init           = g5_cpufreq_cpu_init,
-       .verify         = g5_cpufreq_verify,
-       .target         = g5_cpufreq_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = g5_cpufreq_target,
        .get            = g5_cpufreq_get_speed,
-       .attr           = g5_cpu_freqs_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 
@@ -397,7 +352,8 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpunode)
        /* Check supported platforms */
        if (of_machine_is_compatible("PowerMac8,1") ||
            of_machine_is_compatible("PowerMac8,2") ||
-           of_machine_is_compatible("PowerMac9,1"))
+           of_machine_is_compatible("PowerMac9,1") ||
+           of_machine_is_compatible("PowerMac12,1"))
                use_volts_smu = 1;
        else if (of_machine_is_compatible("PowerMac11,2"))
                use_volts_vdnap = 1;
@@ -647,8 +603,10 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode)
        g5_cpu_freqs[0].frequency = max_freq;
        g5_cpu_freqs[1].frequency = min_freq;
 
+       /* Based on a measurement on Xserve G5, rounded up. */
+       transition_latency = 10 * NSEC_PER_MSEC;
+
        /* Set callbacks */
-       transition_latency = CPUFREQ_ETERNAL;
        g5_switch_volt = g5_pfunc_switch_volt;
        g5_switch_freq = g5_pfunc_switch_freq;
        g5_query_freq = g5_pfunc_query_freq;
index 85f1c8c25ddc5d20a361e219d023548b356b835b..643e7952cad3d08af4af2cd96e8123105d3e7cf5 100644 (file)
@@ -63,12 +63,12 @@ static int powernow_k6_get_cpu_multiplier(void)
 
 
 /**
- * powernow_k6_set_state - set the PowerNow! multiplier
+ * powernow_k6_target - set the PowerNow! multiplier
  * @best_i: clock_ratio[best_i] is the target multiplier
  *
  *   Tries to change the PowerNow! multiplier
  */
-static void powernow_k6_set_state(struct cpufreq_policy *policy,
+static int powernow_k6_target(struct cpufreq_policy *policy,
                unsigned int best_i)
 {
        unsigned long outvalue = 0, invalue = 0;
@@ -77,7 +77,7 @@ static void powernow_k6_set_state(struct cpufreq_policy *policy,
 
        if (clock_ratio[best_i].driver_data > max_multiplier) {
                printk(KERN_ERR PFX "invalid target frequency\n");
-               return;
+               return -EINVAL;
        }
 
        freqs.old = busfreq * powernow_k6_get_cpu_multiplier();
@@ -100,44 +100,6 @@ static void powernow_k6_set_state(struct cpufreq_policy *policy,
 
        cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
-       return;
-}
-
-
-/**
- * powernow_k6_verify - verifies a new CPUfreq policy
- * @policy: new policy
- *
- * Policy must be within lowest and highest possible CPU Frequency,
- * and at least one possible state must be within min and max.
- */
-static int powernow_k6_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &clock_ratio[0]);
-}
-
-
-/**
- * powernow_k6_setpolicy - sets a new CPUFreq policy
- * @policy: new policy
- * @target_freq: the target frequency
- * @relation: how that frequency relates to achieved frequency
- *  (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
- *
- * sets a new CPUFreq policy
- */
-static int powernow_k6_target(struct cpufreq_policy *policy,
-                              unsigned int target_freq,
-                              unsigned int relation)
-{
-       unsigned int newstate = 0;
-
-       if (cpufreq_frequency_table_target(policy, &clock_ratio[0],
-                               target_freq, relation, &newstate))
-               return -EINVAL;
-
-       powernow_k6_set_state(policy, newstate);
-
        return 0;
 }
 
@@ -145,7 +107,6 @@ static int powernow_k6_target(struct cpufreq_policy *policy,
 static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int i, f;
-       int result;
 
        if (policy->cpu != 0)
                return -ENODEV;
@@ -165,15 +126,8 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.transition_latency = 200000;
-       policy->cur = busfreq * max_multiplier;
-
-       result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(clock_ratio, policy->cpu);
 
-       return 0;
+       return cpufreq_table_validate_and_show(policy, clock_ratio);
 }
 
 
@@ -182,7 +136,7 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
        unsigned int i;
        for (i = 0; i < 8; i++) {
                if (i == max_multiplier)
-                       powernow_k6_set_state(policy, i);
+                       powernow_k6_target(policy, i);
        }
        cpufreq_frequency_table_put_attr(policy->cpu);
        return 0;
@@ -195,19 +149,14 @@ static unsigned int powernow_k6_get(unsigned int cpu)
        return ret;
 }
 
-static struct freq_attr *powernow_k6_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver powernow_k6_driver = {
-       .verify         = powernow_k6_verify,
-       .target         = powernow_k6_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = powernow_k6_target,
        .init           = powernow_k6_cpu_init,
        .exit           = powernow_k6_cpu_exit,
        .get            = powernow_k6_get,
        .name           = "powernow-k6",
-       .attr           = powernow_k6_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id powernow_k6_ids[] = {
index 14ce480be8ab2503515cb1d61b8f30b5892d85d2..946708a1d7452d87adc932aac1e1edf7ce1fd29d 100644 (file)
@@ -248,7 +248,7 @@ static void change_VID(int vid)
 }
 
 
-static void change_speed(struct cpufreq_policy *policy, unsigned int index)
+static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
 {
        u8 fid, vid;
        struct cpufreq_freqs freqs;
@@ -291,6 +291,8 @@ static void change_speed(struct cpufreq_policy *policy, unsigned int index)
                local_irq_enable();
 
        cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+
+       return 0;
 }
 
 
@@ -533,27 +535,6 @@ static int powernow_decode_bios(int maxfid, int startvid)
 }
 
 
-static int powernow_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq,
-                           unsigned int relation)
-{
-       unsigned int newstate;
-
-       if (cpufreq_frequency_table_target(policy, powernow_table, target_freq,
-                               relation, &newstate))
-               return -EINVAL;
-
-       change_speed(policy, newstate);
-
-       return 0;
-}
-
-
-static int powernow_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, powernow_table);
-}
-
 /*
  * We use the fact that the bus frequency is somehow
  * a multiple of 100000/3 khz, then we compute sgtc according
@@ -678,11 +659,7 @@ static int powernow_cpu_init(struct cpufreq_policy *policy)
        policy->cpuinfo.transition_latency =
                cpufreq_scale(2000000UL, fsb, latency);
 
-       policy->cur = powernow_get(0);
-
-       cpufreq_frequency_table_get_attr(powernow_table, policy->cpu);
-
-       return cpufreq_frequency_table_cpuinfo(policy, powernow_table);
+       return cpufreq_table_validate_and_show(policy, powernow_table);
 }
 
 static int powernow_cpu_exit(struct cpufreq_policy *policy)
@@ -701,14 +678,9 @@ static int powernow_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-static struct freq_attr *powernow_table_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver powernow_driver = {
-       .verify         = powernow_verify,
-       .target         = powernow_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = powernow_target,
        .get            = powernow_get,
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
        .bios_limit     = acpi_processor_get_bios_limit,
@@ -716,7 +688,7 @@ static struct cpufreq_driver powernow_driver = {
        .init           = powernow_cpu_init,
        .exit           = powernow_cpu_exit,
        .name           = "powernow-k7",
-       .attr           = powernow_table_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init powernow_init(void)
index 2344a9ed17f3c38017701e075c945df8ae0f4bdf..0023c7d40a51a21994620907e75520e5512c5d52 100644 (file)
@@ -977,20 +977,17 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
 
 struct powernowk8_target_arg {
        struct cpufreq_policy           *pol;
-       unsigned                        targfreq;
-       unsigned                        relation;
+       unsigned                        newstate;
 };
 
 static long powernowk8_target_fn(void *arg)
 {
        struct powernowk8_target_arg *pta = arg;
        struct cpufreq_policy *pol = pta->pol;
-       unsigned targfreq = pta->targfreq;
-       unsigned relation = pta->relation;
+       unsigned newstate = pta->newstate;
        struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
        u32 checkfid;
        u32 checkvid;
-       unsigned int newstate;
        int ret;
 
        if (!data)
@@ -1004,8 +1001,9 @@ static long powernowk8_target_fn(void *arg)
                return -EIO;
        }
 
-       pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
-               pol->cpu, targfreq, pol->min, pol->max, relation);
+       pr_debug("targ: cpu %d, %d kHz, min %d, max %d\n",
+               pol->cpu, data->powernow_table[newstate].frequency, pol->min,
+               pol->max);
 
        if (query_current_values_with_pending_wait(data))
                return -EIO;
@@ -1021,10 +1019,6 @@ static long powernowk8_target_fn(void *arg)
                       checkvid, data->currvid);
        }
 
-       if (cpufreq_frequency_table_target(pol, data->powernow_table,
-                               targfreq, relation, &newstate))
-               return -EIO;
-
        mutex_lock(&fidvid_mutex);
 
        powernow_k8_acpi_pst_values(data, newstate);
@@ -1044,26 +1038,13 @@ static long powernowk8_target_fn(void *arg)
 }
 
 /* Driver entry point to switch to the target frequency */
-static int powernowk8_target(struct cpufreq_policy *pol,
-               unsigned targfreq, unsigned relation)
+static int powernowk8_target(struct cpufreq_policy *pol, unsigned index)
 {
-       struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,
-                                            .relation = relation };
+       struct powernowk8_target_arg pta = { .pol = pol, .newstate = index };
 
        return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
 }
 
-/* Driver entry point to verify the policy and range of frequencies */
-static int powernowk8_verify(struct cpufreq_policy *pol)
-{
-       struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
-
-       if (!data)
-               return -EINVAL;
-
-       return cpufreq_frequency_table_verify(pol, data->powernow_table);
-}
-
 struct init_on_cpu {
        struct powernow_k8_data *data;
        int rc;
@@ -1152,11 +1133,8 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
        cpumask_copy(pol->cpus, cpu_core_mask(pol->cpu));
        data->available_cores = pol->cpus;
 
-       pol->cur = find_khz_freq_from_fid(data->currfid);
-       pr_debug("policy current frequency %d kHz\n", pol->cur);
-
        /* min/max the cpu is capable of */
-       if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table)) {
+       if (cpufreq_table_validate_and_show(pol, data->powernow_table)) {
                printk(KERN_ERR FW_BUG PFX "invalid powernow_table\n");
                powernow_k8_cpu_exit_acpi(data);
                kfree(data->powernow_table);
@@ -1164,8 +1142,6 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
                return -EINVAL;
        }
 
-       cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
-
        pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
                 data->currfid, data->currvid);
 
@@ -1227,20 +1203,16 @@ out:
        return khz;
 }
 
-static struct freq_attr *powernow_k8_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver cpufreq_amd64_driver = {
-       .verify         = powernowk8_verify,
-       .target         = powernowk8_target,
+       .flags          = CPUFREQ_ASYNC_NOTIFICATION,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = powernowk8_target,
        .bios_limit     = acpi_processor_get_bios_limit,
        .init           = powernowk8_cpu_init,
        .exit           = powernowk8_cpu_exit,
        .get            = powernowk8_get,
        .name           = "powernow-k8",
-       .attr           = powernow_k8_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static void __request_acpi_cpufreq(void)
index 60e81d524ea8231666210ecca2c97407c0a5a279..3f7be46d2b27ac1f5dc362d85c08697d5530dea2 100644 (file)
@@ -69,8 +69,6 @@ static const struct soc_data sdata[] = {
 static u32 min_cpufreq;
 static const u32 *fmask;
 
-/* serialize frequency changes  */
-static DEFINE_MUTEX(cpufreq_lock);
 static DEFINE_PER_CPU(struct cpu_data *, cpu_data);
 
 /* cpumask in a cluster */
@@ -202,7 +200,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
        table[i].frequency = CPUFREQ_TABLE_END;
 
        /* set the min and max frequency properly */
-       ret = cpufreq_frequency_table_cpuinfo(policy, table);
+       ret = cpufreq_table_validate_and_show(policy, table);
        if (ret) {
                pr_err("invalid frequency table: %d\n", ret);
                goto err_nomem1;
@@ -217,9 +215,6 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
                per_cpu(cpu_data, i) = data;
 
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       policy->cur = corenet_cpufreq_get_speed(policy->cpu);
-
-       cpufreq_frequency_table_get_attr(table, cpu);
        of_node_put(np);
 
        return 0;
@@ -253,60 +248,25 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-static int corenet_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       struct cpufreq_frequency_table *table =
-               per_cpu(cpu_data, policy->cpu)->table;
-
-       return cpufreq_frequency_table_verify(policy, table);
-}
-
 static int corenet_cpufreq_target(struct cpufreq_policy *policy,
-               unsigned int target_freq, unsigned int relation)
+               unsigned int index)
 {
-       struct cpufreq_freqs freqs;
-       unsigned int new;
        struct clk *parent;
-       int ret;
        struct cpu_data *data = per_cpu(cpu_data, policy->cpu);
 
-       cpufreq_frequency_table_target(policy, data->table,
-                       target_freq, relation, &new);
-
-       if (policy->cur == data->table[new].frequency)
-               return 0;
-
-       freqs.old = policy->cur;
-       freqs.new = data->table[new].frequency;
-
-       mutex_lock(&cpufreq_lock);
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
-       parent = of_clk_get(data->parent, data->table[new].driver_data);
-       ret = clk_set_parent(data->clk, parent);
-       if (ret)
-               freqs.new = freqs.old;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-       mutex_unlock(&cpufreq_lock);
-
-       return ret;
+       parent = of_clk_get(data->parent, data->table[index].driver_data);
+       return clk_set_parent(data->clk, parent);
 }
 
-static struct freq_attr *corenet_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver ppc_corenet_cpufreq_driver = {
        .name           = "ppc_cpufreq",
        .flags          = CPUFREQ_CONST_LOOPS,
        .init           = corenet_cpufreq_cpu_init,
        .exit           = __exit_p(corenet_cpufreq_cpu_exit),
-       .verify         = corenet_cpufreq_verify,
-       .target         = corenet_cpufreq_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = corenet_cpufreq_target,
        .get            = corenet_cpufreq_get_speed,
-       .attr           = corenet_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct of_device_id node_matches[] __initdata = {
index 2e448f0bbdc583465672e7ec40804f1d01467224..e42ca9c31ceaf03852206c92419b25e81dc45883 100644 (file)
@@ -30,9 +30,6 @@
 
 #include "ppc_cbe_cpufreq.h"
 
-static DEFINE_MUTEX(cbe_switch_mutex);
-
-
 /* the CBE supports an 8 step frequency scaling */
 static struct cpufreq_frequency_table cbe_freqs[] = {
        {1,     0},
@@ -123,63 +120,28 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
        cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu));
 #endif
 
-       cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
-
        /* this ensures that policy->cpuinfo_min
         * and policy->cpuinfo_max are set correctly */
-       return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs);
-}
-
-static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
-static int cbe_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, cbe_freqs);
+       return cpufreq_table_validate_and_show(policy, cbe_freqs);
 }
 
 static int cbe_cpufreq_target(struct cpufreq_policy *policy,
-                             unsigned int target_freq,
-                             unsigned int relation)
+                             unsigned int cbe_pmode_new)
 {
-       int rc;
-       struct cpufreq_freqs freqs;
-       unsigned int cbe_pmode_new;
-
-       cpufreq_frequency_table_target(policy,
-                                      cbe_freqs,
-                                      target_freq,
-                                      relation,
-                                      &cbe_pmode_new);
-
-       freqs.old = policy->cur;
-       freqs.new = cbe_freqs[cbe_pmode_new].frequency;
-
-       mutex_lock(&cbe_switch_mutex);
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        pr_debug("setting frequency for cpu %d to %d kHz, " \
                 "1/%d of max frequency\n",
                 policy->cpu,
                 cbe_freqs[cbe_pmode_new].frequency,
                 cbe_freqs[cbe_pmode_new].driver_data);
 
-       rc = set_pmode(policy->cpu, cbe_pmode_new);
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-       mutex_unlock(&cbe_switch_mutex);
-
-       return rc;
+       return set_pmode(policy->cpu, cbe_pmode_new);
 }
 
 static struct cpufreq_driver cbe_cpufreq_driver = {
-       .verify         = cbe_cpufreq_verify,
-       .target         = cbe_cpufreq_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = cbe_cpufreq_target,
        .init           = cbe_cpufreq_cpu_init,
-       .exit           = cbe_cpufreq_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .name           = "cbe-cpufreq",
        .flags          = CPUFREQ_CONST_LOOPS,
 };
index 8749eaf1879338ad331f587c9a716a501ab0c701..0a0f4369636a6e14938e728bba38a3323658e7df 100644 (file)
@@ -262,36 +262,15 @@ static u32 mdrefr_dri(unsigned int freq)
        return (interval - (cpu_is_pxa27x() ? 31 : 0)) / 32;
 }
 
-/* find a valid frequency point */
-static int pxa_verify_policy(struct cpufreq_policy *policy)
-{
-       struct cpufreq_frequency_table *pxa_freqs_table;
-       pxa_freqs_t *pxa_freqs;
-       int ret;
-
-       find_freq_tables(&pxa_freqs_table, &pxa_freqs);
-       ret = cpufreq_frequency_table_verify(policy, pxa_freqs_table);
-
-       if (freq_debug)
-               pr_debug("Verified CPU policy: %dKhz min to %dKhz max\n",
-                        policy->min, policy->max);
-
-       return ret;
-}
-
 static unsigned int pxa_cpufreq_get(unsigned int cpu)
 {
        return get_clk_frequency_khz(0);
 }
 
-static int pxa_set_target(struct cpufreq_policy *policy,
-                         unsigned int target_freq,
-                         unsigned int relation)
+static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx)
 {
        struct cpufreq_frequency_table *pxa_freqs_table;
        pxa_freqs_t *pxa_freq_settings;
-       struct cpufreq_freqs freqs;
-       unsigned int idx;
        unsigned long flags;
        unsigned int new_freq_cpu, new_freq_mem;
        unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg;
@@ -300,32 +279,19 @@ static int pxa_set_target(struct cpufreq_policy *policy,
        /* Get the current policy */
        find_freq_tables(&pxa_freqs_table, &pxa_freq_settings);
 
-       /* Lookup the next frequency */
-       if (cpufreq_frequency_table_target(policy, pxa_freqs_table,
-                                          target_freq, relation, &idx)) {
-               return -EINVAL;
-       }
-
        new_freq_cpu = pxa_freq_settings[idx].khz;
        new_freq_mem = pxa_freq_settings[idx].membus;
-       freqs.old = policy->cur;
-       freqs.new = new_freq_cpu;
 
        if (freq_debug)
                pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n",
-                        freqs.new / 1000, (pxa_freq_settings[idx].div2) ?
+                        new_freq_cpu / 1000, (pxa_freq_settings[idx].div2) ?
                         (new_freq_mem / 2000) : (new_freq_mem / 1000));
 
-       if (vcc_core && freqs.new > freqs.old)
+       if (vcc_core && new_freq_cpu > policy->cur) {
                ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
-       if (ret)
-               return ret;
-       /*
-        * Tell everyone what we're about to do...
-        * you should add a notify client with any platform specific
-        * Vcc changing capability
-        */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+               if (ret)
+                       return ret;
+       }
 
        /* Calculate the next MDREFR.  If we're slowing down the SDRAM clock
         * we need to preset the smaller DRI before the change.  If we're
@@ -375,13 +341,6 @@ static int pxa_set_target(struct cpufreq_policy *policy,
                     : "r4", "r5");
        local_irq_restore(flags);
 
-       /*
-        * Tell everyone what we've just done...
-        * you should add a notify client with any platform specific
-        * SDRAM refresh timer adjustments
-        */
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
        /*
         * Even if voltage setting fails, we don't report it, as the frequency
         * change succeeded. The voltage reduction is not a critical failure,
@@ -391,7 +350,7 @@ static int pxa_set_target(struct cpufreq_policy *policy,
         * bug is triggered (seems a deadlock). Should anybody find out where,
         * the "return 0" should become a "return ret".
         */
-       if (vcc_core && freqs.new < freqs.old)
+       if (vcc_core && new_freq_cpu < policy->cur)
                ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
 
        return 0;
@@ -414,8 +373,6 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
 
        /* set default policy and cpuinfo */
        policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
-       policy->cur = get_clk_frequency_khz(0);    /* current freq */
-       policy->min = policy->max = policy->cur;
 
        /* Generate pxa25x the run cpufreq_frequency_table struct */
        for (i = 0; i < NUM_PXA25x_RUN_FREQS; i++) {
@@ -453,10 +410,12 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
                find_freq_tables(&pxa255_freq_table, &pxa255_freqs);
                pr_info("PXA255 cpufreq using %s frequency table\n",
                        pxa255_turbo_table ? "turbo" : "run");
-               cpufreq_frequency_table_cpuinfo(policy, pxa255_freq_table);
+
+               cpufreq_table_validate_and_show(policy, pxa255_freq_table);
+       }
+       else if (cpu_is_pxa27x()) {
+               cpufreq_table_validate_and_show(policy, pxa27x_freq_table);
        }
-       else if (cpu_is_pxa27x())
-               cpufreq_frequency_table_cpuinfo(policy, pxa27x_freq_table);
 
        printk(KERN_INFO "PXA CPU frequency change support initialized\n");
 
@@ -464,9 +423,10 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
 }
 
 static struct cpufreq_driver pxa_cpufreq_driver = {
-       .verify = pxa_verify_policy,
-       .target = pxa_set_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = pxa_set_target,
        .init   = pxa_cpufreq_init,
+       .exit   = cpufreq_generic_exit,
        .get    = pxa_cpufreq_get,
        .name   = "PXA2xx",
 };
index d26306fb00d2e8a749ed044c816533f101defd11..93840048dd110c5130af9d930b2576562d9f8f1c 100644 (file)
@@ -108,7 +108,7 @@ static int setup_freqs_table(struct cpufreq_policy *policy,
        pxa3xx_freqs_num = num;
        pxa3xx_freqs_table = table;
 
-       return cpufreq_frequency_table_cpuinfo(policy, table);
+       return cpufreq_table_validate_and_show(policy, table);
 }
 
 static void __update_core_freq(struct pxa3xx_freq_info *info)
@@ -150,54 +150,26 @@ static void __update_bus_freq(struct pxa3xx_freq_info *info)
                cpu_relax();
 }
 
-static int pxa3xx_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, pxa3xx_freqs_table);
-}
-
 static unsigned int pxa3xx_cpufreq_get(unsigned int cpu)
 {
        return pxa3xx_get_clk_frequency_khz(0);
 }
 
-static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy,
-                             unsigned int target_freq,
-                             unsigned int relation)
+static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, unsigned int index)
 {
        struct pxa3xx_freq_info *next;
-       struct cpufreq_freqs freqs;
        unsigned long flags;
-       int idx;
 
        if (policy->cpu != 0)
                return -EINVAL;
 
-       /* Lookup the next frequency */
-       if (cpufreq_frequency_table_target(policy, pxa3xx_freqs_table,
-                               target_freq, relation, &idx))
-               return -EINVAL;
-
-       next = &pxa3xx_freqs[idx];
-
-       freqs.old = policy->cur;
-       freqs.new = next->cpufreq_mhz * 1000;
-
-       pr_debug("CPU frequency from %d MHz to %d MHz%s\n",
-                       freqs.old / 1000, freqs.new / 1000,
-                       (freqs.old == freqs.new) ? " (skipped)" : "");
-
-       if (freqs.old == target_freq)
-               return 0;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+       next = &pxa3xx_freqs[index];
 
        local_irq_save(flags);
        __update_core_freq(next);
        __update_bus_freq(next);
        local_irq_restore(flags);
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
        return 0;
 }
 
@@ -206,11 +178,10 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
        int ret = -EINVAL;
 
        /* set default policy and cpuinfo */
-       policy->cpuinfo.min_freq = 104000;
-       policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000;
+       policy->min = policy->cpuinfo.min_freq = 104000;
+       policy->max = policy->cpuinfo.max_freq =
+               (cpu_is_pxa320()) ? 806000 : 624000;
        policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
-       policy->max = pxa3xx_get_clk_frequency_khz(0);
-       policy->cur = policy->min = policy->max;
 
        if (cpu_is_pxa300() || cpu_is_pxa310())
                ret = setup_freqs_table(policy, pxa300_freqs,
@@ -230,9 +201,10 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
 }
 
 static struct cpufreq_driver pxa3xx_cpufreq_driver = {
-       .verify         = pxa3xx_cpufreq_verify,
-       .target         = pxa3xx_cpufreq_set,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = pxa3xx_cpufreq_set,
        .init           = pxa3xx_cpufreq_init,
+       .exit           = cpufreq_generic_exit,
        .get            = pxa3xx_cpufreq_get,
        .name           = "pxa3xx-cpufreq",
 };
index 22dcb81ef9d0e9069b8fc4d49249713d59d41dd9..8d904a00027b5fc5ca3a364ffb2c6be7e298c5fd 100644 (file)
@@ -87,16 +87,6 @@ static struct cpufreq_frequency_table s3c2450_freq_table[] = {
        { 0, CPUFREQ_TABLE_END },
 };
 
-static int s3c2416_cpufreq_verify_speed(struct cpufreq_policy *policy)
-{
-       struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
-
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       return cpufreq_frequency_table_verify(policy, s3c_freq->freq_table);
-}
-
 static unsigned int s3c2416_cpufreq_get_speed(unsigned int cpu)
 {
        struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
@@ -227,24 +217,15 @@ static int s3c2416_cpufreq_leave_dvs(struct s3c2416_data *s3c_freq, int idx)
 }
 
 static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
-                                     unsigned int target_freq,
-                                     unsigned int relation)
+                                     unsigned int index)
 {
        struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
-       struct cpufreq_freqs freqs;
+       unsigned int new_freq;
        int idx, ret, to_dvs = 0;
-       unsigned int i;
 
        mutex_lock(&cpufreq_lock);
 
-       pr_debug("cpufreq: to %dKHz, relation %d\n", target_freq, relation);
-
-       ret = cpufreq_frequency_table_target(policy, s3c_freq->freq_table,
-                                            target_freq, relation, &i);
-       if (ret != 0)
-               goto out;
-
-       idx = s3c_freq->freq_table[i].driver_data;
+       idx = s3c_freq->freq_table[index].driver_data;
 
        if (idx == SOURCE_HCLK)
                to_dvs = 1;
@@ -256,24 +237,13 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
                goto out;
        }
 
-       freqs.flags = 0;
-       freqs.old = s3c_freq->is_dvs ? FREQ_DVS
-                                    : clk_get_rate(s3c_freq->armclk) / 1000;
-
        /* When leavin dvs mode, always switch the armdiv to the hclk rate
         * The S3C2416 has stability issues when switching directly to
         * higher frequencies.
         */
-       freqs.new = (s3c_freq->is_dvs && !to_dvs)
+       new_freq = (s3c_freq->is_dvs && !to_dvs)
                                ? clk_get_rate(s3c_freq->hclk) / 1000
-                               : s3c_freq->freq_table[i].frequency;
-
-       pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
-
-       if (!to_dvs && freqs.old == freqs.new)
-               goto out;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+                               : s3c_freq->freq_table[index].frequency;
 
        if (to_dvs) {
                pr_debug("cpufreq: enter dvs\n");
@@ -282,12 +252,10 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
                pr_debug("cpufreq: leave dvs\n");
                ret = s3c2416_cpufreq_leave_dvs(s3c_freq, idx);
        } else {
-               pr_debug("cpufreq: change armdiv to %dkHz\n", freqs.new);
-               ret = s3c2416_cpufreq_set_armdiv(s3c_freq, freqs.new);
+               pr_debug("cpufreq: change armdiv to %dkHz\n", new_freq);
+               ret = s3c2416_cpufreq_set_armdiv(s3c_freq, new_freq);
        }
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
 out:
        mutex_unlock(&cpufreq_lock);
 
@@ -486,20 +454,14 @@ static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy)
                freq++;
        }
 
-       policy->cur = clk_get_rate(s3c_freq->armclk) / 1000;
-
        /* Datasheet says PLL stabalisation time must be at least 300us,
         * so but add some fudge. (reference in LOCKCON0 register description)
         */
-       policy->cpuinfo.transition_latency = (500 * 1000) +
-                                            s3c_freq->regulator_latency;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, s3c_freq->freq_table);
+       ret = cpufreq_generic_init(policy, s3c_freq->freq_table,
+                       (500 * 1000) + s3c_freq->regulator_latency);
        if (ret)
                goto err_freq_table;
 
-       cpufreq_frequency_table_get_attr(s3c_freq->freq_table, 0);
-
        register_reboot_notifier(&s3c2416_cpufreq_reboot_notifier);
 
        return 0;
@@ -518,19 +480,14 @@ err_hclk:
        return ret;
 }
 
-static struct freq_attr *s3c2416_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver s3c2416_cpufreq_driver = {
        .flags          = 0,
-       .verify         = s3c2416_cpufreq_verify_speed,
-       .target         = s3c2416_cpufreq_set_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = s3c2416_cpufreq_set_target,
        .get            = s3c2416_cpufreq_get_speed,
        .init           = s3c2416_cpufreq_driver_init,
        .name           = "s3c2416",
-       .attr           = s3c2416_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init s3c2416_cpufreq_init(void)
index b0f343fcb7eefdfe40b942b202398372a618df44..485088253358d1a5712c9f73cfea9036f65aa156 100644 (file)
@@ -373,23 +373,7 @@ struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
 
 static int s3c_cpufreq_init(struct cpufreq_policy *policy)
 {
-       printk(KERN_INFO "%s: initialising policy %p\n", __func__, policy);
-
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       policy->cur = s3c_cpufreq_get(0);
-       policy->min = policy->cpuinfo.min_freq = 0;
-       policy->max = policy->cpuinfo.max_freq = cpu_cur.info->max.fclk / 1000;
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-
-       /* feed the latency information from the cpu driver */
-       policy->cpuinfo.transition_latency = cpu_cur.info->latency;
-
-       if (ftab)
-               cpufreq_frequency_table_cpuinfo(policy, ftab);
-
-       return 0;
+       return cpufreq_generic_init(policy, ftab, cpu_cur.info->latency);
 }
 
 static int __init s3c_cpufreq_initclks(void)
@@ -416,14 +400,6 @@ static int __init s3c_cpufreq_initclks(void)
        return 0;
 }
 
-static int s3c_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       return 0;
-}
-
 #ifdef CONFIG_PM
 static struct cpufreq_frequency_table suspend_pll;
 static unsigned int suspend_freq;
@@ -473,7 +449,6 @@ static int s3c_cpufreq_resume(struct cpufreq_policy *policy)
 
 static struct cpufreq_driver s3c24xx_driver = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = s3c_cpufreq_verify,
        .target         = s3c_cpufreq_target,
        .get            = s3c_cpufreq_get,
        .init           = s3c_cpufreq_init,
index 8a72b0c555f846da21d25d02d9f94d427a7796b5..67e302eeefec14abbc30bc5fd3b67773b93b0c18 100644 (file)
@@ -54,14 +54,6 @@ static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
 };
 #endif
 
-static int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy *policy)
-{
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table);
-}
-
 static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu)
 {
        if (cpu != 0)
@@ -71,66 +63,48 @@ static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu)
 }
 
 static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
-                                     unsigned int target_freq,
-                                     unsigned int relation)
+                                     unsigned int index)
 {
-       int ret;
-       unsigned int i;
-       struct cpufreq_freqs freqs;
        struct s3c64xx_dvfs *dvfs;
+       unsigned int old_freq, new_freq;
+       int ret;
 
-       ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table,
-                                            target_freq, relation, &i);
-       if (ret != 0)
-               return ret;
-
-       freqs.old = clk_get_rate(armclk) / 1000;
-       freqs.new = s3c64xx_freq_table[i].frequency;
-       freqs.flags = 0;
-       dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].driver_data];
-
-       if (freqs.old == freqs.new)
-               return 0;
-
-       pr_debug("Transition %d-%dkHz\n", freqs.old, freqs.new);
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+       old_freq = clk_get_rate(armclk) / 1000;
+       new_freq = s3c64xx_freq_table[index].frequency;
+       dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[index].driver_data];
 
 #ifdef CONFIG_REGULATOR
-       if (vddarm && freqs.new > freqs.old) {
+       if (vddarm && new_freq > old_freq) {
                ret = regulator_set_voltage(vddarm,
                                            dvfs->vddarm_min,
                                            dvfs->vddarm_max);
                if (ret != 0) {
                        pr_err("Failed to set VDDARM for %dkHz: %d\n",
-                              freqs.new, ret);
-                       freqs.new = freqs.old;
-                       goto post_notify;
+                              new_freq, ret);
+                       return ret;
                }
        }
 #endif
 
-       ret = clk_set_rate(armclk, freqs.new * 1000);
+       ret = clk_set_rate(armclk, new_freq * 1000);
        if (ret < 0) {
                pr_err("Failed to set rate %dkHz: %d\n",
-                      freqs.new, ret);
-               freqs.new = freqs.old;
+                      new_freq, ret);
+               return ret;
        }
 
-post_notify:
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-       if (ret)
-               goto err;
-
 #ifdef CONFIG_REGULATOR
-       if (vddarm && freqs.new < freqs.old) {
+       if (vddarm && new_freq < old_freq) {
                ret = regulator_set_voltage(vddarm,
                                            dvfs->vddarm_min,
                                            dvfs->vddarm_max);
                if (ret != 0) {
                        pr_err("Failed to set VDDARM for %dkHz: %d\n",
-                              freqs.new, ret);
-                       goto err_clk;
+                              new_freq, ret);
+                       if (clk_set_rate(armclk, old_freq * 1000) < 0)
+                               pr_err("Failed to restore original clock rate\n");
+
+                       return ret;
                }
        }
 #endif
@@ -139,14 +113,6 @@ post_notify:
                 clk_get_rate(armclk) / 1000);
 
        return 0;
-
-err_clk:
-       if (clk_set_rate(armclk, freqs.old * 1000) < 0)
-               pr_err("Failed to restore original clock rate\n");
-err:
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       return ret;
 }
 
 #ifdef CONFIG_REGULATOR
@@ -166,7 +132,7 @@ static void __init s3c64xx_cpufreq_config_regulator(void)
                if (freq->frequency == CPUFREQ_ENTRY_INVALID)
                        continue;
 
-               dvfs = &s3c64xx_dvfs_table[freq->index];
+               dvfs = &s3c64xx_dvfs_table[freq->driver_data];
                found = 0;
 
                for (i = 0; i < count; i++) {
@@ -243,15 +209,12 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
                freq++;
        }
 
-       policy->cur = clk_get_rate(armclk) / 1000;
-
        /* Datasheet says PLL stabalisation time (if we were to use
         * the PLLs, which we don't currently) is ~300us worst case,
         * but add some fudge.
         */
-       policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table);
+       ret = cpufreq_generic_init(policy, s3c64xx_freq_table,
+                       (500 * 1000) + regulator_latency);
        if (ret != 0) {
                pr_err("Failed to configure frequency table: %d\n",
                       ret);
@@ -264,8 +227,8 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
 
 static struct cpufreq_driver s3c64xx_cpufreq_driver = {
        .flags          = 0,
-       .verify         = s3c64xx_cpufreq_verify_speed,
-       .target         = s3c64xx_cpufreq_set_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = s3c64xx_cpufreq_set_target,
        .get            = s3c64xx_cpufreq_get_speed,
        .init           = s3c64xx_cpufreq_driver_init,
        .name           = "s3c",
index 5c77570737937c298577303904baa60823fdce60..e3973dae28a744a87c80fcea8aef2bd85446d796 100644 (file)
@@ -26,7 +26,6 @@
 static struct clk *cpu_clk;
 static struct clk *dmc0_clk;
 static struct clk *dmc1_clk;
-static struct cpufreq_freqs freqs;
 static DEFINE_MUTEX(set_freq_lock);
 
 /* APLL M,P,S values for 1G/800Mhz */
@@ -36,16 +35,7 @@ static DEFINE_MUTEX(set_freq_lock);
 /* Use 800MHz when entering sleep mode */
 #define SLEEP_FREQ     (800 * 1000)
 
-/*
- * relation has an additional symantics other than the standard of cpufreq
- * DISALBE_FURTHER_CPUFREQ: disable further access to target
- * ENABLE_FURTUER_CPUFREQ: enable access to target
- */
-enum cpufreq_access {
-       DISABLE_FURTHER_CPUFREQ = 0x10,
-       ENABLE_FURTHER_CPUFREQ = 0x20,
-};
-
+/* Tracks if cpu freqency can be updated anymore */
 static bool no_cpufreq_access;
 
 /*
@@ -174,14 +164,6 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
        __raw_writel(tmp1, reg);
 }
 
-static int s5pv210_verify_speed(struct cpufreq_policy *policy)
-{
-       if (policy->cpu)
-               return -EINVAL;
-
-       return cpufreq_frequency_table_verify(policy, s5pv210_freq_table);
-}
-
 static unsigned int s5pv210_getspeed(unsigned int cpu)
 {
        if (cpu)
@@ -190,22 +172,18 @@ static unsigned int s5pv210_getspeed(unsigned int cpu)
        return clk_get_rate(cpu_clk) / 1000;
 }
 
-static int s5pv210_target(struct cpufreq_policy *policy,
-                         unsigned int target_freq,
-                         unsigned int relation)
+static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
 {
        unsigned long reg;
-       unsigned int index, priv_index;
+       unsigned int priv_index;
        unsigned int pll_changing = 0;
        unsigned int bus_speed_changing = 0;
+       unsigned int old_freq, new_freq;
        int arm_volt, int_volt;
        int ret = 0;
 
        mutex_lock(&set_freq_lock);
 
-       if (relation & ENABLE_FURTHER_CPUFREQ)
-               no_cpufreq_access = false;
-
        if (no_cpufreq_access) {
 #ifdef CONFIG_PM_VERBOSE
                pr_err("%s:%d denied access to %s as it is disabled"
@@ -215,27 +193,13 @@ static int s5pv210_target(struct cpufreq_policy *policy,
                goto exit;
        }
 
-       if (relation & DISABLE_FURTHER_CPUFREQ)
-               no_cpufreq_access = true;
-
-       relation &= ~(ENABLE_FURTHER_CPUFREQ | DISABLE_FURTHER_CPUFREQ);
-
-       freqs.old = s5pv210_getspeed(0);
-
-       if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
-                                          target_freq, relation, &index)) {
-               ret = -EINVAL;
-               goto exit;
-       }
-
-       freqs.new = s5pv210_freq_table[index].frequency;
-
-       if (freqs.new == freqs.old)
-               goto exit;
+       old_freq = s5pv210_getspeed(0);
+       new_freq = s5pv210_freq_table[index].frequency;
 
        /* Finding current running level index */
        if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
-                                          freqs.old, relation, &priv_index)) {
+                                          old_freq, CPUFREQ_RELATION_H,
+                                          &priv_index)) {
                ret = -EINVAL;
                goto exit;
        }
@@ -243,7 +207,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
        arm_volt = dvs_conf[index].arm_volt;
        int_volt = dvs_conf[index].int_volt;
 
-       if (freqs.new > freqs.old) {
+       if (new_freq > old_freq) {
                ret = regulator_set_voltage(arm_regulator,
                                arm_volt, arm_volt_max);
                if (ret)
@@ -255,8 +219,6 @@ static int s5pv210_target(struct cpufreq_policy *policy,
                        goto exit;
        }
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        /* Check if there need to change PLL */
        if ((index == L0) || (priv_index == L0))
                pll_changing = 1;
@@ -467,9 +429,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
                }
        }
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
-       if (freqs.new < freqs.old) {
+       if (new_freq < old_freq) {
                regulator_set_voltage(int_regulator,
                                int_volt, int_volt_max);
 
@@ -551,13 +511,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
        s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
        s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
 
-       policy->cur = policy->min = policy->max = s5pv210_getspeed(0);
-
-       cpufreq_frequency_table_get_attr(s5pv210_freq_table, policy->cpu);
-
-       policy->cpuinfo.transition_latency = 40000;
-
-       return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
+       return cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
 
 out_dmc1:
        clk_put(dmc0_clk);
@@ -573,16 +527,18 @@ static int s5pv210_cpufreq_notifier_event(struct notifier_block *this,
 
        switch (event) {
        case PM_SUSPEND_PREPARE:
-               ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
-                                           DISABLE_FURTHER_CPUFREQ);
+               ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
                if (ret < 0)
                        return NOTIFY_BAD;
 
+               /* Disable updation of cpu frequency */
+               no_cpufreq_access = true;
                return NOTIFY_OK;
        case PM_POST_RESTORE:
        case PM_POST_SUSPEND:
-               cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
-                                     ENABLE_FURTHER_CPUFREQ);
+               /* Enable updation of cpu frequency */
+               no_cpufreq_access = false;
+               cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
 
                return NOTIFY_OK;
        }
@@ -595,18 +551,18 @@ static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
 {
        int ret;
 
-       ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
-                                   DISABLE_FURTHER_CPUFREQ);
+       ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
        if (ret < 0)
                return NOTIFY_BAD;
 
+       no_cpufreq_access = true;
        return NOTIFY_DONE;
 }
 
 static struct cpufreq_driver s5pv210_driver = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = s5pv210_verify_speed,
-       .target         = s5pv210_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = s5pv210_target,
        .get            = s5pv210_getspeed,
        .init           = s5pv210_cpu_init,
        .name           = "s5pv210",
index cff18e87ca58721cc9ae13e432816d712d7d0c2d..623da742f8e7fc6890510101b99f110e2a470292 100644 (file)
@@ -177,60 +177,33 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed)
        }
 }
 
-static int sa1100_target(struct cpufreq_policy *policy,
-                        unsigned int target_freq,
-                        unsigned int relation)
+static int sa1100_target(struct cpufreq_policy *policy, unsigned int ppcr)
 {
        unsigned int cur = sa11x0_getspeed(0);
-       unsigned int new_ppcr;
-       struct cpufreq_freqs freqs;
-
-       new_ppcr = sa11x0_freq_to_ppcr(target_freq);
-       switch (relation) {
-       case CPUFREQ_RELATION_L:
-               if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
-                       new_ppcr--;
-               break;
-       case CPUFREQ_RELATION_H:
-               if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) &&
-                   (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min))
-                       new_ppcr--;
-               break;
-       }
-
-       freqs.old = cur;
-       freqs.new = sa11x0_ppcr_to_freq(new_ppcr);
+       unsigned int new_freq;
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+       new_freq = sa11x0_freq_table[ppcr].frequency;
 
-       if (freqs.new > cur)
-               sa1100_update_dram_timings(cur, freqs.new);
+       if (new_freq > cur)
+               sa1100_update_dram_timings(cur, new_freq);
 
-       PPCR = new_ppcr;
+       PPCR = ppcr;
 
-       if (freqs.new < cur)
-               sa1100_update_dram_timings(cur, freqs.new);
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+       if (new_freq < cur)
+               sa1100_update_dram_timings(cur, new_freq);
 
        return 0;
 }
 
 static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
 {
-       if (policy->cpu != 0)
-               return -EINVAL;
-       policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
-       policy->cpuinfo.min_freq = 59000;
-       policy->cpuinfo.max_freq = 287000;
-       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       return 0;
+       return cpufreq_generic_init(policy, sa11x0_freq_table, CPUFREQ_ETERNAL);
 }
 
 static struct cpufreq_driver sa1100_driver __refdata = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = sa11x0_verify_speed,
-       .target         = sa1100_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = sa1100_target,
        .get            = sa11x0_getspeed,
        .init           = sa1100_cpu_init,
        .name           = "sa1100",
index 39c90b6f42865eb8f8950ce0f7d7ce84d463a9ee..2c2b2e601d132f0f40e86c1c37a47a1f82fd5544 100644 (file)
@@ -229,36 +229,14 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
 /*
  * Ok, set the CPU frequency.
  */
-static int sa1110_target(struct cpufreq_policy *policy,
-                        unsigned int target_freq,
-                        unsigned int relation)
+static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr)
 {
        struct sdram_params *sdram = &sdram_params;
-       struct cpufreq_freqs freqs;
        struct sdram_info sd;
        unsigned long flags;
-       unsigned int ppcr, unused;
-
-       switch (relation) {
-       case CPUFREQ_RELATION_L:
-               ppcr = sa11x0_freq_to_ppcr(target_freq);
-               if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
-                       ppcr--;
-               break;
-       case CPUFREQ_RELATION_H:
-               ppcr = sa11x0_freq_to_ppcr(target_freq);
-               if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) &&
-                   (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min))
-                       ppcr--;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       freqs.old = sa11x0_getspeed(0);
-       freqs.new = sa11x0_ppcr_to_freq(ppcr);
+       unsigned int unused;
 
-       sdram_calculate_timing(&sd, freqs.new, sdram);
+       sdram_calculate_timing(&sd, sa11x0_freq_table[ppcr].frequency, sdram);
 
 #if 0
        /*
@@ -277,8 +255,6 @@ static int sa1110_target(struct cpufreq_policy *policy,
        sd.mdcas[2] = 0xaaaaaaaa;
 #endif
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        /*
         * The clock could be going away for some time.  Set the SDRAMs
         * to refresh rapidly (every 64 memory clock cycles).  To get
@@ -323,30 +299,22 @@ static int sa1110_target(struct cpufreq_policy *policy,
        /*
         * Now, return the SDRAM refresh back to normal.
         */
-       sdram_update_refresh(freqs.new, sdram);
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+       sdram_update_refresh(sa11x0_freq_table[ppcr].frequency, sdram);
 
        return 0;
 }
 
 static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
 {
-       if (policy->cpu != 0)
-               return -EINVAL;
-       policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
-       policy->cpuinfo.min_freq = 59000;
-       policy->cpuinfo.max_freq = 287000;
-       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       return 0;
+       return cpufreq_generic_init(policy, sa11x0_freq_table, CPUFREQ_ETERNAL);
 }
 
 /* sa1110_driver needs __refdata because it must remain after init registers
  * it with cpufreq_register_driver() */
 static struct cpufreq_driver sa1110_driver __refdata = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = sa11x0_verify_speed,
-       .target         = sa1110_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = sa1110_target,
        .get            = sa11x0_getspeed,
        .init           = sa1110_cpu_init,
        .name           = "sa1110",
index d6f6c6f4efa76ac6f82a97ddeff3292a06cfd18c..6adb354e359cc5fef14b1844592abc905117b486 100644 (file)
@@ -53,21 +53,11 @@ static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu)
        }
 }
 
-static void sc520_freq_set_cpu_state(struct cpufreq_policy *policy,
-               unsigned int state)
+static int sc520_freq_target(struct cpufreq_policy *policy, unsigned int state)
 {
 
-       struct cpufreq_freqs    freqs;
        u8 clockspeed_reg;
 
-       freqs.old = sc520_freq_get_cpu_frequency(0);
-       freqs.new = sc520_freq_table[state].frequency;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
-       pr_debug("attempting to set frequency to %i kHz\n",
-                       sc520_freq_table[state].frequency);
-
        local_irq_disable();
 
        clockspeed_reg = *cpuctl & ~0x03;
@@ -75,30 +65,9 @@ static void sc520_freq_set_cpu_state(struct cpufreq_policy *policy,
 
        local_irq_enable();
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-};
-
-static int sc520_freq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]);
-}
-
-static int sc520_freq_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq,
-                           unsigned int relation)
-{
-       unsigned int newstate = 0;
-
-       if (cpufreq_frequency_table_target(policy, sc520_freq_table,
-                               target_freq, relation, &newstate))
-               return -EINVAL;
-
-       sc520_freq_set_cpu_state(policy, newstate);
-
        return 0;
 }
 
-
 /*
  *     Module init and exit code
  */
@@ -106,7 +75,6 @@ static int sc520_freq_target(struct cpufreq_policy *policy,
 static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
-       int result;
 
        /* capability check */
        if (c->x86_vendor != X86_VENDOR_AMD ||
@@ -115,39 +83,19 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.transition_latency = 1000000; /* 1ms */
-       policy->cur = sc520_freq_get_cpu_frequency(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu);
-
-       return 0;
-}
 
-
-static int sc520_freq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_table_validate_and_show(policy, sc520_freq_table);
 }
 
 
-static struct freq_attr *sc520_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-
 static struct cpufreq_driver sc520_freq_driver = {
        .get    = sc520_freq_get_cpu_frequency,
-       .verify = sc520_freq_verify,
-       .target = sc520_freq_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = sc520_freq_target,
        .init   = sc520_freq_cpu_init,
-       .exit   = sc520_freq_cpu_exit,
+       .exit   = cpufreq_generic_exit,
        .name   = "sc520_freq",
-       .attr   = sc520_freq_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id sc520_ids[] = {
index ffc6d24b0cfbed764db6b6c8e2015330e6fb9fbd..387af12503a64e43f15d8fd0fa1d6e108a741f62 100644 (file)
@@ -87,15 +87,12 @@ static int sh_cpufreq_verify(struct cpufreq_policy *policy)
        if (freq_table)
                return cpufreq_frequency_table_verify(policy, freq_table);
 
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
 
        policy->min = (clk_round_rate(cpuclk, 1) + 500) / 1000;
        policy->max = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
 
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
-
+       cpufreq_verify_within_cpu_limits(policy);
        return 0;
 }
 
@@ -114,15 +111,13 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
                return PTR_ERR(cpuclk);
        }
 
-       policy->cur = sh_cpufreq_get(cpu);
-
        freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL;
        if (freq_table) {
                int result;
 
-               result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-               if (!result)
-                       cpufreq_frequency_table_get_attr(freq_table, cpu);
+               result = cpufreq_table_validate_and_show(policy, freq_table);
+               if (result)
+                       return result;
        } else {
                dev_notice(dev, "no frequency table found, falling back "
                           "to rate rounding.\n");
@@ -154,11 +149,6 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-static struct freq_attr *sh_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver sh_cpufreq_driver = {
        .name           = "sh",
        .get            = sh_cpufreq_get,
@@ -166,7 +156,7 @@ static struct cpufreq_driver sh_cpufreq_driver = {
        .verify         = sh_cpufreq_verify,
        .init           = sh_cpufreq_cpu_init,
        .exit           = sh_cpufreq_cpu_exit,
-       .attr           = sh_freq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init sh_cpufreq_module_init(void)
index cf5bc2ca16fa11f4155d757c6d5219b6691a6b81..62aa23e219d4a993da1233cdaa23e1f85ee94f21 100644 (file)
@@ -245,14 +245,12 @@ static unsigned int us2e_freq_get(unsigned int cpu)
        return clock_tick / estar_to_divisor(estar);
 }
 
-static void us2e_set_cpu_divider_index(struct cpufreq_policy *policy,
-               unsigned int index)
+static int us2e_freq_target(struct cpufreq_policy *policy, unsigned int index)
 {
        unsigned int cpu = policy->cpu;
        unsigned long new_bits, new_freq;
        unsigned long clock_tick, divisor, old_divisor, estar;
        cpumask_t cpus_allowed;
-       struct cpufreq_freqs freqs;
 
        cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
        set_cpus_allowed_ptr(current, cpumask_of(cpu));
@@ -266,41 +264,15 @@ static void us2e_set_cpu_divider_index(struct cpufreq_policy *policy,
 
        old_divisor = estar_to_divisor(estar);
 
-       freqs.old = clock_tick / old_divisor;
-       freqs.new = new_freq;
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        if (old_divisor != divisor)
                us2e_transition(estar, new_bits, clock_tick * 1000,
                                old_divisor, divisor);
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
        set_cpus_allowed_ptr(current, &cpus_allowed);
-}
-
-static int us2e_freq_target(struct cpufreq_policy *policy,
-                         unsigned int target_freq,
-                         unsigned int relation)
-{
-       unsigned int new_index = 0;
-
-       if (cpufreq_frequency_table_target(policy,
-                                          &us2e_freq_table[policy->cpu].table[0],
-                                          target_freq, relation, &new_index))
-               return -EINVAL;
-
-       us2e_set_cpu_divider_index(policy, new_index);
 
        return 0;
 }
 
-static int us2e_freq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                                             &us2e_freq_table[policy->cpu].table[0]);
-}
-
 static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int cpu = policy->cpu;
@@ -324,13 +296,15 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
        policy->cpuinfo.transition_latency = 0;
        policy->cur = clock_tick;
 
-       return cpufreq_frequency_table_cpuinfo(policy, table);
+       return cpufreq_table_validate_and_show(policy, table);
 }
 
 static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
 {
-       if (cpufreq_us2e_driver)
-               us2e_set_cpu_divider_index(policy, 0);
+       if (cpufreq_us2e_driver) {
+               cpufreq_frequency_table_put_attr(policy->cpu);
+               us2e_freq_target(policy, 0);
+       }
 
        return 0;
 }
@@ -361,8 +335,8 @@ static int __init us2e_freq_init(void)
                        goto err_out;
 
                driver->init = us2e_freq_cpu_init;
-               driver->verify = us2e_freq_verify;
-               driver->target = us2e_freq_target;
+               driver->verify = cpufreq_generic_frequency_table_verify;
+               driver->target_index = us2e_freq_target;
                driver->get = us2e_freq_get;
                driver->exit = us2e_freq_cpu_exit;
                strcpy(driver->name, "UltraSPARC-IIe");
index ac76b489979d48cac1278525ab861f46b69f8c86..724ffbd7105d3611a0cb7112ba184a912954dc90 100644 (file)
@@ -93,13 +93,11 @@ static unsigned int us3_freq_get(unsigned int cpu)
        return ret;
 }
 
-static void us3_set_cpu_divider_index(struct cpufreq_policy *policy,
-               unsigned int index)
+static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index)
 {
        unsigned int cpu = policy->cpu;
        unsigned long new_bits, new_freq, reg;
        cpumask_t cpus_allowed;
-       struct cpufreq_freqs freqs;
 
        cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
        set_cpus_allowed_ptr(current, cpumask_of(cpu));
@@ -125,43 +123,15 @@ static void us3_set_cpu_divider_index(struct cpufreq_policy *policy,
 
        reg = read_safari_cfg();
 
-       freqs.old = get_current_freq(cpu, reg);
-       freqs.new = new_freq;
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        reg &= ~SAFARI_CFG_DIV_MASK;
        reg |= new_bits;
        write_safari_cfg(reg);
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
        set_cpus_allowed_ptr(current, &cpus_allowed);
-}
-
-static int us3_freq_target(struct cpufreq_policy *policy,
-                         unsigned int target_freq,
-                         unsigned int relation)
-{
-       unsigned int new_index = 0;
-
-       if (cpufreq_frequency_table_target(policy,
-                                          &us3_freq_table[policy->cpu].table[0],
-                                          target_freq,
-                                          relation,
-                                          &new_index))
-               return -EINVAL;
-
-       us3_set_cpu_divider_index(policy, new_index);
 
        return 0;
 }
 
-static int us3_freq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                                             &us3_freq_table[policy->cpu].table[0]);
-}
-
 static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int cpu = policy->cpu;
@@ -181,13 +151,15 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
        policy->cpuinfo.transition_latency = 0;
        policy->cur = clock_tick;
 
-       return cpufreq_frequency_table_cpuinfo(policy, table);
+       return cpufreq_table_validate_and_show(policy, table);
 }
 
 static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
 {
-       if (cpufreq_us3_driver)
-               us3_set_cpu_divider_index(policy, 0);
+       if (cpufreq_us3_driver) {
+               cpufreq_frequency_table_put_attr(policy->cpu);
+               us3_freq_target(policy, 0);
+       }
 
        return 0;
 }
@@ -222,8 +194,8 @@ static int __init us3_freq_init(void)
                        goto err_out;
 
                driver->init = us3_freq_cpu_init;
-               driver->verify = us3_freq_verify;
-               driver->target = us3_freq_target;
+               driver->verify = cpufreq_generic_frequency_table_verify;
+               driver->target_index = us3_freq_target;
                driver->get = us3_freq_get;
                driver->exit = us3_freq_cpu_exit;
                strcpy(driver->name, "UltraSPARC-III");
index 3f418166ce02b8fc57a664f3d870bfb8508f3018..d02ccd19c9c4f20e4b5a3cfdcf1035b0c15c97fd 100644 (file)
@@ -30,11 +30,6 @@ static struct {
        u32 cnt;
 } spear_cpufreq;
 
-static int spear_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, spear_cpufreq.freq_tbl);
-}
-
 static unsigned int spear_cpufreq_get(unsigned int cpu)
 {
        return clk_get_rate(spear_cpufreq.clk) / 1000;
@@ -110,20 +105,14 @@ static int spear1340_set_cpu_rate(struct clk *sys_pclk, unsigned long newfreq)
 }
 
 static int spear_cpufreq_target(struct cpufreq_policy *policy,
-               unsigned int target_freq, unsigned int relation)
+               unsigned int index)
 {
-       struct cpufreq_freqs freqs;
        long newfreq;
        struct clk *srcclk;
-       int index, ret, mult = 1;
-
-       if (cpufreq_frequency_table_target(policy, spear_cpufreq.freq_tbl,
-                               target_freq, relation, &index))
-               return -EINVAL;
-
-       freqs.old = spear_cpufreq_get(0);
+       int ret, mult = 1;
 
        newfreq = spear_cpufreq.freq_tbl[index].frequency * 1000;
+
        if (of_machine_is_compatible("st,spear1340")) {
                /*
                 * SPEAr1340 is special in the sense that due to the possibility
@@ -154,65 +143,32 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
                return newfreq;
        }
 
-       freqs.new = newfreq / 1000;
-       freqs.new /= mult;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
        if (mult == 2)
                ret = spear1340_set_cpu_rate(srcclk, newfreq);
        else
                ret = clk_set_rate(spear_cpufreq.clk, newfreq);
 
-       /* Get current rate after clk_set_rate, in case of failure */
-       if (ret) {
+       if (ret)
                pr_err("CPU Freq: cpu clk_set_rate failed: %d\n", ret);
-               freqs.new = clk_get_rate(spear_cpufreq.clk) / 1000;
-       }
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
        return ret;
 }
 
 static int spear_cpufreq_init(struct cpufreq_policy *policy)
 {
-       int ret;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, spear_cpufreq.freq_tbl);
-       if (ret) {
-               pr_err("cpufreq_frequency_table_cpuinfo() failed");
-               return ret;
-       }
-
-       cpufreq_frequency_table_get_attr(spear_cpufreq.freq_tbl, policy->cpu);
-       policy->cpuinfo.transition_latency = spear_cpufreq.transition_latency;
-       policy->cur = spear_cpufreq_get(0);
-
-       cpumask_setall(policy->cpus);
-
-       return 0;
-}
-
-static int spear_cpufreq_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_generic_init(policy, spear_cpufreq.freq_tbl,
+                       spear_cpufreq.transition_latency);
 }
 
-static struct freq_attr *spear_cpufreq_attr[] = {
-        &cpufreq_freq_attr_scaling_available_freqs,
-        NULL,
-};
-
 static struct cpufreq_driver spear_cpufreq_driver = {
        .name           = "cpufreq-spear",
        .flags          = CPUFREQ_STICKY,
-       .verify         = spear_cpufreq_verify,
-       .target         = spear_cpufreq_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = spear_cpufreq_target,
        .get            = spear_cpufreq_get,
        .init           = spear_cpufreq_init,
-       .exit           = spear_cpufreq_exit,
-       .attr           = spear_cpufreq_attr,
+       .exit           = cpufreq_generic_exit,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int spear_cpufreq_driver_init(void)
index f897d510584285bea376474ca6a3198eeef7d74f..4e1daca5ce3b900c21955dda15b62c11415f6bee 100644 (file)
@@ -343,9 +343,7 @@ static unsigned int get_cur_freq(unsigned int cpu)
 static int centrino_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);
-       unsigned freq;
        unsigned l, h;
-       int ret;
        int i;
 
        /* Only Intel makes Enhanced Speedstep-capable CPUs */
@@ -373,9 +371,8 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
                return -ENODEV;
        }
 
-       if (centrino_cpu_init_table(policy)) {
+       if (centrino_cpu_init_table(policy))
                return -ENODEV;
-       }
 
        /* Check to see if Enhanced SpeedStep is enabled, and try to
           enable it if not. */
@@ -395,22 +392,11 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
                }
        }
 
-       freq = get_cur_freq(policy->cpu);
        policy->cpuinfo.transition_latency = 10000;
                                                /* 10uS transition latency */
-       policy->cur = freq;
-
-       pr_debug("centrino_cpu_init: cur=%dkHz\n", policy->cur);
 
-       ret = cpufreq_frequency_table_cpuinfo(policy,
+       return cpufreq_table_validate_and_show(policy,
                per_cpu(centrino_model, policy->cpu)->op_points);
-       if (ret)
-               return (ret);
-
-       cpufreq_frequency_table_get_attr(
-               per_cpu(centrino_model, policy->cpu)->op_points, policy->cpu);
-
-       return 0;
 }
 
 static int centrino_cpu_exit(struct cpufreq_policy *policy)
@@ -427,37 +413,19 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-/**
- * centrino_verify - verifies a new CPUFreq policy
- * @policy: new policy
- *
- * Limit must be within this model's frequency range at least one
- * border included.
- */
-static int centrino_verify (struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                       per_cpu(centrino_model, policy->cpu)->op_points);
-}
-
 /**
  * centrino_setpolicy - set a new CPUFreq policy
  * @policy: new policy
- * @target_freq: the target frequency
- * @relation: how that frequency relates to achieved frequency
- *     (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
+ * @index: index of target frequency
  *
  * Sets a new CPUFreq policy.
  */
-static int centrino_target (struct cpufreq_policy *policy,
-                           unsigned int target_freq,
-                           unsigned int relation)
+static int centrino_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       unsigned int    newstate = 0;
        unsigned int    msr, oldmsr = 0, h = 0, cpu = policy->cpu;
-       struct cpufreq_freqs    freqs;
        int                     retval = 0;
-       unsigned int            j, first_cpu, tmp;
+       unsigned int            j, first_cpu;
+       struct cpufreq_frequency_table *op_points;
        cpumask_var_t covered_cpus;
 
        if (unlikely(!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL)))
@@ -468,16 +436,8 @@ static int centrino_target (struct cpufreq_policy *policy,
                goto out;
        }
 
-       if (unlikely(cpufreq_frequency_table_target(policy,
-                       per_cpu(centrino_model, cpu)->op_points,
-                       target_freq,
-                       relation,
-                       &newstate))) {
-               retval = -EINVAL;
-               goto out;
-       }
-
        first_cpu = 1;
+       op_points = &per_cpu(centrino_model, cpu)->op_points[index];
        for_each_cpu(j, policy->cpus) {
                int good_cpu;
 
@@ -501,7 +461,7 @@ static int centrino_target (struct cpufreq_policy *policy,
                        break;
                }
 
-               msr = per_cpu(centrino_model, cpu)->op_points[newstate].driver_data;
+               msr = op_points->driver_data;
 
                if (first_cpu) {
                        rdmsr_on_cpu(good_cpu, MSR_IA32_PERF_CTL, &oldmsr, &h);
@@ -512,15 +472,6 @@ static int centrino_target (struct cpufreq_policy *policy,
                                goto out;
                        }
 
-                       freqs.old = extract_clock(oldmsr, cpu, 0);
-                       freqs.new = extract_clock(msr, cpu, 0);
-
-                       pr_debug("target=%dkHz old=%d new=%d msr=%04x\n",
-                               target_freq, freqs.old, freqs.new, msr);
-
-                       cpufreq_notify_transition(policy, &freqs,
-                                       CPUFREQ_PRECHANGE);
-
                        first_cpu = 0;
                        /* all but 16 LSB are reserved, treat them with care */
                        oldmsr &= ~0xffff;
@@ -535,8 +486,6 @@ static int centrino_target (struct cpufreq_policy *policy,
                cpumask_set_cpu(j, covered_cpus);
        }
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
        if (unlikely(retval)) {
                /*
                 * We have failed halfway through the frequency change.
@@ -547,12 +496,6 @@ static int centrino_target (struct cpufreq_policy *policy,
 
                for_each_cpu(j, covered_cpus)
                        wrmsr_on_cpu(j, MSR_IA32_PERF_CTL, oldmsr, h);
-
-               tmp = freqs.new;
-               freqs.new = freqs.old;
-               freqs.old = tmp;
-               cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-               cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
        }
        retval = 0;
 
@@ -561,20 +504,15 @@ out:
        return retval;
 }
 
-static struct freq_attr* centrino_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver centrino_driver = {
        .name           = "centrino", /* should be speedstep-centrino,
                                         but there's a 16 char limit */
        .init           = centrino_cpu_init,
        .exit           = centrino_cpu_exit,
-       .verify         = centrino_verify,
-       .target         = centrino_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = centrino_target,
        .get            = get_cur_freq,
-       .attr           = centrino_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 /*
index 5355abb69afc972d88c9f509924d3e779fa0cdac..7639b2be2a90495ef68c1fca8db8363a1b0caf08 100644 (file)
@@ -251,56 +251,23 @@ static unsigned int speedstep_get(unsigned int cpu)
 /**
  * speedstep_target - set a new CPUFreq policy
  * @policy: new policy
- * @target_freq: the target frequency
- * @relation: how that frequency relates to achieved frequency
- *     (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
+ * @index: index of target frequency
  *
  * Sets a new CPUFreq policy.
  */
-static int speedstep_target(struct cpufreq_policy *policy,
-                            unsigned int target_freq,
-                            unsigned int relation)
+static int speedstep_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       unsigned int newstate = 0, policy_cpu;
-       struct cpufreq_freqs freqs;
-
-       if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0],
-                               target_freq, relation, &newstate))
-               return -EINVAL;
+       unsigned int policy_cpu;
 
        policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask);
-       freqs.old = speedstep_get(policy_cpu);
-       freqs.new = speedstep_freqs[newstate].frequency;
-
-       pr_debug("transiting from %u to %u kHz\n", freqs.old, freqs.new);
-
-       /* no transition necessary */
-       if (freqs.old == freqs.new)
-               return 0;
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
-       smp_call_function_single(policy_cpu, _speedstep_set_state, &newstate,
+       smp_call_function_single(policy_cpu, _speedstep_set_state, &index,
                                 true);
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
-
        return 0;
 }
 
 
-/**
- * speedstep_verify - verifies a new CPUFreq policy
- * @policy: new policy
- *
- * Limit must be within speedstep_low_freq and speedstep_high_freq, with
- * at least one border included.
- */
-static int speedstep_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
-}
-
 struct get_freqs {
        struct cpufreq_policy *policy;
        int ret;
@@ -320,8 +287,7 @@ static void get_freqs_on_cpu(void *_get_freqs)
 
 static int speedstep_cpu_init(struct cpufreq_policy *policy)
 {
-       int result;
-       unsigned int policy_cpu, speed;
+       unsigned int policy_cpu;
        struct get_freqs gf;
 
        /* only run on CPU to be set, or on its sibling */
@@ -336,49 +302,18 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
        if (gf.ret)
                return gf.ret;
 
-       /* get current speed setting */
-       speed = speedstep_get(policy_cpu);
-       if (!speed)
-               return -EIO;
-
-       pr_debug("currently at %s speed setting - %i MHz\n",
-               (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency)
-               ? "low" : "high",
-               (speed / 1000));
-
-       /* cpuinfo and default policy values */
-       policy->cur = speed;
-
-       result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
-
-       return 0;
+       return cpufreq_table_validate_and_show(policy, speedstep_freqs);
 }
 
 
-static int speedstep_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
-static struct freq_attr *speedstep_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-
 static struct cpufreq_driver speedstep_driver = {
        .name   = "speedstep-ich",
-       .verify = speedstep_verify,
-       .target = speedstep_target,
+       .verify = cpufreq_generic_frequency_table_verify,
+       .target_index = speedstep_target,
        .init   = speedstep_cpu_init,
-       .exit   = speedstep_cpu_exit,
+       .exit   = cpufreq_generic_exit,
        .get    = speedstep_get,
-       .attr   = speedstep_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id ss_smi_ids[] = {
index abfba4f731ebdc4212696732a765b56083bc8252..0f5326d6f79ffef866957b26acdd18bf866bd0a9 100644 (file)
@@ -235,52 +235,21 @@ static void speedstep_set_state(unsigned int state)
 /**
  * speedstep_target - set a new CPUFreq policy
  * @policy: new policy
- * @target_freq: new freq
- * @relation:
+ * @index: index of new freq
  *
  * Sets a new CPUFreq policy/freq.
  */
-static int speedstep_target(struct cpufreq_policy *policy,
-                       unsigned int target_freq, unsigned int relation)
+static int speedstep_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       unsigned int newstate = 0;
-       struct cpufreq_freqs freqs;
-
-       if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0],
-                               target_freq, relation, &newstate))
-               return -EINVAL;
-
-       freqs.old = speedstep_freqs[speedstep_get_state()].frequency;
-       freqs.new = speedstep_freqs[newstate].frequency;
-
-       if (freqs.old == freqs.new)
-               return 0;
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-       speedstep_set_state(newstate);
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+       speedstep_set_state(index);
 
        return 0;
 }
 
 
-/**
- * speedstep_verify - verifies a new CPUFreq policy
- * @policy: new policy
- *
- * Limit must be within speedstep_low_freq and speedstep_high_freq, with
- * at least one border included.
- */
-static int speedstep_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
-}
-
-
 static int speedstep_cpu_init(struct cpufreq_policy *policy)
 {
        int result;
-       unsigned int speed, state;
        unsigned int *low, *high;
 
        /* capability check */
@@ -316,32 +285,8 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
                        pr_debug("workaround worked.\n");
        }
 
-       /* get current speed setting */
-       state = speedstep_get_state();
-       speed = speedstep_freqs[state].frequency;
-
-       pr_debug("currently at %s speed setting - %i MHz\n",
-               (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency)
-               ? "low" : "high",
-               (speed / 1000));
-
-       /* cpuinfo and default policy values */
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       policy->cur = speed;
-
-       result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
-
-       return 0;
-}
-
-static int speedstep_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_table_validate_and_show(policy, speedstep_freqs);
 }
 
 static unsigned int speedstep_get(unsigned int cpu)
@@ -362,20 +307,15 @@ static int speedstep_resume(struct cpufreq_policy *policy)
        return result;
 }
 
-static struct freq_attr *speedstep_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver speedstep_driver = {
        .name           = "speedstep-smi",
-       .verify         = speedstep_verify,
-       .target         = speedstep_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = speedstep_target,
        .init           = speedstep_cpu_init,
-       .exit           = speedstep_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .get            = speedstep_get,
        .resume         = speedstep_resume,
-       .attr           = speedstep_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id ss_smi_ids[] = {
index a7b876fdc1d8a5b672346233d7f7b7ce0a7c962f..f42df7ec03c53a00838839861567de2e0d8060fa 100644 (file)
@@ -51,11 +51,6 @@ static unsigned long target_cpu_speed[NUM_CPUS];
 static DEFINE_MUTEX(tegra_cpu_lock);
 static bool is_suspended;
 
-static int tegra_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
 static unsigned int tegra_getspeed(unsigned int cpu)
 {
        unsigned long rate;
@@ -107,12 +102,8 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy,
                unsigned long rate)
 {
        int ret = 0;
-       struct cpufreq_freqs freqs;
 
-       freqs.old = tegra_getspeed(0);
-       freqs.new = rate;
-
-       if (freqs.old == freqs.new)
+       if (tegra_getspeed(0) == rate)
                return ret;
 
        /*
@@ -126,21 +117,10 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy,
        else
                clk_set_rate(emc_clk, 100000000);  /* emc 50Mhz */
 
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
-#ifdef CONFIG_CPU_FREQ_DEBUG
-       printk(KERN_DEBUG "cpufreq-tegra: transition: %u --> %u\n",
-              freqs.old, freqs.new);
-#endif
-
-       ret = tegra_cpu_clk_set_rate(freqs.new * 1000);
-       if (ret) {
-               pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n",
-                       freqs.new);
-               freqs.new = freqs.old;
-       }
-
-       cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+       ret = tegra_cpu_clk_set_rate(rate * 1000);
+       if (ret)
+               pr_err("cpu-tegra: Failed to set cpu frequency to %lu kHz\n",
+                       rate);
 
        return ret;
 }
@@ -155,11 +135,8 @@ static unsigned long tegra_cpu_highest_speed(void)
        return rate;
 }
 
-static int tegra_target(struct cpufreq_policy *policy,
-                      unsigned int target_freq,
-                      unsigned int relation)
+static int tegra_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       unsigned int idx;
        unsigned int freq;
        int ret = 0;
 
@@ -170,10 +147,7 @@ static int tegra_target(struct cpufreq_policy *policy,
                goto out;
        }
 
-       cpufreq_frequency_table_target(policy, freq_table, target_freq,
-               relation, &idx);
-
-       freq = freq_table[idx].frequency;
+       freq = freq_table[index].frequency;
 
        target_cpu_speed[policy->cpu] = freq;
 
@@ -209,21 +183,23 @@ static struct notifier_block tegra_cpu_pm_notifier = {
 
 static int tegra_cpu_init(struct cpufreq_policy *policy)
 {
+       int ret;
+
        if (policy->cpu >= NUM_CPUS)
                return -EINVAL;
 
        clk_prepare_enable(emc_clk);
        clk_prepare_enable(cpu_clk);
 
-       cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-       policy->cur = tegra_getspeed(policy->cpu);
-       target_cpu_speed[policy->cpu] = policy->cur;
+       target_cpu_speed[policy->cpu] = tegra_getspeed(policy->cpu);
 
        /* FIXME: what's the actual transition time? */
-       policy->cpuinfo.transition_latency = 300 * 1000;
-
-       cpumask_copy(policy->cpus, cpu_possible_mask);
+       ret = cpufreq_generic_init(policy, freq_table, 300 * 1000);
+       if (ret) {
+               clk_disable_unprepare(cpu_clk);
+               clk_disable_unprepare(emc_clk);
+               return ret;
+       }
 
        if (policy->cpu == 0)
                register_pm_notifier(&tegra_cpu_pm_notifier);
@@ -233,24 +209,20 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
 
 static int tegra_cpu_exit(struct cpufreq_policy *policy)
 {
-       cpufreq_frequency_table_cpuinfo(policy, freq_table);
+       cpufreq_frequency_table_put_attr(policy->cpu);
+       clk_disable_unprepare(cpu_clk);
        clk_disable_unprepare(emc_clk);
        return 0;
 }
 
-static struct freq_attr *tegra_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver tegra_cpufreq_driver = {
-       .verify         = tegra_verify_speed,
-       .target         = tegra_target,
+       .verify         = cpufreq_generic_frequency_table_verify,
+       .target_index   = tegra_target,
        .get            = tegra_getspeed,
        .init           = tegra_cpu_init,
        .exit           = tegra_cpu_exit,
        .name           = "tegra",
-       .attr           = tegra_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init tegra_cpufreq_init(void)
index b225f04d8ae5c55bcfee26f644812d3d1100cc04..653ae2955b555ad63607d84a4ebeb27be205e644 100644 (file)
@@ -29,9 +29,7 @@ static int ucv2_verify_speed(struct cpufreq_policy *policy)
        if (policy->cpu)
                return -EINVAL;
 
-       cpufreq_verify_within_limits(policy,
-                       policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
-
+       cpufreq_verify_within_cpu_limits(policy);
        return 0;
 }
 
@@ -68,7 +66,6 @@ static int __init ucv2_cpu_init(struct cpufreq_policy *policy)
 {
        if (policy->cpu != 0)
                return -EINVAL;
-       policy->cur = ucv2_getspeed(0);
        policy->min = policy->cpuinfo.min_freq = 250000;
        policy->max = policy->cpuinfo.max_freq = 1000000;
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
diff --git a/drivers/cpufreq/vexpress-spc-cpufreq.c b/drivers/cpufreq/vexpress-spc-cpufreq.c
new file mode 100644 (file)
index 0000000..7f7c9c0
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Versatile Express SPC CPUFreq Interface driver
+ *
+ * It provides necessary ops to arm_big_little cpufreq driver.
+ *
+ * Copyright (C) 2013 ARM Ltd.
+ * Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpufreq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/types.h>
+
+#include "arm_big_little.h"
+
+static int ve_spc_init_opp_table(struct device *cpu_dev)
+{
+       /*
+        * platform specific SPC code must initialise the opp table
+        * so just check if the OPP count is non-zero
+        */
+       return dev_pm_opp_get_opp_count(cpu_dev) <= 0;
+}
+
+static int ve_spc_get_transition_latency(struct device *cpu_dev)
+{
+       return 1000000; /* 1 ms */
+}
+
+static struct cpufreq_arm_bL_ops ve_spc_cpufreq_ops = {
+       .name   = "vexpress-spc",
+       .get_transition_latency = ve_spc_get_transition_latency,
+       .init_opp_table = ve_spc_init_opp_table,
+};
+
+static int ve_spc_cpufreq_probe(struct platform_device *pdev)
+{
+       return bL_cpufreq_register(&ve_spc_cpufreq_ops);
+}
+
+static int ve_spc_cpufreq_remove(struct platform_device *pdev)
+{
+       bL_cpufreq_unregister(&ve_spc_cpufreq_ops);
+       return 0;
+}
+
+static struct platform_driver ve_spc_cpufreq_platdrv = {
+       .driver = {
+               .name   = "vexpress-spc-cpufreq",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = ve_spc_cpufreq_probe,
+       .remove         = ve_spc_cpufreq_remove,
+};
+module_platform_driver(ve_spc_cpufreq_platdrv);
+
+MODULE_LICENSE("GPL");
index 8e366032230893dc35c0d03f55138a20e0a33f07..f23bd75426cdfcac5da246ef6f23adef0a15b0da 100644 (file)
@@ -2,6 +2,17 @@
 # ARM CPU Idle drivers
 #
 
+config ARM_BIG_LITTLE_CPUIDLE
+       bool "Support for ARM big.LITTLE processors"
+       depends on ARCH_VEXPRESS_TC2_PM
+       select ARM_CPU_SUSPEND
+       select CPU_IDLE_MULTIPLE_DRIVERS
+       help
+         Select this option to enable CPU idle driver for big.LITTLE based
+         ARM systems. Driver manages CPUs coordination through MCPM and
+         define different C-states for little and big cores through the
+         multiple CPU idle drivers infrastructure.
+
 config ARM_HIGHBANK_CPUIDLE
        bool "CPU Idle Driver for Calxeda processors"
        depends on ARCH_HIGHBANK
@@ -27,13 +38,9 @@ config ARM_U8500_CPUIDLE
        help
          Select this to enable cpuidle for ST-E u8500 processors
 
-config CPU_IDLE_BIG_LITTLE
-       bool "Support for ARM big.LITTLE processors"
-       depends on ARCH_VEXPRESS_TC2_PM
-       select ARM_CPU_SUSPEND
-       select CPU_IDLE_MULTIPLE_DRIVERS
+config ARM_AT91_CPUIDLE
+       bool "Cpu Idle Driver for the AT91 processors"
+       default y
+       depends on ARCH_AT91
        help
-         Select this option to enable CPU idle driver for big.LITTLE based
-         ARM systems. Driver manages CPUs coordination through MCPM and
-         define different C-states for little and big cores through the
-         multiple CPU idle drivers infrastructure.
+         Select this to enable cpuidle for AT91 processors
index cea5ef58876d8202521545008afb9026565fbe7e..527be28e5c1e4e785032a83027899fdf47103b21 100644 (file)
@@ -7,8 +7,9 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
 
 ##################################################################################
 # ARM SoC drivers
+obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE)   += cpuidle-big_little.o
 obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE)     += cpuidle-calxeda.o
 obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE)     += cpuidle-kirkwood.o
 obj-$(CONFIG_ARM_ZYNQ_CPUIDLE)         += cpuidle-zynq.o
 obj-$(CONFIG_ARM_U8500_CPUIDLE)         += cpuidle-ux500.o
-obj-$(CONFIG_CPU_IDLE_BIG_LITTLE)      += cpuidle-big_little.o
+obj-$(CONFIG_ARM_AT91_CPUIDLE)          += cpuidle-at91.o
index f8a86364c6b64b05489299074c4fb394964e6bc0..e952936418d0f4de89251c8fd64677c14e5a8889 100644 (file)
@@ -147,7 +147,7 @@ static cpumask_t cpuidle_coupled_poked;
  * has returned from this function, the barrier is immediately available for
  * reuse.
  *
- * The atomic variable must be initialized to 0 before any cpu calls
+ * The atomic variable must be initialized to 0 before any cpu calls
  * this function, will be reset to 0 before any cpu returns from this function.
  *
  * Must only be called from within a coupled idle state handler
diff --git a/drivers/cpuidle/cpuidle-at91.c b/drivers/cpuidle/cpuidle-at91.c
new file mode 100644 (file)
index 0000000..a077437
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * based on arch/arm/mach-kirkwood/cpuidle.c
+ *
+ * CPU idle support for AT91 SoC
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * The cpu idle uses wait-for-interrupt and RAM self refresh in order
+ * to implement two idle states -
+ * #1 wait-for-interrupt
+ * #2 wait-for-interrupt and RAM self refresh
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/cpuidle.h>
+#include <linux/io.h>
+#include <linux/export.h>
+#include <asm/proc-fns.h>
+#include <asm/cpuidle.h>
+
+#define AT91_MAX_STATES        2
+
+static void (*at91_standby)(void);
+
+/* Actual code that puts the SoC in different idle states */
+static int at91_enter_idle(struct cpuidle_device *dev,
+                       struct cpuidle_driver *drv,
+                              int index)
+{
+       at91_standby();
+       return index;
+}
+
+static struct cpuidle_driver at91_idle_driver = {
+       .name                   = "at91_idle",
+       .owner                  = THIS_MODULE,
+       .states[0]              = ARM_CPUIDLE_WFI_STATE,
+       .states[1]              = {
+               .enter                  = at91_enter_idle,
+               .exit_latency           = 10,
+               .target_residency       = 10000,
+               .flags                  = CPUIDLE_FLAG_TIME_VALID,
+               .name                   = "RAM_SR",
+               .desc                   = "WFI and DDR Self Refresh",
+       },
+       .state_count = AT91_MAX_STATES,
+};
+
+/* Initialize CPU idle by registering the idle states */
+static int at91_cpuidle_probe(struct platform_device *dev)
+{
+       at91_standby = (void *)(dev->dev.platform_data);
+       
+       return cpuidle_register(&at91_idle_driver, NULL);
+}
+
+static struct platform_driver at91_cpuidle_driver = {
+       .driver = {
+               .name = "cpuidle-at91",
+               .owner = THIS_MODULE,
+       },
+       .probe = at91_cpuidle_probe,
+};
+
+module_platform_driver(at91_cpuidle_driver);
index e0564652af35114f2d73227b68bf781758975629..5e35804b1a952393dd84b20aacaf96442eac4d62 100644 (file)
@@ -111,7 +111,7 @@ static struct cpuidle_driver ux500_idle_driver = {
        .state_count = 2,
 };
 
-static int __init dbx500_cpuidle_probe(struct platform_device *pdev)
+static int dbx500_cpuidle_probe(struct platform_device *pdev)
 {
        /* Configure wake up reasons */
        prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
index 38e03a18359156077e17d8f5b35671de47bf6d8e..aded759280282b08e7fb3e9025f130240b9f6074 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/init.h>
 #include <linux/cpu_pm.h>
 #include <linux/cpuidle.h>
-#include <linux/of.h>
+#include <linux/platform_device.h>
 #include <asm/proc-fns.h>
 #include <asm/cpuidle.h>
 
@@ -70,14 +70,19 @@ static struct cpuidle_driver zynq_idle_driver = {
 };
 
 /* Initialize CPU idle by registering the idle states */
-static int __init zynq_cpuidle_init(void)
+static int zynq_cpuidle_probe(struct platform_device *pdev)
 {
-       if (!of_machine_is_compatible("xlnx,zynq-7000"))
-               return -ENODEV;
-
        pr_info("Xilinx Zynq CpuIdle Driver started\n");
 
        return cpuidle_register(&zynq_idle_driver, NULL);
 }
 
-device_initcall(zynq_cpuidle_init);
+static struct platform_driver zynq_cpuidle_driver = {
+       .driver = {
+               .name = "cpuidle-zynq",
+               .owner = THIS_MODULE,
+       },
+       .probe = zynq_cpuidle_probe,
+};
+
+module_platform_driver(zynq_cpuidle_driver);
index d75040ddd2b3ba8e317dfc76f5367faa62340b8f..2a991e468f78190e1dfab933225d33cfef69d710 100644 (file)
@@ -118,11 +118,9 @@ int cpuidle_idle_call(void)
        struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
        struct cpuidle_driver *drv;
        int next_state, entered_state;
+       bool broadcast;
 
-       if (off)
-               return -ENODEV;
-
-       if (!initialized)
+       if (off || !initialized)
                return -ENODEV;
 
        /* check if the device is ready */
@@ -144,9 +142,10 @@ int cpuidle_idle_call(void)
 
        trace_cpu_idle_rcuidle(next_state, dev->cpu);
 
-       if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP)
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
-                                  &dev->cpu);
+       broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP);
+
+       if (broadcast)
+               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
 
        if (cpuidle_state_is_coupled(dev, drv, next_state))
                entered_state = cpuidle_enter_state_coupled(dev, drv,
@@ -154,9 +153,8 @@ int cpuidle_idle_call(void)
        else
                entered_state = cpuidle_enter_state(dev, drv, next_state);
 
-       if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP)
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
-                                  &dev->cpu);
+       if (broadcast)
+               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 
        trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
 
@@ -228,45 +226,6 @@ void cpuidle_resume(void)
        mutex_unlock(&cpuidle_lock);
 }
 
-#ifdef CONFIG_ARCH_HAS_CPU_RELAX
-static int poll_idle(struct cpuidle_device *dev,
-               struct cpuidle_driver *drv, int index)
-{
-       ktime_t t1, t2;
-       s64 diff;
-
-       t1 = ktime_get();
-       local_irq_enable();
-       while (!need_resched())
-               cpu_relax();
-
-       t2 = ktime_get();
-       diff = ktime_to_us(ktime_sub(t2, t1));
-       if (diff > INT_MAX)
-               diff = INT_MAX;
-
-       dev->last_residency = (int) diff;
-
-       return index;
-}
-
-static void poll_idle_init(struct cpuidle_driver *drv)
-{
-       struct cpuidle_state *state = &drv->states[0];
-
-       snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
-       snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
-       state->exit_latency = 0;
-       state->target_residency = 0;
-       state->power_usage = -1;
-       state->flags = 0;
-       state->enter = poll_idle;
-       state->disabled = false;
-}
-#else
-static void poll_idle_init(struct cpuidle_driver *drv) {}
-#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
-
 /**
  * cpuidle_enable_device - enables idle PM for a CPU
  * @dev: the CPU
@@ -296,8 +255,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
        if (!dev->state_count)
                dev->state_count = drv->state_count;
 
-       poll_idle_init(drv);
-
        ret = cpuidle_add_device_sysfs(dev);
        if (ret)
                return ret;
@@ -358,12 +315,10 @@ static void __cpuidle_unregister_device(struct cpuidle_device *dev)
        module_put(drv->owner);
 }
 
-static int __cpuidle_device_init(struct cpuidle_device *dev)
+static void __cpuidle_device_init(struct cpuidle_device *dev)
 {
        memset(dev->states_usage, 0, sizeof(dev->states_usage));
        dev->last_residency = 0;
-
-       return 0;
 }
 
 /**
@@ -385,13 +340,12 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
        list_add(&dev->device_list, &cpuidle_detected_devices);
 
        ret = cpuidle_coupled_register_device(dev);
-       if (ret) {
+       if (ret)
                __cpuidle_unregister_device(dev);
-               return ret;
-       }
+       else
+               dev->registered = 1;
 
-       dev->registered = 1;
-       return 0;
+       return ret;
 }
 
 /**
@@ -410,9 +364,7 @@ int cpuidle_register_device(struct cpuidle_device *dev)
        if (dev->registered)
                goto out_unlock;
 
-       ret = __cpuidle_device_init(dev);
-       if (ret)
-               goto out_unlock;
+       __cpuidle_device_init(dev);
 
        ret = __cpuidle_register_device(dev);
        if (ret)
@@ -516,7 +468,7 @@ int cpuidle_register(struct cpuidle_driver *drv,
 
 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
                /*
-                * On multiplatform for ARM, the coupled idle states could
+                * On multiplatform for ARM, the coupled idle states could be
                 * enabled in the kernel even if the cpuidle driver does not
                 * use it. Note, coupled_cpus is a struct copy.
                 */
index 6e11701f0fcaef8430e2e8544108df8e337ebbed..06dbe7c86199808aefdf3d9e6b447c0e0b697b1c 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/mutex.h>
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/cpuidle.h>
 #include <linux/cpumask.h>
 #include <linux/clockchips.h>
@@ -56,7 +57,7 @@ static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv)
 }
 
 /**
- * __cpuidle_set_driver - set per CPU driver variables the the given driver.
+ * __cpuidle_set_driver - set per CPU driver variables for the given driver.
  * @drv: a valid pointer to a struct cpuidle_driver
  *
  * For each CPU in the driver's cpumask, unset the registered driver per CPU
@@ -132,7 +133,7 @@ static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv)
  * cpuidle_setup_broadcast_timer - enable/disable the broadcast timer
  * @arg: a void pointer used to match the SMP cross call API
  *
- * @arg is used as a value of type 'long' with on of the two values:
+ * @arg is used as a value of type 'long' with one of the two values:
  * - CLOCK_EVT_NOTIFY_BROADCAST_ON
  * - CLOCK_EVT_NOTIFY_BROADCAST_OFF
  *
@@ -149,10 +150,8 @@ static void cpuidle_setup_broadcast_timer(void *arg)
 /**
  * __cpuidle_driver_init - initialize the driver's internal data
  * @drv: a valid pointer to a struct cpuidle_driver
- *
- * Returns 0 on success, a negative error code otherwise.
  */
-static int __cpuidle_driver_init(struct cpuidle_driver *drv)
+static void __cpuidle_driver_init(struct cpuidle_driver *drv)
 {
        int i;
 
@@ -169,20 +168,55 @@ static int __cpuidle_driver_init(struct cpuidle_driver *drv)
        /*
         * Look for the timer stop flag in the different states, so that we know
         * if the broadcast timer has to be set up.  The loop is in the reverse
-        * order, because usually on of the the deeper states has this flag set.
+        * order, because usually one of the deeper states have this flag set.
         */
        for (i = drv->state_count - 1; i >= 0 ; i--) {
+               if (drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP) {
+                       drv->bctimer = 1;
+                       break;
+               }
+       }
+}
 
-               if (!(drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP))
-                       continue;
+#ifdef CONFIG_ARCH_HAS_CPU_RELAX
+static int poll_idle(struct cpuidle_device *dev,
+               struct cpuidle_driver *drv, int index)
+{
+       ktime_t t1, t2;
+       s64 diff;
 
-               drv->bctimer = 1;
-               break;
-       }
+       t1 = ktime_get();
+       local_irq_enable();
+       while (!need_resched())
+               cpu_relax();
 
-       return 0;
+       t2 = ktime_get();
+       diff = ktime_to_us(ktime_sub(t2, t1));
+       if (diff > INT_MAX)
+               diff = INT_MAX;
+
+       dev->last_residency = (int) diff;
+
+       return index;
 }
 
+static void poll_idle_init(struct cpuidle_driver *drv)
+{
+       struct cpuidle_state *state = &drv->states[0];
+
+       snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
+       snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
+       state->exit_latency = 0;
+       state->target_residency = 0;
+       state->power_usage = -1;
+       state->flags = 0;
+       state->enter = poll_idle;
+       state->disabled = false;
+}
+#else
+static void poll_idle_init(struct cpuidle_driver *drv) {}
+#endif /* !CONFIG_ARCH_HAS_CPU_RELAX */
+
 /**
  * __cpuidle_register_driver: register the driver
  * @drv: a valid pointer to a struct cpuidle_driver
@@ -206,9 +240,7 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv)
        if (cpuidle_disabled())
                return -ENODEV;
 
-       ret = __cpuidle_driver_init(drv);
-       if (ret)
-               return ret;
+       __cpuidle_driver_init(drv);
 
        ret = __cpuidle_set_driver(drv);
        if (ret)
@@ -218,6 +250,8 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv)
                on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
                                 (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1);
 
+       poll_idle_init(drv);
+
        return 0;
 }
 
@@ -346,10 +380,11 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
  */
 void cpuidle_driver_unref(void)
 {
-       struct cpuidle_driver *drv = cpuidle_get_driver();
+       struct cpuidle_driver *drv;
 
        spin_lock(&cpuidle_driver_lock);
 
+       drv = cpuidle_get_driver();
        if (drv && !WARN_ON(drv->refcnt <= 0))
                drv->refcnt--;
 
index ea2f8e7aa24af2936e4b0766f70e36eac2941eea..ca89412f512243a64a05d765708f0e02a848a6be 100644 (file)
@@ -96,46 +96,3 @@ int cpuidle_register_governor(struct cpuidle_governor *gov)
 
        return ret;
 }
-
-/**
- * cpuidle_replace_governor - find a replacement governor
- * @exclude_rating: the rating that will be skipped while looking for
- * new governor.
- */
-static struct cpuidle_governor *cpuidle_replace_governor(int exclude_rating)
-{
-       struct cpuidle_governor *gov;
-       struct cpuidle_governor *ret_gov = NULL;
-       unsigned int max_rating = 0;
-
-       list_for_each_entry(gov, &cpuidle_governors, governor_list) {
-               if (gov->rating == exclude_rating)
-                       continue;
-               if (gov->rating > max_rating) {
-                       max_rating = gov->rating;
-                       ret_gov = gov;
-               }
-       }
-
-       return ret_gov;
-}
-
-/**
- * cpuidle_unregister_governor - unregisters a governor
- * @gov: the governor
- */
-void cpuidle_unregister_governor(struct cpuidle_governor *gov)
-{
-       if (!gov)
-               return;
-
-       mutex_lock(&cpuidle_lock);
-       if (gov == cpuidle_curr_governor) {
-               struct cpuidle_governor *new_gov;
-               new_gov = cpuidle_replace_governor(gov->rating);
-               cpuidle_switch_governor(new_gov);
-       }
-       list_del(&gov->governor_list);
-       mutex_unlock(&cpuidle_lock);
-}
-
index 8739cc05228ca97512a60b9cc3770097f3a044aa..e918b6d0caf7558025578be747b920003adb2698 100644 (file)
@@ -52,11 +52,12 @@ static ssize_t show_current_driver(struct device *dev,
                                   char *buf)
 {
        ssize_t ret;
-       struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
+       struct cpuidle_driver *drv;
 
        spin_lock(&cpuidle_driver_lock);
-       if (cpuidle_driver)
-               ret = sprintf(buf, "%s\n", cpuidle_driver->name);
+       drv = cpuidle_get_driver();
+       if (drv)
+               ret = sprintf(buf, "%s\n", drv->name);
        else
                ret = sprintf(buf, "none\n");
        spin_unlock(&cpuidle_driver_lock);
index c99c00d35d34f73d7ceca6cbf1e68b163fcc502a..a0b2f7e0eedb774fbfa3e8fc0e41b73f10cfefd0 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/devfreq.h>
 #include <linux/workqueue.h>
 #include <linux/platform_device.h>
@@ -902,13 +902,13 @@ static ssize_t available_frequencies_show(struct device *d,
 {
        struct devfreq *df = to_devfreq(d);
        struct device *dev = df->dev.parent;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        ssize_t count = 0;
        unsigned long freq = 0;
 
        rcu_read_lock();
        do {
-               opp = opp_find_freq_ceil(dev, &freq);
+               opp = dev_pm_opp_find_freq_ceil(dev, &freq);
                if (IS_ERR(opp))
                        break;
 
@@ -993,10 +993,10 @@ static int __init devfreq_init(void)
        }
 
        devfreq_wq = create_freezable_workqueue("devfreq_wq");
-       if (IS_ERR(devfreq_wq)) {
+       if (!devfreq_wq) {
                class_destroy(devfreq_class);
                pr_err("%s: couldn't create workqueue\n", __FILE__);
-               return PTR_ERR(devfreq_wq);
+               return -ENOMEM;
        }
        devfreq_class->dev_groups = devfreq_groups;
 
@@ -1029,25 +1029,26 @@ module_exit(devfreq_exit);
  * under the locked area. The pointer returned must be used prior to unlocking
  * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
-struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
-                                   u32 flags)
+struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
+                                          unsigned long *freq,
+                                          u32 flags)
 {
-       struct opp *opp;
+       struct dev_pm_opp *opp;
 
        if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
                /* The freq is an upper bound. opp should be lower */
-               opp = opp_find_freq_floor(dev, freq);
+               opp = dev_pm_opp_find_freq_floor(dev, freq);
 
                /* If not available, use the closest opp */
                if (opp == ERR_PTR(-ERANGE))
-                       opp = opp_find_freq_ceil(dev, freq);
+                       opp = dev_pm_opp_find_freq_ceil(dev, freq);
        } else {
                /* The freq is an lower bound. opp should be higher */
-               opp = opp_find_freq_ceil(dev, freq);
+               opp = dev_pm_opp_find_freq_ceil(dev, freq);
 
                /* If not available, use the closest opp */
                if (opp == ERR_PTR(-ERANGE))
-                       opp = opp_find_freq_floor(dev, freq);
+                       opp = dev_pm_opp_find_freq_floor(dev, freq);
        }
 
        return opp;
@@ -1066,7 +1067,7 @@ int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
        int ret = 0;
 
        rcu_read_lock();
-       nh = opp_get_notifier(dev);
+       nh = dev_pm_opp_get_notifier(dev);
        if (IS_ERR(nh))
                ret = PTR_ERR(nh);
        rcu_read_unlock();
@@ -1092,7 +1093,7 @@ int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
        int ret = 0;
 
        rcu_read_lock();
-       nh = opp_get_notifier(dev);
+       nh = dev_pm_opp_get_notifier(dev);
        if (IS_ERR(nh))
                ret = PTR_ERR(nh);
        rcu_read_unlock();
index c5f86d8caca34c6a7a3ea2341da5c242ddf41c83..cede6f71cd63feb5afebde508199b9be9a507778 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/suspend.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/devfreq.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
@@ -639,7 +639,7 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
        struct platform_device *pdev = container_of(dev, struct platform_device,
                                                    dev);
        struct busfreq_data *data = platform_get_drvdata(pdev);
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long freq;
        unsigned long old_freq = data->curr_oppinfo.rate;
        struct busfreq_opp_info new_oppinfo;
@@ -650,8 +650,8 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
                rcu_read_unlock();
                return PTR_ERR(opp);
        }
-       new_oppinfo.rate = opp_get_freq(opp);
-       new_oppinfo.volt = opp_get_voltage(opp);
+       new_oppinfo.rate = dev_pm_opp_get_freq(opp);
+       new_oppinfo.volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
        freq = new_oppinfo.rate;
 
@@ -873,7 +873,7 @@ static int exynos4210_init_tables(struct busfreq_data *data)
                exynos4210_busclk_table[i].volt = exynos4210_asv_volt[mgrp][i];
 
        for (i = LV_0; i < EX4210_LV_NUM; i++) {
-               err = opp_add(data->dev, exynos4210_busclk_table[i].clk,
+               err = dev_pm_opp_add(data->dev, exynos4210_busclk_table[i].clk,
                              exynos4210_busclk_table[i].volt);
                if (err) {
                        dev_err(data->dev, "Cannot add opp entries.\n");
@@ -940,7 +940,7 @@ static int exynos4x12_init_tables(struct busfreq_data *data)
        }
 
        for (i = 0; i < EX4x12_LV_NUM; i++) {
-               ret = opp_add(data->dev, exynos4x12_mifclk_table[i].clk,
+               ret = dev_pm_opp_add(data->dev, exynos4x12_mifclk_table[i].clk,
                              exynos4x12_mifclk_table[i].volt);
                if (ret) {
                        dev_err(data->dev, "Fail to add opp entries.\n");
@@ -956,7 +956,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
 {
        struct busfreq_data *data = container_of(this, struct busfreq_data,
                                                 pm_notifier);
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        struct busfreq_opp_info new_oppinfo;
        unsigned long maxfreq = ULONG_MAX;
        int err = 0;
@@ -969,7 +969,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
                data->disabled = true;
 
                rcu_read_lock();
-               opp = opp_find_freq_floor(data->dev, &maxfreq);
+               opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
                if (IS_ERR(opp)) {
                        rcu_read_unlock();
                        dev_err(data->dev, "%s: unable to find a min freq\n",
@@ -977,8 +977,8 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
                        mutex_unlock(&data->lock);
                        return PTR_ERR(opp);
                }
-               new_oppinfo.rate = opp_get_freq(opp);
-               new_oppinfo.volt = opp_get_voltage(opp);
+               new_oppinfo.rate = dev_pm_opp_get_freq(opp);
+               new_oppinfo.volt = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
 
                err = exynos4_bus_setvolt(data, &new_oppinfo,
@@ -1020,7 +1020,7 @@ unlock:
 static int exynos4_busfreq_probe(struct platform_device *pdev)
 {
        struct busfreq_data *data;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        struct device *dev = &pdev->dev;
        int err = 0;
 
@@ -1065,15 +1065,16 @@ static int exynos4_busfreq_probe(struct platform_device *pdev)
        }
 
        rcu_read_lock();
-       opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq);
+       opp = dev_pm_opp_find_freq_floor(dev,
+                                        &exynos4_devfreq_profile.initial_freq);
        if (IS_ERR(opp)) {
                rcu_read_unlock();
                dev_err(dev, "Invalid initial frequency %lu kHz.\n",
                        exynos4_devfreq_profile.initial_freq);
                return PTR_ERR(opp);
        }
-       data->curr_oppinfo.rate = opp_get_freq(opp);
-       data->curr_oppinfo.volt = opp_get_voltage(opp);
+       data->curr_oppinfo.rate = dev_pm_opp_get_freq(opp);
+       data->curr_oppinfo.volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
 
        platform_set_drvdata(pdev, data);
index 574b16b59be5df13352ebee4f952e592b9a6f52f..a60da3c1c48eef09dca3c2bb8322d429be1ab568 100644 (file)
 #include <linux/module.h>
 #include <linux/devfreq.h>
 #include <linux/io.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
-#include <linux/opp.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
@@ -132,7 +131,7 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
        struct platform_device *pdev = container_of(dev, struct platform_device,
                                                    dev);
        struct busfreq_data_int *data = platform_get_drvdata(pdev);
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long old_freq, freq;
        unsigned long volt;
 
@@ -144,8 +143,8 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
                return PTR_ERR(opp);
        }
 
-       freq = opp_get_freq(opp);
-       volt = opp_get_voltage(opp);
+       freq = dev_pm_opp_get_freq(opp);
+       volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
 
        old_freq = data->curr_freq;
@@ -246,7 +245,7 @@ static int exynos5250_init_int_tables(struct busfreq_data_int *data)
        int i, err = 0;
 
        for (i = LV_0; i < _LV_END; i++) {
-               err = opp_add(data->dev, exynos5_int_opp_table[i].clk,
+               err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk,
                                exynos5_int_opp_table[i].volt);
                if (err) {
                        dev_err(data->dev, "Cannot add opp entries.\n");
@@ -262,7 +261,7 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
 {
        struct busfreq_data_int *data = container_of(this,
                                        struct busfreq_data_int, pm_notifier);
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long maxfreq = ULONG_MAX;
        unsigned long freq;
        unsigned long volt;
@@ -276,14 +275,14 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
                data->disabled = true;
 
                rcu_read_lock();
-               opp = opp_find_freq_floor(data->dev, &maxfreq);
+               opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
                if (IS_ERR(opp)) {
                        rcu_read_unlock();
                        err = PTR_ERR(opp);
                        goto unlock;
                }
-               freq = opp_get_freq(opp);
-               volt = opp_get_voltage(opp);
+               freq = dev_pm_opp_get_freq(opp);
+               volt = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
 
                err = exynos5_int_setvolt(data, volt);
@@ -316,7 +315,7 @@ unlock:
 static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 {
        struct busfreq_data_int *data;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        struct device *dev = &pdev->dev;
        struct device_node *np;
        unsigned long initial_freq;
@@ -351,46 +350,43 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 
        err = exynos5250_init_int_tables(data);
        if (err)
-               goto err_regulator;
+               return err;
 
-       data->vdd_int = regulator_get(dev, "vdd_int");
+       data->vdd_int = devm_regulator_get(dev, "vdd_int");
        if (IS_ERR(data->vdd_int)) {
                dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
-               err = PTR_ERR(data->vdd_int);
-               goto err_regulator;
+               return PTR_ERR(data->vdd_int);
        }
 
-       data->int_clk = clk_get(dev, "int_clk");
+       data->int_clk = devm_clk_get(dev, "int_clk");
        if (IS_ERR(data->int_clk)) {
                dev_err(dev, "Cannot get clock \"int_clk\"\n");
-               err = PTR_ERR(data->int_clk);
-               goto err_clock;
+               return PTR_ERR(data->int_clk);
        }
 
        rcu_read_lock();
-       opp = opp_find_freq_floor(dev,
+       opp = dev_pm_opp_find_freq_floor(dev,
                        &exynos5_devfreq_int_profile.initial_freq);
        if (IS_ERR(opp)) {
                rcu_read_unlock();
                dev_err(dev, "Invalid initial frequency %lu kHz.\n",
                       exynos5_devfreq_int_profile.initial_freq);
-               err = PTR_ERR(opp);
-               goto err_opp_add;
+               return PTR_ERR(opp);
        }
-       initial_freq = opp_get_freq(opp);
-       initial_volt = opp_get_voltage(opp);
+       initial_freq = dev_pm_opp_get_freq(opp);
+       initial_volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
        data->curr_freq = initial_freq;
 
        err = clk_set_rate(data->int_clk, initial_freq * 1000);
        if (err) {
                dev_err(dev, "Failed to set initial frequency\n");
-               goto err_opp_add;
+               return err;
        }
 
        err = exynos5_int_setvolt(data, initial_volt);
        if (err)
-               goto err_opp_add;
+               return err;
 
        platform_set_drvdata(pdev, data);
 
@@ -419,12 +415,6 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 
 err_devfreq_add:
        devfreq_remove_device(data->devfreq);
-       platform_set_drvdata(pdev, NULL);
-err_opp_add:
-       clk_put(data->int_clk);
-err_clock:
-       regulator_put(data->vdd_int);
-err_regulator:
        return err;
 }
 
@@ -435,9 +425,6 @@ static int exynos5_busfreq_int_remove(struct platform_device *pdev)
        pm_qos_remove_request(&data->int_req);
        unregister_pm_notifier(&data->pm_notifier);
        devfreq_remove_device(data->devfreq);
-       regulator_put(data->vdd_int);
-       clk_put(data->int_clk);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
@@ -479,7 +466,7 @@ static int __init exynos5_busfreq_int_init(void)
 
        exynos5_devfreq_pdev =
                platform_device_register_simple("exynos5-bus-int", -1, NULL, 0);
-       if (IS_ERR_OR_NULL(exynos5_devfreq_pdev)) {
+       if (IS_ERR(exynos5_devfreq_pdev)) {
                ret = PTR_ERR(exynos5_devfreq_pdev);
                goto out1;
        }
index 3519111c566b8a3bc9a43b8b89bc2b866c3d833e..10b577fcf48d82dfd70f6c120d379eaa2f24e2aa 100644 (file)
@@ -305,6 +305,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
                                edma_alloc_slot(EDMA_CTLR(echan->ch_num),
                                                EDMA_SLOT_ANY);
                        if (echan->slot[i] < 0) {
+                               kfree(edesc);
                                dev_err(dev, "Failed to allocate slot\n");
                                kfree(edesc);
                                return NULL;
@@ -346,6 +347,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
                        ccnt = sg_dma_len(sg) / (acnt * bcnt);
                        if (ccnt > (SZ_64K - 1)) {
                                dev_err(dev, "Exceeded max SG segment size\n");
+                               kfree(edesc);
                                return NULL;
                        }
                        cidx = acnt * bcnt;
index 2d9ca6055e5e0bde239247fabe41c960d4dd3020..41b5913ddabe6e0a8b1f417004d86628234b77c5 100644 (file)
@@ -248,14 +248,15 @@ static void lp_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
        struct lp_gpio *lg = irq_data_get_irq_handler_data(data);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
        u32 base, pin, mask;
-       unsigned long reg, pending;
+       unsigned long reg, ena, pending;
        unsigned virq;
 
        /* check from GPIO controller which pin triggered the interrupt */
        for (base = 0; base < lg->chip.ngpio; base += 32) {
                reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
+               ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE);
 
-               while ((pending = inl(reg))) {
+               while ((pending = (inl(reg) & inl(ena)))) {
                        pin = __ffs(pending);
                        mask = BIT(pin);
                        /* Clear before handling so we don't lose an edge */
index 5c1ef2b3ef188253e0031b0ceec2e65239220df5..f2beb728ed8f32cf8eeb1b6135fcf652796ab294 100644 (file)
@@ -73,15 +73,8 @@ static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
 static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data)
 {
        struct acpi_gpio_evt_pin *evt_pin = data;
-       struct acpi_object_list args;
-       union acpi_object arg;
 
-       arg.type = ACPI_TYPE_INTEGER;
-       arg.integer.value = evt_pin->pin;
-       args.count = 1;
-       args.pointer = &arg;
-
-       acpi_evaluate_object(evt_pin->evt_handle, NULL, &args, NULL);
+       acpi_execute_simple_method(evt_pin->evt_handle, NULL, evt_pin->pin);
 
        return IRQ_HANDLED;
 }
index 86ef3461ec0647b42f1e1ff94a9f47225151f7f6..0dee0e0c247ae5fa2f121df234d09979dc00df74 100644 (file)
@@ -136,7 +136,7 @@ static struct gpio_desc *gpio_to_desc(unsigned gpio)
  */
 static int desc_to_gpio(const struct gpio_desc *desc)
 {
-       return desc->chip->base + gpio_chip_hwgpio(desc);
+       return desc - &gpio_desc[0];
 }
 
 
@@ -1398,7 +1398,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
        int                     status = -EPROBE_DEFER;
        unsigned long           flags;
 
-       if (!desc || !desc->chip) {
+       if (!desc) {
                pr_warn("%s: invalid GPIO\n", __func__);
                return -EINVAL;
        }
@@ -1406,6 +1406,8 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
        spin_lock_irqsave(&gpio_lock, flags);
 
        chip = desc->chip;
+       if (chip == NULL)
+               goto done;
 
        if (!try_module_get(chip->owner))
                goto done;
index e572dd20bdee037fed5cdce356191ea84fd41e09..05ad9ba0a67e8ab4c9e79aade5b8ead441b7f3a8 100644 (file)
@@ -402,9 +402,16 @@ long drm_ioctl(struct file *filp,
                cmd = ioctl->cmd_drv;
        }
        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;
 
index 69d8ed5416c31b2e80538fabec553e333fd741ea..2ad27880cd047bc93cf119784895040eeafc3bae 100644 (file)
@@ -505,6 +505,8 @@ static int i915_drm_freeze(struct drm_device *dev)
                intel_modeset_suspend_hw(dev);
        }
 
+       i915_gem_suspend_gtt_mappings(dev);
+
        i915_save_state(dev);
 
        intel_opregion_fini(dev);
@@ -648,7 +650,8 @@ static int i915_drm_thaw(struct drm_device *dev)
                mutex_lock(&dev->struct_mutex);
                i915_gem_restore_gtt_mappings(dev);
                mutex_unlock(&dev->struct_mutex);
-       }
+       } else if (drm_core_check_feature(dev, DRIVER_MODESET))
+               i915_check_and_clear_faults(dev);
 
        __i915_drm_thaw(dev);
 
index 35874b3a86dcc917c9bb68e1cb4879d81a0fc76b..ab0f2c0a440c6a4543a59d81282c4ab21316b2cc 100644 (file)
@@ -497,10 +497,12 @@ struct i915_address_space {
 
        /* FIXME: Need a more generic return type */
        gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
-                                    enum i915_cache_level level);
+                                    enum i915_cache_level level,
+                                    bool valid); /* Create a valid PTE */
        void (*clear_range)(struct i915_address_space *vm,
                            unsigned int first_entry,
-                           unsigned int num_entries);
+                           unsigned int num_entries,
+                           bool use_scratch);
        void (*insert_entries)(struct i915_address_space *vm,
                               struct sg_table *st,
                               unsigned int first_entry,
@@ -2065,6 +2067,8 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
 void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
                              struct drm_i915_gem_object *obj);
 
+void i915_check_and_clear_faults(struct drm_device *dev);
+void i915_gem_suspend_gtt_mappings(struct drm_device *dev);
 void i915_gem_restore_gtt_mappings(struct drm_device *dev);
 int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
 void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
index 212f6d8c35ec6593cc54957ecd24445196d26657..1f7b4caefb6e0776bf61d78af519812765b37741 100644 (file)
 #define HSW_WT_ELLC_LLC_AGE0           HSW_CACHEABILITY_CONTROL(0x6)
 
 static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
-                                    enum i915_cache_level level)
+                                    enum i915_cache_level level,
+                                    bool valid)
 {
-       gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+       gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
        pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
        switch (level) {
@@ -79,9 +80,10 @@ static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
 }
 
 static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
-                                    enum i915_cache_level level)
+                                    enum i915_cache_level level,
+                                    bool valid)
 {
-       gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+       gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
        pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
        switch (level) {
@@ -105,9 +107,10 @@ static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
 #define BYT_PTE_SNOOPED_BY_CPU_CACHES  (1 << 2)
 
 static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
-                                    enum i915_cache_level level)
+                                    enum i915_cache_level level,
+                                    bool valid)
 {
-       gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+       gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
        pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
        /* Mark the page as writeable.  Other platforms don't have a
@@ -122,9 +125,10 @@ static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
 }
 
 static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
-                                    enum i915_cache_level level)
+                                    enum i915_cache_level level,
+                                    bool valid)
 {
-       gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+       gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
        pte |= HSW_PTE_ADDR_ENCODE(addr);
 
        if (level != I915_CACHE_NONE)
@@ -134,9 +138,10 @@ static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
 }
 
 static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
-                                     enum i915_cache_level level)
+                                     enum i915_cache_level level,
+                                     bool valid)
 {
-       gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+       gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
        pte |= HSW_PTE_ADDR_ENCODE(addr);
 
        switch (level) {
@@ -236,7 +241,8 @@ static int gen6_ppgtt_enable(struct drm_device *dev)
 /* PPGTT support for Sandybdrige/Gen6 and later */
 static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
                                   unsigned first_entry,
-                                  unsigned num_entries)
+                                  unsigned num_entries,
+                                  bool use_scratch)
 {
        struct i915_hw_ppgtt *ppgtt =
                container_of(vm, struct i915_hw_ppgtt, base);
@@ -245,7 +251,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
        unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
        unsigned last_pte, i;
 
-       scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC);
+       scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true);
 
        while (num_entries) {
                last_pte = first_pte + num_entries;
@@ -282,7 +288,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
                dma_addr_t page_addr;
 
                page_addr = sg_page_iter_dma_address(&sg_iter);
-               pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level);
+               pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level, true);
                if (++act_pte == I915_PPGTT_PT_ENTRIES) {
                        kunmap_atomic(pt_vaddr);
                        act_pt++;
@@ -367,7 +373,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
        }
 
        ppgtt->base.clear_range(&ppgtt->base, 0,
-                               ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES);
+                               ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES, true);
 
        ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t);
 
@@ -444,7 +450,8 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
 {
        ppgtt->base.clear_range(&ppgtt->base,
                                i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT,
-                               obj->base.size >> PAGE_SHIFT);
+                               obj->base.size >> PAGE_SHIFT,
+                               true);
 }
 
 extern int intel_iommu_gfx_mapped;
@@ -485,15 +492,65 @@ static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
                dev_priv->mm.interruptible = interruptible;
 }
 
+void i915_check_and_clear_faults(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_ring_buffer *ring;
+       int i;
+
+       if (INTEL_INFO(dev)->gen < 6)
+               return;
+
+       for_each_ring(ring, dev_priv, i) {
+               u32 fault_reg;
+               fault_reg = I915_READ(RING_FAULT_REG(ring));
+               if (fault_reg & RING_FAULT_VALID) {
+                       DRM_DEBUG_DRIVER("Unexpected fault\n"
+                                        "\tAddr: 0x%08lx\\n"
+                                        "\tAddress space: %s\n"
+                                        "\tSource ID: %d\n"
+                                        "\tType: %d\n",
+                                        fault_reg & PAGE_MASK,
+                                        fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT",
+                                        RING_FAULT_SRCID(fault_reg),
+                                        RING_FAULT_FAULT_TYPE(fault_reg));
+                       I915_WRITE(RING_FAULT_REG(ring),
+                                  fault_reg & ~RING_FAULT_VALID);
+               }
+       }
+       POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS]));
+}
+
+void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       /* Don't bother messing with faults pre GEN6 as we have little
+        * documentation supporting that it's a good idea.
+        */
+       if (INTEL_INFO(dev)->gen < 6)
+               return;
+
+       i915_check_and_clear_faults(dev);
+
+       dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
+                                      dev_priv->gtt.base.start / PAGE_SIZE,
+                                      dev_priv->gtt.base.total / PAGE_SIZE,
+                                      false);
+}
+
 void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj;
 
+       i915_check_and_clear_faults(dev);
+
        /* First fill our portion of the GTT with scratch pages */
        dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
                                       dev_priv->gtt.base.start / PAGE_SIZE,
-                                      dev_priv->gtt.base.total / PAGE_SIZE);
+                                      dev_priv->gtt.base.total / PAGE_SIZE,
+                                      true);
 
        list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
                i915_gem_clflush_object(obj, obj->pin_display);
@@ -536,7 +593,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
 
        for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
                addr = sg_page_iter_dma_address(&sg_iter);
-               iowrite32(vm->pte_encode(addr, level), &gtt_entries[i]);
+               iowrite32(vm->pte_encode(addr, level, true), &gtt_entries[i]);
                i++;
        }
 
@@ -548,7 +605,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
         */
        if (i != 0)
                WARN_ON(readl(&gtt_entries[i-1]) !=
-                       vm->pte_encode(addr, level));
+                       vm->pte_encode(addr, level, true));
 
        /* This next bit makes the above posting read even more important. We
         * want to flush the TLBs only after we're certain all the PTE updates
@@ -560,7 +617,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
 
 static void gen6_ggtt_clear_range(struct i915_address_space *vm,
                                  unsigned int first_entry,
-                                 unsigned int num_entries)
+                                 unsigned int num_entries,
+                                 bool use_scratch)
 {
        struct drm_i915_private *dev_priv = vm->dev->dev_private;
        gen6_gtt_pte_t scratch_pte, __iomem *gtt_base =
@@ -573,7 +631,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
                 first_entry, num_entries, max_entries))
                num_entries = max_entries;
 
-       scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC);
+       scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch);
+
        for (i = 0; i < num_entries; i++)
                iowrite32(scratch_pte, &gtt_base[i]);
        readl(gtt_base);
@@ -594,7 +653,8 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm,
 
 static void i915_ggtt_clear_range(struct i915_address_space *vm,
                                  unsigned int first_entry,
-                                 unsigned int num_entries)
+                                 unsigned int num_entries,
+                                 bool unused)
 {
        intel_gtt_clear_range(first_entry, num_entries);
 }
@@ -622,7 +682,8 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
 
        dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
                                       entry,
-                                      obj->base.size >> PAGE_SHIFT);
+                                      obj->base.size >> PAGE_SHIFT,
+                                      true);
 
        obj->has_global_gtt_mapping = 0;
 }
@@ -709,11 +770,11 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
                const unsigned long count = (hole_end - hole_start) / PAGE_SIZE;
                DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
                              hole_start, hole_end);
-               ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count);
+               ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count, true);
        }
 
        /* And finally clear the reserved guard page */
-       ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1);
+       ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1, true);
 }
 
 static bool
index 38f96f65d87ad5d182cf38eff2a14b65a35067b6..ef9b35479f0136d0cb23ec7f6eb2bb59afa85e46 100644 (file)
 #define   ARB_MODE_SWIZZLE_IVB (1<<5)
 #define RENDER_HWS_PGA_GEN7    (0x04080)
 #define RING_FAULT_REG(ring)   (0x4094 + 0x100*(ring)->id)
+#define   RING_FAULT_GTTSEL_MASK (1<<11)
+#define   RING_FAULT_SRCID(x)  ((x >> 3) & 0xff)
+#define   RING_FAULT_FAULT_TYPE(x) ((x >> 1) & 0x3)
+#define   RING_FAULT_VALID     (1<<0)
 #define DONE_REG               0x40b0
 #define BSD_HWS_PGA_GEN7       (0x04180)
 #define BLT_HWS_PGA_GEN7       (0x04280)
 #define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN)
 
 #define SOUTH_DSPCLK_GATE_D    0xc2020
+#define  PCH_DPLUNIT_CLOCK_GATE_DISABLE (1<<30)
 #define  PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29)
+#define  PCH_CPUNIT_CLOCK_GATE_DISABLE (1<<14)
 #define  PCH_LP_PARTITION_LEVEL_DISABLE  (1<<12)
 
 /* CPU: FDI_TX */
index 57fe1ae32a0d69d767eb7d698cfeab2ead4231e2..43959edd4291193a538449c1d4f75bba8d30ea8a 100644 (file)
@@ -193,16 +193,14 @@ out:
 
 static bool intel_dsm_pci_probe(struct pci_dev *pdev)
 {
-       acpi_handle dhandle, intel_handle;
-       acpi_status status;
+       acpi_handle dhandle;
        int ret;
 
        dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
        if (!dhandle)
                return false;
 
-       status = acpi_get_handle(dhandle, "_DSM", &intel_handle);
-       if (ACPI_FAILURE(status)) {
+       if (!acpi_has_method(dhandle, "_DSM")) {
                DRM_DEBUG_KMS("no _DSM method for intel device\n");
                return false;
        }
index f4c5e95b2d6f633b8151832973f6b831ab0bc559..26c2ea3e985c22d7011e68f3e73d14fa8e896131 100644 (file)
@@ -4759,7 +4759,9 @@ static void cpt_init_clock_gating(struct drm_device *dev)
         * gating for the panel power sequencer or it will fail to
         * start up when no ports are active.
         */
-       I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
+       I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE |
+                  PCH_DPLUNIT_CLOCK_GATE_DISABLE |
+                  PCH_CPUNIT_CLOCK_GATE_DISABLE);
        I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
                   DPLS_EDP_PPS_FIX_DIS);
        /* The below fixes the weird display corruption, a few pixels shifted
index dd7d2e18271940ea3e9f6d9a90b09140c767e73e..cfbeee607b3ace2eb0c602919033b570580f2625 100644 (file)
@@ -253,18 +253,15 @@ static struct vga_switcheroo_handler nouveau_dsm_handler = {
 
 static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
 {
-       acpi_handle dhandle, nvidia_handle;
-       acpi_status status;
+       acpi_handle dhandle;
        int retval = 0;
 
        dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
        if (!dhandle)
                return false;
 
-       status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
-       if (ACPI_FAILURE(status)) {
+       if (!acpi_has_method(dhandle, "_DSM"))
                return false;
-       }
 
        if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
                retval |= NOUVEAU_DSM_HAS_MUX;
index 32923d2f60021105a5092826bcd7810ca054c960..5e891b226acf9cf60db309fc8b8c596660fe1d96 100644 (file)
@@ -707,24 +707,37 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        switch (connector->connector_type) {
        case DRM_MODE_CONNECTOR_DVII:
        case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
-               if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
-                   (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-                    (radeon_connector->audio == RADEON_AUDIO_AUTO)))
-                       return ATOM_ENCODER_MODE_HDMI;
-               else if (radeon_connector->use_digital)
+               if (radeon_audio != 0) {
+                       if (radeon_connector->use_digital &&
+                           (radeon_connector->audio == RADEON_AUDIO_ENABLE))
+                               return ATOM_ENCODER_MODE_HDMI;
+                       else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                                (radeon_connector->audio == RADEON_AUDIO_AUTO))
+                               return ATOM_ENCODER_MODE_HDMI;
+                       else if (radeon_connector->use_digital)
+                               return ATOM_ENCODER_MODE_DVI;
+                       else
+                               return ATOM_ENCODER_MODE_CRT;
+               } else if (radeon_connector->use_digital) {
                        return ATOM_ENCODER_MODE_DVI;
-               else
+               } else {
                        return ATOM_ENCODER_MODE_CRT;
+               }
                break;
        case DRM_MODE_CONNECTOR_DVID:
        case DRM_MODE_CONNECTOR_HDMIA:
        default:
-               if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
-                   (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-                    (radeon_connector->audio == RADEON_AUDIO_AUTO)))
-                       return ATOM_ENCODER_MODE_HDMI;
-               else
+               if (radeon_audio != 0) {
+                       if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
+                               return ATOM_ENCODER_MODE_HDMI;
+                       else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                                (radeon_connector->audio == RADEON_AUDIO_AUTO))
+                               return ATOM_ENCODER_MODE_HDMI;
+                       else
+                               return ATOM_ENCODER_MODE_DVI;
+               } else {
                        return ATOM_ENCODER_MODE_DVI;
+               }
                break;
        case DRM_MODE_CONNECTOR_LVDS:
                return ATOM_ENCODER_MODE_LVDS;
@@ -732,14 +745,19 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        case DRM_MODE_CONNECTOR_DisplayPort:
                dig_connector = radeon_connector->con_priv;
                if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
-                   (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
+                   (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
                        return ATOM_ENCODER_MODE_DP;
-               else if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
-                        (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-                         (radeon_connector->audio == RADEON_AUDIO_AUTO)))
-                       return ATOM_ENCODER_MODE_HDMI;
-               else
+               } else if (radeon_audio != 0) {
+                       if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
+                               return ATOM_ENCODER_MODE_HDMI;
+                       else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                                (radeon_connector->audio == RADEON_AUDIO_AUTO))
+                               return ATOM_ENCODER_MODE_HDMI;
+                       else
+                               return ATOM_ENCODER_MODE_DVI;
+               } else {
                        return ATOM_ENCODER_MODE_DVI;
+               }
                break;
        case DRM_MODE_CONNECTOR_eDP:
                return ATOM_ENCODER_MODE_DP;
@@ -1655,7 +1673,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) {
index b874ccdf52f7c2807461fef654290bc09da7c55d..9cd2bc989ac713d1604cec5ab1311ac3680066c5 100644 (file)
@@ -1694,6 +1694,7 @@ static int cik_init_microcode(struct radeon_device *rdev)
                               fw_name);
                        release_firmware(rdev->smc_fw);
                        rdev->smc_fw = NULL;
+                       err = 0;
                } else if (rdev->smc_fw->size != smc_req_size) {
                        printk(KERN_ERR
                               "cik_smc: Bogus length %zu in firmware \"%s\"\n",
@@ -3182,6 +3183,7 @@ int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
        r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256);
        if (r) {
                DRM_ERROR("radeon: failed to get ib (%d).\n", r);
+               radeon_scratch_free(rdev, scratch);
                return r;
        }
        ib.ptr[0] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
@@ -3198,6 +3200,8 @@ int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
        r = radeon_fence_wait(ib.fence, false);
        if (r) {
                DRM_ERROR("radeon: fence wait failed (%d).\n", r);
+               radeon_scratch_free(rdev, scratch);
+               radeon_ib_free(rdev, &ib);
                return r;
        }
        for (i = 0; i < rdev->usec_timeout; i++) {
index 85a69d2ea3d2c8d86c9c552902d260dd576ac927..9fcd338c0fcf6bb1e113c80c8b116bcf5c56abbc 100644 (file)
@@ -113,6 +113,9 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        u8 *sadb;
        int sad_count;
 
+       /* XXX: setting this register causes hangs on some asics */
+       return;
+
        if (!dig->afmt->pin)
                return;
 
index f815c20640bd45e28c9d27fa86897a99af5d40d6..fe1de855775ecca1491ced31f797f5cac6d05abc 100644 (file)
@@ -67,6 +67,9 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        u8 *sadb;
        int sad_count;
 
+       /* XXX: setting this register causes hangs on some asics */
+       return;
+
        list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
                if (connector->encoder == encoder)
                        radeon_connector = to_radeon_connector(connector);
index 93c1f9ef5da9b5ee7c3474bfaaae5bbe7497cf91..cac2866d79da441dfbbbcef860f713c9c7ad5a58 100644 (file)
@@ -804,6 +804,7 @@ int ni_init_microcode(struct radeon_device *rdev)
                               fw_name);
                        release_firmware(rdev->smc_fw);
                        rdev->smc_fw = NULL;
+                       err = 0;
                } else if (rdev->smc_fw->size != smc_req_size) {
                        printk(KERN_ERR
                               "ni_mc: Bogus length %zu in firmware \"%s\"\n",
index 2a1b1876b4312eb332c017cb027aeb346bf2c850..f9be22062df1eb8048384cabec6219e8a5238fff 100644 (file)
@@ -2302,6 +2302,7 @@ int r600_init_microcode(struct radeon_device *rdev)
                               fw_name);
                        release_firmware(rdev->smc_fw);
                        rdev->smc_fw = NULL;
+                       err = 0;
                } else if (rdev->smc_fw->size != smc_req_size) {
                        printk(KERN_ERR
                               "smc: Bogus length %zu in firmware \"%s\"\n",
index 5b729319f27b880dd70c52e19d5aeb33fe1d2cd8..06022e3b9c3bdc0a0660a60c448e25038659e41d 100644 (file)
@@ -309,6 +309,9 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        u8 *sadb;
        int sad_count;
 
+       /* XXX: setting this register causes hangs on some asics */
+       return;
+
        list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
                if (connector->encoder == encoder)
                        radeon_connector = to_radeon_connector(connector);
index 79159b5da05bc778dc71b819a32c4139d28f967b..64565732cb98cf25af4e4d1f564e307c85cf4a8f 100644 (file)
@@ -1658,9 +1658,12 @@ radeon_add_atom_connector(struct drm_device *dev,
                        drm_object_attach_property(&radeon_connector->base.base,
                                                      rdev->mode_info.underscan_vborder_property,
                                                      0);
-                       drm_object_attach_property(&radeon_connector->base.base,
-                                                  rdev->mode_info.audio_property,
-                                                  RADEON_AUDIO_DISABLE);
+                       if (radeon_audio != 0)
+                               drm_object_attach_property(&radeon_connector->base.base,
+                                                          rdev->mode_info.audio_property,
+                                                          (radeon_audio == 1) ?
+                                                          RADEON_AUDIO_AUTO :
+                                                          RADEON_AUDIO_DISABLE);
                        subpixel_order = SubPixelHorizontalRGB;
                        connector->interlace_allowed = true;
                        if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
@@ -1754,10 +1757,12 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                              rdev->mode_info.underscan_vborder_property,
                                                              0);
                        }
-                       if (ASIC_IS_DCE2(rdev)) {
+                       if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
                                drm_object_attach_property(&radeon_connector->base.base,
-                                                             rdev->mode_info.audio_property,
-                                                             RADEON_AUDIO_DISABLE);
+                                                          rdev->mode_info.audio_property,
+                                                          (radeon_audio == 1) ?
+                                                          RADEON_AUDIO_AUTO :
+                                                          RADEON_AUDIO_DISABLE);
                        }
                        if (connector_type == DRM_MODE_CONNECTOR_DVII) {
                                radeon_connector->dac_load_detect = true;
@@ -1799,10 +1804,12 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                              rdev->mode_info.underscan_vborder_property,
                                                              0);
                        }
-                       if (ASIC_IS_DCE2(rdev)) {
+                       if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
                                drm_object_attach_property(&radeon_connector->base.base,
-                                                             rdev->mode_info.audio_property,
-                                                             RADEON_AUDIO_DISABLE);
+                                                          rdev->mode_info.audio_property,
+                                                          (radeon_audio == 1) ?
+                                                          RADEON_AUDIO_AUTO :
+                                                          RADEON_AUDIO_DISABLE);
                        }
                        subpixel_order = SubPixelHorizontalRGB;
                        connector->interlace_allowed = true;
@@ -1843,10 +1850,12 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                              rdev->mode_info.underscan_vborder_property,
                                                              0);
                        }
-                       if (ASIC_IS_DCE2(rdev)) {
+                       if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
                                drm_object_attach_property(&radeon_connector->base.base,
-                                                             rdev->mode_info.audio_property,
-                                                             RADEON_AUDIO_DISABLE);
+                                                          rdev->mode_info.audio_property,
+                                                          (radeon_audio == 1) ?
+                                                          RADEON_AUDIO_AUTO :
+                                                          RADEON_AUDIO_DISABLE);
                        }
                        connector->interlace_allowed = true;
                        /* in theory with a DP to VGA converter... */
index 66c222836631a4bc8dcd12b2f81f6e935218c566..80285e35bc6513fda3d5f5c975399a60feaab1e3 100644 (file)
@@ -85,9 +85,8 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
                   VRAM, also but everything into VRAM on AGP cards to avoid
                   image corruptions */
                if (p->ring == R600_RING_TYPE_UVD_INDEX &&
-                   p->rdev->family < CHIP_PALM &&
                    (i == 0 || drm_pci_device_is_agp(p->rdev->ddev))) {
-
+                       /* TODO: is this still needed for NI+ ? */
                        p->relocs[i].lobj.domain =
                                RADEON_GEM_DOMAIN_VRAM;
 
index cdd12dcd988b1ed3260076b6d984cbf388dc35a7..9c14a1ba1de43aa9086741fda75c9aba3cc96394 100644 (file)
@@ -153,7 +153,7 @@ int radeon_benchmarking = 0;
 int radeon_testing = 0;
 int radeon_connector_table = 0;
 int radeon_tv = 1;
-int radeon_audio = 1;
+int radeon_audio = -1;
 int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
 int radeon_pcie_gen2 = -1;
@@ -196,7 +196,7 @@ module_param_named(connector_table, radeon_connector_table, int, 0444);
 MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
 module_param_named(tv, radeon_tv, int, 0444);
 
-MODULE_PARM_DESC(audio, "Audio enable (1 = enable)");
+MODULE_PARM_DESC(audio, "Audio enable (-1 = auto, 0 = disable, 1 = enable)");
 module_param_named(audio, radeon_audio, int, 0444);
 
 MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)");
index 4f2e73f79638f244c43558722128910404b2b04b..308eff5be1b420b74b18ccb1b1e0c89f4bd67f32 100644 (file)
@@ -476,7 +476,8 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
                return -EINVAL;
        }
 
-       if (p->rdev->family < CHIP_PALM && (cmd == 0 || cmd == 0x3) &&
+       /* TODO: is this still necessary on NI+ ? */
+       if ((cmd == 0 || cmd == 0x3) &&
            (start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) {
                DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n",
                          start, end);
index d4652af425b87b11c6b723930473b3b810742b10..d96f7cbca0a115f58eaeca9df3a6e585d6b3445d 100644 (file)
@@ -1681,6 +1681,7 @@ static int si_init_microcode(struct radeon_device *rdev)
                       fw_name);
                release_firmware(rdev->smc_fw);
                rdev->smc_fw = NULL;
+               err = 0;
        } else if (rdev->smc_fw->size != smc_req_size) {
                printk(KERN_ERR
                       "si_smc: Bogus length %zu in firmware \"%s\"\n",
index 3100fa9cb52f4ff5f0b924af6d146f1e06ae6908..7266805d9786c6fe9bfd38501f7ab674f7d05a73 100644 (file)
@@ -212,8 +212,8 @@ int uvd_v1_0_start(struct radeon_device *rdev)
        /* enable VCPU clock */
        WREG32(UVD_VCPU_CNTL,  1 << 9);
 
-       /* enable UMC and NC0 */
-       WREG32_P(UVD_LMI_CTRL2, 1 << 13, ~((1 << 8) | (1 << 13)));
+       /* enable UMC */
+       WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
 
        /* boot up the VCPU */
        WREG32(UVD_SOFT_RESET, 0);
index 1a90f0a2f7e5aa7b994558b18a3cffd2d1254ee8..0508f93b9795fbc2b4ccf9c8f34ea62383a7e138 100644 (file)
@@ -740,9 +740,17 @@ static void vmw_postclose(struct drm_device *dev,
        struct vmw_fpriv *vmw_fp;
 
        vmw_fp = vmw_fpriv(file_priv);
-       ttm_object_file_release(&vmw_fp->tfile);
-       if (vmw_fp->locked_master)
+
+       if (vmw_fp->locked_master) {
+               struct vmw_master *vmaster =
+                       vmw_master(vmw_fp->locked_master);
+
+               ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
+               ttm_vt_unlock(&vmaster->lock);
                drm_master_put(&vmw_fp->locked_master);
+       }
+
+       ttm_object_file_release(&vmw_fp->tfile);
        kfree(vmw_fp);
 }
 
@@ -925,14 +933,13 @@ static void vmw_master_drop(struct drm_device *dev,
 
        vmw_fp->locked_master = drm_master_get(file_priv->master);
        ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
-       vmw_execbuf_release_pinned_bo(dev_priv);
-
        if (unlikely((ret != 0))) {
                DRM_ERROR("Unable to lock TTM at VT switch.\n");
                drm_master_put(&vmw_fp->locked_master);
        }
 
-       ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
+       ttm_lock_set_kill(&vmaster->lock, false, SIGTERM);
+       vmw_execbuf_release_pinned_bo(dev_priv);
 
        if (!dev_priv->enable_fb) {
                ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
index 0e67cf41065d801e6526d23dc5cdf375bdabe1c7..37fb4befec82634ccf3a504428af8ed60f4a0e56 100644 (file)
@@ -970,7 +970,7 @@ void vmw_resource_unreserve(struct vmw_resource *res,
        if (new_backup)
                res->backup_offset = new_backup_offset;
 
-       if (!res->func->may_evict)
+       if (!res->func->may_evict || res->id == -1)
                return;
 
        write_lock(&dev_priv->resource_lock);
index 5a8c01112a233a5ce52ce7260d19376720c74042..e80da62363bc2c96d6be419f89d002f3a55e4d36 100644 (file)
@@ -319,7 +319,7 @@ static s32 item_sdata(struct hid_item *item)
 
 static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
 {
-       __u32 raw_value;
+       __s32 raw_value;
        switch (item->tag) {
        case HID_GLOBAL_ITEM_TAG_PUSH:
 
@@ -370,10 +370,11 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
                return 0;
 
        case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
-               /* Units exponent negative numbers are given through a
-                * two's complement.
-                * See "6.2.2.7 Global Items" for more information. */
-               raw_value = item_udata(item);
+               /* Many devices provide unit exponent as a two's complement
+                * nibble due to the common misunderstanding of HID
+                * specification 1.11, 6.2.2.7 Global Items. Attempt to handle
+                * both this and the standard encoding. */
+               raw_value = item_sdata(item);
                if (!(raw_value & 0xfffffff0))
                        parser->global.unit_exponent = hid_snto32(raw_value, 4);
                else
@@ -1870,6 +1871,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO2, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
        { }
 };
index 9cbc7ab07dfaee581141b0191f4e76300a18d1d6..f0296a50be5f754fc7be2b8f593bf2b2beca1e22 100644 (file)
 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN   0x0003
 
 #define USB_VENDOR_ID_NINTENDO         0x057e
+#define USB_VENDOR_ID_NINTENDO2                0x054c
 #define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306
 #define USB_DEVICE_ID_NINTENDO_WIIMOTE2        0x0330
 
 #define USB_DEVICE_ID_SYNAPTICS_COMP_TP        0x0009
 #define USB_DEVICE_ID_SYNAPTICS_WTP    0x0010
 #define USB_DEVICE_ID_SYNAPTICS_DPAD   0x0013
+#define USB_DEVICE_ID_SYNAPTICS_LTS1   0x0af8
+#define USB_DEVICE_ID_SYNAPTICS_LTS2   0x1d10
 
 #define USB_VENDOR_ID_THINGM           0x27b8
 #define USB_DEVICE_ID_BLINK1           0x01ed
 #define USB_VENDOR_ID_PRIMAX   0x0461
 #define USB_DEVICE_ID_PRIMAX_KEYBOARD  0x4e05
 
+#define USB_VENDOR_ID_SIS      0x0457
+#define USB_DEVICE_ID_SIS_TS   0x1013
+
 #endif
index 8741d953dcc80acb552bac187ffe6997ad95ca4e..d97f2323af573ecf229f9d76b536634c57c26e17 100644 (file)
@@ -192,6 +192,7 @@ static int hidinput_setkeycode(struct input_dev *dev,
        return -EINVAL;
 }
 
+
 /**
  * hidinput_calc_abs_res - calculate an absolute axis resolution
  * @field: the HID report field to calculate resolution for
@@ -234,23 +235,17 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
        case ABS_MT_TOOL_Y:
        case ABS_MT_TOUCH_MAJOR:
        case ABS_MT_TOUCH_MINOR:
-               if (field->unit & 0xffffff00)           /* Not a length */
-                       return 0;
-               unit_exponent += hid_snto32(field->unit >> 4, 4) - 1;
-               switch (field->unit & 0xf) {
-               case 0x1:                               /* If centimeters */
+               if (field->unit == 0x11) {              /* If centimeters */
                        /* Convert to millimeters */
                        unit_exponent += 1;
-                       break;
-               case 0x3:                               /* If inches */
+               } else if (field->unit == 0x13) {       /* If inches */
                        /* Convert to millimeters */
                        prev = physical_extents;
                        physical_extents *= 254;
                        if (physical_extents < prev)
                                return 0;
                        unit_exponent -= 1;
-                       break;
-               default:
+               } else {
                        return 0;
                }
                break;
index abb20db2b443ccdcc34159a97fcc83307db65c40..1446f526ee8bbade2290b615fc14b6aae35dc09f 100644 (file)
@@ -834,7 +834,8 @@ static void wiimote_init_set_type(struct wiimote_data *wdata,
                goto done;
        }
 
-       if (vendor == USB_VENDOR_ID_NINTENDO) {
+       if (vendor == USB_VENDOR_ID_NINTENDO ||
+           vendor == USB_VENDOR_ID_NINTENDO2) {
                if (product == USB_DEVICE_ID_NINTENDO_WIIMOTE) {
                        devtype = WIIMOTE_DEV_GEN10;
                        goto done;
@@ -1855,6 +1856,8 @@ static void wiimote_hid_remove(struct hid_device *hdev)
 static const struct hid_device_id wiimote_hid_devices[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
                                USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO2,
+                               USB_DEVICE_ID_NINTENDO_WIIMOTE) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
                                USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
        { }
index c1336193b04ba3deb92c3edf2468551f3f6933a9..fd7ce374f812ead7960b72a5d00ac3b5908ab221 100644 (file)
@@ -854,10 +854,10 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
                0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
                0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
        };
-       struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object params[4], *obj;
+       union acpi_object params[4];
        struct acpi_object_list input;
        struct acpi_device *adev;
+       unsigned long long value;
        acpi_handle handle;
 
        handle = ACPI_HANDLE(&client->dev);
@@ -878,22 +878,14 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
        params[3].package.count = 0;
        params[3].package.elements = NULL;
 
-       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf))) {
+       if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_DSM", &input,
+                                                               &value))) {
                dev_err(&client->dev, "device _DSM execution failed\n");
                return -ENODEV;
        }
 
-       obj = (union acpi_object *)buf.pointer;
-       if (obj->type != ACPI_TYPE_INTEGER) {
-               dev_err(&client->dev, "device _DSM returned invalid type: %d\n",
-                       obj->type);
-               kfree(buf.pointer);
-               return -EINVAL;
-       }
-
-       pdata->hid_descriptor_address = obj->integer.value;
+       pdata->hid_descriptor_address = value;
 
-       kfree(buf.pointer);
        return 0;
 }
 
index 07345521f4210f4988627cff4421beedc96d1c06..3fca3be08337d76fdd8ecaec09c3d1693b0ac4ef 100644 (file)
@@ -110,6 +110,9 @@ static const struct hid_blacklist {
        { 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 },
+       { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_SIS, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS },
 
        { 0, 0 }
 };
index 3be58f89ac774962db749fcdea5c032e28edce0d..75ba8608383e4b1d26e65a389f099f7028e7b733 100644 (file)
@@ -254,10 +254,12 @@ static int i2c_device_probe(struct device *dev)
                                        client->flags & I2C_CLIENT_WAKE);
        dev_dbg(dev, "probe\n");
 
+       acpi_dev_pm_attach(&client->dev, true);
        status = driver->probe(client, i2c_match_id(driver->id_table, client));
        if (status) {
                client->driver = NULL;
                i2c_set_clientdata(client, NULL);
+               acpi_dev_pm_detach(&client->dev, true);
        }
        return status;
 }
@@ -283,6 +285,7 @@ static int i2c_device_remove(struct device *dev)
                client->driver = NULL;
                i2c_set_clientdata(client, NULL);
        }
+       acpi_dev_pm_detach(&client->dev, true);
        return status;
 }
 
@@ -1111,8 +1114,10 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
        if (ret < 0 || !info.addr)
                return AE_OK;
 
+       adev->power.flags.ignore_parent = true;
        strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
        if (!i2c_new_device(adapter, &info)) {
+               adev->power.flags.ignore_parent = false;
                dev_err(&adapter->dev,
                        "failed to add I2C device %s from ACPI\n",
                        dev_name(&adev->dev));
index fa6964d8681a0d126fcf7c4845896b3f06298f8f..3f95a533c1a8f17de582b2abe28e51bd77006fd2 100644 (file)
@@ -123,7 +123,7 @@ static struct cpuidle_state *cpuidle_state_table;
  * which is also the index into the MWAIT hint array.
  * Thus C0 is a dummy.
  */
-static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state nehalem_cstates[] __initdata = {
        {
                .name = "C1-NHM",
                .desc = "MWAIT 0x00",
@@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = {
                .enter = NULL }
 };
 
-static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state snb_cstates[] __initdata = {
        {
                .name = "C1-SNB",
                .desc = "MWAIT 0x00",
@@ -196,7 +196,7 @@ static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = {
                .enter = NULL }
 };
 
-static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state ivb_cstates[] __initdata = {
        {
                .name = "C1-IVB",
                .desc = "MWAIT 0x00",
@@ -236,7 +236,7 @@ static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = {
                .enter = NULL }
 };
 
-static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state hsw_cstates[] __initdata = {
        {
                .name = "C1-HSW",
                .desc = "MWAIT 0x00",
@@ -297,7 +297,7 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = {
                .enter = NULL }
 };
 
-static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state atom_cstates[] __initdata = {
        {
                .name = "C1E-ATM",
                .desc = "MWAIT 0x00",
@@ -390,7 +390,7 @@ static int cpu_hotplug_notify(struct notifier_block *n,
        int hotcpu = (unsigned long)hcpu;
        struct cpuidle_device *dev;
 
-       switch (action & 0xf) {
+       switch (action & ~CPU_TASKS_FROZEN) {
        case CPU_ONLINE:
 
                if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
@@ -490,7 +490,7 @@ MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
 /*
  * intel_idle_probe()
  */
-static int intel_idle_probe(void)
+static int __init intel_idle_probe(void)
 {
        unsigned int eax, ebx, ecx;
        const struct x86_cpu_id *id;
@@ -558,7 +558,7 @@ static void intel_idle_cpuidle_devices_uninit(void)
  * intel_idle_cpuidle_driver_init()
  * allocate, initialize cpuidle_states
  */
-static int intel_idle_cpuidle_driver_init(void)
+static int __init intel_idle_cpuidle_driver_init(void)
 {
        int cstate;
        struct cpuidle_driver *drv = &intel_idle_driver;
@@ -628,7 +628,7 @@ static int intel_idle_cpu_init(int cpu)
                int num_substates, mwait_hint, mwait_cstate, mwait_substate;
 
                if (cpuidle_state_table[cstate].enter == NULL)
-                       continue;
+                       break;
 
                if (cstate + 1 > max_cstate) {
                        printk(PREFIX "max_cstate %d reached\n", max_cstate);
index a7b30be86ae06cb7ae59a077aa45ee4e58f52051..52605c0ea3a69fce7c1d312d4fa1610de43174fd 100644 (file)
@@ -525,8 +525,10 @@ static int adf4350_probe(struct spi_device *spi)
        }
 
        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
-       if (indio_dev == NULL)
-               return -ENOMEM;
+       if (indio_dev == NULL) {
+               ret =  -ENOMEM;
+               goto error_disable_clk;
+       }
 
        st = iio_priv(indio_dev);
 
index 2710f7245c3b5472b0e924bd22a94f6bc1212b6f..2db7dcd826b9db6500e354498b385cbb3ebd9f7d 100644 (file)
@@ -477,6 +477,9 @@ void iio_disable_all_buffers(struct iio_dev *indio_dev)
        indio_dev->currentmode = INDIO_DIRECT_MODE;
        if (indio_dev->setup_ops->postdisable)
                indio_dev->setup_ops->postdisable(indio_dev);
+
+       if (indio_dev->available_scan_masks == NULL)
+               kfree(indio_dev->active_scan_mask);
 }
 
 int iio_update_buffers(struct iio_dev *indio_dev,
index 5ceda710f516bc4721e14961a504fa7e2c3054a9..b84791f03a27f5d174b60680f77c59de06bb542a 100644 (file)
@@ -31,6 +31,17 @@ config INFINIBAND_USER_ACCESS
          libibverbs, libibcm and a hardware driver library from
          <http://www.openfabrics.org/git/>.
 
+config INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
+       bool "Experimental and unstable ABI for userspace access to flow steering verbs"
+       depends on INFINIBAND_USER_ACCESS
+       depends on STAGING
+       ---help---
+         The final ABI for userspace access to flow steering verbs
+         has not been defined.  To use the current ABI, *WHICH WILL
+         CHANGE IN THE FUTURE*, say Y here.
+
+         If unsure, say N.
+
 config INFINIBAND_USER_MEM
        bool
        depends on INFINIBAND_USER_ACCESS != n
index d040b877475f3f04f9f6c2fea63ba772fbd9586c..d8f9c6c272d732a898b334be0c3034aadf37b275 100644 (file)
@@ -217,7 +217,9 @@ IB_UVERBS_DECLARE_CMD(destroy_srq);
 IB_UVERBS_DECLARE_CMD(create_xsrq);
 IB_UVERBS_DECLARE_CMD(open_xrcd);
 IB_UVERBS_DECLARE_CMD(close_xrcd);
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 IB_UVERBS_DECLARE_CMD(create_flow);
 IB_UVERBS_DECLARE_CMD(destroy_flow);
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 
 #endif /* UVERBS_H */
index f2b81b9ee0d6849c67693e50c351721c64df27fe..2f0f01b70e3bd22c538cd3a4081be0a9ec3f790f 100644 (file)
@@ -54,7 +54,9 @@ static struct uverbs_lock_class qp_lock_class = { .name = "QP-uobj" };
 static struct uverbs_lock_class ah_lock_class  = { .name = "AH-uobj" };
 static struct uverbs_lock_class srq_lock_class = { .name = "SRQ-uobj" };
 static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" };
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" };
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 
 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)                      \
        do {                                                            \
@@ -2599,6 +2601,7 @@ out_put:
        return ret ? ret : in_len;
 }
 
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 static int kern_spec_to_ib_spec(struct ib_kern_spec *kern_spec,
                                union ib_flow_spec *ib_spec)
 {
@@ -2824,6 +2827,7 @@ ssize_t ib_uverbs_destroy_flow(struct ib_uverbs_file *file,
 
        return ret ? ret : in_len;
 }
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 
 static int __uverbs_create_xsrq(struct ib_uverbs_file *file,
                                struct ib_uverbs_create_xsrq *cmd,
index 75ad86c4abf82a86572d9ca8b35d52a7f9d2d4ce..2df31f68ea0905ef06ac1ed054348cf669cfaa61 100644 (file)
@@ -115,8 +115,10 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
        [IB_USER_VERBS_CMD_CLOSE_XRCD]          = ib_uverbs_close_xrcd,
        [IB_USER_VERBS_CMD_CREATE_XSRQ]         = ib_uverbs_create_xsrq,
        [IB_USER_VERBS_CMD_OPEN_QP]             = ib_uverbs_open_qp,
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
        [IB_USER_VERBS_CMD_CREATE_FLOW]         = ib_uverbs_create_flow,
        [IB_USER_VERBS_CMD_DESTROY_FLOW]        = ib_uverbs_destroy_flow
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 };
 
 static void ib_uverbs_add_one(struct ib_device *device);
@@ -605,6 +607,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
        if (!(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command)))
                return -ENOSYS;
 
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
        if (hdr.command >= IB_USER_VERBS_CMD_THRESHOLD) {
                struct ib_uverbs_cmd_hdr_ex hdr_ex;
 
@@ -621,6 +624,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
                                                     (hdr_ex.out_words +
                                                      hdr_ex.provider_out_words) * 4);
        } else {
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
                if (hdr.in_words * 4 != count)
                        return -EINVAL;
 
@@ -628,7 +632,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
                                                     buf + sizeof(hdr),
                                                     hdr.in_words * 4,
                                                     hdr.out_words * 4);
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
        }
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 }
 
 static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
index d5d1929753e4fdc95bbdc67625f5f0521ffeb32f..cedda25232be2454b3b2f0902152d96a7b1dfd75 100644 (file)
@@ -141,7 +141,7 @@ static const char *to_qp_state_str(int state)
                return "C2_QP_STATE_ERROR";
        default:
                return "<invalid QP state>";
-       };
+       }
 }
 
 void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
index d6c5a73becf40ecfc0f177422f34de1f14247f32..f0612645de998f6bcba2dfa0ae34a2b51483af38 100644 (file)
@@ -1691,9 +1691,11 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                ibdev->ib_dev.create_flow       = mlx4_ib_create_flow;
                ibdev->ib_dev.destroy_flow      = mlx4_ib_destroy_flow;
 
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
                ibdev->ib_dev.uverbs_cmd_mask   |=
                        (1ull << IB_USER_VERBS_CMD_CREATE_FLOW) |
                        (1ull << IB_USER_VERBS_CMD_DESTROY_FLOW);
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
        }
 
        mlx4_ib_alloc_eqs(dev, ibdev);
index 3f831de9a4d8a901607afc26c81827cc5c1e3bd5..b1a6cb3a2809282fbfab1b44b09c53e315a93466 100644 (file)
@@ -164,6 +164,7 @@ int mlx5_vector2eqn(struct mlx5_ib_dev *dev, int vector, int *eqn, int *irqn)
 static int alloc_comp_eqs(struct mlx5_ib_dev *dev)
 {
        struct mlx5_eq_table *table = &dev->mdev.priv.eq_table;
+       char name[MLX5_MAX_EQ_NAME];
        struct mlx5_eq *eq, *n;
        int ncomp_vec;
        int nent;
@@ -180,11 +181,10 @@ static int alloc_comp_eqs(struct mlx5_ib_dev *dev)
                        goto clean;
                }
 
-               snprintf(eq->name, MLX5_MAX_EQ_NAME, "mlx5_comp%d", i);
+               snprintf(name, MLX5_MAX_EQ_NAME, "mlx5_comp%d", i);
                err = mlx5_create_map_eq(&dev->mdev, eq,
                                         i + MLX5_EQ_VEC_COMP_BASE, nent, 0,
-                                        eq->name,
-                                        &dev->mdev.priv.uuari.uars[0]);
+                                        name, &dev->mdev.priv.uuari.uars[0]);
                if (err) {
                        kfree(eq);
                        goto clean;
@@ -301,9 +301,8 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
        props->max_srq_sge         = max_rq_sg - 1;
        props->max_fast_reg_page_list_len = (unsigned int)-1;
        props->local_ca_ack_delay  = dev->mdev.caps.local_ca_ack_delay;
-       props->atomic_cap          = dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_ATOMIC ?
-               IB_ATOMIC_HCA : IB_ATOMIC_NONE;
-       props->masked_atomic_cap   = IB_ATOMIC_HCA;
+       props->atomic_cap          = IB_ATOMIC_NONE;
+       props->masked_atomic_cap   = IB_ATOMIC_NONE;
        props->max_pkeys           = be16_to_cpup((__be16 *)(out_mad->data + 28));
        props->max_mcast_grp       = 1 << dev->mdev.caps.log_max_mcg;
        props->max_mcast_qp_attach = dev->mdev.caps.max_qp_mcg;
@@ -1006,6 +1005,11 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
        ibev.device           = &ibdev->ib_dev;
        ibev.element.port_num = port;
 
+       if (port < 1 || port > ibdev->num_ports) {
+               mlx5_ib_warn(ibdev, "warning: event on port %d\n", port);
+               return;
+       }
+
        if (ibdev->ib_active)
                ib_dispatch_event(&ibev);
 }
index bd41df95b6f0214deb445ab228be8d157373074f..3453580b1eb2cc45800b8ee697157a24cf269970 100644 (file)
@@ -42,6 +42,10 @@ enum {
        DEF_CACHE_SIZE  = 10,
 };
 
+enum {
+       MLX5_UMR_ALIGN  = 2048
+};
+
 static __be64 *mr_align(__be64 *ptr, int align)
 {
        unsigned long mask = align - 1;
@@ -61,13 +65,11 @@ static int order2idx(struct mlx5_ib_dev *dev, int order)
 
 static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
 {
-       struct device *ddev = dev->ib_dev.dma_device;
        struct mlx5_mr_cache *cache = &dev->cache;
        struct mlx5_cache_ent *ent = &cache->ent[c];
        struct mlx5_create_mkey_mbox_in *in;
        struct mlx5_ib_mr *mr;
        int npages = 1 << ent->order;
-       int size = sizeof(u64) * npages;
        int err = 0;
        int i;
 
@@ -83,21 +85,6 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
                }
                mr->order = ent->order;
                mr->umred = 1;
-               mr->pas = kmalloc(size + 0x3f, GFP_KERNEL);
-               if (!mr->pas) {
-                       kfree(mr);
-                       err = -ENOMEM;
-                       goto out;
-               }
-               mr->dma = dma_map_single(ddev, mr_align(mr->pas, 0x40), size,
-                                        DMA_TO_DEVICE);
-               if (dma_mapping_error(ddev, mr->dma)) {
-                       kfree(mr->pas);
-                       kfree(mr);
-                       err = -ENOMEM;
-                       goto out;
-               }
-
                in->seg.status = 1 << 6;
                in->seg.xlt_oct_size = cpu_to_be32((npages + 1) / 2);
                in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
@@ -108,8 +95,6 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
                                            sizeof(*in));
                if (err) {
                        mlx5_ib_warn(dev, "create mkey failed %d\n", err);
-                       dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
-                       kfree(mr->pas);
                        kfree(mr);
                        goto out;
                }
@@ -129,11 +114,9 @@ out:
 
 static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
 {
-       struct device *ddev = dev->ib_dev.dma_device;
        struct mlx5_mr_cache *cache = &dev->cache;
        struct mlx5_cache_ent *ent = &cache->ent[c];
        struct mlx5_ib_mr *mr;
-       int size;
        int err;
        int i;
 
@@ -149,14 +132,10 @@ static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
                ent->size--;
                spin_unlock(&ent->lock);
                err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
-               if (err) {
+               if (err)
                        mlx5_ib_warn(dev, "failed destroy mkey\n");
-               } else {
-                       size = ALIGN(sizeof(u64) * (1 << mr->order), 0x40);
-                       dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
-                       kfree(mr->pas);
+               else
                        kfree(mr);
-               }
        }
 }
 
@@ -408,13 +387,12 @@ static void free_cached_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
 
 static void clean_keys(struct mlx5_ib_dev *dev, int c)
 {
-       struct device *ddev = dev->ib_dev.dma_device;
        struct mlx5_mr_cache *cache = &dev->cache;
        struct mlx5_cache_ent *ent = &cache->ent[c];
        struct mlx5_ib_mr *mr;
-       int size;
        int err;
 
+       cancel_delayed_work(&ent->dwork);
        while (1) {
                spin_lock(&ent->lock);
                if (list_empty(&ent->head)) {
@@ -427,14 +405,10 @@ static void clean_keys(struct mlx5_ib_dev *dev, int c)
                ent->size--;
                spin_unlock(&ent->lock);
                err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
-               if (err) {
+               if (err)
                        mlx5_ib_warn(dev, "failed destroy mkey\n");
-               } else {
-                       size = ALIGN(sizeof(u64) * (1 << mr->order), 0x40);
-                       dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
-                       kfree(mr->pas);
+               else
                        kfree(mr);
-               }
        }
 }
 
@@ -540,13 +514,15 @@ int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
        int i;
 
        dev->cache.stopped = 1;
-       destroy_workqueue(dev->cache.wq);
+       flush_workqueue(dev->cache.wq);
 
        mlx5_mr_cache_debugfs_cleanup(dev);
 
        for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++)
                clean_keys(dev, i);
 
+       destroy_workqueue(dev->cache.wq);
+
        return 0;
 }
 
@@ -675,10 +651,12 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
                                  int page_shift, int order, int access_flags)
 {
        struct mlx5_ib_dev *dev = to_mdev(pd->device);
+       struct device *ddev = dev->ib_dev.dma_device;
        struct umr_common *umrc = &dev->umrc;
        struct ib_send_wr wr, *bad;
        struct mlx5_ib_mr *mr;
        struct ib_sge sg;
+       int size = sizeof(u64) * npages;
        int err;
        int i;
 
@@ -697,7 +675,22 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
        if (!mr)
                return ERR_PTR(-EAGAIN);
 
-       mlx5_ib_populate_pas(dev, umem, page_shift, mr_align(mr->pas, 0x40), 1);
+       mr->pas = kmalloc(size + MLX5_UMR_ALIGN - 1, GFP_KERNEL);
+       if (!mr->pas) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       mlx5_ib_populate_pas(dev, umem, page_shift,
+                            mr_align(mr->pas, MLX5_UMR_ALIGN), 1);
+
+       mr->dma = dma_map_single(ddev, mr_align(mr->pas, MLX5_UMR_ALIGN), size,
+                                DMA_TO_DEVICE);
+       if (dma_mapping_error(ddev, mr->dma)) {
+               kfree(mr->pas);
+               err = -ENOMEM;
+               goto error;
+       }
 
        memset(&wr, 0, sizeof(wr));
        wr.wr_id = (u64)(unsigned long)mr;
@@ -718,6 +711,9 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
        wait_for_completion(&mr->done);
        up(&umrc->sem);
 
+       dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
+       kfree(mr->pas);
+
        if (mr->status != IB_WC_SUCCESS) {
                mlx5_ib_warn(dev, "reg umr failed\n");
                err = -EFAULT;
index 045f8cdbd303deba81e60c5f1f52330b536b9617..5659ea88074108e60d9253085ce89f962326b808 100644 (file)
@@ -203,7 +203,7 @@ static int sq_overhead(enum ib_qp_type qp_type)
 
        switch (qp_type) {
        case IB_QPT_XRC_INI:
-               size = sizeof(struct mlx5_wqe_xrc_seg);
+               size += sizeof(struct mlx5_wqe_xrc_seg);
                /* fall through */
        case IB_QPT_RC:
                size += sizeof(struct mlx5_wqe_ctrl_seg) +
@@ -211,20 +211,23 @@ static int sq_overhead(enum ib_qp_type qp_type)
                        sizeof(struct mlx5_wqe_raddr_seg);
                break;
 
+       case IB_QPT_XRC_TGT:
+               return 0;
+
        case IB_QPT_UC:
-               size = sizeof(struct mlx5_wqe_ctrl_seg) +
+               size += sizeof(struct mlx5_wqe_ctrl_seg) +
                        sizeof(struct mlx5_wqe_raddr_seg);
                break;
 
        case IB_QPT_UD:
        case IB_QPT_SMI:
        case IB_QPT_GSI:
-               size = sizeof(struct mlx5_wqe_ctrl_seg) +
+               size += sizeof(struct mlx5_wqe_ctrl_seg) +
                        sizeof(struct mlx5_wqe_datagram_seg);
                break;
 
        case MLX5_IB_QPT_REG_UMR:
-               size = sizeof(struct mlx5_wqe_ctrl_seg) +
+               size += sizeof(struct mlx5_wqe_ctrl_seg) +
                        sizeof(struct mlx5_wqe_umr_ctrl_seg) +
                        sizeof(struct mlx5_mkey_seg);
                break;
@@ -270,7 +273,8 @@ static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
                return wqe_size;
 
        if (wqe_size > dev->mdev.caps.max_sq_desc_sz) {
-               mlx5_ib_dbg(dev, "\n");
+               mlx5_ib_dbg(dev, "wqe_size(%d) > max_sq_desc_sz(%d)\n",
+                           wqe_size, dev->mdev.caps.max_sq_desc_sz);
                return -EINVAL;
        }
 
@@ -280,9 +284,15 @@ static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
 
        wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size);
        qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB;
+       if (qp->sq.wqe_cnt > dev->mdev.caps.max_wqes) {
+               mlx5_ib_dbg(dev, "wqe count(%d) exceeds limits(%d)\n",
+                           qp->sq.wqe_cnt, dev->mdev.caps.max_wqes);
+               return -ENOMEM;
+       }
        qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
        qp->sq.max_gs = attr->cap.max_send_sge;
-       qp->sq.max_post = 1 << ilog2(wq_size / wqe_size);
+       qp->sq.max_post = wq_size / wqe_size;
+       attr->cap.max_send_wr = qp->sq.max_post;
 
        return wq_size;
 }
@@ -1280,6 +1290,11 @@ static enum mlx5_qp_optpar opt_mask[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE][MLX5_Q
                                          MLX5_QP_OPTPAR_Q_KEY,
                        [MLX5_QP_ST_MLX] = MLX5_QP_OPTPAR_PKEY_INDEX    |
                                           MLX5_QP_OPTPAR_Q_KEY,
+                       [MLX5_QP_ST_XRC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH |
+                                         MLX5_QP_OPTPAR_RRE            |
+                                         MLX5_QP_OPTPAR_RAE            |
+                                         MLX5_QP_OPTPAR_RWE            |
+                                         MLX5_QP_OPTPAR_PKEY_INDEX,
                },
        },
        [MLX5_QP_STATE_RTR] = {
@@ -1314,6 +1329,11 @@ static enum mlx5_qp_optpar opt_mask[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE][MLX5_Q
                [MLX5_QP_STATE_RTS] = {
                        [MLX5_QP_ST_UD]  = MLX5_QP_OPTPAR_Q_KEY,
                        [MLX5_QP_ST_MLX] = MLX5_QP_OPTPAR_Q_KEY,
+                       [MLX5_QP_ST_UC]  = MLX5_QP_OPTPAR_RWE,
+                       [MLX5_QP_ST_RC]  = MLX5_QP_OPTPAR_RNR_TIMEOUT   |
+                                          MLX5_QP_OPTPAR_RWE           |
+                                          MLX5_QP_OPTPAR_RAE           |
+                                          MLX5_QP_OPTPAR_RRE,
                },
        },
 };
@@ -1651,29 +1671,6 @@ static __always_inline void set_raddr_seg(struct mlx5_wqe_raddr_seg *rseg,
        rseg->reserved = 0;
 }
 
-static void set_atomic_seg(struct mlx5_wqe_atomic_seg *aseg, struct ib_send_wr *wr)
-{
-       if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
-               aseg->swap_add = cpu_to_be64(wr->wr.atomic.swap);
-               aseg->compare  = cpu_to_be64(wr->wr.atomic.compare_add);
-       } else if (wr->opcode == IB_WR_MASKED_ATOMIC_FETCH_AND_ADD) {
-               aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
-               aseg->compare  = cpu_to_be64(wr->wr.atomic.compare_add_mask);
-       } else {
-               aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
-               aseg->compare  = 0;
-       }
-}
-
-static void set_masked_atomic_seg(struct mlx5_wqe_masked_atomic_seg *aseg,
-                                 struct ib_send_wr *wr)
-{
-       aseg->swap_add          = cpu_to_be64(wr->wr.atomic.swap);
-       aseg->swap_add_mask     = cpu_to_be64(wr->wr.atomic.swap_mask);
-       aseg->compare           = cpu_to_be64(wr->wr.atomic.compare_add);
-       aseg->compare_mask      = cpu_to_be64(wr->wr.atomic.compare_add_mask);
-}
-
 static void set_datagram_seg(struct mlx5_wqe_datagram_seg *dseg,
                             struct ib_send_wr *wr)
 {
@@ -2063,28 +2060,11 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 
                        case IB_WR_ATOMIC_CMP_AND_SWP:
                        case IB_WR_ATOMIC_FETCH_AND_ADD:
-                               set_raddr_seg(seg, wr->wr.atomic.remote_addr,
-                                             wr->wr.atomic.rkey);
-                               seg  += sizeof(struct mlx5_wqe_raddr_seg);
-
-                               set_atomic_seg(seg, wr);
-                               seg  += sizeof(struct mlx5_wqe_atomic_seg);
-
-                               size += (sizeof(struct mlx5_wqe_raddr_seg) +
-                                        sizeof(struct mlx5_wqe_atomic_seg)) / 16;
-                               break;
-
                        case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
-                               set_raddr_seg(seg, wr->wr.atomic.remote_addr,
-                                             wr->wr.atomic.rkey);
-                               seg  += sizeof(struct mlx5_wqe_raddr_seg);
-
-                               set_masked_atomic_seg(seg, wr);
-                               seg  += sizeof(struct mlx5_wqe_masked_atomic_seg);
-
-                               size += (sizeof(struct mlx5_wqe_raddr_seg) +
-                                        sizeof(struct mlx5_wqe_masked_atomic_seg)) / 16;
-                               break;
+                               mlx5_ib_warn(dev, "Atomic operations are not supported yet\n");
+                               err = -ENOSYS;
+                               *bad_wr = wr;
+                               goto out;
 
                        case IB_WR_LOCAL_INV:
                                next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
index 84d297afd6a9889642007a4b3d6b2e0e6e25be74..0aa478bc291ae39aec0ed8c243cce72fe7ed2bdd 100644 (file)
@@ -295,7 +295,7 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
        mlx5_vfree(in);
        if (err) {
                mlx5_ib_dbg(dev, "create SRQ failed, err %d\n", err);
-               goto err_srq;
+               goto err_usr_kern_srq;
        }
 
        mlx5_ib_dbg(dev, "create SRQ with srqn 0x%x\n", srq->msrq.srqn);
@@ -316,6 +316,8 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
 
 err_core:
        mlx5_core_destroy_srq(&dev->mdev, &srq->msrq);
+
+err_usr_kern_srq:
        if (pd->uobject)
                destroy_srq_user(pd, srq);
        else
index 7c9d35f39d756950b9470d50201f882ca6fba1e3..69020173899397ee5889287ee79f0c3525ab8991 100644 (file)
@@ -357,7 +357,7 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
                        mthca_warn(dev, "Unhandled event %02x(%02x) on EQ %d\n",
                                   eqe->type, eqe->subtype, eq->eqn);
                        break;
-               };
+               }
 
                set_eqe_hw(eqe);
                ++eq->cons_index;
index 4ed8235d2d36d818360cce7e2d43010e0840ab62..50219ab2279d56ae6599e7189b06034bf12049d9 100644 (file)
@@ -150,7 +150,7 @@ enum ib_qp_state get_ibqp_state(enum ocrdma_qp_state qps)
                return IB_QPS_SQE;
        case OCRDMA_QPS_ERR:
                return IB_QPS_ERR;
-       };
+       }
        return IB_QPS_ERR;
 }
 
@@ -171,7 +171,7 @@ static enum ocrdma_qp_state get_ocrdma_qp_state(enum ib_qp_state qps)
                return OCRDMA_QPS_SQE;
        case IB_QPS_ERR:
                return OCRDMA_QPS_ERR;
-       };
+       }
        return OCRDMA_QPS_ERR;
 }
 
@@ -1982,7 +1982,7 @@ int ocrdma_mbx_create_qp(struct ocrdma_qp *qp, struct ib_qp_init_attr *attrs,
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_QP, sizeof(*cmd));
        if (!cmd)
index 56e004940f1806c9203e788985395ea4ea5bdddb..0ce7674621eaba2aa310fef332695b67f3057971 100644 (file)
@@ -531,7 +531,7 @@ static void ocrdma_event_handler(struct ocrdma_dev *dev, u32 event)
        case BE_DEV_DOWN:
                ocrdma_close(dev);
                break;
-       };
+       }
 }
 
 static struct ocrdma_driver ocrdma_drv = {
index 6e982bb43c3172d2cc36b844c1b97f8bb0960237..69f1d1221a6bea07039fc37b5ead33f941fc74a4 100644 (file)
@@ -141,7 +141,7 @@ static inline void get_link_speed_and_width(struct ocrdma_dev *dev,
                /* Unsupported */
                *ib_speed = IB_SPEED_SDR;
                *ib_width = IB_WIDTH_1X;
-       };
+       }
 }
 
 
@@ -2331,7 +2331,7 @@ static enum ib_wc_status ocrdma_to_ibwc_err(u16 status)
        default:
                ibwc_status = IB_WC_GENERAL_ERR;
                break;
-       };
+       }
        return ibwc_status;
 }
 
@@ -2370,7 +2370,7 @@ static void ocrdma_update_wc(struct ocrdma_qp *qp, struct ib_wc *ibwc,
                pr_err("%s() invalid opcode received = 0x%x\n",
                       __func__, hdr->cw & OCRDMA_WQE_OPCODE_MASK);
                break;
-       };
+       }
 }
 
 static void ocrdma_set_cqe_status_flushed(struct ocrdma_qp *qp,
index 3591855cc5b54caeca1e9675757a43579537b4be..6df23502059a44eccd32c725477cd5fee1ef2923 100644 (file)
@@ -594,7 +594,7 @@ isert_connect_release(struct isert_conn *isert_conn)
 
        pr_debug("Entering isert_connect_release(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
 
-       if (device->use_frwr)
+       if (device && device->use_frwr)
                isert_conn_free_frwr_pool(isert_conn);
 
        if (isert_conn->conn_qp) {
index 785675a56a10f8117b052ff06bf4e9b462e720b5..9009469502307d720483282f46625b8ad919caa9 100644 (file)
@@ -88,7 +88,7 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
                        pr_warn("Device scope bus [%d] not found\n", scope->bus);
                        break;
                }
-               pdev = pci_get_slot(bus, PCI_DEVFN(path->dev, path->fn));
+               pdev = pci_get_slot(bus, PCI_DEVFN(path->device, path->function));
                if (!pdev) {
                        /* warning will be printed below */
                        break;
@@ -99,7 +99,7 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
        }
        if (!pdev) {
                pr_warn("Device scope device [%04x:%02x:%02x.%02x] not found\n",
-                       segment, scope->bus, path->dev, path->fn);
+                       segment, scope->bus, path->device, path->function);
                *dev = NULL;
                return 0;
        }
index f71673dbb23da174cfd8045b0782ce38cc4b4f3a..ab86902fd9fff49e1d72f6cb81574d7c9aac6f22 100644 (file)
@@ -686,12 +686,12 @@ static void ir_parse_one_hpet_scope(struct acpi_dmar_device_scope *scope,
                 * Access PCI directly due to the PCI
                 * subsystem isn't initialized yet.
                 */
-               bus = read_pci_config_byte(bus, path->dev, path->fn,
+               bus = read_pci_config_byte(bus, path->device, path->function,
                                           PCI_SECONDARY_BUS);
                path++;
        }
        ir_hpet[ir_hpet_num].bus   = bus;
-       ir_hpet[ir_hpet_num].devfn = PCI_DEVFN(path->dev, path->fn);
+       ir_hpet[ir_hpet_num].devfn = PCI_DEVFN(path->device, path->function);
        ir_hpet[ir_hpet_num].iommu = iommu;
        ir_hpet[ir_hpet_num].id    = scope->enumeration_id;
        ir_hpet_num++;
@@ -714,13 +714,13 @@ static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope,
                 * Access PCI directly due to the PCI
                 * subsystem isn't initialized yet.
                 */
-               bus = read_pci_config_byte(bus, path->dev, path->fn,
+               bus = read_pci_config_byte(bus, path->device, path->function,
                                           PCI_SECONDARY_BUS);
                path++;
        }
 
        ir_ioapic[ir_ioapic_num].bus   = bus;
-       ir_ioapic[ir_ioapic_num].devfn = PCI_DEVFN(path->dev, path->fn);
+       ir_ioapic[ir_ioapic_num].devfn = PCI_DEVFN(path->device, path->function);
        ir_ioapic[ir_ioapic_num].iommu = iommu;
        ir_ioapic[ir_ioapic_num].id    = scope->enumeration_id;
        ir_ioapic_num++;
index b6a74bcbb08f8800bae2aa57888498a46eb85f69..2a7f0dd6abab4d6bb21ba028b5b3a25721080a2c 100644 (file)
@@ -1000,7 +1000,7 @@ static void request_write(struct cached_dev *dc, struct search *s)
 
                if (bio->bi_rw & REQ_FLUSH) {
                        /* Also need to send a flush to the backing device */
-                       struct bio *flush = bio_alloc_bioset(0, GFP_NOIO,
+                       struct bio *flush = bio_alloc_bioset(GFP_NOIO, 0,
                                                             dc->disk.bio_split);
 
                        flush->bi_rw    = WRITE_FLUSH;
index 4caa8e6d59d7968584e23a9187bc07f8c81df321..2d2b1b7588d7e476b7fc814a63c82bad2edb1ed6 100644 (file)
@@ -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;
index adf4d7e1d5e15233a67e7108dc24b8a7bb6efeb1..561a65f82e26af05c8210f94b49367b6fa51e55b 100644 (file)
@@ -8111,6 +8111,7 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
        u64 *p;
        int lo, hi;
        int rv = 1;
+       unsigned long flags;
 
        if (bb->shift < 0)
                /* badblocks are disabled */
@@ -8125,7 +8126,7 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
                sectors = next - s;
        }
 
-       write_seqlock_irq(&bb->lock);
+       write_seqlock_irqsave(&bb->lock, flags);
 
        p = bb->page;
        lo = 0;
@@ -8241,7 +8242,7 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
        bb->changed = 1;
        if (!acknowledged)
                bb->unacked_exist = 1;
-       write_sequnlock_irq(&bb->lock);
+       write_sequnlock_irqrestore(&bb->lock, flags);
 
        return rv;
 }
index d60412c7f9952a350e85002f6578bd66ee416a44..aacf6bf352d87978a15633b05a0d51d3579ce16d 100644 (file)
@@ -1479,6 +1479,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++;
index df7b0a06b0ea2d820aec6ad5a752a13bb64e13e8..73dc8a377522e19af92c9bed26519a479f36dbea 100644 (file)
@@ -1782,6 +1782,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++;
index 7ff4f252ca1a42943252a9e19b975da5b2f8ce9b..f8b9068439267a3539d671e6e59ceb0b47b90547 100644 (file)
@@ -778,6 +778,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
                        bi->bi_io_vec[0].bv_offset = 0;
                        bi->bi_size = STRIPE_SIZE;
+                       /*
+                        * If this is discard request, set bi_vcnt 0. We don't
+                        * want to confuse SCSI because SCSI will replace payload
+                        */
+                       if (rw & REQ_DISCARD)
+                               bi->bi_vcnt = 0;
                        if (rrdev)
                                set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
 
@@ -816,6 +822,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        rbi->bi_io_vec[0].bv_len = STRIPE_SIZE;
                        rbi->bi_io_vec[0].bv_offset = 0;
                        rbi->bi_size = STRIPE_SIZE;
+                       /*
+                        * If this is discard request, set bi_vcnt 0. We don't
+                        * want to confuse SCSI because SCSI will replace payload
+                        */
+                       if (rw & REQ_DISCARD)
+                               rbi->bi_vcnt = 0;
                        if (conf->mddev->gendisk)
                                trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
                                                      rbi, disk_devt(conf->mddev->gendisk),
@@ -2910,6 +2922,14 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                }
                /* now that discard is done we can proceed with any sync */
                clear_bit(STRIPE_DISCARD, &sh->state);
+               /*
+                * SCSI discard will change some bio fields and the stripe has
+                * no updated data, so remove it from hash list and the stripe
+                * will be reinitialized
+                */
+               spin_lock_irq(&conf->device_lock);
+               remove_hash(sh);
+               spin_unlock_irq(&conf->device_lock);
                if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
                        set_bit(STRIPE_HANDLE, &sh->state);
 
index 2521f7e23018f70a33a9ad43e1bb26e79e037ab8..e79749cfec814b75f0ac84d2f5ad881399a79a75 100644 (file)
@@ -912,14 +912,8 @@ static int tda10071_init(struct dvb_frontend *fe)
                { 0xd5, 0x03, 0x03 },
        };
 
-       /* firmware status */
-       ret = tda10071_rd_reg(priv, 0x51, &tmp);
-       if (ret)
-               goto error;
-
-       if (!tmp) {
+       if (priv->warm) {
                /* warm state - wake up device from sleep */
-               priv->warm = 1;
 
                for (i = 0; i < ARRAY_SIZE(tab); i++) {
                        ret = tda10071_wr_reg_mask(priv, tab[i].reg,
@@ -937,7 +931,6 @@ static int tda10071_init(struct dvb_frontend *fe)
                        goto error;
        } else {
                /* cold state - try to download firmware */
-               priv->warm = 0;
 
                /* request the firmware, this will block and timeout */
                ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
index bb0c99d7a4f169d25c642b5143efcf36c087c397..b06a7e54ee0d25100f1f01abcac7ddc70e8489df 100644 (file)
@@ -628,16 +628,13 @@ static int ad9389b_s_stream(struct v4l2_subdev *sd, int enable)
 
 static const struct v4l2_dv_timings_cap ad9389b_timings_cap = {
        .type = V4L2_DV_BT_656_1120,
-       .bt = {
-               .max_width = 1920,
-               .max_height = 1200,
-               .min_pixelclock = 25000000,
-               .max_pixelclock = 170000000,
-               .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+       /* keep this initialization for compatibility with GCC < 4.4.6 */
+       .reserved = { 0 },
+       V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000,
+               V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
                        V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
-               .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
-                       V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM,
-       },
+               V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
+               V4L2_DV_BT_CAP_CUSTOM)
 };
 
 static int ad9389b_s_dv_timings(struct v4l2_subdev *sd,
index 7a576097471f352939cc703d6fbac368cf02f532..7c8d971f1f613206b1821bfa023ea5326ba48028 100644 (file)
@@ -119,16 +119,14 @@ static int adv7511_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
 
 static const struct v4l2_dv_timings_cap adv7511_timings_cap = {
        .type = V4L2_DV_BT_656_1120,
-       .bt = {
-               .max_width = ADV7511_MAX_WIDTH,
-               .max_height = ADV7511_MAX_HEIGHT,
-               .min_pixelclock = ADV7511_MIN_PIXELCLOCK,
-               .max_pixelclock = ADV7511_MAX_PIXELCLOCK,
-               .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+       /* keep this initialization for compatibility with GCC < 4.4.6 */
+       .reserved = { 0 },
+       V4L2_INIT_BT_TIMINGS(0, ADV7511_MAX_WIDTH, 0, ADV7511_MAX_HEIGHT,
+               ADV7511_MIN_PIXELCLOCK, ADV7511_MAX_PIXELCLOCK,
+               V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
                        V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
-               .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
-                       V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM,
-       },
+               V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
+                       V4L2_DV_BT_CAP_CUSTOM)
 };
 
 static inline struct adv7511_state *get_adv7511_state(struct v4l2_subdev *sd)
@@ -1126,6 +1124,7 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
        state->i2c_edid = i2c_new_dummy(client->adapter, state->i2c_edid_addr >> 1);
        if (state->i2c_edid == NULL) {
                v4l2_err(sd, "failed to register edid i2c client\n");
+               err = -ENOMEM;
                goto err_entity;
        }
 
@@ -1133,6 +1132,7 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
        state->work_queue = create_singlethread_workqueue(sd->name);
        if (state->work_queue == NULL) {
                v4l2_err(sd, "could not create workqueue\n");
+               err = -ENOMEM;
                goto err_unreg_cec;
        }
 
index d1748901337cd08be083e9a6a7d35958f6aeca7b..22f729d66a9696522e18d42932ae383594cbca5f 100644 (file)
@@ -546,30 +546,24 @@ static inline bool is_digital_input(struct v4l2_subdev *sd)
 
 static const struct v4l2_dv_timings_cap adv7842_timings_cap_analog = {
        .type = V4L2_DV_BT_656_1120,
-       .bt = {
-               .max_width = 1920,
-               .max_height = 1200,
-               .min_pixelclock = 25000000,
-               .max_pixelclock = 170000000,
-               .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+       /* keep this initialization for compatibility with GCC < 4.4.6 */
+       .reserved = { 0 },
+       V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000,
+               V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
                        V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
-               .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
-                       V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM,
-       },
+               V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
+                       V4L2_DV_BT_CAP_CUSTOM)
 };
 
 static const struct v4l2_dv_timings_cap adv7842_timings_cap_digital = {
        .type = V4L2_DV_BT_656_1120,
-       .bt = {
-               .max_width = 1920,
-               .max_height = 1200,
-               .min_pixelclock = 25000000,
-               .max_pixelclock = 225000000,
-               .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+       /* keep this initialization for compatibility with GCC < 4.4.6 */
+       .reserved = { 0 },
+       V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 225000000,
+               V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
                        V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
-               .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
-                       V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM,
-       },
+               V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
+                       V4L2_DV_BT_CAP_CUSTOM)
 };
 
 static inline const struct v4l2_dv_timings_cap *
index a58a8f663ffbb3a028540fc8763ce5521e55e828..d9f65d7e3e58b64dea5b930d5800e20921fd8778 100644 (file)
@@ -46,14 +46,10 @@ struct ths8200_state {
 
 static const struct v4l2_dv_timings_cap ths8200_timings_cap = {
        .type = V4L2_DV_BT_656_1120,
-       .bt = {
-               .max_width = 1920,
-               .max_height = 1080,
-               .min_pixelclock = 25000000,
-               .max_pixelclock = 148500000,
-               .standards = V4L2_DV_BT_STD_CEA861,
-               .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE,
-       },
+       /* keep this initialization for compatibility with GCC < 4.4.6 */
+       .reserved = { 0 },
+       V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1080, 25000000, 148500000,
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_BT_CAP_PROGRESSIVE)
 };
 
 static inline struct ths8200_state *to_state(struct v4l2_subdev *sd)
index e12bbd8c3f0b8da63f8418e6a00bc803f883963a..fb60da85bc2c039e3ab7a6db22fa1182c4e977bb 100644 (file)
@@ -1455,6 +1455,7 @@ static int video_release(struct file *file)
 
        /* stop video capture */
        if (res_check(fh, RESOURCE_VIDEO)) {
+               pm_qos_remove_request(&dev->qos_request);
                videobuf_streamoff(&fh->cap);
                res_free(dev,fh,RESOURCE_VIDEO);
        }
index 15d23968d1de8392a61deb4a4bcd2b0489ce689d..9b88a46010072fbe3b4aeefa46bbc8ee0f04ea7e 100644 (file)
@@ -1423,6 +1423,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
        jpeg->vfd_decoder->release      = video_device_release;
        jpeg->vfd_decoder->lock         = &jpeg->lock;
        jpeg->vfd_decoder->v4l2_dev     = &jpeg->v4l2_dev;
+       jpeg->vfd_decoder->vfl_dir      = VFL_DIR_M2M;
 
        ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
        if (ret) {
index 7a9c5e9329f2655327c2c3d6a22e660a11728d38..4f30341dc2ab239ed4b736292c1b7ccb6d208b5e 100644 (file)
@@ -776,7 +776,7 @@ static int sh_vou_try_fmt_vid_out(struct file *file, void *priv,
        v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 1,
                              &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0);
 
-       for (i = 0; ARRAY_SIZE(vou_fmt); i++)
+       for (i = 0; i < ARRAY_SIZE(vou_fmt); i++)
                if (vou_fmt[i].pfmt == pix->pixelformat)
                        return 0;
 
index 8f9f6211c52e1e052f0ce4db84b3bcd951260d72..f975b70086922c866dc415f9eca4506aef3c19ea 100644 (file)
@@ -266,7 +266,6 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
        struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
        struct idmac_video_param *video = &ichan->params.video;
        const struct soc_mbus_pixelfmt *host_fmt = icd->current_fmt->host_fmt;
-       unsigned long flags;
        dma_cookie_t cookie;
        size_t new_size;
 
@@ -328,7 +327,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
                memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
 #endif
 
-       spin_lock_irqsave(&mx3_cam->lock, flags);
+       spin_lock_irq(&mx3_cam->lock);
        list_add_tail(&buf->queue, &mx3_cam->capture);
 
        if (!mx3_cam->active)
@@ -351,7 +350,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
        if (mx3_cam->active == buf)
                mx3_cam->active = NULL;
 
-       spin_unlock_irqrestore(&mx3_cam->lock, flags);
+       spin_unlock_irq(&mx3_cam->lock);
 error:
        vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 }
index ad9309da4a9102779f67cbd999aee72db465c51d..6c96e4898777f29f5c9ae4457d488e9424b32f2b 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include "e4000_priv.h"
+#include <linux/math64.h>
 
 /* write multiple registers */
 static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
@@ -233,7 +234,7 @@ static int e4000_set_params(struct dvb_frontend *fe)
         * or more.
         */
        f_vco = c->frequency * e4000_pll_lut[i].mul;
-       sigma_delta = 0x10000UL * (f_vco % priv->cfg->clock) / priv->cfg->clock;
+       sigma_delta = div_u64(0x10000ULL * (f_vco % priv->cfg->clock), priv->cfg->clock);
        buf[0] = f_vco / priv->cfg->clock;
        buf[1] = (sigma_delta >> 0) & 0xff;
        buf[2] = (sigma_delta >> 8) & 0xff;
index c43c8d32be40c30e99be96d6fedd5a8fdd3832d9..be77482c30704a5b81615199f563770c0147ec0f 100644 (file)
@@ -111,6 +111,13 @@ static const struct dmi_system_id stk_upside_down_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "F3JC")
                }
        },
+       {
+               .ident = "T12Rg-H",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HCL Infosystems Limited"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T12Rg-H")
+               }
+       },
        {}
 };
 
index 81695d48c13ebc5ceeb5560a0787aae94a516766..c3bb2502225bc6c8932d4aca36de62f1fd1daee2 100644 (file)
@@ -2090,6 +2090,15 @@ static struct usb_device_id uvc_ids[] = {
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0,
          .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Microsoft Lifecam NX-3000 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x045e,
+         .idProduct            = 0x0721,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_DEF },
        /* Microsoft Lifecam VX-7000 */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2174,6 +2183,15 @@ static struct usb_device_id uvc_ids[] = {
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0,
          .driver_info          = UVC_QUIRK_PROBE_DEF },
+       /* Dell SP2008WFP Monitor */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x05a9,
+         .idProduct            = 0x2641,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_DEF },
        /* Dell Alienware X51 */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
index 594c75eab5a5d84b42d20ce6e5ba014fe91c0972..de0e87f0b2c3a833f113121709b9a496d29ef1f3 100644 (file)
@@ -353,7 +353,9 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 
                        if (b->m.planes[plane].bytesused > length)
                                return -EINVAL;
-                       if (b->m.planes[plane].data_offset >=
+
+                       if (b->m.planes[plane].data_offset > 0 &&
+                           b->m.planes[plane].data_offset >=
                            b->m.planes[plane].bytesused)
                                return -EINVAL;
                }
index fd56f25632018fde92f1acefc4d284e6a47d6dba..646f08f4f504c05ae37dd95cbc1fe8333705e658 100644 (file)
@@ -423,6 +423,39 @@ static inline int vma_is_io(struct vm_area_struct *vma)
        return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
 }
 
+static int vb2_dc_get_user_pfn(unsigned long start, int n_pages,
+       struct vm_area_struct *vma, unsigned long *res)
+{
+       unsigned long pfn, start_pfn, prev_pfn;
+       unsigned int i;
+       int ret;
+
+       if (!vma_is_io(vma))
+               return -EFAULT;
+
+       ret = follow_pfn(vma, start, &pfn);
+       if (ret)
+               return ret;
+
+       start_pfn = pfn;
+       start += PAGE_SIZE;
+
+       for (i = 1; i < n_pages; ++i, start += PAGE_SIZE) {
+               prev_pfn = pfn;
+               ret = follow_pfn(vma, start, &pfn);
+
+               if (ret) {
+                       pr_err("no page for address %lu\n", start);
+                       return ret;
+               }
+               if (pfn != prev_pfn + 1)
+                       return -EINVAL;
+       }
+
+       *res = start_pfn;
+       return 0;
+}
+
 static int vb2_dc_get_user_pages(unsigned long start, struct page **pages,
        int n_pages, struct vm_area_struct *vma, int write)
 {
@@ -433,6 +466,9 @@ static int vb2_dc_get_user_pages(unsigned long start, struct page **pages,
                        unsigned long pfn;
                        int ret = follow_pfn(vma, start, &pfn);
 
+                       if (!pfn_valid(pfn))
+                               return -EINVAL;
+
                        if (ret) {
                                pr_err("no page for address %lu\n", start);
                                return ret;
@@ -468,16 +504,49 @@ static void vb2_dc_put_userptr(void *buf_priv)
        struct vb2_dc_buf *buf = buf_priv;
        struct sg_table *sgt = buf->dma_sgt;
 
-       dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
-       if (!vma_is_io(buf->vma))
-               vb2_dc_sgt_foreach_page(sgt, vb2_dc_put_dirty_page);
+       if (sgt) {
+               dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
+               if (!vma_is_io(buf->vma))
+                       vb2_dc_sgt_foreach_page(sgt, vb2_dc_put_dirty_page);
 
-       sg_free_table(sgt);
-       kfree(sgt);
+               sg_free_table(sgt);
+               kfree(sgt);
+       }
        vb2_put_vma(buf->vma);
        kfree(buf);
 }
 
+/*
+ * For some kind of reserved memory there might be no struct page available,
+ * so all that can be done to support such 'pages' is to try to convert
+ * pfn to dma address or at the last resort just assume that
+ * dma address == physical address (like it has been assumed in earlier version
+ * of videobuf2-dma-contig
+ */
+
+#ifdef __arch_pfn_to_dma
+static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long pfn)
+{
+       return (dma_addr_t)__arch_pfn_to_dma(dev, pfn);
+}
+#elif defined(__pfn_to_bus)
+static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long pfn)
+{
+       return (dma_addr_t)__pfn_to_bus(pfn);
+}
+#elif defined(__pfn_to_phys)
+static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long pfn)
+{
+       return (dma_addr_t)__pfn_to_phys(pfn);
+}
+#else
+static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long pfn)
+{
+       /* really, we cannot do anything better at this point */
+       return (dma_addr_t)(pfn) << PAGE_SHIFT;
+}
+#endif
+
 static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
        unsigned long size, int write)
 {
@@ -548,6 +617,14 @@ static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
        /* extract page list from userspace mapping */
        ret = vb2_dc_get_user_pages(start, pages, n_pages, vma, write);
        if (ret) {
+               unsigned long pfn;
+               if (vb2_dc_get_user_pfn(start, n_pages, vma, &pfn) == 0) {
+                       buf->dma_addr = vb2_dc_pfn_to_dma(buf->dev, pfn);
+                       buf->size = size;
+                       kfree(pages);
+                       return buf;
+               }
+
                pr_err("failed to get user pages\n");
                goto fail_vma;
        }
index 59ab0692f0b97f58fef750b6f5e29c11b6fa0367..a9830ff8e3f38443a69d2e1d599c8dc45e136ff1 100644 (file)
@@ -349,7 +349,7 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
 
 int common_nfc_set_geometry(struct gpmi_nand_data *this)
 {
-       return set_geometry_by_ecc_info(this) ? 0 : legacy_set_geometry(this);
+       return legacy_set_geometry(this);
 }
 
 struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
index dd03dfdfb0d65e0ded1b0a124221663b586482b5..c28d4e29af1a549dfd0c59fd20870da3a7a676f9 100644 (file)
@@ -1320,7 +1320,12 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
        for (cs = 0; cs < pdata->num_cs; cs++) {
                struct mtd_info *mtd = info->host[cs]->mtd;
 
-               mtd->name = pdev->name;
+               /*
+                * The mtd name matches the one used in 'mtdparts' kernel
+                * parameter. This name cannot be changed or otherwise
+                * user's mtd partitions configuration would get broken.
+                */
+               mtd->name = "pxa3xx_nand-0";
                info->cs = cs;
                ret = pxa3xx_nand_scan(mtd);
                if (ret) {
index 3b1ff6148702beb3818fbae7da2b0206f7d1c7f4..693d8ffe465311b6aab964c25304f4bbdd04cdf0 100644 (file)
@@ -1405,10 +1405,10 @@ static int at91_can_remove(struct platform_device *pdev)
 
 static const struct platform_device_id at91_can_id_table[] = {
        {
-               .name = "at91_can",
+               .name = "at91sam9x5_can",
                .driver_data = (kernel_ulong_t)&at91_at91sam9x5_data,
        }, {
-               .name = "at91sam9x5_can",
+               .name = "at91_can",
                .driver_data = (kernel_ulong_t)&at91_at91sam9263_data,
        }, {
                /* sentinel */
index f9cba4123c663084b66c2dbdaac5885a579278fd..1870c4731a572d193bef5e6dc0b7364e5f1751ed 100644 (file)
@@ -705,14 +705,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;
 }
index 3f21142138b79868a0f18fa7d246432e99d96192..8f5ce747feb57a093dc78e4a24bd9742b5ea99fc 100644 (file)
@@ -62,7 +62,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)
@@ -735,9 +735,11 @@ static int flexcan_chip_start(struct net_device *dev)
         *
         */
        reg_mcr = flexcan_read(&regs->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, &regs->mcr);
 
@@ -771,6 +773,10 @@ static int flexcan_chip_start(struct net_device *dev)
        netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
        flexcan_write(reg_ctrl, &regs->ctrl);
 
+       /* Abort any pending TX, mark Mailbox as INACTIVE */
+       flexcan_write(FLEXCAN_MB_CNT_CODE(0x4),
+                     &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+
        /* acceptance mask/acceptance code (accept everything) */
        flexcan_write(0x0, &regs->rxgmask);
        flexcan_write(0x0, &regs->rx14mask);
@@ -979,9 +985,9 @@ static void unregister_flexcandev(struct net_device *dev)
 }
 
 static const struct of_device_id flexcan_of_match[] = {
-       { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
-       { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
        { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
+       { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
+       { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
        { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, flexcan_of_match);
index 97b3d32a98bd010ab1a1327ef7382e5bd64139b8..c5e375ddd6c09c137232ecfc8264439bc614e08e 100644 (file)
@@ -1197,8 +1197,9 @@ union cdu_context {
 /* TM (timers) host DB constants */
 #define TM_ILT_PAGE_SZ_HW      0
 #define TM_ILT_PAGE_SZ         (4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
-/* #define TM_CONN_NUM         (CNIC_STARTING_CID+CNIC_ISCSI_CXT_MAX) */
-#define TM_CONN_NUM            1024
+#define TM_CONN_NUM            (BNX2X_FIRST_VF_CID + \
+                                BNX2X_VF_CIDS + \
+                                CNIC_ISCSI_CID_MAX)
 #define TM_ILT_SZ              (8 * TM_CONN_NUM)
 #define TM_ILT_LINES           DIV_ROUND_UP(TM_ILT_SZ, TM_ILT_PAGE_SZ)
 
@@ -1527,7 +1528,6 @@ struct bnx2x {
 #define PCI_32BIT_FLAG                 (1 << 1)
 #define ONE_PORT_FLAG                  (1 << 2)
 #define NO_WOL_FLAG                    (1 << 3)
-#define USING_DAC_FLAG                 (1 << 4)
 #define USING_MSIX_FLAG                        (1 << 5)
 #define USING_MSI_FLAG                 (1 << 6)
 #define DISABLE_MSI_FLAG               (1 << 7)
@@ -1621,7 +1621,7 @@ struct bnx2x {
        u16                     rx_ticks_int;
        u16                     rx_ticks;
 /* Maximal coalescing timeout in us */
-#define BNX2X_MAX_COALESCE_TOUT                (0xf0*12)
+#define BNX2X_MAX_COALESCE_TOUT                (0xff*BNX2X_BTR)
 
        u32                     lin_cnt;
 
@@ -2072,7 +2072,8 @@ u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
 
 void bnx2x_prep_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae,
                               u8 src_type, u8 dst_type);
-int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae);
+int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae,
+                              u32 *comp);
 
 /* FLR related routines */
 u32 bnx2x_flr_clnup_poll_count(struct bnx2x *bp);
@@ -2498,4 +2499,8 @@ enum bnx2x_pci_bus_speed {
 };
 
 void bnx2x_set_local_cmng(struct bnx2x *bp);
+
+#define MCPR_SCRATCH_BASE(bp) \
+       (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
+
 #endif /* bnx2x.h */
index e66beff2704d19241695fe5028e33efb3ca95519..4ab4c89c60cd1eeca873fad127d2702ab2a1a0d1 100644 (file)
@@ -681,6 +681,7 @@ static void bnx2x_gro_receive(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                }
        }
 #endif
+       skb_record_rx_queue(skb, fp->rx_queue);
        napi_gro_receive(&fp->napi, skb);
 }
 
index 324de5f05332e78aa6c108d23891105880ee5bd8..e8efa1c93ffecdefde5183e91cbf67d7286928af 100644 (file)
@@ -891,17 +891,8 @@ static void bnx2x_get_regs(struct net_device *dev,
         * will re-enable parity attentions right after the dump.
         */
 
-       /* Disable parity on path 0 */
-       bnx2x_pretend_func(bp, 0);
        bnx2x_disable_blocks_parity(bp);
 
-       /* Disable parity on path 1 */
-       bnx2x_pretend_func(bp, 1);
-       bnx2x_disable_blocks_parity(bp);
-
-       /* Return to current function */
-       bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
-
        dump_hdr.header_size = (sizeof(struct dump_header) / 4) - 1;
        dump_hdr.preset = DUMP_ALL_PRESETS;
        dump_hdr.version = BNX2X_DUMP_VERSION;
@@ -928,18 +919,9 @@ static void bnx2x_get_regs(struct net_device *dev,
        /* Actually read the registers */
        __bnx2x_get_regs(bp, p);
 
-       /* Re-enable parity attentions on path 0 */
-       bnx2x_pretend_func(bp, 0);
+       /* Re-enable parity attentions */
        bnx2x_clear_blocks_parity(bp);
        bnx2x_enable_blocks_parity(bp);
-
-       /* Re-enable parity attentions on path 1 */
-       bnx2x_pretend_func(bp, 1);
-       bnx2x_clear_blocks_parity(bp);
-       bnx2x_enable_blocks_parity(bp);
-
-       /* Return to current function */
-       bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
 }
 
 static int bnx2x_get_preset_regs_len(struct net_device *dev, u32 preset)
@@ -993,17 +975,8 @@ static int bnx2x_get_dump_data(struct net_device *dev,
         * will re-enable parity attentions right after the dump.
         */
 
-       /* Disable parity on path 0 */
-       bnx2x_pretend_func(bp, 0);
        bnx2x_disable_blocks_parity(bp);
 
-       /* Disable parity on path 1 */
-       bnx2x_pretend_func(bp, 1);
-       bnx2x_disable_blocks_parity(bp);
-
-       /* Return to current function */
-       bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
-
        dump_hdr.header_size = (sizeof(struct dump_header) / 4) - 1;
        dump_hdr.preset = bp->dump_preset_idx;
        dump_hdr.version = BNX2X_DUMP_VERSION;
@@ -1032,19 +1005,10 @@ static int bnx2x_get_dump_data(struct net_device *dev,
        /* Actually read the registers */
        __bnx2x_get_preset_regs(bp, p, dump_hdr.preset);
 
-       /* Re-enable parity attentions on path 0 */
-       bnx2x_pretend_func(bp, 0);
+       /* Re-enable parity attentions */
        bnx2x_clear_blocks_parity(bp);
        bnx2x_enable_blocks_parity(bp);
 
-       /* Re-enable parity attentions on path 1 */
-       bnx2x_pretend_func(bp, 1);
-       bnx2x_clear_blocks_parity(bp);
-       bnx2x_enable_blocks_parity(bp);
-
-       /* Return to current function */
-       bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
-
        return 0;
 }
 
index 76df015f486ad9d1653efccde3538dbb47263849..c2dfea7968f452defdca6fd4b1ea68758381038e 100644 (file)
@@ -640,23 +640,35 @@ static const struct {
  * [30] MCP Latched ump_tx_parity
  * [31] MCP Latched scpad_parity
  */
-#define MISC_AEU_ENABLE_MCP_PRTY_BITS  \
+#define MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS      \
        (AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \
         AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \
-        AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \
+        AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY)
+
+#define MISC_AEU_ENABLE_MCP_PRTY_BITS  \
+       (MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS | \
         AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY)
 
 /* Below registers control the MCP parity attention output. When
  * MISC_AEU_ENABLE_MCP_PRTY_BITS are set - attentions are
  * enabled, when cleared - disabled.
  */
-static const u32 mcp_attn_ctl_regs[] = {
-       MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0,
-       MISC_REG_AEU_ENABLE4_NIG_0,
-       MISC_REG_AEU_ENABLE4_PXP_0,
-       MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0,
-       MISC_REG_AEU_ENABLE4_NIG_1,
-       MISC_REG_AEU_ENABLE4_PXP_1
+static const struct {
+       u32 addr;
+       u32 bits;
+} mcp_attn_ctl_regs[] = {
+       { MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0,
+               MISC_AEU_ENABLE_MCP_PRTY_BITS },
+       { MISC_REG_AEU_ENABLE4_NIG_0,
+               MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
+       { MISC_REG_AEU_ENABLE4_PXP_0,
+               MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
+       { MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0,
+               MISC_AEU_ENABLE_MCP_PRTY_BITS },
+       { MISC_REG_AEU_ENABLE4_NIG_1,
+               MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
+       { MISC_REG_AEU_ENABLE4_PXP_1,
+               MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS }
 };
 
 static inline void bnx2x_set_mcp_parity(struct bnx2x *bp, u8 enable)
@@ -665,14 +677,14 @@ static inline void bnx2x_set_mcp_parity(struct bnx2x *bp, u8 enable)
        u32 reg_val;
 
        for (i = 0; i < ARRAY_SIZE(mcp_attn_ctl_regs); i++) {
-               reg_val = REG_RD(bp, mcp_attn_ctl_regs[i]);
+               reg_val = REG_RD(bp, mcp_attn_ctl_regs[i].addr);
 
                if (enable)
-                       reg_val |= MISC_AEU_ENABLE_MCP_PRTY_BITS;
+                       reg_val |= mcp_attn_ctl_regs[i].bits;
                else
-                       reg_val &= ~MISC_AEU_ENABLE_MCP_PRTY_BITS;
+                       reg_val &= ~mcp_attn_ctl_regs[i].bits;
 
-               REG_WR(bp, mcp_attn_ctl_regs[i], reg_val);
+               REG_WR(bp, mcp_attn_ctl_regs[i].addr, reg_val);
        }
 }
 
index 82b658d8c04c47c52931b5138375cd38f0ca519a..b42f89ce02ef5997fa46e57a9521b0873968d7b7 100644 (file)
@@ -503,9 +503,9 @@ void bnx2x_prep_dmae_with_comp(struct bnx2x *bp,
 }
 
 /* issue a dmae command over the init-channel and wait for completion */
-int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae)
+int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae,
+                              u32 *comp)
 {
-       u32 *wb_comp = bnx2x_sp(bp, wb_comp);
        int cnt = CHIP_REV_IS_SLOW(bp) ? (400000) : 4000;
        int rc = 0;
 
@@ -518,14 +518,14 @@ int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae)
        spin_lock_bh(&bp->dmae_lock);
 
        /* reset completion */
-       *wb_comp = 0;
+       *comp = 0;
 
        /* post the command on the channel used for initializations */
        bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
 
        /* wait for completion */
        udelay(5);
-       while ((*wb_comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) {
+       while ((*comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) {
 
                if (!cnt ||
                    (bp->recovery_state != BNX2X_RECOVERY_DONE &&
@@ -537,7 +537,7 @@ int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae)
                cnt--;
                udelay(50);
        }
-       if (*wb_comp & DMAE_PCI_ERR_FLAG) {
+       if (*comp & DMAE_PCI_ERR_FLAG) {
                BNX2X_ERR("DMAE PCI error!\n");
                rc = DMAE_PCI_ERROR;
        }
@@ -574,7 +574,7 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
        dmae.len = len32;
 
        /* issue the command and wait for completion */
-       rc = bnx2x_issue_dmae_with_comp(bp, &dmae);
+       rc = bnx2x_issue_dmae_with_comp(bp, &dmae, bnx2x_sp(bp, wb_comp));
        if (rc) {
                BNX2X_ERR("DMAE returned failure %d\n", rc);
                bnx2x_panic();
@@ -611,7 +611,7 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
        dmae.len = len32;
 
        /* issue the command and wait for completion */
-       rc = bnx2x_issue_dmae_with_comp(bp, &dmae);
+       rc = bnx2x_issue_dmae_with_comp(bp, &dmae, bnx2x_sp(bp, wb_comp));
        if (rc) {
                BNX2X_ERR("DMAE returned failure %d\n", rc);
                bnx2x_panic();
@@ -751,6 +751,10 @@ static int bnx2x_mc_assert(struct bnx2x *bp)
        return rc;
 }
 
+#define MCPR_TRACE_BUFFER_SIZE (0x800)
+#define SCRATCH_BUFFER_SIZE(bp)        \
+       (CHIP_IS_E1(bp) ? 0x10000 : (CHIP_IS_E1H(bp) ? 0x20000 : 0x28000))
+
 void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl)
 {
        u32 addr, val;
@@ -775,7 +779,17 @@ void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl)
                trace_shmem_base = bp->common.shmem_base;
        else
                trace_shmem_base = SHMEM2_RD(bp, other_shmem_base_addr);
-       addr = trace_shmem_base - 0x800;
+
+       /* sanity */
+       if (trace_shmem_base < MCPR_SCRATCH_BASE(bp) + MCPR_TRACE_BUFFER_SIZE ||
+           trace_shmem_base >= MCPR_SCRATCH_BASE(bp) +
+                               SCRATCH_BUFFER_SIZE(bp)) {
+               BNX2X_ERR("Unable to dump trace buffer (mark %x)\n",
+                         trace_shmem_base);
+               return;
+       }
+
+       addr = trace_shmem_base - MCPR_TRACE_BUFFER_SIZE;
 
        /* validate TRCB signature */
        mark = REG_RD(bp, addr);
@@ -787,14 +801,17 @@ void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl)
        /* read cyclic buffer pointer */
        addr += 4;
        mark = REG_RD(bp, addr);
-       mark = (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
-                       + ((mark + 0x3) & ~0x3) - 0x08000000;
+       mark = MCPR_SCRATCH_BASE(bp) + ((mark + 0x3) & ~0x3) - 0x08000000;
+       if (mark >= trace_shmem_base || mark < addr + 4) {
+               BNX2X_ERR("Mark doesn't fall inside Trace Buffer\n");
+               return;
+       }
        printk("%s" "begin fw dump (mark 0x%x)\n", lvl, mark);
 
        printk("%s", lvl);
 
        /* dump buffer after the mark */
-       for (offset = mark; offset <= trace_shmem_base; offset += 0x8*4) {
+       for (offset = mark; offset < trace_shmem_base; offset += 0x8*4) {
                for (word = 0; word < 8; word++)
                        data[word] = htonl(REG_RD(bp, offset + 4*word));
                data[8] = 0x0;
@@ -4280,65 +4297,60 @@ static void _print_next_block(int idx, const char *blk)
        pr_cont("%s%s", idx ? ", " : "", blk);
 }
 
-static int bnx2x_check_blocks_with_parity0(struct bnx2x *bp, u32 sig,
-                                           int par_num, bool print)
+static bool bnx2x_check_blocks_with_parity0(struct bnx2x *bp, u32 sig,
+                                           int *par_num, bool print)
 {
-       int i = 0;
-       u32 cur_bit = 0;
+       u32 cur_bit;
+       bool res;
+       int i;
+
+       res = false;
+
        for (i = 0; sig; i++) {
-               cur_bit = ((u32)0x1 << i);
+               cur_bit = (0x1UL << i);
                if (sig & cur_bit) {
-                       switch (cur_bit) {
-                       case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "BRB");
+                       res |= true; /* Each bit is real error! */
+
+                       if (print) {
+                               switch (cur_bit) {
+                               case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "BRB");
                                        _print_parity(bp,
                                                      BRB1_REG_BRB1_PRTY_STS);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "PARSER");
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR:
+                                       _print_next_block((*par_num)++,
+                                                         "PARSER");
                                        _print_parity(bp, PRS_REG_PRS_PRTY_STS);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "TSDM");
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "TSDM");
                                        _print_parity(bp,
                                                      TSDM_REG_TSDM_PRTY_STS);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++,
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR:
+                                       _print_next_block((*par_num)++,
                                                          "SEARCHER");
                                        _print_parity(bp, SRC_REG_SRC_PRTY_STS);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "TCM");
-                                       _print_parity(bp,
-                                                     TCM_REG_TCM_PRTY_STS);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "TSEMI");
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "TCM");
+                                       _print_parity(bp, TCM_REG_TCM_PRTY_STS);
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR:
+                                       _print_next_block((*par_num)++,
+                                                         "TSEMI");
                                        _print_parity(bp,
                                                      TSEM_REG_TSEM_PRTY_STS_0);
                                        _print_parity(bp,
                                                      TSEM_REG_TSEM_PRTY_STS_1);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "XPB");
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "XPB");
                                        _print_parity(bp, GRCBASE_XPB +
                                                          PB_REG_PB_PRTY_STS);
+                                       break;
                                }
-                               break;
                        }
 
                        /* Clear the bit */
@@ -4346,53 +4358,59 @@ static int bnx2x_check_blocks_with_parity0(struct bnx2x *bp, u32 sig,
                }
        }
 
-       return par_num;
+       return res;
 }
 
-static int bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig,
-                                           int par_num, bool *global,
+static bool bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig,
+                                           int *par_num, bool *global,
                                            bool print)
 {
-       int i = 0;
-       u32 cur_bit = 0;
+       u32 cur_bit;
+       bool res;
+       int i;
+
+       res = false;
+
        for (i = 0; sig; i++) {
-               cur_bit = ((u32)0x1 << i);
+               cur_bit = (0x1UL << i);
                if (sig & cur_bit) {
+                       res |= true; /* Each bit is real error! */
                        switch (cur_bit) {
                        case AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "PBF");
+                                       _print_next_block((*par_num)++, "PBF");
                                        _print_parity(bp, PBF_REG_PBF_PRTY_STS);
                                }
                                break;
                        case AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "QM");
+                                       _print_next_block((*par_num)++, "QM");
                                        _print_parity(bp, QM_REG_QM_PRTY_STS);
                                }
                                break;
                        case AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "TM");
+                                       _print_next_block((*par_num)++, "TM");
                                        _print_parity(bp, TM_REG_TM_PRTY_STS);
                                }
                                break;
                        case AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "XSDM");
+                                       _print_next_block((*par_num)++, "XSDM");
                                        _print_parity(bp,
                                                      XSDM_REG_XSDM_PRTY_STS);
                                }
                                break;
                        case AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "XCM");
+                                       _print_next_block((*par_num)++, "XCM");
                                        _print_parity(bp, XCM_REG_XCM_PRTY_STS);
                                }
                                break;
                        case AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "XSEMI");
+                                       _print_next_block((*par_num)++,
+                                                         "XSEMI");
                                        _print_parity(bp,
                                                      XSEM_REG_XSEM_PRTY_STS_0);
                                        _print_parity(bp,
@@ -4401,7 +4419,7 @@ static int bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig,
                                break;
                        case AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++,
+                                       _print_next_block((*par_num)++,
                                                          "DOORBELLQ");
                                        _print_parity(bp,
                                                      DORQ_REG_DORQ_PRTY_STS);
@@ -4409,7 +4427,7 @@ static int bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig,
                                break;
                        case AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "NIG");
+                                       _print_next_block((*par_num)++, "NIG");
                                        if (CHIP_IS_E1x(bp)) {
                                                _print_parity(bp,
                                                        NIG_REG_NIG_PRTY_STS);
@@ -4423,32 +4441,34 @@ static int bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig,
                                break;
                        case AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR:
                                if (print)
-                                       _print_next_block(par_num++,
+                                       _print_next_block((*par_num)++,
                                                          "VAUX PCI CORE");
                                *global = true;
                                break;
                        case AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "DEBUG");
+                                       _print_next_block((*par_num)++,
+                                                         "DEBUG");
                                        _print_parity(bp, DBG_REG_DBG_PRTY_STS);
                                }
                                break;
                        case AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "USDM");
+                                       _print_next_block((*par_num)++, "USDM");
                                        _print_parity(bp,
                                                      USDM_REG_USDM_PRTY_STS);
                                }
                                break;
                        case AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "UCM");
+                                       _print_next_block((*par_num)++, "UCM");
                                        _print_parity(bp, UCM_REG_UCM_PRTY_STS);
                                }
                                break;
                        case AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "USEMI");
+                                       _print_next_block((*par_num)++,
+                                                         "USEMI");
                                        _print_parity(bp,
                                                      USEM_REG_USEM_PRTY_STS_0);
                                        _print_parity(bp,
@@ -4457,21 +4477,21 @@ static int bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig,
                                break;
                        case AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "UPB");
+                                       _print_next_block((*par_num)++, "UPB");
                                        _print_parity(bp, GRCBASE_UPB +
                                                          PB_REG_PB_PRTY_STS);
                                }
                                break;
                        case AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "CSDM");
+                                       _print_next_block((*par_num)++, "CSDM");
                                        _print_parity(bp,
                                                      CSDM_REG_CSDM_PRTY_STS);
                                }
                                break;
                        case AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR:
                                if (print) {
-                                       _print_next_block(par_num++, "CCM");
+                                       _print_next_block((*par_num)++, "CCM");
                                        _print_parity(bp, CCM_REG_CCM_PRTY_STS);
                                }
                                break;
@@ -4482,80 +4502,73 @@ static int bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig,
                }
        }
 
-       return par_num;
+       return res;
 }
 
-static int bnx2x_check_blocks_with_parity2(struct bnx2x *bp, u32 sig,
-                                           int par_num, bool print)
+static bool bnx2x_check_blocks_with_parity2(struct bnx2x *bp, u32 sig,
+                                           int *par_num, bool print)
 {
-       int i = 0;
-       u32 cur_bit = 0;
+       u32 cur_bit;
+       bool res;
+       int i;
+
+       res = false;
+
        for (i = 0; sig; i++) {
-               cur_bit = ((u32)0x1 << i);
+               cur_bit = (0x1UL << i);
                if (sig & cur_bit) {
-                       switch (cur_bit) {
-                       case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "CSEMI");
+                       res |= true; /* Each bit is real error! */
+                       if (print) {
+                               switch (cur_bit) {
+                               case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR:
+                                       _print_next_block((*par_num)++,
+                                                         "CSEMI");
                                        _print_parity(bp,
                                                      CSEM_REG_CSEM_PRTY_STS_0);
                                        _print_parity(bp,
                                                      CSEM_REG_CSEM_PRTY_STS_1);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "PXP");
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "PXP");
                                        _print_parity(bp, PXP_REG_PXP_PRTY_STS);
                                        _print_parity(bp,
                                                      PXP2_REG_PXP2_PRTY_STS_0);
                                        _print_parity(bp,
                                                      PXP2_REG_PXP2_PRTY_STS_1);
-                               }
-                               break;
-                       case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR:
-                               if (print)
-                                       _print_next_block(par_num++,
-                                       "PXPPCICLOCKCLIENT");
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "CFC");
+                                       break;
+                               case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR:
+                                       _print_next_block((*par_num)++,
+                                                         "PXPPCICLOCKCLIENT");
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "CFC");
                                        _print_parity(bp,
                                                      CFC_REG_CFC_PRTY_STS);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "CDU");
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "CDU");
                                        _print_parity(bp, CDU_REG_CDU_PRTY_STS);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "DMAE");
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "DMAE");
                                        _print_parity(bp,
                                                      DMAE_REG_DMAE_PRTY_STS);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "IGU");
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "IGU");
                                        if (CHIP_IS_E1x(bp))
                                                _print_parity(bp,
                                                        HC_REG_HC_PRTY_STS);
                                        else
                                                _print_parity(bp,
                                                        IGU_REG_IGU_PRTY_STS);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "MISC");
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "MISC");
                                        _print_parity(bp,
                                                      MISC_REG_MISC_PRTY_STS);
+                                       break;
                                }
-                               break;
                        }
 
                        /* Clear the bit */
@@ -4563,40 +4576,49 @@ static int bnx2x_check_blocks_with_parity2(struct bnx2x *bp, u32 sig,
                }
        }
 
-       return par_num;
+       return res;
 }
 
-static int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
-                                          bool *global, bool print)
+static bool bnx2x_check_blocks_with_parity3(struct bnx2x *bp, u32 sig,
+                                           int *par_num, bool *global,
+                                           bool print)
 {
-       int i = 0;
-       u32 cur_bit = 0;
+       bool res = false;
+       u32 cur_bit;
+       int i;
+
        for (i = 0; sig; i++) {
-               cur_bit = ((u32)0x1 << i);
+               cur_bit = (0x1UL << i);
                if (sig & cur_bit) {
                        switch (cur_bit) {
                        case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY:
                                if (print)
-                                       _print_next_block(par_num++, "MCP ROM");
+                                       _print_next_block((*par_num)++,
+                                                         "MCP ROM");
                                *global = true;
+                               res |= true;
                                break;
                        case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY:
                                if (print)
-                                       _print_next_block(par_num++,
+                                       _print_next_block((*par_num)++,
                                                          "MCP UMP RX");
                                *global = true;
+                               res |= true;
                                break;
                        case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY:
                                if (print)
-                                       _print_next_block(par_num++,
+                                       _print_next_block((*par_num)++,
                                                          "MCP UMP TX");
                                *global = true;
+                               res |= true;
                                break;
                        case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY:
                                if (print)
-                                       _print_next_block(par_num++,
+                                       _print_next_block((*par_num)++,
                                                          "MCP SCPAD");
-                               *global = true;
+                               /* clear latched SCPAD PATIRY from MCP */
+                               REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL,
+                                      1UL << 10);
                                break;
                        }
 
@@ -4605,45 +4627,50 @@ static int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
                }
        }
 
-       return par_num;
+       return res;
 }
 
-static int bnx2x_check_blocks_with_parity4(struct bnx2x *bp, u32 sig,
-                                           int par_num, bool print)
+static bool bnx2x_check_blocks_with_parity4(struct bnx2x *bp, u32 sig,
+                                           int *par_num, bool print)
 {
-       int i = 0;
-       u32 cur_bit = 0;
+       u32 cur_bit;
+       bool res;
+       int i;
+
+       res = false;
+
        for (i = 0; sig; i++) {
-               cur_bit = ((u32)0x1 << i);
+               cur_bit = (0x1UL << i);
                if (sig & cur_bit) {
-                       switch (cur_bit) {
-                       case AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "PGLUE_B");
+                       res |= true; /* Each bit is real error! */
+                       if (print) {
+                               switch (cur_bit) {
+                               case AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR:
+                                       _print_next_block((*par_num)++,
+                                                         "PGLUE_B");
                                        _print_parity(bp,
-                                               PGLUE_B_REG_PGLUE_B_PRTY_STS);
-                               }
-                               break;
-                       case AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR:
-                               if (print) {
-                                       _print_next_block(par_num++, "ATC");
+                                                     PGLUE_B_REG_PGLUE_B_PRTY_STS);
+                                       break;
+                               case AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR:
+                                       _print_next_block((*par_num)++, "ATC");
                                        _print_parity(bp,
                                                      ATC_REG_ATC_PRTY_STS);
+                                       break;
                                }
-                               break;
                        }
-
                        /* Clear the bit */
                        sig &= ~cur_bit;
                }
        }
 
-       return par_num;
+       return res;
 }
 
 static bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print,
                              u32 *sig)
 {
+       bool res = false;
+
        if ((sig[0] & HW_PRTY_ASSERT_SET_0) ||
            (sig[1] & HW_PRTY_ASSERT_SET_1) ||
            (sig[2] & HW_PRTY_ASSERT_SET_2) ||
@@ -4660,23 +4687,22 @@ static bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print,
                if (print)
                        netdev_err(bp->dev,
                                   "Parity errors detected in blocks: ");
-               par_num = bnx2x_check_blocks_with_parity0(bp,
-                       sig[0] & HW_PRTY_ASSERT_SET_0, par_num, print);
-               par_num = bnx2x_check_blocks_with_parity1(bp,
-                       sig[1] & HW_PRTY_ASSERT_SET_1, par_num, global, print);
-               par_num = bnx2x_check_blocks_with_parity2(bp,
-                       sig[2] & HW_PRTY_ASSERT_SET_2, par_num, print);
-               par_num = bnx2x_check_blocks_with_parity3(
-                       sig[3] & HW_PRTY_ASSERT_SET_3, par_num, global, print);
-               par_num = bnx2x_check_blocks_with_parity4(bp,
-                       sig[4] & HW_PRTY_ASSERT_SET_4, par_num, print);
+               res |= bnx2x_check_blocks_with_parity0(bp,
+                       sig[0] & HW_PRTY_ASSERT_SET_0, &par_num, print);
+               res |= bnx2x_check_blocks_with_parity1(bp,
+                       sig[1] & HW_PRTY_ASSERT_SET_1, &par_num, global, print);
+               res |= bnx2x_check_blocks_with_parity2(bp,
+                       sig[2] & HW_PRTY_ASSERT_SET_2, &par_num, print);
+               res |= bnx2x_check_blocks_with_parity3(bp,
+                       sig[3] & HW_PRTY_ASSERT_SET_3, &par_num, global, print);
+               res |= bnx2x_check_blocks_with_parity4(bp,
+                       sig[4] & HW_PRTY_ASSERT_SET_4, &par_num, print);
 
                if (print)
                        pr_cont("\n");
+       }
 
-               return true;
-       } else
-               return false;
+       return res;
 }
 
 /**
@@ -7126,7 +7152,7 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
        int port = BP_PORT(bp);
        int init_phase = port ? PHASE_PORT1 : PHASE_PORT0;
        u32 low, high;
-       u32 val;
+       u32 val, reg;
 
        DP(NETIF_MSG_HW, "starting port init  port %d\n", port);
 
@@ -7271,6 +7297,17 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
        val |= CHIP_IS_E1(bp) ? 0 : 0x10;
        REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, val);
 
+       /* SCPAD_PARITY should NOT trigger close the gates */
+       reg = port ? MISC_REG_AEU_ENABLE4_NIG_1 : MISC_REG_AEU_ENABLE4_NIG_0;
+       REG_WR(bp, reg,
+              REG_RD(bp, reg) &
+              ~AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY);
+
+       reg = port ? MISC_REG_AEU_ENABLE4_PXP_1 : MISC_REG_AEU_ENABLE4_PXP_0;
+       REG_WR(bp, reg,
+              REG_RD(bp, reg) &
+              ~AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY);
+
        bnx2x_init_block(bp, BLOCK_NIG, init_phase);
 
        if (!CHIP_IS_E1x(bp)) {
@@ -11685,9 +11722,6 @@ static int bnx2x_init_bp(struct bnx2x *bp)
 static int bnx2x_open(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
-       bool global = false;
-       int other_engine = BP_PATH(bp) ? 0 : 1;
-       bool other_load_status, load_status;
        int rc;
 
        bp->stats_init = true;
@@ -11703,6 +11737,10 @@ static int bnx2x_open(struct net_device *dev)
         * Parity recovery is only relevant for PF driver.
         */
        if (IS_PF(bp)) {
+               int other_engine = BP_PATH(bp) ? 0 : 1;
+               bool other_load_status, load_status;
+               bool global = false;
+
                other_load_status = bnx2x_get_load_status(bp, other_engine);
                load_status = bnx2x_get_load_status(bp, BP_PATH(bp));
                if (!bnx2x_reset_is_done(bp, BP_PATH(bp)) ||
@@ -12080,7 +12118,6 @@ static int bnx2x_set_coherency_mask(struct bnx2x *bp)
        struct device *dev = &bp->pdev->dev;
 
        if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) {
-               bp->flags |= USING_DAC_FLAG;
                if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) {
                        dev_err(dev, "dma_set_coherent_mask failed, aborting\n");
                        return -EIO;
@@ -12248,8 +12285,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
                NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
 
        dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX;
-       if (bp->flags & USING_DAC_FLAG)
-               dev->features |= NETIF_F_HIGHDMA;
+       dev->features |= NETIF_F_HIGHDMA;
 
        /* Add Loopback capability to the device */
        dev->hw_features |= NETIF_F_LOOPBACK;
@@ -12612,24 +12648,24 @@ static int set_max_cos_est(int chip_id)
                return BNX2X_MULTI_TX_COS_E1X;
        case BCM57712:
        case BCM57712_MF:
-       case BCM57712_VF:
                return BNX2X_MULTI_TX_COS_E2_E3A0;
        case BCM57800:
        case BCM57800_MF:
-       case BCM57800_VF:
        case BCM57810:
        case BCM57810_MF:
        case BCM57840_4_10:
        case BCM57840_2_20:
        case BCM57840_O:
        case BCM57840_MFO:
-       case BCM57810_VF:
        case BCM57840_MF:
-       case BCM57840_VF:
        case BCM57811:
        case BCM57811_MF:
-       case BCM57811_VF:
                return BNX2X_MULTI_TX_COS_E3B0;
+       case BCM57712_VF:
+       case BCM57800_VF:
+       case BCM57810_VF:
+       case BCM57840_VF:
+       case BCM57811_VF:
                return 1;
        default:
                pr_err("Unknown board_type (%d), aborting\n", chip_id);
index 9ad012bdd9151e44ce699b640e77273ad9901796..bf08ad68b4052374552e376739a101af0a652cf6 100644 (file)
@@ -470,10 +470,10 @@ static int bnx2x_vfop_qdtor_cmd(struct bnx2x *bp,
                                 bnx2x_vfop_qdtor, cmd->done);
                return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_qdtor,
                                             cmd->block);
+       } else {
+               BNX2X_ERR("VF[%d] failed to add a vfop\n", vf->abs_vfid);
+               return -ENOMEM;
        }
-       DP(BNX2X_MSG_IOV, "VF[%d] failed to add a vfop. rc %d\n",
-          vf->abs_vfid, vfop->rc);
-       return -ENOMEM;
 }
 
 static void
@@ -3390,14 +3390,16 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
                rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_ETH_MAC, true);
                if (rc) {
                        BNX2X_ERR("failed to delete eth macs\n");
-                       return -EINVAL;
+                       rc = -EINVAL;
+                       goto out;
                }
 
                /* remove existing uc list macs */
                rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_UC_LIST_MAC, true);
                if (rc) {
                        BNX2X_ERR("failed to delete uc_list macs\n");
-                       return -EINVAL;
+                       rc = -EINVAL;
+                       goto out;
                }
 
                /* configure the new mac to device */
@@ -3405,6 +3407,7 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
                bnx2x_set_mac_one(bp, (u8 *)&bulletin->mac, mac_obj, true,
                                  BNX2X_ETH_MAC, &ramrod_flags);
 
+out:
                bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC);
        }
 
@@ -3467,7 +3470,8 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
                                          &ramrod_flags);
                if (rc) {
                        BNX2X_ERR("failed to delete vlans\n");
-                       return -EINVAL;
+                       rc = -EINVAL;
+                       goto out;
                }
 
                /* send queue update ramrod to configure default vlan and silent
@@ -3501,7 +3505,8 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
                        rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
                        if (rc) {
                                BNX2X_ERR("failed to configure vlan\n");
-                               return -EINVAL;
+                               rc =  -EINVAL;
+                               goto out;
                        }
 
                        /* configure default vlan to vf queue and set silent
@@ -3519,18 +3524,18 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
                rc = bnx2x_queue_state_change(bp, &q_params);
                if (rc) {
                        BNX2X_ERR("Failed to configure default VLAN\n");
-                       return rc;
+                       goto out;
                }
 
                /* clear the flag indicating that this VF needs its vlan
-                * (will only be set if the HV configured th Vlan before vf was
-                * and we were called because the VF came up later
+                * (will only be set if the HV configured the Vlan before vf was
+                * up and we were called because the VF came up later
                 */
+out:
                vf->cfg_flags &= ~VF_CFG_VLAN;
-
                bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
        }
-       return 0;
+       return rc;
 }
 
 /* crc is the first field in the bulletin board. Compute the crc over the
index 86436c77af036d7884b9cc9525646a44f3ec4acf..3b75070411aab83136ac2c245ba9c65682aefebe 100644 (file)
@@ -196,7 +196,7 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp)
 
        } else if (bp->func_stx) {
                *stats_comp = 0;
-               bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
+               bnx2x_issue_dmae_with_comp(bp, dmae, stats_comp);
        }
 }
 
index da16953eb2ec58012f059273abf153c7e81293b9..28757dfacf0da0107576e0c8f7db3222fd5f7a1e 100644 (file)
@@ -980,7 +980,7 @@ static int bnx2x_copy32_vf_dmae(struct bnx2x *bp, u8 from_vf,
        dmae.len = len32;
 
        /* issue the command and wait for completion */
-       return bnx2x_issue_dmae_with_comp(bp, &dmae);
+       return bnx2x_issue_dmae_with_comp(bp, &dmae, bnx2x_sp(bp, wb_comp));
 }
 
 static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf)
index 78d6d6b970e105bb1de4c157a35af4e861e4f280..48f52882a22b07414b7fed808fe72ccd52650300 100644 (file)
 #define XGMAC_DMA_HW_FEATURE   0x00000f58      /* Enabled Hardware Features */
 
 #define XGMAC_ADDR_AE          0x80000000
-#define XGMAC_MAX_FILTER_ADDR  31
 
 /* PMT Control and Status */
 #define XGMAC_PMT_POINTER_RESET        0x80000000
@@ -384,6 +383,7 @@ struct xgmac_priv {
        struct device *device;
        struct napi_struct napi;
 
+       int max_macs;
        struct xgmac_extra_stats xstats;
 
        spinlock_t stats_lock;
@@ -1291,14 +1291,12 @@ static void xgmac_set_rx_mode(struct net_device *dev)
        netdev_dbg(priv->dev, "# mcasts %d, # unicast %d\n",
                 netdev_mc_count(dev), netdev_uc_count(dev));
 
-       if (dev->flags & IFF_PROMISC) {
-               writel(XGMAC_FRAME_FILTER_PR, ioaddr + XGMAC_FRAME_FILTER);
-               return;
-       }
+       if (dev->flags & IFF_PROMISC)
+               value |= XGMAC_FRAME_FILTER_PR;
 
        memset(hash_filter, 0, sizeof(hash_filter));
 
-       if (netdev_uc_count(dev) > XGMAC_MAX_FILTER_ADDR) {
+       if (netdev_uc_count(dev) > priv->max_macs) {
                use_hash = true;
                value |= XGMAC_FRAME_FILTER_HUC | XGMAC_FRAME_FILTER_HPF;
        }
@@ -1321,7 +1319,7 @@ static void xgmac_set_rx_mode(struct net_device *dev)
                goto out;
        }
 
-       if ((netdev_mc_count(dev) + reg - 1) > XGMAC_MAX_FILTER_ADDR) {
+       if ((netdev_mc_count(dev) + reg - 1) > priv->max_macs) {
                use_hash = true;
                value |= XGMAC_FRAME_FILTER_HMC | XGMAC_FRAME_FILTER_HPF;
        } else {
@@ -1342,8 +1340,8 @@ static void xgmac_set_rx_mode(struct net_device *dev)
        }
 
 out:
-       for (i = reg; i < XGMAC_MAX_FILTER_ADDR; i++)
-               xgmac_set_mac_addr(ioaddr, NULL, reg);
+       for (i = reg; i <= priv->max_macs; i++)
+               xgmac_set_mac_addr(ioaddr, NULL, i);
        for (i = 0; i < XGMAC_NUM_HASH; i++)
                writel(hash_filter[i], ioaddr + XGMAC_HASH(i));
 
@@ -1761,6 +1759,13 @@ static int xgmac_probe(struct platform_device *pdev)
        uid = readl(priv->base + XGMAC_VERSION);
        netdev_info(ndev, "h/w version is 0x%x\n", uid);
 
+       /* Figure out how many valid mac address filter registers we have */
+       writel(1, priv->base + XGMAC_ADDR_HIGH(31));
+       if (readl(priv->base + XGMAC_ADDR_HIGH(31)) == 1)
+               priv->max_macs = 31;
+       else
+               priv->max_macs = 7;
+
        writel(0, priv->base + XGMAC_DMA_INTR_ENA);
        ndev->irq = platform_get_irq(pdev, 0);
        if (ndev->irq == -ENXIO) {
index 5f5896e522d2c6068d7b6bc9c685cbc279be48d8..a7a941b1a655a3bbf82baa949c1fe81d17458701 100644 (file)
@@ -158,18 +158,6 @@ static inline board_info_t *to_dm9000_board(struct net_device *dev)
 
 /* DM9000 network board routine ---------------------------- */
 
-static void
-dm9000_reset(board_info_t * db)
-{
-       dev_dbg(db->dev, "resetting device\n");
-
-       /* RESET device */
-       writeb(DM9000_NCR, db->io_addr);
-       udelay(200);
-       writeb(NCR_RST, db->io_data);
-       udelay(200);
-}
-
 /*
  *   Read a byte from I/O port
  */
@@ -191,6 +179,27 @@ iow(board_info_t * db, int reg, int value)
        writeb(value, db->io_data);
 }
 
+static void
+dm9000_reset(board_info_t *db)
+{
+       dev_dbg(db->dev, "resetting device\n");
+
+       /* Reset DM9000, see DM9000 Application Notes V1.22 Jun 11, 2004 page 29
+        * The essential point is that we have to do a double reset, and the
+        * instruction is to set LBK into MAC internal loopback mode.
+        */
+       iow(db, DM9000_NCR, 0x03);
+       udelay(100); /* Application note says at least 20 us */
+       if (ior(db, DM9000_NCR) & 1)
+               dev_err(db->dev, "dm9000 did not respond to first reset\n");
+
+       iow(db, DM9000_NCR, 0);
+       iow(db, DM9000_NCR, 0x03);
+       udelay(100);
+       if (ior(db, DM9000_NCR) & 1)
+               dev_err(db->dev, "dm9000 did not respond to second reset\n");
+}
+
 /* routines for sending block to chip */
 
 static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
@@ -744,15 +753,20 @@ static const struct ethtool_ops dm9000_ethtool_ops = {
 static void dm9000_show_carrier(board_info_t *db,
                                unsigned carrier, unsigned nsr)
 {
+       int lpa;
        struct net_device *ndev = db->ndev;
+       struct mii_if_info *mii = &db->mii;
        unsigned ncr = dm9000_read_locked(db, DM9000_NCR);
 
-       if (carrier)
-               dev_info(db->dev, "%s: link up, %dMbps, %s-duplex, no LPA\n",
+       if (carrier) {
+               lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
+               dev_info(db->dev,
+                        "%s: link up, %dMbps, %s-duplex, lpa 0x%04X\n",
                         ndev->name, (nsr & NSR_SPEED) ? 10 : 100,
-                        (ncr & NCR_FDX) ? "full" : "half");
-       else
+                        (ncr & NCR_FDX) ? "full" : "half", lpa);
+       } else {
                dev_info(db->dev, "%s: link down\n", ndev->name);
+       }
 }
 
 static void
@@ -890,9 +904,15 @@ dm9000_init_dm9000(struct net_device *dev)
                        (dev->features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0);
 
        iow(db, DM9000_GPCR, GPCR_GEP_CNTL);    /* Let GPIO0 output */
+       iow(db, DM9000_GPR, 0);
 
-       dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
-       dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */
+       /* If we are dealing with DM9000B, some extra steps are required: a
+        * manual phy reset, and setting init params.
+        */
+       if (db->type == TYPE_DM9000B) {
+               dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);
+               dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM);
+       }
 
        ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
 
index bd0e0c0bbcd8e0e21d5295ef92aea6fb769d2c69..c08fd32bb8e50abd5ba37a7029641df6bfcb80d9 100644 (file)
@@ -1198,7 +1198,6 @@ int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo)
 
        if (lancer_chip(adapter)) {
                req->hdr.version = 1;
-               req->if_id = cpu_to_le16(adapter->if_handle);
        } else if (BEx_chip(adapter)) {
                if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC)
                        req->hdr.version = 2;
@@ -1206,6 +1205,8 @@ int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo)
                req->hdr.version = 2;
        }
 
+       if (req->hdr.version > 0)
+               req->if_id = cpu_to_le16(adapter->if_handle);
        req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
        req->ulp_num = BE_ULP1_NUM;
        req->type = BE_ETH_TX_RING_TYPE_STANDARD;
index c4eaadeb572fa3dcd97396afffd961f936d0189d..9fbe4dda7a0e4d68d6bee463fbc6e0a18fa8c061 100644 (file)
@@ -88,6 +88,7 @@
 
 #include <asm/io.h>
 #include <asm/reg.h>
+#include <asm/mpc85xx.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <linux/module.h>
@@ -939,9 +940,8 @@ static void gfar_init_filer_table(struct gfar_private *priv)
        }
 }
 
-static void gfar_detect_errata(struct gfar_private *priv)
+static void __gfar_detect_errata_83xx(struct gfar_private *priv)
 {
-       struct device *dev = &priv->ofdev->dev;
        unsigned int pvr = mfspr(SPRN_PVR);
        unsigned int svr = mfspr(SPRN_SVR);
        unsigned int mod = (svr >> 16) & 0xfff6; /* w/o E suffix */
@@ -957,15 +957,33 @@ static void gfar_detect_errata(struct gfar_private *priv)
            (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
                priv->errata |= GFAR_ERRATA_76;
 
-       /* MPC8313 and MPC837x all rev */
-       if ((pvr == 0x80850010 && mod == 0x80b0) ||
-           (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
-               priv->errata |= GFAR_ERRATA_A002;
+       /* MPC8313 Rev < 2.0 */
+       if (pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020)
+               priv->errata |= GFAR_ERRATA_12;
+}
 
-       /* MPC8313 Rev < 2.0, MPC8548 rev 2.0 */
-       if ((pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020) ||
-           (pvr == 0x80210020 && mod == 0x8030 && rev == 0x0020))
+static void __gfar_detect_errata_85xx(struct gfar_private *priv)
+{
+       unsigned int svr = mfspr(SPRN_SVR);
+
+       if ((SVR_SOC_VER(svr) == SVR_8548) && (SVR_REV(svr) == 0x20))
                priv->errata |= GFAR_ERRATA_12;
+       if (((SVR_SOC_VER(svr) == SVR_P2020) && (SVR_REV(svr) < 0x20)) ||
+           ((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20)))
+               priv->errata |= GFAR_ERRATA_76; /* aka eTSEC 20 */
+}
+
+static void gfar_detect_errata(struct gfar_private *priv)
+{
+       struct device *dev = &priv->ofdev->dev;
+
+       /* no plans to fix */
+       priv->errata |= GFAR_ERRATA_A002;
+
+       if (pvr_version_is(PVR_VER_E500V1) || pvr_version_is(PVR_VER_E500V2))
+               __gfar_detect_errata_85xx(priv);
+       else /* non-mpc85xx parts, i.e. e300 core based */
+               __gfar_detect_errata_83xx(priv);
 
        if (priv->errata)
                dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
@@ -1599,7 +1617,7 @@ static int __gfar_is_rx_idle(struct gfar_private *priv)
        /* Normaly TSEC should not hang on GRS commands, so we should
         * actually wait for IEVENT_GRSC flag.
         */
-       if (likely(!gfar_has_errata(priv, GFAR_ERRATA_A002)))
+       if (!gfar_has_errata(priv, GFAR_ERRATA_A002))
                return 0;
 
        /* Read the eTSEC register at offset 0xD1C. If bits 7-14 are
index 86d51429a189295d9c7418a1273b625a933d9a9b..151e00cad113f5d7c42249e091a844d56955ba49 100644 (file)
@@ -2655,6 +2655,8 @@ static int igb_set_eee(struct net_device *netdev,
            (hw->phy.media_type != e1000_media_type_copper))
                return -EOPNOTSUPP;
 
+       memset(&eee_curr, 0, sizeof(struct ethtool_eee));
+
        ret_val = igb_get_eee(netdev, &eee_curr);
        if (ret_val)
                return ret_val;
index 7fb5677451f9fb7aee3ebccd31a82b476cfac4df..2c210ec35d59da72e0a55257665538d184bc04ef 100644 (file)
@@ -1131,15 +1131,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);
 }
 
 
@@ -2237,6 +2235,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);
@@ -2534,6 +2533,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
        if (!ppdev)
                return -ENOMEM;
        ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       ppdev->dev.of_node = pnp;
 
        ret = platform_device_add_resources(ppdev, &res, 1);
        if (ret)
@@ -2916,7 +2916,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);
 
index dec455c8f6274a9827f93bf038d8e12c58242765..afe2efa69c8683647766a8d5dc7d561f3f76c2df 100644 (file)
@@ -70,14 +70,15 @@ static int mlx4_alloc_pages(struct mlx4_en_priv *priv,
                put_page(page);
                return -ENOMEM;
        }
-       page_alloc->size = PAGE_SIZE << order;
+       page_alloc->page_size = PAGE_SIZE << order;
        page_alloc->page = page;
        page_alloc->dma = dma;
-       page_alloc->offset = frag_info->frag_align;
+       page_alloc->page_offset = frag_info->frag_align;
        /* Not doing get_page() for each frag is a big win
         * on asymetric workloads.
         */
-       atomic_set(&page->_count, page_alloc->size / frag_info->frag_stride);
+       atomic_set(&page->_count,
+                  page_alloc->page_size / frag_info->frag_stride);
        return 0;
 }
 
@@ -96,16 +97,19 @@ static int mlx4_en_alloc_frags(struct mlx4_en_priv *priv,
        for (i = 0; i < priv->num_frags; i++) {
                frag_info = &priv->frag_info[i];
                page_alloc[i] = ring_alloc[i];
-               page_alloc[i].offset += frag_info->frag_stride;
-               if (page_alloc[i].offset + frag_info->frag_stride <= ring_alloc[i].size)
+               page_alloc[i].page_offset += frag_info->frag_stride;
+
+               if (page_alloc[i].page_offset + frag_info->frag_stride <=
+                   ring_alloc[i].page_size)
                        continue;
+
                if (mlx4_alloc_pages(priv, &page_alloc[i], frag_info, gfp))
                        goto out;
        }
 
        for (i = 0; i < priv->num_frags; i++) {
                frags[i] = ring_alloc[i];
-               dma = ring_alloc[i].dma + ring_alloc[i].offset;
+               dma = ring_alloc[i].dma + ring_alloc[i].page_offset;
                ring_alloc[i] = page_alloc[i];
                rx_desc->data[i].addr = cpu_to_be64(dma);
        }
@@ -117,7 +121,7 @@ out:
                frag_info = &priv->frag_info[i];
                if (page_alloc[i].page != ring_alloc[i].page) {
                        dma_unmap_page(priv->ddev, page_alloc[i].dma,
-                               page_alloc[i].size, PCI_DMA_FROMDEVICE);
+                               page_alloc[i].page_size, PCI_DMA_FROMDEVICE);
                        page = page_alloc[i].page;
                        atomic_set(&page->_count, 1);
                        put_page(page);
@@ -131,10 +135,12 @@ static void mlx4_en_free_frag(struct mlx4_en_priv *priv,
                              int i)
 {
        const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i];
+       u32 next_frag_end = frags[i].page_offset + 2 * frag_info->frag_stride;
+
 
-       if (frags[i].offset + frag_info->frag_stride > frags[i].size)
-               dma_unmap_page(priv->ddev, frags[i].dma, frags[i].size,
-                                        PCI_DMA_FROMDEVICE);
+       if (next_frag_end > frags[i].page_size)
+               dma_unmap_page(priv->ddev, frags[i].dma, frags[i].page_size,
+                              PCI_DMA_FROMDEVICE);
 
        if (frags[i].page)
                put_page(frags[i].page);
@@ -161,7 +167,7 @@ out:
 
                page_alloc = &ring->page_alloc[i];
                dma_unmap_page(priv->ddev, page_alloc->dma,
-                              page_alloc->size, PCI_DMA_FROMDEVICE);
+                              page_alloc->page_size, PCI_DMA_FROMDEVICE);
                page = page_alloc->page;
                atomic_set(&page->_count, 1);
                put_page(page);
@@ -184,10 +190,11 @@ static void mlx4_en_destroy_allocator(struct mlx4_en_priv *priv,
                       i, page_count(page_alloc->page));
 
                dma_unmap_page(priv->ddev, page_alloc->dma,
-                               page_alloc->size, PCI_DMA_FROMDEVICE);
-               while (page_alloc->offset + frag_info->frag_stride < page_alloc->size) {
+                               page_alloc->page_size, PCI_DMA_FROMDEVICE);
+               while (page_alloc->page_offset + frag_info->frag_stride <
+                      page_alloc->page_size) {
                        put_page(page_alloc->page);
-                       page_alloc->offset += frag_info->frag_stride;
+                       page_alloc->page_offset += frag_info->frag_stride;
                }
                page_alloc->page = NULL;
        }
@@ -478,7 +485,7 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
                /* Save page reference in skb */
                __skb_frag_set_page(&skb_frags_rx[nr], frags[nr].page);
                skb_frag_size_set(&skb_frags_rx[nr], frag_info->frag_size);
-               skb_frags_rx[nr].page_offset = frags[nr].offset;
+               skb_frags_rx[nr].page_offset = frags[nr].page_offset;
                skb->truesize += frag_info->frag_stride;
                frags[nr].page = NULL;
        }
@@ -517,7 +524,7 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
 
        /* Get pointer to first fragment so we could copy the headers into the
         * (linear part of the) skb */
-       va = page_address(frags[0].page) + frags[0].offset;
+       va = page_address(frags[0].page) + frags[0].page_offset;
 
        if (length <= SMALL_PACKET_SIZE) {
                /* We are copying all relevant data to the skb - temporarily
@@ -645,7 +652,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                        dma_sync_single_for_cpu(priv->ddev, dma, sizeof(*ethh),
                                                DMA_FROM_DEVICE);
                        ethh = (struct ethhdr *)(page_address(frags[0].page) +
-                                                frags[0].offset);
+                                                frags[0].page_offset);
 
                        if (is_multicast_ether_addr(ethh->h_dest)) {
                                struct mlx4_mac_entry *entry;
index 5e0aa569306aab2f6c8185cd1574cdd4abeb4aab..bf06e3610d27787ced2f43b9f9aa9fef105aa3df 100644 (file)
@@ -237,8 +237,8 @@ struct mlx4_en_tx_desc {
 struct mlx4_en_rx_alloc {
        struct page     *page;
        dma_addr_t      dma;
-       u32             offset;
-       u32             size;
+       u32             page_offset;
+       u32             page_size;
 };
 
 struct mlx4_en_tx_ring {
index 5472cbd34028d9038539824c4167a0c3010a3a01..6ca30739625f7ac568d693b5d4b9d3d9e47b46de 100644 (file)
@@ -180,28 +180,32 @@ static int verify_block_sig(struct mlx5_cmd_prot_block *block)
        return 0;
 }
 
-static void calc_block_sig(struct mlx5_cmd_prot_block *block, u8 token)
+static void calc_block_sig(struct mlx5_cmd_prot_block *block, u8 token,
+                          int csum)
 {
        block->token = token;
-       block->ctrl_sig = ~xor8_buf(block->rsvd0, sizeof(*block) - sizeof(block->data) - 2);
-       block->sig = ~xor8_buf(block, sizeof(*block) - 1);
+       if (csum) {
+               block->ctrl_sig = ~xor8_buf(block->rsvd0, sizeof(*block) -
+                                           sizeof(block->data) - 2);
+               block->sig = ~xor8_buf(block, sizeof(*block) - 1);
+       }
 }
 
-static void calc_chain_sig(struct mlx5_cmd_msg *msg, u8 token)
+static void calc_chain_sig(struct mlx5_cmd_msg *msg, u8 token, int csum)
 {
        struct mlx5_cmd_mailbox *next = msg->next;
 
        while (next) {
-               calc_block_sig(next->buf, token);
+               calc_block_sig(next->buf, token, csum);
                next = next->next;
        }
 }
 
-static void set_signature(struct mlx5_cmd_work_ent *ent)
+static void set_signature(struct mlx5_cmd_work_ent *ent, int csum)
 {
        ent->lay->sig = ~xor8_buf(ent->lay, sizeof(*ent->lay));
-       calc_chain_sig(ent->in, ent->token);
-       calc_chain_sig(ent->out, ent->token);
+       calc_chain_sig(ent->in, ent->token, csum);
+       calc_chain_sig(ent->out, ent->token, csum);
 }
 
 static void poll_timeout(struct mlx5_cmd_work_ent *ent)
@@ -539,8 +543,7 @@ static void cmd_work_handler(struct work_struct *work)
        lay->type = MLX5_PCI_CMD_XPORT;
        lay->token = ent->token;
        lay->status_own = CMD_OWNER_HW;
-       if (!cmd->checksum_disabled)
-               set_signature(ent);
+       set_signature(ent, !cmd->checksum_disabled);
        dump_command(dev, ent, 1);
        ktime_get_ts(&ent->ts1);
 
@@ -773,8 +776,6 @@ static int mlx5_copy_from_msg(void *to, struct mlx5_cmd_msg *from, int size)
 
                copy = min_t(int, size, MLX5_CMD_DATA_BLOCK_SIZE);
                block = next->buf;
-               if (xor8_buf(block, sizeof(*block)) != 0xff)
-                       return -EINVAL;
 
                memcpy(to, block->data, copy);
                to += copy;
@@ -1361,6 +1362,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
                goto err_map;
        }
 
+       cmd->checksum_disabled = 1;
        cmd->max_reg_cmds = (1 << cmd->log_sz) - 1;
        cmd->bitmask = (1 << cmd->max_reg_cmds) - 1;
 
@@ -1510,7 +1512,7 @@ int mlx5_cmd_status_to_err(struct mlx5_outbox_hdr *hdr)
        case MLX5_CMD_STAT_BAD_SYS_STATE_ERR:           return -EIO;
        case MLX5_CMD_STAT_BAD_RES_ERR:                 return -EINVAL;
        case MLX5_CMD_STAT_RES_BUSY:                    return -EBUSY;
-       case MLX5_CMD_STAT_LIM_ERR:                     return -EINVAL;
+       case MLX5_CMD_STAT_LIM_ERR:                     return -ENOMEM;
        case MLX5_CMD_STAT_BAD_RES_STATE_ERR:           return -EINVAL;
        case MLX5_CMD_STAT_IX_ERR:                      return -EINVAL;
        case MLX5_CMD_STAT_NO_RES_ERR:                  return -EAGAIN;
index 443cc4d7b024c02d2cc77861868e1c1b17ee2524..2231d93cc7ad116e55c77e0269fa27878f6c6a4d 100644 (file)
@@ -366,9 +366,11 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
                goto err_in;
        }
 
+       snprintf(eq->name, MLX5_MAX_EQ_NAME, "%s@pci:%s",
+                name, pci_name(dev->pdev));
        eq->eqn = out.eq_number;
        err = request_irq(table->msix_arr[vecidx].vector, mlx5_msix_handler, 0,
-                         name, eq);
+                         eq->name, eq);
        if (err)
                goto err_eq;
 
index b47739b0b5f6dfb34139ad74e02ac10db1d4fbbd..bc0f5fb66e249dc2e652b4126f9b907707b87c6c 100644 (file)
@@ -165,9 +165,7 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
        struct mlx5_cmd_set_hca_cap_mbox_in *set_ctx = NULL;
        struct mlx5_cmd_query_hca_cap_mbox_in query_ctx;
        struct mlx5_cmd_set_hca_cap_mbox_out set_out;
-       struct mlx5_profile *prof = dev->profile;
        u64 flags;
-       int csum = 1;
        int err;
 
        memset(&query_ctx, 0, sizeof(query_ctx));
@@ -197,20 +195,14 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
        memcpy(&set_ctx->hca_cap, &query_out->hca_cap,
               sizeof(set_ctx->hca_cap));
 
-       if (prof->mask & MLX5_PROF_MASK_CMDIF_CSUM) {
-               csum = !!prof->cmdif_csum;
-               flags = be64_to_cpu(set_ctx->hca_cap.flags);
-               if (csum)
-                       flags |= MLX5_DEV_CAP_FLAG_CMDIF_CSUM;
-               else
-                       flags &= ~MLX5_DEV_CAP_FLAG_CMDIF_CSUM;
-
-               set_ctx->hca_cap.flags = cpu_to_be64(flags);
-       }
-
        if (dev->profile->mask & MLX5_PROF_MASK_QP_SIZE)
                set_ctx->hca_cap.log_max_qp = dev->profile->log_max_qp;
 
+       flags = be64_to_cpu(query_out->hca_cap.flags);
+       /* disable checksum */
+       flags &= ~MLX5_DEV_CAP_FLAG_CMDIF_CSUM;
+
+       set_ctx->hca_cap.flags = cpu_to_be64(flags);
        memset(&set_out, 0, sizeof(set_out));
        set_ctx->hca_cap.log_uar_page_sz = cpu_to_be16(PAGE_SHIFT - 12);
        set_ctx->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_SET_HCA_CAP);
@@ -225,9 +217,6 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
        if (err)
                goto query_ex;
 
-       if (!csum)
-               dev->cmd.checksum_disabled = 1;
-
 query_ex:
        kfree(query_out);
        kfree(set_ctx);
index 3a2408d448203623754d0aa87e35c16e809da43f..7b12acf210f81cd408a4b0e8a965fd4441165c9f 100644 (file)
@@ -90,6 +90,10 @@ struct mlx5_manage_pages_outbox {
        __be64                  pas[0];
 };
 
+enum {
+       MAX_RECLAIM_TIME_MSECS  = 5000,
+};
+
 static int insert_page(struct mlx5_core_dev *dev, u64 addr, struct page *page, u16 func_id)
 {
        struct rb_root *root = &dev->priv.page_root;
@@ -279,6 +283,9 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages,
        int err;
        int i;
 
+       if (nclaimed)
+               *nclaimed = 0;
+
        memset(&in, 0, sizeof(in));
        outlen = sizeof(*out) + npages * sizeof(out->pas[0]);
        out = mlx5_vzalloc(outlen);
@@ -388,20 +395,25 @@ static int optimal_reclaimed_pages(void)
 
 int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev)
 {
-       unsigned long end = jiffies + msecs_to_jiffies(5000);
+       unsigned long end = jiffies + msecs_to_jiffies(MAX_RECLAIM_TIME_MSECS);
        struct fw_page *fwp;
        struct rb_node *p;
+       int nclaimed = 0;
        int err;
 
        do {
                p = rb_first(&dev->priv.page_root);
                if (p) {
                        fwp = rb_entry(p, struct fw_page, rb_node);
-                       err = reclaim_pages(dev, fwp->func_id, optimal_reclaimed_pages(), NULL);
+                       err = reclaim_pages(dev, fwp->func_id,
+                                           optimal_reclaimed_pages(),
+                                           &nclaimed);
                        if (err) {
                                mlx5_core_warn(dev, "failed reclaiming pages (%d)\n", err);
                                return err;
                        }
+                       if (nclaimed)
+                               end = jiffies + msecs_to_jiffies(MAX_RECLAIM_TIME_MSECS);
                }
                if (time_after(jiffies, end)) {
                        mlx5_core_warn(dev, "FW did not return all pages. giving up...\n");
index bd1a2d2bc2aebbad9612d167915fd743cf973c94..ea54d95e5b9f9caa250974b050b5de82a2231e31 100644 (file)
@@ -448,7 +448,8 @@ static int moxart_mac_probe(struct platform_device *pdev)
        irq = irq_of_parse_and_map(node, 0);
        if (irq <= 0) {
                netdev_err(ndev, "irq_of_parse_and_map failed\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto irq_map_fail;
        }
 
        priv = netdev_priv(ndev);
@@ -472,24 +473,32 @@ static int moxart_mac_probe(struct platform_device *pdev)
        priv->tx_desc_base = dma_alloc_coherent(NULL, TX_REG_DESC_SIZE *
                                                TX_DESC_NUM, &priv->tx_base,
                                                GFP_DMA | GFP_KERNEL);
-       if (priv->tx_desc_base == NULL)
+       if (priv->tx_desc_base == NULL) {
+               ret = -ENOMEM;
                goto init_fail;
+       }
 
        priv->rx_desc_base = dma_alloc_coherent(NULL, RX_REG_DESC_SIZE *
                                                RX_DESC_NUM, &priv->rx_base,
                                                GFP_DMA | GFP_KERNEL);
-       if (priv->rx_desc_base == NULL)
+       if (priv->rx_desc_base == NULL) {
+               ret = -ENOMEM;
                goto init_fail;
+       }
 
        priv->tx_buf_base = kmalloc(priv->tx_buf_size * TX_DESC_NUM,
                                    GFP_ATOMIC);
-       if (!priv->tx_buf_base)
+       if (!priv->tx_buf_base) {
+               ret = -ENOMEM;
                goto init_fail;
+       }
 
        priv->rx_buf_base = kmalloc(priv->rx_buf_size * RX_DESC_NUM,
                                    GFP_ATOMIC);
-       if (!priv->rx_buf_base)
+       if (!priv->rx_buf_base) {
+               ret = -ENOMEM;
                goto init_fail;
+       }
 
        platform_set_drvdata(pdev, ndev);
 
@@ -522,7 +531,8 @@ static int moxart_mac_probe(struct platform_device *pdev)
 init_fail:
        netdev_err(ndev, "init failed\n");
        moxart_mac_free_memory(ndev);
-
+irq_map_fail:
+       free_netdev(ndev);
        return ret;
 }
 
index ebe4c86e5230223f0c5465485a9812dc1a0aa3b0..ff83a9fcd4c5a844955d221c9daef96772402b7a 100644 (file)
@@ -665,7 +665,7 @@ static int qlcnic_set_channels(struct net_device *dev,
                        return err;
        }
 
-       if (channel->tx_count) {
+       if (qlcnic_82xx_check(adapter) && channel->tx_count) {
                err = qlcnic_validate_max_tx_rings(adapter, channel->tx_count);
                if (err)
                        return err;
index 21d00a0449a10f394fe6b02d5689c7b0ab3b95cf..9e61eb8674524575481d0f1158d75353ea4ef724 100644 (file)
@@ -2257,7 +2257,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        err = qlcnic_alloc_adapter_resources(adapter);
        if (err)
-               goto err_out_free_netdev;
+               goto err_out_free_wq;
 
        adapter->dev_rst_time = jiffies;
        adapter->ahw->revision_id = pdev->revision;
@@ -2396,6 +2396,9 @@ err_out_disable_msi:
 err_out_free_hw:
        qlcnic_free_adapter_resources(adapter);
 
+err_out_free_wq:
+       destroy_workqueue(adapter->qlcnic_wq);
+
 err_out_free_netdev:
        free_netdev(netdev);
 
@@ -3648,11 +3651,6 @@ int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *adapter, u32 txq)
        u8 max_hw = QLCNIC_MAX_TX_RINGS;
        u32 max_allowed;
 
-       if (!qlcnic_82xx_check(adapter)) {
-               netdev_err(netdev, "No Multi TX-Q support\n");
-               return -EINVAL;
-       }
-
        if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
                netdev_err(netdev, "No Multi TX-Q support in INT-x mode\n");
                return -EINVAL;
@@ -3692,8 +3690,7 @@ int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter,
        u8 max_hw = adapter->ahw->max_rx_ques;
        u32 max_allowed;
 
-       if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x &&
-           !qlcnic_use_msi) {
+       if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
                netdev_err(netdev, "No RSS support in INT-x mode\n");
                return -EINVAL;
        }
index 5cd831ebfa83b0a95c472926a0105c521f7c352a..b57c278d3b46b2eeb1d9b56b3cc9ca312ba67f61 100644 (file)
@@ -688,12 +688,16 @@ static struct sh_eth_cpu_data r8a7740_data = {
        .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
                          EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
                          EESR_TDE | EESR_ECI,
+       .fdr_value      = 0x0000070f,
+       .rmcr_value     = 0x00000001,
 
        .apr            = 1,
        .mpr            = 1,
        .tpauser        = 1,
        .bculr          = 1,
        .hw_swap        = 1,
+       .rpadir         = 1,
+       .rpadir_value   = 2 << 16,
        .no_trimd       = 1,
        .no_ade         = 1,
        .tsu            = 1,
index 9f18ae984f9ed38386b16e5284d4d10864687c4b..21f9ad6392e9e2d547817c91e5260558eefcbcbb 100644 (file)
@@ -444,6 +444,18 @@ static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
        EF10_DMA_STAT(rx_align_error, RX_ALIGN_ERROR_PKTS),
        EF10_DMA_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS),
        EF10_DMA_STAT(rx_nodesc_drops, RX_NODESC_DROPS),
+       EF10_DMA_STAT(rx_pm_trunc_bb_overflow, PM_TRUNC_BB_OVERFLOW),
+       EF10_DMA_STAT(rx_pm_discard_bb_overflow, PM_DISCARD_BB_OVERFLOW),
+       EF10_DMA_STAT(rx_pm_trunc_vfifo_full, PM_TRUNC_VFIFO_FULL),
+       EF10_DMA_STAT(rx_pm_discard_vfifo_full, PM_DISCARD_VFIFO_FULL),
+       EF10_DMA_STAT(rx_pm_trunc_qbb, PM_TRUNC_QBB),
+       EF10_DMA_STAT(rx_pm_discard_qbb, PM_DISCARD_QBB),
+       EF10_DMA_STAT(rx_pm_discard_mapping, PM_DISCARD_MAPPING),
+       EF10_DMA_STAT(rx_dp_q_disabled_packets, RXDP_Q_DISABLED_PKTS),
+       EF10_DMA_STAT(rx_dp_di_dropped_packets, RXDP_DI_DROPPED_PKTS),
+       EF10_DMA_STAT(rx_dp_streaming_packets, RXDP_STREAMING_PKTS),
+       EF10_DMA_STAT(rx_dp_emerg_fetch, RXDP_EMERGENCY_FETCH_CONDITIONS),
+       EF10_DMA_STAT(rx_dp_emerg_wait, RXDP_EMERGENCY_WAIT_CONDITIONS),
 };
 
 #define HUNT_COMMON_STAT_MASK ((1ULL << EF10_STAT_tx_bytes) |          \
@@ -498,44 +510,72 @@ static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
 #define HUNT_40G_EXTRA_STAT_MASK ((1ULL << EF10_STAT_rx_align_error) | \
                                  (1ULL << EF10_STAT_rx_length_error))
 
-#if BITS_PER_LONG == 64
-#define STAT_MASK_BITMAP(bits) (bits)
-#else
-#define STAT_MASK_BITMAP(bits) (bits) & 0xffffffff, (bits) >> 32
-#endif
-
-static const unsigned long *efx_ef10_stat_mask(struct efx_nic *efx)
-{
-       static const unsigned long hunt_40g_stat_mask[] = {
-               STAT_MASK_BITMAP(HUNT_COMMON_STAT_MASK |
-                                HUNT_40G_EXTRA_STAT_MASK)
-       };
-       static const unsigned long hunt_10g_only_stat_mask[] = {
-               STAT_MASK_BITMAP(HUNT_COMMON_STAT_MASK |
-                                HUNT_10G_ONLY_STAT_MASK)
-       };
+/* These statistics are only provided if the firmware supports the
+ * capability PM_AND_RXDP_COUNTERS.
+ */
+#define HUNT_PM_AND_RXDP_STAT_MASK (                                   \
+       (1ULL << EF10_STAT_rx_pm_trunc_bb_overflow) |                   \
+       (1ULL << EF10_STAT_rx_pm_discard_bb_overflow) |                 \
+       (1ULL << EF10_STAT_rx_pm_trunc_vfifo_full) |                    \
+       (1ULL << EF10_STAT_rx_pm_discard_vfifo_full) |                  \
+       (1ULL << EF10_STAT_rx_pm_trunc_qbb) |                           \
+       (1ULL << EF10_STAT_rx_pm_discard_qbb) |                         \
+       (1ULL << EF10_STAT_rx_pm_discard_mapping) |                     \
+       (1ULL << EF10_STAT_rx_dp_q_disabled_packets) |                  \
+       (1ULL << EF10_STAT_rx_dp_di_dropped_packets) |                  \
+       (1ULL << EF10_STAT_rx_dp_streaming_packets) |                   \
+       (1ULL << EF10_STAT_rx_dp_emerg_fetch) |                         \
+       (1ULL << EF10_STAT_rx_dp_emerg_wait))
+
+static u64 efx_ef10_raw_stat_mask(struct efx_nic *efx)
+{
+       u64 raw_mask = HUNT_COMMON_STAT_MASK;
        u32 port_caps = efx_mcdi_phy_get_caps(efx);
+       struct efx_ef10_nic_data *nic_data = efx->nic_data;
 
        if (port_caps & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
-               return hunt_40g_stat_mask;
+               raw_mask |= HUNT_40G_EXTRA_STAT_MASK;
        else
-               return hunt_10g_only_stat_mask;
+               raw_mask |= HUNT_10G_ONLY_STAT_MASK;
+
+       if (nic_data->datapath_caps &
+           (1 << MC_CMD_GET_CAPABILITIES_OUT_PM_AND_RXDP_COUNTERS_LBN))
+               raw_mask |= HUNT_PM_AND_RXDP_STAT_MASK;
+
+       return raw_mask;
+}
+
+static void efx_ef10_get_stat_mask(struct efx_nic *efx, unsigned long *mask)
+{
+       u64 raw_mask = efx_ef10_raw_stat_mask(efx);
+
+#if BITS_PER_LONG == 64
+       mask[0] = raw_mask;
+#else
+       mask[0] = raw_mask & 0xffffffff;
+       mask[1] = raw_mask >> 32;
+#endif
 }
 
 static size_t efx_ef10_describe_stats(struct efx_nic *efx, u8 *names)
 {
+       DECLARE_BITMAP(mask, EF10_STAT_COUNT);
+
+       efx_ef10_get_stat_mask(efx, mask);
        return efx_nic_describe_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
-                                     efx_ef10_stat_mask(efx), names);
+                                     mask, names);
 }
 
 static int efx_ef10_try_update_nic_stats(struct efx_nic *efx)
 {
        struct efx_ef10_nic_data *nic_data = efx->nic_data;
-       const unsigned long *stats_mask = efx_ef10_stat_mask(efx);
+       DECLARE_BITMAP(mask, EF10_STAT_COUNT);
        __le64 generation_start, generation_end;
        u64 *stats = nic_data->stats;
        __le64 *dma_stats;
 
+       efx_ef10_get_stat_mask(efx, mask);
+
        dma_stats = efx->stats_buffer.addr;
        nic_data = efx->nic_data;
 
@@ -543,8 +583,9 @@ static int efx_ef10_try_update_nic_stats(struct efx_nic *efx)
        if (generation_end == EFX_MC_STATS_GENERATION_INVALID)
                return 0;
        rmb();
-       efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, stats_mask,
+       efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, mask,
                             stats, efx->stats_buffer.addr, false);
+       rmb();
        generation_start = dma_stats[MC_CMD_MAC_GENERATION_START];
        if (generation_end != generation_start)
                return -EAGAIN;
@@ -563,12 +604,14 @@ static int efx_ef10_try_update_nic_stats(struct efx_nic *efx)
 static size_t efx_ef10_update_stats(struct efx_nic *efx, u64 *full_stats,
                                    struct rtnl_link_stats64 *core_stats)
 {
-       const unsigned long *mask = efx_ef10_stat_mask(efx);
+       DECLARE_BITMAP(mask, EF10_STAT_COUNT);
        struct efx_ef10_nic_data *nic_data = efx->nic_data;
        u64 *stats = nic_data->stats;
        size_t stats_count = 0, index;
        int retry;
 
+       efx_ef10_get_stat_mask(efx, mask);
+
        /* If we're unlucky enough to read statistics during the DMA, wait
         * up to 10ms for it to finish (typically takes <500us)
         */
index c082562dbf4ee8d96388dc21e0b2da1803fe84f2..366c8e3e37844c8e2d8840a4662467067e937b3b 100644 (file)
@@ -963,7 +963,7 @@ static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
                               bool *was_attached)
 {
        MCDI_DECLARE_BUF(inbuf, MC_CMD_DRV_ATTACH_IN_LEN);
-       MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_OUT_LEN);
+       MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_EXT_OUT_LEN);
        size_t outlen;
        int rc;
 
@@ -981,6 +981,22 @@ static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
                goto fail;
        }
 
+       /* We currently assume we have control of the external link
+        * and are completely trusted by firmware.  Abort probing
+        * if that's not true for this function.
+        */
+       if (driver_operating &&
+           outlen >= MC_CMD_DRV_ATTACH_EXT_OUT_LEN &&
+           (MCDI_DWORD(outbuf, DRV_ATTACH_EXT_OUT_FUNC_FLAGS) &
+            (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL |
+             1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED)) !=
+           (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL |
+            1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED)) {
+               netif_err(efx, probe, efx->net_dev,
+                         "This driver version only supports one function per port\n");
+               return -ENODEV;
+       }
+
        if (was_attached != NULL)
                *was_attached = MCDI_DWORD(outbuf, DRV_ATTACH_OUT_OLD_STATE);
        return 0;
index b5cf62492f8e77ff5bf2a8f0504ae7df4cf8c2ef..e0a63ddb7a6ceb1246dc9a7a7349ce7efffa0d9e 100644 (file)
 #define          MC_CMD_MAC_RX_LANES01_DISP_ERR  0x39 /* enum */
 #define          MC_CMD_MAC_RX_LANES23_DISP_ERR  0x3a /* enum */
 #define          MC_CMD_MAC_RX_MATCH_FAULT  0x3b /* enum */
-#define          MC_CMD_GMAC_DMABUF_START  0x40 /* enum */
-#define          MC_CMD_GMAC_DMABUF_END    0x5f /* enum */
+/* enum: PM trunc_bb_overflow counter. Valid for EF10 with PM_AND_RXDP_COUNTERS
+ * capability only.
+ */
+#define          MC_CMD_MAC_PM_TRUNC_BB_OVERFLOW  0x3c
+/* enum: PM discard_bb_overflow counter. Valid for EF10 with
+ * PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_PM_DISCARD_BB_OVERFLOW  0x3d
+/* enum: PM trunc_vfifo_full counter. Valid for EF10 with PM_AND_RXDP_COUNTERS
+ * capability only.
+ */
+#define          MC_CMD_MAC_PM_TRUNC_VFIFO_FULL  0x3e
+/* enum: PM discard_vfifo_full counter. Valid for EF10 with
+ * PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_PM_DISCARD_VFIFO_FULL  0x3f
+/* enum: PM trunc_qbb counter. Valid for EF10 with PM_AND_RXDP_COUNTERS
+ * capability only.
+ */
+#define          MC_CMD_MAC_PM_TRUNC_QBB  0x40
+/* enum: PM discard_qbb counter. Valid for EF10 with PM_AND_RXDP_COUNTERS
+ * capability only.
+ */
+#define          MC_CMD_MAC_PM_DISCARD_QBB  0x41
+/* enum: PM discard_mapping counter. Valid for EF10 with PM_AND_RXDP_COUNTERS
+ * capability only.
+ */
+#define          MC_CMD_MAC_PM_DISCARD_MAPPING  0x42
+/* enum: RXDP counter: Number of packets dropped due to the queue being
+ * disabled. Valid for EF10 with PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_RXDP_Q_DISABLED_PKTS  0x43
+/* enum: RXDP counter: Number of packets dropped by the DICPU. Valid for EF10
+ * with PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_RXDP_DI_DROPPED_PKTS  0x45
+/* enum: RXDP counter: Number of non-host packets. Valid for EF10 with
+ * PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_RXDP_STREAMING_PKTS  0x46
+/* enum: RXDP counter: Number of times an emergency descriptor fetch was
+ * performed. Valid for EF10 with PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_RXDP_EMERGENCY_FETCH_CONDITIONS  0x47
+/* enum: RXDP counter: Number of times the DPCPU waited for an existing
+ * descriptor fetch. Valid for EF10 with PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_RXDP_EMERGENCY_WAIT_CONDITIONS  0x48
+/* enum: Start of GMAC stats buffer space, for Siena only. */
+#define          MC_CMD_GMAC_DMABUF_START  0x40
+/* enum: End of GMAC stats buffer space, for Siena only. */
+#define          MC_CMD_GMAC_DMABUF_END    0x5f
 #define          MC_CMD_MAC_GENERATION_END 0x60 /* enum */
 #define          MC_CMD_MAC_NSTATS  0x61 /* enum */
 
 #define        MC_CMD_GET_CAPABILITIES_OUT_RX_BATCHING_WIDTH 1
 #define        MC_CMD_GET_CAPABILITIES_OUT_MCAST_FILTER_CHAINING_LBN 26
 #define        MC_CMD_GET_CAPABILITIES_OUT_MCAST_FILTER_CHAINING_WIDTH 1
+#define        MC_CMD_GET_CAPABILITIES_OUT_PM_AND_RXDP_COUNTERS_LBN 27
+#define        MC_CMD_GET_CAPABILITIES_OUT_PM_AND_RXDP_COUNTERS_WIDTH 1
 /* RxDPCPU firmware id. */
 #define       MC_CMD_GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID_OFST 4
 #define       MC_CMD_GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID_LEN 2
index e7dbd2dd202e8bb7332b83560f1fa93d56071674..9826594c8a48fa21ca75040fd1513db024092a6e 100644 (file)
@@ -469,8 +469,7 @@ size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
  * @count: Length of the @desc array
  * @mask: Bitmask of which elements of @desc are enabled
  * @stats: Buffer to update with the converted statistics.  The length
- *     of this array must be at least the number of set bits in the
- *     first @count bits of @mask.
+ *     of this array must be at least @count.
  * @dma_buf: DMA buffer containing hardware statistics
  * @accumulate: If set, the converted values will be added rather than
  *     directly stored to the corresponding elements of @stats
@@ -503,11 +502,9 @@ void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
                        }
 
                        if (accumulate)
-                               *stats += val;
+                               stats[index] += val;
                        else
-                               *stats = val;
+                               stats[index] = val;
                }
-
-               ++stats;
        }
 }
index fda29d39032f422d2c395a4fe68a4c5091654006..890bbbe8320ee247ba1ee37965334ed1828d226c 100644 (file)
@@ -386,6 +386,18 @@ enum {
        EF10_STAT_rx_align_error,
        EF10_STAT_rx_length_error,
        EF10_STAT_rx_nodesc_drops,
+       EF10_STAT_rx_pm_trunc_bb_overflow,
+       EF10_STAT_rx_pm_discard_bb_overflow,
+       EF10_STAT_rx_pm_trunc_vfifo_full,
+       EF10_STAT_rx_pm_discard_vfifo_full,
+       EF10_STAT_rx_pm_trunc_qbb,
+       EF10_STAT_rx_pm_discard_qbb,
+       EF10_STAT_rx_pm_discard_mapping,
+       EF10_STAT_rx_dp_q_disabled_packets,
+       EF10_STAT_rx_dp_di_dropped_packets,
+       EF10_STAT_rx_dp_streaming_packets,
+       EF10_STAT_rx_dp_emerg_fetch,
+       EF10_STAT_rx_dp_emerg_wait,
        EF10_STAT_COUNT
 };
 
index 5730fe2445a6c1acf5dfa5cd8767d1b1bb749734..98eedb90cdc3c0220c6f8f4d26d2b7f945cf9624 100644 (file)
@@ -1124,8 +1124,7 @@ static const char * chip_ids[ 16 ] =  {
                        void __iomem *__ioaddr = ioaddr;                \
                        if (__len >= 2 && (unsigned long)__ptr & 2) {   \
                                __len -= 2;                             \
-                               SMC_outw(*(u16 *)__ptr, ioaddr,         \
-                                       DATA_REG(lp));          \
+                               SMC_outsw(ioaddr, DATA_REG(lp), __ptr, 1); \
                                __ptr += 2;                             \
                        }                                               \
                        if (SMC_CAN_USE_DATACS && lp->datacs)           \
@@ -1133,8 +1132,7 @@ static const char * chip_ids[ 16 ] =  {
                        SMC_outsl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
                        if (__len & 2) {                                \
                                __ptr += (__len & ~3);                  \
-                               SMC_outw(*((u16 *)__ptr), ioaddr,       \
-                                        DATA_REG(lp));         \
+                               SMC_outsw(ioaddr, DATA_REG(lp), __ptr, 1); \
                        }                                               \
                } else if (SMC_16BIT(lp))                               \
                        SMC_outsw(ioaddr, DATA_REG(lp), p, (l) >> 1);   \
index 79974e31187ac19af63452a3a0c421a5ff2b7cf7..cc3ce557e4aa62074873ee34e348ec24a0719ccf 100644 (file)
@@ -639,13 +639,6 @@ void cpsw_rx_handler(void *token, int len, int status)
 static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
 {
        struct cpsw_priv *priv = dev_id;
-       u32 rx, tx, rx_thresh;
-
-       rx_thresh = __raw_readl(&priv->wr_regs->rx_thresh_stat);
-       rx = __raw_readl(&priv->wr_regs->rx_stat);
-       tx = __raw_readl(&priv->wr_regs->tx_stat);
-       if (!rx_thresh && !rx && !tx)
-               return IRQ_NONE;
 
        cpsw_intr_disable(priv);
        if (priv->irq_enabled == true) {
@@ -1169,9 +1162,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
                }
        }
 
+       napi_enable(&priv->napi);
        cpdma_ctlr_start(priv->dma);
        cpsw_intr_enable(priv);
-       napi_enable(&priv->napi);
        cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
        cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
 
@@ -1771,8 +1764,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
        }
        data->mac_control = prop;
 
-       if (!of_property_read_u32(node, "dual_emac", &prop))
-               data->dual_emac = prop;
+       if (of_property_read_bool(node, "dual_emac"))
+               data->dual_emac = 1;
 
        /*
         * Populate all the child nodes here...
@@ -1782,7 +1775,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
        if (ret)
                pr_warn("Doesn't have any child node\n");
 
-       for_each_node_by_name(slave_node, "slave") {
+       for_each_child_of_node(node, slave_node) {
                struct cpsw_slave_data *slave_data = data->slave_data + i;
                const void *mac_addr = NULL;
                u32 phyid;
@@ -1791,6 +1784,10 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                struct device_node *mdio_node;
                struct platform_device *mdio;
 
+               /* This is no slave child node, continue */
+               if (strcmp(slave_node->name, "slave"))
+                       continue;
+
                parp = of_get_property(slave_node, "phy_id", &lenp);
                if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
                        pr_err("Missing slave[%d] phy_id property\n", i);
index 67df09ea9d045da26420de1e9da09af58ec0edb8..6a32ef9d63ae2500d5a397a3d6837be525ff7d6f 100644 (file)
@@ -876,8 +876,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);
index 0721e72f9299250c6c29f0e1d3f7f51affffe7e8..5af1c3e5032addd1441722899d3ab1fb0b010ae9 100644 (file)
@@ -975,7 +975,6 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                        return -EINVAL;         /* Cannot change this parameter when up */
                if ((ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_KERNEL)) == NULL)
                        return -ENOBUFS;
-               ym->bitrate = 9600;
                if (copy_from_user(ym, ifr->ifr_data, sizeof(struct yamdrv_ioctl_mcs))) {
                        kfree(ym);
                        return -EFAULT;
index 42e6deee6db55ed607170109438960523d6b9b8e..0632d34905c73811456594cf0bf5e27f8710f5c7 100644 (file)
@@ -82,7 +82,6 @@ struct mrf24j40 {
 
        struct mutex buffer_mutex; /* only used to protect buf */
        struct completion tx_complete;
-       struct work_struct irqwork;
        u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */
 };
 
@@ -344,6 +343,8 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
        if (ret)
                goto err;
 
+       INIT_COMPLETION(devrec->tx_complete);
+
        /* Set TXNTRIG bit of TXNCON to send packet */
        ret = read_short_reg(devrec, REG_TXNCON, &val);
        if (ret)
@@ -354,8 +355,6 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
                val |= 0x4;
        write_short_reg(devrec, REG_TXNCON, val);
 
-       INIT_COMPLETION(devrec->tx_complete);
-
        /* Wait for the device to send the TX complete interrupt. */
        ret = wait_for_completion_interruptible_timeout(
                                                &devrec->tx_complete,
@@ -590,17 +589,6 @@ static struct ieee802154_ops mrf24j40_ops = {
 static irqreturn_t mrf24j40_isr(int irq, void *data)
 {
        struct mrf24j40 *devrec = data;
-
-       disable_irq_nosync(irq);
-
-       schedule_work(&devrec->irqwork);
-
-       return IRQ_HANDLED;
-}
-
-static void mrf24j40_isrwork(struct work_struct *work)
-{
-       struct mrf24j40 *devrec = container_of(work, struct mrf24j40, irqwork);
        u8 intstat;
        int ret;
 
@@ -618,7 +606,7 @@ static void mrf24j40_isrwork(struct work_struct *work)
                mrf24j40_handle_rx(devrec);
 
 out:
-       enable_irq(devrec->spi->irq);
+       return IRQ_HANDLED;
 }
 
 static int mrf24j40_probe(struct spi_device *spi)
@@ -642,7 +630,6 @@ static int mrf24j40_probe(struct spi_device *spi)
 
        mutex_init(&devrec->buffer_mutex);
        init_completion(&devrec->tx_complete);
-       INIT_WORK(&devrec->irqwork, mrf24j40_isrwork);
        devrec->spi = spi;
        spi_set_drvdata(spi, devrec);
 
@@ -688,11 +675,12 @@ static int mrf24j40_probe(struct spi_device *spi)
        val &= ~0x3; /* Clear RX mode (normal) */
        write_short_reg(devrec, REG_RXMCR, val);
 
-       ret = request_irq(spi->irq,
-                         mrf24j40_isr,
-                         IRQF_TRIGGER_FALLING,
-                         dev_name(&spi->dev),
-                         devrec);
+       ret = request_threaded_irq(spi->irq,
+                                  NULL,
+                                  mrf24j40_isr,
+                                  IRQF_TRIGGER_LOW|IRQF_ONESHOT,
+                                  dev_name(&spi->dev),
+                                  devrec);
 
        if (ret) {
                dev_err(printdev(devrec), "Unable to get IRQ");
@@ -721,7 +709,6 @@ static int mrf24j40_remove(struct spi_device *spi)
        dev_dbg(printdev(devrec), "remove\n");
 
        free_irq(spi->irq, devrec);
-       flush_work(&devrec->irqwork); /* TODO: Is this the right call? */
        ieee802154_unregister_device(devrec->dev);
        ieee802154_free_device(devrec->dev);
        /* TODO: Will ieee802154_free_device() wait until ->xmit() is
index 807815fc996839d14efd18625fb300a2f48d2577..7cb105c103fe9408eb7c02b96dac4f4bfb702456 100644 (file)
@@ -1293,7 +1293,8 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
        if (unlikely(!noblock))
                add_wait_queue(&tfile->wq.wait, &wait);
        while (len) {
-               current->state = TASK_INTERRUPTIBLE;
+               if (unlikely(!noblock))
+                       current->state = TASK_INTERRUPTIBLE;
 
                /* Read frames from the queue */
                if (!(skb = skb_dequeue(&tfile->socket.sk->sk_receive_queue))) {
@@ -1320,9 +1321,10 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
                break;
        }
 
-       current->state = TASK_RUNNING;
-       if (unlikely(!noblock))
+       if (unlikely(!noblock)) {
+               current->state = TASK_RUNNING;
                remove_wait_queue(&tfile->wq.wait, &wait);
+       }
 
        return ret;
 }
index 3569293df8726df8c87786ad83b5be506e6b3285..846cc19c04f23f2f5a15adf65d8098cc36513eb6 100644 (file)
@@ -36,8 +36,8 @@
 #define AX_RXHDR_L4_TYPE_TCP                   16
 #define AX_RXHDR_L3CSUM_ERR                    2
 #define AX_RXHDR_L4CSUM_ERR                    1
-#define AX_RXHDR_CRC_ERR                       ((u32)BIT(31))
-#define AX_RXHDR_DROP_ERR                      ((u32)BIT(30))
+#define AX_RXHDR_CRC_ERR                       ((u32)BIT(29))
+#define AX_RXHDR_DROP_ERR                      ((u32)BIT(31))
 #define AX_ACCESS_MAC                          0x01
 #define AX_ACCESS_PHY                          0x02
 #define AX_ACCESS_EEPROM                       0x04
@@ -1406,6 +1406,19 @@ static const struct driver_info sitecom_info = {
        .tx_fixup = ax88179_tx_fixup,
 };
 
+static const struct driver_info samsung_info = {
+       .description = "Samsung USB Ethernet Adapter",
+       .bind = ax88179_bind,
+       .unbind = ax88179_unbind,
+       .status = ax88179_status,
+       .link_reset = ax88179_link_reset,
+       .reset = ax88179_reset,
+       .stop = ax88179_stop,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = ax88179_rx_fixup,
+       .tx_fixup = ax88179_tx_fixup,
+};
+
 static const struct usb_device_id products[] = {
 {
        /* ASIX AX88179 10/100/1000 */
@@ -1418,7 +1431,11 @@ static const struct usb_device_id products[] = {
 }, {
        /* Sitecom USB 3.0 to Gigabit Adapter */
        USB_DEVICE(0x0df6, 0x0072),
-       .driver_info = (unsigned long) &sitecom_info,
+       .driver_info = (unsigned long)&sitecom_info,
+}, {
+       /* Samsung USB Ethernet Adapter */
+       USB_DEVICE(0x04e8, 0xa100),
+       .driver_info = (unsigned long)&samsung_info,
 },
        { },
 };
index 3d6aaf79d8b2399565b4e9c1a64edd4fe27b90af..818ce90185b5dee9e736923cee09d2b7a0a8d840 100644 (file)
@@ -714,6 +714,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
        {QMI_FIXED_INTF(0x2357, 0x9000, 4)},    /* TP-LINK MA260 */
        {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
+       {QMI_FIXED_INTF(0x0b3c, 0xc005, 6)},    /* Olivetti Olicard 200 */
        {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)},    /* Cinterion PLxx */
 
        /* 4. Gobi 1000 devices */
index bf94e10a37c8e0121d783fc54c1b565b57a7ce21..90a429b7ebad8497d317639389c041d534366255 100644 (file)
@@ -1688,8 +1688,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        if (dev->can_dma_sg && !(info->flags & FLAG_SEND_ZLP) &&
                !(info->flags & FLAG_MULTI_PACKET)) {
                dev->padding_pkt = kzalloc(1, GFP_KERNEL);
-               if (!dev->padding_pkt)
+               if (!dev->padding_pkt) {
+                       status = -ENOMEM;
                        goto out4;
+               }
        }
 
        status = register_netdev (net);
index defec2b3c5a408ff035889d015d717f040e2864c..9fbdfcd1e1a0693e96edd908928953097b99742d 100644 (file)
@@ -938,7 +938,9 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
                return -EINVAL;
        } else {
                vi->curr_queue_pairs = queue_pairs;
-               schedule_delayed_work(&vi->refill, 0);
+               /* virtnet_open() will refill when device is going to up. */
+               if (dev->flags & IFF_UP)
+                       schedule_delayed_work(&vi->refill, 0);
        }
 
        return 0;
@@ -1116,6 +1118,11 @@ static int virtnet_cpu_callback(struct notifier_block *nfb,
 {
        struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb);
 
+       mutex_lock(&vi->config_lock);
+
+       if (!vi->config_enable)
+               goto done;
+
        switch(action & ~CPU_TASKS_FROZEN) {
        case CPU_ONLINE:
        case CPU_DOWN_FAILED:
@@ -1128,6 +1135,9 @@ static int virtnet_cpu_callback(struct notifier_block *nfb,
        default:
                break;
        }
+
+done:
+       mutex_unlock(&vi->config_lock);
        return NOTIFY_OK;
 }
 
@@ -1733,7 +1743,9 @@ static int virtnet_restore(struct virtio_device *vdev)
        vi->config_enable = true;
        mutex_unlock(&vi->config_lock);
 
+       rtnl_lock();
        virtnet_set_queues(vi, vi->curr_queue_pairs);
+       rtnl_unlock();
 
        return 0;
 }
index 3f0c4f268751030318dd920a2a81bf2ddd1d328d..bcfff0d62de4f2070d5ac644a3becfedb74e3462 100644 (file)
@@ -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) ==
index 6a24a5a70cc7d4459e04e0348882f0324dd4fad3..4c0a69779b8980a16ccca5a90acc5ece605cf06a 100644 (file)
@@ -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;
index e4f65900132dedf40a68e2299b2a6177e8dfaf89..709301f88dcd26210a18db4d6eb1f8e230905608 100644 (file)
@@ -208,6 +208,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        unsigned long flags;
+       int i;
 
        if (ath_startrecv(sc) != 0) {
                ath_err(common, "Unable to restart recv logic\n");
@@ -235,6 +236,15 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
                }
        work:
                ath_restart_work(sc);
+
+               for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+                       if (!ATH_TXQ_SETUP(sc, i))
+                               continue;
+
+                       spin_lock_bh(&sc->tx.txq[i].axq_lock);
+                       ath_txq_schedule(sc, &sc->tx.txq[i]);
+                       spin_unlock_bh(&sc->tx.txq[i].axq_lock);
+               }
        }
 
        ieee80211_wake_queues(sc->hw);
@@ -539,21 +549,10 @@ chip_reset:
 
 static int ath_reset(struct ath_softc *sc)
 {
-       int i, r;
+       int r;
 
        ath9k_ps_wakeup(sc);
-
        r = ath_reset_internal(sc, NULL);
-
-       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-               if (!ATH_TXQ_SETUP(sc, i))
-                       continue;
-
-               spin_lock_bh(&sc->tx.txq[i].axq_lock);
-               ath_txq_schedule(sc, &sc->tx.txq[i]);
-               spin_unlock_bh(&sc->tx.txq[i].axq_lock);
-       }
-
        ath9k_ps_restore(sc);
 
        return r;
index 5ac713d2ff5d22dc6d976291c6d97098bfbceafd..dd30452df9663574d54024f20eeac031a9910ba3 100644 (file)
@@ -1969,15 +1969,18 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
 static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
                               struct ath_atx_tid *tid, struct sk_buff *skb)
 {
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ath_frame_info *fi = get_frame_info(skb);
        struct list_head bf_head;
-       struct ath_buf *bf;
-
-       bf = fi->bf;
+       struct ath_buf *bf = fi->bf;
 
        INIT_LIST_HEAD(&bf_head);
        list_add_tail(&bf->list, &bf_head);
        bf->bf_state.bf_type = 0;
+       if (tid && (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
+               bf->bf_state.bf_type = BUF_AMPDU;
+               ath_tx_addto_baw(sc, tid, bf);
+       }
 
        bf->bf_next = NULL;
        bf->bf_lastbf = bf;
index 899cad34ccd3aa1649029d90294fe21c30608d14..755a0c8edfe1235e73180b8b45d6143afa582547 100644 (file)
@@ -237,7 +237,9 @@ static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id)
        struct hwbus_priv *self = dev_id;
 
        if (self->core) {
+               cw1200_spi_lock(self);
                cw1200_irq_handler(self->core);
+               cw1200_spi_unlock(self);
                return IRQ_HANDLED;
        } else {
                return IRQ_NONE;
index 30d45e2fc193a5bc04987acbdef9b0252a2b5c01..8ac305be68f489be533606cb8260dbfd4dc5cfda 100644 (file)
@@ -240,6 +240,12 @@ const struct iwl_cfg iwl6035_2agn_cfg = {
        .ht_params = &iwl6000_ht_params,
 };
 
+const struct iwl_cfg iwl6035_2agn_sff_cfg = {
+       .name = "Intel(R) Centrino(R) Ultimate-N 6235 AGN",
+       IWL_DEVICE_6035,
+       .ht_params = &iwl6000_ht_params,
+};
+
 const struct iwl_cfg iwl1030_bgn_cfg = {
        .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
        IWL_DEVICE_6030,
index e4d370bff30679fceacc1bc82907ccb6bc194f22..b03c25e14903d05c150c176d608f4be1f654673e 100644 (file)
@@ -280,6 +280,7 @@ extern const struct iwl_cfg iwl2000_2bgn_cfg;
 extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
 extern const struct iwl_cfg iwl2030_2bgn_cfg;
 extern const struct iwl_cfg iwl6035_2agn_cfg;
+extern const struct iwl_cfg iwl6035_2agn_sff_cfg;
 extern const struct iwl_cfg iwl105_bgn_cfg;
 extern const struct iwl_cfg iwl105_bgn_d_cfg;
 extern const struct iwl_cfg iwl135_bgn_cfg;
index dd57a36ecb1005d7571290a59925fd4d641b61aa..80b47508647ca8d5861f4b4c8dc8e8ec879d34c3 100644 (file)
@@ -601,8 +601,10 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
 {
        int ret;
 
-       WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
-                 "%s bad state = %d", __func__, trans->state);
+       if (trans->state != IWL_TRANS_FW_ALIVE) {
+               IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+               return -EIO;
+       }
 
        if (!(cmd->flags & CMD_ASYNC))
                lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
index 21407a353a3b0e623c87ae3627957ae45ae3b162..d58e393324ef3ff9591f1cf297cf656c259037ae 100644 (file)
@@ -273,7 +273,10 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
                if (!mvmvif->queue_params[ac].uapsd)
                        continue;
 
-               cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
+               if (mvm->cur_ucode != IWL_UCODE_WOWLAN)
+                       cmd->flags |=
+                               cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
+
                cmd->uapsd_ac_flags |= BIT(ac);
 
                /* QNDP TID - the highest TID with no admission control */
index 9a7ab84953000234b463ac1636cabcf506b95433..621fb71f282a88e9a285bb3d4b2b26a1b2fef275 100644 (file)
@@ -394,6 +394,11 @@ static bool iwl_mvm_scan_abort_notif(struct iwl_notif_wait_data *notif_wait,
                        return false;
                }
 
+               /*
+                * If scan cannot be aborted, it means that we had a
+                * SCAN_COMPLETE_NOTIFICATION in the pipe and it called
+                * ieee80211_scan_completed already.
+                */
                IWL_DEBUG_SCAN(mvm, "Scan cannot be aborted, exit now: %d\n",
                               *resp);
                return true;
@@ -417,14 +422,19 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
                                               SCAN_COMPLETE_NOTIFICATION };
        int ret;
 
+       if (mvm->scan_status == IWL_MVM_SCAN_NONE)
+               return;
+
        iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort,
                                   scan_abort_notif,
                                   ARRAY_SIZE(scan_abort_notif),
                                   iwl_mvm_scan_abort_notif, NULL);
 
-       ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, CMD_SYNC, 0, NULL);
+       ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD,
+                                  CMD_SYNC | CMD_SEND_IN_RFKILL, 0, NULL);
        if (ret) {
                IWL_ERR(mvm, "Couldn't send SCAN_ABORT_CMD: %d\n", ret);
+               /* mac80211's state will be cleaned in the fw_restart flow */
                goto out_remove_notif;
        }
 
index dc02cb9792afbbb48c23f01d748c262bee1828fd..26108a1a29fa6d6871cea350aae20820c27d4220 100644 (file)
@@ -139,13 +139,16 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 
 /* 6x00 Series */
        {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x422B, 0x1108, iwl6000_3agn_cfg)},
        {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x422B, 0x1128, iwl6000_3agn_cfg)},
        {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
        {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
        {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
        {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
        {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
        {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x4238, 0x1118, iwl6000_3agn_cfg)},
        {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
        {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
 
@@ -153,12 +156,16 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
        {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
+       {IWL_PCI_DEVICE(0x0082, 0x1308, iwl6005_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x0082, 0x1328, iwl6005_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0085, 0x1318, iwl6005_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
        {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)},
        {IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)},
+       {IWL_PCI_DEVICE(0x0085, 0xC228, iwl6005_2agn_sff_cfg)},
        {IWL_PCI_DEVICE(0x0082, 0x4820, iwl6005_2agn_d_cfg)},
        {IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_2agn_mow1_cfg)},/* low 5GHz active */
        {IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_2agn_mow2_cfg)},/* high 5GHz active */
@@ -240,8 +247,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 
 /* 6x35 Series */
        {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x088E, 0x406A, iwl6035_2agn_sff_cfg)},
        {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x088F, 0x426A, iwl6035_2agn_sff_cfg)},
        {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x088E, 0x446A, iwl6035_2agn_sff_cfg)},
        {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)},
        {IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)},
 
@@ -260,54 +270,86 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 #if IS_ENABLED(CONFIG_IWLMVM)
 /* 7000 Series */
        {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x406A, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4162, iwl7260_n_cfg)},
        {IWL_PCI_DEVICE(0x08B2, 0x4270, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B2, 0x4272, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B2, 0x4260, iwl7260_2n_cfg)},
+       {IWL_PCI_DEVICE(0x08B2, 0x426A, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B2, 0x4262, iwl7260_n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4470, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x4472, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4460, iwl7260_2n_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x446A, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg_high_temp)},
        {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg_high_temp)},
        {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg_high_temp)},
+       {IWL_PCI_DEVICE(0x08B1, 0x4570, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x4560, iwl7260_2n_cfg)},
+       {IWL_PCI_DEVICE(0x08B2, 0x4370, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B2, 0x4360, iwl7260_2n_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x5070, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x402A, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0xC072, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC170, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC060, iwl7260_2n_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0xC06A, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC160, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC062, iwl7260_n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC162, iwl7260_n_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0xC770, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0xC760, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B2, 0xC272, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)},
+       {IWL_PCI_DEVICE(0x08B2, 0xC26A, iwl7260_n_cfg)},
        {IWL_PCI_DEVICE(0x08B2, 0xC262, iwl7260_n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC470, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0xC472, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC460, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC462, iwl7260_n_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0xC570, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0xC560, iwl7260_2n_cfg)},
+       {IWL_PCI_DEVICE(0x08B2, 0xC370, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0xC360, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC020, iwl7260_2n_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0xC02A, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B2, 0xC220, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC420, iwl7260_2n_cfg)},
 
 /* 3160 Series */
        {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B3, 0x0072, iwl3160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x0170, iwl3160_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B3, 0x0172, iwl3160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x0060, iwl3160_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x0062, iwl3160_n_cfg)},
        {IWL_PCI_DEVICE(0x08B4, 0x0270, iwl3160_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B4, 0x0272, iwl3160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x0470, iwl3160_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B3, 0x0472, iwl3160_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B4, 0x0370, iwl3160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B3, 0x8072, iwl3160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x8170, iwl3160_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B3, 0x8172, iwl3160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)},
        {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)},
 #endif /* CONFIG_IWLMVM */
 
        {0}
index bad95d28d50da52158ff102de3fc9855e46a662b..c3f904d422b08b1074345fcba99a31390f663945 100644 (file)
@@ -1401,6 +1401,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        spin_lock_init(&trans_pcie->reg_lock);
        init_waitqueue_head(&trans_pcie->ucode_write_waitq);
 
+       err = pci_enable_device(pdev);
+       if (err)
+               goto out_no_pci;
+
        if (!cfg->base_params->pcie_l1_allowed) {
                /*
                 * W/A - seems to solve weird behavior. We need to remove this
@@ -1412,10 +1416,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                                       PCIE_LINK_STATE_CLKPM);
        }
 
-       err = pci_enable_device(pdev);
-       if (err)
-               goto out_no_pci;
-
        pci_set_master(pdev);
 
        err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
index f45eb29c2ede0b62cc1723f82ae7f30cc1f5a8ed..1424335163b97e4d6625a8fca7ec7c19a1d07c9c 100644 (file)
@@ -1102,6 +1102,8 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
                 * non-AGG queue.
                 */
                iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
+
+               ssn = trans_pcie->txq[txq_id].q.read_ptr;
        }
 
        /* Place first TFD at index corresponding to start sequence number.
index 9d7c0e6c4fc7419facd68a3c61f251fbedb86143..37f873bb342f5043046b18c3fe3b573ebdedac64 100644 (file)
@@ -1422,13 +1422,19 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac)
  */
 int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
 {
+       int ret = 0;
+
        if (!priv->media_connected)
                return 0;
 
        switch (priv->bss_mode) {
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_P2P_CLIENT:
-               return mwifiex_deauthenticate_infra(priv, mac);
+               ret = mwifiex_deauthenticate_infra(priv, mac);
+               if (ret)
+                       cfg80211_disconnected(priv->netdev, 0, NULL, 0,
+                                             GFP_KERNEL);
+               break;
        case NL80211_IFTYPE_ADHOC:
                return mwifiex_send_cmd_sync(priv,
                                             HostCmd_CMD_802_11_AD_HOC_STOP,
@@ -1440,7 +1446,7 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
                break;
        }
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(mwifiex_deauthenticate);
 
index fd778337deeec4e58b1bddb4d08668aaf51890d9..c2b91f566e05073d83dbbe60e265a78ddaf8fa9e 100644 (file)
@@ -358,10 +358,12 @@ process_start:
                }
        } while (true);
 
-       if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter))
+       spin_lock_irqsave(&adapter->main_proc_lock, flags);
+       if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter)) {
+               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
                goto process_start;
+       }
 
-       spin_lock_irqsave(&adapter->main_proc_lock, flags);
        adapter->mwifiex_processing = false;
        spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
 
index 8b057524b252e535307644ddaa98e12df75a35cd..8c351f71f72f9f6f6a17650198ba805bf7c1f5cd 100644 (file)
@@ -118,7 +118,8 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
        dev_dbg(adapter->dev,
                "info: successfully disconnected from %pM: reason code %d\n",
                priv->cfg_bssid, reason_code);
-       if (priv->bss_mode == NL80211_IFTYPE_STATION) {
+       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
+           priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
                cfg80211_disconnected(priv->netdev, reason_code, NULL, 0,
                                      GFP_KERNEL);
        }
index 76d95deb274be56feb9803adb5b8d198f0c35bd0..dc49e525ae5e55e9a090308b80122998e08857d8 100644 (file)
@@ -105,13 +105,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
                goto exit_release_regions;
        }
 
-       pci_enable_msi(pci_dev);
-
        hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
        if (!hw) {
                rt2x00_probe_err("Failed to allocate hardware\n");
                retval = -ENOMEM;
-               goto exit_disable_msi;
+               goto exit_release_regions;
        }
 
        pci_set_drvdata(pci_dev, hw);
@@ -152,9 +150,6 @@ exit_free_reg:
 exit_free_device:
        ieee80211_free_hw(hw);
 
-exit_disable_msi:
-       pci_disable_msi(pci_dev);
-
 exit_release_regions:
        pci_release_regions(pci_dev);
 
@@ -179,8 +174,6 @@ void rt2x00pci_remove(struct pci_dev *pci_dev)
        rt2x00pci_free_reg(rt2x00dev);
        ieee80211_free_hw(hw);
 
-       pci_disable_msi(pci_dev);
-
        /*
         * Free the PCI device data.
         */
index 763cf1defab5b4027b22604c3771e4c8465a4405..5a060e537fbe99171f234c29a6320f75ad22a1f3 100644 (file)
@@ -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);
        }
index b45bce20ad7624421b7500cff3ccfc5a49f9204f..1b08d879837231256f4cc954bbe8fbd0c4aa9391 100644 (file)
@@ -39,11 +39,15 @@ static int connect_rings(struct backend_info *);
 static void connect(struct backend_info *);
 static void backend_create_xenvif(struct backend_info *be);
 static void unregister_hotplug_status_watch(struct backend_info *be);
+static void set_backend_state(struct backend_info *be,
+                             enum xenbus_state state);
 
 static int netback_remove(struct xenbus_device *dev)
 {
        struct backend_info *be = dev_get_drvdata(&dev->dev);
 
+       set_backend_state(be, XenbusStateClosed);
+
        unregister_hotplug_status_watch(be);
        if (be->vif) {
                kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
index 9d2009a9004d14bc6f80bc9e6192a478fc9362aa..78cc76053328c2c8c70bff559f5dc0f903a241df 100644 (file)
@@ -74,10 +74,4 @@ config OF_MTD
        depends on MTD
        def_bool y
 
-config OF_RESERVED_MEM
-       depends on OF_FLATTREE && (DMA_CMA || (HAVE_GENERIC_DMA_COHERENT && HAVE_MEMBLOCK))
-       def_bool y
-       help
-         Initialization code for DMA reserved memory
-
 endmenu # OF
index ed9660adad7751357b49914fcb046fa64470767c..efd05102c40533100794b7d6a7626f583a1f0cdc 100644 (file)
@@ -9,4 +9,3 @@ obj-$(CONFIG_OF_MDIO)   += of_mdio.o
 obj-$(CONFIG_OF_PCI)   += of_pci.o
 obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
 obj-$(CONFIG_OF_MTD)   += of_mtd.o
-obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
index 865d3f66c86b2735810e1f6d4d7a219dfd9b350e..7d4c70f859e30687bcd0892c195f9cbfc34826dc 100644 (file)
@@ -303,10 +303,8 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
        struct device_node *cpun, *cpus;
 
        cpus = of_find_node_by_path("/cpus");
-       if (!cpus) {
-               pr_warn("Missing cpus node, bailing out\n");
+       if (!cpus)
                return NULL;
-       }
 
        for_each_child_of_node(cpus, cpun) {
                if (of_node_cmp(cpun->type, "cpu"))
index 229dd9d69e180529cc7e3135d71001421ab9deea..a4fa9ad31b8f7cfb62f45abf47ada0649d87b867 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/random.h>
 
 #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
 #ifdef CONFIG_PPC
@@ -803,14 +802,3 @@ void __init unflatten_device_tree(void)
 }
 
 #endif /* CONFIG_OF_EARLY_FLATTREE */
-
-/* Feed entire flattened device tree into the random pool */
-static int __init add_fdt_randomness(void)
-{
-       if (initial_boot_params)
-               add_device_randomness(initial_boot_params,
-                               be32_to_cpu(initial_boot_params->totalsize));
-
-       return 0;
-}
-core_initcall(add_fdt_randomness);
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
deleted file mode 100644 (file)
index 0fe40c7..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Device tree based initialization code for reserved memory.
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- * Author: Marek Szyprowski <m.szyprowski@samsung.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 optional) any later version of the license.
- */
-
-#include <linux/memblock.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/of_fdt.h>
-#include <linux/of_platform.h>
-#include <linux/mm.h>
-#include <linux/sizes.h>
-#include <linux/mm_types.h>
-#include <linux/dma-contiguous.h>
-#include <linux/dma-mapping.h>
-#include <linux/of_reserved_mem.h>
-
-#define MAX_RESERVED_REGIONS   16
-struct reserved_mem {
-       phys_addr_t             base;
-       unsigned long           size;
-       struct cma              *cma;
-       char                    name[32];
-};
-static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
-static int reserved_mem_count;
-
-static int __init fdt_scan_reserved_mem(unsigned long node, const char *uname,
-                                       int depth, void *data)
-{
-       struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
-       phys_addr_t base, size;
-       int is_cma, is_reserved;
-       unsigned long len;
-       const char *status;
-       __be32 *prop;
-
-       is_cma = IS_ENABLED(CONFIG_DMA_CMA) &&
-              of_flat_dt_is_compatible(node, "linux,contiguous-memory-region");
-       is_reserved = of_flat_dt_is_compatible(node, "reserved-memory-region");
-
-       if (!is_reserved && !is_cma) {
-               /* ignore node and scan next one */
-               return 0;
-       }
-
-       status = of_get_flat_dt_prop(node, "status", &len);
-       if (status && strcmp(status, "okay") != 0) {
-               /* ignore disabled node nad scan next one */
-               return 0;
-       }
-
-       prop = of_get_flat_dt_prop(node, "reg", &len);
-       if (!prop || (len < (dt_root_size_cells + dt_root_addr_cells) *
-                            sizeof(__be32))) {
-               pr_err("Reserved mem: node %s, incorrect \"reg\" property\n",
-                      uname);
-               /* ignore node and scan next one */
-               return 0;
-       }
-       base = dt_mem_next_cell(dt_root_addr_cells, &prop);
-       size = dt_mem_next_cell(dt_root_size_cells, &prop);
-
-       if (!size) {
-               /* ignore node and scan next one */
-               return 0;
-       }
-
-       pr_info("Reserved mem: found %s, memory base %lx, size %ld MiB\n",
-               uname, (unsigned long)base, (unsigned long)size / SZ_1M);
-
-       if (reserved_mem_count == ARRAY_SIZE(reserved_mem))
-               return -ENOSPC;
-
-       rmem->base = base;
-       rmem->size = size;
-       strlcpy(rmem->name, uname, sizeof(rmem->name));
-
-       if (is_cma) {
-               struct cma *cma;
-               if (dma_contiguous_reserve_area(size, base, 0, &cma) == 0) {
-                       rmem->cma = cma;
-                       reserved_mem_count++;
-                       if (of_get_flat_dt_prop(node,
-                                               "linux,default-contiguous-region",
-                                               NULL))
-                               dma_contiguous_set_default(cma);
-               }
-       } else if (is_reserved) {
-               if (memblock_remove(base, size) == 0)
-                       reserved_mem_count++;
-               else
-                       pr_err("Failed to reserve memory for %s\n", uname);
-       }
-
-       return 0;
-}
-
-static struct reserved_mem *get_dma_memory_region(struct device *dev)
-{
-       struct device_node *node;
-       const char *name;
-       int i;
-
-       node = of_parse_phandle(dev->of_node, "memory-region", 0);
-       if (!node)
-               return NULL;
-
-       name = kbasename(node->full_name);
-       for (i = 0; i < reserved_mem_count; i++)
-               if (strcmp(name, reserved_mem[i].name) == 0)
-                       return &reserved_mem[i];
-       return NULL;
-}
-
-/**
- * of_reserved_mem_device_init() - assign reserved memory region to given device
- *
- * This function assign memory region pointed by "memory-region" device tree
- * property to the given device.
- */
-void of_reserved_mem_device_init(struct device *dev)
-{
-       struct reserved_mem *region = get_dma_memory_region(dev);
-       if (!region)
-               return;
-
-       if (region->cma) {
-               dev_set_cma_area(dev, region->cma);
-               pr_info("Assigned CMA %s to %s device\n", region->name,
-                       dev_name(dev));
-       } else {
-               if (dma_declare_coherent_memory(dev, region->base, region->base,
-                   region->size, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) != 0)
-                       pr_info("Declared reserved memory %s to %s device\n",
-                               region->name, dev_name(dev));
-       }
-}
-
-/**
- * of_reserved_mem_device_release() - release reserved memory device structures
- *
- * This function releases structures allocated for memory region handling for
- * the given device.
- */
-void of_reserved_mem_device_release(struct device *dev)
-{
-       struct reserved_mem *region = get_dma_memory_region(dev);
-       if (!region && !region->cma)
-               dma_release_declared_memory(dev);
-}
-
-/**
- * early_init_dt_scan_reserved_mem() - create reserved memory regions
- *
- * This function grabs memory from early allocator for device exclusive use
- * defined in device tree structures. It should be called by arch specific code
- * once the early allocator (memblock) has been activated and all other
- * subsystems have already allocated/reserved memory.
- */
-void __init early_init_dt_scan_reserved_mem(void)
-{
-       of_scan_flat_dt_by_path("/memory/reserved-memory",
-                               fdt_scan_reserved_mem, NULL);
-}
index 9b439ac63d8e73eef85aa490d5cab6ec825120b7..f6dcde22082155577b3cdf0b0f55f103e059cae6 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
 
 const struct of_device_id of_default_bus_match_table[] = {
@@ -219,8 +218,6 @@ static struct platform_device *of_platform_device_create_pdata(
        dev->dev.bus = &platform_bus_type;
        dev->dev.platform_data = platform_data;
 
-       of_reserved_mem_device_init(&dev->dev);
-
        /* We do not fill the DMA ops for platform devices by default.
         * This is currently the responsibility of the platform code
         * to do such, possibly using a device notifier
@@ -228,7 +225,6 @@ static struct platform_device *of_platform_device_create_pdata(
 
        if (of_device_add(dev) != 0) {
                platform_device_put(dev);
-               of_reserved_mem_device_release(&dev->dev);
                return NULL;
        }
 
index 2a47e82821dacff72dd227950a6c3de828755053..5440131cd4eecff5fb74a3d9bbcd63d00f4d1ad1 100644 (file)
@@ -411,13 +411,10 @@ EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
 static int pcihp_is_ejectable(acpi_handle handle)
 {
        acpi_status status;
-       acpi_handle tmp;
        unsigned long long removable;
-       status = acpi_get_handle(handle, "_ADR", &tmp);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(handle, "_ADR"))
                return 0;
-       status = acpi_get_handle(handle, "_EJ0", &tmp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(handle, "_EJ0"))
                return 1;
        status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable);
        if (ACPI_SUCCESS(status) && removable)
index 0b7d23b4ad954489b657480d0ee08a3b7b2d81d8..be12fbfcae1042e90c00d192bffe46c47821b6c4 100644 (file)
@@ -994,14 +994,16 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
 
                /*
                 * This bridge should have been registered as a hotplug function
-                * under its parent, so the context has to be there.  If not, we
-                * are in deep goo.
+                * under its parent, so the context should be there, unless the
+                * parent is going to be handled by pciehp, in which case this
+                * bridge is not interesting to us either.
                 */
                mutex_lock(&acpiphp_context_lock);
                context = acpiphp_get_context(handle);
-               if (WARN_ON(!context)) {
+               if (!context) {
                        mutex_unlock(&acpiphp_context_lock);
                        put_device(&bus->dev);
+                       pci_dev_put(bridge->pci_dev);
                        kfree(bridge);
                        return;
                }
index b0299e6d9a3f2d1359f78454eb67e399ea6d3eb1..dfd1f59de729c6293416d789fb6f665dc09bf701 100644 (file)
@@ -181,7 +181,6 @@ static bool acpi_pci_power_manageable(struct pci_dev *dev)
 static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 {
        acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
-       acpi_handle tmp;
        static const u8 state_conv[] = {
                [PCI_D0] = ACPI_STATE_D0,
                [PCI_D1] = ACPI_STATE_D1,
@@ -192,7 +191,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
        int error = -EINVAL;
 
        /* If the ACPI device has _EJ0, ignore the device */
-       if (!handle || ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
+       if (!handle || acpi_has_method(handle, "_EJ0"))
                return -ENODEV;
 
        switch (state) {
index 96d6b2eef4f2a1209f2c9f113e3932b8eb812738..b51a7460cc49bc03b4c055e8f46bfe2fedf718ff 100644 (file)
@@ -504,6 +504,7 @@ config ASUS_WMI
        depends on BACKLIGHT_CLASS_DEVICE
        depends on RFKILL || RFKILL = n
        depends on HOTPLUG_PCI
+       depends on ACPI_VIDEO || ACPI_VIDEO = n
        select INPUT_SPARSEKMAP
        select LEDS_CLASS
        select NEW_LEDS
index a6afd4108beb0592c15604efa9f779180d5349ef..aefcc32e563479d2b22404fdd75ceb7072423d16 100644 (file)
@@ -190,16 +190,10 @@ struct eeepc_laptop {
  */
 static int write_acpi_int(acpi_handle handle, const char *method, int val)
 {
-       struct acpi_object_list params;
-       union acpi_object in_obj;
        acpi_status status;
 
-       params.count = 1;
-       params.pointer = &in_obj;
-       in_obj.type = ACPI_TYPE_INTEGER;
-       in_obj.integer.value = val;
+       status = acpi_execute_simple_method(handle, (char *)method, val);
 
-       status = acpi_evaluate_object(handle, (char *)method, &params, NULL);
        return (status == AE_OK ? 0 : -1);
 }
 
index 52b8a97efde150f52d393b4e7a6c0be9360bc9ef..9d30d69aa78f24a3bbb1caa71f797f9c520bbc5c 100644 (file)
@@ -219,8 +219,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
        { .type = ACPI_TYPE_INTEGER }
        };
        struct acpi_object_list arg_list = { 4, &params[0] };
-       struct acpi_buffer output;
-       union acpi_object out_obj;
+       unsigned long long value;
        acpi_handle handle = NULL;
 
        status = acpi_get_handle(fujitsu_hotkey->acpi_handle, "FUNC", &handle);
@@ -235,10 +234,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
        params[2].integer.value = arg1;
        params[3].integer.value = arg2;
 
-       output.length = sizeof(out_obj);
-       output.pointer = &out_obj;
-
-       status = acpi_evaluate_object(handle, NULL, &arg_list, &output);
+       status = acpi_evaluate_integer(handle, NULL, &arg_list, &value);
        if (ACPI_FAILURE(status)) {
                vdbg_printk(FUJLAPTOP_DBG_WARN,
                        "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n",
@@ -246,18 +242,10 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
                return -ENODEV;
        }
 
-       if (out_obj.type != ACPI_TYPE_INTEGER) {
-               vdbg_printk(FUJLAPTOP_DBG_WARN,
-                       "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) did not "
-                       "return an integer\n",
-                       cmd, arg0, arg1, arg2);
-               return -ENODEV;
-       }
-
        vdbg_printk(FUJLAPTOP_DBG_TRACE,
                "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n",
-                       cmd, arg0, arg1, arg2, (int)out_obj.integer.value);
-       return out_obj.integer.value;
+                       cmd, arg0, arg1, arg2, (int)value);
+       return value;
 }
 
 #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
@@ -317,8 +305,6 @@ static enum led_brightness kblamps_get(struct led_classdev *cdev)
 static int set_lcd_level(int level)
 {
        acpi_status status = AE_OK;
-       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list arg_list = { 1, &arg0 };
        acpi_handle handle = NULL;
 
        vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n",
@@ -333,9 +319,8 @@ static int set_lcd_level(int level)
                return -ENODEV;
        }
 
-       arg0.integer.value = level;
 
-       status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+       status = acpi_execute_simple_method(handle, NULL, level);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -345,8 +330,6 @@ static int set_lcd_level(int level)
 static int set_lcd_level_alt(int level)
 {
        acpi_status status = AE_OK;
-       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list arg_list = { 1, &arg0 };
        acpi_handle handle = NULL;
 
        vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBL2 [%d]\n",
@@ -361,9 +344,7 @@ static int set_lcd_level_alt(int level)
                return -ENODEV;
        }
 
-       arg0.integer.value = level;
-
-       status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+       status = acpi_execute_simple_method(handle, NULL, level);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -586,11 +567,10 @@ static struct platform_driver fujitsupf_driver = {
 
 static void dmi_check_cb_common(const struct dmi_system_id *id)
 {
-       acpi_handle handle;
        pr_info("Identified laptop model '%s'\n", id->ident);
        if (use_alt_lcd_levels == -1) {
-               if (ACPI_SUCCESS(acpi_get_handle(NULL,
-                               "\\_SB.PCI0.LPCB.FJEX.SBL2", &handle)))
+               if (acpi_has_method(NULL,
+                               "\\_SB.PCI0.LPCB.FJEX.SBL2"))
                        use_alt_lcd_levels = 1;
                else
                        use_alt_lcd_levels = 0;
@@ -653,7 +633,6 @@ static struct dmi_system_id fujitsu_dmi_table[] = {
 
 static int acpi_fujitsu_add(struct acpi_device *device)
 {
-       acpi_handle handle;
        int result = 0;
        int state = 0;
        struct input_dev *input;
@@ -702,8 +681,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)
 
        fujitsu->dev = device;
 
-       if (ACPI_SUCCESS
-           (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) {
+       if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
                vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
                if (ACPI_FAILURE
                    (acpi_evaluate_object
@@ -803,7 +781,6 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event)
 
 static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
 {
-       acpi_handle handle;
        int result = 0;
        int state = 0;
        struct input_dev *input;
@@ -866,8 +843,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
 
        fujitsu_hotkey->dev = device;
 
-       if (ACPI_SUCCESS
-           (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) {
+       if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
                vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
                if (ACPI_FAILURE
                    (acpi_evaluate_object
index 89c4519d48ac80d2a54f42ceabf7a48b792e871c..6788acc22ab97f01b410240eef0a5b2082c98550 100644 (file)
@@ -72,8 +72,15 @@ enum {
        VPCCMD_W_BL_POWER = 0x33,
 };
 
+struct ideapad_rfk_priv {
+       int dev;
+       struct ideapad_private *priv;
+};
+
 struct ideapad_private {
+       struct acpi_device *adev;
        struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
+       struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM];
        struct platform_device *platform_device;
        struct input_dev *inputdev;
        struct backlight_device *blightdev;
@@ -81,8 +88,6 @@ struct ideapad_private {
        unsigned long cfg;
 };
 
-static acpi_handle ideapad_handle;
-static struct ideapad_private *ideapad_priv;
 static bool no_bt_rfkill;
 module_param(no_bt_rfkill, bool, 0444);
 MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
@@ -200,34 +205,38 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
  */
 static int debugfs_status_show(struct seq_file *s, void *data)
 {
+       struct ideapad_private *priv = s->private;
        unsigned long value;
 
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &value))
+       if (!priv)
+               return -EINVAL;
+
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value))
                seq_printf(s, "Backlight max:\t%lu\n", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_BL, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value))
                seq_printf(s, "Backlight now:\t%lu\n", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value))
                seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");
        seq_printf(s, "=====================\n");
 
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_RF, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value))
                seq_printf(s, "Radio status:\t%s(%lu)\n",
                           value ? "On" : "Off", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_WIFI, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value))
                seq_printf(s, "Wifi status:\t%s(%lu)\n",
                           value ? "On" : "Off", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_BT, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value))
                seq_printf(s, "BT status:\t%s(%lu)\n",
                           value ? "On" : "Off", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_3G, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value))
                seq_printf(s, "3G status:\t%s(%lu)\n",
                           value ? "On" : "Off", value);
        seq_printf(s, "=====================\n");
 
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_TOUCHPAD, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value))
                seq_printf(s, "Touchpad status:%s(%lu)\n",
                           value ? "On" : "Off", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value))
                seq_printf(s, "Camera status:\t%s(%lu)\n",
                           value ? "On" : "Off", value);
 
@@ -236,7 +245,7 @@ static int debugfs_status_show(struct seq_file *s, void *data)
 
 static int debugfs_status_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, debugfs_status_show, NULL);
+       return single_open(file, debugfs_status_show, inode->i_private);
 }
 
 static const struct file_operations debugfs_status_fops = {
@@ -249,21 +258,23 @@ static const struct file_operations debugfs_status_fops = {
 
 static int debugfs_cfg_show(struct seq_file *s, void *data)
 {
-       if (!ideapad_priv) {
+       struct ideapad_private *priv = s->private;
+
+       if (!priv) {
                seq_printf(s, "cfg: N/A\n");
        } else {
                seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
-                          ideapad_priv->cfg);
-               if (test_bit(CFG_BT_BIT, &ideapad_priv->cfg))
+                          priv->cfg);
+               if (test_bit(CFG_BT_BIT, &priv->cfg))
                        seq_printf(s, "Bluetooth ");
-               if (test_bit(CFG_3G_BIT, &ideapad_priv->cfg))
+               if (test_bit(CFG_3G_BIT, &priv->cfg))
                        seq_printf(s, "3G ");
-               if (test_bit(CFG_WIFI_BIT, &ideapad_priv->cfg))
+               if (test_bit(CFG_WIFI_BIT, &priv->cfg))
                        seq_printf(s, "Wireless ");
-               if (test_bit(CFG_CAMERA_BIT, &ideapad_priv->cfg))
+               if (test_bit(CFG_CAMERA_BIT, &priv->cfg))
                        seq_printf(s, "Camera ");
                seq_printf(s, "\nGraphic: ");
-               switch ((ideapad_priv->cfg)&0x700) {
+               switch ((priv->cfg)&0x700) {
                case 0x100:
                        seq_printf(s, "Intel");
                        break;
@@ -287,7 +298,7 @@ static int debugfs_cfg_show(struct seq_file *s, void *data)
 
 static int debugfs_cfg_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, debugfs_cfg_show, NULL);
+       return single_open(file, debugfs_cfg_show, inode->i_private);
 }
 
 static const struct file_operations debugfs_cfg_fops = {
@@ -308,14 +319,14 @@ static int ideapad_debugfs_init(struct ideapad_private *priv)
                goto errout;
        }
 
-       node = debugfs_create_file("cfg", S_IRUGO, priv->debug, NULL,
+       node = debugfs_create_file("cfg", S_IRUGO, priv->debug, priv,
                                   &debugfs_cfg_fops);
        if (!node) {
                pr_err("failed to create cfg in debugfs");
                goto errout;
        }
 
-       node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL,
+       node = debugfs_create_file("status", S_IRUGO, priv->debug, priv,
                                   &debugfs_status_fops);
        if (!node) {
                pr_err("failed to create status in debugfs");
@@ -342,8 +353,9 @@ static ssize_t show_ideapad_cam(struct device *dev,
                                char *buf)
 {
        unsigned long result;
+       struct ideapad_private *priv = dev_get_drvdata(dev);
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &result))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result))
                return sprintf(buf, "-1\n");
        return sprintf(buf, "%lu\n", result);
 }
@@ -353,12 +365,13 @@ static ssize_t store_ideapad_cam(struct device *dev,
                                 const char *buf, size_t count)
 {
        int ret, state;
+       struct ideapad_private *priv = dev_get_drvdata(dev);
 
        if (!count)
                return 0;
        if (sscanf(buf, "%i", &state) != 1)
                return -EINVAL;
-       ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state);
+       ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
        if (ret < 0)
                return -EIO;
        return count;
@@ -371,8 +384,9 @@ static ssize_t show_ideapad_fan(struct device *dev,
                                char *buf)
 {
        unsigned long result;
+       struct ideapad_private *priv = dev_get_drvdata(dev);
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_FAN, &result))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result))
                return sprintf(buf, "-1\n");
        return sprintf(buf, "%lu\n", result);
 }
@@ -382,6 +396,7 @@ static ssize_t store_ideapad_fan(struct device *dev,
                                 const char *buf, size_t count)
 {
        int ret, state;
+       struct ideapad_private *priv = dev_get_drvdata(dev);
 
        if (!count)
                return 0;
@@ -389,7 +404,7 @@ static ssize_t store_ideapad_fan(struct device *dev,
                return -EINVAL;
        if (state < 0 || state > 4 || state == 3)
                return -EINVAL;
-       ret = write_ec_cmd(ideapad_handle, VPCCMD_W_FAN, state);
+       ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
        if (ret < 0)
                return -EIO;
        return count;
@@ -415,7 +430,8 @@ static umode_t ideapad_is_visible(struct kobject *kobj,
                supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
        else if (attr == &dev_attr_fan_mode.attr) {
                unsigned long value;
-               supported = !read_ec_data(ideapad_handle, VPCCMD_R_FAN, &value);
+               supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN,
+                                         &value);
        } else
                supported = true;
 
@@ -445,9 +461,9 @@ const struct ideapad_rfk_data ideapad_rfk_data[] = {
 
 static int ideapad_rfk_set(void *data, bool blocked)
 {
-       unsigned long opcode = (unsigned long)data;
+       struct ideapad_rfk_priv *priv = data;
 
-       return write_ec_cmd(ideapad_handle, opcode, !blocked);
+       return write_ec_cmd(priv->priv->adev->handle, priv->dev, !blocked);
 }
 
 static struct rfkill_ops ideapad_rfk_ops = {
@@ -459,7 +475,7 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv)
        unsigned long hw_blocked;
        int i;
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_RF, &hw_blocked))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
                return;
        hw_blocked = !hw_blocked;
 
@@ -468,27 +484,30 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv)
                        rfkill_set_hw_state(priv->rfk[i], hw_blocked);
 }
 
-static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
+static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
 {
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
        int ret;
        unsigned long sw_blocked;
 
        if (no_bt_rfkill &&
            (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
                /* Force to enable bluetooth when no_bt_rfkill=1 */
-               write_ec_cmd(ideapad_handle,
+               write_ec_cmd(priv->adev->handle,
                             ideapad_rfk_data[dev].opcode, 1);
                return 0;
        }
-
-       priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adevice->dev,
-                                     ideapad_rfk_data[dev].type, &ideapad_rfk_ops,
-                                     (void *)(long)dev);
+       priv->rfk_priv[dev].dev = dev;
+       priv->rfk_priv[dev].priv = priv;
+
+       priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name,
+                                     &priv->platform_device->dev,
+                                     ideapad_rfk_data[dev].type,
+                                     &ideapad_rfk_ops,
+                                     &priv->rfk_priv[dev]);
        if (!priv->rfk[dev])
                return -ENOMEM;
 
-       if (read_ec_data(ideapad_handle, ideapad_rfk_data[dev].opcode-1,
+       if (read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1,
                         &sw_blocked)) {
                rfkill_init_sw_state(priv->rfk[dev], 0);
        } else {
@@ -504,10 +523,8 @@ static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
        return 0;
 }
 
-static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
+static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
 {
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
-
        if (!priv->rfk[dev])
                return;
 
@@ -518,37 +535,16 @@ static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
 /*
  * Platform device
  */
-static int ideapad_platform_init(struct ideapad_private *priv)
+static int ideapad_sysfs_init(struct ideapad_private *priv)
 {
-       int result;
-
-       priv->platform_device = platform_device_alloc("ideapad", -1);
-       if (!priv->platform_device)
-               return -ENOMEM;
-       platform_set_drvdata(priv->platform_device, priv);
-
-       result = platform_device_add(priv->platform_device);
-       if (result)
-               goto fail_platform_device;
-
-       result = sysfs_create_group(&priv->platform_device->dev.kobj,
+       return sysfs_create_group(&priv->platform_device->dev.kobj,
                                    &ideapad_attribute_group);
-       if (result)
-               goto fail_sysfs;
-       return 0;
-
-fail_sysfs:
-       platform_device_del(priv->platform_device);
-fail_platform_device:
-       platform_device_put(priv->platform_device);
-       return result;
 }
 
-static void ideapad_platform_exit(struct ideapad_private *priv)
+static void ideapad_sysfs_exit(struct ideapad_private *priv)
 {
        sysfs_remove_group(&priv->platform_device->dev.kobj,
                           &ideapad_attribute_group);
-       platform_device_unregister(priv->platform_device);
 }
 
 /*
@@ -623,7 +619,7 @@ static void ideapad_input_novokey(struct ideapad_private *priv)
 {
        unsigned long long_pressed;
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_NOVO, &long_pressed))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))
                return;
        if (long_pressed)
                ideapad_input_report(priv, 17);
@@ -635,7 +631,7 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv)
 {
        unsigned long bit, value;
 
-       read_ec_data(ideapad_handle, VPCCMD_R_SPECIAL_BUTTONS, &value);
+       read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value);
 
        for (bit = 0; bit < 16; bit++) {
                if (test_bit(bit, &value)) {
@@ -662,19 +658,28 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv)
  */
 static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
 {
+       struct ideapad_private *priv = bl_get_data(blightdev);
        unsigned long now;
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
+       if (!priv)
+               return -EINVAL;
+
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
                return -EIO;
        return now;
 }
 
 static int ideapad_backlight_update_status(struct backlight_device *blightdev)
 {
-       if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL,
+       struct ideapad_private *priv = bl_get_data(blightdev);
+
+       if (!priv)
+               return -EINVAL;
+
+       if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,
                         blightdev->props.brightness))
                return -EIO;
-       if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL_POWER,
+       if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,
                         blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
                return -EIO;
 
@@ -692,11 +697,11 @@ static int ideapad_backlight_init(struct ideapad_private *priv)
        struct backlight_properties props;
        unsigned long max, now, power;
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &max))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max))
                return -EIO;
-       if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
                return -EIO;
-       if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
                return -EIO;
 
        memset(&props, 0, sizeof(struct backlight_properties));
@@ -734,7 +739,7 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv)
 
        if (!blightdev)
                return;
-       if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
                return;
        blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
 }
@@ -745,7 +750,7 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
 
        /* if we control brightness via acpi video driver */
        if (priv->blightdev == NULL) {
-               read_ec_data(ideapad_handle, VPCCMD_R_BL, &now);
+               read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
                return;
        }
 
@@ -755,19 +760,12 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
 /*
  * module init/exit
  */
-static const struct acpi_device_id ideapad_device_ids[] = {
-       { "VPC2004", 0},
-       { "", 0},
-};
-MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
-
-static void ideapad_sync_touchpad_state(struct acpi_device *adevice)
+static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
 {
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
        unsigned long value;
 
        /* Without reading from EC touchpad LED doesn't switch state */
-       if (!read_ec_data(adevice->handle, VPCCMD_R_TOUCHPAD, &value)) {
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
                /* Some IdeaPads don't really turn off touchpad - they only
                 * switch the LED state. We (de)activate KBC AUX port to turn
                 * touchpad off and on. We send KEY_TOUCHPAD_OFF and
@@ -779,26 +777,77 @@ static void ideapad_sync_touchpad_state(struct acpi_device *adevice)
        }
 }
 
-static int ideapad_acpi_add(struct acpi_device *adevice)
+static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+       struct ideapad_private *priv = data;
+       unsigned long vpc1, vpc2, vpc_bit;
+
+       if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
+               return;
+       if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
+               return;
+
+       vpc1 = (vpc2 << 8) | vpc1;
+       for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
+               if (test_bit(vpc_bit, &vpc1)) {
+                       switch (vpc_bit) {
+                       case 9:
+                               ideapad_sync_rfk_state(priv);
+                               break;
+                       case 13:
+                       case 11:
+                       case 7:
+                       case 6:
+                               ideapad_input_report(priv, vpc_bit);
+                               break;
+                       case 5:
+                               ideapad_sync_touchpad_state(priv);
+                               break;
+                       case 4:
+                               ideapad_backlight_notify_brightness(priv);
+                               break;
+                       case 3:
+                               ideapad_input_novokey(priv);
+                               break;
+                       case 2:
+                               ideapad_backlight_notify_power(priv);
+                               break;
+                       case 0:
+                               ideapad_check_special_buttons(priv);
+                               break;
+                       default:
+                               pr_info("Unknown event: %lu\n", vpc_bit);
+                       }
+               }
+       }
+}
+
+static int ideapad_acpi_add(struct platform_device *pdev)
 {
        int ret, i;
        int cfg;
        struct ideapad_private *priv;
+       struct acpi_device *adev;
+
+       ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
+       if (ret)
+               return -ENODEV;
 
-       if (read_method_int(adevice->handle, "_CFG", &cfg))
+       if (read_method_int(adev->handle, "_CFG", &cfg))
                return -ENODEV;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
-       dev_set_drvdata(&adevice->dev, priv);
-       ideapad_priv = priv;
-       ideapad_handle = adevice->handle;
+
+       dev_set_drvdata(&pdev->dev, priv);
        priv->cfg = cfg;
+       priv->adev = adev;
+       priv->platform_device = pdev;
 
-       ret = ideapad_platform_init(priv);
+       ret = ideapad_sysfs_init(priv);
        if (ret)
-               goto platform_failed;
+               goto sysfs_failed;
 
        ret = ideapad_debugfs_init(priv);
        if (ret)
@@ -810,117 +859,92 @@ static int ideapad_acpi_add(struct acpi_device *adevice)
 
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
                if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
-                       ideapad_register_rfkill(adevice, i);
+                       ideapad_register_rfkill(priv, i);
                else
                        priv->rfk[i] = NULL;
        }
        ideapad_sync_rfk_state(priv);
-       ideapad_sync_touchpad_state(adevice);
+       ideapad_sync_touchpad_state(priv);
 
        if (!acpi_video_backlight_support()) {
                ret = ideapad_backlight_init(priv);
                if (ret && ret != -ENODEV)
                        goto backlight_failed;
        }
+       ret = acpi_install_notify_handler(adev->handle,
+               ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);
+       if (ret)
+               goto notification_failed;
 
        return 0;
-
+notification_failed:
+       ideapad_backlight_exit(priv);
 backlight_failed:
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
-               ideapad_unregister_rfkill(adevice, i);
+               ideapad_unregister_rfkill(priv, i);
        ideapad_input_exit(priv);
 input_failed:
        ideapad_debugfs_exit(priv);
 debugfs_failed:
-       ideapad_platform_exit(priv);
-platform_failed:
+       ideapad_sysfs_exit(priv);
+sysfs_failed:
        kfree(priv);
        return ret;
 }
 
-static int ideapad_acpi_remove(struct acpi_device *adevice)
+static int ideapad_acpi_remove(struct platform_device *pdev)
 {
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
+       struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
        int i;
 
+       acpi_remove_notify_handler(priv->adev->handle,
+               ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
        ideapad_backlight_exit(priv);
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
-               ideapad_unregister_rfkill(adevice, i);
+               ideapad_unregister_rfkill(priv, i);
        ideapad_input_exit(priv);
        ideapad_debugfs_exit(priv);
-       ideapad_platform_exit(priv);
-       dev_set_drvdata(&adevice->dev, NULL);
+       ideapad_sysfs_exit(priv);
+       dev_set_drvdata(&pdev->dev, NULL);
        kfree(priv);
 
        return 0;
 }
 
-static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
+#ifdef CONFIG_PM_SLEEP
+static int ideapad_acpi_resume(struct device *device)
 {
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
-       acpi_handle handle = adevice->handle;
-       unsigned long vpc1, vpc2, vpc_bit;
-
-       if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
-               return;
-       if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
-               return;
+       struct ideapad_private *priv;
 
-       vpc1 = (vpc2 << 8) | vpc1;
-       for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
-               if (test_bit(vpc_bit, &vpc1)) {
-                       switch (vpc_bit) {
-                       case 9:
-                               ideapad_sync_rfk_state(priv);
-                               break;
-                       case 13:
-                       case 11:
-                       case 7:
-                       case 6:
-                               ideapad_input_report(priv, vpc_bit);
-                               break;
-                       case 5:
-                               ideapad_sync_touchpad_state(adevice);
-                               break;
-                       case 4:
-                               ideapad_backlight_notify_brightness(priv);
-                               break;
-                       case 3:
-                               ideapad_input_novokey(priv);
-                               break;
-                       case 2:
-                               ideapad_backlight_notify_power(priv);
-                               break;
-                       case 0:
-                               ideapad_check_special_buttons(priv);
-                               break;
-                       default:
-                               pr_info("Unknown event: %lu\n", vpc_bit);
-                       }
-               }
-       }
-}
+       if (!device)
+               return -EINVAL;
+       priv = dev_get_drvdata(device);
 
-static int ideapad_acpi_resume(struct device *device)
-{
-       ideapad_sync_rfk_state(ideapad_priv);
-       ideapad_sync_touchpad_state(to_acpi_device(device));
+       ideapad_sync_rfk_state(priv);
+       ideapad_sync_touchpad_state(priv);
        return 0;
 }
-
+#endif
 static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
 
-static struct acpi_driver ideapad_acpi_driver = {
-       .name = "ideapad_acpi",
-       .class = "IdeaPad",
-       .ids = ideapad_device_ids,
-       .ops.add = ideapad_acpi_add,
-       .ops.remove = ideapad_acpi_remove,
-       .ops.notify = ideapad_acpi_notify,
-       .drv.pm = &ideapad_pm,
-       .owner = THIS_MODULE,
+static const struct acpi_device_id ideapad_device_ids[] = {
+       { "VPC2004", 0},
+       { "", 0},
 };
-module_acpi_driver(ideapad_acpi_driver);
+MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
+
+static struct platform_driver ideapad_acpi_driver = {
+       .probe = ideapad_acpi_add,
+       .remove = ideapad_acpi_remove,
+       .driver = {
+               .name   = "ideapad_acpi",
+               .owner  = THIS_MODULE,
+               .pm     = &ideapad_pm,
+               .acpi_match_table = ACPI_PTR(ideapad_device_ids),
+       },
+};
+
+module_platform_driver(ideapad_acpi_driver);
 
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
 MODULE_DESCRIPTION("IdeaPad ACPI Extras");
index 41b740cb28bca8743ea282bbf2fb5639a2f4266c..a2083a9e5662d660fd95cbb297815aa0570c8268 100644 (file)
@@ -29,24 +29,16 @@ static ssize_t irst_show_wakeup_events(struct device *dev,
                                       char *buf)
 {
        struct acpi_device *acpi;
-       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *result;
+       unsigned long long value;
        acpi_status status;
 
        acpi = to_acpi_device(dev);
 
-       status = acpi_evaluate_object(acpi->handle, "GFFS", NULL, &output);
+       status = acpi_evaluate_integer(acpi->handle, "GFFS", NULL, &value);
        if (!ACPI_SUCCESS(status))
                return -EINVAL;
 
-       result = output.pointer;
-
-       if (result->type != ACPI_TYPE_INTEGER) {
-               kfree(result);
-               return -EINVAL;
-       }
-
-       return sprintf(buf, "%lld\n", result->integer.value);
+       return sprintf(buf, "%lld\n", value);
 }
 
 static ssize_t irst_store_wakeup_events(struct device *dev,
@@ -54,8 +46,6 @@ static ssize_t irst_store_wakeup_events(struct device *dev,
                                        const char *buf, size_t count)
 {
        struct acpi_device *acpi;
-       struct acpi_object_list input;
-       union acpi_object param;
        acpi_status status;
        unsigned long value;
        int error;
@@ -67,13 +57,7 @@ static ssize_t irst_store_wakeup_events(struct device *dev,
        if (error)
                return error;
 
-       param.type = ACPI_TYPE_INTEGER;
-       param.integer.value = value;
-
-       input.count = 1;
-       input.pointer = &param;
-
-       status = acpi_evaluate_object(acpi->handle, "SFFS", &input, NULL);
+       status = acpi_execute_simple_method(acpi->handle, "SFFS", value);
 
        if (!ACPI_SUCCESS(status))
                return -EINVAL;
@@ -91,24 +75,16 @@ static ssize_t irst_show_wakeup_time(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
        struct acpi_device *acpi;
-       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *result;
+       unsigned long long value;
        acpi_status status;
 
        acpi = to_acpi_device(dev);
 
-       status = acpi_evaluate_object(acpi->handle, "GFTV", NULL, &output);
+       status = acpi_evaluate_integer(acpi->handle, "GFTV", NULL, &value);
        if (!ACPI_SUCCESS(status))
                return -EINVAL;
 
-       result = output.pointer;
-
-       if (result->type != ACPI_TYPE_INTEGER) {
-               kfree(result);
-               return -EINVAL;
-       }
-
-       return sprintf(buf, "%lld\n", result->integer.value);
+       return sprintf(buf, "%lld\n", value);
 }
 
 static ssize_t irst_store_wakeup_time(struct device *dev,
@@ -116,8 +92,6 @@ static ssize_t irst_store_wakeup_time(struct device *dev,
                                      const char *buf, size_t count)
 {
        struct acpi_device *acpi;
-       struct acpi_object_list input;
-       union acpi_object param;
        acpi_status status;
        unsigned long value;
        int error;
@@ -129,13 +103,7 @@ static ssize_t irst_store_wakeup_time(struct device *dev,
        if (error)
                return error;
 
-       param.type = ACPI_TYPE_INTEGER;
-       param.integer.value = value;
-
-       input.count = 1;
-       input.pointer = &param;
-
-       status = acpi_evaluate_object(acpi->handle, "SFTV", &input, NULL);
+       status = acpi_execute_simple_method(acpi->handle, "SFTV", value);
 
        if (!ACPI_SUCCESS(status))
                return -EINVAL;
index 52259dcabecb8251edad2a0e0dc7eccb9b174500..1838400dc0360615f799fac64a82b51f7efb9c17 100644 (file)
@@ -25,37 +25,18 @@ MODULE_LICENSE("GPL");
 
 static int smartconnect_acpi_init(struct acpi_device *acpi)
 {
-       struct acpi_object_list input;
-       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *result;
-       union acpi_object param;
+       unsigned long long value;
        acpi_status status;
 
-       status = acpi_evaluate_object(acpi->handle, "GAOS", NULL, &output);
+       status = acpi_evaluate_integer(acpi->handle, "GAOS", NULL, &value);
        if (!ACPI_SUCCESS(status))
                return -EINVAL;
 
-       result = output.pointer;
-
-       if (result->type != ACPI_TYPE_INTEGER) {
-               kfree(result);
-               return -EINVAL;
-       }
-
-       if (result->integer.value & 0x1) {
-               param.type = ACPI_TYPE_INTEGER;
-               param.integer.value = 0;
-
-               input.count = 1;
-               input.pointer = &param;
-
+       if (value & 0x1) {
                dev_info(&acpi->dev, "Disabling Intel Smart Connect\n");
-               status = acpi_evaluate_object(acpi->handle, "SAOS", &input,
-                                             NULL);
+               status = acpi_execute_simple_method(acpi->handle, "SAOS", 0);
        }
 
-       kfree(result);
-
        return 0;
 }
 
index d6cfc1558c2f1e067d8fd72edb1dc7ce3ecd00e3..11244f8703c402c876fb34b0e107383781661416 100644 (file)
@@ -156,19 +156,15 @@ static struct thermal_cooling_device_ops memory_cooling_ops = {
 static int intel_menlow_memory_add(struct acpi_device *device)
 {
        int result = -ENODEV;
-       acpi_status status = AE_OK;
-       acpi_handle dummy;
        struct thermal_cooling_device *cdev;
 
        if (!device)
                return -EINVAL;
 
-       status = acpi_get_handle(device->handle, MEMORY_GET_BANDWIDTH, &dummy);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(device->handle, MEMORY_GET_BANDWIDTH))
                goto end;
 
-       status = acpi_get_handle(device->handle, MEMORY_SET_BANDWIDTH, &dummy);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(device->handle, MEMORY_SET_BANDWIDTH))
                goto end;
 
        cdev = thermal_cooling_device_register("Memory controller", device,
index d3fd52036fd6e041592c7060c987ed5508684a0e..47caab0ea7a14faa1051b35eafe1ff8e53703ee0 100644 (file)
@@ -127,18 +127,17 @@ MODULE_PARM_DESC(minor,
                 "default is -1 (automatic)");
 #endif
 
-static int kbd_backlight = 1;
+static int kbd_backlight = -1;
 module_param(kbd_backlight, int, 0444);
 MODULE_PARM_DESC(kbd_backlight,
                 "set this to 0 to disable keyboard backlight, "
-                "1 to enable it (default: 0)");
+                "1 to enable it (default: no change from current value)");
 
-static int kbd_backlight_timeout;      /* = 0 */
+static int kbd_backlight_timeout = -1;
 module_param(kbd_backlight_timeout, int, 0444);
 MODULE_PARM_DESC(kbd_backlight_timeout,
-                "set this to 0 to set the default 10 seconds timeout, "
-                "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
-                "(default: 0)");
+                "meaningful values vary from 0 to 3 and their meaning depends "
+                "on the model (default: no change from current value)");
 
 #ifdef CONFIG_PM_SLEEP
 static void sony_nc_kbd_backlight_resume(void);
@@ -1509,7 +1508,6 @@ static void sony_nc_function_resume(void)
 static int sony_nc_resume(struct device *dev)
 {
        struct sony_nc_value *item;
-       acpi_handle handle;
 
        for (item = sony_nc_values; item->name; item++) {
                int ret;
@@ -1524,15 +1522,13 @@ static int sony_nc_resume(struct device *dev)
                }
        }
 
-       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
-                                        &handle))) {
+       if (acpi_has_method(sony_nc_acpi_handle, "ECON")) {
                int arg = 1;
                if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
                        dprintk("ECON Method failed\n");
        }
 
-       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
-                                        &handle)))
+       if (acpi_has_method(sony_nc_acpi_handle, "SN00"))
                sony_nc_function_resume();
 
        return 0;
@@ -1844,6 +1840,8 @@ static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
        if (!kbdbl_ctl)
                return -ENOMEM;
 
+       kbdbl_ctl->mode = kbd_backlight;
+       kbdbl_ctl->timeout = kbd_backlight_timeout;
        kbdbl_ctl->handle = handle;
        if (handle == 0x0137)
                kbdbl_ctl->base = 0x0C00;
@@ -1870,8 +1868,8 @@ static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
        if (ret)
                goto outmode;
 
-       __sony_nc_kbd_backlight_mode_set(kbd_backlight);
-       __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
+       __sony_nc_kbd_backlight_mode_set(kbdbl_ctl->mode);
+       __sony_nc_kbd_backlight_timeout_set(kbdbl_ctl->timeout);
 
        return 0;
 
@@ -1886,17 +1884,8 @@ outkzalloc:
 static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
 {
        if (kbdbl_ctl) {
-               int result;
-
                device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
                device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr);
-
-               /* restore the default hw behaviour */
-               sony_call_snc_handle(kbdbl_ctl->handle,
-                               kbdbl_ctl->base | 0x10000, &result);
-               sony_call_snc_handle(kbdbl_ctl->handle,
-                               kbdbl_ctl->base + 0x200, &result);
-
                kfree(kbdbl_ctl);
                kbdbl_ctl = NULL;
        }
@@ -2690,7 +2679,6 @@ static void sony_nc_backlight_ng_read_limits(int handle,
 
 static void sony_nc_backlight_setup(void)
 {
-       acpi_handle unused;
        int max_brightness = 0;
        const struct backlight_ops *ops = NULL;
        struct backlight_properties props;
@@ -2725,8 +2713,7 @@ static void sony_nc_backlight_setup(void)
                sony_nc_backlight_ng_read_limits(0x14c, &sony_bl_props);
                max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
 
-       } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
-                                               &unused))) {
+       } else if (acpi_has_method(sony_nc_acpi_handle, "GBRT")) {
                ops = &sony_backlight_ops;
                max_brightness = SONY_MAX_BRIGHTNESS - 1;
 
@@ -2758,7 +2745,6 @@ static int sony_nc_add(struct acpi_device *device)
 {
        acpi_status status;
        int result = 0;
-       acpi_handle handle;
        struct sony_nc_value *item;
 
        pr_info("%s v%s\n", SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
@@ -2798,15 +2784,13 @@ static int sony_nc_add(struct acpi_device *device)
                goto outplatform;
        }
 
-       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
-                                        &handle))) {
+       if (acpi_has_method(sony_nc_acpi_handle, "ECON")) {
                int arg = 1;
                if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
                        dprintk("ECON Method failed\n");
        }
 
-       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
-                                        &handle))) {
+       if (acpi_has_method(sony_nc_acpi_handle, "SN00")) {
                dprintk("Doing SNC setup\n");
                /* retrieve the available handles */
                result = sony_nc_handles_setup(sony_pf_device);
@@ -2829,9 +2813,8 @@ static int sony_nc_add(struct acpi_device *device)
 
                /* find the available acpiget as described in the DSDT */
                for (; item->acpiget && *item->acpiget; ++item->acpiget) {
-                       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
-                                                        *item->acpiget,
-                                                        &handle))) {
+                       if (acpi_has_method(sony_nc_acpi_handle,
+                                                       *item->acpiget)) {
                                dprintk("Found %s getter: %s\n",
                                                item->name, *item->acpiget);
                                item->devattr.attr.mode |= S_IRUGO;
@@ -2841,9 +2824,8 @@ static int sony_nc_add(struct acpi_device *device)
 
                /* find the available acpiset as described in the DSDT */
                for (; item->acpiset && *item->acpiset; ++item->acpiset) {
-                       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
-                                                        *item->acpiset,
-                                                        &handle))) {
+                       if (acpi_has_method(sony_nc_acpi_handle,
+                                                       *item->acpiset)) {
                                dprintk("Found %s setter: %s\n",
                                                item->name, *item->acpiset);
                                item->devattr.attr.mode |= S_IWUSR;
index 03ca6c139f1a5c9dd0cc821045bad7b5cb409d51..170f2788ee671491725fe6403b96a4b5d6cca9bc 100644 (file)
@@ -700,6 +700,14 @@ static void __init drv_acpi_handle_init(const char *name,
 static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle,
                        u32 level, void *context, void **return_value)
 {
+       struct acpi_device *dev;
+       if (!strcmp(context, "video")) {
+               if (acpi_bus_get_device(handle, &dev))
+                       return AE_OK;
+               if (strcmp(ACPI_VIDEO_HID, acpi_device_hid(dev)))
+                       return AE_OK;
+       }
+
        *(acpi_handle *)return_value = handle;
 
        return AE_CTRL_TERMINATE;
@@ -712,10 +720,10 @@ static void __init tpacpi_acpi_handle_locate(const char *name,
        acpi_status status;
        acpi_handle device_found;
 
-       BUG_ON(!name || !hid || !handle);
+       BUG_ON(!name || !handle);
        vdbg_printk(TPACPI_DBG_INIT,
                        "trying to locate ACPI handle for %s, using HID %s\n",
-                       name, hid);
+                       name, hid ? hid : "NULL");
 
        memset(&device_found, 0, sizeof(device_found));
        status = acpi_get_devices(hid, tpacpi_acpi_handle_locate_callback,
@@ -6090,19 +6098,28 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *obj;
+       struct acpi_device *device, *child;
        int rc;
 
-       if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) {
+       if (acpi_bus_get_device(handle, &device))
+               return 0;
+
+       rc = 0;
+       list_for_each_entry(child, &device->children, node) {
+               acpi_status status = acpi_evaluate_object(child->handle, "_BCL",
+                                                         NULL, &buffer);
+               if (ACPI_FAILURE(status))
+                       continue;
+
                obj = (union acpi_object *)buffer.pointer;
                if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
                        pr_err("Unknown _BCL data, please report this to %s\n",
-                              TPACPI_MAIL);
+                               TPACPI_MAIL);
                        rc = 0;
                } else {
                        rc = obj->package.count;
                }
-       } else {
-               return 0;
+               break;
        }
 
        kfree(buffer.pointer);
@@ -6118,7 +6135,7 @@ static unsigned int __init tpacpi_check_std_acpi_brightness_support(void)
        acpi_handle video_device;
        int bcl_levels = 0;
 
-       tpacpi_acpi_handle_locate("video", ACPI_VIDEO_HID, &video_device);
+       tpacpi_acpi_handle_locate("video", NULL, &video_device);
        if (video_device)
                bcl_levels = tpacpi_query_bcl_levels(video_device);
 
index 4ab618c63b457e0bbf5a613274ab10a3e76f26cc..67897c8740ba58ea3c93cf54b0a2a3e74a1e3a84 100644 (file)
@@ -80,13 +80,9 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
 static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
 {
        acpi_status status;
-       union acpi_object fncx_params[1] = {
-               { .type = ACPI_TYPE_INTEGER }
-       };
-       struct acpi_object_list fncx_arg_list = { 1, &fncx_params[0] };
 
-       fncx_params[0].integer.value = state ? 0x86 : 0x87;
-       status = acpi_evaluate_object(device->handle, "FNCX", &fncx_arg_list, NULL);
+       status = acpi_execute_simple_method(device->handle, "FNCX",
+                                               state ? 0x86 : 0x87);
        if (ACPI_FAILURE(status)) {
                pr_err("Unable to switch FNCX notifications\n");
                return -ENODEV;
index eb3467ea6d860e6c6961f3294922804e0e5776a2..0cfadb65f7c639597abce1d1bcb81ba3a04ff1d3 100644 (file)
@@ -191,16 +191,9 @@ static __inline__ void _set_bit(u32 * word, u32 mask, int value)
 
 static int write_acpi_int(const char *methodName, int val)
 {
-       struct acpi_object_list params;
-       union acpi_object in_objs[1];
        acpi_status status;
 
-       params.count = ARRAY_SIZE(in_objs);
-       params.pointer = in_objs;
-       in_objs[0].type = ACPI_TYPE_INTEGER;
-       in_objs[0].integer.value = val;
-
-       status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
+       status = acpi_execute_simple_method(NULL, (char *)methodName, val);
        return (status == AE_OK) ? 0 : -EIO;
 }
 
@@ -947,21 +940,17 @@ static void toshiba_acpi_hotkey_work(struct work_struct *work)
  */
 static int toshiba_acpi_query_hotkey(struct toshiba_acpi_dev *dev)
 {
-       struct acpi_buffer buf;
-       union acpi_object out_obj;
+       unsigned long long value;
        acpi_status status;
 
-       buf.pointer = &out_obj;
-       buf.length = sizeof(out_obj);
-
-       status = acpi_evaluate_object(dev->acpi_dev->handle, "INFO",
-                                     NULL, &buf);
-       if (ACPI_FAILURE(status) || out_obj.type != ACPI_TYPE_INTEGER) {
+       status = acpi_evaluate_integer(dev->acpi_dev->handle, "INFO",
+                                     NULL, &value);
+       if (ACPI_FAILURE(status)) {
                pr_err("ACPI INFO method execution failed\n");
                return -EIO;
        }
 
-       return out_obj.integer.value;
+       return value;
 }
 
 static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
@@ -981,7 +970,7 @@ static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
 static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
 {
        acpi_status status;
-       acpi_handle ec_handle, handle;
+       acpi_handle ec_handle;
        int error;
        u32 hci_result;
 
@@ -1008,10 +997,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
         */
        status = AE_ERROR;
        ec_handle = ec_get_handle();
-       if (ec_handle)
-               status = acpi_get_handle(ec_handle, "NTFY", &handle);
-
-       if (ACPI_SUCCESS(status)) {
+       if (ec_handle && acpi_has_method(ec_handle, "NTFY")) {
                INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work);
 
                error = i8042_install_filter(toshiba_acpi_i8042_filter);
@@ -1027,10 +1013,9 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
         * Determine hotkey query interface. Prefer using the INFO
         * method when it is available.
         */
-       status = acpi_get_handle(dev->acpi_dev->handle, "INFO", &handle);
-       if (ACPI_SUCCESS(status)) {
+       if (acpi_has_method(dev->acpi_dev->handle, "INFO"))
                dev->info_supported = 1;
-       else {
+       else {
                hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
                if (hci_result == HCI_SUCCESS)
                        dev->system_event_supported = 1;
@@ -1155,15 +1140,10 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
 
 static const char *find_hci_method(acpi_handle handle)
 {
-       acpi_status status;
-       acpi_handle hci_handle;
-
-       status = acpi_get_handle(handle, "GHCI", &hci_handle);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(handle, "GHCI"))
                return "GHCI";
 
-       status = acpi_get_handle(handle, "SPFC", &hci_handle);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(handle, "SPFC"))
                return "SPFC";
 
        return NULL;
index 601ea951224201a87719f0acc7de5ee7e4635649..62e8c221d01ea10a5f105a0a44b2d2d8277d7878 100644 (file)
@@ -252,8 +252,6 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
 {
        struct guid_block *block = NULL;
        char method[5];
-       struct acpi_object_list input;
-       union acpi_object params[1];
        acpi_status status;
        acpi_handle handle;
 
@@ -263,13 +261,9 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
        if (!block)
                return AE_NOT_EXIST;
 
-       input.count = 1;
-       input.pointer = params;
-       params[0].type = ACPI_TYPE_INTEGER;
-       params[0].integer.value = enable;
 
        snprintf(method, 5, "WE%02X", block->notify_id);
-       status = acpi_evaluate_object(handle, method, &input, NULL);
+       status = acpi_execute_simple_method(handle, method, enable);
 
        if (status != AE_OK && status != AE_NOT_FOUND)
                return status;
@@ -353,10 +347,10 @@ struct acpi_buffer *out)
 {
        struct guid_block *block = NULL;
        struct wmi_block *wblock = NULL;
-       acpi_handle handle, wc_handle;
+       acpi_handle handle;
        acpi_status status, wc_status = AE_ERROR;
-       struct acpi_object_list input, wc_input;
-       union acpi_object wc_params[1], wq_params[1];
+       struct acpi_object_list input;
+       union acpi_object wq_params[1];
        char method[5];
        char wc_method[5] = "WC";
 
@@ -386,11 +380,6 @@ struct acpi_buffer *out)
         * enable collection.
         */
        if (block->flags & ACPI_WMI_EXPENSIVE) {
-               wc_input.count = 1;
-               wc_input.pointer = wc_params;
-               wc_params[0].type = ACPI_TYPE_INTEGER;
-               wc_params[0].integer.value = 1;
-
                strncat(wc_method, block->object_id, 2);
 
                /*
@@ -398,10 +387,9 @@ struct acpi_buffer *out)
                 * expensive, but have no corresponding WCxx method. So we
                 * should not fail if this happens.
                 */
-               wc_status = acpi_get_handle(handle, wc_method, &wc_handle);
-               if (ACPI_SUCCESS(wc_status))
-                       wc_status = acpi_evaluate_object(handle, wc_method,
-                               &wc_input, NULL);
+               if (acpi_has_method(handle, wc_method))
+                       wc_status = acpi_execute_simple_method(handle,
+                                                               wc_method, 1);
        }
 
        strcpy(method, "WQ");
@@ -414,9 +402,7 @@ struct acpi_buffer *out)
         * the WQxx method failed - we should disable collection anyway.
         */
        if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
-               wc_params[0].integer.value = 0;
-               status = acpi_evaluate_object(handle,
-               wc_method, &wc_input, NULL);
+               status = acpi_execute_simple_method(handle, wc_method, 0);
        }
 
        return status;
index 34049b0b4c731e352ae48f62c7fd3edcfc71b517..747826d99059955f8941d592ef2f7734cd38fd08 100644 (file)
@@ -239,8 +239,6 @@ static char *__init pnpacpi_get_id(struct acpi_device *device)
 
 static int __init pnpacpi_add_device(struct acpi_device *device)
 {
-       acpi_handle temp = NULL;
-       acpi_status status;
        struct pnp_dev *dev;
        char *pnpid;
        struct acpi_hardware_id *id;
@@ -253,8 +251,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
         * If a PnPacpi device is not present , the device
         * driver should not be loaded.
         */
-       status = acpi_get_handle(device->handle, "_CRS", &temp);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(device->handle, "_CRS"))
                return 0;
 
        pnpid = pnpacpi_get_id(device);
@@ -271,16 +268,14 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
        dev->data = device;
        /* .enabled means the device can decode the resources */
        dev->active = device->status.enabled;
-       status = acpi_get_handle(device->handle, "_SRS", &temp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(device->handle, "_SRS"))
                dev->capabilities |= PNP_CONFIGURABLE;
        dev->capabilities |= PNP_READ;
        if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE))
                dev->capabilities |= PNP_WRITE;
        if (device->flags.removable)
                dev->capabilities |= PNP_REMOVABLE;
-       status = acpi_get_handle(device->handle, "_DIS", &temp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(device->handle, "_DIS"))
                dev->capabilities |= PNP_DISABLE;
 
        if (strlen(acpi_device_name(device)))
diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig
new file mode 100644 (file)
index 0000000..a7c81b5
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# Generic power capping sysfs interface configuration
+#
+
+menuconfig POWERCAP
+       bool "Generic powercap sysfs driver"
+       help
+         The power capping sysfs interface allows kernel subsystems to expose power
+         capping settings to user space in a consistent way.  Usually, it consists
+         of multiple control types that determine which settings may be exposed and
+         power zones representing parts of the system that can be subject to power
+         capping.
+
+         If you want this code to be compiled in, say Y here.
+
+if POWERCAP
+# Client driver configurations go here.
+config INTEL_RAPL
+       tristate "Intel RAPL Support"
+       depends on X86
+       default n
+       ---help---
+         This enables support for the Intel Running Average Power Limit (RAPL)
+         technology which allows power limits to be enforced and monitored on
+         modern Intel processors (Sandy Bridge and later).
+
+         In RAPL, the platform level settings are divided into domains for
+         fine grained control. These domains include processor package, DRAM
+         controller, CPU core (Power Plance 0), graphics uncore (Power Plane
+         1), etc.
+
+endif
diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile
new file mode 100644 (file)
index 0000000..0a21ef3
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_POWERCAP) += powercap_sys.o
+obj-$(CONFIG_INTEL_RAPL) += intel_rapl.o
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
new file mode 100644 (file)
index 0000000..2a786c5
--- /dev/null
@@ -0,0 +1,1395 @@
+/*
+ * Intel Running Average Power Limit (RAPL) Driver
+ * Copyright (c) 2013, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/log2.h>
+#include <linux/bitmap.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/cpu.h>
+#include <linux/powercap.h>
+
+#include <asm/processor.h>
+#include <asm/cpu_device_id.h>
+
+/* bitmasks for RAPL MSRs, used by primitive access functions */
+#define ENERGY_STATUS_MASK      0xffffffff
+
+#define POWER_LIMIT1_MASK       0x7FFF
+#define POWER_LIMIT1_ENABLE     BIT(15)
+#define POWER_LIMIT1_CLAMP      BIT(16)
+
+#define POWER_LIMIT2_MASK       (0x7FFFULL<<32)
+#define POWER_LIMIT2_ENABLE     BIT_ULL(47)
+#define POWER_LIMIT2_CLAMP      BIT_ULL(48)
+#define POWER_PACKAGE_LOCK      BIT_ULL(63)
+#define POWER_PP_LOCK           BIT(31)
+
+#define TIME_WINDOW1_MASK       (0x7FULL<<17)
+#define TIME_WINDOW2_MASK       (0x7FULL<<49)
+
+#define POWER_UNIT_OFFSET      0
+#define POWER_UNIT_MASK                0x0F
+
+#define ENERGY_UNIT_OFFSET     0x08
+#define ENERGY_UNIT_MASK       0x1F00
+
+#define TIME_UNIT_OFFSET       0x10
+#define TIME_UNIT_MASK         0xF0000
+
+#define POWER_INFO_MAX_MASK     (0x7fffULL<<32)
+#define POWER_INFO_MIN_MASK     (0x7fffULL<<16)
+#define POWER_INFO_MAX_TIME_WIN_MASK     (0x3fULL<<48)
+#define POWER_INFO_THERMAL_SPEC_MASK     0x7fff
+
+#define PERF_STATUS_THROTTLE_TIME_MASK 0xffffffff
+#define PP_POLICY_MASK         0x1F
+
+/* Non HW constants */
+#define RAPL_PRIMITIVE_DERIVED       BIT(1) /* not from raw data */
+#define RAPL_PRIMITIVE_DUMMY         BIT(2)
+
+/* scale RAPL units to avoid floating point math inside kernel */
+#define POWER_UNIT_SCALE     (1000000)
+#define ENERGY_UNIT_SCALE    (1000000)
+#define TIME_UNIT_SCALE      (1000000)
+
+#define TIME_WINDOW_MAX_MSEC 40000
+#define TIME_WINDOW_MIN_MSEC 250
+
+enum unit_type {
+       ARBITRARY_UNIT, /* no translation */
+       POWER_UNIT,
+       ENERGY_UNIT,
+       TIME_UNIT,
+};
+
+enum rapl_domain_type {
+       RAPL_DOMAIN_PACKAGE, /* entire package/socket */
+       RAPL_DOMAIN_PP0, /* core power plane */
+       RAPL_DOMAIN_PP1, /* graphics uncore */
+       RAPL_DOMAIN_DRAM,/* DRAM control_type */
+       RAPL_DOMAIN_MAX,
+};
+
+enum rapl_domain_msr_id {
+       RAPL_DOMAIN_MSR_LIMIT,
+       RAPL_DOMAIN_MSR_STATUS,
+       RAPL_DOMAIN_MSR_PERF,
+       RAPL_DOMAIN_MSR_POLICY,
+       RAPL_DOMAIN_MSR_INFO,
+       RAPL_DOMAIN_MSR_MAX,
+};
+
+/* per domain data, some are optional */
+enum rapl_primitives {
+       ENERGY_COUNTER,
+       POWER_LIMIT1,
+       POWER_LIMIT2,
+       FW_LOCK,
+
+       PL1_ENABLE,  /* power limit 1, aka long term */
+       PL1_CLAMP,   /* allow frequency to go below OS request */
+       PL2_ENABLE,  /* power limit 2, aka short term, instantaneous */
+       PL2_CLAMP,
+
+       TIME_WINDOW1, /* long term */
+       TIME_WINDOW2, /* short term */
+       THERMAL_SPEC_POWER,
+       MAX_POWER,
+
+       MIN_POWER,
+       MAX_TIME_WINDOW,
+       THROTTLED_TIME,
+       PRIORITY_LEVEL,
+
+       /* below are not raw primitive data */
+       AVERAGE_POWER,
+       NR_RAPL_PRIMITIVES,
+};
+
+#define NR_RAW_PRIMITIVES (NR_RAPL_PRIMITIVES - 2)
+
+/* Can be expanded to include events, etc.*/
+struct rapl_domain_data {
+       u64 primitives[NR_RAPL_PRIMITIVES];
+       unsigned long timestamp;
+};
+
+
+#define        DOMAIN_STATE_INACTIVE           BIT(0)
+#define        DOMAIN_STATE_POWER_LIMIT_SET    BIT(1)
+#define DOMAIN_STATE_BIOS_LOCKED        BIT(2)
+
+#define NR_POWER_LIMITS (2)
+struct rapl_power_limit {
+       struct powercap_zone_constraint *constraint;
+       int prim_id; /* primitive ID used to enable */
+       struct rapl_domain *domain;
+       const char *name;
+};
+
+static const char pl1_name[] = "long_term";
+static const char pl2_name[] = "short_term";
+
+struct rapl_domain {
+       const char *name;
+       enum rapl_domain_type id;
+       int msrs[RAPL_DOMAIN_MSR_MAX];
+       struct powercap_zone power_zone;
+       struct rapl_domain_data rdd;
+       struct rapl_power_limit rpl[NR_POWER_LIMITS];
+       u64 attr_map; /* track capabilities */
+       unsigned int state;
+       int package_id;
+};
+#define power_zone_to_rapl_domain(_zone) \
+       container_of(_zone, struct rapl_domain, power_zone)
+
+
+/* Each physical package contains multiple domains, these are the common
+ * data across RAPL domains within a package.
+ */
+struct rapl_package {
+       unsigned int id; /* physical package/socket id */
+       unsigned int nr_domains;
+       unsigned long domain_map; /* bit map of active domains */
+       unsigned int power_unit_divisor;
+       unsigned int energy_unit_divisor;
+       unsigned int time_unit_divisor;
+       struct rapl_domain *domains; /* array of domains, sized at runtime */
+       struct powercap_zone *power_zone; /* keep track of parent zone */
+       int nr_cpus; /* active cpus on the package, topology info is lost during
+                     * cpu hotplug. so we have to track ourselves.
+                     */
+       unsigned long power_limit_irq; /* keep track of package power limit
+                                       * notify interrupt enable status.
+                                       */
+       struct list_head plist;
+};
+#define PACKAGE_PLN_INT_SAVED   BIT(0)
+#define MAX_PRIM_NAME (32)
+
+/* per domain data. used to describe individual knobs such that access function
+ * can be consolidated into one instead of many inline functions.
+ */
+struct rapl_primitive_info {
+       const char *name;
+       u64 mask;
+       int shift;
+       enum rapl_domain_msr_id id;
+       enum unit_type unit;
+       u32 flag;
+};
+
+#define PRIMITIVE_INFO_INIT(p, m, s, i, u, f) {        \
+               .name = #p,                     \
+               .mask = m,                      \
+               .shift = s,                     \
+               .id = i,                        \
+               .unit = u,                      \
+               .flag = f                       \
+       }
+
+static void rapl_init_domains(struct rapl_package *rp);
+static int rapl_read_data_raw(struct rapl_domain *rd,
+                       enum rapl_primitives prim,
+                       bool xlate, u64 *data);
+static int rapl_write_data_raw(struct rapl_domain *rd,
+                       enum rapl_primitives prim,
+                       unsigned long long value);
+static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
+                       int to_raw);
+static void package_power_limit_irq_save(int package_id);
+
+static LIST_HEAD(rapl_packages); /* guarded by CPU hotplug lock */
+
+static const char * const rapl_domain_names[] = {
+       "package",
+       "core",
+       "uncore",
+       "dram",
+};
+
+static struct powercap_control_type *control_type; /* PowerCap Controller */
+
+/* caller to ensure CPU hotplug lock is held */
+static struct rapl_package *find_package_by_id(int id)
+{
+       struct rapl_package *rp;
+
+       list_for_each_entry(rp, &rapl_packages, plist) {
+               if (rp->id == id)
+                       return rp;
+       }
+
+       return NULL;
+}
+
+/* caller to ensure CPU hotplug lock is held */
+static int find_active_cpu_on_package(int package_id)
+{
+       int i;
+
+       for_each_online_cpu(i) {
+               if (topology_physical_package_id(i) == package_id)
+                       return i;
+       }
+       /* all CPUs on this package are offline */
+
+       return -ENODEV;
+}
+
+/* caller must hold cpu hotplug lock */
+static void rapl_cleanup_data(void)
+{
+       struct rapl_package *p, *tmp;
+
+       list_for_each_entry_safe(p, tmp, &rapl_packages, plist) {
+               kfree(p->domains);
+               list_del(&p->plist);
+               kfree(p);
+       }
+}
+
+static int get_energy_counter(struct powercap_zone *power_zone, u64 *energy_raw)
+{
+       struct rapl_domain *rd;
+       u64 energy_now;
+
+       /* prevent CPU hotplug, make sure the RAPL domain does not go
+        * away while reading the counter.
+        */
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+
+       if (!rapl_read_data_raw(rd, ENERGY_COUNTER, true, &energy_now)) {
+               *energy_raw = energy_now;
+               put_online_cpus();
+
+               return 0;
+       }
+       put_online_cpus();
+
+       return -EIO;
+}
+
+static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy)
+{
+       *energy = rapl_unit_xlate(0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
+       return 0;
+}
+
+static int release_zone(struct powercap_zone *power_zone)
+{
+       struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
+       struct rapl_package *rp;
+
+       /* package zone is the last zone of a package, we can free
+        * memory here since all children has been unregistered.
+        */
+       if (rd->id == RAPL_DOMAIN_PACKAGE) {
+               rp = find_package_by_id(rd->package_id);
+               if (!rp) {
+                       dev_warn(&power_zone->dev, "no package id %s\n",
+                               rd->name);
+                       return -ENODEV;
+               }
+               kfree(rd);
+               rp->domains = NULL;
+       }
+
+       return 0;
+
+}
+
+static int find_nr_power_limit(struct rapl_domain *rd)
+{
+       int i;
+
+       for (i = 0; i < NR_POWER_LIMITS; i++) {
+               if (rd->rpl[i].name == NULL)
+                       break;
+       }
+
+       return i;
+}
+
+static int set_domain_enable(struct powercap_zone *power_zone, bool mode)
+{
+       struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
+       int nr_powerlimit;
+
+       if (rd->state & DOMAIN_STATE_BIOS_LOCKED)
+               return -EACCES;
+       get_online_cpus();
+       nr_powerlimit = find_nr_power_limit(rd);
+       /* here we activate/deactivate the hardware for power limiting */
+       rapl_write_data_raw(rd, PL1_ENABLE, mode);
+       /* always enable clamp such that p-state can go below OS requested
+        * range. power capping priority over guranteed frequency.
+        */
+       rapl_write_data_raw(rd, PL1_CLAMP, mode);
+       /* some domains have pl2 */
+       if (nr_powerlimit > 1) {
+               rapl_write_data_raw(rd, PL2_ENABLE, mode);
+               rapl_write_data_raw(rd, PL2_CLAMP, mode);
+       }
+       put_online_cpus();
+
+       return 0;
+}
+
+static int get_domain_enable(struct powercap_zone *power_zone, bool *mode)
+{
+       struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
+       u64 val;
+
+       if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
+               *mode = false;
+               return 0;
+       }
+       get_online_cpus();
+       if (rapl_read_data_raw(rd, PL1_ENABLE, true, &val)) {
+               put_online_cpus();
+               return -EIO;
+       }
+       *mode = val;
+       put_online_cpus();
+
+       return 0;
+}
+
+/* per RAPL domain ops, in the order of rapl_domain_type */
+static struct powercap_zone_ops zone_ops[] = {
+       /* RAPL_DOMAIN_PACKAGE */
+       {
+               .get_energy_uj = get_energy_counter,
+               .get_max_energy_range_uj = get_max_energy_counter,
+               .release = release_zone,
+               .set_enable = set_domain_enable,
+               .get_enable = get_domain_enable,
+       },
+       /* RAPL_DOMAIN_PP0 */
+       {
+               .get_energy_uj = get_energy_counter,
+               .get_max_energy_range_uj = get_max_energy_counter,
+               .release = release_zone,
+               .set_enable = set_domain_enable,
+               .get_enable = get_domain_enable,
+       },
+       /* RAPL_DOMAIN_PP1 */
+       {
+               .get_energy_uj = get_energy_counter,
+               .get_max_energy_range_uj = get_max_energy_counter,
+               .release = release_zone,
+               .set_enable = set_domain_enable,
+               .get_enable = get_domain_enable,
+       },
+       /* RAPL_DOMAIN_DRAM */
+       {
+               .get_energy_uj = get_energy_counter,
+               .get_max_energy_range_uj = get_max_energy_counter,
+               .release = release_zone,
+               .set_enable = set_domain_enable,
+               .get_enable = get_domain_enable,
+       },
+};
+
+static int set_power_limit(struct powercap_zone *power_zone, int id,
+                       u64 power_limit)
+{
+       struct rapl_domain *rd;
+       struct rapl_package *rp;
+       int ret = 0;
+
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+       rp = find_package_by_id(rd->package_id);
+       if (!rp) {
+               ret = -ENODEV;
+               goto set_exit;
+       }
+
+       if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
+               dev_warn(&power_zone->dev, "%s locked by BIOS, monitoring only\n",
+                       rd->name);
+               ret = -EACCES;
+               goto set_exit;
+       }
+
+       switch (rd->rpl[id].prim_id) {
+       case PL1_ENABLE:
+               rapl_write_data_raw(rd, POWER_LIMIT1, power_limit);
+               break;
+       case PL2_ENABLE:
+               rapl_write_data_raw(rd, POWER_LIMIT2, power_limit);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       if (!ret)
+               package_power_limit_irq_save(rd->package_id);
+set_exit:
+       put_online_cpus();
+       return ret;
+}
+
+static int get_current_power_limit(struct powercap_zone *power_zone, int id,
+                                       u64 *data)
+{
+       struct rapl_domain *rd;
+       u64 val;
+       int prim;
+       int ret = 0;
+
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+       switch (rd->rpl[id].prim_id) {
+       case PL1_ENABLE:
+               prim = POWER_LIMIT1;
+               break;
+       case PL2_ENABLE:
+               prim = POWER_LIMIT2;
+               break;
+       default:
+               put_online_cpus();
+               return -EINVAL;
+       }
+       if (rapl_read_data_raw(rd, prim, true, &val))
+               ret = -EIO;
+       else
+               *data = val;
+
+       put_online_cpus();
+
+       return ret;
+}
+
+static int set_time_window(struct powercap_zone *power_zone, int id,
+                                                               u64 window)
+{
+       struct rapl_domain *rd;
+       int ret = 0;
+
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+       switch (rd->rpl[id].prim_id) {
+       case PL1_ENABLE:
+               rapl_write_data_raw(rd, TIME_WINDOW1, window);
+               break;
+       case PL2_ENABLE:
+               rapl_write_data_raw(rd, TIME_WINDOW2, window);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       put_online_cpus();
+       return ret;
+}
+
+static int get_time_window(struct powercap_zone *power_zone, int id, u64 *data)
+{
+       struct rapl_domain *rd;
+       u64 val;
+       int ret = 0;
+
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+       switch (rd->rpl[id].prim_id) {
+       case PL1_ENABLE:
+               ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val);
+               break;
+       case PL2_ENABLE:
+               ret = rapl_read_data_raw(rd, TIME_WINDOW2, true, &val);
+               break;
+       default:
+               put_online_cpus();
+               return -EINVAL;
+       }
+       if (!ret)
+               *data = val;
+       put_online_cpus();
+
+       return ret;
+}
+
+static const char *get_constraint_name(struct powercap_zone *power_zone, int id)
+{
+       struct rapl_power_limit *rpl;
+       struct rapl_domain *rd;
+
+       rd = power_zone_to_rapl_domain(power_zone);
+       rpl = (struct rapl_power_limit *) &rd->rpl[id];
+
+       return rpl->name;
+}
+
+
+static int get_max_power(struct powercap_zone *power_zone, int id,
+                                       u64 *data)
+{
+       struct rapl_domain *rd;
+       u64 val;
+       int prim;
+       int ret = 0;
+
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+       switch (rd->rpl[id].prim_id) {
+       case PL1_ENABLE:
+               prim = THERMAL_SPEC_POWER;
+               break;
+       case PL2_ENABLE:
+               prim = MAX_POWER;
+               break;
+       default:
+               put_online_cpus();
+               return -EINVAL;
+       }
+       if (rapl_read_data_raw(rd, prim, true, &val))
+               ret = -EIO;
+       else
+               *data = val;
+
+       put_online_cpus();
+
+       return ret;
+}
+
+static struct powercap_zone_constraint_ops constraint_ops = {
+       .set_power_limit_uw = set_power_limit,
+       .get_power_limit_uw = get_current_power_limit,
+       .set_time_window_us = set_time_window,
+       .get_time_window_us = get_time_window,
+       .get_max_power_uw = get_max_power,
+       .get_name = get_constraint_name,
+};
+
+/* called after domain detection and package level data are set */
+static void rapl_init_domains(struct rapl_package *rp)
+{
+       int i;
+       struct rapl_domain *rd = rp->domains;
+
+       for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
+               unsigned int mask = rp->domain_map & (1 << i);
+               switch (mask) {
+               case BIT(RAPL_DOMAIN_PACKAGE):
+                       rd->name = rapl_domain_names[RAPL_DOMAIN_PACKAGE];
+                       rd->id = RAPL_DOMAIN_PACKAGE;
+                       rd->msrs[0] = MSR_PKG_POWER_LIMIT;
+                       rd->msrs[1] = MSR_PKG_ENERGY_STATUS;
+                       rd->msrs[2] = MSR_PKG_PERF_STATUS;
+                       rd->msrs[3] = 0;
+                       rd->msrs[4] = MSR_PKG_POWER_INFO;
+                       rd->rpl[0].prim_id = PL1_ENABLE;
+                       rd->rpl[0].name = pl1_name;
+                       rd->rpl[1].prim_id = PL2_ENABLE;
+                       rd->rpl[1].name = pl2_name;
+                       break;
+               case BIT(RAPL_DOMAIN_PP0):
+                       rd->name = rapl_domain_names[RAPL_DOMAIN_PP0];
+                       rd->id = RAPL_DOMAIN_PP0;
+                       rd->msrs[0] = MSR_PP0_POWER_LIMIT;
+                       rd->msrs[1] = MSR_PP0_ENERGY_STATUS;
+                       rd->msrs[2] = 0;
+                       rd->msrs[3] = MSR_PP0_POLICY;
+                       rd->msrs[4] = 0;
+                       rd->rpl[0].prim_id = PL1_ENABLE;
+                       rd->rpl[0].name = pl1_name;
+                       break;
+               case BIT(RAPL_DOMAIN_PP1):
+                       rd->name = rapl_domain_names[RAPL_DOMAIN_PP1];
+                       rd->id = RAPL_DOMAIN_PP1;
+                       rd->msrs[0] = MSR_PP1_POWER_LIMIT;
+                       rd->msrs[1] = MSR_PP1_ENERGY_STATUS;
+                       rd->msrs[2] = 0;
+                       rd->msrs[3] = MSR_PP1_POLICY;
+                       rd->msrs[4] = 0;
+                       rd->rpl[0].prim_id = PL1_ENABLE;
+                       rd->rpl[0].name = pl1_name;
+                       break;
+               case BIT(RAPL_DOMAIN_DRAM):
+                       rd->name = rapl_domain_names[RAPL_DOMAIN_DRAM];
+                       rd->id = RAPL_DOMAIN_DRAM;
+                       rd->msrs[0] = MSR_DRAM_POWER_LIMIT;
+                       rd->msrs[1] = MSR_DRAM_ENERGY_STATUS;
+                       rd->msrs[2] = MSR_DRAM_PERF_STATUS;
+                       rd->msrs[3] = 0;
+                       rd->msrs[4] = MSR_DRAM_POWER_INFO;
+                       rd->rpl[0].prim_id = PL1_ENABLE;
+                       rd->rpl[0].name = pl1_name;
+                       break;
+               }
+               if (mask) {
+                       rd->package_id = rp->id;
+                       rd++;
+               }
+       }
+}
+
+static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
+                       int to_raw)
+{
+       u64 divisor = 1;
+       int scale = 1; /* scale to user friendly data without floating point */
+       u64 f, y; /* fraction and exp. used for time unit */
+       struct rapl_package *rp;
+
+       rp = find_package_by_id(package);
+       if (!rp)
+               return value;
+
+       switch (type) {
+       case POWER_UNIT:
+               divisor = rp->power_unit_divisor;
+               scale = POWER_UNIT_SCALE;
+               break;
+       case ENERGY_UNIT:
+               scale = ENERGY_UNIT_SCALE;
+               divisor = rp->energy_unit_divisor;
+               break;
+       case TIME_UNIT:
+               divisor = rp->time_unit_divisor;
+               scale = TIME_UNIT_SCALE;
+               /* special processing based on 2^Y*(1+F)/4 = val/divisor, refer
+                * to Intel Software Developer's manual Vol. 3a, CH 14.7.4.
+                */
+               if (!to_raw) {
+                       f = (value & 0x60) >> 5;
+                       y = value & 0x1f;
+                       value = (1 << y) * (4 + f) * scale / 4;
+                       return div64_u64(value, divisor);
+               } else {
+                       do_div(value, scale);
+                       value *= divisor;
+                       y = ilog2(value);
+                       f = div64_u64(4 * (value - (1 << y)), 1 << y);
+                       value = (y & 0x1f) | ((f & 0x3) << 5);
+                       return value;
+               }
+               break;
+       case ARBITRARY_UNIT:
+       default:
+               return value;
+       };
+
+       if (to_raw)
+               return div64_u64(value * divisor, scale);
+       else
+               return div64_u64(value * scale, divisor);
+}
+
+/* in the order of enum rapl_primitives */
+static struct rapl_primitive_info rpi[] = {
+       /* name, mask, shift, msr index, unit divisor */
+       PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0,
+                               RAPL_DOMAIN_MSR_STATUS, ENERGY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(POWER_LIMIT1, POWER_LIMIT1_MASK, 0,
+                               RAPL_DOMAIN_MSR_LIMIT, POWER_UNIT, 0),
+       PRIMITIVE_INFO_INIT(POWER_LIMIT2, POWER_LIMIT2_MASK, 32,
+                               RAPL_DOMAIN_MSR_LIMIT, POWER_UNIT, 0),
+       PRIMITIVE_INFO_INIT(FW_LOCK, POWER_PP_LOCK, 31,
+                               RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15,
+                               RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(PL1_CLAMP, POWER_LIMIT1_CLAMP, 16,
+                               RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(PL2_ENABLE, POWER_LIMIT2_ENABLE, 47,
+                               RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(PL2_CLAMP, POWER_LIMIT2_CLAMP, 48,
+                               RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(TIME_WINDOW1, TIME_WINDOW1_MASK, 17,
+                               RAPL_DOMAIN_MSR_LIMIT, TIME_UNIT, 0),
+       PRIMITIVE_INFO_INIT(TIME_WINDOW2, TIME_WINDOW2_MASK, 49,
+                               RAPL_DOMAIN_MSR_LIMIT, TIME_UNIT, 0),
+       PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, POWER_INFO_THERMAL_SPEC_MASK,
+                               0, RAPL_DOMAIN_MSR_INFO, POWER_UNIT, 0),
+       PRIMITIVE_INFO_INIT(MAX_POWER, POWER_INFO_MAX_MASK, 32,
+                               RAPL_DOMAIN_MSR_INFO, POWER_UNIT, 0),
+       PRIMITIVE_INFO_INIT(MIN_POWER, POWER_INFO_MIN_MASK, 16,
+                               RAPL_DOMAIN_MSR_INFO, POWER_UNIT, 0),
+       PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, POWER_INFO_MAX_TIME_WIN_MASK, 48,
+                               RAPL_DOMAIN_MSR_INFO, TIME_UNIT, 0),
+       PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0,
+                               RAPL_DOMAIN_MSR_PERF, TIME_UNIT, 0),
+       PRIMITIVE_INFO_INIT(PRIORITY_LEVEL, PP_POLICY_MASK, 0,
+                               RAPL_DOMAIN_MSR_POLICY, ARBITRARY_UNIT, 0),
+       /* non-hardware */
+       PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0, POWER_UNIT,
+                               RAPL_PRIMITIVE_DERIVED),
+       {NULL, 0, 0, 0},
+};
+
+/* Read primitive data based on its related struct rapl_primitive_info.
+ * if xlate flag is set, return translated data based on data units, i.e.
+ * time, energy, and power.
+ * RAPL MSRs are non-architectual and are laid out not consistently across
+ * domains. Here we use primitive info to allow writing consolidated access
+ * functions.
+ * For a given primitive, it is processed by MSR mask and shift. Unit conversion
+ * is pre-assigned based on RAPL unit MSRs read at init time.
+ * 63-------------------------- 31--------------------------- 0
+ * |                           xxxxx (mask)                   |
+ * |                                |<- shift ----------------|
+ * 63-------------------------- 31--------------------------- 0
+ */
+static int rapl_read_data_raw(struct rapl_domain *rd,
+                       enum rapl_primitives prim,
+                       bool xlate, u64 *data)
+{
+       u64 value, final;
+       u32 msr;
+       struct rapl_primitive_info *rp = &rpi[prim];
+       int cpu;
+
+       if (!rp->name || rp->flag & RAPL_PRIMITIVE_DUMMY)
+               return -EINVAL;
+
+       msr = rd->msrs[rp->id];
+       if (!msr)
+               return -EINVAL;
+       /* use physical package id to look up active cpus */
+       cpu = find_active_cpu_on_package(rd->package_id);
+       if (cpu < 0)
+               return cpu;
+
+       /* special-case package domain, which uses a different bit*/
+       if (prim == FW_LOCK && rd->id == RAPL_DOMAIN_PACKAGE) {
+               rp->mask = POWER_PACKAGE_LOCK;
+               rp->shift = 63;
+       }
+       /* non-hardware data are collected by the polling thread */
+       if (rp->flag & RAPL_PRIMITIVE_DERIVED) {
+               *data = rd->rdd.primitives[prim];
+               return 0;
+       }
+
+       if (rdmsrl_safe_on_cpu(cpu, msr, &value)) {
+               pr_debug("failed to read msr 0x%x on cpu %d\n", msr, cpu);
+               return -EIO;
+       }
+
+       final = value & rp->mask;
+       final = final >> rp->shift;
+       if (xlate)
+               *data = rapl_unit_xlate(rd->package_id, rp->unit, final, 0);
+       else
+               *data = final;
+
+       return 0;
+}
+
+/* Similar use of primitive info in the read counterpart */
+static int rapl_write_data_raw(struct rapl_domain *rd,
+                       enum rapl_primitives prim,
+                       unsigned long long value)
+{
+       u64 msr_val;
+       u32 msr;
+       struct rapl_primitive_info *rp = &rpi[prim];
+       int cpu;
+
+       cpu = find_active_cpu_on_package(rd->package_id);
+       if (cpu < 0)
+               return cpu;
+       msr = rd->msrs[rp->id];
+       if (rdmsrl_safe_on_cpu(cpu, msr, &msr_val)) {
+               dev_dbg(&rd->power_zone.dev,
+                       "failed to read msr 0x%x on cpu %d\n", msr, cpu);
+               return -EIO;
+       }
+       value = rapl_unit_xlate(rd->package_id, rp->unit, value, 1);
+       msr_val &= ~rp->mask;
+       msr_val |= value << rp->shift;
+       if (wrmsrl_safe_on_cpu(cpu, msr, msr_val)) {
+               dev_dbg(&rd->power_zone.dev,
+                       "failed to write msr 0x%x on cpu %d\n", msr, cpu);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int rapl_check_unit(struct rapl_package *rp, int cpu)
+{
+       u64 msr_val;
+       u32 value;
+
+       if (rdmsrl_safe_on_cpu(cpu, MSR_RAPL_POWER_UNIT, &msr_val)) {
+               pr_err("Failed to read power unit MSR 0x%x on CPU %d, exit.\n",
+                       MSR_RAPL_POWER_UNIT, cpu);
+               return -ENODEV;
+       }
+
+       /* Raw RAPL data stored in MSRs are in certain scales. We need to
+        * convert them into standard units based on the divisors reported in
+        * the RAPL unit MSRs.
+        * i.e.
+        * energy unit: 1/enery_unit_divisor Joules
+        * power unit: 1/power_unit_divisor Watts
+        * time unit: 1/time_unit_divisor Seconds
+        */
+       value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
+       rp->energy_unit_divisor = 1 << value;
+
+
+       value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
+       rp->power_unit_divisor = 1 << value;
+
+       value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
+       rp->time_unit_divisor = 1 << value;
+
+       pr_debug("Physical package %d units: energy=%d, time=%d, power=%d\n",
+               rp->id,
+               rp->energy_unit_divisor,
+               rp->time_unit_divisor,
+               rp->power_unit_divisor);
+
+       return 0;
+}
+
+/* REVISIT:
+ * When package power limit is set artificially low by RAPL, LVT
+ * thermal interrupt for package power limit should be ignored
+ * since we are not really exceeding the real limit. The intention
+ * is to avoid excessive interrupts while we are trying to save power.
+ * A useful feature might be routing the package_power_limit interrupt
+ * to userspace via eventfd. once we have a usecase, this is simple
+ * to do by adding an atomic notifier.
+ */
+
+static void package_power_limit_irq_save(int package_id)
+{
+       u32 l, h = 0;
+       int cpu;
+       struct rapl_package *rp;
+
+       rp = find_package_by_id(package_id);
+       if (!rp)
+               return;
+
+       if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
+               return;
+
+       cpu = find_active_cpu_on_package(package_id);
+       if (cpu < 0)
+               return;
+       /* save the state of PLN irq mask bit before disabling it */
+       rdmsr_safe_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
+       if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) {
+               rp->power_limit_irq = l & PACKAGE_THERM_INT_PLN_ENABLE;
+               rp->power_limit_irq |= PACKAGE_PLN_INT_SAVED;
+       }
+       l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
+       wrmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+}
+
+/* restore per package power limit interrupt enable state */
+static void package_power_limit_irq_restore(int package_id)
+{
+       u32 l, h;
+       int cpu;
+       struct rapl_package *rp;
+
+       rp = find_package_by_id(package_id);
+       if (!rp)
+               return;
+
+       if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
+               return;
+
+       cpu = find_active_cpu_on_package(package_id);
+       if (cpu < 0)
+               return;
+
+       /* irq enable state not saved, nothing to restore */
+       if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED))
+               return;
+       rdmsr_safe_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
+
+       if (rp->power_limit_irq & PACKAGE_THERM_INT_PLN_ENABLE)
+               l |= PACKAGE_THERM_INT_PLN_ENABLE;
+       else
+               l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
+
+       wrmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+}
+
+static const struct x86_cpu_id rapl_ids[] = {
+       { X86_VENDOR_INTEL, 6, 0x2a},/* SNB */
+       { X86_VENDOR_INTEL, 6, 0x2d},/* SNB EP */
+       { X86_VENDOR_INTEL, 6, 0x3a},/* IVB */
+       { X86_VENDOR_INTEL, 6, 0x45},/* HSW */
+       /* TODO: Add more CPU IDs after testing */
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, rapl_ids);
+
+/* read once for all raw primitive data for all packages, domains */
+static void rapl_update_domain_data(void)
+{
+       int dmn, prim;
+       u64 val;
+       struct rapl_package *rp;
+
+       list_for_each_entry(rp, &rapl_packages, plist) {
+               for (dmn = 0; dmn < rp->nr_domains; dmn++) {
+                       pr_debug("update package %d domain %s data\n", rp->id,
+                               rp->domains[dmn].name);
+                       /* exclude non-raw primitives */
+                       for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++)
+                               if (!rapl_read_data_raw(&rp->domains[dmn], prim,
+                                                               rpi[prim].unit,
+                                                               &val))
+                                       rp->domains[dmn].rdd.primitives[prim] =
+                                                                       val;
+               }
+       }
+
+}
+
+static int rapl_unregister_powercap(void)
+{
+       struct rapl_package *rp;
+       struct rapl_domain *rd, *rd_package = NULL;
+
+       /* unregister all active rapl packages from the powercap layer,
+        * hotplug lock held
+        */
+       list_for_each_entry(rp, &rapl_packages, plist) {
+               package_power_limit_irq_restore(rp->id);
+
+               for (rd = rp->domains; rd < rp->domains + rp->nr_domains;
+                    rd++) {
+                       pr_debug("remove package, undo power limit on %d: %s\n",
+                               rp->id, rd->name);
+                       rapl_write_data_raw(rd, PL1_ENABLE, 0);
+                       rapl_write_data_raw(rd, PL2_ENABLE, 0);
+                       rapl_write_data_raw(rd, PL1_CLAMP, 0);
+                       rapl_write_data_raw(rd, PL2_CLAMP, 0);
+                       if (rd->id == RAPL_DOMAIN_PACKAGE) {
+                               rd_package = rd;
+                               continue;
+                       }
+                       powercap_unregister_zone(control_type, &rd->power_zone);
+               }
+               /* do the package zone last */
+               if (rd_package)
+                       powercap_unregister_zone(control_type,
+                                               &rd_package->power_zone);
+       }
+       powercap_unregister_control_type(control_type);
+
+       return 0;
+}
+
+static int rapl_package_register_powercap(struct rapl_package *rp)
+{
+       struct rapl_domain *rd;
+       int ret = 0;
+       char dev_name[17]; /* max domain name = 7 + 1 + 8 for int + 1 for null*/
+       struct powercap_zone *power_zone = NULL;
+       int nr_pl;
+
+       /* first we register package domain as the parent zone*/
+       for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+               if (rd->id == RAPL_DOMAIN_PACKAGE) {
+                       nr_pl = find_nr_power_limit(rd);
+                       pr_debug("register socket %d package domain %s\n",
+                               rp->id, rd->name);
+                       memset(dev_name, 0, sizeof(dev_name));
+                       snprintf(dev_name, sizeof(dev_name), "%s-%d",
+                               rd->name, rp->id);
+                       power_zone = powercap_register_zone(&rd->power_zone,
+                                                       control_type,
+                                                       dev_name, NULL,
+                                                       &zone_ops[rd->id],
+                                                       nr_pl,
+                                                       &constraint_ops);
+                       if (IS_ERR(power_zone)) {
+                               pr_debug("failed to register package, %d\n",
+                                       rp->id);
+                               ret = PTR_ERR(power_zone);
+                               goto exit_package;
+                       }
+                       /* track parent zone in per package/socket data */
+                       rp->power_zone = power_zone;
+                       /* done, only one package domain per socket */
+                       break;
+               }
+       }
+       if (!power_zone) {
+               pr_err("no package domain found, unknown topology!\n");
+               ret = -ENODEV;
+               goto exit_package;
+       }
+       /* now register domains as children of the socket/package*/
+       for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+               if (rd->id == RAPL_DOMAIN_PACKAGE)
+                       continue;
+               /* number of power limits per domain varies */
+               nr_pl = find_nr_power_limit(rd);
+               power_zone = powercap_register_zone(&rd->power_zone,
+                                               control_type, rd->name,
+                                               rp->power_zone,
+                                               &zone_ops[rd->id], nr_pl,
+                                               &constraint_ops);
+
+               if (IS_ERR(power_zone)) {
+                       pr_debug("failed to register power_zone, %d:%s:%s\n",
+                               rp->id, rd->name, dev_name);
+                       ret = PTR_ERR(power_zone);
+                       goto err_cleanup;
+               }
+       }
+
+exit_package:
+       return ret;
+err_cleanup:
+       /* clean up previously initialized domains within the package if we
+        * failed after the first domain setup.
+        */
+       while (--rd >= rp->domains) {
+               pr_debug("unregister package %d domain %s\n", rp->id, rd->name);
+               powercap_unregister_zone(control_type, &rd->power_zone);
+       }
+
+       return ret;
+}
+
+static int rapl_register_powercap(void)
+{
+       struct rapl_domain *rd;
+       struct rapl_package *rp;
+       int ret = 0;
+
+       control_type = powercap_register_control_type(NULL, "intel-rapl", NULL);
+       if (IS_ERR(control_type)) {
+               pr_debug("failed to register powercap control_type.\n");
+               return PTR_ERR(control_type);
+       }
+       /* read the initial data */
+       rapl_update_domain_data();
+       list_for_each_entry(rp, &rapl_packages, plist)
+               if (rapl_package_register_powercap(rp))
+                       goto err_cleanup_package;
+       return ret;
+
+err_cleanup_package:
+       /* clean up previously initialized packages */
+       list_for_each_entry_continue_reverse(rp, &rapl_packages, plist) {
+               for (rd = rp->domains; rd < rp->domains + rp->nr_domains;
+                    rd++) {
+                       pr_debug("unregister zone/package %d, %s domain\n",
+                               rp->id, rd->name);
+                       powercap_unregister_zone(control_type, &rd->power_zone);
+               }
+       }
+
+       return ret;
+}
+
+static int rapl_check_domain(int cpu, int domain)
+{
+       unsigned msr;
+       u64 val1, val2 = 0;
+       int retry = 0;
+
+       switch (domain) {
+       case RAPL_DOMAIN_PACKAGE:
+               msr = MSR_PKG_ENERGY_STATUS;
+               break;
+       case RAPL_DOMAIN_PP0:
+               msr = MSR_PP0_ENERGY_STATUS;
+               break;
+       case RAPL_DOMAIN_PP1:
+               msr = MSR_PP1_ENERGY_STATUS;
+               break;
+       case RAPL_DOMAIN_DRAM:
+               msr = MSR_DRAM_ENERGY_STATUS;
+               break;
+       default:
+               pr_err("invalid domain id %d\n", domain);
+               return -EINVAL;
+       }
+       if (rdmsrl_safe_on_cpu(cpu, msr, &val1))
+               return -ENODEV;
+
+       /* energy counters roll slowly on some domains */
+       while (++retry < 10) {
+               usleep_range(10000, 15000);
+               rdmsrl_safe_on_cpu(cpu, msr, &val2);
+               if ((val1 & ENERGY_STATUS_MASK) != (val2 & ENERGY_STATUS_MASK))
+                       return 0;
+       }
+       /* if energy counter does not change, report as bad domain */
+       pr_info("domain %s energy ctr %llu:%llu not working, skip\n",
+               rapl_domain_names[domain], val1, val2);
+
+       return -ENODEV;
+}
+
+/* Detect active and valid domains for the given CPU, caller must
+ * ensure the CPU belongs to the targeted package and CPU hotlug is disabled.
+ */
+static int rapl_detect_domains(struct rapl_package *rp, int cpu)
+{
+       int i;
+       int ret = 0;
+       struct rapl_domain *rd;
+       u64 locked;
+
+       for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
+               /* use physical package id to read counters */
+               if (!rapl_check_domain(cpu, i))
+                       rp->domain_map |= 1 << i;
+       }
+       rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX);
+       if (!rp->nr_domains) {
+               pr_err("no valid rapl domains found in package %d\n", rp->id);
+               ret = -ENODEV;
+               goto done;
+       }
+       pr_debug("found %d domains on package %d\n", rp->nr_domains, rp->id);
+
+       rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain),
+                       GFP_KERNEL);
+       if (!rp->domains) {
+               ret = -ENOMEM;
+               goto done;
+       }
+       rapl_init_domains(rp);
+
+       for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+               /* check if the domain is locked by BIOS */
+               if (rapl_read_data_raw(rd, FW_LOCK, false, &locked)) {
+                       pr_info("RAPL package %d domain %s locked by BIOS\n",
+                               rp->id, rd->name);
+                               rd->state |= DOMAIN_STATE_BIOS_LOCKED;
+               }
+       }
+
+
+done:
+       return ret;
+}
+
+static bool is_package_new(int package)
+{
+       struct rapl_package *rp;
+
+       /* caller prevents cpu hotplug, there will be no new packages added
+        * or deleted while traversing the package list, no need for locking.
+        */
+       list_for_each_entry(rp, &rapl_packages, plist)
+               if (package == rp->id)
+                       return false;
+
+       return true;
+}
+
+/* RAPL interface can be made of a two-level hierarchy: package level and domain
+ * level. We first detect the number of packages then domains of each package.
+ * We have to consider the possiblity of CPU online/offline due to hotplug and
+ * other scenarios.
+ */
+static int rapl_detect_topology(void)
+{
+       int i;
+       int phy_package_id;
+       struct rapl_package *new_package, *rp;
+
+       for_each_online_cpu(i) {
+               phy_package_id = topology_physical_package_id(i);
+               if (is_package_new(phy_package_id)) {
+                       new_package = kzalloc(sizeof(*rp), GFP_KERNEL);
+                       if (!new_package) {
+                               rapl_cleanup_data();
+                               return -ENOMEM;
+                       }
+                       /* add the new package to the list */
+                       new_package->id = phy_package_id;
+                       new_package->nr_cpus = 1;
+
+                       /* check if the package contains valid domains */
+                       if (rapl_detect_domains(new_package, i) ||
+                               rapl_check_unit(new_package, i)) {
+                               kfree(new_package->domains);
+                               kfree(new_package);
+                               /* free up the packages already initialized */
+                               rapl_cleanup_data();
+                               return -ENODEV;
+                       }
+                       INIT_LIST_HEAD(&new_package->plist);
+                       list_add(&new_package->plist, &rapl_packages);
+               } else {
+                       rp = find_package_by_id(phy_package_id);
+                       if (rp)
+                               ++rp->nr_cpus;
+               }
+       }
+
+       return 0;
+}
+
+/* called from CPU hotplug notifier, hotplug lock held */
+static void rapl_remove_package(struct rapl_package *rp)
+{
+       struct rapl_domain *rd, *rd_package = NULL;
+
+       for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+               if (rd->id == RAPL_DOMAIN_PACKAGE) {
+                       rd_package = rd;
+                       continue;
+               }
+               pr_debug("remove package %d, %s domain\n", rp->id, rd->name);
+               powercap_unregister_zone(control_type, &rd->power_zone);
+       }
+       /* do parent zone last */
+       powercap_unregister_zone(control_type, &rd_package->power_zone);
+       list_del(&rp->plist);
+       kfree(rp);
+}
+
+/* called from CPU hotplug notifier, hotplug lock held */
+static int rapl_add_package(int cpu)
+{
+       int ret = 0;
+       int phy_package_id;
+       struct rapl_package *rp;
+
+       phy_package_id = topology_physical_package_id(cpu);
+       rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
+       if (!rp)
+               return -ENOMEM;
+
+       /* add the new package to the list */
+       rp->id = phy_package_id;
+       rp->nr_cpus = 1;
+       /* check if the package contains valid domains */
+       if (rapl_detect_domains(rp, cpu) ||
+               rapl_check_unit(rp, cpu)) {
+               ret = -ENODEV;
+               goto err_free_package;
+       }
+       if (!rapl_package_register_powercap(rp)) {
+               INIT_LIST_HEAD(&rp->plist);
+               list_add(&rp->plist, &rapl_packages);
+               return ret;
+       }
+
+err_free_package:
+       kfree(rp->domains);
+       kfree(rp);
+
+       return ret;
+}
+
+/* Handles CPU hotplug on multi-socket systems.
+ * If a CPU goes online as the first CPU of the physical package
+ * we add the RAPL package to the system. Similarly, when the last
+ * CPU of the package is removed, we remove the RAPL package and its
+ * associated domains. Cooling devices are handled accordingly at
+ * per-domain level.
+ */
+static int rapl_cpu_callback(struct notifier_block *nfb,
+                               unsigned long action, void *hcpu)
+{
+       unsigned long cpu = (unsigned long)hcpu;
+       int phy_package_id;
+       struct rapl_package *rp;
+
+       phy_package_id = topology_physical_package_id(cpu);
+       switch (action) {
+       case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
+       case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
+               rp = find_package_by_id(phy_package_id);
+               if (rp)
+                       ++rp->nr_cpus;
+               else
+                       rapl_add_package(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
+               rp = find_package_by_id(phy_package_id);
+               if (!rp)
+                       break;
+               if (--rp->nr_cpus == 0)
+                       rapl_remove_package(rp);
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block rapl_cpu_notifier = {
+       .notifier_call = rapl_cpu_callback,
+};
+
+static int __init rapl_init(void)
+{
+       int ret = 0;
+
+       if (!x86_match_cpu(rapl_ids)) {
+               pr_err("driver does not support CPU family %d model %d\n",
+                       boot_cpu_data.x86, boot_cpu_data.x86_model);
+
+               return -ENODEV;
+       }
+       /* prevent CPU hotplug during detection */
+       get_online_cpus();
+       ret = rapl_detect_topology();
+       if (ret)
+               goto done;
+
+       if (rapl_register_powercap()) {
+               rapl_cleanup_data();
+               ret = -ENODEV;
+               goto done;
+       }
+       register_hotcpu_notifier(&rapl_cpu_notifier);
+done:
+       put_online_cpus();
+
+       return ret;
+}
+
+static void __exit rapl_exit(void)
+{
+       get_online_cpus();
+       unregister_hotcpu_notifier(&rapl_cpu_notifier);
+       rapl_unregister_powercap();
+       rapl_cleanup_data();
+       put_online_cpus();
+}
+
+module_init(rapl_init);
+module_exit(rapl_exit);
+
+MODULE_DESCRIPTION("Driver for Intel RAPL (Running Average Power Limit)");
+MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c
new file mode 100644 (file)
index 0000000..8d0fe43
--- /dev/null
@@ -0,0 +1,685 @@
+/*
+ * Power capping class
+ * Copyright (c) 2013, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/powercap.h>
+
+#define to_powercap_zone(n) container_of(n, struct powercap_zone, dev)
+#define to_powercap_control_type(n) \
+                       container_of(n, struct powercap_control_type, dev)
+
+/* Power zone show function */
+#define define_power_zone_show(_attr)          \
+static ssize_t _attr##_show(struct device *dev, \
+                                       struct device_attribute *dev_attr,\
+                                       char *buf) \
+{ \
+       u64 value; \
+       ssize_t len = -EINVAL; \
+       struct powercap_zone *power_zone = to_powercap_zone(dev); \
+       \
+       if (power_zone->ops->get_##_attr) { \
+               if (!power_zone->ops->get_##_attr(power_zone, &value)) \
+                       len = sprintf(buf, "%lld\n", value); \
+       } \
+       \
+       return len; \
+}
+
+/* The only meaningful input is 0 (reset), others are silently ignored */
+#define define_power_zone_store(_attr)         \
+static ssize_t _attr##_store(struct device *dev,\
+                               struct device_attribute *dev_attr, \
+                               const char *buf, size_t count) \
+{ \
+       int err; \
+       struct powercap_zone *power_zone = to_powercap_zone(dev); \
+       u64 value; \
+       \
+       err = kstrtoull(buf, 10, &value); \
+       if (err) \
+               return -EINVAL; \
+       if (value) \
+               return count; \
+       if (power_zone->ops->reset_##_attr) { \
+               if (!power_zone->ops->reset_##_attr(power_zone)) \
+                       return count; \
+       } \
+       \
+       return -EINVAL; \
+}
+
+/* Power zone constraint show function */
+#define define_power_zone_constraint_show(_attr) \
+static ssize_t show_constraint_##_attr(struct device *dev, \
+                               struct device_attribute *dev_attr,\
+                               char *buf) \
+{ \
+       u64 value; \
+       ssize_t len = -ENODATA; \
+       struct powercap_zone *power_zone = to_powercap_zone(dev); \
+       int id; \
+       struct powercap_zone_constraint *pconst;\
+       \
+       if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
+               return -EINVAL; \
+       if (id >= power_zone->const_id_cnt)     \
+               return -EINVAL; \
+       pconst = &power_zone->constraints[id]; \
+       if (pconst && pconst->ops && pconst->ops->get_##_attr) { \
+               if (!pconst->ops->get_##_attr(power_zone, id, &value)) \
+                       len = sprintf(buf, "%lld\n", value); \
+       } \
+       \
+       return len; \
+}
+
+/* Power zone constraint store function */
+#define define_power_zone_constraint_store(_attr) \
+static ssize_t store_constraint_##_attr(struct device *dev,\
+                               struct device_attribute *dev_attr, \
+                               const char *buf, size_t count) \
+{ \
+       int err; \
+       u64 value; \
+       struct powercap_zone *power_zone = to_powercap_zone(dev); \
+       int id; \
+       struct powercap_zone_constraint *pconst;\
+       \
+       if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
+               return -EINVAL; \
+       if (id >= power_zone->const_id_cnt)     \
+               return -EINVAL; \
+       pconst = &power_zone->constraints[id]; \
+       err = kstrtoull(buf, 10, &value); \
+       if (err) \
+               return -EINVAL; \
+       if (pconst && pconst->ops && pconst->ops->set_##_attr) { \
+               if (!pconst->ops->set_##_attr(power_zone, id, value)) \
+                       return count; \
+       } \
+       \
+       return -ENODATA; \
+}
+
+/* Power zone information callbacks */
+define_power_zone_show(power_uw);
+define_power_zone_show(max_power_range_uw);
+define_power_zone_show(energy_uj);
+define_power_zone_store(energy_uj);
+define_power_zone_show(max_energy_range_uj);
+
+/* Power zone attributes */
+static DEVICE_ATTR_RO(max_power_range_uw);
+static DEVICE_ATTR_RO(power_uw);
+static DEVICE_ATTR_RO(max_energy_range_uj);
+static DEVICE_ATTR_RW(energy_uj);
+
+/* Power zone constraint attributes callbacks */
+define_power_zone_constraint_show(power_limit_uw);
+define_power_zone_constraint_store(power_limit_uw);
+define_power_zone_constraint_show(time_window_us);
+define_power_zone_constraint_store(time_window_us);
+define_power_zone_constraint_show(max_power_uw);
+define_power_zone_constraint_show(min_power_uw);
+define_power_zone_constraint_show(max_time_window_us);
+define_power_zone_constraint_show(min_time_window_us);
+
+/* For one time seeding of constraint device attributes */
+struct powercap_constraint_attr {
+       struct device_attribute power_limit_attr;
+       struct device_attribute time_window_attr;
+       struct device_attribute max_power_attr;
+       struct device_attribute min_power_attr;
+       struct device_attribute max_time_window_attr;
+       struct device_attribute min_time_window_attr;
+       struct device_attribute name_attr;
+};
+
+static struct powercap_constraint_attr
+                               constraint_attrs[MAX_CONSTRAINTS_PER_ZONE];
+
+/* A list of powercap control_types */
+static LIST_HEAD(powercap_cntrl_list);
+/* Mutex to protect list of powercap control_types */
+static DEFINE_MUTEX(powercap_cntrl_list_lock);
+
+#define POWERCAP_CONSTRAINT_NAME_LEN   30 /* Some limit to avoid overflow */
+static ssize_t show_constraint_name(struct device *dev,
+                               struct device_attribute *dev_attr,
+                               char *buf)
+{
+       const char *name;
+       struct powercap_zone *power_zone = to_powercap_zone(dev);
+       int id;
+       ssize_t len = -ENODATA;
+       struct powercap_zone_constraint *pconst;
+
+       if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id))
+               return -EINVAL;
+       if (id >= power_zone->const_id_cnt)
+               return -EINVAL;
+       pconst = &power_zone->constraints[id];
+
+       if (pconst && pconst->ops && pconst->ops->get_name) {
+               name = pconst->ops->get_name(power_zone, id);
+               if (name) {
+                       snprintf(buf, POWERCAP_CONSTRAINT_NAME_LEN,
+                                                               "%s\n", name);
+                       buf[POWERCAP_CONSTRAINT_NAME_LEN] = '\0';
+                       len = strlen(buf);
+               }
+       }
+
+       return len;
+}
+
+static int create_constraint_attribute(int id, const char *name,
+                               int mode,
+                               struct device_attribute *dev_attr,
+                               ssize_t (*show)(struct device *,
+                                       struct device_attribute *, char *),
+                               ssize_t (*store)(struct device *,
+                                       struct device_attribute *,
+                               const char *, size_t)
+                               )
+{
+
+       dev_attr->attr.name = kasprintf(GFP_KERNEL, "constraint_%d_%s",
+                                                               id, name);
+       if (!dev_attr->attr.name)
+               return -ENOMEM;
+       dev_attr->attr.mode = mode;
+       dev_attr->show = show;
+       dev_attr->store = store;
+
+       return 0;
+}
+
+static void free_constraint_attributes(void)
+{
+       int i;
+
+       for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) {
+               kfree(constraint_attrs[i].power_limit_attr.attr.name);
+               kfree(constraint_attrs[i].time_window_attr.attr.name);
+               kfree(constraint_attrs[i].name_attr.attr.name);
+               kfree(constraint_attrs[i].max_power_attr.attr.name);
+               kfree(constraint_attrs[i].min_power_attr.attr.name);
+               kfree(constraint_attrs[i].max_time_window_attr.attr.name);
+               kfree(constraint_attrs[i].min_time_window_attr.attr.name);
+       }
+}
+
+static int seed_constraint_attributes(void)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) {
+               ret = create_constraint_attribute(i, "power_limit_uw",
+                                       S_IWUSR | S_IRUGO,
+                                       &constraint_attrs[i].power_limit_attr,
+                                       show_constraint_power_limit_uw,
+                                       store_constraint_power_limit_uw);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "time_window_us",
+                                       S_IWUSR | S_IRUGO,
+                                       &constraint_attrs[i].time_window_attr,
+                                       show_constraint_time_window_us,
+                                       store_constraint_time_window_us);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "name", S_IRUGO,
+                               &constraint_attrs[i].name_attr,
+                               show_constraint_name,
+                               NULL);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "max_power_uw", S_IRUGO,
+                               &constraint_attrs[i].max_power_attr,
+                               show_constraint_max_power_uw,
+                               NULL);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "min_power_uw", S_IRUGO,
+                               &constraint_attrs[i].min_power_attr,
+                               show_constraint_min_power_uw,
+                               NULL);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "max_time_window_us",
+                               S_IRUGO,
+                               &constraint_attrs[i].max_time_window_attr,
+                               show_constraint_max_time_window_us,
+                               NULL);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "min_time_window_us",
+                               S_IRUGO,
+                               &constraint_attrs[i].min_time_window_attr,
+                               show_constraint_min_time_window_us,
+                               NULL);
+               if (ret)
+                       goto err_alloc;
+
+       }
+
+       return 0;
+
+err_alloc:
+       free_constraint_attributes();
+
+       return ret;
+}
+
+static int create_constraints(struct powercap_zone *power_zone,
+                               int nr_constraints,
+                               struct powercap_zone_constraint_ops *const_ops)
+{
+       int i;
+       int ret = 0;
+       int count;
+       struct powercap_zone_constraint *pconst;
+
+       if (!power_zone || !const_ops || !const_ops->get_power_limit_uw ||
+                                       !const_ops->set_power_limit_uw ||
+                                       !const_ops->get_time_window_us ||
+                                       !const_ops->set_time_window_us)
+               return -EINVAL;
+
+       count = power_zone->zone_attr_count;
+       for (i = 0; i < nr_constraints; ++i) {
+               pconst = &power_zone->constraints[i];
+               pconst->ops = const_ops;
+               pconst->id = power_zone->const_id_cnt;
+               power_zone->const_id_cnt++;
+               power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].power_limit_attr.attr;
+               power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].time_window_attr.attr;
+               if (pconst->ops->get_name)
+                       power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].name_attr.attr;
+               if (pconst->ops->get_max_power_uw)
+                       power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].max_power_attr.attr;
+               if (pconst->ops->get_min_power_uw)
+                       power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].min_power_attr.attr;
+               if (pconst->ops->get_max_time_window_us)
+                       power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].max_time_window_attr.attr;
+               if (pconst->ops->get_min_time_window_us)
+                       power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].min_time_window_attr.attr;
+       }
+       power_zone->zone_attr_count = count;
+
+       return ret;
+}
+
+static bool control_type_valid(void *control_type)
+{
+       struct powercap_control_type *pos = NULL;
+       bool found = false;
+
+       mutex_lock(&powercap_cntrl_list_lock);
+
+       list_for_each_entry(pos, &powercap_cntrl_list, node) {
+               if (pos == control_type) {
+                       found = true;
+                       break;
+               }
+       }
+       mutex_unlock(&powercap_cntrl_list_lock);
+
+       return found;
+}
+
+static ssize_t name_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct powercap_zone *power_zone = to_powercap_zone(dev);
+
+       return sprintf(buf, "%s\n", power_zone->name);
+}
+
+static DEVICE_ATTR_RO(name);
+
+/* Create zone and attributes in sysfs */
+static void create_power_zone_common_attributes(
+                                       struct powercap_zone *power_zone)
+{
+       int count = 0;
+
+       power_zone->zone_dev_attrs[count++] = &dev_attr_name.attr;
+       if (power_zone->ops->get_max_energy_range_uj)
+               power_zone->zone_dev_attrs[count++] =
+                                       &dev_attr_max_energy_range_uj.attr;
+       if (power_zone->ops->get_energy_uj)
+               power_zone->zone_dev_attrs[count++] =
+                                       &dev_attr_energy_uj.attr;
+       if (power_zone->ops->get_power_uw)
+               power_zone->zone_dev_attrs[count++] =
+                                       &dev_attr_power_uw.attr;
+       if (power_zone->ops->get_max_power_range_uw)
+               power_zone->zone_dev_attrs[count++] =
+                                       &dev_attr_max_power_range_uw.attr;
+       power_zone->zone_dev_attrs[count] = NULL;
+       power_zone->zone_attr_count = count;
+}
+
+static void powercap_release(struct device *dev)
+{
+       bool allocated;
+
+       if (dev->parent) {
+               struct powercap_zone *power_zone = to_powercap_zone(dev);
+
+               /* Store flag as the release() may free memory */
+               allocated = power_zone->allocated;
+               /* Remove id from parent idr struct */
+               idr_remove(power_zone->parent_idr, power_zone->id);
+               /* Destroy idrs allocated for this zone */
+               idr_destroy(&power_zone->idr);
+               kfree(power_zone->name);
+               kfree(power_zone->zone_dev_attrs);
+               kfree(power_zone->constraints);
+               if (power_zone->ops->release)
+                       power_zone->ops->release(power_zone);
+               if (allocated)
+                       kfree(power_zone);
+       } else {
+               struct powercap_control_type *control_type =
+                                               to_powercap_control_type(dev);
+
+               /* Store flag as the release() may free memory */
+               allocated = control_type->allocated;
+               idr_destroy(&control_type->idr);
+               mutex_destroy(&control_type->lock);
+               if (control_type->ops && control_type->ops->release)
+                       control_type->ops->release(control_type);
+               if (allocated)
+                       kfree(control_type);
+       }
+}
+
+static ssize_t enabled_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       bool mode = true;
+
+       /* Default is enabled */
+       if (dev->parent) {
+               struct powercap_zone *power_zone = to_powercap_zone(dev);
+               if (power_zone->ops->get_enable)
+                       if (power_zone->ops->get_enable(power_zone, &mode))
+                               mode = false;
+       } else {
+               struct powercap_control_type *control_type =
+                                               to_powercap_control_type(dev);
+               if (control_type->ops && control_type->ops->get_enable)
+                       if (control_type->ops->get_enable(control_type, &mode))
+                               mode = false;
+       }
+
+       return sprintf(buf, "%d\n", mode);
+}
+
+static ssize_t enabled_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,  size_t len)
+{
+       bool mode;
+
+       if (strtobool(buf, &mode))
+               return -EINVAL;
+       if (dev->parent) {
+               struct powercap_zone *power_zone = to_powercap_zone(dev);
+               if (power_zone->ops->set_enable)
+                       if (!power_zone->ops->set_enable(power_zone, mode))
+                               return len;
+       } else {
+               struct powercap_control_type *control_type =
+                                               to_powercap_control_type(dev);
+               if (control_type->ops && control_type->ops->set_enable)
+                       if (!control_type->ops->set_enable(control_type, mode))
+                               return len;
+       }
+
+       return -ENOSYS;
+}
+
+static DEVICE_ATTR_RW(enabled);
+
+static struct attribute *powercap_attrs[] = {
+       &dev_attr_enabled.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(powercap);
+
+static struct class powercap_class = {
+       .name = "powercap",
+       .dev_release = powercap_release,
+       .dev_groups = powercap_groups,
+};
+
+struct powercap_zone *powercap_register_zone(
+                               struct powercap_zone *power_zone,
+                               struct powercap_control_type *control_type,
+                               const char *name,
+                               struct powercap_zone *parent,
+                               const struct powercap_zone_ops *ops,
+                               int nr_constraints,
+                               struct powercap_zone_constraint_ops *const_ops)
+{
+       int result;
+       int nr_attrs;
+
+       if (!name || !control_type || !ops ||
+                       nr_constraints > MAX_CONSTRAINTS_PER_ZONE ||
+                       (!ops->get_energy_uj && !ops->get_power_uw) ||
+                       !control_type_valid(control_type))
+               return ERR_PTR(-EINVAL);
+
+       if (power_zone) {
+               if (!ops->release)
+                       return ERR_PTR(-EINVAL);
+               memset(power_zone, 0, sizeof(*power_zone));
+       } else {
+               power_zone = kzalloc(sizeof(*power_zone), GFP_KERNEL);
+               if (!power_zone)
+                       return ERR_PTR(-ENOMEM);
+               power_zone->allocated = true;
+       }
+       power_zone->ops = ops;
+       power_zone->control_type_inst = control_type;
+       if (!parent) {
+               power_zone->dev.parent = &control_type->dev;
+               power_zone->parent_idr = &control_type->idr;
+       } else {
+               power_zone->dev.parent = &parent->dev;
+               power_zone->parent_idr = &parent->idr;
+       }
+       power_zone->dev.class = &powercap_class;
+
+       mutex_lock(&control_type->lock);
+       /* Using idr to get the unique id */
+       result = idr_alloc(power_zone->parent_idr, NULL, 0, 0, GFP_KERNEL);
+       if (result < 0)
+               goto err_idr_alloc;
+
+       power_zone->id = result;
+       idr_init(&power_zone->idr);
+       power_zone->name = kstrdup(name, GFP_KERNEL);
+       if (!power_zone->name)
+               goto err_name_alloc;
+       dev_set_name(&power_zone->dev, "%s:%x",
+                                       dev_name(power_zone->dev.parent),
+                                       power_zone->id);
+       power_zone->constraints = kzalloc(sizeof(*power_zone->constraints) *
+                                        nr_constraints, GFP_KERNEL);
+       if (!power_zone->constraints)
+               goto err_const_alloc;
+
+       nr_attrs = nr_constraints * POWERCAP_CONSTRAINTS_ATTRS +
+                                               POWERCAP_ZONE_MAX_ATTRS + 1;
+       power_zone->zone_dev_attrs = kzalloc(sizeof(void *) *
+                                               nr_attrs, GFP_KERNEL);
+       if (!power_zone->zone_dev_attrs)
+               goto err_attr_alloc;
+       create_power_zone_common_attributes(power_zone);
+       result = create_constraints(power_zone, nr_constraints, const_ops);
+       if (result)
+               goto err_dev_ret;
+
+       power_zone->zone_dev_attrs[power_zone->zone_attr_count] = NULL;
+       power_zone->dev_zone_attr_group.attrs = power_zone->zone_dev_attrs;
+       power_zone->dev_attr_groups[0] = &power_zone->dev_zone_attr_group;
+       power_zone->dev_attr_groups[1] = NULL;
+       power_zone->dev.groups = power_zone->dev_attr_groups;
+       result = device_register(&power_zone->dev);
+       if (result)
+               goto err_dev_ret;
+
+       control_type->nr_zones++;
+       mutex_unlock(&control_type->lock);
+
+       return power_zone;
+
+err_dev_ret:
+       kfree(power_zone->zone_dev_attrs);
+err_attr_alloc:
+       kfree(power_zone->constraints);
+err_const_alloc:
+       kfree(power_zone->name);
+err_name_alloc:
+       idr_remove(power_zone->parent_idr, power_zone->id);
+err_idr_alloc:
+       if (power_zone->allocated)
+               kfree(power_zone);
+       mutex_unlock(&control_type->lock);
+
+       return ERR_PTR(result);
+}
+EXPORT_SYMBOL_GPL(powercap_register_zone);
+
+int powercap_unregister_zone(struct powercap_control_type *control_type,
+                               struct powercap_zone *power_zone)
+{
+       if (!power_zone || !control_type)
+               return -EINVAL;
+
+       mutex_lock(&control_type->lock);
+       control_type->nr_zones--;
+       mutex_unlock(&control_type->lock);
+
+       device_unregister(&power_zone->dev);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(powercap_unregister_zone);
+
+struct powercap_control_type *powercap_register_control_type(
+                               struct powercap_control_type *control_type,
+                               const char *name,
+                               const struct powercap_control_type_ops *ops)
+{
+       int result;
+
+       if (!name)
+               return ERR_PTR(-EINVAL);
+       if (control_type) {
+               if (!ops || !ops->release)
+                       return ERR_PTR(-EINVAL);
+               memset(control_type, 0, sizeof(*control_type));
+       } else {
+               control_type = kzalloc(sizeof(*control_type), GFP_KERNEL);
+               if (!control_type)
+                       return ERR_PTR(-ENOMEM);
+               control_type->allocated = true;
+       }
+       mutex_init(&control_type->lock);
+       control_type->ops = ops;
+       INIT_LIST_HEAD(&control_type->node);
+       control_type->dev.class = &powercap_class;
+       dev_set_name(&control_type->dev, "%s", name);
+       result = device_register(&control_type->dev);
+       if (result) {
+               if (control_type->allocated)
+                       kfree(control_type);
+               return ERR_PTR(result);
+       }
+       idr_init(&control_type->idr);
+
+       mutex_lock(&powercap_cntrl_list_lock);
+       list_add_tail(&control_type->node, &powercap_cntrl_list);
+       mutex_unlock(&powercap_cntrl_list_lock);
+
+       return control_type;
+}
+EXPORT_SYMBOL_GPL(powercap_register_control_type);
+
+int powercap_unregister_control_type(struct powercap_control_type *control_type)
+{
+       struct powercap_control_type *pos = NULL;
+
+       if (control_type->nr_zones) {
+               dev_err(&control_type->dev, "Zones of this type still not freed\n");
+               return -EINVAL;
+       }
+       mutex_lock(&powercap_cntrl_list_lock);
+       list_for_each_entry(pos, &powercap_cntrl_list, node) {
+               if (pos == control_type) {
+                       list_del(&control_type->node);
+                       mutex_unlock(&powercap_cntrl_list_lock);
+                       device_unregister(&control_type->dev);
+                       return 0;
+               }
+       }
+       mutex_unlock(&powercap_cntrl_list_lock);
+
+       return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(powercap_unregister_control_type);
+
+static int __init powercap_init(void)
+{
+       int result = 0;
+
+       result = seed_constraint_attributes();
+       if (result)
+               return result;
+
+       result = class_register(&powercap_class);
+
+       return result;
+}
+
+device_initcall(powercap_init);
+
+MODULE_DESCRIPTION("PowerCap sysfs Driver");
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
index 5adb2042e824fc30815ea891c54b89526680b4eb..cee7e2708a1fe35359eb81cc458d939e50ad1906 100644 (file)
@@ -2077,6 +2077,7 @@ dasd_eckd_build_format(struct dasd_device *base,
        int intensity = 0;
        int r0_perm;
        int nr_tracks;
+       int use_prefix;
 
        startdev = dasd_alias_get_start_dev(base);
        if (!startdev)
@@ -2106,28 +2107,46 @@ dasd_eckd_build_format(struct dasd_device *base,
                intensity = fdata->intensity;
        }
 
+       use_prefix = base_priv->features.feature[8] & 0x01;
+
        switch (intensity) {
        case 0x00:      /* Normal format */
        case 0x08:      /* Normal format, use cdl. */
                cplength = 2 + (rpt*nr_tracks);
-               datasize = sizeof(struct PFX_eckd_data) +
-                       sizeof(struct LO_eckd_data) +
-                       rpt * nr_tracks * sizeof(struct eckd_count);
+               if (use_prefix)
+                       datasize = sizeof(struct PFX_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               rpt * nr_tracks * sizeof(struct eckd_count);
+               else
+                       datasize = sizeof(struct DE_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               rpt * nr_tracks * sizeof(struct eckd_count);
                break;
        case 0x01:      /* Write record zero and format track. */
        case 0x09:      /* Write record zero and format track, use cdl. */
                cplength = 2 + rpt * nr_tracks;
-               datasize = sizeof(struct PFX_eckd_data) +
-                       sizeof(struct LO_eckd_data) +
-                       sizeof(struct eckd_count) +
-                       rpt * nr_tracks * sizeof(struct eckd_count);
+               if (use_prefix)
+                       datasize = sizeof(struct PFX_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               sizeof(struct eckd_count) +
+                               rpt * nr_tracks * sizeof(struct eckd_count);
+               else
+                       datasize = sizeof(struct DE_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               sizeof(struct eckd_count) +
+                               rpt * nr_tracks * sizeof(struct eckd_count);
                break;
        case 0x04:      /* Invalidate track. */
        case 0x0c:      /* Invalidate track, use cdl. */
                cplength = 3;
-               datasize = sizeof(struct PFX_eckd_data) +
-                       sizeof(struct LO_eckd_data) +
-                       sizeof(struct eckd_count);
+               if (use_prefix)
+                       datasize = sizeof(struct PFX_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               sizeof(struct eckd_count);
+               else
+                       datasize = sizeof(struct DE_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               sizeof(struct eckd_count);
                break;
        default:
                dev_warn(&startdev->cdev->dev,
@@ -2147,14 +2166,25 @@ dasd_eckd_build_format(struct dasd_device *base,
 
        switch (intensity & ~0x08) {
        case 0x00: /* Normal format. */
-               prefix(ccw++, (struct PFX_eckd_data *) data,
-                      fdata->start_unit, fdata->stop_unit,
-                      DASD_ECKD_CCW_WRITE_CKD, base, startdev);
-               /* grant subsystem permission to format R0 */
-               if (r0_perm)
-                       ((struct PFX_eckd_data *)data)
-                               ->define_extent.ga_extended |= 0x04;
-               data += sizeof(struct PFX_eckd_data);
+               if (use_prefix) {
+                       prefix(ccw++, (struct PFX_eckd_data *) data,
+                              fdata->start_unit, fdata->stop_unit,
+                              DASD_ECKD_CCW_WRITE_CKD, base, startdev);
+                       /* grant subsystem permission to format R0 */
+                       if (r0_perm)
+                               ((struct PFX_eckd_data *)data)
+                                       ->define_extent.ga_extended |= 0x04;
+                       data += sizeof(struct PFX_eckd_data);
+               } else {
+                       define_extent(ccw++, (struct DE_eckd_data *) data,
+                                     fdata->start_unit, fdata->stop_unit,
+                                     DASD_ECKD_CCW_WRITE_CKD, startdev);
+                       /* grant subsystem permission to format R0 */
+                       if (r0_perm)
+                               ((struct DE_eckd_data *) data)
+                                       ->ga_extended |= 0x04;
+                       data += sizeof(struct DE_eckd_data);
+               }
                ccw[-1].flags |= CCW_FLAG_CC;
                locate_record(ccw++, (struct LO_eckd_data *) data,
                              fdata->start_unit, 0, rpt*nr_tracks,
@@ -2163,11 +2193,18 @@ dasd_eckd_build_format(struct dasd_device *base,
                data += sizeof(struct LO_eckd_data);
                break;
        case 0x01: /* Write record zero + format track. */
-               prefix(ccw++, (struct PFX_eckd_data *) data,
-                      fdata->start_unit, fdata->stop_unit,
-                      DASD_ECKD_CCW_WRITE_RECORD_ZERO,
-                      base, startdev);
-               data += sizeof(struct PFX_eckd_data);
+               if (use_prefix) {
+                       prefix(ccw++, (struct PFX_eckd_data *) data,
+                              fdata->start_unit, fdata->stop_unit,
+                              DASD_ECKD_CCW_WRITE_RECORD_ZERO,
+                              base, startdev);
+                       data += sizeof(struct PFX_eckd_data);
+               } else {
+                       define_extent(ccw++, (struct DE_eckd_data *) data,
+                              fdata->start_unit, fdata->stop_unit,
+                              DASD_ECKD_CCW_WRITE_RECORD_ZERO, startdev);
+                       data += sizeof(struct DE_eckd_data);
+               }
                ccw[-1].flags |= CCW_FLAG_CC;
                locate_record(ccw++, (struct LO_eckd_data *) data,
                              fdata->start_unit, 0, rpt * nr_tracks + 1,
@@ -2176,10 +2213,17 @@ dasd_eckd_build_format(struct dasd_device *base,
                data += sizeof(struct LO_eckd_data);
                break;
        case 0x04: /* Invalidate track. */
-               prefix(ccw++, (struct PFX_eckd_data *) data,
-                      fdata->start_unit, fdata->stop_unit,
-                      DASD_ECKD_CCW_WRITE_CKD, base, startdev);
-               data += sizeof(struct PFX_eckd_data);
+               if (use_prefix) {
+                       prefix(ccw++, (struct PFX_eckd_data *) data,
+                              fdata->start_unit, fdata->stop_unit,
+                              DASD_ECKD_CCW_WRITE_CKD, base, startdev);
+                       data += sizeof(struct PFX_eckd_data);
+               } else {
+                       define_extent(ccw++, (struct DE_eckd_data *) data,
+                              fdata->start_unit, fdata->stop_unit,
+                              DASD_ECKD_CCW_WRITE_CKD, startdev);
+                       data += sizeof(struct DE_eckd_data);
+               }
                ccw[-1].flags |= CCW_FLAG_CC;
                locate_record(ccw++, (struct LO_eckd_data *) data,
                              fdata->start_unit, 0, 1,
index a3aa374799dcf99bd334b6e49c8d7753838fbdc3..1fe264379e0d10b57ddca456ce16b72c23535ccb 100644 (file)
@@ -486,7 +486,7 @@ sclp_sync_wait(void)
        timeout = 0;
        if (timer_pending(&sclp_request_timer)) {
                /* Get timeout TOD value */
-               timeout = get_tod_clock() +
+               timeout = get_tod_clock_fast() +
                          sclp_tod_from_jiffies(sclp_request_timer.expires -
                                                jiffies);
        }
@@ -508,7 +508,7 @@ sclp_sync_wait(void)
        while (sclp_running_state != sclp_running_state_idle) {
                /* Check for expired request timer */
                if (timer_pending(&sclp_request_timer) &&
-                   get_tod_clock() > timeout &&
+                   get_tod_clock_fast() > timeout &&
                    del_timer(&sclp_request_timer))
                        sclp_request_timer.function(sclp_request_timer.data);
                cpu_relax();
index 9b3a24e8d3a0e0dfec9ffcbf1757ddd37f66329e..cf31d3321dab86b889b16fa5e3b9b2e433c3992d 100644 (file)
@@ -313,7 +313,7 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp)
        int ret;
 
        dev_num = iminor(inode);
-       if (dev_num > MAXMINOR)
+       if (dev_num >= MAXMINOR)
                return -ENODEV;
        logptr = &sys_ser[dev_num];
 
index d7da67a31c77f606ef68445f9da446b521a4abf1..88e35d85d205f7c21de1f81860865386a7845289 100644 (file)
@@ -878,9 +878,9 @@ static void css_reset(void)
                        atomic_inc(&chpid_reset_count);
        }
        /* Wait for machine check for all channel paths. */
-       timeout = get_tod_clock() + (RCHP_TIMEOUT << 12);
+       timeout = get_tod_clock_fast() + (RCHP_TIMEOUT << 12);
        while (atomic_read(&chpid_reset_count) != 0) {
-               if (get_tod_clock() > timeout)
+               if (get_tod_clock_fast() > timeout)
                        break;
                cpu_relax();
        }
index 8ed52aa4912269405158e300f1c983577b29caec..bbd3e511c771addebda2639675d85664b3191494 100644 (file)
@@ -338,10 +338,10 @@ again:
                retries++;
 
                if (!start_time) {
-                       start_time = get_tod_clock();
+                       start_time = get_tod_clock_fast();
                        goto again;
                }
-               if ((get_tod_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE)
+               if (get_tod_clock_fast() - start_time < QDIO_BUSY_BIT_PATIENCE)
                        goto again;
        }
        if (retries) {
@@ -504,7 +504,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
        int count, stop;
        unsigned char state = 0;
 
-       q->timestamp = get_tod_clock();
+       q->timestamp = get_tod_clock_fast();
 
        /*
         * Don't check 128 buffers, as otherwise qdio_inbound_q_moved
@@ -595,7 +595,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q)
         * At this point we know, that inbound first_to_check
         * has (probably) not moved (see qdio_inbound_processing).
         */
-       if (get_tod_clock() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) {
+       if (get_tod_clock_fast() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) {
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x",
                              q->first_to_check);
                return 1;
@@ -728,7 +728,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
        int count, stop;
        unsigned char state = 0;
 
-       q->timestamp = get_tod_clock();
+       q->timestamp = get_tod_clock_fast();
 
        if (need_siga_sync(q))
                if (((queue_type(q) != QDIO_IQDIO_QFMT) &&
index feab3a5e50b5ec6f546b102b6550ff7652424cac..757eb0716d45d4f273519ca2e2dd2ed03486a4a8 100644 (file)
@@ -696,7 +696,7 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter)
        while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
                                        PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
                                        pci_device)) != NULL) {
-               struct blogic_adapter *adapter = adapter;
+               struct blogic_adapter *host_adapter = adapter;
                struct blogic_adapter_info adapter_info;
                enum blogic_isa_ioport mod_ioaddr_req;
                unsigned char bus;
@@ -744,9 +744,9 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter)
                   known and enabled, note that the particular Standard ISA I/O
                   Address should not be probed.
                 */
-               adapter->io_addr = io_addr;
-               blogic_intreset(adapter);
-               if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
+               host_adapter->io_addr = io_addr;
+               blogic_intreset(host_adapter);
+               if (blogic_cmd(host_adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
                                &adapter_info, sizeof(adapter_info)) ==
                                sizeof(adapter_info)) {
                        if (adapter_info.isa_port < 6)
@@ -762,7 +762,7 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter)
                   I/O Address assigned at system initialization.
                 */
                mod_ioaddr_req = BLOGIC_IO_DISABLE;
-               blogic_cmd(adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req,
+               blogic_cmd(host_adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req,
                                sizeof(mod_ioaddr_req), NULL, 0);
                /*
                   For the first MultiMaster Host Adapter enumerated,
@@ -779,12 +779,12 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter)
 
                        fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45;
                        fetch_localram.count = sizeof(autoscsi_byte45);
-                       blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM,
+                       blogic_cmd(host_adapter, BLOGIC_FETCH_LOCALRAM,
                                        &fetch_localram, sizeof(fetch_localram),
                                        &autoscsi_byte45,
                                        sizeof(autoscsi_byte45));
-                       blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id,
-                                       sizeof(id));
+                       blogic_cmd(host_adapter, BLOGIC_GET_BOARD_ID, NULL, 0,
+                                       &id, sizeof(id));
                        if (id.fw_ver_digit1 == '5')
                                force_scan_order =
                                        autoscsi_byte45.force_scan_order;
index 2ef497ebadc06500a2aa95090f26d188cf8bccb7..ee5c1833eb731cb1e0e731448c287ca1b8f5b2ad 100644 (file)
@@ -20,7 +20,7 @@
  * | Device Discovery             |       0x2095       | 0x2020-0x2022, |
  * |                              |                    | 0x2011-0x2012, |
  * |                              |                    | 0x2016         |
- * | Queue Command and IO tracing |       0x3058       | 0x3006-0x300b  |
+ * | Queue Command and IO tracing |       0x3059       | 0x3006-0x300b  |
  * |                              |                    | 0x3027-0x3028  |
  * |                              |                    | 0x303d-0x3041  |
  * |                              |                    | 0x302d,0x3033  |
index df1b30ba938cc0578d409880711d2afa5b2a8898..ff9c86b1a0d896a870dd62b22515ee5dfc629284 100644 (file)
@@ -1957,6 +1957,15 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
        que = MSW(sts->handle);
        req = ha->req_q_map[que];
 
+       /* Check for invalid queue pointer */
+       if (req == NULL ||
+           que >= find_first_zero_bit(ha->req_qid_map, ha->max_req_queues)) {
+               ql_dbg(ql_dbg_io, vha, 0x3059,
+                   "Invalid status handle (0x%x): Bad req pointer. req=%p, "
+                   "que=%u.\n", sts->handle, req, que);
+               return;
+       }
+
        /* Validate handle. */
        if (handle < req->num_outstanding_cmds)
                sp = req->outstanding_cmds[handle];
index e62d17d41d4e7b84ddf7469194aa0c63d541d59d..5693f6d7eddb8b20cd9b3e0374a4e73e60ab7aa2 100644 (file)
@@ -2854,6 +2854,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
                gd->events |= DISK_EVENT_MEDIA_CHANGE;
        }
 
+       blk_pm_runtime_init(sdp->request_queue, dev);
        add_disk(gd);
        if (sdkp->capacity)
                sd_dif_config_host(sdkp);
@@ -2862,7 +2863,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
 
        sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
                  sdp->removable ? "removable " : "");
-       blk_pm_runtime_init(sdp->request_queue, dev);
        scsi_autopm_put_device(sdp);
        put_device(&sdkp->dev);
 }
index 9e039c60c0680ae761e2be41f0de0a171368f3c6..740f9ddda227d55f15042e1e7a8d2cadb58aae71 100644 (file)
@@ -240,15 +240,27 @@ EXPORT_SYMBOL_GPL(spi_bus_type);
 static int spi_drv_probe(struct device *dev)
 {
        const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
+       struct spi_device               *spi = to_spi_device(dev);
+       int ret;
+
+       acpi_dev_pm_attach(&spi->dev, true);
+       ret = sdrv->probe(spi);
+       if (ret)
+               acpi_dev_pm_detach(&spi->dev, true);
 
-       return sdrv->probe(to_spi_device(dev));
+       return ret;
 }
 
 static int spi_drv_remove(struct device *dev)
 {
        const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
+       struct spi_device               *spi = to_spi_device(dev);
+       int ret;
+
+       ret = sdrv->remove(spi);
+       acpi_dev_pm_detach(&spi->dev, true);
 
-       return sdrv->remove(to_spi_device(dev));
+       return ret;
 }
 
 static void spi_drv_shutdown(struct device *dev)
@@ -1025,8 +1037,10 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
                return AE_OK;
        }
 
+       adev->power.flags.ignore_parent = true;
        strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias));
        if (spi_add_device(spi)) {
+               adev->power.flags.ignore_parent = false;
                dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",
                        dev_name(&adev->dev));
                spi_dev_put(spi);
index b94a95a597d63ec6428f2b92d460fe208465d351..76d5bbd4d93c38f3e25274f8d7b337eb808f1b7d 100644 (file)
@@ -1,3 +1,4 @@
 config USB_MSI3101
        tristate "Mirics MSi3101 SDR Dongle"
        depends on USB && VIDEO_DEV && VIDEO_V4L2
+        select VIDEOBUF2_VMALLOC
index 24c7b70a6cbf401696ee3faba21047d68a75f6e2..4c3bf776bb207b755c9a5bde50aa32138a6ff09a 100644 (file)
@@ -1131,7 +1131,13 @@ static int msi3101_queue_setup(struct vb2_queue *vq,
        /* Absolute min and max number of buffers available for mmap() */
        *nbuffers = 32;
        *nplanes = 1;
-       sizes[0] = PAGE_ALIGN(3 * 3072); /* 3 * 768 * 4 */
+       /*
+        *   3, wMaxPacketSize 3x 1024 bytes
+        * 504, max IQ sample pairs per 1024 frame
+        *   2, two samples, I and Q
+        *   4, 32-bit float
+        */
+       sizes[0] = PAGE_ALIGN(3 * 504 * 2 * 4); /* = 12096 */
        dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
                        __func__, *nbuffers, sizes[0]);
        return 0;
@@ -1657,7 +1663,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
                        f->frequency * 625UL / 10UL);
 }
 
-const struct v4l2_ioctl_ops msi3101_ioctl_ops = {
+static const struct v4l2_ioctl_ops msi3101_ioctl_ops = {
        .vidioc_querycap          = msi3101_querycap,
 
        .vidioc_enum_input        = msi3101_enum_input,
index 551c96ca60acab10e0033a8946693b1371bcbfbe..0f199f6a07385e6ea03d4c12da24863cd7e4f7cd 100644 (file)
@@ -134,10 +134,10 @@ static int pscsi_pmode_enable_hba(struct se_hba *hba, unsigned long mode_flag)
         * pSCSI Host ID and enable for phba mode
         */
        sh = scsi_host_lookup(phv->phv_host_id);
-       if (IS_ERR(sh)) {
+       if (!sh) {
                pr_err("pSCSI: Unable to locate SCSI Host for"
                        " phv_host_id: %d\n", phv->phv_host_id);
-               return PTR_ERR(sh);
+               return -EINVAL;
        }
 
        phv->phv_lld_host = sh;
@@ -515,10 +515,10 @@ static int pscsi_configure_device(struct se_device *dev)
                        sh = phv->phv_lld_host;
                } else {
                        sh = scsi_host_lookup(pdv->pdv_host_id);
-                       if (IS_ERR(sh)) {
+                       if (!sh) {
                                pr_err("pSCSI: Unable to locate"
                                        " pdv_host_id: %d\n", pdv->pdv_host_id);
-                               return PTR_ERR(sh);
+                               return -EINVAL;
                        }
                }
        } else {
index 4714c6f8da4be5fe39e797237fa8a35de0450883..d9b92b2c524d4f055a035f4343175fbdd3877c4c 100644 (file)
@@ -263,6 +263,11 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
                        sectors, cmd->se_dev->dev_attrib.max_write_same_len);
                return TCM_INVALID_CDB_FIELD;
        }
+       /* We always have ANC_SUP == 0 so setting ANCHOR is always an error */
+       if (flags[0] & 0x10) {
+               pr_warn("WRITE SAME with ANCHOR not supported\n");
+               return TCM_INVALID_CDB_FIELD;
+       }
        /*
         * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting
         * translated into block discard requests within backend code.
index 3da4fd10b9f820b6409980055ae19a2b3607f713..474cd44fac14d61b530a6100d5e6060086777560 100644 (file)
@@ -82,6 +82,9 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
        mutex_lock(&g_device_mutex);
        list_for_each_entry(se_dev, &g_device_list, g_dev_node) {
 
+               if (!se_dev->dev_attrib.emulate_3pc)
+                       continue;
+
                memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
                target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]);
 
@@ -357,6 +360,7 @@ struct xcopy_pt_cmd {
        struct se_cmd se_cmd;
        struct xcopy_op *xcopy_op;
        struct completion xpt_passthrough_sem;
+       unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
 };
 
 static struct se_port xcopy_pt_port;
@@ -675,7 +679,8 @@ static int target_xcopy_issue_pt_cmd(struct xcopy_pt_cmd *xpt_cmd)
 
        pr_debug("target_xcopy_issue_pt_cmd(): SCSI status: 0x%02x\n",
                        se_cmd->scsi_status);
-       return 0;
+
+       return (se_cmd->scsi_status) ? -EINVAL : 0;
 }
 
 static int target_xcopy_read_source(
@@ -708,7 +713,7 @@ static int target_xcopy_read_source(
                (unsigned long long)src_lba, src_sectors, length);
 
        transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, NULL, length,
-                               DMA_FROM_DEVICE, 0, NULL);
+                             DMA_FROM_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
        xop->src_pt_cmd = xpt_cmd;
 
        rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0],
@@ -768,7 +773,7 @@ static int target_xcopy_write_destination(
                (unsigned long long)dst_lba, dst_sectors, length);
 
        transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, NULL, length,
-                               DMA_TO_DEVICE, 0, NULL);
+                             DMA_TO_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
        xop->dst_pt_cmd = xpt_cmd;
 
        rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, dst_dev, &cdb[0],
@@ -884,30 +889,42 @@ out:
 
 sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
 {
+       struct se_device *dev = se_cmd->se_dev;
        struct xcopy_op *xop = NULL;
        unsigned char *p = NULL, *seg_desc;
        unsigned int list_id, list_id_usage, sdll, inline_dl, sa;
+       sense_reason_t ret = TCM_INVALID_PARAMETER_LIST;
        int rc;
        unsigned short tdll;
 
+       if (!dev->dev_attrib.emulate_3pc) {
+               pr_err("EXTENDED_COPY operation explicitly disabled\n");
+               return TCM_UNSUPPORTED_SCSI_OPCODE;
+       }
+
        sa = se_cmd->t_task_cdb[1] & 0x1f;
        if (sa != 0x00) {
                pr_err("EXTENDED_COPY(LID4) not supported\n");
                return TCM_UNSUPPORTED_SCSI_OPCODE;
        }
 
+       xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL);
+       if (!xop) {
+               pr_err("Unable to allocate xcopy_op\n");
+               return TCM_OUT_OF_RESOURCES;
+       }
+       xop->xop_se_cmd = se_cmd;
+
        p = transport_kmap_data_sg(se_cmd);
        if (!p) {
                pr_err("transport_kmap_data_sg() failed in target_do_xcopy\n");
+               kfree(xop);
                return TCM_OUT_OF_RESOURCES;
        }
 
        list_id = p[0];
-       if (list_id != 0x00) {
-               pr_err("XCOPY with non zero list_id: 0x%02x\n", list_id);
-               goto out;
-       }
-       list_id_usage = (p[1] & 0x18);
+       list_id_usage = (p[1] & 0x18) >> 3;
+
        /*
         * Determine TARGET DESCRIPTOR LIST LENGTH + SEGMENT DESCRIPTOR LIST LENGTH
         */
@@ -920,13 +937,6 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
                goto out;
        }
 
-       xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL);
-       if (!xop) {
-               pr_err("Unable to allocate xcopy_op\n");
-               goto out;
-       }
-       xop->xop_se_cmd = se_cmd;
-
        pr_debug("Processing XCOPY with list_id: 0x%02x list_id_usage: 0x%02x"
                " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
                tdll, sdll, inline_dl);
@@ -935,6 +945,17 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
        if (rc <= 0)
                goto out;
 
+       if (xop->src_dev->dev_attrib.block_size !=
+           xop->dst_dev->dev_attrib.block_size) {
+               pr_err("XCOPY: Non matching src_dev block_size: %u + dst_dev"
+                      " block_size: %u currently unsupported\n",
+                       xop->src_dev->dev_attrib.block_size,
+                       xop->dst_dev->dev_attrib.block_size);
+               xcopy_pt_undepend_remotedev(xop);
+               ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+               goto out;
+       }
+
        pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc,
                                rc * XCOPY_TARGET_DESC_LEN);
        seg_desc = &p[16];
@@ -957,7 +978,7 @@ out:
        if (p)
                transport_kunmap_data_sg(se_cmd);
        kfree(xop);
-       return TCM_INVALID_CDB_FIELD;
+       return ret;
 }
 
 static sense_reason_t target_rcr_operating_parameters(struct se_cmd *se_cmd)
index dbfc390330acf2ee8bc6af339ff22f3b6fc3ec77..5ef596765060ac605013e41a45ced379132e8853 100644 (file)
@@ -78,7 +78,6 @@ config THERMAL_GOV_USER_SPACE
 config CPU_THERMAL
        bool "generic cpu cooling support"
        depends on CPU_FREQ
-       select CPU_FREQ_TABLE
        help
          This implements the generic cpu cooling mechanism through frequency
          reduction. An ACPI version of this already exists
index f10a6ad37c0609fd2383061d1c4f651bb9cde36b..c2301da08ac7bb0958755b5f2b1291447f4aae6a 100644 (file)
@@ -310,8 +310,6 @@ void exynos_report_trigger(struct thermal_sensor_conf *conf)
        }
 
        th_zone = conf->pzone_data;
-       if (th_zone->therm_dev)
-               return;
 
        if (th_zone->bind == false) {
                for (i = 0; i < th_zone->cool_dev_size; i++) {
index b43afda8acd163085a11eaeb851fb1869403ed4b..32f38b90c4f6a6705b44e8381ee339c2382e47bb 100644 (file)
@@ -317,6 +317,9 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
 
        con = readl(data->base + reg->tmu_ctrl);
 
+       if (pdata->test_mux)
+               con |= (pdata->test_mux << reg->test_mux_addr_shift);
+
        if (pdata->reference_voltage) {
                con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
                con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
@@ -488,7 +491,7 @@ static const struct of_device_id exynos_tmu_match[] = {
        },
        {
                .compatible = "samsung,exynos4412-tmu",
-               .data = (void *)EXYNOS5250_TMU_DRV_DATA,
+               .data = (void *)EXYNOS4412_TMU_DRV_DATA,
        },
        {
                .compatible = "samsung,exynos5250-tmu",
@@ -629,9 +632,10 @@ static int exynos_tmu_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       if (pdata->type == SOC_ARCH_EXYNOS ||
-               pdata->type == SOC_ARCH_EXYNOS4210 ||
-                               pdata->type == SOC_ARCH_EXYNOS5440)
+       if (pdata->type == SOC_ARCH_EXYNOS4210 ||
+           pdata->type == SOC_ARCH_EXYNOS4412 ||
+           pdata->type == SOC_ARCH_EXYNOS5250 ||
+           pdata->type == SOC_ARCH_EXYNOS5440)
                data->soc = pdata->type;
        else {
                ret = -EINVAL;
index b364c9eee70103a622a852096295f4e3339b474f..3fb65547e64c9d9e3d3410f1c0ea729fb5a9332e 100644 (file)
@@ -41,7 +41,8 @@ enum calibration_mode {
 
 enum soc_type {
        SOC_ARCH_EXYNOS4210 = 1,
-       SOC_ARCH_EXYNOS,
+       SOC_ARCH_EXYNOS4412,
+       SOC_ARCH_EXYNOS5250,
        SOC_ARCH_EXYNOS5440,
 };
 
@@ -84,6 +85,7 @@ enum soc_type {
  * @triminfo_reload_shift: shift of triminfo reload enable bit in triminfo_ctrl
        reg.
  * @tmu_ctrl: TMU main controller register.
+ * @test_mux_addr_shift: shift bits of test mux address.
  * @buf_vref_sel_shift: shift bits of reference voltage in tmu_ctrl register.
  * @buf_vref_sel_mask: mask bits of reference voltage in tmu_ctrl register.
  * @therm_trip_mode_shift: shift bits of tripping mode in tmu_ctrl register.
@@ -150,6 +152,7 @@ struct exynos_tmu_registers {
        u32     triminfo_reload_shift;
 
        u32     tmu_ctrl;
+       u32     test_mux_addr_shift;
        u32     buf_vref_sel_shift;
        u32     buf_vref_sel_mask;
        u32     therm_trip_mode_shift;
@@ -257,6 +260,7 @@ struct exynos_tmu_registers {
  * @first_point_trim: temp value of the first point trimming
  * @second_point_trim: temp value of the second point trimming
  * @default_temp_offset: default temperature offset in case of no trimming
+ * @test_mux; information if SoC supports test MUX
  * @cal_type: calibration type for temperature
  * @cal_mode: calibration mode for temperature
  * @freq_clip_table: Table representing frequency reduction percentage.
@@ -286,6 +290,7 @@ struct exynos_tmu_platform_data {
        u8 first_point_trim;
        u8 second_point_trim;
        u8 default_temp_offset;
+       u8 test_mux;
 
        enum calibration_type cal_type;
        enum calibration_mode cal_mode;
index 9002499c1f69289350f2e7edd813716919927083..073c292baa53e12d0bc7c6aef2a8956a81ea4a6d 100644 (file)
@@ -90,14 +90,15 @@ struct exynos_tmu_init_data const exynos4210_default_tmu_data = {
 };
 #endif
 
-#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
-static const struct exynos_tmu_registers exynos5250_tmu_registers = {
+#if defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)
+static const struct exynos_tmu_registers exynos4412_tmu_registers = {
        .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
        .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
        .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
        .triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
        .triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
+       .test_mux_addr_shift = EXYNOS4412_MUX_ADDR_SHIFT,
        .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
        .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
        .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
@@ -128,7 +129,7 @@ static const struct exynos_tmu_registers exynos5250_tmu_registers = {
        .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
 };
 
-#define EXYNOS5250_TMU_DATA \
+#define EXYNOS4412_TMU_DATA \
        .threshold_falling = 10, \
        .trigger_levels[0] = 85, \
        .trigger_levels[1] = 103, \
@@ -162,15 +163,32 @@ static const struct exynos_tmu_registers exynos5250_tmu_registers = {
                .temp_level = 103, \
        }, \
        .freq_tab_count = 2, \
-       .type = SOC_ARCH_EXYNOS, \
-       .registers = &exynos5250_tmu_registers, \
+       .registers = &exynos4412_tmu_registers, \
        .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \
                        TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \
                        TMU_SUPPORT_EMUL_TIME)
+#endif
 
+#if defined(CONFIG_SOC_EXYNOS4412)
+struct exynos_tmu_init_data const exynos4412_default_tmu_data = {
+       .tmu_data = {
+               {
+                       EXYNOS4412_TMU_DATA,
+                       .type = SOC_ARCH_EXYNOS4412,
+                       .test_mux = EXYNOS4412_MUX_ADDR_VALUE,
+               },
+       },
+       .tmu_count = 1,
+};
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5250)
 struct exynos_tmu_init_data const exynos5250_default_tmu_data = {
        .tmu_data = {
-               { EXYNOS5250_TMU_DATA },
+               {
+                       EXYNOS4412_TMU_DATA,
+                       .type = SOC_ARCH_EXYNOS5250,
+               },
        },
        .tmu_count = 1,
 };
index dc7feb51099b449bb680e5b9237966b8eb47295e..a1ea19d9e0a6e6bfee1a80f173dcdf4786dcc284 100644 (file)
 
 #define EXYNOS_MAX_TRIGGER_PER_REG     4
 
+/* Exynos4412 specific */
+#define EXYNOS4412_MUX_ADDR_VALUE          6
+#define EXYNOS4412_MUX_ADDR_SHIFT          20
+
 /*exynos5440 specific registers*/
 #define EXYNOS5440_TMU_S0_7_TRIM               0x000
 #define EXYNOS5440_TMU_S0_7_CTRL               0x020
@@ -138,7 +142,14 @@ extern struct exynos_tmu_init_data const exynos4210_default_tmu_data;
 #define EXYNOS4210_TMU_DRV_DATA (NULL)
 #endif
 
-#if (defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412))
+#if defined(CONFIG_SOC_EXYNOS4412)
+extern struct exynos_tmu_init_data const exynos4412_default_tmu_data;
+#define EXYNOS4412_TMU_DRV_DATA (&exynos4412_default_tmu_data)
+#else
+#define EXYNOS4412_TMU_DRV_DATA (NULL)
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5250)
 extern struct exynos_tmu_init_data const exynos5250_default_tmu_data;
 #define EXYNOS5250_TMU_DRV_DATA (&exynos5250_default_tmu_data)
 #else
index eeef0e2498caa39edc55cd3cf6345953a537f626..fdb07199d9c2693b8ae91af6d626f588ed21350b 100644 (file)
@@ -159,7 +159,7 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
 
        INIT_LIST_HEAD(&hwmon->tz_list);
        strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH);
-       hwmon->device = hwmon_device_register(&tz->device);
+       hwmon->device = hwmon_device_register(NULL);
        if (IS_ERR(hwmon->device)) {
                result = PTR_ERR(hwmon->device);
                goto free_mem;
index 4f8b9af54a5a75d1de884a342920ccb50f9ba869..5a47cc8c8f85ae1771c3faa1042b8f068978d570 100644 (file)
@@ -110,6 +110,7 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
                } else {
                        dev_err(bgp->dev,
                                "Failed to read PCB state. Using defaults\n");
+                       ret = 0;
                }
        }
        *temp = ti_thermal_hotspot_temperature(tmp, slope, constant);
index f36950e4134f55deb02e3a6eb172e9481828ea18..7722cb9d5a8020076afe549192b198542461f352 100644 (file)
@@ -316,18 +316,19 @@ static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
        int phy_id = topology_physical_package_id(cpu);
        struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu);
        bool notify = false;
+       unsigned long flags;
 
        if (!phdev)
                return;
 
-       spin_lock(&pkg_work_lock);
+       spin_lock_irqsave(&pkg_work_lock, flags);
        ++pkg_work_cnt;
        if (unlikely(phy_id > max_phy_id)) {
-               spin_unlock(&pkg_work_lock);
+               spin_unlock_irqrestore(&pkg_work_lock, flags);
                return;
        }
        pkg_work_scheduled[phy_id] = 0;
-       spin_unlock(&pkg_work_lock);
+       spin_unlock_irqrestore(&pkg_work_lock, flags);
 
        enable_pkg_thres_interrupt();
        rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
@@ -397,6 +398,7 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
        int thres_count;
        u32 eax, ebx, ecx, edx;
        u8 *temp;
+       unsigned long flags;
 
        cpuid(6, &eax, &ebx, &ecx, &edx);
        thres_count = ebx & 0x07;
@@ -420,19 +422,19 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
                goto err_ret_unlock;
        }
 
-       spin_lock(&pkg_work_lock);
+       spin_lock_irqsave(&pkg_work_lock, flags);
        if (topology_physical_package_id(cpu) > max_phy_id)
                max_phy_id = topology_physical_package_id(cpu);
        temp = krealloc(pkg_work_scheduled,
                        (max_phy_id+1) * sizeof(u8), GFP_ATOMIC);
        if (!temp) {
-               spin_unlock(&pkg_work_lock);
+               spin_unlock_irqrestore(&pkg_work_lock, flags);
                err = -ENOMEM;
                goto err_ret_free;
        }
        pkg_work_scheduled = temp;
        pkg_work_scheduled[topology_physical_package_id(cpu)] = 0;
-       spin_unlock(&pkg_work_lock);
+       spin_unlock_irqrestore(&pkg_work_lock, flags);
 
        phy_dev_entry->phys_proc_id = topology_physical_package_id(cpu);
        phy_dev_entry->first_cpu = cpu;
index a0ebbc9ce5cdbacc69cc8c240f8d9fd76e43ec12..042aa077b5b3e166a8453ac0684da1dd024f6785 100644 (file)
@@ -1912,9 +1912,6 @@ static int serial_imx_probe_dt(struct imx_port *sport,
 
        sport->devdata = of_id->data;
 
-       if (of_device_is_stdout_path(np))
-               add_preferred_console(imx_reg.cons->name, sport->port.line, 0);
-
        return 0;
 }
 #else
index 93b697a0de658ddc6769fedbe822b1151fef4bab..15ad6fcda88b323b2f5711b753ee76126741ea04 100644 (file)
@@ -561,12 +561,13 @@ static int vt8500_serial_probe(struct platform_device *pdev)
        if (!mmres || !irqres)
                return -ENODEV;
 
-       if (np)
+       if (np) {
                port = of_alias_get_id(np, "serial");
                if (port >= VT8500_MAX_PORTS)
                        port = -1;
-       else
+       } else {
                port = -1;
+       }
 
        if (port < 0) {
                /* calculate the port id */
index 6f96795dd20cc3ff3d0c08490ae8d87b0b2ccccf..64d7a6d9a1adcbd679258661a6b5875bd8bf834a 100644 (file)
@@ -100,8 +100,10 @@ static void host_stop(struct ci_hdrc *ci)
 {
        struct usb_hcd *hcd = ci->hcd;
 
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
+       if (hcd) {
+               usb_remove_hcd(hcd);
+               usb_put_hcd(hcd);
+       }
        if (ci->platdata->reg_vbus)
                regulator_disable(ci->platdata->reg_vbus);
 }
index 5b44cd47da5b28b30046bead355aa54eda3eec0f..01fe36273f3b144cb1c1fe3306ebdf16459c605f 100644 (file)
@@ -97,6 +97,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 },
 
@@ -130,6 +133,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 },
index 2c76ef1320eab679e1dd1aabd1c8466981392efc..08ef2829a7e2b1c06bbd0af51f308884c8ad9a26 100644 (file)
@@ -799,7 +799,7 @@ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev)
         * switchable ports.
         */
        pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
-                       cpu_to_le32(ports_available));
+                       ports_available);
 
        pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
                        &ports_available);
@@ -821,7 +821,7 @@ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev)
         * host.
         */
        pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
-                       cpu_to_le32(ports_available));
+                       ports_available);
 
        pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
                        &ports_available);
index 773a6b28c4f1657670547265e0d73caed6366907..e8b4c56dcf62adf1f5326e8609087cd387fedc2e 100644 (file)
@@ -1157,18 +1157,6 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
                t1 = xhci_port_state_to_neutral(t1);
                if (t1 != t2)
                        xhci_writel(xhci, t2, port_array[port_index]);
-
-               if (hcd->speed != HCD_USB3) {
-                       /* enable remote wake up for USB 2.0 */
-                       __le32 __iomem *addr;
-                       u32 tmp;
-
-                       /* Get the port power control register address. */
-                       addr = port_array[port_index] + PORTPMSC;
-                       tmp = xhci_readl(xhci, addr);
-                       tmp |= PORT_RWE;
-                       xhci_writel(xhci, tmp, addr);
-               }
        }
        hcd->state = HC_STATE_SUSPENDED;
        bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
@@ -1247,20 +1235,6 @@ int xhci_bus_resume(struct usb_hcd *hcd)
                                xhci_ring_device(xhci, slot_id);
                } else
                        xhci_writel(xhci, temp, port_array[port_index]);
-
-               if (hcd->speed != HCD_USB3) {
-                       /* disable remote wake up for USB 2.0 */
-                       __le32 __iomem *addr;
-                       u32 tmp;
-
-                       /* Add one to the port status register address to get
-                        * the port power control register address.
-                        */
-                       addr = port_array[port_index] + PORTPMSC;
-                       tmp = xhci_readl(xhci, addr);
-                       tmp &= ~PORT_RWE;
-                       xhci_writel(xhci, tmp, addr);
-               }
        }
 
        (void) xhci_readl(xhci, &xhci->op_regs->command);
index 236c3aabe94083ab5c1829241a46a20d39829587..b8dffd59eb256e52786328e5e4f1919846a80d9c 100644 (file)
@@ -35,6 +35,9 @@
 #define PCI_VENDOR_ID_ETRON            0x1b6f
 #define PCI_DEVICE_ID_ASROCK_P67       0x7023
 
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI     0x8c31
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI  0x9c31
+
 static const char hcd_name[] = "xhci_hcd";
 
 /* called after powerup, by probe or system-pm "wakeup" */
@@ -69,6 +72,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                                "QUIRK: Fresco Logic xHC needs configure"
                                " endpoint cmd after reset endpoint");
                }
+               if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+                               pdev->revision == 0x4) {
+                       xhci->quirks |= XHCI_SLOW_SUSPEND;
+                       xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
+                               "QUIRK: Fresco Logic xHC revision %u"
+                               "must be suspended extra slowly",
+                               pdev->revision);
+               }
                /* Fresco Logic confirms: all revisions of this chip do not
                 * support MSI, even though some of them claim to in their PCI
                 * capabilities.
@@ -110,6 +121,15 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
                xhci->quirks |= XHCI_AVOID_BEI;
        }
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+           (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI ||
+            pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI)) {
+               /* Workaround for occasional spurious wakeups from S5 (or
+                * any other sleep) on Haswell machines with LPT and LPT-LP
+                * with the new Intel BIOS
+                */
+               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+       }
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
                xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -217,6 +237,11 @@ static void xhci_pci_remove(struct pci_dev *dev)
                usb_put_hcd(xhci->shared_hcd);
        }
        usb_hcd_pci_remove(dev);
+
+       /* Workaround for spurious wakeups at shutdown with HSW */
+       if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+               pci_set_power_state(dev, PCI_D3hot);
+
        kfree(xhci);
 }
 
index 1e36dbb4836693dbe5ac90b8231361f82645a7b1..6e0d886bcce52c19361d321cf68c0abacf5b054c 100644 (file)
@@ -730,6 +730,9 @@ void xhci_shutdown(struct usb_hcd *hcd)
 
        spin_lock_irq(&xhci->lock);
        xhci_halt(xhci);
+       /* Workaround for spurious wakeups at shutdown with HSW */
+       if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+               xhci_reset(xhci);
        spin_unlock_irq(&xhci->lock);
 
        xhci_cleanup_msix(xhci);
@@ -737,6 +740,10 @@ void xhci_shutdown(struct usb_hcd *hcd)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "xhci_shutdown completed - status = %x",
                        xhci_readl(xhci, &xhci->op_regs->status));
+
+       /* Yet another workaround for spurious wakeups at shutdown with HSW */
+       if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+               pci_set_power_state(to_pci_dev(hcd->self.controller), PCI_D3hot);
 }
 
 #ifdef CONFIG_PM
@@ -839,6 +846,7 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
 int xhci_suspend(struct xhci_hcd *xhci)
 {
        int                     rc = 0;
+       unsigned int            delay = XHCI_MAX_HALT_USEC;
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        u32                     command;
 
@@ -861,8 +869,12 @@ int xhci_suspend(struct xhci_hcd *xhci)
        command = xhci_readl(xhci, &xhci->op_regs->command);
        command &= ~CMD_RUN;
        xhci_writel(xhci, command, &xhci->op_regs->command);
+
+       /* Some chips from Fresco Logic need an extraordinary delay */
+       delay *= (xhci->quirks & XHCI_SLOW_SUSPEND) ? 10 : 1;
+
        if (xhci_handshake(xhci, &xhci->op_regs->status,
-                     STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
+                     STS_HALT, STS_HALT, delay)) {
                xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
                spin_unlock_irq(&xhci->lock);
                return -ETIMEDOUT;
index 289fbfbae7463f429ef051602e08e7eccb3e06e8..941d5f59e4dcc254770bac770ba024e36a677bad 100644 (file)
@@ -1548,6 +1548,8 @@ struct xhci_hcd {
 #define XHCI_COMP_MODE_QUIRK   (1 << 14)
 #define XHCI_AVOID_BEI         (1 << 15)
 #define XHCI_PLAT              (1 << 16)
+#define XHCI_SLOW_SUSPEND      (1 << 17)
+#define XHCI_SPURIOUS_WAKEUP   (1 << 18)
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
        /* There are two roothubs to keep track of bus suspend info for */
index e2b21c1d9c403088d704d12901c8049e329c360f..ba5f70f92888774c5ef900d44c6f8ad941e6b4e9 100644 (file)
@@ -246,6 +246,6 @@ config USB_EZUSB_FX2
 config USB_HSIC_USB3503
        tristate "USB3503 HSIC to USB20 Driver"
        depends on I2C
-       select REGMAP
+       select REGMAP_I2C
        help
          This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver.
index 18e877ffe7b7d8c7393bdf43efdfd0d58e618011..cd70cc8861711015f5443e2b76e969209d9bdb3a 100644 (file)
@@ -921,6 +921,52 @@ static void musb_generic_disable(struct musb *musb)
 
 }
 
+/*
+ * Program the HDRC to start (enable interrupts, dma, etc.).
+ */
+void musb_start(struct musb *musb)
+{
+       void __iomem    *regs = musb->mregs;
+       u8              devctl = musb_readb(regs, MUSB_DEVCTL);
+
+       dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
+
+       /*  Set INT enable registers, enable interrupts */
+       musb->intrtxe = musb->epmask;
+       musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
+       musb->intrrxe = musb->epmask & 0xfffe;
+       musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
+       musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
+
+       musb_writeb(regs, MUSB_TESTMODE, 0);
+
+       /* put into basic highspeed mode and start session */
+       musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
+                       | MUSB_POWER_HSENAB
+                       /* ENSUSPEND wedges tusb */
+                       /* | MUSB_POWER_ENSUSPEND */
+                  );
+
+       musb->is_active = 0;
+       devctl = musb_readb(regs, MUSB_DEVCTL);
+       devctl &= ~MUSB_DEVCTL_SESSION;
+
+       /* session started after:
+        * (a) ID-grounded irq, host mode;
+        * (b) vbus present/connect IRQ, peripheral mode;
+        * (c) peripheral initiates, using SRP
+        */
+       if (musb->port_mode != MUSB_PORT_MODE_HOST &&
+                       (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
+               musb->is_active = 1;
+       } else {
+               devctl |= MUSB_DEVCTL_SESSION;
+       }
+
+       musb_platform_enable(musb);
+       musb_writeb(regs, MUSB_DEVCTL, devctl);
+}
+
 /*
  * Make the HDRC stop (disable interrupts, etc.);
  * reversible by musb_start
index 65f3917b4fc5fb55c95bf4157d70a1d7194a110d..1c5bf75ee8ff8a45a3da1fca7cb1d31920f0eeff 100644 (file)
@@ -503,6 +503,7 @@ static inline void musb_configure_ep0(struct musb *musb)
 extern const char musb_driver_name[];
 
 extern void musb_stop(struct musb *musb);
+extern void musb_start(struct musb *musb);
 
 extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
 extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
index b19ed213ab8580c5456cbddaca4f217db31733c4..3671898a4535b3cf2de3c0e188f4947485d2760d 100644 (file)
@@ -1853,11 +1853,14 @@ static int musb_gadget_start(struct usb_gadget *g,
        musb->gadget_driver = driver;
 
        spin_lock_irqsave(&musb->lock, flags);
+       musb->is_active = 1;
 
        otg_set_peripheral(otg, &musb->g);
        musb->xceiv->state = OTG_STATE_B_IDLE;
        spin_unlock_irqrestore(&musb->lock, flags);
 
+       musb_start(musb);
+
        /* REVISIT:  funcall to other code, which also
         * handles power budgeting ... this way also
         * ensures HdrcStart is indirectly called.
index a523950c2b32e66e07f7c8bd78daa181f691f25c..d1d6b83aabca61df43dffccf57ccbe7687cbe399 100644 (file)
 
 #include "musb_core.h"
 
-/*
-* Program the HDRC to start (enable interrupts, dma, etc.).
-*/
-static void musb_start(struct musb *musb)
-{
-       void __iomem    *regs = musb->mregs;
-       u8              devctl = musb_readb(regs, MUSB_DEVCTL);
-
-       dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
-
-       /*  Set INT enable registers, enable interrupts */
-       musb->intrtxe = musb->epmask;
-       musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
-       musb->intrrxe = musb->epmask & 0xfffe;
-       musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
-       musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
-
-       musb_writeb(regs, MUSB_TESTMODE, 0);
-
-       /* put into basic highspeed mode and start session */
-       musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
-                                               | MUSB_POWER_HSENAB
-                                               /* ENSUSPEND wedges tusb */
-                                               /* | MUSB_POWER_ENSUSPEND */
-                                               );
-
-       musb->is_active = 0;
-       devctl = musb_readb(regs, MUSB_DEVCTL);
-       devctl &= ~MUSB_DEVCTL_SESSION;
-
-       /* session started after:
-        * (a) ID-grounded irq, host mode;
-        * (b) vbus present/connect IRQ, peripheral mode;
-        * (c) peripheral initiates, using SRP
-        */
-       if (musb->port_mode != MUSB_PORT_MODE_HOST &&
-           (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
-               musb->is_active = 1;
-       } else {
-               devctl |= MUSB_DEVCTL_SESSION;
-       }
-
-       musb_platform_enable(musb);
-       musb_writeb(regs, MUSB_DEVCTL, devctl);
-}
-
 static void musb_port_suspend(struct musb *musb, bool do_suspend)
 {
        struct usb_otg  *otg = musb->xceiv->otg;
index 80a7104d5ddb3e6d81fa125bb13d9a4d0af05dcf..acaee066b99aa10e5ecf2a8e75cffd31899b6507 100644 (file)
@@ -451,6 +451,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,
@@ -689,6 +693,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) },
@@ -1257,7 +1477,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) },
@@ -1345,6 +1567,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);
index 760b78560f67fd7e7d905d53dff2cb7a46f2919f..c9a35697ebe9a6e131d5a9c145e5f3f3415dd5bf 100644 (file)
@@ -190,6 +190,7 @@ static struct usb_device_id ti_id_table_combined[] = {
        { 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) },
        { }     /* terminator */
 };
index 94d75edef77fdf34e4f5e341e5952e532f03f09e..18509e6c21ab84e7d3133f7a0e428ba462d2a24b 100644 (file)
@@ -211,8 +211,11 @@ static int slave_configure(struct scsi_device *sdev)
                /*
                 * Many devices do not respond properly to READ_CAPACITY_16.
                 * Tell the SCSI layer to try READ_CAPACITY_10 first.
+                * However some USB 3.0 drive enclosures return capacity
+                * modulo 2TB. Those must use READ_CAPACITY_16
                 */
-               sdev->try_rc_10_first = 1;
+               if (!(us->fflags & US_FL_NEEDS_CAP16))
+                       sdev->try_rc_10_first = 1;
 
                /* assume SPC3 or latter devices support sense size > 18 */
                if (sdev->scsi_level > SCSI_SPC_2)
index c015f2c16729c5b4030fc829fae9a3cfb90acde6..de32cfa5bfa6ca0772d0955ea83b9b98dd698ea5 100644 (file)
@@ -1925,6 +1925,13 @@ UNUSUAL_DEV(  0x1652, 0x6600, 0x0201, 0x0201,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Oliver Neukum <oneukum@suse.com> */
+UNUSUAL_DEV(  0x174c, 0x55aa, 0x0100, 0x0100,
+               "ASMedia",
+               "AS2105",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NEEDS_CAP16),
+
 /* Reported by Jesse Feddema <jdfeddema@gmail.com> */
 UNUSUAL_DEV(  0x177f, 0x0400, 0x0000, 0x0000,
                "Yarvik",
index a9807dea3887af0afe44e545784f70d46efa40dd..4fb7a8f83c8a99ff8d3412a5328b2407c98409a8 100644 (file)
@@ -545,6 +545,8 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
        long npage;
        int ret = 0, prot = 0;
        uint64_t mask;
+       struct vfio_dma *dma = NULL;
+       unsigned long pfn;
 
        end = map->iova + map->size;
 
@@ -587,8 +589,6 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
        }
 
        for (iova = map->iova; iova < end; iova += size, vaddr += size) {
-               struct vfio_dma *dma = NULL;
-               unsigned long pfn;
                long i;
 
                /* Pin a contiguous chunk of memory */
@@ -597,16 +597,15 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
                if (npage <= 0) {
                        WARN_ON(!npage);
                        ret = (int)npage;
-                       break;
+                       goto out;
                }
 
                /* Verify pages are not already mapped */
                for (i = 0; i < npage; i++) {
                        if (iommu_iova_to_phys(iommu->domain,
                                               iova + (i << PAGE_SHIFT))) {
-                               vfio_unpin_pages(pfn, npage, prot, true);
                                ret = -EBUSY;
-                               break;
+                               goto out_unpin;
                        }
                }
 
@@ -616,8 +615,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
                if (ret) {
                        if (ret != -EBUSY ||
                            map_try_harder(iommu, iova, pfn, npage, prot)) {
-                               vfio_unpin_pages(pfn, npage, prot, true);
-                               break;
+                               goto out_unpin;
                        }
                }
 
@@ -672,9 +670,8 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
                        dma = kzalloc(sizeof(*dma), GFP_KERNEL);
                        if (!dma) {
                                iommu_unmap(iommu->domain, iova, size);
-                               vfio_unpin_pages(pfn, npage, prot, true);
                                ret = -ENOMEM;
-                               break;
+                               goto out_unpin;
                        }
 
                        dma->size = size;
@@ -685,16 +682,21 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
                }
        }
 
-       if (ret) {
-               struct vfio_dma *tmp;
-               iova = map->iova;
-               size = map->size;
-               while ((tmp = vfio_find_dma(iommu, iova, size))) {
-                       int r = vfio_remove_dma_overlap(iommu, iova,
-                                                       &size, tmp);
-                       if (WARN_ON(r || !size))
-                               break;
-               }
+       WARN_ON(ret);
+       mutex_unlock(&iommu->lock);
+       return ret;
+
+out_unpin:
+       vfio_unpin_pages(pfn, npage, prot, true);
+
+out:
+       iova = map->iova;
+       size = map->size;
+       while ((dma = vfio_find_dma(iommu, iova, size))) {
+               int r = vfio_remove_dma_overlap(iommu, iova,
+                                               &size, dma);
+               if (WARN_ON(r || !size))
+                       break;
        }
 
        mutex_unlock(&iommu->lock);
index ce5221fa393a8db2ca9f4de61817ae230f3f0bc8..e663921eebb6f899db67e352077689b6e84d270f 100644 (file)
@@ -1056,7 +1056,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
                if (data_direction != DMA_NONE) {
                        ret = vhost_scsi_map_iov_to_sgl(cmd,
                                        &vq->iov[data_first], data_num,
-                                       data_direction == DMA_TO_DEVICE);
+                                       data_direction == DMA_FROM_DEVICE);
                        if (unlikely(ret)) {
                                vq_err(vq, "Failed to map iov to sgl\n");
                                goto err_free;
index 94a403a9717ae9f84c941e334098bbc0c0713bbb..5d05555fe841d2a4eaac7d230e498e0c51f5d841 100644 (file)
@@ -21,6 +21,9 @@
 #include <asm/backlight.h>
 #endif
 
+static struct list_head backlight_dev_list;
+static struct mutex backlight_dev_list_mutex;
+
 static const char *const backlight_types[] = {
        [BACKLIGHT_RAW] = "raw",
        [BACKLIGHT_PLATFORM] = "platform",
@@ -349,10 +352,32 @@ struct backlight_device *backlight_device_register(const char *name,
        mutex_unlock(&pmac_backlight_mutex);
 #endif
 
+       mutex_lock(&backlight_dev_list_mutex);
+       list_add(&new_bd->entry, &backlight_dev_list);
+       mutex_unlock(&backlight_dev_list_mutex);
+
        return new_bd;
 }
 EXPORT_SYMBOL(backlight_device_register);
 
+bool backlight_device_registered(enum backlight_type type)
+{
+       bool found = false;
+       struct backlight_device *bd;
+
+       mutex_lock(&backlight_dev_list_mutex);
+       list_for_each_entry(bd, &backlight_dev_list, entry) {
+               if (bd->props.type == type) {
+                       found = true;
+                       break;
+               }
+       }
+       mutex_unlock(&backlight_dev_list_mutex);
+
+       return found;
+}
+EXPORT_SYMBOL(backlight_device_registered);
+
 /**
  * backlight_device_unregister - unregisters a backlight device object.
  * @bd: the backlight device object to be unregistered and freed.
@@ -364,6 +389,10 @@ void backlight_device_unregister(struct backlight_device *bd)
        if (!bd)
                return;
 
+       mutex_lock(&backlight_dev_list_mutex);
+       list_del(&bd->entry);
+       mutex_unlock(&backlight_dev_list_mutex);
+
 #ifdef CONFIG_PMAC_BACKLIGHT
        mutex_lock(&pmac_backlight_mutex);
        if (pmac_backlight == bd)
@@ -499,6 +528,8 @@ static int __init backlight_class_init(void)
 
        backlight_class->dev_groups = bl_device_groups;
        backlight_class->pm = &backlight_class_dev_pm_ops;
+       INIT_LIST_HEAD(&backlight_dev_list);
+       mutex_init(&backlight_dev_list_mutex);
        return 0;
 }
 
index c7c64f18773d87d5f23e81ec90ba7d8bfaee504a..fa932c2f7d97276b66199eda06b6edb6565208bb 100644 (file)
@@ -613,6 +613,9 @@ static int w1_bus_notify(struct notifier_block *nb, unsigned long action,
        sl = dev_to_w1_slave(dev);
        fops = sl->family->fops;
 
+       if (!fops)
+               return 0;
+
        switch (action) {
        case BUS_NOTIFY_ADD_DEVICE:
                /* if the family driver needs to initialize something... */
@@ -713,7 +716,10 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
        atomic_set(&sl->refcnt, 0);
        init_completion(&sl->released);
 
+       /* slave modules need to be loaded in a context with unlocked mutex */
+       mutex_unlock(&dev->mutex);
        request_module("w1-family-0x%0x", rn->family);
+       mutex_lock(&dev->mutex);
 
        spin_lock(&w1_flock);
        f = w1_family_registered(rn->family);
index b0ef7b07b1b3be510e85dd1bab6711e7d27cebee..51e3afa7835479e00fa346241cfccd10b6e60a80 100644 (file)
@@ -6437,6 +6437,7 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
 
        if (btrfs_extent_readonly(root, disk_bytenr))
                goto out;
+       btrfs_release_path(path);
 
        /*
         * look for other files referencing this extent, if we
index 4d7433534f5cd77b7f9b240fba57ac7923df07e6..6024877335caf2a9dfa6af1018c5da19b0e8a2ae 100644 (file)
@@ -1005,9 +1005,19 @@ grow_dev_page(struct block_device *bdev, sector_t block,
        struct buffer_head *bh;
        sector_t end_block;
        int ret = 0;            /* Will call free_more_memory() */
+       gfp_t gfp_mask;
 
-       page = find_or_create_page(inode->i_mapping, index,
-               (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
+       gfp_mask = mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS;
+       gfp_mask |= __GFP_MOVABLE;
+       /*
+        * XXX: __getblk_slow() can not really deal with failure and
+        * will endlessly loop on improvised global reclaim.  Prefer
+        * looping in the allocator rather than here, at least that
+        * code knows what it's doing.
+        */
+       gfp_mask |= __GFP_NOFAIL;
+
+       page = find_or_create_page(inode->i_mapping, index, gfp_mask);
        if (!page)
                return ret;
 
index a16b4e58bcc62ee88f9772f75120ef250d0112bd..77fc5e181077b1f897cf27d40c140133b6cf6d0f 100644 (file)
@@ -120,14 +120,16 @@ cifs_read_super(struct super_block *sb)
 {
        struct inode *inode;
        struct cifs_sb_info *cifs_sb;
+       struct cifs_tcon *tcon;
        int rc = 0;
 
        cifs_sb = CIFS_SB(sb);
+       tcon = cifs_sb_master_tcon(cifs_sb);
 
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
                sb->s_flags |= MS_POSIXACL;
 
-       if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES)
+       if (tcon->ses->capabilities & tcon->ses->server->vals->cap_large_files)
                sb->s_maxbytes = MAX_LFS_FILESIZE;
        else
                sb->s_maxbytes = MAX_NON_LFS;
@@ -147,7 +149,7 @@ cifs_read_super(struct super_block *sb)
                goto out_no_root;
        }
 
-       if (cifs_sb_master_tcon(cifs_sb)->nocase)
+       if (tcon->nocase)
                sb->s_d_op = &cifs_ci_dentry_ops;
        else
                sb->s_d_op = &cifs_dentry_ops;
index a630475e421c421ef38f6633ddb31c8351827752..08f9dfb1a894402eec24579717f6c48d4d92f695 100644 (file)
@@ -1491,15 +1491,30 @@ struct file_notify_information {
        __u8  FileName[0];
 } __attribute__((packed));
 
-struct reparse_data {
-       __u32   ReparseTag;
-       __u16   ReparseDataLength;
+/* For IO_REPARSE_TAG_SYMLINK */
+struct reparse_symlink_data {
+       __le32  ReparseTag;
+       __le16  ReparseDataLength;
        __u16   Reserved;
-       __u16   SubstituteNameOffset;
-       __u16   SubstituteNameLength;
-       __u16   PrintNameOffset;
-       __u16   PrintNameLength;
-       __u32   Flags;
+       __le16  SubstituteNameOffset;
+       __le16  SubstituteNameLength;
+       __le16  PrintNameOffset;
+       __le16  PrintNameLength;
+       __le32  Flags;
+       char    PathBuffer[0];
+} __attribute__((packed));
+
+/* For IO_REPARSE_TAG_NFS */
+#define NFS_SPECFILE_LNK       0x00000000014B4E4C
+#define NFS_SPECFILE_CHR       0x0000000000524843
+#define NFS_SPECFILE_BLK       0x00000000004B4C42
+#define NFS_SPECFILE_FIFO      0x000000004F464946
+#define NFS_SPECFILE_SOCK      0x000000004B434F53
+struct reparse_posix_data {
+       __le32  ReparseTag;
+       __le16  ReparseDataLength;
+       __u16   Reserved;
+       __le64  InodeType; /* LNK, FIFO, CHR etc. */
        char    PathBuffer[0];
 } __attribute__((packed));
 
index 4baf35949b51a16a395a698f40b66dd312a14246..ccd31ab815d4b2404d58a0e42f3ad606d35b87f5 100644 (file)
@@ -3088,7 +3088,8 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
        bool is_unicode;
        unsigned int sub_len;
        char *sub_start;
-       struct reparse_data *reparse_buf;
+       struct reparse_symlink_data *reparse_buf;
+       struct reparse_posix_data *posix_buf;
        __u32 data_offset, data_count;
        char *end_of_smb;
 
@@ -3137,20 +3138,47 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
                goto qreparse_out;
        }
        end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
-       reparse_buf = (struct reparse_data *)
+       reparse_buf = (struct reparse_symlink_data *)
                                ((char *)&pSMBr->hdr.Protocol + data_offset);
        if ((char *)reparse_buf >= end_of_smb) {
                rc = -EIO;
                goto qreparse_out;
        }
-       if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset +
-                               reparse_buf->PrintNameLength) > end_of_smb) {
+       if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
+               cifs_dbg(FYI, "NFS style reparse tag\n");
+               posix_buf =  (struct reparse_posix_data *)reparse_buf;
+
+               if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
+                       cifs_dbg(FYI, "unsupported file type 0x%llx\n",
+                                le64_to_cpu(posix_buf->InodeType));
+                       rc = -EOPNOTSUPP;
+                       goto qreparse_out;
+               }
+               is_unicode = true;
+               sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
+               if (posix_buf->PathBuffer + sub_len > end_of_smb) {
+                       cifs_dbg(FYI, "reparse buf beyond SMB\n");
+                       rc = -EIO;
+                       goto qreparse_out;
+               }
+               *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
+                               sub_len, is_unicode, nls_codepage);
+               goto qreparse_out;
+       } else if (reparse_buf->ReparseTag !=
+                       cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
+               rc = -EOPNOTSUPP;
+               goto qreparse_out;
+       }
+
+       /* Reparse tag is NTFS symlink */
+       sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
+                               reparse_buf->PathBuffer;
+       sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
+       if (sub_start + sub_len > end_of_smb) {
                cifs_dbg(FYI, "reparse buf beyond SMB\n");
                rc = -EIO;
                goto qreparse_out;
        }
-       sub_start = reparse_buf->SubstituteNameOffset + reparse_buf->PathBuffer;
-       sub_len = reparse_buf->SubstituteNameLength;
        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
                is_unicode = true;
        else
index af847e1cf1c1985f5ddadd07e10dbc0e38a162a2..651a5279607b968a255a528e5411e4f4b39ca438 100644 (file)
@@ -780,7 +780,9 @@ static const struct {
        ERRDOS, ERRnoaccess, 0xc0000290}, {
        ERRDOS, ERRbadfunc, 0xc000029c}, {
        ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
-       ERRDOS, ERRinvlevel, 0x007c0001}, };
+       ERRDOS, ERRinvlevel, 0x007c0001}, {
+       0, 0, 0 }
+};
 
 /*****************************************************************************
  Print an error message from the status code
index 352358de1d7e37a8126d61d76898112393f64d08..e87387dbf39fa1d24b19f245e86da4c907b0fdaf 100644 (file)
@@ -500,9 +500,9 @@ select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
                                return NTLMv2;
                        if (global_secflags & CIFSSEC_MAY_NTLM)
                                return NTLM;
-                       /* Fallthrough */
                default:
-                       return Unspecified;
+                       /* Fallthrough to attempt LANMAN authentication next */
+                       break;
                }
        case CIFS_NEGFLAVOR_LANMAN:
                switch (requested) {
index eba0efde66d70ae15974eef74b10ff6d83ca44d8..edccb5252462b6b465d3d71cb7d3de20e8d2be9a 100644 (file)
@@ -687,6 +687,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
        else
                return -EIO;
 
+       /* no need to send SMB logoff if uid already closed due to reconnect */
+       if (ses->need_reconnect)
+               goto smb2_session_already_dead;
+
        rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req);
        if (rc)
                return rc;
@@ -701,6 +705,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
         * No tcon so can't do
         * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
         */
+
+smb2_session_already_dead:
        return rc;
 }
 
index d952ee48f4dcc629a5d1e91c3470cbd2bd6d1aec..a4b2391fe66e4e11cea93e7396b987c335d43823 100644 (file)
 #define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */
 #define FSCTL_SRV_READ_HASH          0x001441BB /* BB add struct */
 
+/* See FSCC 2.1.2.5 */
 #define IO_REPARSE_TAG_MOUNT_POINT   0xA0000003
 #define IO_REPARSE_TAG_HSM           0xC0000004
 #define IO_REPARSE_TAG_SIS           0x80000007
+#define IO_REPARSE_TAG_HSM2          0x80000006
+#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
+/* Used by the DFS filter. See MS-DFSC */
+#define IO_REPARSE_TAG_DFS           0x8000000A
+/* Used by the DFS filter See MS-DFSC */
+#define IO_REPARSE_TAG_DFSR          0x80000012
+#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
+/* See section MS-FSCC 2.1.2.4 */
+#define IO_REPARSE_TAG_SYMLINK       0xA000000C
+#define IO_REPARSE_TAG_DEDUP         0x80000013
+#define IO_REPARSE_APPXSTREAM       0xC0000014
+/* NFS symlinks, Win 8/SMB3 and later */
+#define IO_REPARSE_TAG_NFS           0x80000014
 
 /* fsctl flags */
 /* If Flags is set to this value, the request is an FSCTL not ioctl request */
index 6fdcb1b4a106747779ae77ed365116256e79edec..800b938e4061768f5f55ee414b45afa56e6d6aa2 100644 (file)
@@ -410,8 +410,13 @@ static int
 wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
                      const int optype)
 {
-       return wait_for_free_credits(server, timeout,
-                               server->ops->get_credits_field(server, optype));
+       int *val;
+
+       val = server->ops->get_credits_field(server, optype);
+       /* Since an echo is already inflight, no need to wait to send another */
+       if (*val <= 0 && optype == CIFS_ECHO_OP)
+               return -EAGAIN;
+       return wait_for_free_credits(server, timeout, val);
 }
 
 static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
index 41000305d716ea51c47ed52ddb5abe024045e958..20532cb0b06e7ebfc6887e87fd3781e65eb41999 100644 (file)
@@ -1331,14 +1331,6 @@ rename_retry:
  * list is non-empty and continue searching.
  */
 
-/**
- * have_submounts - check for mounts over a dentry
- * @parent: dentry to check.
- *
- * Return true if the parent or its subdirectories contain
- * a mount point
- */
-
 static enum d_walk_ret check_mount(void *data, struct dentry *dentry)
 {
        int *ret = data;
@@ -1349,6 +1341,13 @@ static enum d_walk_ret check_mount(void *data, struct dentry *dentry)
        return D_WALK_CONTINUE;
 }
 
+/**
+ * have_submounts - check for mounts over a dentry
+ * @parent: dentry to check.
+ *
+ * Return true if the parent or its subdirectories contain
+ * a mount point
+ */
 int have_submounts(struct dentry *parent)
 {
        int ret = 0;
index c88e355f7635f61e59f58cb4acc617b84928e4e5..000eae2782b6e905aefa05980ef91c54b81a8274 100644 (file)
@@ -408,7 +408,7 @@ static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat,
                                    struct page *page)
 {
        return ecryptfs_lower_header_size(crypt_stat) +
-              (page->index << PAGE_CACHE_SHIFT);
+              ((loff_t)page->index << PAGE_CACHE_SHIFT);
 }
 
 /**
index 7d52806c21197206a5932b08a68e7dc9d6899253..4725a07f003cf3279fa81813748442afc24a053c 100644 (file)
@@ -1149,7 +1149,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
        struct ecryptfs_msg_ctx *msg_ctx;
        struct ecryptfs_message *msg = NULL;
        char *auth_tok_sig;
-       char *payload;
+       char *payload = NULL;
        size_t payload_len = 0;
        int rc;
 
@@ -1203,6 +1203,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
        }
 out:
        kfree(msg);
+       kfree(payload);
        return rc;
 }
 
index 1194b1f0f8396c934ab6a382deadab6c0a6c4c2f..f8cde46de9cd77c3047182e94164bdfdac4a317d 100644 (file)
@@ -1783,7 +1783,7 @@ retry:
                d_tmpfile(dentry, inode);
                err = ext3_orphan_add(handle, inode);
                if (err)
-                       goto err_drop_inode;
+                       goto err_unlock_inode;
                mark_inode_dirty(inode);
                unlock_new_inode(inode);
        }
@@ -1791,10 +1791,9 @@ retry:
        if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
                goto retry;
        return err;
-err_drop_inode:
+err_unlock_inode:
        ext3_journal_stop(handle);
        unlock_new_inode(inode);
-       iput(inode);
        return err;
 }
 
index 1bec5a5c1e45a29e9ead318987ec03d803104c5a..5a0408d7b1147094c3e82b6d11750b33396b7732 100644 (file)
@@ -2319,7 +2319,7 @@ retry:
                d_tmpfile(dentry, inode);
                err = ext4_orphan_add(handle, inode);
                if (err)
-                       goto err_drop_inode;
+                       goto err_unlock_inode;
                mark_inode_dirty(inode);
                unlock_new_inode(inode);
        }
@@ -2328,10 +2328,9 @@ retry:
        if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
                goto retry;
        return err;
-err_drop_inode:
+err_unlock_inode:
        ext4_journal_stop(handle);
        unlock_new_inode(inode);
-       iput(inode);
        return err;
 }
 
index abdd15ad13c9c52bf672465787e3811c06ef7224..e900ca518635bcecb1cfdbe9d54cab640ec49333 100644 (file)
@@ -297,7 +297,7 @@ void flush_delayed_fput(void)
        delayed_fput(NULL);
 }
 
-static DECLARE_WORK(delayed_fput_work, delayed_fput);
+static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);
 
 void fput(struct file *file)
 {
@@ -317,7 +317,7 @@ void fput(struct file *file)
                }
 
                if (llist_add(&file->f_u.fu_llist, &delayed_fput_list))
-                       schedule_work(&delayed_fput_work);
+                       schedule_delayed_work(&delayed_fput_work, 1);
        }
 }
 
index c1a3e603279c9cbe4fb141fc2b9bdcfa1d76a033..7f464c513ba0a85a2fd4fe7923a9799bb319e92b 100644 (file)
@@ -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:
index 645268f23eb64cb8c2931ce33391beb2d0080c36..caa28051e197e898e3c2bc52afce37bcbb284853 100644 (file)
@@ -2294,10 +2294,11 @@ out:
  * path_mountpoint - look up a path to be umounted
  * @dfd:       directory file descriptor to start walk from
  * @name:      full pathname to walk
+ * @path:      pointer to container for result
  * @flags:     lookup flags
  *
  * Look up the given name, but don't attempt to revalidate the last component.
- * Returns 0 and "path" will be valid on success; Retuns error otherwise.
+ * Returns 0 and "path" will be valid on success; Returns error otherwise.
  */
 static int
 path_mountpoint(int dfd, const char *name, struct path *path, unsigned int flags)
index 9f8ef9b7674db1ca1004b682b40a6e5500dcfc24..8eaa1ba793fc188879d405e768a81aedbaa4bf76 100644 (file)
@@ -288,10 +288,14 @@ static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
 static unsigned long proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags)
 {
        struct proc_dir_entry *pde = PDE(file_inode(file));
-       int rv = -EIO;
-       unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+       unsigned long rv = -EIO;
+       unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long) = NULL;
        if (use_pde(pde)) {
-               get_unmapped_area = pde->proc_fops->get_unmapped_area;
+#ifdef CONFIG_MMU
+               get_unmapped_area = current->mm->get_unmapped_area;
+#endif
+               if (pde->proc_fops->get_unmapped_area)
+                       get_unmapped_area = pde->proc_fops->get_unmapped_area;
                if (get_unmapped_area)
                        rv = get_unmapped_area(file, orig_addr, len, pgoff, flags);
                unuse_pde(pde);
index 7366e9d63cee7d8658e9fed949a2fe7b22519c6f..390bdab01c3c782cc14b55c6d1ef35ebddcc4197 100644 (file)
@@ -941,6 +941,8 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
                frame = pte_pfn(pte);
                flags = PM_PRESENT;
                page = vm_normal_page(vma, addr, pte);
+               if (pte_soft_dirty(pte))
+                       flags2 |= __PM_SOFT_DIRTY;
        } else if (is_swap_pte(pte)) {
                swp_entry_t entry;
                if (pte_swp_soft_dirty(pte))
@@ -960,7 +962,7 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
 
        if (page && !PageAnon(page))
                flags |= PM_FILE;
-       if ((vma->vm_flags & VM_SOFTDIRTY) || pte_soft_dirty(pte))
+       if ((vma->vm_flags & VM_SOFTDIRTY))
                flags2 |= __PM_SOFT_DIRTY;
 
        *pme = make_pme(PM_PFRAME(frame) | PM_STATUS2(pm->v2, flags2) | flags);
index 3135c2525c76635606ae9722f6badb5a11e44543..a290157265ef5cfb52dbdb6a9e950e9733462d16 100644 (file)
@@ -328,6 +328,8 @@ loff_t seq_lseek(struct file *file, loff_t offset, int whence)
                                m->read_pos = offset;
                                retval = file->f_pos = offset;
                        }
+               } else {
+                       file->f_pos = offset;
                }
        }
        file->f_version = m->version;
index 1c16f821434f9c2ffee4ea793605800fa99a56b4..d98c67001840b705db746e4a1bc89ccba209652b 100644 (file)
  *      ACPI PM timer
  *      FACS table (Waking vectors and Global Lock)
  */
+#ifndef ACPI_REDUCED_HARDWARE
 #define ACPI_REDUCED_HARDWARE           FALSE
+#endif
 
 /******************************************************************************
  *
index cf051e05a8fe682894251ec5944299a8ead8277f..4e280bd226ddaa107a3d19f08b07389279b53922 100644 (file)
@@ -125,8 +125,9 @@ struct acpi_exception_info {
 #define AE_NO_HANDLER                   EXCEP_ENV (0x001A)
 #define AE_OWNER_ID_LIMIT               EXCEP_ENV (0x001B)
 #define AE_NOT_CONFIGURED               EXCEP_ENV (0x001C)
+#define AE_ACCESS                       EXCEP_ENV (0x001D)
 
-#define AE_CODE_ENV_MAX                 0x001C
+#define AE_CODE_ENV_MAX                 0x001D
 
 /*
  * Programmer exceptions
@@ -227,7 +228,7 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = {
        EXCEP_TXT("AE_NO_ACPI_TABLES", "ACPI tables could not be found"),
        EXCEP_TXT("AE_NO_NAMESPACE", "A namespace has not been loaded"),
        EXCEP_TXT("AE_NO_MEMORY", "Insufficient dynamic memory"),
-       EXCEP_TXT("AE_NOT_FOUND", "The name was not found in the namespace"),
+       EXCEP_TXT("AE_NOT_FOUND", "A requested entity is not found"),
        EXCEP_TXT("AE_NOT_EXIST", "A required entity does not exist"),
        EXCEP_TXT("AE_ALREADY_EXISTS", "An entity already exists"),
        EXCEP_TXT("AE_TYPE", "The object type is incorrect"),
@@ -259,7 +260,8 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = {
        EXCEP_TXT("AE_OWNER_ID_LIMIT",
                  "There are no more Owner IDs available for ACPI tables or control methods"),
        EXCEP_TXT("AE_NOT_CONFIGURED",
-                 "The interface is not part of the current subsystem configuration")
+                 "The interface is not part of the current subsystem configuration"),
+       EXCEP_TXT("AE_ACCESS", "Permission denied for the requested operation")
 };
 
 static const struct acpi_exception_info acpi_gbl_exception_names_pgm[] = {
index ce08ef7d969cffb7516bd65fed39eda6bc29f39b..1f36777e26febf8fcbbd38650950d6a91ba9b1bd 100644 (file)
 
 /* Method names - these methods can appear anywhere in the namespace */
 
-#define METHOD_NAME__SB_        "_SB_"
-#define METHOD_NAME__HID        "_HID"
-#define METHOD_NAME__CID        "_CID"
-#define METHOD_NAME__UID        "_UID"
-#define METHOD_NAME__SUB        "_SUB"
 #define METHOD_NAME__ADR        "_ADR"
-#define METHOD_NAME__INI        "_INI"
-#define METHOD_NAME__STA        "_STA"
-#define METHOD_NAME__REG        "_REG"
-#define METHOD_NAME__SEG        "_SEG"
+#define METHOD_NAME__AEI        "_AEI"
 #define METHOD_NAME__BBN        "_BBN"
-#define METHOD_NAME__PRT        "_PRT"
+#define METHOD_NAME__CBA        "_CBA"
+#define METHOD_NAME__CID        "_CID"
 #define METHOD_NAME__CRS        "_CRS"
+#define METHOD_NAME__HID        "_HID"
+#define METHOD_NAME__INI        "_INI"
+#define METHOD_NAME__PLD        "_PLD"
 #define METHOD_NAME__PRS        "_PRS"
-#define METHOD_NAME__AEI        "_AEI"
+#define METHOD_NAME__PRT        "_PRT"
 #define METHOD_NAME__PRW        "_PRW"
+#define METHOD_NAME__REG        "_REG"
+#define METHOD_NAME__SB_        "_SB_"
+#define METHOD_NAME__SEG        "_SEG"
 #define METHOD_NAME__SRS        "_SRS"
-#define METHOD_NAME__CBA        "_CBA"
-#define METHOD_NAME__PLD        "_PLD"
+#define METHOD_NAME__STA        "_STA"
+#define METHOD_NAME__SUB        "_SUB"
+#define METHOD_NAME__UID        "_UID"
 
 /* Method names - these methods must appear at the namespace root */
 
index 02e113bb8b7d5c777fdc435a5285208238ce66e9..15100f625e6550a94bc2afe721ccf3804a2360d5 100644 (file)
@@ -222,7 +222,8 @@ struct acpi_device_power_flags {
        u32 power_resources:1;  /* Power resources */
        u32 inrush_current:1;   /* Serialize Dx->D0 */
        u32 power_removed:1;    /* Optimize Dx->D0 */
-       u32 reserved:28;
+       u32 ignore_parent:1;    /* Power is independent of parent power state */
+       u32 reserved:27;
 };
 
 struct acpi_device_power_state {
@@ -311,7 +312,6 @@ struct acpi_device {
        unsigned int physical_node_count;
        struct list_head physical_node_list;
        struct mutex physical_node_lock;
-       struct list_head power_dependent;
        void (*remove)(struct acpi_device *);
 };
 
@@ -456,8 +456,6 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
 acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
                                    acpi_notify_handler handler);
 int acpi_pm_device_sleep_state(struct device *, int *, int);
-void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev);
-void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev);
 #else
 static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
                                               acpi_notify_handler handler,
@@ -478,10 +476,6 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
        return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ?
                m : ACPI_STATE_D0;
 }
-static inline void acpi_dev_pm_add_dependent(acpi_handle handle,
-                                            struct device *depdev) {}
-static inline void acpi_dev_pm_remove_dependent(acpi_handle handle,
-                                               struct device *depdev) {}
 #endif
 
 #ifdef CONFIG_PM_RUNTIME
index 64b8c7639520d1e41e1439bc558d7a35424e25ef..01e6c6d8b7e142d58b6e45bc921bace23e2b00f1 100644 (file)
@@ -77,54 +77,80 @@ struct acpi_signal_fatal_info {
 /*
  * OSL Initialization and shutdown primitives
  */
-acpi_status __init acpi_os_initialize(void);
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize
+acpi_status acpi_os_initialize(void);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate
 acpi_status acpi_os_terminate(void);
+#endif
 
 /*
  * ACPI Table interfaces
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_root_pointer
 acpi_physical_address acpi_os_get_root_pointer(void);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_predefined_override
 acpi_status
 acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
                            acpi_string * new_val);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_table_override
 acpi_status
 acpi_os_table_override(struct acpi_table_header *existing_table,
                       struct acpi_table_header **new_table);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_physical_table_override
 acpi_status
 acpi_os_physical_table_override(struct acpi_table_header *existing_table,
                                acpi_physical_address * new_address,
                                u32 *new_table_length);
+#endif
 
 /*
  * Spinlock primitives
  */
-#ifndef acpi_os_create_lock
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock
 acpi_status acpi_os_create_lock(acpi_spinlock * out_handle);
 #endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_lock
 void acpi_os_delete_lock(acpi_spinlock handle);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_lock
 acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock handle);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_lock
 void acpi_os_release_lock(acpi_spinlock handle, acpi_cpu_flags flags);
+#endif
 
 /*
  * Semaphore primitives
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_semaphore
 acpi_status
 acpi_os_create_semaphore(u32 max_units,
                         u32 initial_units, acpi_semaphore * out_handle);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_semaphore
 acpi_status acpi_os_delete_semaphore(acpi_semaphore handle);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_wait_semaphore
 acpi_status
 acpi_os_wait_semaphore(acpi_semaphore handle, u32 units, u16 timeout);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_signal_semaphore
 acpi_status acpi_os_signal_semaphore(acpi_semaphore handle, u32 units);
+#endif
 
 /*
  * Mutex primitives. May be configured to use semaphores instead via
@@ -132,29 +158,48 @@ acpi_status acpi_os_signal_semaphore(acpi_semaphore handle, u32 units);
  */
 #if (ACPI_MUTEX_TYPE != ACPI_BINARY_SEMAPHORE)
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_mutex
 acpi_status acpi_os_create_mutex(acpi_mutex * out_handle);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_mutex
 void acpi_os_delete_mutex(acpi_mutex handle);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_mutex
 acpi_status acpi_os_acquire_mutex(acpi_mutex handle, u16 timeout);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_mutex
 void acpi_os_release_mutex(acpi_mutex handle);
 #endif
 
+#endif
+
 /*
  * Memory allocation and mapping
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_allocate
 void *acpi_os_allocate(acpi_size size);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_allocate_zeroed
+void *acpi_os_allocate_zeroed(acpi_size size);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_free
 void acpi_os_free(void *memory);
+#endif
 
-void __iomem *acpi_os_map_memory(acpi_physical_address where,
-                               acpi_size length);
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_map_memory
+void *acpi_os_map_memory(acpi_physical_address where, acpi_size length);
+#endif
 
-void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size);
-void early_acpi_os_unmap_memory(void __iomem * virt, acpi_size size);
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_unmap_memory
+void acpi_os_unmap_memory(void *logical_address, acpi_size size);
+#endif
 
-#ifdef ACPI_FUTURE_USAGE
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_physical_address
 acpi_status
 acpi_os_get_physical_address(void *logical_address,
                             acpi_physical_address * physical_address);
@@ -163,117 +208,195 @@ acpi_os_get_physical_address(void *logical_address,
 /*
  * Memory/Object Cache
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_cache
 acpi_status
 acpi_os_create_cache(char *cache_name,
                     u16 object_size,
                     u16 max_depth, acpi_cache_t ** return_cache);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_cache
 acpi_status acpi_os_delete_cache(acpi_cache_t * cache);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_purge_cache
 acpi_status acpi_os_purge_cache(acpi_cache_t * cache);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_object
 void *acpi_os_acquire_object(acpi_cache_t * cache);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_object
 acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object);
+#endif
 
 /*
  * Interrupt handlers
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_install_interrupt_handler
 acpi_status
 acpi_os_install_interrupt_handler(u32 interrupt_number,
                                  acpi_osd_handler service_routine,
                                  void *context);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_remove_interrupt_handler
 acpi_status
 acpi_os_remove_interrupt_handler(u32 interrupt_number,
                                 acpi_osd_handler service_routine);
-
-void acpi_os_gpe_count(u32 gpe_number);
-void acpi_os_fixed_event_count(u32 fixed_event_number);
+#endif
 
 /*
  * Threads and Scheduling
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id
 acpi_thread_id acpi_os_get_thread_id(void);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_execute
 acpi_status
 acpi_os_execute(acpi_execute_type type,
                acpi_osd_exec_callback function, void *context);
+#endif
 
-acpi_status
-acpi_os_hotplug_execute(acpi_osd_exec_callback function, void *context);
-
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_wait_events_complete
 void acpi_os_wait_events_complete(void);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_sleep
 void acpi_os_sleep(u64 milliseconds);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_stall
 void acpi_os_stall(u32 microseconds);
+#endif
 
 /*
  * Platform and hardware-independent I/O interfaces
  */
-acpi_status acpi_os_read_port(acpi_io_address address, u32 * value, u32 width);
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_read_port
+acpi_status acpi_os_read_port(acpi_io_address address, u32 *value, u32 width);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_write_port
 acpi_status acpi_os_write_port(acpi_io_address address, u32 value, u32 width);
+#endif
 
 /*
  * Platform and hardware-independent physical memory interfaces
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_read_memory
 acpi_status
 acpi_os_read_memory(acpi_physical_address address, u64 *value, u32 width);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_write_memory
 acpi_status
 acpi_os_write_memory(acpi_physical_address address, u64 value, u32 width);
+#endif
 
 /*
  * Platform and hardware-independent PCI configuration space access
  * Note: Can't use "Register" as a parameter, changed to "Reg" --
  * certain compilers complain.
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_read_pci_configuration
 acpi_status
 acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id,
                               u32 reg, u64 *value, u32 width);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_write_pci_configuration
 acpi_status
 acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id,
                                u32 reg, u64 value, u32 width);
+#endif
 
 /*
  * Miscellaneous
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_readable
+u8 acpi_os_readable(void *pointer, acpi_size length);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_writable
+u8 acpi_os_writable(void *pointer, acpi_size length);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_timer
 u64 acpi_os_get_timer(void);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_signal
 acpi_status acpi_os_signal(u32 function, void *info);
+#endif
 
 /*
  * Debug print routines
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_printf
 void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *format, ...);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_vprintf
 void acpi_os_vprintf(const char *format, va_list args);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_redirect_output
 void acpi_os_redirect_output(void *destination);
+#endif
 
-#ifdef ACPI_FUTURE_USAGE
 /*
  * Debug input
  */
-u32 acpi_os_get_line(char *buffer);
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_line
+acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read);
+#endif
+
+/*
+ * Obtain ACPI table(s)
+ */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_name
+acpi_status
+acpi_os_get_table_by_name(char *signature,
+                         u32 instance,
+                         struct acpi_table_header **table,
+                         acpi_physical_address * address);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_index
+acpi_status
+acpi_os_get_table_by_index(u32 index,
+                          struct acpi_table_header **table,
+                          u32 *instance, acpi_physical_address * address);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_address
+acpi_status
+acpi_os_get_table_by_address(acpi_physical_address address,
+                            struct acpi_table_header **table);
 #endif
 
 /*
  * Directory manipulation
  */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_open_directory
 void *acpi_os_open_directory(char *pathname,
                             char *wildcard_spec, char requested_file_type);
+#endif
 
 /* requeste_file_type values */
 
 #define REQUEST_FILE_ONLY                   0
 #define REQUEST_DIR_ONLY                    1
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_next_filename
 char *acpi_os_get_next_filename(void *dir_handle);
+#endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_close_directory
 void acpi_os_close_directory(void *dir_handle);
+#endif
 
 #endif                         /* __ACPIOSXF_H__ */
index 85bfdbe178052bd2231dce137b1463d174b2bffe..d8f9457755b4168787a66f903c15cb9d6506af25 100644 (file)
@@ -46,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20130725
+#define ACPI_CA_VERSION                 0x20130927
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
@@ -54,6 +54,7 @@
 #include <acpi/acbuffer.h>
 
 extern u8 acpi_gbl_permanent_mmap;
+extern u32 acpi_rsdt_forced;
 
 /*
  * Globals that are publically available
@@ -106,39 +107,41 @@ extern u8 acpi_gbl_disable_ssdt_table_load;
        static ACPI_INLINE prototype {return(AE_OK);}
 
 #define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \
-       static ACPI_INLINE prototype {}
+       static ACPI_INLINE prototype {return;}
 
 #endif                         /* !ACPI_REDUCED_HARDWARE */
 
-extern u32 acpi_rsdt_forced;
 /*
  * Initialization
  */
-acpi_status
+acpi_status __init
 acpi_initialize_tables(struct acpi_table_desc *initial_storage,
                       u32 initial_table_count, u8 allow_resize);
 
 acpi_status __init acpi_initialize_subsystem(void);
 
-acpi_status acpi_enable_subsystem(u32 flags);
+acpi_status __init acpi_enable_subsystem(u32 flags);
 
-acpi_status acpi_initialize_objects(u32 flags);
+acpi_status __init acpi_initialize_objects(u32 flags);
 
-acpi_status acpi_terminate(void);
+acpi_status __init acpi_terminate(void);
 
 /*
  * Miscellaneous global interfaces
  */
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable(void))
+
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable(void))
 #ifdef ACPI_FUTURE_USAGE
-acpi_status acpi_subsystem_status(void);
+ acpi_status acpi_subsystem_status(void);
 #endif
 
 #ifdef ACPI_FUTURE_USAGE
 acpi_status acpi_get_system_info(struct acpi_buffer *ret_buffer);
 #endif
 
+acpi_status acpi_get_statistics(struct acpi_statistics *stats);
+
 const char *acpi_format_exception(acpi_status exception);
 
 acpi_status acpi_purge_cached_objects(void);
@@ -158,15 +161,6 @@ acpi_status
 acpi_decode_pld_buffer(u8 *in_buffer,
                       acpi_size length, struct acpi_pld_info **return_buffer);
 
-/*
- * ACPI Memory management
- */
-void *acpi_allocate(u32 size);
-
-void *acpi_callocate(u32 size);
-
-void acpi_free(void *address);
-
 /*
  * ACPI table load/unload interfaces
  */
@@ -174,14 +168,14 @@ acpi_status acpi_load_table(struct acpi_table_header *table);
 
 acpi_status acpi_unload_parent_table(acpi_handle object);
 
-acpi_status acpi_load_tables(void);
+acpi_status __init acpi_load_tables(void);
 
 /*
  * ACPI table manipulation interfaces
  */
-acpi_status acpi_reallocate_root_table(void);
+acpi_status __init acpi_reallocate_root_table(void);
 
-acpi_status acpi_find_root_pointer(acpi_size *rsdp_address);
+acpi_status __init acpi_find_root_pointer(acpi_size *rsdp_address);
 
 acpi_status acpi_unload_table_id(acpi_owner_id id);
 
@@ -193,6 +187,7 @@ acpi_status
 acpi_get_table_with_size(acpi_string signature,
               u32 instance, struct acpi_table_header **out_table,
               acpi_size *tbl_size);
+
 acpi_status
 acpi_get_table(acpi_string signature,
               u32 instance, struct acpi_table_header **out_table);
@@ -280,8 +275,18 @@ acpi_status
 acpi_install_initialization_handler(acpi_init_handler handler, u32 function);
 
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
-                               acpi_install_global_event_handler
-                               (acpi_gbl_event_handler handler, void *context))
+                               acpi_install_sci_handler(acpi_sci_handler
+                                                        address,
+                                                        void *context))
+
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+                                acpi_remove_sci_handler(acpi_sci_handler
+                                                        address))
+
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+                                acpi_install_global_event_handler
+                                (acpi_gbl_event_handler handler,
+                                 void *context))
 
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                 acpi_install_fixed_event_handler(u32
@@ -290,10 +295,12 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                                                  handler,
                                                                  void
                                                                  *context))
+
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                 acpi_remove_fixed_event_handler(u32 acpi_event,
                                                                 acpi_event_handler
                                                                 handler))
+
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                 acpi_install_gpe_handler(acpi_handle
                                                          gpe_device,
@@ -302,6 +309,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                                          acpi_gpe_handler
                                                          address,
                                                          void *context))
+
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                 acpi_remove_gpe_handler(acpi_handle gpe_device,
                                                         u32 gpe_number,
@@ -338,6 +346,7 @@ acpi_status acpi_install_interface_handler(acpi_interface_handler handler);
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                acpi_acquire_global_lock(u16 timeout,
                                                         u32 *handle))
+
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                acpi_release_global_lock(u32 handle))
 
@@ -364,6 +373,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                acpi_get_event_status(u32 event,
                                                      acpi_event_status
                                                      *event_status))
+
 /*
  * General Purpose Event (GPE) Interfaces
  */
@@ -394,10 +404,12 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                                        parent_device,
                                                        acpi_handle gpe_device,
                                                        u32 gpe_number))
+
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                 acpi_set_gpe_wake_mask(acpi_handle gpe_device,
                                                        u32 gpe_number,
                                                        u8 action))
+
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                 acpi_get_gpe_status(acpi_handle gpe_device,
                                                     u32 gpe_number,
@@ -419,6 +431,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                                       *gpe_block_address,
                                                       u32 register_count,
                                                       u32 interrupt_number))
+
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                 acpi_remove_gpe_block(acpi_handle gpe_device))
 
@@ -493,13 +506,13 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
  * Sleep/Wake interfaces
  */
 acpi_status
-acpi_get_sleep_type_data(u8 sleep_state, u8 * slp_typ_a, u8 * slp_typ_b);
+acpi_get_sleep_type_data(u8 sleep_state, u8 *slp_typ_a, u8 *slp_typ_b);
 
 acpi_status acpi_enter_sleep_state_prep(u8 sleep_state);
 
-acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state);
+acpi_status acpi_enter_sleep_state(u8 sleep_state);
 
-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void))
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enter_sleep_state_s4bios(void))
 
 acpi_status acpi_leave_sleep_state_prep(u8 sleep_state);
 
@@ -508,7 +521,6 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state);
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                acpi_set_firmware_waking_vector(u32
                                                                physical_address))
-
 #if ACPI_MACHINE_WIDTH == 64
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                acpi_set_firmware_waking_vector64(u64
@@ -532,50 +544,53 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
 /*
  * Error/Warning output
  */
+ACPI_PRINTF_LIKE(3)
 void ACPI_INTERNAL_VAR_XFACE
-acpi_error(const char *module_name,
-          u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3);
+acpi_error(const char *module_name, u32 line_number, const char *format, ...);
 
+ACPI_PRINTF_LIKE(4)
 void ACPI_INTERNAL_VAR_XFACE
 acpi_exception(const char *module_name,
-              u32 line_number,
-              acpi_status status, const char *format, ...) ACPI_PRINTF_LIKE(4);
+              u32 line_number, acpi_status status, const char *format, ...);
 
+ACPI_PRINTF_LIKE(3)
 void ACPI_INTERNAL_VAR_XFACE
-acpi_warning(const char *module_name,
-            u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3);
+acpi_warning(const char *module_name, u32 line_number, const char *format, ...);
 
+ACPI_PRINTF_LIKE(3)
 void ACPI_INTERNAL_VAR_XFACE
-acpi_info(const char *module_name,
-         u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3);
+acpi_info(const char *module_name, u32 line_number, const char *format, ...);
 
+ACPI_PRINTF_LIKE(3)
 void ACPI_INTERNAL_VAR_XFACE
 acpi_bios_error(const char *module_name,
-               u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3);
+               u32 line_number, const char *format, ...);
 
+ACPI_PRINTF_LIKE(3)
 void ACPI_INTERNAL_VAR_XFACE
 acpi_bios_warning(const char *module_name,
-                 u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3);
+                 u32 line_number, const char *format, ...);
 
 /*
  * Debug output
  */
 #ifdef ACPI_DEBUG_OUTPUT
 
+ACPI_PRINTF_LIKE(6)
 void ACPI_INTERNAL_VAR_XFACE
 acpi_debug_print(u32 requested_debug_level,
                 u32 line_number,
                 const char *function_name,
                 const char *module_name,
-                u32 component_id, const char *format, ...) ACPI_PRINTF_LIKE(6);
+                u32 component_id, const char *format, ...);
 
+ACPI_PRINTF_LIKE(6)
 void ACPI_INTERNAL_VAR_XFACE
 acpi_debug_print_raw(u32 requested_debug_level,
                     u32 line_number,
                     const char *function_name,
                     const char *module_name,
-                    u32 component_id,
-                    const char *format, ...) ACPI_PRINTF_LIKE(6);
+                    u32 component_id, const char *format, ...);
 #endif
 
 #endif                         /* __ACXFACE_H__ */
index 9b58a8f4377127f198498e7db54430cf9c5979ae..94970880126f151a74c00de146a58d2a6aad6c59 100644 (file)
@@ -146,7 +146,24 @@ struct acpi_table_rsdp {
        u8 reserved[3];         /* Reserved, must be zero */
 };
 
-#define ACPI_RSDP_REV0_SIZE     20     /* Size of original ACPI 1.0 RSDP */
+/* Standalone struct for the ACPI 1.0 RSDP */
+
+struct acpi_rsdp_common {
+       char signature[8];
+       u8 checksum;
+       char oem_id[ACPI_OEM_ID_SIZE];
+       u8 revision;
+       u32 rsdt_physical_address;
+};
+
+/* Standalone struct for the extended part of the RSDP (ACPI 2.0+) */
+
+struct acpi_rsdp_extension {
+       u32 length;
+       u64 xsdt_physical_address;
+       u8 extended_checksum;
+       u8 reserved[3];
+};
 
 /*******************************************************************************
  *
index ffaac0e7e0c687afffa8025588cb713311e88cb9..40f7ed115452aa7c537a8288579a7b974434b601 100644 (file)
@@ -444,8 +444,8 @@ enum acpi_dmar_scope_type {
 };
 
 struct acpi_dmar_pci_path {
-       u8 dev;
-       u8 fn;
+       u8 device;
+       u8 function;
 };
 
 /*
index b748aefce929983cf94d3729db782e62c2843768..809b1a0fee7fd916d2204020b8392a05bc51e172 100644 (file)
@@ -299,13 +299,57 @@ typedef u32 acpi_physical_address;
 #endif
 
 /*
- * All ACPICA functions that are available to the rest of the kernel are
- * tagged with this macro which can be defined as appropriate for the host.
+ * All ACPICA external functions that are available to the rest of the kernel
+ * are tagged with thes macros which can be defined as appropriate for the host.
+ *
+ * Notes:
+ * ACPI_EXPORT_SYMBOL_INIT is used for initialization and termination
+ * interfaces that may need special processing.
+ * ACPI_EXPORT_SYMBOL is used for all other public external functions.
  */
+#ifndef ACPI_EXPORT_SYMBOL_INIT
+#define ACPI_EXPORT_SYMBOL_INIT(symbol)
+#endif
+
 #ifndef ACPI_EXPORT_SYMBOL
 #define ACPI_EXPORT_SYMBOL(symbol)
 #endif
 
+/*
+ * Compiler/Clibrary-dependent debug initialization. Used for ACPICA
+ * utilities only.
+ */
+#ifndef ACPI_DEBUG_INITIALIZE
+#define ACPI_DEBUG_INITIALIZE()
+#endif
+
+/*******************************************************************************
+ *
+ * Configuration
+ *
+ ******************************************************************************/
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+/*
+ * Memory allocation tracking (used by acpi_exec to detect memory leaks)
+ */
+#define ACPI_MEM_PARAMETERS             _COMPONENT, _acpi_module_name, __LINE__
+#define ACPI_ALLOCATE(a)                acpi_ut_allocate_and_track ((acpi_size) (a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE_ZEROED(a)         acpi_ut_allocate_zeroed_and_track ((acpi_size) (a), ACPI_MEM_PARAMETERS)
+#define ACPI_FREE(a)                    acpi_ut_free_and_track (a, ACPI_MEM_PARAMETERS)
+#define ACPI_MEM_TRACKING(a)            a
+
+#else
+/*
+ * Normal memory allocation directly via the OS services layer
+ */
+#define ACPI_ALLOCATE(a)                acpi_os_allocate ((acpi_size) (a))
+#define ACPI_ALLOCATE_ZEROED(a)         acpi_os_allocate_zeroed ((acpi_size) (a))
+#define ACPI_FREE(a)                    acpi_os_free (a)
+#define ACPI_MEM_TRACKING(a)
+
+#endif                         /* ACPI_DBG_TRACK_ALLOCATIONS */
+
 /******************************************************************************
  *
  * ACPI Specification constants (Do not change unless the specification changes)
@@ -322,6 +366,7 @@ typedef u32 acpi_physical_address;
 #define ACPI_PM1_REGISTER_WIDTH         16
 #define ACPI_PM2_REGISTER_WIDTH         8
 #define ACPI_PM_TIMER_WIDTH             32
+#define ACPI_RESET_REGISTER_WIDTH       8
 
 /* Names within the namespace are 4 bytes long */
 
@@ -474,6 +519,11 @@ typedef u64 acpi_integer;
 #define ACPI_MOVE_NAME(dest,src)        (ACPI_STRNCPY (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE))
 #endif
 
+/* Support for the special RSDP signature (8 characters) */
+
+#define ACPI_VALIDATE_RSDP_SIG(a)       (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8))
+#define ACPI_MAKE_RSDP_SIG(dest)        (ACPI_MEMCPY (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8))
+
 /*******************************************************************************
  *
  * Miscellaneous constants
@@ -886,9 +936,13 @@ struct acpi_buffer {
        void *pointer;          /* pointer to buffer */
 };
 
-/* Free a buffer created in an struct acpi_buffer via ACPI_ALLOCATE_LOCAL_BUFFER */
-
-#define ACPI_FREE_BUFFER(b)         ACPI_FREE(b.pointer)
+/*
+ * Free a buffer created in an struct acpi_buffer via ACPI_ALLOCATE_BUFFER.
+ * Note: We use acpi_os_free here because acpi_os_allocate was used to allocate
+ * the buffer. This purposefully bypasses the internal allocation tracking
+ * mechanism (if it is enabled).
+ */
+#define ACPI_FREE_BUFFER(b)         acpi_os_free((b).pointer)
 
 /*
  * name_type for acpi_get_name
@@ -927,6 +981,16 @@ struct acpi_system_info {
        u32 debug_layer;
 };
 
+/*
+ * System statistics returned by acpi_get_statistics()
+ */
+struct acpi_statistics {
+       u32 sci_count;
+       u32 gpe_count;
+       u32 fixed_event_count[ACPI_NUM_FIXED_EVENTS];
+       u32 method_count;
+};
+
 /* Table Event Types */
 
 #define ACPI_TABLE_EVENT_LOAD           0x0
@@ -945,6 +1009,9 @@ typedef void
 /*
  * Various handlers and callback procedures
  */
+typedef
+u32 (*acpi_sci_handler) (void *context);
+
 typedef
 void (*acpi_gbl_event_handler) (u32 event_type,
                               acpi_handle device,
index ef04b36ca6ed788de2e4b8c305508a2f9d165f3f..974d3ef7c1413d42be45b974487ca062e2cfdcc4 100644 (file)
 #endif
 
 /*
- * acpi_bin/acpi_help/acpi_src configuration. All single threaded, with
- * no debug output.
+ * acpi_bin/acpi_dump/acpi_src/acpi_xtract configuration. All single
+ * threaded, with no debug output.
  */
 #if (defined ACPI_BIN_APP)   || \
+       (defined ACPI_DUMP_APP)  || \
        (defined ACPI_SRC_APP)   || \
        (defined ACPI_XTRACT_APP)
 #define ACPI_APPLICATION
 #if defined(_LINUX) || defined(__linux__)
 #include <acpi/platform/aclinux.h>
 
+#elif defined(_APPLE) || defined(__APPLE__)
+#include "acmacosx.h"
+
 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 #include "acfreebsd.h"
 
index 68534ef86ec81a903e09ccd93169baf69b4bb73e..ab57930794a5843e252c59c2ffadf310af877ff5 100644 (file)
@@ -50,7 +50,6 @@
 #define ACPI_USE_DO_WHILE_0
 #define ACPI_MUTEX_TYPE             ACPI_BINARY_SEMAPHORE
 
-
 #ifdef __KERNEL__
 
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/sched.h>
 #include <linux/atomic.h>
-#include <asm/div64.h>
-#include <asm/acpi.h>
+#include <linux/math64.h>
 #include <linux/slab.h>
 #include <linux/spinlock_types.h>
-#include <asm/current.h>
+#ifdef EXPORT_ACPI_INTERFACES
+#include <linux/export.h>
+#endif
+#include <asm/acpi.h>
 
 /* Host-dependent types and defines for in-kernel ACPICA */
 
@@ -74,7 +75,7 @@
 #define acpi_spinlock                       spinlock_t *
 #define acpi_cpu_flags                      unsigned long
 
-#else /* !__KERNEL__ */
+#else                          /* !__KERNEL__ */
 
 #include <stdarg.h>
 #include <string.h>
@@ -87,7 +88,7 @@
 #define ACPI_FLUSH_CPU_CACHE()
 #define ACPI_CAST_PTHREAD_T(pthread) ((acpi_thread_id) (pthread))
 
-#if defined(__ia64__) || defined(__x86_64__)
+#if defined(__ia64__) || defined(__x86_64__) || defined(__aarch64__)
 #define ACPI_MACHINE_WIDTH          64
 #define COMPILER_DEPENDENT_INT64    long
 #define COMPILER_DEPENDENT_UINT64   unsigned long
 #define __cdecl
 #endif
 
-#endif /* __KERNEL__ */
+#endif                         /* __KERNEL__ */
 
 /* Linux uses GCC */
 
 #include <acpi/platform/acgcc.h>
 
 #ifdef __KERNEL__
+
+/*
+ * FIXME: Inclusion of actypes.h
+ * Linux kernel need this before defining inline OSL interfaces as
+ * actypes.h need to be included to find ACPICA type definitions.
+ * Since from ACPICA's perspective, the actypes.h should be included after
+ * acenv.h (aclinux.h), this leads to a inclusion mis-ordering issue.
+ */
 #include <acpi/actypes.h>
+
 /*
  * Overrides for in-kernel ACPICA
  */
-static inline acpi_thread_id acpi_os_get_thread_id(void)
-{
-       return (acpi_thread_id)(unsigned long)current;
-}
+acpi_status __init acpi_os_initialize(void);
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize
+
+acpi_status acpi_os_terminate(void);
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate
+
+/*
+ * Memory allocation/deallocation
+ */
 
 /*
  * The irqs_disabled() check is for resume from RAM.
@@ -126,25 +141,45 @@ static inline acpi_thread_id acpi_os_get_thread_id(void)
  */
 static inline void *acpi_os_allocate(acpi_size size)
 {
-       return kmalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
+       return kmalloc(size, irqs_disabled()? GFP_ATOMIC : GFP_KERNEL);
 }
 
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_allocate
+
+/* Use native linux version of acpi_os_allocate_zeroed */
+
 static inline void *acpi_os_allocate_zeroed(acpi_size size)
 {
-       return kzalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
+       return kzalloc(size, irqs_disabled()? GFP_ATOMIC : GFP_KERNEL);
 }
 
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_allocate_zeroed
+#define USE_NATIVE_ALLOCATE_ZEROED
+
+static inline void acpi_os_free(void *memory)
+{
+       kfree(memory);
+}
+
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_free
+
 static inline void *acpi_os_acquire_object(acpi_cache_t * cache)
 {
        return kmem_cache_zalloc(cache,
-               irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
+                                irqs_disabled()? GFP_ATOMIC : GFP_KERNEL);
 }
 
-#define ACPI_ALLOCATE(a)        acpi_os_allocate(a)
-#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a)
-#define ACPI_FREE(a)            kfree(a)
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_object
+
+static inline acpi_thread_id acpi_os_get_thread_id(void)
+{
+       return (acpi_thread_id) (unsigned long)current;
+}
+
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id
 
 #ifndef CONFIG_PREEMPT
+
 /*
  * Used within ACPICA to show where it is safe to preempt execution
  * when CONFIG_PREEMPT=n
@@ -154,6 +189,7 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache)
                if (!irqs_disabled()) \
                        cond_resched(); \
        } while (0)
+
 #endif
 
 /*
@@ -163,17 +199,53 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache)
  * all locks to the name of the argument of acpi_os_create_lock(), which
  * prevents lockdep from reporting false positives for ACPICA locks.
  */
-#define acpi_os_create_lock(__handle)                          \
-({                                                             \
-       spinlock_t *lock = ACPI_ALLOCATE(sizeof(*lock));        \
-                                                               \
-       if (lock) {                                             \
-               *(__handle) = lock;                             \
-               spin_lock_init(*(__handle));                    \
-       }                                                       \
-       lock ? AE_OK : AE_NO_MEMORY;                            \
-})
-
-#endif /* __KERNEL__ */
-
-#endif /* __ACLINUX_H__ */
+#define acpi_os_create_lock(__handle) \
+       ({ \
+               spinlock_t *lock = ACPI_ALLOCATE(sizeof(*lock)); \
+               if (lock) { \
+                       *(__handle) = lock; \
+                       spin_lock_init(*(__handle)); \
+               } \
+               lock ? AE_OK : AE_NO_MEMORY; \
+       })
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock
+
+void __iomem *acpi_os_map_memory(acpi_physical_address where, acpi_size length);
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_map_memory
+
+void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size);
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_unmap_memory
+
+/*
+ * OSL interfaces used by debugger/disassembler
+ */
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_readable
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_writable
+
+/*
+ * OSL interfaces used by utilities
+ */
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_redirect_output
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_line
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_name
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_index
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_address
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_open_directory
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_next_filename
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_close_directory
+
+/*
+ * OSL interfaces added by Linux
+ */
+void early_acpi_os_unmap_memory(void __iomem * virt, acpi_size size);
+
+void acpi_os_gpe_count(u32 gpe_number);
+
+void acpi_os_fixed_event_count(u32 fixed_event_number);
+
+acpi_status
+acpi_os_hotplug_execute(acpi_osd_exec_callback function, void *context);
+
+#endif                         /* __KERNEL__ */
+
+#endif                         /* __ACLINUX_H__ */
index 66096d06925e417d70d6b8974a00a035d05ef1d8..6eb1d3cb5104ce9e16d239a5b3dcfd4e8088148c 100644 (file)
@@ -199,6 +199,7 @@ struct acpi_processor_flags {
 struct acpi_processor {
        acpi_handle handle;
        u32 acpi_id;
+       u32 apic_id;
        u32 id;
        u32 pblk;
        int performance_platform_limit;
@@ -224,7 +225,6 @@ struct acpi_processor_errata {
        } piix4;
 };
 
-extern void acpi_processor_load_module(struct acpi_processor *pr);
 extern int acpi_processor_preregister_performance(struct
                                                  acpi_processor_performance
                                                  __percpu *performance);
@@ -314,6 +314,8 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
 
 /* in processor_core.c */
 void acpi_processor_set_pdc(acpi_handle handle);
+int acpi_get_apicid(acpi_handle, int type, u32 acpi_id);
+int acpi_map_cpuid(int apic_id, u32 acpi_id);
 int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
 
 /* in processor_throttling.c */
index a5db4aeefa3642107e28b431c21a89c195569993..3bc74141453f85b93400536f0bcb61f1354b8bf5 100644 (file)
@@ -116,7 +116,7 @@ void acpi_numa_arch_fixup(void);
 
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
 /* Arch dependent functions for cpu hotplug support */
-int acpi_map_lsapic(acpi_handle handle, int *pcpu);
+int acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu);
 int acpi_unmap_lsapic(int cpu);
 #endif /* CONFIG_ACPI_HOTPLUG_CPU */
 
index 53b77949c79d4c84b6595614206857e2b6796b1f..5f9cd963213dd3a3150abd3e34f62a6925096053 100644 (file)
@@ -100,6 +100,9 @@ struct backlight_device {
        /* The framebuffer notifier block */
        struct notifier_block fb_notif;
 
+       /* list entry of all registered backlight devices */
+       struct list_head entry;
+
        struct device dev;
 };
 
@@ -123,6 +126,7 @@ extern void devm_backlight_device_unregister(struct device *dev,
                                        struct backlight_device *bd);
 extern void backlight_force_update(struct backlight_device *bd,
                                   enum backlight_update_reason reason);
+extern bool backlight_device_registered(enum backlight_type type);
 
 #define to_backlight_device(obj) container_of(obj, struct backlight_device, dev)
 
index a3b6b82108b9ad239dd1dda1abe6c8e3f585d3b3..5a1c8b71ccd84616b0471b833ee909c9d794be5f 100644 (file)
@@ -4,8 +4,11 @@
 
 #ifdef __KERNEL__
 #define BIT(nr)                        (1UL << (nr))
+#define BIT_ULL(nr)            (1ULL << (nr))
 #define BIT_MASK(nr)           (1UL << ((nr) % BITS_PER_LONG))
 #define BIT_WORD(nr)           ((nr) / BITS_PER_LONG)
+#define BIT_ULL_MASK(nr)       (1ULL << ((nr) % BITS_PER_LONG_LONG))
+#define BIT_ULL_WORD(nr)       ((nr) / BITS_PER_LONG_LONG)
 #define BITS_PER_BYTE          8
 #define BITS_TO_LONGS(nr)      DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
 #endif
index 801ff9e73679a00d7f945d82253454a236319966..3434ef7de017de0d5a33e7dd5dbfb173678c58c0 100644 (file)
@@ -185,19 +185,6 @@ extern void cpu_hotplug_enable(void);
 void clear_tasks_mm_cpumask(int cpu);
 int cpu_down(unsigned int cpu);
 
-#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
-extern void cpu_hotplug_driver_lock(void);
-extern void cpu_hotplug_driver_unlock(void);
-#else
-static inline void cpu_hotplug_driver_lock(void)
-{
-}
-
-static inline void cpu_hotplug_driver_unlock(void)
-{
-}
-#endif
-
 #else          /* CONFIG_HOTPLUG_CPU */
 
 static inline void cpu_hotplug_begin(void) {}
index fcabc42d66ab413a38730cb78d8eedc9bda91084..5bd6ab9b0c2750fca49409c9714d41f1ce7a2d9f 100644 (file)
@@ -85,6 +85,20 @@ struct cpufreq_policy {
        struct list_head        policy_list;
        struct kobject          kobj;
        struct completion       kobj_unregister;
+
+       /*
+        * The rules for this semaphore:
+        * - Any routine that wants to read from the policy structure will
+        *   do a down_read on this semaphore.
+        * - Any routine that will write to the policy structure and/or may take away
+        *   the policy altogether (eg. CPU hotplug), will hold this lock in write
+        *   mode before doing so.
+        *
+        * Additional rules:
+        * - Lock should not be held across
+        *     __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
+        */
+       struct rw_semaphore     rwsem;
 };
 
 /* Only for ACPI */
@@ -180,13 +194,6 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
 struct cpufreq_driver {
        char                    name[CPUFREQ_NAME_LEN];
        u8                      flags;
-       /*
-        * This should be set by platforms having multiple clock-domains, i.e.
-        * supporting multiple policies. With this sysfs directories of governor
-        * would be created in cpu/cpu<num>/cpufreq/ directory and so they can
-        * use the same governor with different tunables for different clusters.
-        */
-       bool                    have_governor_per_policy;
 
        /* needed by all drivers */
        int     (*init)         (struct cpufreq_policy *policy);
@@ -194,9 +201,11 @@ struct cpufreq_driver {
 
        /* define one out of two */
        int     (*setpolicy)    (struct cpufreq_policy *policy);
-       int     (*target)       (struct cpufreq_policy *policy,
+       int     (*target)       (struct cpufreq_policy *policy, /* Deprecated */
                                 unsigned int target_freq,
                                 unsigned int relation);
+       int     (*target_index) (struct cpufreq_policy *policy,
+                                unsigned int index);
 
        /* should be defined, if possible */
        unsigned int    (*get)  (unsigned int cpu);
@@ -211,13 +220,29 @@ struct cpufreq_driver {
 };
 
 /* flags */
-#define CPUFREQ_STICKY         0x01    /* the driver isn't removed even if
-                                        * all ->init() calls failed */
-#define CPUFREQ_CONST_LOOPS    0x02    /* loops_per_jiffy or other kernel
-                                        * "constants" aren't affected by
-                                        * frequency transitions */
-#define CPUFREQ_PM_NO_WARN     0x04    /* don't warn on suspend/resume speed
-                                        * mismatches */
+#define CPUFREQ_STICKY         (1 << 0)        /* driver isn't removed even if
+                                                  all ->init() calls failed */
+#define CPUFREQ_CONST_LOOPS    (1 << 1)        /* loops_per_jiffy or other
+                                                  kernel "constants" aren't
+                                                  affected by frequency
+                                                  transitions */
+#define CPUFREQ_PM_NO_WARN     (1 << 2)        /* don't warn on suspend/resume
+                                                  speed mismatches */
+
+/*
+ * This should be set by platforms having multiple clock-domains, i.e.
+ * supporting multiple policies. With this sysfs directories of governor would
+ * be created in cpu/cpu<num>/cpufreq/ directory and so they can use the same
+ * governor with different tunables for different clusters.
+ */
+#define CPUFREQ_HAVE_GOVERNOR_PER_POLICY (1 << 3)
+
+/*
+ * Driver will do POSTCHANGE notifications from outside of their ->target()
+ * routine and so must set cpufreq_driver->flags with this flag, so that core
+ * can handle them specially.
+ */
+#define CPUFREQ_ASYNC_NOTIFICATION  (1 << 4)
 
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
@@ -240,6 +265,13 @@ static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
        return;
 }
 
+static inline void
+cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
+{
+       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+                       policy->cpuinfo.max_freq);
+}
+
 /*********************************************************************
  *                     CPUFREQ NOTIFIER INTERFACE                    *
  *********************************************************************/
@@ -392,6 +424,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
 
 int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table);
+int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy);
 
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table,
@@ -407,8 +440,20 @@ struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
 
 /* the following are really really optional */
 extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
+extern struct freq_attr *cpufreq_generic_attr[];
 void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
                                      unsigned int cpu);
 void cpufreq_frequency_table_put_attr(unsigned int cpu);
+int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
+                                     struct cpufreq_frequency_table *table);
+
+int cpufreq_generic_init(struct cpufreq_policy *policy,
+               struct cpufreq_frequency_table *table,
+               unsigned int transition_latency);
+static inline int cpufreq_generic_exit(struct cpufreq_policy *policy)
+{
+       cpufreq_frequency_table_put_attr(policy->cpu);
+       return 0;
+}
 
 #endif /* _LINUX_CPUFREQ_H */
index 781addc66f03135e1fe033bd6aeb0476c0321fd2..50fcbb0ac4e7033922508aa1fc805936087cd5f2 100644 (file)
@@ -114,7 +114,7 @@ struct cpuidle_driver {
        int                     safe_state_index;
 
        /* the driver handles the cpus in cpumask */
-       struct cpumask       *cpumask;
+       struct cpumask          *cpumask;
 };
 
 #ifdef CONFIG_CPU_IDLE
@@ -195,16 +195,10 @@ struct cpuidle_governor {
 };
 
 #ifdef CONFIG_CPU_IDLE
-
 extern int cpuidle_register_governor(struct cpuidle_governor *gov);
-extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
-
 #else
-
 static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
 {return 0;}
-static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { }
-
 #endif
 
 #ifdef CONFIG_ARCH_HAS_CPU_RELAX
index 5f1ab92107e63b1889da7e544189f8b73cc740fb..7a7cc74d7f27e9901e59d2a61b850c0ec6acbe9e 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/device.h>
 #include <linux/notifier.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 
 #define DEVFREQ_NAME_LEN 16
 
@@ -187,7 +187,7 @@ extern int devfreq_suspend_device(struct devfreq *devfreq);
 extern int devfreq_resume_device(struct devfreq *devfreq);
 
 /* Helper functions for devfreq user device driver with OPP. */
-extern struct opp *devfreq_recommended_opp(struct device *dev,
+extern struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
                                           unsigned long *freq, u32 flags);
 extern int devfreq_register_opp_notifier(struct device *dev,
                                         struct devfreq *devfreq);
@@ -238,7 +238,7 @@ static inline int devfreq_resume_device(struct devfreq *devfreq)
        return 0;
 }
 
-static inline struct opp *devfreq_recommended_opp(struct device *dev,
+static inline struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
                                           unsigned long *freq, u32 flags)
 {
        return ERR_PTR(-EINVAL);
index a6ac84871d6d415eb0e671b45daeddacbc7ad4a3..ff4e40cd45b1dcb15c66f1e178b655df7c40c0eb 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/atomic.h>
 #include <linux/compat.h>
+#include <linux/workqueue.h>
 #include <uapi/linux/filter.h>
 
 #ifdef CONFIG_COMPAT
@@ -25,15 +26,19 @@ struct sk_filter
 {
        atomic_t                refcnt;
        unsigned int            len;    /* Number of filter blocks */
+       struct rcu_head         rcu;
        unsigned int            (*bpf_func)(const struct sk_buff *skb,
                                            const struct sock_filter *filter);
-       struct rcu_head         rcu;
-       struct sock_filter      insns[0];
+       union {
+               struct sock_filter      insns[0];
+               struct work_struct      work;
+       };
 };
 
-static inline unsigned int sk_filter_len(const struct sk_filter *fp)
+static inline unsigned int sk_filter_size(unsigned int proglen)
 {
-       return fp->len * sizeof(struct sock_filter) + sizeof(*fp);
+       return max(sizeof(struct sk_filter),
+                  offsetof(struct sk_filter, insns[proglen]));
 }
 
 extern int sk_filter(struct sock *sk, struct sk_buff *skb);
@@ -67,11 +72,13 @@ static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
 }
 #define SK_RUN_FILTER(FILTER, SKB) (*FILTER->bpf_func)(SKB, FILTER->insns)
 #else
+#include <linux/slab.h>
 static inline void bpf_jit_compile(struct sk_filter *fp)
 {
 }
 static inline void bpf_jit_free(struct sk_filter *fp)
 {
+       kfree(fp);
 }
 #define SK_RUN_FILTER(FILTER, SKB) sk_run_filter(SKB, FILTER->insns)
 #endif
index ecc82b37c4ccf00fb863ecf6981de19bbccec52a..b3e7a667e03c24ca5c3d1c54c0db5c7b0bdde052 100644 (file)
@@ -137,47 +137,24 @@ extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg,
 extern void mem_cgroup_replace_page_cache(struct page *oldpage,
                                        struct page *newpage);
 
-/**
- * mem_cgroup_toggle_oom - toggle the memcg OOM killer for the current task
- * @new: true to enable, false to disable
- *
- * Toggle whether a failed memcg charge should invoke the OOM killer
- * or just return -ENOMEM.  Returns the previous toggle state.
- *
- * NOTE: Any path that enables the OOM killer before charging must
- *       call mem_cgroup_oom_synchronize() afterward to finalize the
- *       OOM handling and clean up.
- */
-static inline bool mem_cgroup_toggle_oom(bool new)
+static inline void mem_cgroup_oom_enable(void)
 {
-       bool old;
-
-       old = current->memcg_oom.may_oom;
-       current->memcg_oom.may_oom = new;
-
-       return old;
+       WARN_ON(current->memcg_oom.may_oom);
+       current->memcg_oom.may_oom = 1;
 }
 
-static inline void mem_cgroup_enable_oom(void)
+static inline void mem_cgroup_oom_disable(void)
 {
-       bool old = mem_cgroup_toggle_oom(true);
-
-       WARN_ON(old == true);
-}
-
-static inline void mem_cgroup_disable_oom(void)
-{
-       bool old = mem_cgroup_toggle_oom(false);
-
-       WARN_ON(old == false);
+       WARN_ON(!current->memcg_oom.may_oom);
+       current->memcg_oom.may_oom = 0;
 }
 
 static inline bool task_in_memcg_oom(struct task_struct *p)
 {
-       return p->memcg_oom.in_memcg_oom;
+       return p->memcg_oom.memcg;
 }
 
-bool mem_cgroup_oom_synchronize(void);
+bool mem_cgroup_oom_synchronize(bool wait);
 
 #ifdef CONFIG_MEMCG_SWAP
 extern int do_swap_account;
@@ -402,16 +379,11 @@ static inline void mem_cgroup_end_update_page_stat(struct page *page,
 {
 }
 
-static inline bool mem_cgroup_toggle_oom(bool new)
-{
-       return false;
-}
-
-static inline void mem_cgroup_enable_oom(void)
+static inline void mem_cgroup_oom_enable(void)
 {
 }
 
-static inline void mem_cgroup_disable_oom(void)
+static inline void mem_cgroup_oom_disable(void)
 {
 }
 
@@ -420,7 +392,7 @@ static inline bool task_in_memcg_oom(struct task_struct *p)
        return false;
 }
 
-static inline bool mem_cgroup_oom_synchronize(void)
+static inline bool mem_cgroup_oom_synchronize(bool wait)
 {
        return false;
 }
index 68029b30c3dc89e2d2620fd41101b2ab05069344..5eb4e31af22b8e05356dfef793c1b96497af8cb3 100644 (file)
@@ -181,7 +181,7 @@ enum {
        MLX5_DEV_CAP_FLAG_TLP_HINTS     = 1LL << 39,
        MLX5_DEV_CAP_FLAG_SIG_HAND_OVER = 1LL << 40,
        MLX5_DEV_CAP_FLAG_DCT           = 1LL << 41,
-       MLX5_DEV_CAP_FLAG_CMDIF_CSUM    = 1LL << 46,
+       MLX5_DEV_CAP_FLAG_CMDIF_CSUM    = 3LL << 46,
 };
 
 enum {
@@ -417,7 +417,7 @@ struct mlx5_init_seg {
        struct health_buffer    health;
        __be32                  rsvd2[884];
        __be32                  health_counter;
-       __be32                  rsvd3[1023];
+       __be32                  rsvd3[1019];
        __be64                  ieee1588_clk;
        __be32                  ieee1588_clk_type;
        __be32                  clr_intx;
index 8888381fc150b8f3f852077407ee8187a54cb7aa..6b8c496572c841d8ec8be70740557f1caf50b79a 100644 (file)
@@ -82,7 +82,7 @@ enum {
 };
 
 enum {
-       MLX5_MAX_EQ_NAME        = 20
+       MLX5_MAX_EQ_NAME        = 32
 };
 
 enum {
@@ -747,8 +747,7 @@ static inline u32 mlx5_idx_to_mkey(u32 mkey_idx)
 
 enum {
        MLX5_PROF_MASK_QP_SIZE          = (u64)1 << 0,
-       MLX5_PROF_MASK_CMDIF_CSUM       = (u64)1 << 1,
-       MLX5_PROF_MASK_MR_CACHE         = (u64)1 << 2,
+       MLX5_PROF_MASK_MR_CACHE         = (u64)1 << 1,
 };
 
 enum {
@@ -758,7 +757,6 @@ enum {
 struct mlx5_profile {
        u64     mask;
        u32     log_max_qp;
-       int     cmdif_csum;
        struct {
                int     size;
                int     limit;
index 3de49aca451970a738b5ae55cfd74656248ac9ea..25f5d2d11e7c4c5b6053c4ba5c7ac17a601f4f2b 100644 (file)
@@ -2264,11 +2264,12 @@ static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
 }
 
 #ifdef CONFIG_XPS
-extern int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask,
+extern int netif_set_xps_queue(struct net_device *dev,
+                              const struct cpumask *mask,
                               u16 index);
 #else
 static inline int netif_set_xps_queue(struct net_device *dev,
-                                     struct cpumask *mask,
+                                     const struct cpumask *mask,
                                      u16 index)
 {
        return 0;
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
deleted file mode 100644 (file)
index c841282..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __OF_RESERVED_MEM_H
-#define __OF_RESERVED_MEM_H
-
-#ifdef CONFIG_OF_RESERVED_MEM
-void of_reserved_mem_device_init(struct device *dev);
-void of_reserved_mem_device_release(struct device *dev);
-void early_init_dt_scan_reserved_mem(void);
-#else
-static inline void of_reserved_mem_device_init(struct device *dev) { }
-static inline void of_reserved_mem_device_release(struct device *dev) { }
-static inline void early_init_dt_scan_reserved_mem(void) { }
-#endif
-
-#endif /* __OF_RESERVED_MEM_H */
diff --git a/include/linux/opp.h b/include/linux/opp.h
deleted file mode 100644 (file)
index 3aca2b8..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Generic OPP Interface
- *
- * Copyright (C) 2009-2010 Texas Instruments Incorporated.
- *     Nishanth Menon
- *     Romit Dasgupta
- *     Kevin Hilman
- *
- * 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 __LINUX_OPP_H__
-#define __LINUX_OPP_H__
-
-#include <linux/err.h>
-#include <linux/cpufreq.h>
-#include <linux/notifier.h>
-
-struct opp;
-struct device;
-
-enum opp_event {
-       OPP_EVENT_ADD, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE,
-};
-
-#if defined(CONFIG_PM_OPP)
-
-unsigned long opp_get_voltage(struct opp *opp);
-
-unsigned long opp_get_freq(struct opp *opp);
-
-int opp_get_opp_count(struct device *dev);
-
-struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
-                               bool available);
-
-struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq);
-
-struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
-
-int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt);
-
-int opp_enable(struct device *dev, unsigned long freq);
-
-int opp_disable(struct device *dev, unsigned long freq);
-
-struct srcu_notifier_head *opp_get_notifier(struct device *dev);
-#else
-static inline unsigned long opp_get_voltage(struct opp *opp)
-{
-       return 0;
-}
-
-static inline unsigned long opp_get_freq(struct opp *opp)
-{
-       return 0;
-}
-
-static inline int opp_get_opp_count(struct device *dev)
-{
-       return 0;
-}
-
-static inline struct opp *opp_find_freq_exact(struct device *dev,
-                                       unsigned long freq, bool available)
-{
-       return ERR_PTR(-EINVAL);
-}
-
-static inline struct opp *opp_find_freq_floor(struct device *dev,
-                                       unsigned long *freq)
-{
-       return ERR_PTR(-EINVAL);
-}
-
-static inline struct opp *opp_find_freq_ceil(struct device *dev,
-                                       unsigned long *freq)
-{
-       return ERR_PTR(-EINVAL);
-}
-
-static inline int opp_add(struct device *dev, unsigned long freq,
-                                       unsigned long u_volt)
-{
-       return -EINVAL;
-}
-
-static inline int opp_enable(struct device *dev, unsigned long freq)
-{
-       return 0;
-}
-
-static inline int opp_disable(struct device *dev, unsigned long freq)
-{
-       return 0;
-}
-
-static inline struct srcu_notifier_head *opp_get_notifier(struct device *dev)
-{
-       return ERR_PTR(-EINVAL);
-}
-#endif         /* CONFIG_PM_OPP */
-
-#if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
-int of_init_opp_table(struct device *dev);
-#else
-static inline int of_init_opp_table(struct device *dev)
-{
-       return -EINVAL;
-}
-#endif
-
-#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
-int opp_init_cpufreq_table(struct device *dev,
-                           struct cpufreq_frequency_table **table);
-void opp_free_cpufreq_table(struct device *dev,
-                               struct cpufreq_frequency_table **table);
-#else
-static inline int opp_init_cpufreq_table(struct device *dev,
-                           struct cpufreq_frequency_table **table)
-{
-       return -EINVAL;
-}
-
-static inline
-void opp_free_cpufreq_table(struct device *dev,
-                               struct cpufreq_frequency_table **table)
-{
-}
-#endif         /* CONFIG_CPU_FREQ */
-
-#endif         /* __LINUX_OPP_H__ */
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
new file mode 100644 (file)
index 0000000..5151b00
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ *     Nishanth Menon
+ *     Romit Dasgupta
+ *     Kevin Hilman
+ *
+ * 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 __LINUX_OPP_H__
+#define __LINUX_OPP_H__
+
+#include <linux/err.h>
+#include <linux/cpufreq.h>
+#include <linux/notifier.h>
+
+struct dev_pm_opp;
+struct device;
+
+enum dev_pm_opp_event {
+       OPP_EVENT_ADD, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE,
+};
+
+#if defined(CONFIG_PM_OPP)
+
+unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
+
+unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
+
+int dev_pm_opp_get_opp_count(struct device *dev);
+
+struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
+                                             unsigned long freq,
+                                             bool available);
+
+struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
+                                             unsigned long *freq);
+
+struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
+                                            unsigned long *freq);
+
+int dev_pm_opp_add(struct device *dev, unsigned long freq,
+                  unsigned long u_volt);
+
+int dev_pm_opp_enable(struct device *dev, unsigned long freq);
+
+int dev_pm_opp_disable(struct device *dev, unsigned long freq);
+
+struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev);
+#else
+static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
+{
+       return 0;
+}
+
+static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
+{
+       return 0;
+}
+
+static inline int dev_pm_opp_get_opp_count(struct device *dev)
+{
+       return 0;
+}
+
+static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
+                                       unsigned long freq, bool available)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
+                                       unsigned long *freq)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
+                                       unsigned long *freq)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline int dev_pm_opp_add(struct device *dev, unsigned long freq,
+                                       unsigned long u_volt)
+{
+       return -EINVAL;
+}
+
+static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq)
+{
+       return 0;
+}
+
+static inline int dev_pm_opp_disable(struct device *dev, unsigned long freq)
+{
+       return 0;
+}
+
+static inline struct srcu_notifier_head *dev_pm_opp_get_notifier(
+                                                       struct device *dev)
+{
+       return ERR_PTR(-EINVAL);
+}
+#endif         /* CONFIG_PM_OPP */
+
+#if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
+int of_init_opp_table(struct device *dev);
+#else
+static inline int of_init_opp_table(struct device *dev)
+{
+       return -EINVAL;
+}
+#endif
+
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
+int dev_pm_opp_init_cpufreq_table(struct device *dev,
+                           struct cpufreq_frequency_table **table);
+void dev_pm_opp_free_cpufreq_table(struct device *dev,
+                               struct cpufreq_frequency_table **table);
+#else
+static inline int dev_pm_opp_init_cpufreq_table(struct device *dev,
+                           struct cpufreq_frequency_table **table)
+{
+       return -EINVAL;
+}
+
+static inline
+void dev_pm_opp_free_cpufreq_table(struct device *dev,
+                               struct cpufreq_frequency_table **table)
+{
+}
+#endif         /* CONFIG_CPU_FREQ */
+
+#endif         /* __LINUX_OPP_H__ */
diff --git a/include/linux/powercap.h b/include/linux/powercap.h
new file mode 100644 (file)
index 0000000..4e25041
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * powercap.h: Data types and headers for sysfs power capping interface
+ * Copyright (c) 2013, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ */
+
+#ifndef __POWERCAP_H__
+#define __POWERCAP_H__
+
+#include <linux/device.h>
+#include <linux/idr.h>
+
+/*
+ * A power cap class device can contain multiple powercap control_types.
+ * Each control_type can have multiple power zones, which can be independently
+ * controlled. Each power zone can have one or more constraints.
+ */
+
+struct powercap_control_type;
+struct powercap_zone;
+struct powercap_zone_constraint;
+
+/**
+ * struct powercap_control_type_ops - Define control type callbacks
+ * @set_enable:                Enable/Disable whole control type.
+ *                     Default is enabled. But this callback allows all zones
+ *                     to be in disable state and remove any applied power
+ *                     limits. If disabled power zone can only be monitored
+ *                     not controlled.
+ * @get_enable:                get Enable/Disable status.
+ * @release:           Callback to inform that last reference to this
+ *                     control type is closed. So it is safe to free data
+ *                     structure associated with this control type.
+ *                     This callback is mandatory if the client own memory
+ *                     for the control type.
+ *
+ * This structure defines control type callbacks to be implemented by client
+ * drivers
+ */
+struct powercap_control_type_ops {
+       int (*set_enable) (struct powercap_control_type *, bool mode);
+       int (*get_enable) (struct powercap_control_type *, bool *mode);
+       int (*release) (struct powercap_control_type *);
+};
+
+/**
+ * struct powercap_control_type- Defines a powercap control_type
+ * @name:              name of control_type
+ * @dev:               device for this control_type
+ * @idr:               idr to have unique id for its child
+ * @root_node:         Root holding power zones for this control_type
+ * @ops:               Pointer to callback struct
+ * @node_lock:         mutex for control type
+ * @allocated:         This is possible that client owns the memory
+ *                     used by this structure. In this case
+ *                     this flag is set to false by framework to
+ *                     prevent deallocation during release process.
+ *                     Otherwise this flag is set to true.
+ * @ctrl_inst:         link to the control_type list
+ *
+ * Defines powercap control_type. This acts as a container for power
+ * zones, which use same method to control power. E.g. RAPL, RAPL-PCI etc.
+ * All fields are private and should not be used by client drivers.
+ */
+struct powercap_control_type {
+       struct device dev;
+       struct idr idr;
+       int nr_zones;
+       const struct powercap_control_type_ops *ops;
+       struct mutex lock;
+       bool allocated;
+       struct list_head node;
+};
+
+/**
+ * struct powercap_zone_ops - Define power zone callbacks
+ * @get_max_energy_range_uj:   Get maximum range of energy counter in
+ *                             micro-joules.
+ * @get_energy_uj:             Get current energy counter in micro-joules.
+ * @reset_energy_uj:           Reset micro-joules energy counter.
+ * @get_max_power_range_uw:    Get maximum range of power counter in
+ *                             micro-watts.
+ * @get_power_uw:              Get current power counter in micro-watts.
+ * @set_enable:                        Enable/Disable power zone controls.
+ *                             Default is enabled.
+ * @get_enable:                        get Enable/Disable status.
+ * @release:                   Callback to inform that last reference to this
+ *                             control type is closed. So it is safe to free
+ *                             data structure associated with this
+ *                             control type. Mandatory, if client driver owns
+ *                             the power_zone memory.
+ *
+ * This structure defines zone callbacks to be implemented by client drivers.
+ * Client drives can define both energy and power related callbacks. But at
+ * the least one type (either power or energy) is mandatory. Client drivers
+ * should handle mutual exclusion, if required in callbacks.
+ */
+struct powercap_zone_ops {
+       int (*get_max_energy_range_uj) (struct powercap_zone *, u64 *);
+       int (*get_energy_uj) (struct powercap_zone *, u64 *);
+       int (*reset_energy_uj) (struct powercap_zone *);
+       int (*get_max_power_range_uw) (struct powercap_zone *, u64 *);
+       int (*get_power_uw) (struct powercap_zone *, u64 *);
+       int (*set_enable) (struct powercap_zone *, bool mode);
+       int (*get_enable) (struct powercap_zone *, bool *mode);
+       int (*release) (struct powercap_zone *);
+};
+
+#define        POWERCAP_ZONE_MAX_ATTRS         6
+#define        POWERCAP_CONSTRAINTS_ATTRS      8
+#define MAX_CONSTRAINTS_PER_ZONE       10
+/**
+ * struct powercap_zone- Defines instance of a power cap zone
+ * @id:                        Unique id
+ * @name:              Power zone name.
+ * @control_type_inst: Control type instance for this zone.
+ * @ops:               Pointer to the zone operation structure.
+ * @dev:               Instance of a device.
+ * @const_id_cnt:      Number of constraint defined.
+ * @idr:               Instance to an idr entry for children zones.
+ * @parent_idr:                To remove reference from the parent idr.
+ * @private_data:      Private data pointer if any for this zone.
+ * @zone_dev_attrs:    Attributes associated with this device.
+ * @zone_attr_count:   Attribute count.
+ * @dev_zone_attr_group: Attribute group for attributes.
+ * @dev_attr_groups:   Attribute group store to register with device.
+ * @allocated:         This is possible that client owns the memory
+ *                     used by this structure. In this case
+ *                     this flag is set to false by framework to
+ *                     prevent deallocation during release process.
+ *                     Otherwise this flag is set to true.
+ * @constraint_ptr:    List of constraints for this zone.
+ *
+ * This defines a power zone instance. The fields of this structure are
+ * private, and should not be used by client drivers.
+ */
+struct powercap_zone {
+       int id;
+       char *name;
+       void *control_type_inst;
+       const struct powercap_zone_ops *ops;
+       struct device dev;
+       int const_id_cnt;
+       struct idr idr;
+       struct idr *parent_idr;
+       void *private_data;
+       struct attribute **zone_dev_attrs;
+       int zone_attr_count;
+       struct attribute_group dev_zone_attr_group;
+       const struct attribute_group *dev_attr_groups[2]; /* 1 group + NULL */
+       bool allocated;
+       struct powercap_zone_constraint *constraints;
+};
+
+/**
+ * struct powercap_zone_constraint_ops - Define constraint callbacks
+ * @set_power_limit_uw:                Set power limit in micro-watts.
+ * @get_power_limit_uw:                Get power limit in micro-watts.
+ * @set_time_window_us:                Set time window in micro-seconds.
+ * @get_time_window_us:                Get time window in micro-seconds.
+ * @get_max_power_uw:          Get max power allowed in micro-watts.
+ * @get_min_power_uw:          Get min power allowed in micro-watts.
+ * @get_max_time_window_us:    Get max time window allowed in micro-seconds.
+ * @get_min_time_window_us:    Get min time window allowed in micro-seconds.
+ * @get_name:                  Get the name of constraint
+ *
+ * This structure is used to define the constraint callbacks for the client
+ * drivers. The following callbacks are mandatory and can't be NULL:
+ *  set_power_limit_uw
+ *  get_power_limit_uw
+ *  set_time_window_us
+ *  get_time_window_us
+ *  get_name
+ *  Client drivers should handle mutual exclusion, if required in callbacks.
+ */
+struct powercap_zone_constraint_ops {
+       int (*set_power_limit_uw) (struct powercap_zone *, int, u64);
+       int (*get_power_limit_uw) (struct powercap_zone *, int, u64 *);
+       int (*set_time_window_us) (struct powercap_zone *, int, u64);
+       int (*get_time_window_us) (struct powercap_zone *, int, u64 *);
+       int (*get_max_power_uw) (struct powercap_zone *, int, u64 *);
+       int (*get_min_power_uw) (struct powercap_zone *, int, u64 *);
+       int (*get_max_time_window_us) (struct powercap_zone *, int, u64 *);
+       int (*get_min_time_window_us) (struct powercap_zone *, int, u64 *);
+       const char *(*get_name) (struct powercap_zone *, int);
+};
+
+/**
+ * struct powercap_zone_constraint- Defines instance of a constraint
+ * @id:                        Instance Id of this constraint.
+ * @power_zone:                Pointer to the power zone for this constraint.
+ * @ops:               Pointer to the constraint callbacks.
+ *
+ * This defines a constraint instance.
+ */
+struct powercap_zone_constraint {
+       int id;
+       struct powercap_zone *power_zone;
+       struct powercap_zone_constraint_ops *ops;
+};
+
+
+/* For clients to get their device pointer, may be used for dev_dbgs */
+#define POWERCAP_GET_DEV(power_zone)   (&power_zone->dev)
+
+/**
+* powercap_set_zone_data() - Set private data for a zone
+* @power_zone: A pointer to the valid zone instance.
+* @pdata:      A pointer to the user private data.
+*
+* Allows client drivers to associate some private data to zone instance.
+*/
+static inline void powercap_set_zone_data(struct powercap_zone *power_zone,
+                                               void *pdata)
+{
+       if (power_zone)
+               power_zone->private_data = pdata;
+}
+
+/**
+* powercap_get_zone_data() - Get private data for a zone
+* @power_zone: A pointer to the valid zone instance.
+*
+* Allows client drivers to get private data associate with a zone,
+* using call to powercap_set_zone_data.
+*/
+static inline void *powercap_get_zone_data(struct powercap_zone *power_zone)
+{
+       if (power_zone)
+               return power_zone->private_data;
+       return NULL;
+}
+
+/**
+* powercap_register_control_type() - Register a control_type with framework
+* @control_type:       Pointer to client allocated memory for the control type
+*                      structure storage. If this is NULL, powercap framework
+*                      will allocate memory and own it.
+*                      Advantage of this parameter is that client can embed
+*                      this data in its data structures and allocate in a
+*                      single call, preventing multiple allocations.
+* @control_type_name:  The Name of this control_type, which will be shown
+*                      in the sysfs Interface.
+* @ops:                        Callbacks for control type. This parameter is optional.
+*
+* Used to create a control_type with the power capping class. Here control_type
+* can represent a type of technology, which can control a range of power zones.
+* For example a control_type can be RAPL (Running Average Power Limit)
+* Intel® 64 and IA-32 Processor Architectures. The name can be any string
+* which must be unique, otherwise this function returns NULL.
+* A pointer to the control_type instance is returned on success.
+*/
+struct powercap_control_type *powercap_register_control_type(
+                               struct powercap_control_type *control_type,
+                               const char *name,
+                               const struct powercap_control_type_ops *ops);
+
+/**
+* powercap_unregister_control_type() - Unregister a control_type from framework
+* @instance:   A pointer to the valid control_type instance.
+*
+* Used to unregister a control_type with the power capping class.
+* All power zones registered under this control type have to be unregistered
+* before calling this function, or it will fail with an error code.
+*/
+int powercap_unregister_control_type(struct powercap_control_type *instance);
+
+/* Zone register/unregister API */
+
+/**
+* powercap_register_zone() - Register a power zone
+* @power_zone: Pointer to client allocated memory for the power zone structure
+*              storage. If this is NULL, powercap framework will allocate
+*              memory and own it. Advantage of this parameter is that client
+*              can embed this data in its data structures and allocate in a
+*              single call, preventing multiple allocations.
+* @control_type: A control_type instance under which this zone operates.
+* @name:       A name for this zone.
+* @parent:     A pointer to the parent power zone instance if any or NULL
+* @ops:                Pointer to zone operation callback structure.
+* @no_constraints: Number of constraints for this zone
+* @const_ops:  Pointer to constraint callback structure
+*
+* Register a power zone under a given control type. A power zone must register
+* a pointer to a structure representing zone callbacks.
+* A power zone can be located under a parent power zone, in which case @parent
+* should point to it.  Otherwise, if @parent is NULL, the new power zone will
+* be located directly under the given control type
+* For each power zone there may be a number of constraints that appear in the
+* sysfs under that zone as attributes with unique numeric IDs.
+* Returns pointer to the power_zone on success.
+*/
+struct powercap_zone *powercap_register_zone(
+                       struct powercap_zone *power_zone,
+                       struct powercap_control_type *control_type,
+                       const char *name,
+                       struct powercap_zone *parent,
+                       const struct powercap_zone_ops *ops,
+                       int nr_constraints,
+                       struct powercap_zone_constraint_ops *const_ops);
+
+/**
+* powercap_unregister_zone() - Unregister a zone device
+* @control_type:       A pointer to the valid instance of a control_type.
+* @power_zone: A pointer to the valid zone instance for a control_type
+*
+* Used to unregister a zone device for a control_type.  Caller should
+* make sure that children for this zone are unregistered first.
+*/
+int powercap_unregister_zone(struct powercap_control_type *control_type,
+                               struct powercap_zone *power_zone);
+
+#endif
index 6682da36b293cfad598a0c5803e9e32038f72aa3..e27baeeda3f470ed99ae899d8de22da062856bf8 100644 (file)
@@ -1394,11 +1394,10 @@ struct task_struct {
        } memcg_batch;
        unsigned int memcg_kmem_skip_account;
        struct memcg_oom_info {
+               struct mem_cgroup *memcg;
+               gfp_t gfp_mask;
+               int order;
                unsigned int may_oom:1;
-               unsigned int in_memcg_oom:1;
-               unsigned int oom_locked:1;
-               int wakeups;
-               struct mem_cgroup *wait_on_memcg;
        } memcg_oom;
 #endif
 #ifdef CONFIG_UPROBES
diff --git a/include/linux/tc_act/tc_defact.h b/include/linux/tc_act/tc_defact.h
deleted file mode 100644 (file)
index 6f65d07..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __LINUX_TC_DEF_H
-#define __LINUX_TC_DEF_H
-
-#include <linux/pkt_cls.h>
-
-struct tc_defact {
-       tc_gen;
-};
-                                                                                
-enum {
-       TCA_DEF_UNSPEC,
-       TCA_DEF_TM,
-       TCA_DEF_PARMS,
-       TCA_DEF_DATA,
-       __TCA_DEF_MAX
-};
-#define TCA_DEF_MAX (__TCA_DEF_MAX - 1)
-
-#endif
index f9a7e7bc925be61322a24304076503bd918a520a..11d85b9c1b081af6a9f4f30ac3c1458766ed4238 100644 (file)
@@ -12,7 +12,7 @@ struct usb_phy_gen_xceiv_platform_data {
        unsigned int needs_reset:1;
 };
 
-#if IS_ENABLED(CONFIG_NOP_USB_XCEIV)
+#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
 /* sometimes transceivers are accessed only through e.g. ULPI */
 extern void usb_nop_xceiv_register(void);
 extern void usb_nop_xceiv_unregister(void);
index bf99cd01be206ebeb170d826e176c3ac22e1493e..630356866030d88a355390a932105ff9c86b98bb 100644 (file)
@@ -66,7 +66,9 @@
        US_FLAG(INITIAL_READ10, 0x00100000)                     \
                /* Initial READ(10) (and others) must be retried */     \
        US_FLAG(WRITE_CACHE,    0x00200000)                     \
-               /* Write Cache status is not available */
+               /* Write Cache status is not available */       \
+       US_FLAG(NEEDS_CAP16,    0x00400000)
+               /* cannot handle READ_CAPACITY_10 */
 
 #define US_FLAG(name, value)   US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
index 7fe28228b2742efc0c9eb69c7bbc866f0194ef19..512cdc2fb80f40f99bb1b09fe1d0d4dcfeab345c 100644 (file)
@@ -77,6 +77,6 @@ struct yamdrv_ioctl_cfg {
 
 struct yamdrv_ioctl_mcs {
        int cmd;
-       int bitrate;
+       unsigned int bitrate;
        unsigned char bits[YAM_FPGA_SIZE];
 };
index a7a683e30b64e6beb2bc87907c85576d85385007..a8c2ef6d3b932abbb42e28be158d472effd02513 100644 (file)
@@ -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:
index 3bc4865f82679137077db4dd82c177bd39b51515..3c4c944096c9e5133695a415b530c80908980f39 100644 (file)
@@ -479,10 +479,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 */
index f525e7038cca4eaae4fd7b011ae1f97072ddffc9..2b786b7e35850fe4b4b147a8a0cdcf0b010d2cb9 100644 (file)
@@ -194,11 +194,9 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
               skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
 }
 
-static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, struct in6_addr *dest)
+static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt)
 {
-       if (rt->rt6i_flags & RTF_GATEWAY)
-               return &rt->rt6i_gateway;
-       return dest;
+       return &rt->rt6i_gateway;
 }
 
 #endif
index d0d11df9cba1ca3b4f8196071f8a0beed8b32f25..807d6b7a943fecab78db1afd6b57ee33b70ded72 100644 (file)
@@ -133,7 +133,7 @@ struct ieee802154_ops {
 
 /* Basic interface to register ieee802154 device */
 struct ieee802154_dev *
-ieee802154_alloc_device(size_t priv_data_lex, struct ieee802154_ops *ops);
+ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops);
 void ieee802154_free_device(struct ieee802154_dev *dev);
 int ieee802154_register_device(struct ieee802154_dev *dev);
 void ieee802154_unregister_device(struct ieee802154_dev *dev);
index 1d37a8086bed53575fedc30b9c1db750d4cd2822..808cbc2ec6c1b38ea82198d2171079863377777d 100644 (file)
@@ -1630,16 +1630,14 @@ static inline void sk_filter_release(struct sk_filter *fp)
 
 static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
 {
-       unsigned int size = sk_filter_len(fp);
-
-       atomic_sub(size, &sk->sk_omem_alloc);
+       atomic_sub(sk_filter_size(fp->len), &sk->sk_omem_alloc);
        sk_filter_release(fp);
 }
 
 static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
 {
        atomic_inc(&fp->refcnt);
-       atomic_add(sk_filter_len(fp), &sk->sk_omem_alloc);
+       atomic_add(sk_filter_size(fp->len), &sk->sk_omem_alloc);
 }
 
 /*
index fe66533e9b7a51ef143acd33ff398bee47f71398..fb0a312bcb810c93622028ef93934d3779189142 100644 (file)
@@ -68,6 +68,7 @@ struct rsnd_scu_platform_info {
  *
  * A : generation
  */
+#define RSND_GEN_MASK  (0xF << 0)
 #define RSND_GEN1      (1 << 0) /* fixme */
 #define RSND_GEN2      (2 << 0) /* fixme */
 
index aef8fc3540254c8796015d016a8e326eb71ed054..da9cc0f05c93843e713923fc1b5d063e7d444cae 100644 (file)
@@ -144,7 +144,7 @@ TRACE_EVENT(target_sequencer_start,
        ),
 
        TP_fast_assign(
-               __entry->unpacked_lun   = cmd->se_lun->unpacked_lun;
+               __entry->unpacked_lun   = cmd->orig_fe_lun;
                __entry->opcode         = cmd->t_task_cdb[0];
                __entry->data_length    = cmd->data_length;
                __entry->task_attribute = cmd->sam_task_attr;
@@ -182,7 +182,7 @@ TRACE_EVENT(target_cmd_complete,
        ),
 
        TP_fast_assign(
-               __entry->unpacked_lun   = cmd->se_lun->unpacked_lun;
+               __entry->unpacked_lun   = cmd->orig_fe_lun;
                __entry->opcode         = cmd->t_task_cdb[0];
                __entry->data_length    = cmd->data_length;
                __entry->task_attribute = cmd->sam_task_attr;
index 550811712f78c71aad43b4a531b07e1df536b64f..28acbaf4a81ec091a54740c54adfd57ec2f9ad59 100644 (file)
@@ -223,6 +223,8 @@ struct drm_mode_get_connector {
        __u32 connection;
        __u32 mm_width, mm_height; /**< HxW in millimeters */
        __u32 subpixel;
+
+       __u32 pad;
 };
 
 #define DRM_MODE_PROP_PENDING  (1<<0)
index 0623ec4e728f09550fd8c5e0e464f4a771265bdb..56f121605c998c28e8a173067e94e24ec7d9c653 100644 (file)
@@ -1,5 +1,6 @@
 # UAPI Header export list
 header-y += tc_csum.h
+header-y += tc_defact.h
 header-y += tc_gact.h
 header-y += tc_ipt.h
 header-y += tc_mirred.h
diff --git a/include/uapi/linux/tc_act/tc_defact.h b/include/uapi/linux/tc_act/tc_defact.h
new file mode 100644 (file)
index 0000000..17dddb4
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __LINUX_TC_DEF_H
+#define __LINUX_TC_DEF_H
+
+#include <linux/pkt_cls.h>
+
+struct tc_defact {
+       tc_gen;
+};
+
+enum {
+       TCA_DEF_UNSPEC,
+       TCA_DEF_TM,
+       TCA_DEF_PARMS,
+       TCA_DEF_DATA,
+       __TCA_DEF_MAX
+};
+#define TCA_DEF_MAX (__TCA_DEF_MAX - 1)
+
+#endif
index 0b233c56b0e402ef75f691b5dcf6c6f1cc87a01b..e3ddd86c90a68610a20625729a99cf8effea8f31 100644 (file)
@@ -87,8 +87,10 @@ enum {
        IB_USER_VERBS_CMD_CLOSE_XRCD,
        IB_USER_VERBS_CMD_CREATE_XSRQ,
        IB_USER_VERBS_CMD_OPEN_QP,
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
        IB_USER_VERBS_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD,
        IB_USER_VERBS_CMD_DESTROY_FLOW
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 };
 
 /*
@@ -126,6 +128,7 @@ struct ib_uverbs_cmd_hdr {
        __u16 out_words;
 };
 
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 struct ib_uverbs_cmd_hdr_ex {
        __u32 command;
        __u16 in_words;
@@ -134,6 +137,7 @@ struct ib_uverbs_cmd_hdr_ex {
        __u16 provider_out_words;
        __u32 cmd_hdr_reserved;
 };
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 
 struct ib_uverbs_get_context {
        __u64 response;
@@ -696,6 +700,7 @@ struct ib_uverbs_detach_mcast {
        __u64 driver_data[0];
 };
 
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 struct ib_kern_eth_filter {
        __u8  dst_mac[6];
        __u8  src_mac[6];
@@ -780,6 +785,7 @@ struct ib_uverbs_destroy_flow  {
        __u32 comp_mask;
        __u32 flow_handle;
 };
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 
 struct ib_uverbs_create_srq {
        __u64 response;
index 8c4f59b0204a2821811a4b28fd48e0ce6163d987..db9d241af133d770cb0a95a22cacf257f79b1215 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1282,6 +1282,12 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
 
        sem_lock(sma, NULL, -1);
 
+       if (sma->sem_perm.deleted) {
+               sem_unlock(sma, -1);
+               rcu_read_unlock();
+               return -EIDRM;
+       }
+
        curr = &sma->sem_base[semnum];
 
        ipc_assert_locked_object(&sma->sem_perm);
@@ -1336,12 +1342,14 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                int i;
 
                sem_lock(sma, NULL, -1);
+               if (sma->sem_perm.deleted) {
+                       err = -EIDRM;
+                       goto out_unlock;
+               }
                if(nsems > SEMMSL_FAST) {
                        if (!ipc_rcu_getref(sma)) {
-                               sem_unlock(sma, -1);
-                               rcu_read_unlock();
                                err = -EIDRM;
-                               goto out_free;
+                               goto out_unlock;
                        }
                        sem_unlock(sma, -1);
                        rcu_read_unlock();
@@ -1354,10 +1362,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                        rcu_read_lock();
                        sem_lock_and_putref(sma);
                        if (sma->sem_perm.deleted) {
-                               sem_unlock(sma, -1);
-                               rcu_read_unlock();
                                err = -EIDRM;
-                               goto out_free;
+                               goto out_unlock;
                        }
                }
                for (i = 0; i < sma->sem_nsems; i++)
@@ -1375,8 +1381,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                struct sem_undo *un;
 
                if (!ipc_rcu_getref(sma)) {
-                       rcu_read_unlock();
-                       return -EIDRM;
+                       err = -EIDRM;
+                       goto out_rcu_wakeup;
                }
                rcu_read_unlock();
 
@@ -1404,10 +1410,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                rcu_read_lock();
                sem_lock_and_putref(sma);
                if (sma->sem_perm.deleted) {
-                       sem_unlock(sma, -1);
-                       rcu_read_unlock();
                        err = -EIDRM;
-                       goto out_free;
+                       goto out_unlock;
                }
 
                for (i = 0; i < nsems; i++)
@@ -1431,6 +1435,10 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                goto out_rcu_wakeup;
 
        sem_lock(sma, NULL, -1);
+       if (sma->sem_perm.deleted) {
+               err = -EIDRM;
+               goto out_unlock;
+       }
        curr = &sma->sem_base[semnum];
 
        switch (cmd) {
@@ -1836,6 +1844,10 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
        if (error)
                goto out_rcu_wakeup;
 
+       error = -EIDRM;
+       locknum = sem_lock(sma, sops, nsops);
+       if (sma->sem_perm.deleted)
+               goto out_unlock_free;
        /*
         * semid identifiers are not unique - find_alloc_undo may have
         * allocated an undo structure, it was invalidated by an RMID
@@ -1843,8 +1855,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
         * This case can be detected checking un->semid. The existence of
         * "un" itself is guaranteed by rcu.
         */
-       error = -EIDRM;
-       locknum = sem_lock(sma, sops, nsops);
        if (un && un->semid == -1)
                goto out_unlock_free;
 
@@ -2057,6 +2067,12 @@ void exit_sem(struct task_struct *tsk)
                }
 
                sem_lock(sma, NULL, -1);
+               /* exit_sem raced with IPC_RMID, nothing to do */
+               if (sma->sem_perm.deleted) {
+                       sem_unlock(sma, -1);
+                       rcu_read_unlock();
+                       continue;
+               }
                un = __lookup_undo(ulp, semid);
                if (un == NULL) {
                        /* exit_sem raced with IPC_RMID+semget() that created
index fdb8ae7407755f9b1c3725e2a7fd38a8a31c7f54..7684f41bce76a9b430f04b7e4e77810b48798a42 100644 (file)
  *            Pavel Emelianov <xemul@openvz.org>
  *
  * General sysv ipc locking scheme:
- *  when doing ipc id lookups, take the ids->rwsem
- *      rcu_read_lock()
- *          obtain the ipc object (kern_ipc_perm)
- *          perform security, capabilities, auditing and permission checks, etc.
- *          acquire the ipc lock (kern_ipc_perm.lock) throught ipc_lock_object()
- *             perform data updates (ie: SET, RMID, LOCK/UNLOCK commands)
+ *     rcu_read_lock()
+ *          obtain the ipc object (kern_ipc_perm) by looking up the id in an idr
+ *         tree.
+ *         - perform initial checks (capabilities, auditing and permission,
+ *           etc).
+ *         - perform read-only operations, such as STAT, INFO commands.
+ *           acquire the ipc lock (kern_ipc_perm.lock) through
+ *           ipc_lock_object()
+ *             - perform data updates, such as SET, RMID commands and
+ *               mechanism-specific operations (semop/semtimedop,
+ *               msgsnd/msgrcv, shmat/shmdt).
+ *         drop the ipc lock, through ipc_unlock_object().
+ *     rcu_read_unlock()
+ *
+ *  The ids->rwsem must be taken when:
+ *     - creating, removing and iterating the existing entries in ipc
+ *       identifier sets.
+ *     - iterating through files under /proc/sysvipc/
+ *
+ *  Note that sems have a special fast path that avoids kern_ipc_perm.lock -
+ *  see sem_lock().
  */
 
 #include <linux/mm.h>
index 2418b6e71a854e187573ec12746481ce863e721a..8bd9cfdc70d7bc020dbc19a05813e2e49443b8e8 100644 (file)
@@ -2039,7 +2039,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
 
                /* @tsk either already exited or can't exit until the end */
                if (tsk->flags & PF_EXITING)
-                       continue;
+                       goto next;
 
                /* as per above, nr_threads may decrease, but not increase. */
                BUG_ON(i >= group_size);
@@ -2047,7 +2047,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
                ent.cgrp = task_cgroup_from_root(tsk, root);
                /* nothing to do if this task is already in the cgroup */
                if (ent.cgrp == cgrp)
-                       continue;
+                       goto next;
                /*
                 * saying GFP_ATOMIC has no effect here because we did prealloc
                 * earlier, but it's good form to communicate our expectations.
@@ -2055,7 +2055,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
                retval = flex_array_put(group, i, &ent, GFP_ATOMIC);
                BUG_ON(retval != 0);
                i++;
-
+       next:
                if (!threadgroup)
                        break;
        } while_each_thread(leader, tsk);
@@ -3188,11 +3188,9 @@ css_next_descendant_post(struct cgroup_subsys_state *pos,
 
        WARN_ON_ONCE(!rcu_read_lock_held());
 
-       /* if first iteration, visit the leftmost descendant */
-       if (!pos) {
-               next = css_leftmost_descendant(root);
-               return next != root ? next : NULL;
-       }
+       /* if first iteration, visit leftmost descendant which may be @root */
+       if (!pos)
+               return css_leftmost_descendant(root);
 
        /* if we visited @root, we're done */
        if (pos == root)
index d49a9d29334cc4d67c24bad9814221a0371a6350..953c14348375a6d440a904ec7d7e0d3e70d1d767 100644 (file)
@@ -6767,6 +6767,10 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
        if (ret)
                return -EFAULT;
 
+       /* disabled for now */
+       if (attr->mmap2)
+               return -EINVAL;
+
        if (attr->__reserved_1)
                return -EINVAL;
 
index 6d647aedffea494dec6b11d20fa222a05fd49f7f..d24105b1b794e635e93509c04e0ac6edb85cc7f5 100644 (file)
@@ -410,7 +410,7 @@ ww_mutex_set_context_fastpath(struct ww_mutex *lock,
 static __always_inline int __sched
 __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                    struct lockdep_map *nest_lock, unsigned long ip,
-                   struct ww_acquire_ctx *ww_ctx)
+                   struct ww_acquire_ctx *ww_ctx, const bool use_ww_ctx)
 {
        struct task_struct *task = current;
        struct mutex_waiter waiter;
@@ -450,7 +450,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                struct task_struct *owner;
                struct mspin_node  node;
 
-               if (!__builtin_constant_p(ww_ctx == NULL) && ww_ctx->acquired > 0) {
+               if (use_ww_ctx && ww_ctx->acquired > 0) {
                        struct ww_mutex *ww;
 
                        ww = container_of(lock, struct ww_mutex, base);
@@ -480,7 +480,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                if ((atomic_read(&lock->count) == 1) &&
                    (atomic_cmpxchg(&lock->count, 1, 0) == 1)) {
                        lock_acquired(&lock->dep_map, ip);
-                       if (!__builtin_constant_p(ww_ctx == NULL)) {
+                       if (use_ww_ctx) {
                                struct ww_mutex *ww;
                                ww = container_of(lock, struct ww_mutex, base);
 
@@ -551,7 +551,7 @@ slowpath:
                        goto err;
                }
 
-               if (!__builtin_constant_p(ww_ctx == NULL) && ww_ctx->acquired > 0) {
+               if (use_ww_ctx && ww_ctx->acquired > 0) {
                        ret = __mutex_lock_check_stamp(lock, ww_ctx);
                        if (ret)
                                goto err;
@@ -575,7 +575,7 @@ skip_wait:
        lock_acquired(&lock->dep_map, ip);
        mutex_set_owner(lock);
 
-       if (!__builtin_constant_p(ww_ctx == NULL)) {
+       if (use_ww_ctx) {
                struct ww_mutex *ww = container_of(lock, struct ww_mutex, base);
                struct mutex_waiter *cur;
 
@@ -615,7 +615,7 @@ mutex_lock_nested(struct mutex *lock, unsigned int subclass)
 {
        might_sleep();
        __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE,
-                           subclass, NULL, _RET_IP_, NULL);
+                           subclass, NULL, _RET_IP_, NULL, 0);
 }
 
 EXPORT_SYMBOL_GPL(mutex_lock_nested);
@@ -625,7 +625,7 @@ _mutex_lock_nest_lock(struct mutex *lock, struct lockdep_map *nest)
 {
        might_sleep();
        __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE,
-                           0, nest, _RET_IP_, NULL);
+                           0, nest, _RET_IP_, NULL, 0);
 }
 
 EXPORT_SYMBOL_GPL(_mutex_lock_nest_lock);
@@ -635,7 +635,7 @@ mutex_lock_killable_nested(struct mutex *lock, unsigned int subclass)
 {
        might_sleep();
        return __mutex_lock_common(lock, TASK_KILLABLE,
-                                  subclass, NULL, _RET_IP_, NULL);
+                                  subclass, NULL, _RET_IP_, NULL, 0);
 }
 EXPORT_SYMBOL_GPL(mutex_lock_killable_nested);
 
@@ -644,7 +644,7 @@ mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass)
 {
        might_sleep();
        return __mutex_lock_common(lock, TASK_INTERRUPTIBLE,
-                                  subclass, NULL, _RET_IP_, NULL);
+                                  subclass, NULL, _RET_IP_, NULL, 0);
 }
 
 EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested);
@@ -682,7 +682,7 @@ __ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
 
        might_sleep();
        ret =  __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE,
-                                  0, &ctx->dep_map, _RET_IP_, ctx);
+                                  0, &ctx->dep_map, _RET_IP_, ctx, 1);
        if (!ret && ctx->acquired > 1)
                return ww_mutex_deadlock_injection(lock, ctx);
 
@@ -697,7 +697,7 @@ __ww_mutex_lock_interruptible(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
 
        might_sleep();
        ret = __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE,
-                                 0, &ctx->dep_map, _RET_IP_, ctx);
+                                 0, &ctx->dep_map, _RET_IP_, ctx, 1);
 
        if (!ret && ctx->acquired > 1)
                return ww_mutex_deadlock_injection(lock, ctx);
@@ -809,28 +809,28 @@ __mutex_lock_slowpath(atomic_t *lock_count)
        struct mutex *lock = container_of(lock_count, struct mutex, count);
 
        __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0,
-                           NULL, _RET_IP_, NULL);
+                           NULL, _RET_IP_, NULL, 0);
 }
 
 static noinline int __sched
 __mutex_lock_killable_slowpath(struct mutex *lock)
 {
        return __mutex_lock_common(lock, TASK_KILLABLE, 0,
-                                  NULL, _RET_IP_, NULL);
+                                  NULL, _RET_IP_, NULL, 0);
 }
 
 static noinline int __sched
 __mutex_lock_interruptible_slowpath(struct mutex *lock)
 {
        return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, 0,
-                                  NULL, _RET_IP_, NULL);
+                                  NULL, _RET_IP_, NULL, 0);
 }
 
 static noinline int __sched
 __ww_mutex_lock_slowpath(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
 {
        return __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE, 0,
-                                  NULL, _RET_IP_, ctx);
+                                  NULL, _RET_IP_, ctx, 1);
 }
 
 static noinline int __sched
@@ -838,7 +838,7 @@ __ww_mutex_lock_interruptible_slowpath(struct ww_mutex *lock,
                                            struct ww_acquire_ctx *ctx)
 {
        return __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE, 0,
-                                  NULL, _RET_IP_, ctx);
+                                  NULL, _RET_IP_, ctx, 1);
 }
 
 #endif
index d444c4e834f4526ec318f71b1076a02c909e34a8..2fac9cc79b3da6183dd56f5e3469a7de54d4167e 100644 (file)
@@ -178,6 +178,22 @@ config PM_SLEEP_DEBUG
        def_bool y
        depends on PM_DEBUG && PM_SLEEP
 
+config DPM_WATCHDOG
+       bool "Device suspend/resume watchdog"
+       depends on PM_DEBUG && PSTORE
+       ---help---
+         Sets up a watchdog timer to capture drivers that are
+         locked up attempting to suspend/resume a device.
+         A detected lockup causes system panic with message
+         captured in pstore device for inspection in subsequent
+         boot session.
+
+config DPM_WATCHDOG_TIMEOUT
+       int "Watchdog timeout in seconds"
+       range 1 120
+       default 12
+       depends on DPM_WATCHDOG
+
 config PM_TRACE
        bool
        help
index c9c759d5a15cbd53831bdf7552dc455a64a40b5b..0121dab83f43d82ddfb620f7423d6c9728f8b01b 100644 (file)
@@ -846,7 +846,7 @@ static int software_resume(void)
        goto Finish;
 }
 
-late_initcall(software_resume);
+late_initcall_sync(software_resume);
 
 
 static const char * const hibernation_modes[] = {
index a394297f8b2f94ea806a545c6e92e4b7221d2f7e..8dff9b48075af3f61eeab3531b3ad706b88718e4 100644 (file)
@@ -558,30 +558,12 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
        if (count == sizeof(s32)) {
                if (copy_from_user(&value, buf, sizeof(s32)))
                        return -EFAULT;
-       } else if (count <= 11) { /* ASCII perhaps? */
-               char ascii_value[11];
-               unsigned long int ulval;
+       } else {
                int ret;
 
-               if (copy_from_user(ascii_value, buf, count))
-                       return -EFAULT;
-
-               if (count > 10) {
-                       if (ascii_value[10] == '\n')
-                               ascii_value[10] = '\0';
-                       else
-                               return -EINVAL;
-               } else {
-                       ascii_value[count] = '\0';
-               }
-               ret = kstrtoul(ascii_value, 16, &ulval);
-               if (ret) {
-                       pr_debug("%s, 0x%lx, 0x%x\n", ascii_value, ulval, ret);
-                       return -EINVAL;
-               }
-               value = (s32)lower_32_bits(ulval);
-       } else {
-               return -EINVAL;
+               ret = kstrtos32_from_user(buf, count, 16, &value);
+               if (ret)
+                       return ret;
        }
 
        req = filp->private_data;
index 98c3b34a4cffcedeae812de0ddc947f874cef839..10c22cae83a035e43eb54a79272fd1e6ae2fc757 100644 (file)
@@ -1402,7 +1402,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. */
index 957f06164ad1004b0050dbdcb7563c91c3755e55..24850270c8024948d60c0f827457b18d2de2d9a7 100644 (file)
@@ -36,9 +36,9 @@ static struct snapshot_data {
        struct snapshot_handle handle;
        int swap;
        int mode;
-       char frozen;
-       char ready;
-       char platform_support;
+       bool frozen;
+       bool ready;
+       bool platform_support;
        bool free_bitmaps;
 } snapshot_state;
 
@@ -93,9 +93,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
        if (error)
                atomic_inc(&snapshot_device_available);
 
-       data->frozen = 0;
-       data->ready = 0;
-       data->platform_support = 0;
+       data->frozen = false;
+       data->ready = false;
+       data->platform_support = false;
 
  Unlock:
        unlock_system_sleep();
@@ -229,7 +229,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                if (error)
                        thaw_processes();
                else
-                       data->frozen = 1;
+                       data->frozen = true;
 
                break;
 
@@ -240,7 +240,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                free_basic_memory_bitmaps();
                data->free_bitmaps = false;
                thaw_processes();
-               data->frozen = 0;
+               data->frozen = false;
                break;
 
        case SNAPSHOT_CREATE_IMAGE:
@@ -270,7 +270,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
        case SNAPSHOT_FREE:
                swsusp_free();
                memset(&data->handle, 0, sizeof(struct snapshot_handle));
-               data->ready = 0;
+               data->ready = false;
                /*
                 * It is necessary to thaw kernel threads here, because
                 * SNAPSHOT_CREATE_IMAGE may be invoked directly after
@@ -334,7 +334,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                 * PM_HIBERNATION_PREPARE
                 */
                error = suspend_devices_and_enter(PM_SUSPEND_MEM);
-               data->ready = 0;
+               data->ready = false;
                break;
 
        case SNAPSHOT_PLATFORM_SUPPORT:
index 38959c86678987d0306548b73c03b9413c68b321..662c5798a685d77904fcc1080596e4e4bd5d34b3 100644 (file)
@@ -33,29 +33,64 @@ struct ce_unbind {
        int res;
 };
 
-/**
- * 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);
 
@@ -380,8 +415,8 @@ void clockevents_config(struct clock_event_device *dev, u32 freq)
                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);
 }
 
 /**
index 7deeb6297a483d7272acb30c4f3b0c0d6b0e76b3..1a53d497a8c53ae460686af6107531c4161eae53 100644 (file)
@@ -53,6 +53,7 @@ int percpu_ref_init(struct percpu_ref *ref, percpu_ref_func_t *release)
        ref->release = release;
        return 0;
 }
+EXPORT_SYMBOL_GPL(percpu_ref_init);
 
 /**
  * percpu_ref_cancel_init - cancel percpu_ref_init()
@@ -84,6 +85,7 @@ void percpu_ref_cancel_init(struct percpu_ref *ref)
                free_percpu(ref->pcpu_count);
        }
 }
+EXPORT_SYMBOL_GPL(percpu_ref_cancel_init);
 
 static void percpu_ref_kill_rcu(struct rcu_head *rcu)
 {
@@ -156,3 +158,4 @@ void percpu_ref_kill_and_confirm(struct percpu_ref *ref,
 
        call_rcu_sched(&ref->rcu, percpu_ref_kill_rcu);
 }
+EXPORT_SYMBOL_GPL(percpu_ref_kill_and_confirm);
index 1e6aec4a2d2ebae29c0fea0405a7e81f422beeb4..ae4846ff48494e9ac5e733a5d5339b61763a49f5 100644 (file)
@@ -1616,7 +1616,6 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        struct inode *inode = mapping->host;
        pgoff_t offset = vmf->pgoff;
        struct page *page;
-       bool memcg_oom;
        pgoff_t size;
        int ret = 0;
 
@@ -1625,11 +1624,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                return VM_FAULT_SIGBUS;
 
        /*
-        * Do we have something in the page cache already?  Either
-        * way, try readahead, but disable the memcg OOM killer for it
-        * as readahead is optional and no errors are propagated up
-        * the fault stack.  The OOM killer is enabled while trying to
-        * instantiate the faulting page individually below.
+        * Do we have something in the page cache already?
         */
        page = find_get_page(mapping, offset);
        if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) {
@@ -1637,14 +1632,10 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                 * We found the page, so try async readahead before
                 * waiting for the lock.
                 */
-               memcg_oom = mem_cgroup_toggle_oom(false);
                do_async_mmap_readahead(vma, ra, file, page, offset);
-               mem_cgroup_toggle_oom(memcg_oom);
        } else if (!page) {
                /* No page in the page cache at all */
-               memcg_oom = mem_cgroup_toggle_oom(false);
                do_sync_mmap_readahead(vma, ra, file, offset);
-               mem_cgroup_toggle_oom(memcg_oom);
                count_vm_event(PGMAJFAULT);
                mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
                ret = VM_FAULT_MAJOR;
index 7489884682d84a6b5840fef19e90234076fd374e..610e3df2768a6a5b2ec1e293da4c96dafbbe2d30 100644 (file)
@@ -2697,6 +2697,7 @@ void __split_huge_page_pmd(struct vm_area_struct *vma, unsigned long address,
 
        mmun_start = haddr;
        mmun_end   = haddr + HPAGE_PMD_SIZE;
+again:
        mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
        spin_lock(&mm->page_table_lock);
        if (unlikely(!pmd_trans_huge(*pmd))) {
@@ -2719,7 +2720,14 @@ void __split_huge_page_pmd(struct vm_area_struct *vma, unsigned long address,
        split_huge_page(page);
 
        put_page(page);
-       BUG_ON(pmd_trans_huge(*pmd));
+
+       /*
+        * We don't always have down_write of mmap_sem here: a racing
+        * do_huge_pmd_wp_page() might have copied-on-write to another
+        * huge page before our split_huge_page() got the anon_vma lock.
+        */
+       if (unlikely(pmd_trans_huge(*pmd)))
+               goto again;
 }
 
 void split_huge_page_pmd_mm(struct mm_struct *mm, unsigned long address,
index b49579c7f2a550462c334f97907f2fc131a65e00..0b7656e804d126cf0fcfa04a8b427396af86deb1 100644 (file)
@@ -653,6 +653,7 @@ static void free_huge_page(struct page *page)
        BUG_ON(page_count(page));
        BUG_ON(page_mapcount(page));
        restore_reserve = PagePrivate(page);
+       ClearPagePrivate(page);
 
        spin_lock(&hugetlb_lock);
        hugetlb_cgroup_uncharge_page(hstate_index(h),
@@ -695,8 +696,22 @@ static void prep_compound_gigantic_page(struct page *page, unsigned long order)
        /* we rely on prep_new_huge_page to set the destructor */
        set_compound_order(page, order);
        __SetPageHead(page);
+       __ClearPageReserved(page);
        for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) {
                __SetPageTail(p);
+               /*
+                * For gigantic hugepages allocated through bootmem at
+                * boot, it's safer to be consistent with the not-gigantic
+                * hugepages and clear the PG_reserved bit from all tail pages
+                * too.  Otherwse drivers using get_user_pages() to access tail
+                * pages may get the reference counting wrong if they see
+                * PG_reserved set on a tail page (despite the head page not
+                * having PG_reserved set).  Enforcing this consistency between
+                * head and tail pages allows drivers to optimize away a check
+                * on the head page when they need know if put_page() is needed
+                * after get_user_pages().
+                */
+               __ClearPageReserved(p);
                set_page_count(p, 0);
                p->first_page = page;
        }
@@ -1329,9 +1344,9 @@ static void __init gather_bootmem_prealloc(void)
 #else
                page = virt_to_page(m);
 #endif
-               __ClearPageReserved(page);
                WARN_ON(page_count(page) != 1);
                prep_compound_huge_page(page, h->order);
+               WARN_ON(PageReserved(page));
                prep_new_huge_page(h, page, page_to_nid(page));
                /*
                 * If we had gigantic hugepages allocated at boot time, we need
index 1c52ddbc839ba1f8f42e940c51bc321ba6b2abfe..34d3ca9572d6baed85499d099a0050af3b9bdf66 100644 (file)
@@ -866,6 +866,7 @@ static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg,
        unsigned long val = 0;
        int cpu;
 
+       get_online_cpus();
        for_each_online_cpu(cpu)
                val += per_cpu(memcg->stat->events[idx], cpu);
 #ifdef CONFIG_HOTPLUG_CPU
@@ -873,6 +874,7 @@ static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg,
        val += memcg->nocpu_base.events[idx];
        spin_unlock(&memcg->pcp_counter_lock);
 #endif
+       put_online_cpus();
        return val;
 }
 
@@ -2159,110 +2161,59 @@ static void memcg_oom_recover(struct mem_cgroup *memcg)
                memcg_wakeup_oom(memcg);
 }
 
-/*
- * try to call OOM killer
- */
 static void mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
 {
-       bool locked;
-       int wakeups;
-
        if (!current->memcg_oom.may_oom)
                return;
-
-       current->memcg_oom.in_memcg_oom = 1;
-
        /*
-        * As with any blocking lock, a contender needs to start
-        * listening for wakeups before attempting the trylock,
-        * otherwise it can miss the wakeup from the unlock and sleep
-        * indefinitely.  This is just open-coded because our locking
-        * is so particular to memcg hierarchies.
+        * We are in the middle of the charge context here, so we
+        * don't want to block when potentially sitting on a callstack
+        * that holds all kinds of filesystem and mm locks.
+        *
+        * Also, the caller may handle a failed allocation gracefully
+        * (like optional page cache readahead) and so an OOM killer
+        * invocation might not even be necessary.
+        *
+        * That's why we don't do anything here except remember the
+        * OOM context and then deal with it at the end of the page
+        * fault when the stack is unwound, the locks are released,
+        * and when we know whether the fault was overall successful.
         */
-       wakeups = atomic_read(&memcg->oom_wakeups);
-       mem_cgroup_mark_under_oom(memcg);
-
-       locked = mem_cgroup_oom_trylock(memcg);
-
-       if (locked)
-               mem_cgroup_oom_notify(memcg);
-
-       if (locked && !memcg->oom_kill_disable) {
-               mem_cgroup_unmark_under_oom(memcg);
-               mem_cgroup_out_of_memory(memcg, mask, order);
-               mem_cgroup_oom_unlock(memcg);
-               /*
-                * There is no guarantee that an OOM-lock contender
-                * sees the wakeups triggered by the OOM kill
-                * uncharges.  Wake any sleepers explicitely.
-                */
-               memcg_oom_recover(memcg);
-       } else {
-               /*
-                * A system call can just return -ENOMEM, but if this
-                * is a page fault and somebody else is handling the
-                * OOM already, we need to sleep on the OOM waitqueue
-                * for this memcg until the situation is resolved.
-                * Which can take some time because it might be
-                * handled by a userspace task.
-                *
-                * However, this is the charge context, which means
-                * that we may sit on a large call stack and hold
-                * various filesystem locks, the mmap_sem etc. and we
-                * don't want the OOM handler to deadlock on them
-                * while we sit here and wait.  Store the current OOM
-                * context in the task_struct, then return -ENOMEM.
-                * At the end of the page fault handler, with the
-                * stack unwound, pagefault_out_of_memory() will check
-                * back with us by calling
-                * mem_cgroup_oom_synchronize(), possibly putting the
-                * task to sleep.
-                */
-               current->memcg_oom.oom_locked = locked;
-               current->memcg_oom.wakeups = wakeups;
-               css_get(&memcg->css);
-               current->memcg_oom.wait_on_memcg = memcg;
-       }
+       css_get(&memcg->css);
+       current->memcg_oom.memcg = memcg;
+       current->memcg_oom.gfp_mask = mask;
+       current->memcg_oom.order = order;
 }
 
 /**
  * mem_cgroup_oom_synchronize - complete memcg OOM handling
+ * @handle: actually kill/wait or just clean up the OOM state
  *
- * This has to be called at the end of a page fault if the the memcg
- * OOM handler was enabled and the fault is returning %VM_FAULT_OOM.
+ * This has to be called at the end of a page fault if the memcg OOM
+ * handler was enabled.
  *
- * Memcg supports userspace OOM handling, so failed allocations must
+ * Memcg supports userspace OOM handling where failed allocations must
  * sleep on a waitqueue until the userspace task resolves the
  * situation.  Sleeping directly in the charge context with all kinds
  * of locks held is not a good idea, instead we remember an OOM state
  * in the task and mem_cgroup_oom_synchronize() has to be called at
- * the end of the page fault to put the task to sleep and clean up the
- * OOM state.
+ * the end of the page fault to complete the OOM handling.
  *
  * Returns %true if an ongoing memcg OOM situation was detected and
- * finalized, %false otherwise.
+ * completed, %false otherwise.
  */
-bool mem_cgroup_oom_synchronize(void)
+bool mem_cgroup_oom_synchronize(bool handle)
 {
+       struct mem_cgroup *memcg = current->memcg_oom.memcg;
        struct oom_wait_info owait;
-       struct mem_cgroup *memcg;
+       bool locked;
 
        /* OOM is global, do not handle */
-       if (!current->memcg_oom.in_memcg_oom)
-               return false;
-
-       /*
-        * We invoked the OOM killer but there is a chance that a kill
-        * did not free up any charges.  Everybody else might already
-        * be sleeping, so restart the fault and keep the rampage
-        * going until some charges are released.
-        */
-       memcg = current->memcg_oom.wait_on_memcg;
        if (!memcg)
-               goto out;
+               return false;
 
-       if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current))
-               goto out_memcg;
+       if (!handle)
+               goto cleanup;
 
        owait.memcg = memcg;
        owait.wait.flags = 0;
@@ -2271,13 +2222,25 @@ bool mem_cgroup_oom_synchronize(void)
        INIT_LIST_HEAD(&owait.wait.task_list);
 
        prepare_to_wait(&memcg_oom_waitq, &owait.wait, TASK_KILLABLE);
-       /* Only sleep if we didn't miss any wakeups since OOM */
-       if (atomic_read(&memcg->oom_wakeups) == current->memcg_oom.wakeups)
+       mem_cgroup_mark_under_oom(memcg);
+
+       locked = mem_cgroup_oom_trylock(memcg);
+
+       if (locked)
+               mem_cgroup_oom_notify(memcg);
+
+       if (locked && !memcg->oom_kill_disable) {
+               mem_cgroup_unmark_under_oom(memcg);
+               finish_wait(&memcg_oom_waitq, &owait.wait);
+               mem_cgroup_out_of_memory(memcg, current->memcg_oom.gfp_mask,
+                                        current->memcg_oom.order);
+       } else {
                schedule();
-       finish_wait(&memcg_oom_waitq, &owait.wait);
-out_memcg:
-       mem_cgroup_unmark_under_oom(memcg);
-       if (current->memcg_oom.oom_locked) {
+               mem_cgroup_unmark_under_oom(memcg);
+               finish_wait(&memcg_oom_waitq, &owait.wait);
+       }
+
+       if (locked) {
                mem_cgroup_oom_unlock(memcg);
                /*
                 * There is no guarantee that an OOM-lock contender
@@ -2286,10 +2249,9 @@ out_memcg:
                 */
                memcg_oom_recover(memcg);
        }
+cleanup:
+       current->memcg_oom.memcg = NULL;
        css_put(&memcg->css);
-       current->memcg_oom.wait_on_memcg = NULL;
-out:
-       current->memcg_oom.in_memcg_oom = 0;
        return true;
 }
 
@@ -2703,6 +2665,9 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm,
                     || fatal_signal_pending(current)))
                goto bypass;
 
+       if (unlikely(task_in_memcg_oom(current)))
+               goto bypass;
+
        /*
         * We always charge the cgroup the mm_struct belongs to.
         * The mm_struct's mem_cgroup changes on task migration if the
@@ -2801,6 +2766,8 @@ done:
        return 0;
 nomem:
        *ptr = NULL;
+       if (gfp_mask & __GFP_NOFAIL)
+               return 0;
        return -ENOMEM;
 bypass:
        *ptr = root_mem_cgroup;
index ca00039471152eae75bb8321a129a4edfc6f580e..1311f26497e6a0f776682ed8a7e23b8620a5b9ad 100644 (file)
@@ -837,6 +837,8 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                                         */
                                        make_migration_entry_read(&entry);
                                        pte = swp_entry_to_pte(entry);
+                                       if (pte_swp_soft_dirty(*src_pte))
+                                               pte = pte_swp_mksoft_dirty(pte);
                                        set_pte_at(src_mm, addr, src_pte, pte);
                                }
                        }
@@ -3863,15 +3865,21 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
         * space.  Kernel faults are handled more gracefully.
         */
        if (flags & FAULT_FLAG_USER)
-               mem_cgroup_enable_oom();
+               mem_cgroup_oom_enable();
 
        ret = __handle_mm_fault(mm, vma, address, flags);
 
-       if (flags & FAULT_FLAG_USER)
-               mem_cgroup_disable_oom();
-
-       if (WARN_ON(task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM)))
-               mem_cgroup_oom_synchronize();
+       if (flags & FAULT_FLAG_USER) {
+               mem_cgroup_oom_disable();
+                /*
+                 * The task may have entered a memcg OOM situation but
+                 * if the allocation error was handled gracefully (no
+                 * VM_FAULT_OOM), there is no need to kill anything.
+                 * Just clean up the OOM state peacefully.
+                 */
+                if (task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM))
+                        mem_cgroup_oom_synchronize(false);
+       }
 
        return ret;
 }
index a26bccd44ccb0a907662c08135399462bd816b9c..7a7325ee1d089696a8073a84d2f748f326124805 100644 (file)
@@ -161,6 +161,8 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
 
        get_page(new);
        pte = pte_mkold(mk_pte(new, vma->vm_page_prot));
+       if (pte_swp_soft_dirty(*ptep))
+               pte = pte_mksoft_dirty(pte);
        if (is_write_migration_entry(entry))
                pte = pte_mkwrite(pte);
 #ifdef CONFIG_HUGETLB_PAGE
index 94722a4d6b438311de1d1690d81a0d598a907339..a3af058f68e4d9f434337d0dcd6127d5d8c6d039 100644 (file)
@@ -94,13 +94,16 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                        swp_entry_t entry = pte_to_swp_entry(oldpte);
 
                        if (is_write_migration_entry(entry)) {
+                               pte_t newpte;
                                /*
                                 * A protection check is difficult so
                                 * just be safe and disable write
                                 */
                                make_migration_entry_read(&entry);
-                               set_pte_at(mm, addr, pte,
-                                       swp_entry_to_pte(entry));
+                               newpte = swp_entry_to_pte(entry);
+                               if (pte_swp_soft_dirty(oldpte))
+                                       newpte = pte_swp_mksoft_dirty(newpte);
+                               set_pte_at(mm, addr, pte, newpte);
                        }
                        pages++;
                }
index 91b13d6a16d453b50894e6028800b92399bf8f14..0843feb66f3d0236abd4386b5bfd0170c24ae0ef 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <asm/pgalloc.h>
 
 #include "internal.h"
 
@@ -63,10 +62,8 @@ static pmd_t *alloc_new_pmd(struct mm_struct *mm, struct vm_area_struct *vma,
                return NULL;
 
        pmd = pmd_alloc(mm, pud, addr);
-       if (!pmd) {
-               pud_free(mm, pud);
+       if (!pmd)
                return NULL;
-       }
 
        VM_BUG_ON(pmd_trans_huge(*pmd));
 
index 314e9d2743813ea5e52c08929b8a4cbb4621dfa9..6738c47f1f7280edc5f3fe610b2658195a0a77e0 100644 (file)
@@ -680,7 +680,7 @@ void pagefault_out_of_memory(void)
 {
        struct zonelist *zonelist;
 
-       if (mem_cgroup_oom_synchronize())
+       if (mem_cgroup_oom_synchronize(true))
                return;
 
        zonelist = node_zonelist(first_online_node, GFP_KERNEL);
index f5236f804aa6cdf9800f445c31950a52cdd6b88f..63807583d8e89f1c96f8b05bcf5fe422ed200c26 100644 (file)
@@ -1210,11 +1210,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
@@ -1226,7 +1226,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,
index a3443278ce3a693b4c2625df3752a59e975abca3..e2e98af703ea9fdcbab4bcd034bc82a1482c9ca6 100644 (file)
@@ -56,6 +56,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name,
                        continue;
                }
 
+#if !defined(CONFIG_SLUB) || !defined(CONFIG_SLUB_DEBUG_ON)
                /*
                 * For simplicity, we won't check this in the list of memcg
                 * caches. We have control over memcg naming, and if there
@@ -69,6 +70,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name,
                        s = NULL;
                        return -EINVAL;
                }
+#endif
        }
 
        WARN_ON(strchr(name, ' '));     /* It confuses parsers */
index 3963fc24fcc1b6f8c4d365de4d99bda8993311b7..de7c904e52e507079f5bae7a2b7854a9d7cf80b0 100644 (file)
@@ -1824,6 +1824,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        struct filename *pathname;
        int i, type, prev;
        int err;
+       unsigned int old_block_size;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1914,6 +1915,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        }
 
        swap_file = p->swap_file;
+       old_block_size = p->old_block_size;
        p->swap_file = NULL;
        p->max = 0;
        swap_map = p->swap_map;
@@ -1938,7 +1940,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        inode = mapping->host;
        if (S_ISBLK(inode->i_mode)) {
                struct block_device *bdev = I_BDEV(inode);
-               set_blocksize(bdev, p->old_block_size);
+               set_blocksize(bdev, old_block_size);
                blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
        } else {
                mutex_lock(&inode->i_mutex);
index 53f2f82f83ae0d16bf19646cdb5b3bce5fc4e4cf..eea668d9cff6c578ada0cf6c02eca5e22de5598d 100644 (file)
@@ -211,6 +211,7 @@ void unregister_shrinker(struct shrinker *shrinker)
        down_write(&shrinker_rwsem);
        list_del(&shrinker->list);
        up_write(&shrinker_rwsem);
+       kfree(shrinker->nr_deferred);
 }
 EXPORT_SYMBOL(unregister_shrinker);
 
index 841e35f1db22caff3afd03c104403f0c744776cb..d93510c6aa2da860d779570cbf0a4c7cee278ad5 100644 (file)
@@ -804,6 +804,10 @@ static void zswap_frontswap_invalidate_area(unsigned type)
        }
        tree->rbroot = RB_ROOT;
        spin_unlock(&tree->lock);
+
+       zbud_destroy_pool(tree->pool);
+       kfree(tree);
+       zswap_trees[type] = NULL;
 }
 
 static struct zbud_ops zswap_zbud_ops = {
index 309129732285fd610159446bade5ede27c835d1c..c7e634af85165613822074b28ceeca4af7153ae7 100644 (file)
@@ -171,7 +171,7 @@ static size_t vlan_get_size(const struct net_device *dev)
 
        return nla_total_size(2) +      /* IFLA_VLAN_PROTOCOL */
               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);
 }
index c72d1bcdcf4906a1a23808cab2a464804a3fcda6..1356af660b5bf05645394a28c91cdbc54e5ad4c2 100644 (file)
@@ -65,6 +65,7 @@ static int __init batadv_init(void)
        batadv_recv_handler_init();
 
        batadv_iv_init();
+       batadv_nc_init();
 
        batadv_event_workqueue = create_singlethread_workqueue("bat_events");
 
@@ -142,7 +143,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
        if (ret < 0)
                goto err;
 
-       ret = batadv_nc_init(bat_priv);
+       ret = batadv_nc_mesh_init(bat_priv);
        if (ret < 0)
                goto err;
 
@@ -167,7 +168,7 @@ void batadv_mesh_free(struct net_device *soft_iface)
        batadv_vis_quit(bat_priv);
 
        batadv_gw_node_purge(bat_priv);
-       batadv_nc_free(bat_priv);
+       batadv_nc_mesh_free(bat_priv);
        batadv_dat_free(bat_priv);
        batadv_bla_free(bat_priv);
 
index a487d46e0aeccdb72ab4ad6e361dd0b4b87a7c05..4ecc0b6bf8ab63a41b57235f6706207bd5da9e99 100644 (file)
@@ -34,6 +34,20 @@ static void batadv_nc_worker(struct work_struct *work);
 static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
                                       struct batadv_hard_iface *recv_if);
 
+/**
+ * batadv_nc_init - one-time initialization for network coding
+ */
+int __init batadv_nc_init(void)
+{
+       int ret;
+
+       /* Register our packet type */
+       ret = batadv_recv_handler_register(BATADV_CODED,
+                                          batadv_nc_recv_coded_packet);
+
+       return ret;
+}
+
 /**
  * batadv_nc_start_timer - initialise the nc periodic worker
  * @bat_priv: the bat priv with all the soft interface information
@@ -45,10 +59,10 @@ static void batadv_nc_start_timer(struct batadv_priv *bat_priv)
 }
 
 /**
- * batadv_nc_init - initialise coding hash table and start house keeping
+ * batadv_nc_mesh_init - initialise coding hash table and start house keeping
  * @bat_priv: the bat priv with all the soft interface information
  */
-int batadv_nc_init(struct batadv_priv *bat_priv)
+int batadv_nc_mesh_init(struct batadv_priv *bat_priv)
 {
        bat_priv->nc.timestamp_fwd_flush = jiffies;
        bat_priv->nc.timestamp_sniffed_purge = jiffies;
@@ -70,11 +84,6 @@ int batadv_nc_init(struct batadv_priv *bat_priv)
        batadv_hash_set_lock_class(bat_priv->nc.coding_hash,
                                   &batadv_nc_decoding_hash_lock_class_key);
 
-       /* Register our packet type */
-       if (batadv_recv_handler_register(BATADV_CODED,
-                                        batadv_nc_recv_coded_packet) < 0)
-               goto err;
-
        INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker);
        batadv_nc_start_timer(bat_priv);
 
@@ -1721,12 +1730,11 @@ free_nc_packet:
 }
 
 /**
- * batadv_nc_free - clean up network coding memory
+ * batadv_nc_mesh_free - clean up network coding memory
  * @bat_priv: the bat priv with all the soft interface information
  */
-void batadv_nc_free(struct batadv_priv *bat_priv)
+void batadv_nc_mesh_free(struct batadv_priv *bat_priv)
 {
-       batadv_recv_handler_unregister(BATADV_CODED);
        cancel_delayed_work_sync(&bat_priv->nc.work);
 
        batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL);
index 85a4ec81ad50bda26449cfdadbcaf28e62391b8b..ddfa618e80bf0202fdf6bc89ffe213b44cbfb28a 100644 (file)
@@ -22,8 +22,9 @@
 
 #ifdef CONFIG_BATMAN_ADV_NC
 
-int batadv_nc_init(struct batadv_priv *bat_priv);
-void batadv_nc_free(struct batadv_priv *bat_priv);
+int batadv_nc_init(void);
+int batadv_nc_mesh_init(struct batadv_priv *bat_priv);
+void batadv_nc_mesh_free(struct batadv_priv *bat_priv);
 void batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
                              struct batadv_orig_node *orig_node,
                              struct batadv_orig_node *orig_neigh_node,
@@ -46,12 +47,17 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv);
 
 #else /* ifdef CONFIG_BATMAN_ADV_NC */
 
-static inline int batadv_nc_init(struct batadv_priv *bat_priv)
+static inline int batadv_nc_init(void)
 {
        return 0;
 }
 
-static inline void batadv_nc_free(struct batadv_priv *bat_priv)
+static inline int batadv_nc_mesh_init(struct batadv_priv *bat_priv)
+{
+       return 0;
+}
+
+static inline void batadv_nc_mesh_free(struct batadv_priv *bat_priv)
 {
        return;
 }
index ffd5874f25920a94c74f5d97ebf4a0e2aa77f48d..33e8f23acddd9ca2c817913753142ce063c1fb9e 100644 (file)
@@ -700,7 +700,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 
                vid = nla_get_u16(tb[NDA_VLAN]);
 
-               if (vid >= VLAN_N_VID) {
+               if (!vid || vid >= VLAN_VID_MASK) {
                        pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
                                vid);
                        return -EINVAL;
@@ -794,7 +794,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 
                vid = nla_get_u16(tb[NDA_VLAN]);
 
-               if (vid >= VLAN_N_VID) {
+               if (!vid || vid >= VLAN_VID_MASK) {
                        pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
                                vid);
                        return -EINVAL;
index 85a09bb5ca51b864cd671c63746d65dfd531ed79..b7b1914dfa252a3731a26e2bcf2be3afc5171661 100644 (file)
@@ -453,7 +453,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
                call_rcu_bh(&p->rcu, br_multicast_free_pg);
                err = 0;
 
-               if (!mp->ports && !mp->mglist && mp->timer_armed &&
+               if (!mp->ports && !mp->mglist &&
                    netif_running(br->dev))
                        mod_timer(&mp->timer, jiffies);
                break;
index d1c5786306784a7353b845cad60e2d39abec0f72..8b0b610ca2c9a3cb8eb14ead723198783db35659 100644 (file)
@@ -272,7 +272,7 @@ static void br_multicast_del_pg(struct net_bridge *br,
                del_timer(&p->timer);
                call_rcu_bh(&p->rcu, br_multicast_free_pg);
 
-               if (!mp->ports && !mp->mglist && mp->timer_armed &&
+               if (!mp->ports && !mp->mglist &&
                    netif_running(br->dev))
                        mod_timer(&mp->timer, jiffies);
 
@@ -620,7 +620,6 @@ rehash:
 
        mp->br = br;
        mp->addr = *group;
-
        setup_timer(&mp->timer, br_multicast_group_expired,
                    (unsigned long)mp);
 
@@ -660,6 +659,7 @@ static int br_multicast_add_group(struct net_bridge *br,
        struct net_bridge_mdb_entry *mp;
        struct net_bridge_port_group *p;
        struct net_bridge_port_group __rcu **pp;
+       unsigned long now = jiffies;
        int err;
 
        spin_lock(&br->multicast_lock);
@@ -674,6 +674,7 @@ static int br_multicast_add_group(struct net_bridge *br,
 
        if (!port) {
                mp->mglist = true;
+               mod_timer(&mp->timer, now + br->multicast_membership_interval);
                goto out;
        }
 
@@ -681,7 +682,7 @@ static int br_multicast_add_group(struct net_bridge *br,
             (p = mlock_dereference(*pp, br)) != NULL;
             pp = &p->next) {
                if (p->port == port)
-                       goto out;
+                       goto found;
                if ((unsigned long)p->port < (unsigned long)port)
                        break;
        }
@@ -692,6 +693,8 @@ static int br_multicast_add_group(struct net_bridge *br,
        rcu_assign_pointer(*pp, p);
        br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
 
+found:
+       mod_timer(&p->timer, now + br->multicast_membership_interval);
 out:
        err = 0;
 
@@ -1191,9 +1194,6 @@ static int br_ip4_multicast_query(struct net_bridge *br,
        if (!mp)
                goto out;
 
-       mod_timer(&mp->timer, now + br->multicast_membership_interval);
-       mp->timer_armed = true;
-
        max_delay *= br->multicast_last_member_count;
 
        if (mp->mglist &&
@@ -1270,9 +1270,6 @@ static int br_ip6_multicast_query(struct net_bridge *br,
        if (!mp)
                goto out;
 
-       mod_timer(&mp->timer, now + br->multicast_membership_interval);
-       mp->timer_armed = true;
-
        max_delay *= br->multicast_last_member_count;
        if (mp->mglist &&
            (timer_pending(&mp->timer) ?
@@ -1358,7 +1355,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
                        call_rcu_bh(&p->rcu, br_multicast_free_pg);
                        br_mdb_notify(br->dev, port, group, RTM_DELMDB);
 
-                       if (!mp->ports && !mp->mglist && mp->timer_armed &&
+                       if (!mp->ports && !mp->mglist &&
                            netif_running(br->dev))
                                mod_timer(&mp->timer, jiffies);
                }
@@ -1370,12 +1367,30 @@ static void br_multicast_leave_group(struct net_bridge *br,
                     br->multicast_last_member_interval;
 
        if (!port) {
-               if (mp->mglist && mp->timer_armed &&
+               if (mp->mglist &&
                    (timer_pending(&mp->timer) ?
                     time_after(mp->timer.expires, time) :
                     try_to_del_timer_sync(&mp->timer) >= 0)) {
                        mod_timer(&mp->timer, time);
                }
+
+               goto out;
+       }
+
+       for (p = mlock_dereference(mp->ports, br);
+            p != NULL;
+            p = mlock_dereference(p->next, br)) {
+               if (p->port != port)
+                       continue;
+
+               if (!hlist_unhashed(&p->mglist) &&
+                   (timer_pending(&p->timer) ?
+                    time_after(p->timer.expires, time) :
+                    try_to_del_timer_sync(&p->timer) >= 0)) {
+                       mod_timer(&p->timer, time);
+               }
+
+               break;
        }
 out:
        spin_unlock(&br->multicast_lock);
@@ -1798,7 +1813,6 @@ void br_multicast_stop(struct net_bridge *br)
                hlist_for_each_entry_safe(mp, n, &mdb->mhash[i],
                                          hlist[ver]) {
                        del_timer(&mp->timer);
-                       mp->timer_armed = false;
                        call_rcu_bh(&mp->rcu, br_multicast_free_group);
                }
        }
index e74ddc1c29a8be20f1a093fcc8e27b11bca6f03e..f75d92e4f96b33cec6fd46fc37151224f86ed018 100644 (file)
@@ -243,7 +243,7 @@ static int br_afspec(struct net_bridge *br,
 
                vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
 
-               if (vinfo->vid >= VLAN_N_VID)
+               if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
                        return -EINVAL;
 
                switch (cmd) {
index efb57d91156975b3b43a2afdc588128a2f6e1f79..e14c33b42f75c3d1f4b6bb095b32efdb9218683e 100644 (file)
@@ -126,7 +126,6 @@ struct net_bridge_mdb_entry
        struct timer_list               timer;
        struct br_ip                    addr;
        bool                            mglist;
-       bool                            timer_armed;
 };
 
 struct net_bridge_mdb_htable
@@ -643,9 +642,7 @@ static inline u16 br_get_pvid(const struct net_port_vlans *v)
         * vid wasn't set
         */
        smp_rmb();
-       return (v->pvid & VLAN_TAG_PRESENT) ?
-                       (v->pvid & ~VLAN_TAG_PRESENT) :
-                       VLAN_N_VID;
+       return v->pvid ?: VLAN_N_VID;
 }
 
 #else
index 108084a0467160e30eb001cd2dbb326fdc4dadd3..656a6f3e40de1b13b9ea7a89373da5d5615e5bb2 100644 (file)
@@ -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) {
index 9a9ffe7e4019741d75456e3b9afdba21c44785b3..53f0990eab58e08a3da9160a27ee0834bd0f0272 100644 (file)
@@ -45,37 +45,34 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
                return 0;
        }
 
-       if (vid) {
-               if (v->port_idx) {
-                       p = v->parent.port;
-                       br = p->br;
-                       dev = p->dev;
-               } else {
-                       br = v->parent.br;
-                       dev = br->dev;
-               }
-               ops = dev->netdev_ops;
-
-               if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
-                       /* Add VLAN to the device filter if it is supported.
-                        * Stricly speaking, this is not necessary now, since
-                        * devices are made promiscuous by the bridge, but if
-                        * that ever changes this code will allow tagged
-                        * traffic to enter the bridge.
-                        */
-                       err = ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q),
-                                                      vid);
-                       if (err)
-                               return err;
-               }
-
-               err = br_fdb_insert(br, p, dev->dev_addr, vid);
-               if (err) {
-                       br_err(br, "failed insert local address into bridge "
-                              "forwarding table\n");
-                       goto out_filt;
-               }
+       if (v->port_idx) {
+               p = v->parent.port;
+               br = p->br;
+               dev = p->dev;
+       } else {
+               br = v->parent.br;
+               dev = br->dev;
+       }
+       ops = dev->netdev_ops;
+
+       if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
+               /* Add VLAN to the device filter if it is supported.
+                * Stricly speaking, this is not necessary now, since
+                * devices are made promiscuous by the bridge, but if
+                * that ever changes this code will allow tagged
+                * traffic to enter the bridge.
+                */
+               err = ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q),
+                                              vid);
+               if (err)
+                       return err;
+       }
 
+       err = br_fdb_insert(br, p, dev->dev_addr, vid);
+       if (err) {
+               br_err(br, "failed insert local address into bridge "
+                      "forwarding table\n");
+               goto out_filt;
        }
 
        set_bit(vid, v->vlan_bitmap);
@@ -98,7 +95,7 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
        __vlan_delete_pvid(v, vid);
        clear_bit(vid, v->untagged_bitmap);
 
-       if (v->port_idx && vid) {
+       if (v->port_idx) {
                struct net_device *dev = v->parent.port->dev;
                const struct net_device_ops *ops = dev->netdev_ops;
 
@@ -192,6 +189,8 @@ out:
 bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
                        struct sk_buff *skb, u16 *vid)
 {
+       int err;
+
        /* If VLAN filtering is disabled on the bridge, all packets are
         * permitted.
         */
@@ -204,20 +203,32 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
        if (!v)
                return false;
 
-       if (br_vlan_get_tag(skb, vid)) {
+       err = br_vlan_get_tag(skb, vid);
+       if (!*vid) {
                u16 pvid = br_get_pvid(v);
 
-               /* Frame did not have a tag.  See if pvid is set
-                * on this port.  That tells us which vlan untagged
-                * traffic belongs to.
+               /* Frame had a tag with VID 0 or did not have a tag.
+                * See if pvid is set on this port.  That tells us which
+                * vlan untagged or priority-tagged traffic belongs to.
                 */
                if (pvid == VLAN_N_VID)
                        return false;
 
-               /* PVID is set on this port.  Any untagged ingress
-                * frame is considered to belong to this vlan.
+               /* PVID is set on this port.  Any untagged or priority-tagged
+                * ingress frame is considered to belong to this vlan.
                 */
-               __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid);
+               *vid = pvid;
+               if (likely(err))
+                       /* Untagged Frame. */
+                       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid);
+               else
+                       /* Priority-tagged Frame.
+                        * At this point, We know that skb->vlan_tci had
+                        * VLAN_TAG_PRESENT bit and its VID field was 0x000.
+                        * We update only VID field and preserve PCP field.
+                        */
+                       skb->vlan_tci |= pvid;
+
                return true;
        }
 
@@ -248,7 +259,9 @@ bool br_allowed_egress(struct net_bridge *br,
        return false;
 }
 
-/* Must be protected by RTNL */
+/* Must be protected by RTNL.
+ * Must be called with vid in range from 1 to 4094 inclusive.
+ */
 int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
 {
        struct net_port_vlans *pv = NULL;
@@ -278,7 +291,9 @@ out:
        return err;
 }
 
-/* Must be protected by RTNL */
+/* Must be protected by RTNL.
+ * Must be called with vid in range from 1 to 4094 inclusive.
+ */
 int br_vlan_delete(struct net_bridge *br, u16 vid)
 {
        struct net_port_vlans *pv;
@@ -289,14 +304,9 @@ int br_vlan_delete(struct net_bridge *br, u16 vid)
        if (!pv)
                return -EINVAL;
 
-       if (vid) {
-               /* If the VID !=0 remove fdb for this vid. VID 0 is special
-                * in that it's the default and is always there in the fdb.
-                */
-               spin_lock_bh(&br->hash_lock);
-               fdb_delete_by_addr(br, br->dev->dev_addr, vid);
-               spin_unlock_bh(&br->hash_lock);
-       }
+       spin_lock_bh(&br->hash_lock);
+       fdb_delete_by_addr(br, br->dev->dev_addr, vid);
+       spin_unlock_bh(&br->hash_lock);
 
        __vlan_del(pv, vid);
        return 0;
@@ -329,7 +339,9 @@ unlock:
        return 0;
 }
 
-/* Must be protected by RTNL */
+/* Must be protected by RTNL.
+ * Must be called with vid in range from 1 to 4094 inclusive.
+ */
 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
 {
        struct net_port_vlans *pv = NULL;
@@ -363,7 +375,9 @@ clean_up:
        return err;
 }
 
-/* Must be protected by RTNL */
+/* Must be protected by RTNL.
+ * Must be called with vid in range from 1 to 4094 inclusive.
+ */
 int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
 {
        struct net_port_vlans *pv;
@@ -374,14 +388,9 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
        if (!pv)
                return -EINVAL;
 
-       if (vid) {
-               /* If the VID !=0 remove fdb for this vid. VID 0 is special
-                * in that it's the default and is always there in the fdb.
-                */
-               spin_lock_bh(&port->br->hash_lock);
-               fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
-               spin_unlock_bh(&port->br->hash_lock);
-       }
+       spin_lock_bh(&port->br->hash_lock);
+       fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
+       spin_unlock_bh(&port->br->hash_lock);
 
        return __vlan_del(pv, vid);
 }
index f0a1ba6c8086acc65a87e519fca48853a3bd091e..89032580bd1d8aa5ef29d1395661bdd0bcfe95f1 100644 (file)
@@ -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);
index 65f829cfd928b3bda157b0848e13edfa5b118bae..3430b1ed12e5f93b14ca1f377f848fa29a81be00 100644 (file)
@@ -1917,7 +1917,8 @@ static struct xps_map *expand_xps_map(struct xps_map *map,
        return new_map;
 }
 
-int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask, u16 index)
+int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
+                       u16 index)
 {
        struct xps_dev_maps *dev_maps, *new_dev_maps = NULL;
        struct xps_map *map, *new_map;
index 6438f29ff26650b240be40d7d80953dc28f13cb0..01b780856db29e5a2a7ebbc36aa7062340b28bb8 100644 (file)
@@ -644,7 +644,6 @@ void sk_filter_release_rcu(struct rcu_head *rcu)
        struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
 
        bpf_jit_free(fp);
-       kfree(fp);
 }
 EXPORT_SYMBOL(sk_filter_release_rcu);
 
@@ -683,7 +682,7 @@ int sk_unattached_filter_create(struct sk_filter **pfp,
        if (fprog->filter == NULL)
                return -EINVAL;
 
-       fp = kmalloc(fsize + sizeof(*fp), GFP_KERNEL);
+       fp = kmalloc(sk_filter_size(fprog->len), GFP_KERNEL);
        if (!fp)
                return -ENOMEM;
        memcpy(fp->insns, fprog->filter, fsize);
@@ -723,6 +722,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
 {
        struct sk_filter *fp, *old_fp;
        unsigned int fsize = sizeof(struct sock_filter) * fprog->len;
+       unsigned int sk_fsize = sk_filter_size(fprog->len);
        int err;
 
        if (sock_flag(sk, SOCK_FILTER_LOCKED))
@@ -732,11 +732,11 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
        if (fprog->filter == NULL)
                return -EINVAL;
 
-       fp = sock_kmalloc(sk, fsize+sizeof(*fp), GFP_KERNEL);
+       fp = sock_kmalloc(sk, sk_fsize, GFP_KERNEL);
        if (!fp)
                return -ENOMEM;
        if (copy_from_user(fp->insns, fprog->filter, fsize)) {
-               sock_kfree_s(sk, fp, fsize+sizeof(*fp));
+               sock_kfree_s(sk, fp, sk_fsize);
                return -EFAULT;
        }
 
index 3f1ec1586ae174d9bea18de2bcada31c3c88a5bb..8d9d05edd2eb1e66024311c62c6b7679c52bdc7d 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <net/secure_seq.h>
 
+#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
 #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4)
 
 static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned;
@@ -29,6 +30,7 @@ static void net_secret_init(void)
                cmpxchg(&net_secret[--i], 0, tmp);
        }
 }
+#endif
 
 #ifdef CONFIG_INET
 static u32 seq_scale(u32 seq)
index 5b6beba494a350cb28adfc7724487f1a13e6c011..0b39e7ae43837e602ff473b641675fbf22b83b5c 100644 (file)
@@ -2319,6 +2319,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
        sk->sk_ll_usec          =       sysctl_net_busy_read;
 #endif
 
+       sk->sk_pacing_rate = ~0U;
        /*
         * Before updating sk_refcnt, we must commit prior changes to memory
         * (Documentation/RCU/rculist_nulls.txt for details)
index c85e71e0c7ffc640bd9592ce52b03dbde6cad926..ff41b4d60d302e18a1ebcf1bdfc950970fdd3aae 100644 (file)
@@ -1372,6 +1372,8 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
        real_dev = dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
        if (!real_dev)
                return -ENODEV;
+       if (real_dev->type != ARPHRD_IEEE802154)
+               return -EINVAL;
 
        lowpan_dev_info(dev)->real_dev = real_dev;
        lowpan_dev_info(dev)->fragment_tag = 0;
@@ -1386,6 +1388,9 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
 
        entry->ldev = dev;
 
+       /* Set the lowpan harware address to the wpan hardware address. */
+       memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN);
+
        mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
        INIT_LIST_HEAD(&entry->list);
        list_add_tail(&entry->list, &lowpan_devices);
index 7bd8983dbfcf308e61dc55bb9491b3dd6866fa35..96da9c77decad927aa7a29ea816efa2a3013db37 100644 (file)
@@ -287,7 +287,7 @@ begintw:
                        if (unlikely(!INET_TW_MATCH(sk, net, acookie,
                                                    saddr, daddr, ports,
                                                    dif))) {
-                               sock_put(sk);
+                               inet_twsk_put(inet_twsk(sk));
                                goto begintw;
                        }
                        goto out;
index a04d872c54f919c7133e7830773301cdf070f3ed..3982eabf61e126060fc7c5b48042bea2f0417135 100644 (file)
@@ -772,15 +772,20 @@ static inline int ip_ufo_append_data(struct sock *sk,
                /* initialize protocol header pointer */
                skb->transport_header = skb->network_header + fragheaderlen;
 
-               skb->ip_summed = CHECKSUM_PARTIAL;
                skb->csum = 0;
 
-               /* specify the length of each IP datagram fragment */
-               skb_shinfo(skb)->gso_size = maxfraglen - fragheaderlen;
-               skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+
                __skb_queue_tail(queue, skb);
+       } else if (skb_is_gso(skb)) {
+               goto append;
        }
 
+       skb->ip_summed = CHECKSUM_PARTIAL;
+       /* specify the length of each IP datagram fragment */
+       skb_shinfo(skb)->gso_size = maxfraglen - fragheaderlen;
+       skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+
+append:
        return skb_append_datato_frags(sk, skb, getfrag, from,
                                       (length - transhdrlen));
 }
index e805e7b3030e3dad2f8fd83d140f0bb7f100d69c..6e87f853d03334567906c8782250049c568e4280 100644 (file)
@@ -125,8 +125,17 @@ static int vti_rcv(struct sk_buff *skb)
                                  iph->saddr, iph->daddr, 0);
        if (tunnel != NULL) {
                struct pcpu_tstats *tstats;
+               u32 oldmark = skb->mark;
+               int ret;
 
-               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+
+               /* temporarily mark the skb with the tunnel o_key, to
+                * only match policies with this mark.
+                */
+               skb->mark = be32_to_cpu(tunnel->parms.o_key);
+               ret = xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb);
+               skb->mark = oldmark;
+               if (!ret)
                        return -1;
 
                tstats = this_cpu_ptr(tunnel->dev->tstats);
@@ -135,7 +144,6 @@ static int vti_rcv(struct sk_buff *skb)
                tstats->rx_bytes += skb->len;
                u64_stats_update_end(&tstats->syncp);
 
-               skb->mark = 0;
                secpath_reset(skb);
                skb->dev = tunnel->dev;
                return 1;
@@ -167,7 +175,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 
        memset(&fl4, 0, sizeof(fl4));
        flowi4_init_output(&fl4, tunnel->parms.link,
-                          be32_to_cpu(tunnel->parms.i_key), RT_TOS(tos),
+                          be32_to_cpu(tunnel->parms.o_key), RT_TOS(tos),
                           RT_SCOPE_UNIVERSE,
                           IPPROTO_IPIP, 0,
                           dst, tiph->saddr, 0, 0);
index 727f4365bcdff3acdb415fe75fd878a3bc5050af..6011615e810d397ce8ffa5daeca58ce6921e85f0 100644 (file)
@@ -2072,7 +2072,7 @@ struct rtable *__ip_route_output_key(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);
index 25a89eaa669de9240036abc04f1385eb168f995e..a16b01b537baa1e0e2b63e606f96fb37571d7638 100644 (file)
@@ -1284,7 +1284,10 @@ static bool 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);
 
@@ -3288,7 +3291,7 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag)
                        tcp_init_cwnd_reduction(sk, true);
                        tcp_set_ca_state(sk, TCP_CA_CWR);
                        tcp_end_cwnd_reduction(sk);
-                       tcp_set_ca_state(sk, TCP_CA_Open);
+                       tcp_try_keep_open(sk);
                        NET_INC_STATS_BH(sock_net(sk),
                                         LINUX_MIB_TCPLOSSPROBERECOVERY);
                }
@@ -5709,6 +5712,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                } else
                        tcp_init_metrics(sk);
 
+               tcp_update_pacing_rate(sk);
+
                /* Prevent spurious tcp_cwnd_restart() on first data packet */
                tp->lsndtime = tcp_time_stamp;
 
index e6bb8256e59f3738280a022f250f6fefd621cb38..d46f2143305c2632e7703f2677310dd177d67208 100644 (file)
@@ -637,6 +637,8 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb
        unsigned int size = 0;
        unsigned int eff_sacks;
 
+       opts->options = 0;
+
 #ifdef CONFIG_TCP_MD5SIG
        *md5 = tp->af_specific->md5_lookup(sk, sk);
        if (unlikely(*md5)) {
@@ -984,8 +986,10 @@ 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)
 {
-       if (skb->len <= mss_now || !sk_can_gso(sk) ||
-           skb->ip_summed == CHECKSUM_NONE) {
+       /* Make sure we own this skb before messing gso_size/gso_segs */
+       WARN_ON_ONCE(skb_cloned(skb));
+
+       if (skb->len <= mss_now || skb->ip_summed == CHECKSUM_NONE) {
                /* Avoid the costly divide in the normal
                 * non-TSO case.
                 */
@@ -1065,9 +1069,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. */
@@ -2342,6 +2344,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));
                }
index 9a459be24af762b42e2d667618f7149c055e5ef6..ccde54248c8ca77d3efc173ce457aa5f0153337a 100644 (file)
@@ -107,6 +107,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 
        memset(fl4, 0, sizeof(struct flowi4));
        fl4->flowi4_mark = skb->mark;
+       fl4->flowi4_oif = skb_dst(skb)->dev->ifindex;
 
        if (!ip_is_fragment(iph)) {
                switch (iph->protocol) {
index 73784c3d4642e09f0f9f92d1f699769ec08258d9..82e1da3a40b915e65c2ecf15662415511cc91286 100644 (file)
@@ -618,8 +618,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset);
        struct xfrm_state *x;
 
-       if (type != ICMPV6_DEST_UNREACH &&
-           type != ICMPV6_PKT_TOOBIG &&
+       if (type != ICMPV6_PKT_TOOBIG &&
            type != NDISC_REDIRECT)
                return;
 
index d3618a78fcac4b1f6e606a904196de79235833b1..e67e63f9858d7feae9e6fba4de667edb8f81875d 100644 (file)
@@ -436,8 +436,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset);
        struct xfrm_state *x;
 
-       if (type != ICMPV6_DEST_UNREACH &&
-           type != ICMPV6_PKT_TOOBIG &&
+       if (type != ICMPV6_PKT_TOOBIG &&
            type != NDISC_REDIRECT)
                return;
 
index 32b4a1675d826d8ce50e36dbf314456075e1660e..066640e0ba8e3b5f4759cabcfc5bbe125ef2df20 100644 (file)
@@ -116,7 +116,7 @@ begintw:
                        }
                        if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr,
                                                     ports, dif))) {
-                               sock_put(sk);
+                               inet_twsk_put(inet_twsk(sk));
                                goto begintw;
                        }
                        goto out;
index 7bb5446b9d73c16a7f4096f2705ce60f997c7c2a..bf4a9a084de5aa8f733318276d6e84cc37d5e249 100644 (file)
@@ -976,6 +976,7 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
                if (t->parms.o_flags&GRE_SEQ)
                        addend += 4;
        }
+       t->hlen = addend;
 
        if (p->flags & IP6_TNL_F_CAP_XMIT) {
                int strict = (ipv6_addr_type(&p->raddr) &
@@ -1002,8 +1003,6 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
                }
                ip6_rt_put(rt);
        }
-
-       t->hlen = addend;
 }
 
 static int ip6gre_tnl_change(struct ip6_tnl *t,
@@ -1173,9 +1172,8 @@ done:
 
 static int ip6gre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
 {
-       struct ip6_tnl *tunnel = netdev_priv(dev);
        if (new_mtu < 68 ||
-           new_mtu > 0xFFF8 - dev->hard_header_len - tunnel->hlen)
+           new_mtu > 0xFFF8 - dev->hard_header_len)
                return -EINVAL;
        dev->mtu = new_mtu;
        return 0;
index a54c45ce4a48f0d3a65f6c54ac77bb73a6a41280..91fb4e8212f52d434e6d072103f70dbb8d219326 100644 (file)
@@ -105,7 +105,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
        }
 
        rcu_read_lock_bh();
-       nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
+       nexthop = rt6_nexthop((struct rt6_info *)dst);
        neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
        if (unlikely(!neigh))
                neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
@@ -874,7 +874,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
         */
        rt = (struct rt6_info *) *dst;
        rcu_read_lock_bh();
-       n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt, &fl6->daddr));
+       n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt));
        err = n && !(n->nud_state & NUD_VALID) ? -EINVAL : 0;
        rcu_read_unlock_bh();
 
@@ -1008,6 +1008,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
 
 {
        struct sk_buff *skb;
+       struct frag_hdr fhdr;
        int err;
 
        /* There is support for UDP large send offload by network
@@ -1015,8 +1016,6 @@ 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);
@@ -1036,20 +1035,24 @@ static inline int ip6_ufo_append_data(struct sock *sk,
                skb->transport_header = skb->network_header + fragheaderlen;
 
                skb->protocol = htons(ETH_P_IPV6);
-               skb->ip_summed = CHECKSUM_PARTIAL;
                skb->csum = 0;
 
-               /* Specify the length of each IPv6 datagram fragment.
-                * It has to be a multiple of 8.
-                */
-               skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
-                                            sizeof(struct frag_hdr)) & ~7;
-               skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
-               ipv6_select_ident(&fhdr, rt);
-               skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
                __skb_queue_tail(&sk->sk_write_queue, skb);
+       } else if (skb_is_gso(skb)) {
+               goto append;
        }
 
+       skb->ip_summed = CHECKSUM_PARTIAL;
+       /* Specify the length of each IPv6 datagram fragment.
+        * It has to be a multiple of 8.
+        */
+       skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
+                                    sizeof(struct frag_hdr)) & ~7;
+       skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+       ipv6_select_ident(&fhdr, rt);
+       skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
+
+append:
        return skb_append_datato_frags(sk, skb, getfrag, from,
                                       (length - transhdrlen));
 }
index a791552e042212d866b2cd96c35e2f0b5d289ab5..583b77e2f69be1d1499da479e2f8da1435d22a97 100644 (file)
@@ -1430,9 +1430,17 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 static int
 ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
 {
-       if (new_mtu < IPV6_MIN_MTU) {
-               return -EINVAL;
+       struct ip6_tnl *tnl = netdev_priv(dev);
+
+       if (tnl->parms.proto == IPPROTO_IPIP) {
+               if (new_mtu < 68)
+                       return -EINVAL;
+       } else {
+               if (new_mtu < IPV6_MIN_MTU)
+                       return -EINVAL;
        }
+       if (new_mtu > 0xFFF8 - dev->hard_header_len)
+               return -EINVAL;
        dev->mtu = new_mtu;
        return 0;
 }
index 5636a912074acb8ecf445d9d6df753ff8e3eba95..ce507d9e1c900d3990e6025b37087309f850eaca 100644 (file)
@@ -64,8 +64,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                (struct ip_comp_hdr *)(skb->data + offset);
        struct xfrm_state *x;
 
-       if (type != ICMPV6_DEST_UNREACH &&
-           type != ICMPV6_PKT_TOOBIG &&
+       if (type != ICMPV6_PKT_TOOBIG &&
            type != NDISC_REDIRECT)
                return;
 
index c979dd96d82a838534ae0105dbfb9e665ad410e6..f54e3a1010989ac93619d4984df4ed9b32aed521 100644 (file)
@@ -476,6 +476,24 @@ out:
 }
 
 #ifdef CONFIG_IPV6_ROUTER_PREF
+struct __rt6_probe_work {
+       struct work_struct work;
+       struct in6_addr target;
+       struct net_device *dev;
+};
+
+static void rt6_probe_deferred(struct work_struct *w)
+{
+       struct in6_addr mcaddr;
+       struct __rt6_probe_work *work =
+               container_of(w, struct __rt6_probe_work, work);
+
+       addrconf_addr_solict_mult(&work->target, &mcaddr);
+       ndisc_send_ns(work->dev, NULL, &work->target, &mcaddr, NULL);
+       dev_put(work->dev);
+       kfree(w);
+}
+
 static void rt6_probe(struct rt6_info *rt)
 {
        struct neighbour *neigh;
@@ -499,17 +517,23 @@ static void rt6_probe(struct rt6_info *rt)
 
        if (!neigh ||
            time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
-               struct in6_addr mcaddr;
-               struct in6_addr *target;
+               struct __rt6_probe_work *work;
 
-               if (neigh) {
+               work = kmalloc(sizeof(*work), GFP_ATOMIC);
+
+               if (neigh && work)
                        neigh->updated = jiffies;
+
+               if (neigh)
                        write_unlock(&neigh->lock);
-               }
 
-               target = (struct in6_addr *)&rt->rt6i_gateway;
-               addrconf_addr_solict_mult(target, &mcaddr);
-               ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL);
+               if (work) {
+                       INIT_WORK(&work->work, rt6_probe_deferred);
+                       work->target = rt->rt6i_gateway;
+                       dev_hold(rt->dst.dev);
+                       work->dev = rt->dst.dev;
+                       schedule_work(&work->work);
+               }
        } else {
 out:
                write_unlock(&neigh->lock);
@@ -851,7 +875,6 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort,
                        if (ort->rt6i_dst.plen != 128 &&
                            ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
                                rt->rt6i_flags |= RTF_ANYCAST;
-                       rt->rt6i_gateway = *daddr;
                }
 
                rt->rt6i_flags |= RTF_CACHE;
@@ -1338,6 +1361,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
        rt->dst.flags |= DST_HOST;
        rt->dst.output  = ip6_output;
        atomic_set(&rt->dst.__refcnt, 1);
+       rt->rt6i_gateway  = fl6->daddr;
        rt->rt6i_dst.addr = fl6->daddr;
        rt->rt6i_dst.plen = 128;
        rt->rt6i_idev     = idev;
@@ -1873,7 +1897,10 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
                        in6_dev_hold(rt->rt6i_idev);
                rt->dst.lastuse = jiffies;
 
-               rt->rt6i_gateway = ort->rt6i_gateway;
+               if (ort->rt6i_flags & RTF_GATEWAY)
+                       rt->rt6i_gateway = ort->rt6i_gateway;
+               else
+                       rt->rt6i_gateway = *dest;
                rt->rt6i_flags = ort->rt6i_flags;
                if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
                    (RTF_DEFAULT | RTF_ADDRCONF))
@@ -2160,6 +2187,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
        else
                rt->rt6i_flags |= RTF_LOCAL;
 
+       rt->rt6i_gateway  = *addr;
        rt->rt6i_dst.addr = *addr;
        rt->rt6i_dst.plen = 128;
        rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL);
index 72b7eaaf3ca0e3e6b7cad3edea8aa69e71cbe147..18786098fd412dd5fa95a9fc096195f387b53fa0 100644 (file)
@@ -1225,9 +1225,6 @@ do_udp_sendmsg:
        if (tclass < 0)
                tclass = np->tclass;
 
-       if (dontfrag < 0)
-               dontfrag = np->dontfrag;
-
        if (msg->msg_flags&MSG_CONFIRM)
                goto do_confirm;
 back_from_confirm:
@@ -1246,6 +1243,8 @@ back_from_confirm:
        up->pending = AF_INET6;
 
 do_append_data:
+       if (dontfrag < 0)
+               dontfrag = np->dontfrag;
        up->len += ulen;
        getfrag  =  is_udplite ?  udplite_getfrag : ip_generic_getfrag;
        err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen,
index 23ed03d786c8376cc59f9fa2cf577ee01a4c2c2d..08ed2772b7aa58225bd6be95518ea95c1191dcd9 100644 (file)
@@ -138,6 +138,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 
        memset(fl6, 0, sizeof(struct flowi6));
        fl6->flowi6_mark = skb->mark;
+       fl6->flowi6_oif = skb_dst(skb)->dev->ifindex;
 
        fl6->daddr = reverse ? hdr->saddr : hdr->daddr;
        fl6->saddr = reverse ? hdr->daddr : hdr->saddr;
index 9d585370c5b4d6a1e60728df4dad6c79ca196ee3..911ef03bf8fbf1716672fb503f39de7fe13746d9 100644 (file)
@@ -1098,7 +1098,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 
        x->id.proto = proto;
        x->id.spi = sa->sadb_sa_spi;
-       x->props.replay_window = sa->sadb_sa_replay;
+       x->props.replay_window = min_t(unsigned int, sa->sadb_sa_replay,
+                                       (sizeof(x->replay.bitmap) * 8));
        if (sa->sadb_sa_flags & SADB_SAFLAGS_NOECN)
                x->props.flags |= XFRM_STATE_NOECN;
        if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)
index feae495a0a30accd9eb5a88baf1c23095bb38d66..b076e8309bc2722885c27108316634f064cb44ff 100644 (file)
@@ -115,6 +115,11 @@ struct l2tp_net {
 static void l2tp_session_set_header_len(struct l2tp_session *session, int version);
 static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel);
 
+static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk)
+{
+       return sk->sk_user_data;
+}
+
 static inline struct l2tp_net *l2tp_pernet(struct net *net)
 {
        BUG_ON(!net);
@@ -504,7 +509,7 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk,
                return 0;
 
 #if IS_ENABLED(CONFIG_IPV6)
-       if (sk->sk_family == PF_INET6) {
+       if (sk->sk_family == PF_INET6 && !l2tp_tunnel(sk)->v4mapped) {
                if (!uh->check) {
                        LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n");
                        return 1;
@@ -1128,7 +1133,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
        /* Queue the packet to IP for output */
        skb->local_df = 1;
 #if IS_ENABLED(CONFIG_IPV6)
-       if (skb->sk->sk_family == PF_INET6)
+       if (skb->sk->sk_family == PF_INET6 && !tunnel->v4mapped)
                error = inet6_csk_xmit(skb, NULL);
        else
 #endif
@@ -1255,7 +1260,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
 
                /* Calculate UDP checksum if configured to do so */
 #if IS_ENABLED(CONFIG_IPV6)
-               if (sk->sk_family == PF_INET6)
+               if (sk->sk_family == PF_INET6 && !tunnel->v4mapped)
                        l2tp_xmit_ipv6_csum(sk, skb, udp_len);
                else
 #endif
@@ -1304,10 +1309,9 @@ EXPORT_SYMBOL_GPL(l2tp_xmit_skb);
  */
 static void l2tp_tunnel_destruct(struct sock *sk)
 {
-       struct l2tp_tunnel *tunnel;
+       struct l2tp_tunnel *tunnel = l2tp_tunnel(sk);
        struct l2tp_net *pn;
 
-       tunnel = sk->sk_user_data;
        if (tunnel == NULL)
                goto end;
 
@@ -1675,7 +1679,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
        }
 
        /* Check if this socket has already been prepped */
-       tunnel = (struct l2tp_tunnel *)sk->sk_user_data;
+       tunnel = l2tp_tunnel(sk);
        if (tunnel != NULL) {
                /* This socket has already been prepped */
                err = -EBUSY;
@@ -1704,6 +1708,24 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
        if (cfg != NULL)
                tunnel->debug = cfg->debug;
 
+#if IS_ENABLED(CONFIG_IPV6)
+       if (sk->sk_family == PF_INET6) {
+               struct ipv6_pinfo *np = inet6_sk(sk);
+
+               if (ipv6_addr_v4mapped(&np->saddr) &&
+                   ipv6_addr_v4mapped(&np->daddr)) {
+                       struct inet_sock *inet = inet_sk(sk);
+
+                       tunnel->v4mapped = true;
+                       inet->inet_saddr = np->saddr.s6_addr32[3];
+                       inet->inet_rcv_saddr = np->rcv_saddr.s6_addr32[3];
+                       inet->inet_daddr = np->daddr.s6_addr32[3];
+               } else {
+                       tunnel->v4mapped = false;
+               }
+       }
+#endif
+
        /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
        tunnel->encap = encap;
        if (encap == L2TP_ENCAPTYPE_UDP) {
@@ -1712,7 +1734,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
                udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv;
                udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy;
 #if IS_ENABLED(CONFIG_IPV6)
-               if (sk->sk_family == PF_INET6)
+               if (sk->sk_family == PF_INET6 && !tunnel->v4mapped)
                        udpv6_encap_enable();
                else
 #endif
index 66a559b104b6a7af0bc5c76770c32ad0f816670c..6f251cbc2ed787409794f3f5063312ef7b9e9c72 100644 (file)
@@ -194,6 +194,9 @@ struct l2tp_tunnel {
        struct sock             *sock;          /* Parent socket */
        int                     fd;             /* Parent fd, if tunnel socket
                                                 * was created by userspace */
+#if IS_ENABLED(CONFIG_IPV6)
+       bool                    v4mapped;
+#endif
 
        struct work_struct      del_work;
 
index 5ebee2ded9e9a8f40d2a282600b47f6cb088a910..8c46b271064a43607190198e76c1e1ff4c540396 100644 (file)
@@ -353,7 +353,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);
@@ -422,7 +424,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);
index 2e7855a1b10d17198adcfec98d550838daef80bd..629dee7ec9bfbae6dc0f00cdaf91b58968980c99 100644 (file)
@@ -3518,7 +3518,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
                return -EINVAL;
        }
        band = chanctx_conf->def.chan->band;
-       sta = sta_info_get(sdata, peer);
+       sta = sta_info_get_bss(sdata, peer);
        if (sta) {
                qos = test_sta_flag(sta, WLAN_STA_WME);
        } else {
index b6186517ec567e85eb986d77dd6ff72c36a4379d..611abfcfb5ebba3c135edbcf8b2efb4a47f38374 100644 (file)
@@ -893,6 +893,8 @@ 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,
@@ -900,6 +902,7 @@ enum {
        SCAN_ONCHANNEL_SCANNING,
        SCAN_COMPLETED,
        SCAN_ABORTED,
+       SCAN_HW_CANCELLED,
 };
 
 /**
index acd1f71adc0386ab588f0939309e2367330f2b29..0c2a29484c07cdaaaf716b1f5ba0184d1047ee68 100644 (file)
@@ -394,6 +394,8 @@ void ieee80211_sw_roc_work(struct work_struct *work)
 
                if (started)
                        ieee80211_start_next_roc(local);
+               else if (list_empty(&local->roc_list))
+                       ieee80211_run_deferred_scan(local);
        }
 
  out_unlock:
index 54395d7583ba70e31111b08092c88d2901be7815..674eac1f996c9ddd664f2f70022514efc228b109 100644 (file)
@@ -3056,6 +3056,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
        case NL80211_IFTYPE_ADHOC:
                if (!bssid)
                        return 0;
+               if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
+                   ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
+                       return 0;
                if (ieee80211_is_beacon(hdr->frame_control)) {
                        return 1;
                } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
index 08afe74b98f4b6cbdda21ed3d8ff68b9a95fa64b..d2d17a4492245953413c5742d22d2af9e15fd74d 100644 (file)
@@ -238,6 +238,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;
@@ -940,7 +943,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,
                                rcu_dereference_protected(local->scan_sdata,
index 368837fe3b800e87f408039ef4d36e84bfaa7069..78dc2e99027e06b8a9fc37f5bdf7f06483476f2b 100644 (file)
@@ -180,6 +180,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);
index 3456c0486b482bfb44a6f797ebaff5d70bde4940..70b5a05c0a4e12b8cb36252465171ffbc7ef1686 100644 (file)
@@ -1120,7 +1120,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
                tx->sta = rcu_dereference(sdata->u.vlan.sta);
                if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
                        return TX_DROP;
-       } else if (info->flags & IEEE80211_TX_CTL_INJECTED ||
+       } else if (info->flags & (IEEE80211_TX_CTL_INJECTED |
+                                 IEEE80211_TX_INTFL_NL80211_FRAME_TX) ||
                   tx->sdata->control_port_protocol == tx->skb->protocol) {
                tx->sta = sta_info_get_bss(sdata, hdr->addr1);
        }
index e1b34a18b24344cb95a642c436fc5322054207ce..69e4ef5348a0e916b76fa87de9d83402ec99a5e4 100644 (file)
@@ -2103,7 +2103,7 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband;
-       int rate, skip, shift;
+       int rate, shift;
        u8 i, exrates, *pos;
        u32 basic_rates = sdata->vif.bss_conf.basic_rates;
        u32 rate_flags;
@@ -2131,14 +2131,11 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
                pos = skb_put(skb, exrates + 2);
                *pos++ = WLAN_EID_EXT_SUPP_RATES;
                *pos++ = exrates;
-               skip = 0;
                for (i = 8; i < sband->n_bitrates; i++) {
                        u8 basic = 0;
                        if ((rate_flags & sband->bitrates[i].flags)
                            != rate_flags)
                                continue;
-                       if (skip++ < 8)
-                               continue;
                        if (need_basic && basic_rates & BIT(i))
                                basic = 0x80;
                        rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
@@ -2241,6 +2238,10 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
        }
 
        rate = cfg80211_calculate_bitrate(&ri);
+       if (WARN_ONCE(!rate,
+                     "Invalid bitrate: flags=0x%x, idx=%d, vht_nss=%d\n",
+                     status->flag, status->rate_idx, status->vht_nss))
+               return 0;
 
        /* rewind from end of MPDU */
        if (status->flag & RX_FLAG_MACTIME_END)
index bdebd03bc8cd448a75ca94db1c88ea461f72093a..70866d192efc9351f2fcafe3ef23ce0c131fc0ba 100644 (file)
@@ -778,8 +778,8 @@ static int callforward_do_filter(const union nf_inet_addr *src,
                                   flowi6_to_flowi(&fl1), false)) {
                        if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
                                           flowi6_to_flowi(&fl2), false)) {
-                               if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,
-                                           sizeof(rt1->rt6i_gateway)) &&
+                               if (ipv6_addr_equal(rt6_nexthop(rt1),
+                                                   rt6_nexthop(rt2)) &&
                                    rt1->dst.dev == rt2->dst.dev)
                                        ret = 1;
                                dst_release(&rt2->dst);
index a2fef8b10b960c15d29556b7dc832737c848b3b6..a9dfdda9ed1d55d17643f36ba05d9ac04ce1557d 100644 (file)
@@ -472,20 +472,16 @@ begin:
        if (f->credit > 0 || !q->rate_enable)
                goto out;
 
-       if (skb->sk && skb->sk->sk_state != TCP_TIME_WAIT) {
-               rate = skb->sk->sk_pacing_rate ?: q->flow_default_rate;
+       rate = q->flow_max_rate;
+       if (skb->sk && skb->sk->sk_state != TCP_TIME_WAIT)
+               rate = min(skb->sk->sk_pacing_rate, rate);
 
-               rate = min(rate, q->flow_max_rate);
-       } else {
-               rate = q->flow_max_rate;
-               if (rate == ~0U)
-                       goto out;
-       }
-       if (rate) {
+       if (rate != ~0U) {
                u32 plen = max(qdisc_pkt_len(skb), q->quantum);
                u64 len = (u64)plen * NSEC_PER_SEC;
 
-               do_div(len, rate);
+               if (likely(rate))
+                       do_div(len, rate);
                /* Since socket rate can change later,
                 * clamp the delay to 125 ms.
                 * TODO: maybe segment the too big skb, as in commit
@@ -656,7 +652,7 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
                q->quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
 
        if (tb[TCA_FQ_INITIAL_QUANTUM])
-               q->quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
+               q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
 
        if (tb[TCA_FQ_FLOW_DEFAULT_RATE])
                q->flow_default_rate = nla_get_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]);
@@ -735,12 +731,14 @@ static int fq_dump(struct Qdisc *sch, struct sk_buff *skb)
        if (opts == NULL)
                goto nla_put_failure;
 
+       /* TCA_FQ_FLOW_DEFAULT_RATE is not used anymore,
+        * do not bother giving its value
+        */
        if (nla_put_u32(skb, TCA_FQ_PLIMIT, sch->limit) ||
            nla_put_u32(skb, TCA_FQ_FLOW_PLIMIT, q->flow_plimit) ||
            nla_put_u32(skb, TCA_FQ_QUANTUM, q->quantum) ||
            nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM, q->initial_quantum) ||
            nla_put_u32(skb, TCA_FQ_RATE_ENABLE, q->rate_enable) ||
-           nla_put_u32(skb, TCA_FQ_FLOW_DEFAULT_RATE, q->flow_default_rate) ||
            nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) ||
            nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log))
                goto nla_put_failure;
index a6d788d45216a6f286e5aaea0cdb0587cd0f7848..b87e83d0747821bc2251c3b099f91a3358c211d9 100644 (file)
@@ -358,6 +358,21 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche
        return PSCHED_NS2TICKS(ticks);
 }
 
+static void tfifo_reset(struct Qdisc *sch)
+{
+       struct netem_sched_data *q = qdisc_priv(sch);
+       struct rb_node *p;
+
+       while ((p = rb_first(&q->t_root))) {
+               struct sk_buff *skb = netem_rb_to_skb(p);
+
+               rb_erase(p, &q->t_root);
+               skb->next = NULL;
+               skb->prev = NULL;
+               kfree_skb(skb);
+       }
+}
+
 static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
 {
        struct netem_sched_data *q = qdisc_priv(sch);
@@ -520,6 +535,7 @@ static unsigned int netem_drop(struct Qdisc *sch)
                        skb->next = NULL;
                        skb->prev = NULL;
                        len = qdisc_pkt_len(skb);
+                       sch->qstats.backlog -= len;
                        kfree_skb(skb);
                }
        }
@@ -609,6 +625,7 @@ static void netem_reset(struct Qdisc *sch)
        struct netem_sched_data *q = qdisc_priv(sch);
 
        qdisc_reset_queue(sch);
+       tfifo_reset(sch);
        if (q->qdisc)
                qdisc_reset(q->qdisc);
        qdisc_watchdog_cancel(&q->watchdog);
index 0ac3a65daccb71cd78ae5e2c52696c33df7e16e4..319137340d158df36094c45b8eae1fc13df50825 100644 (file)
@@ -536,7 +536,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
         * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
         */
        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
index ebed4b68f768a1afccea45ea7dc22ef555f3f679..c226aceee65b8b8c59d93d6a133a04c86177ceef 100644 (file)
@@ -1964,6 +1964,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 int flags,
                         struct used_address *used_address)
@@ -1982,8 +1992,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;
+       }
 
        if (msg_sys->msg_iovlen > UIO_FASTIOV) {
                err = -EMSGSIZE;
@@ -2191,8 +2204,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;
+       }
 
        if (msg_sys->msg_iovlen > UIO_FASTIOV) {
                err = -EMSGSIZE;
index 86de99ad297605d04356f9efd7be174d2f7c7993..c1f403bed683ee8653356870f35457fe6e7f18eb 100644 (file)
@@ -1246,6 +1246,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;
@@ -1280,6 +1289,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;
index d591091603bfe4da1d6a87810287bdd5aaecc6da..86fa0f3b2cafa46d47db9cd03e46dfe89c22d238 100644 (file)
@@ -124,6 +124,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);
 
index 67153964aad2059652ffd34d79c956585cc9c1e3..aff959e5a1b360e7cb467cade7f7d617544b3909 100644 (file)
@@ -566,18 +566,13 @@ int wiphy_register(struct wiphy *wiphy)
        /* check and set up bitrates */
        ieee80211_set_bitrate_flags(wiphy);
 
-
+       rtnl_lock();
        res = device_add(&rdev->wiphy.dev);
-       if (res)
-               return res;
-
-       res = rfkill_register(rdev->rfkill);
        if (res) {
-               device_del(&rdev->wiphy.dev);
+               rtnl_unlock();
                return res;
        }
 
-       rtnl_lock();
        /* set up regulatory info */
        wiphy_regulatory_register(wiphy);
 
@@ -606,6 +601,15 @@ int wiphy_register(struct wiphy *wiphy)
 
        rdev->wiphy.registered = true;
        rtnl_unlock();
+
+       res = rfkill_register(rdev->rfkill);
+       if (res) {
+               rfkill_destroy(rdev->rfkill);
+               rdev->rfkill = NULL;
+               wiphy_unregister(&rdev->wiphy);
+               return res;
+       }
+
        return 0;
 }
 EXPORT_SYMBOL(wiphy_register);
@@ -640,7 +644,8 @@ void wiphy_unregister(struct wiphy *wiphy)
                rtnl_unlock();
                __count == 0; }));
 
-       rfkill_unregister(rdev->rfkill);
+       if (rdev->rfkill)
+               rfkill_unregister(rdev->rfkill);
 
        rtnl_lock();
        rdev->wiphy.registered = false;
@@ -953,8 +958,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
        case NETDEV_PRE_UP:
                if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
                        return notifier_from_errno(-EOPNOTSUPP);
-               if (rfkill_blocked(rdev->rfkill))
-                       return notifier_from_errno(-ERFKILL);
                ret = cfg80211_can_add_interface(rdev, wdev->iftype);
                if (ret)
                        return notifier_from_errno(ret);
index 9ad43c619c54830f915193daa60eadef92b5bda5..3159e9c284c5b10c3b7cd0cf4d384d278b0a6245 100644 (file)
@@ -411,6 +411,9 @@ static inline int
 cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
                           enum nl80211_iftype iftype)
 {
+       if (rfkill_blocked(rdev->rfkill))
+               return -ERFKILL;
+
        return cfg80211_can_change_interface(rdev, NULL, iftype);
 }
 
index 39bff7d367687fbdd4d220d76e34d66e4e586a9c..403fe29c024db86f732b0c0d74b8d97d4cfc84bf 100644 (file)
@@ -263,6 +263,8 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
                                if (chan->flags & IEEE80211_CHAN_DISABLED)
                                        continue;
                                wdev->wext.ibss.chandef.chan = chan;
+                               wdev->wext.ibss.chandef.center_freq1 =
+                                       chan->center_freq;
                                break;
                        }
 
@@ -347,6 +349,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
        if (chan) {
                wdev->wext.ibss.chandef.chan = chan;
                wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+               wdev->wext.ibss.chandef.center_freq1 = freq;
                wdev->wext.ibss.channel_fixed = true;
        } else {
                /* cfg80211_ibss_wext_join will pick one if needed */
index af8d84a4a5b2a05fab2de732722e6535c8e699d0..626dc3b5fd8d205305b8ddfecaf106c33adcb9d6 100644 (file)
@@ -2421,7 +2421,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
                change = true;
        }
 
-       if (flags && (*flags & NL80211_MNTR_FLAG_ACTIVE) &&
+       if (flags && (*flags & MONITOR_FLAG_ACTIVE) &&
            !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
                return -EOPNOTSUPP;
 
@@ -2483,7 +2483,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                                  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
                                  &flags);
 
-       if (!err && (flags & NL80211_MNTR_FLAG_ACTIVE) &&
+       if (!err && (flags & MONITOR_FLAG_ACTIVE) &&
            !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
                return -EOPNOTSUPP;
 
index 7d604c06c3dc38d1155366a52f184971be1197e3..a271c27fac774ce987c0db6f1330ffbfca6dc7f7 100644 (file)
@@ -97,6 +97,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;
@@ -131,7 +135,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;
                }
index ed38d5d81f9e1f4890cf36447713badd48691489..76e1873811d4cac098cd4d563e865e847997a4a4 100644 (file)
@@ -334,7 +334,8 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
 
        atomic_inc(&policy->genid);
 
-       del_timer(&policy->polq.hold_timer);
+       if (del_timer(&policy->polq.hold_timer))
+               xfrm_pol_put(policy);
        xfrm_queue_purge(&policy->polq.hold_queue);
 
        if (del_timer(&policy->timer))
@@ -589,7 +590,8 @@ static void xfrm_policy_requeue(struct xfrm_policy *old,
 
        spin_lock_bh(&pq->hold_queue.lock);
        skb_queue_splice_init(&pq->hold_queue, &list);
-       del_timer(&pq->hold_timer);
+       if (del_timer(&pq->hold_timer))
+               xfrm_pol_put(old);
        spin_unlock_bh(&pq->hold_queue.lock);
 
        if (skb_queue_empty(&list))
@@ -600,7 +602,8 @@ static void xfrm_policy_requeue(struct xfrm_policy *old,
        spin_lock_bh(&pq->hold_queue.lock);
        skb_queue_splice(&list, &pq->hold_queue);
        pq->timeout = XFRM_QUEUE_TMO_MIN;
-       mod_timer(&pq->hold_timer, jiffies);
+       if (!mod_timer(&pq->hold_timer, jiffies))
+               xfrm_pol_hold(new);
        spin_unlock_bh(&pq->hold_queue.lock);
 }
 
@@ -1769,6 +1772,10 @@ static void xfrm_policy_queue_process(unsigned long arg)
 
        spin_lock(&pq->hold_queue.lock);
        skb = skb_peek(&pq->hold_queue);
+       if (!skb) {
+               spin_unlock(&pq->hold_queue.lock);
+               goto out;
+       }
        dst = skb_dst(skb);
        sk = skb->sk;
        xfrm_decode_session(skb, &fl, dst->ops->family);
@@ -1787,8 +1794,9 @@ static void xfrm_policy_queue_process(unsigned long arg)
                        goto purge_queue;
 
                pq->timeout = pq->timeout << 1;
-               mod_timer(&pq->hold_timer, jiffies + pq->timeout);
-               return;
+               if (!mod_timer(&pq->hold_timer, jiffies + pq->timeout))
+                       xfrm_pol_hold(pol);
+       goto out;
        }
 
        dst_release(dst);
@@ -1819,11 +1827,14 @@ static void xfrm_policy_queue_process(unsigned long arg)
                err = dst_output(skb);
        }
 
+out:
+       xfrm_pol_put(pol);
        return;
 
 purge_queue:
        pq->timeout = 0;
        xfrm_queue_purge(&pq->hold_queue);
+       xfrm_pol_put(pol);
 }
 
 static int xdst_queue_output(struct sk_buff *skb)
@@ -1831,7 +1842,8 @@ static int xdst_queue_output(struct sk_buff *skb)
        unsigned long sched_next;
        struct dst_entry *dst = skb_dst(skb);
        struct xfrm_dst *xdst = (struct xfrm_dst *) dst;
-       struct xfrm_policy_queue *pq = &xdst->pols[0]->polq;
+       struct xfrm_policy *pol = xdst->pols[0];
+       struct xfrm_policy_queue *pq = &pol->polq;
 
        if (pq->hold_queue.qlen > XFRM_MAX_QUEUE_LEN) {
                kfree_skb(skb);
@@ -1850,10 +1862,12 @@ static int xdst_queue_output(struct sk_buff *skb)
        if (del_timer(&pq->hold_timer)) {
                if (time_before(pq->hold_timer.expires, sched_next))
                        sched_next = pq->hold_timer.expires;
+               xfrm_pol_put(pol);
        }
 
        __skb_queue_tail(&pq->hold_queue, skb);
-       mod_timer(&pq->hold_timer, sched_next);
+       if (!mod_timer(&pq->hold_timer, sched_next))
+               xfrm_pol_hold(pol);
 
        spin_unlock_bh(&pq->hold_queue.lock);
 
index 8dafe6d3c6e41ebd20e5d0347d4ab9b0e6326a34..dab57daae40856030790fa8070068a59d82220af 100644 (file)
@@ -61,9 +61,9 @@ static void xfrm_replay_notify(struct xfrm_state *x, int event)
 
        switch (event) {
        case XFRM_REPLAY_UPDATE:
-               if (x->replay_maxdiff &&
-                   (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
-                   (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
+               if (!x->replay_maxdiff ||
+                   ((x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
+                   (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))) {
                        if (x->xflags & XFRM_TIME_DEFER)
                                event = XFRM_REPLAY_TIMEOUT;
                        else
@@ -129,8 +129,7 @@ static int xfrm_replay_check(struct xfrm_state *x,
                return 0;
 
        diff = x->replay.seq - seq;
-       if (diff >= min_t(unsigned int, x->props.replay_window,
-                         sizeof(x->replay.bitmap) * 8)) {
+       if (diff >= x->props.replay_window) {
                x->stats.replay_window++;
                goto err;
        }
@@ -302,9 +301,10 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
 
        switch (event) {
        case XFRM_REPLAY_UPDATE:
-               if (x->replay_maxdiff &&
-                   (replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
-                   (replay_esn->oseq - preplay_esn->oseq < x->replay_maxdiff)) {
+               if (!x->replay_maxdiff ||
+                   ((replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
+                   (replay_esn->oseq - preplay_esn->oseq
+                    < x->replay_maxdiff))) {
                        if (x->xflags & XFRM_TIME_DEFER)
                                event = XFRM_REPLAY_TIMEOUT;
                        else
@@ -353,28 +353,30 @@ static void xfrm_replay_notify_esn(struct xfrm_state *x, int event)
 
        switch (event) {
        case XFRM_REPLAY_UPDATE:
-               if (!x->replay_maxdiff)
-                       break;
-
-               if (replay_esn->seq_hi == preplay_esn->seq_hi)
-                       seq_diff = replay_esn->seq - preplay_esn->seq;
-               else
-                       seq_diff = ~preplay_esn->seq + replay_esn->seq + 1;
-
-               if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
-                       oseq_diff = replay_esn->oseq - preplay_esn->oseq;
-               else
-                       oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1;
-
-               if (seq_diff < x->replay_maxdiff &&
-                   oseq_diff < x->replay_maxdiff) {
+               if (x->replay_maxdiff) {
+                       if (replay_esn->seq_hi == preplay_esn->seq_hi)
+                               seq_diff = replay_esn->seq - preplay_esn->seq;
+                       else
+                               seq_diff = ~preplay_esn->seq + replay_esn->seq
+                                          + 1;
 
-                       if (x->xflags & XFRM_TIME_DEFER)
-                               event = XFRM_REPLAY_TIMEOUT;
+                       if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
+                               oseq_diff = replay_esn->oseq
+                                           - preplay_esn->oseq;
                        else
-                               return;
+                               oseq_diff = ~preplay_esn->oseq
+                                           + replay_esn->oseq + 1;
+
+                       if (seq_diff >= x->replay_maxdiff ||
+                           oseq_diff >= x->replay_maxdiff)
+                               break;
                }
 
+               if (x->xflags & XFRM_TIME_DEFER)
+                       event = XFRM_REPLAY_TIMEOUT;
+               else
+                       return;
+
                break;
 
        case XFRM_REPLAY_TIMEOUT:
index 3f565e495ac68cea83e1d52cf7db7e820fe777ad..f964d4c00ffb53457aa46b24f0225249c1d46b7c 100644 (file)
@@ -446,7 +446,8 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
        memcpy(&x->sel, &p->sel, sizeof(x->sel));
        memcpy(&x->lft, &p->lft, sizeof(x->lft));
        x->props.mode = p->mode;
-       x->props.replay_window = p->replay_window;
+       x->props.replay_window = min_t(unsigned int, p->replay_window,
+                                       sizeof(x->replay.bitmap) * 8);
        x->props.reqid = p->reqid;
        x->props.family = p->family;
        memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
@@ -1856,7 +1857,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (x->km.state != XFRM_STATE_VALID)
                goto out;
 
-       err = xfrm_replay_verify_len(x->replay_esn, rp);
+       err = xfrm_replay_verify_len(x->replay_esn, re);
        if (err)
                goto out;
 
index 95c2b2689a03aa521bc923323f521a8c191d107d..7db9954f1af2c56c42400746f367f5f4d9906ca8 100644 (file)
@@ -580,15 +580,13 @@ static struct aa_namespace *__next_namespace(struct aa_namespace *root,
 
        /* check if the next ns is a sibling, parent, gp, .. */
        parent = ns->parent;
-       while (parent) {
+       while (ns != root) {
                mutex_unlock(&ns->lock);
                next = list_entry_next(ns, base.list);
                if (!list_entry_is_head(next, &parent->sub_ns, base.list)) {
                        mutex_lock(&next->lock);
                        return next;
                }
-               if (parent == root)
-                       return NULL;
                ns = parent;
                parent = parent->parent;
        }
index 345bec07a27d9292dbfc1306d1f5e12563eaa891..705c2879d3a94a79e10d1190468483c2f9d7192a 100644 (file)
@@ -610,6 +610,7 @@ void aa_free_profile(struct aa_profile *profile)
        aa_put_dfa(profile->policy.dfa);
        aa_put_replacedby(profile->replacedby);
 
+       kzfree(profile->hash);
        kzfree(profile);
 }
 
index ac41e9cdc976a1c190c51684519abb9c475c2c59..26ad4f0aade3fcf2c26940c008fae9a55c63244c 100644 (file)
@@ -3531,7 +3531,7 @@ static int create_capture_mixers(struct hda_codec *codec)
                if (!multi)
                        err = create_single_cap_vol_ctl(codec, n, vol, sw,
                                                        inv_dmic);
-               else if (!multi_cap_vol)
+               else if (!multi_cap_vol && !inv_dmic)
                        err = create_bind_cap_vol_ctl(codec, n, vol, sw);
                else
                        err = create_multi_cap_vol_ctl(codec);
index 4f255dfee4504454702bfdec305b1b72820a26ac..f59a321a6d6af04d6dce32751410e4eb3f9d9df0 100644 (file)
@@ -4845,6 +4845,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne
                        if ((err = hdsp_get_iobox_version(hdsp)) < 0)
                                return err;
                }
+               memset(&hdsp_version, 0, sizeof(hdsp_version));
                hdsp_version.io_type = hdsp->io_type;
                hdsp_version.firmware_rev = hdsp->firmware_rev;
                if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))))
index 651ce09236755ff9938062e3e719926fad856f9a..c91eba504f92bc053dd2a51b8f62c7bff6bcc2d6 100644 (file)
@@ -270,7 +270,7 @@ MODULE_DEVICE_TABLE(of, pcm1681_dt_ids);
 static const struct regmap_config pcm1681_regmap = {
        .reg_bits               = 8,
        .val_bits               = 8,
-       .max_register           = ARRAY_SIZE(pcm1681_reg_defaults) + 1,
+       .max_register           = 0x13,
        .reg_defaults           = pcm1681_reg_defaults,
        .num_reg_defaults       = ARRAY_SIZE(pcm1681_reg_defaults),
        .writeable_reg          = pcm1681_writeable_reg,
index 2a8eccf64c76565ab5abb96f3436face0dda4f01..7613181123fe393042643847f4e2b5dbf4c89285 100644 (file)
@@ -188,7 +188,7 @@ MODULE_DEVICE_TABLE(of, pcm1792a_of_match);
 static const struct regmap_config pcm1792a_regmap = {
        .reg_bits               = 8,
        .val_bits               = 8,
-       .max_register           = 24,
+       .max_register           = 23,
        .reg_defaults           = pcm1792a_reg_defaults,
        .num_reg_defaults       = ARRAY_SIZE(pcm1792a_reg_defaults),
        .writeable_reg          = pcm1792a_writeable_reg,
index 6e3f269243e050fe5149e60807c0e41cbf6e4147..64ad84d8a3061e5e4ba824c7178d10f87921c797 100644 (file)
@@ -674,6 +674,8 @@ static const struct snd_soc_dapm_route intercon[] = {
        /* Left Input */
        {"Left Line1L Mux", "single-ended", "LINE1L"},
        {"Left Line1L Mux", "differential", "LINE1L"},
+       {"Left Line1R Mux", "single-ended", "LINE1R"},
+       {"Left Line1R Mux", "differential", "LINE1R"},
 
        {"Left Line2L Mux", "single-ended", "LINE2L"},
        {"Left Line2L Mux", "differential", "LINE2L"},
@@ -690,6 +692,8 @@ static const struct snd_soc_dapm_route intercon[] = {
        /* Right Input */
        {"Right Line1R Mux", "single-ended", "LINE1R"},
        {"Right Line1R Mux", "differential", "LINE1R"},
+       {"Right Line1L Mux", "single-ended", "LINE1L"},
+       {"Right Line1L Mux", "differential", "LINE1L"},
 
        {"Right Line2R Mux", "single-ended", "LINE2R"},
        {"Right Line2R Mux", "differential", "LINE2R"},
index c6b743978d5ecdcdf402ddb43df0b7bd0400c422..6b81d0ce2c44ac637188fffdb67f10289f17f67a 100644 (file)
@@ -936,7 +936,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
        ssi_private->ssi_phys = res.start;
 
        ssi_private->irq = irq_of_parse_and_map(np, 0);
-       if (ssi_private->irq == NO_IRQ) {
+       if (ssi_private->irq == 0) {
                dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
                return -ENXIO;
        }
index a3d60d4bea4ce8ace84d2860921b5c46d3f00895..a2fd7321b5a9a1bbd321f756af14fd9f071a372f 100644 (file)
@@ -112,7 +112,7 @@ static int imx_mc13783_probe(struct platform_device *pdev)
                return ret;
        }
 
-       if (machine_is_mx31_3ds()) {
+       if (machine_is_mx31_3ds() || machine_is_mx31moboard()) {
                imx_audmux_v2_configure_port(MX31_AUDMUX_PORT4_SSI_PINS_4,
                        IMX_AUDMUX_V2_PTCR_SYN,
                        IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0) |
index f58bcd85c07fbd8b302c0c3bcd97fd3cf6ed4d0c..57d6941676ffabc509754317337bf109e16376a3 100644 (file)
@@ -600,19 +600,17 @@ static int imx_ssi_probe(struct platform_device *pdev)
        ssi->fiq_params.dma_params_rx = &ssi->dma_params_rx;
        ssi->fiq_params.dma_params_tx = &ssi->dma_params_tx;
 
-       ret = imx_pcm_fiq_init(pdev, &ssi->fiq_params);
-       if (ret)
-               goto failed_pcm_fiq;
+       ssi->fiq_init = imx_pcm_fiq_init(pdev, &ssi->fiq_params);
+       ssi->dma_init = imx_pcm_dma_init(pdev);
 
-       ret = imx_pcm_dma_init(pdev);
-       if (ret)
-               goto failed_pcm_dma;
+       if (ssi->fiq_init && ssi->dma_init) {
+               ret = ssi->fiq_init;
+               goto failed_pcm;
+       }
 
        return 0;
 
-failed_pcm_dma:
-       imx_pcm_fiq_exit(pdev);
-failed_pcm_fiq:
+failed_pcm:
        snd_soc_unregister_component(&pdev->dev);
 failed_register:
        release_mem_region(res->start, resource_size(res));
@@ -628,8 +626,11 @@ static int imx_ssi_remove(struct platform_device *pdev)
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        struct imx_ssi *ssi = platform_get_drvdata(pdev);
 
-       imx_pcm_dma_exit(pdev);
-       imx_pcm_fiq_exit(pdev);
+       if (!ssi->dma_init)
+               imx_pcm_dma_exit(pdev);
+
+       if (!ssi->fiq_init)
+               imx_pcm_fiq_exit(pdev);
 
        snd_soc_unregister_component(&pdev->dev);
 
index fb1616ba8c5967e1892b4ff6c7e180b2b9447047..560c40fc9ebbb50241e3732f3a76ece064178bf2 100644 (file)
@@ -211,6 +211,8 @@ struct imx_ssi {
        struct imx_dma_data filter_data_rx;
        struct imx_pcm_fiq_params fiq_params;
 
+       int fiq_init;
+       int dma_init;
        int enabled;
 };
 
index daa78a0095facf5ff35d1eb0b6ca61836b7c9210..4a07f7179690d36e3526cb8bcf9c4fc20e2ca509 100644 (file)
@@ -1,6 +1,6 @@
 config SND_OMAP_SOC
        tristate "SoC Audio for the Texas Instruments OMAP chips"
-       depends on (ARCH_OMAP && DMA_OMAP) || (ARCH_ARM && COMPILE_TEST)
+       depends on (ARCH_OMAP && DMA_OMAP) || (ARM && COMPILE_TEST)
        select SND_DMAENGINE_PCM
 
 config SND_OMAP_SOC_DMIC
@@ -26,7 +26,7 @@ config SND_OMAP_SOC_N810
 
 config SND_OMAP_SOC_RX51
        tristate "SoC Audio support for Nokia RX-51"
-       depends on SND_OMAP_SOC && ARCH_ARM && (MACH_NOKIA_RX51 || COMPILE_TEST)
+       depends on SND_OMAP_SOC && ARM && (MACH_NOKIA_RX51 || COMPILE_TEST)
        select SND_OMAP_SOC_MCBSP
        select SND_SOC_TLV320AIC3X
        select SND_SOC_TPA6130A2
index 9cc6986a8cfb347465a9aa442b3b4e79a4f8d9f6..5dd87f4c919e50650e61e8084856138d47f6f119 100644 (file)
@@ -220,8 +220,8 @@ int rsnd_gen_path_exit(struct rsnd_priv *priv,
 void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
                               struct rsnd_mod *mod,
                               enum rsnd_reg reg);
-#define rsnd_is_gen1(s)                ((s)->info->flags & RSND_GEN1)
-#define rsnd_is_gen2(s)                ((s)->info->flags & RSND_GEN2)
+#define rsnd_is_gen1(s)                (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1)
+#define rsnd_is_gen2(s)                (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2)
 
 /*
  *     R-Car ADG
index d0323a693ba20f4719731369f85324e9ba582096..999550bbad40e66f259d9ed2b044ed478e377d72 100644 (file)
@@ -262,7 +262,9 @@ static int usb_stream_hwdep_mmap(struct snd_hwdep *hw,
        }
 
        area->vm_ops = &usb_stream_hwdep_vm_ops;
-       area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+       area->vm_flags |= VM_DONTDUMP;
+       if (!read)
+               area->vm_flags |= VM_DONTEXPAND;
        area->vm_private_data = us122l;
        atomic_inc(&us122l->mmap_count);
 out:
index 9b393e7dca6fe849037d5a1314a8cf6b22e1f596..63df031fc9c73868160305b7875d6e20eded09df 100644 (file)
@@ -187,7 +187,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
                return -1;
        }
 
-       event->header.type = PERF_RECORD_MMAP2;
+       event->header.type = PERF_RECORD_MMAP;
        /*
         * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
         */
@@ -198,7 +198,6 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
                char prot[5];
                char execname[PATH_MAX];
                char anonstr[] = "//anon";
-               unsigned int ino;
                size_t size;
                ssize_t n;
 
@@ -209,13 +208,10 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
                strcpy(execname, "");
 
                /* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
-               n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
-                      &event->mmap2.start, &event->mmap2.len, prot,
-                      &event->mmap2.pgoff, &event->mmap2.maj,
-                      &event->mmap2.min,
-                      &ino, execname);
-
-               event->mmap2.ino = (u64)ino;
+               n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
+                      &event->mmap.start, &event->mmap.len, prot,
+                      &event->mmap.pgoff,
+                      execname);
 
                if (n != 8)
                        continue;
@@ -227,15 +223,15 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
                        strcpy(execname, anonstr);
 
                size = strlen(execname) + 1;
-               memcpy(event->mmap2.filename, execname, size);
+               memcpy(event->mmap.filename, execname, size);
                size = PERF_ALIGN(size, sizeof(u64));
-               event->mmap2.len -= event->mmap.start;
-               event->mmap2.header.size = (sizeof(event->mmap2) -
-                                       (sizeof(event->mmap2.filename) - size));
-               memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
-               event->mmap2.header.size += machine->id_hdr_size;
-               event->mmap2.pid = tgid;
-               event->mmap2.tid = pid;
+               event->mmap.len -= event->mmap.start;
+               event->mmap.header.size = (sizeof(event->mmap) -
+                                       (sizeof(event->mmap.filename) - size));
+               memset(event->mmap.filename + size, 0, machine->id_hdr_size);
+               event->mmap.header.size += machine->id_hdr_size;
+               event->mmap.pid = tgid;
+               event->mmap.tid = pid;
 
                if (process(tool, event, &synth_sample, machine) != 0) {
                        rc = -1;
index 0ce9febf1ba0c8c1a691c74a0c55fa1c4a8dfd14..9f1ef9bee2d0c96583dac31d4c12bcc220b519bf 100644 (file)
@@ -678,7 +678,6 @@ void perf_evsel__config(struct perf_evsel *evsel,
                attr->sample_type       |= PERF_SAMPLE_WEIGHT;
 
        attr->mmap  = track;
-       attr->mmap2 = track && !perf_missing_features.mmap2;
        attr->comm  = track;
 
        /*
index c09e0a9fdf4cda118be077fbee1fb382dcc3d5ee..f0692737ebf1237373a140c0ec76a7a4a7a96f9d 100644 (file)
@@ -1357,10 +1357,10 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
                        goto post;
                }
 
+               fname = dwarf_decl_file(&spdie);
                if (addr == (unsigned long)baseaddr) {
                        /* Function entry - Relative line number is 0 */
                        lineno = baseline;
-                       fname = dwarf_decl_file(&spdie);
                        goto post;
                }
 
index a85e4ae5f3ac582381740f8b29460e6f83ae6bd6..c0c9795c4f0235b51848e01db33a7950069b182a 100644 (file)
@@ -282,7 +282,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
 
        event = find_cache_event(evsel);
        if (!event)
-               die("ug! no event found for type %" PRIu64, evsel->attr.config);
+               die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
 
        pid = raw_field_value(event, "common_pid", data);
 
index 4fa655d68a81c8a1b8dd8b60f885721edc7cfea1..41bd85559d4b01aa8ee0e89615ece47c4115b0d0 100644 (file)
@@ -151,7 +151,7 @@ static int check_timer_create(int which)
        fflush(stdout);
 
        done = 0;
-       timer_create(which, NULL, &id);
+       err = timer_create(which, NULL, &id);
        if (err < 0) {
                perror("Can't create timer\n");
                return -1;