Merge branches 'sh/xstate', 'sh/hw-breakpoints' and 'sh/stable-updates'
authorPaul Mundt <lethal@linux-sh.org>
Wed, 13 Jan 2010 04:02:55 +0000 (13:02 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 13 Jan 2010 04:02:55 +0000 (13:02 +0900)
667 files changed:
.gitignore
Documentation/DMA-mapping.txt [deleted file]
Documentation/DocBook/mtdnand.tmpl
Documentation/IO-mapping.txt
Documentation/PCI/PCI-DMA-mapping.txt [new file with mode: 0644]
Documentation/block/00-INDEX
Documentation/block/as-iosched.txt [deleted file]
Documentation/block/biodoc.txt
Documentation/filesystems/ext4.txt
Documentation/filesystems/nilfs2.txt
Documentation/filesystems/proc.txt
Documentation/hwmon/amc6821 [new file with mode: 0644]
Documentation/hwmon/k10temp
Documentation/ioctl/ioctl-number.txt
Documentation/kernel-doc-nano-HOWTO.txt
Documentation/kernel-parameters.txt
Documentation/kvm/api.txt
Documentation/laptops/thinkpad-acpi.txt
Documentation/sound/alsa/Procfile.txt
Documentation/trace/ftrace-design.txt
Documentation/trace/mmiotrace.txt
Documentation/trace/ring-buffer-design.txt
Documentation/trace/tracepoint-analysis.txt
Documentation/vgaarbiter.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/misc.c
arch/arm/boot/compressed/piggy.S [deleted file]
arch/arm/boot/compressed/piggy.gzip.S [new file with mode: 0644]
arch/arm/boot/compressed/piggy.lzo.S [new file with mode: 0644]
arch/arm/mach-davinci/board-dm355-evm.c
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/cp_intc.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-mmp/ttc_dkb.c
arch/arm/mach-mx2/mxt_td60.c
arch/arm/mach-mx25/clock.c
arch/arm/mach-mx25/devices.c
arch/arm/mach-mx25/devices.h
arch/arm/mach-mx25/mx25pdk.c
arch/arm/mach-mx3/Kconfig
arch/arm/mach-mx3/mm.c
arch/arm/mach-mx3/mx31ads.c
arch/arm/mach-mx3/mx31lite.c
arch/arm/mach-mx3/mx31moboard-devboard.c
arch/arm/mach-mx3/mx31moboard-marxbot.c
arch/arm/mach-mx3/mx31moboard.c
arch/arm/mach-mx3/mx31pdk.c
arch/arm/mach-mx3/pcm037.c
arch/arm/mach-omap1/clock_data.c
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/mux.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/clock2xxx.c
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/clock34xx_data.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/opp2420_data.c
arch/arm/mach-omap2/opp2430_data.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/include/mach/zylonite.h
arch/arm/mach-pxa/littleton.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/zeus.c
arch/arm/mach-pxa/zylonite.c
arch/arm/mach-pxa/zylonite_pxa300.c
arch/arm/mach-pxa/zylonite_pxa320.c
arch/arm/mach-s3c2410/include/mach/ts.h [new file with mode: 0644]
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mach-s3c2440/mach-osiris.c
arch/arm/mach-w90x900/include/mach/system.h
arch/arm/mach-w90x900/time.c
arch/arm/mm/init.c
arch/arm/mm/tlb-v7.S
arch/arm/plat-mxc/include/mach/iomux-mx25.h
arch/arm/plat-mxc/include/mach/mx25.h
arch/arm/plat-omap/clock.c
arch/arm/plat-omap/cpu-omap.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/include/plat/board.h
arch/arm/plat-omap/include/plat/clock.h
arch/arm/plat-omap/include/plat/control.h
arch/arm/plat-omap/include/plat/io.h
arch/arm/plat-omap/include/plat/mux.h
arch/arm/plat-omap/include/plat/omap7xx.h
arch/arm/plat-omap/io.c
arch/arm/plat-omap/iommu.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-pxa/pwm.c
arch/arm/plat-s3c/dev-nand.c
arch/arm/plat-s3c/include/plat/devs.h
arch/arm/plat-s3c24xx/devs.c
arch/arm/plat-s3c24xx/s3c244x.c
arch/arm/plat-s3c64xx/s3c6400-clock.c
arch/blackfin/include/asm/page.h
arch/blackfin/kernel/kgdb.c
arch/blackfin/mm/Makefile
arch/blackfin/mm/maccess.c [new file with mode: 0644]
arch/frv/include/asm/page.h
arch/ia64/include/asm/ftrace.h
arch/ia64/include/asm/kprobes.h
arch/ia64/include/asm/tlb.h
arch/ia64/include/asm/topology.h
arch/ia64/include/asm/types.h
arch/ia64/kernel/mca.c
arch/ia64/kernel/perfmon.c
arch/ia64/kvm/vcpu.h
arch/ia64/kvm/vmm.c
arch/ia64/kvm/vtlb.c
arch/ia64/mm/init.c
arch/ia64/mm/tlb.c
arch/mips/mm/init.c
arch/mips/sgi-ip27/ip27-memory.c
arch/mn10300/Makefile
arch/mn10300/configs/asb2303_defconfig
arch/mn10300/include/asm/bitops.h
arch/mn10300/include/asm/div64.h
arch/mn10300/include/asm/system.h
arch/mn10300/include/asm/tlbflush.h
arch/mn10300/include/asm/uaccess.h
arch/mn10300/include/asm/unistd.h
arch/mn10300/kernel/entry.S
arch/mn10300/kernel/mn10300-serial.c
arch/mn10300/kernel/signal.c
arch/mn10300/lib/checksum.c
arch/mn10300/lib/delay.c
arch/mn10300/lib/usercopy.c
arch/mn10300/mm/dma-alloc.c
arch/mn10300/mm/init.c
arch/mn10300/mm/misalignment.c
arch/mn10300/unit-asb2305/include/unit/serial.h
arch/mn10300/unit-asb2305/include/unit/timex.h
arch/mn10300/unit-asb2305/leds.c
arch/mn10300/unit-asb2305/pci-asb2305.c
arch/mn10300/unit-asb2305/pci-asb2305.h
arch/mn10300/unit-asb2305/pci.c
arch/mn10300/unit-asb2305/unit-init.c
arch/powerpc/boot/Makefile
arch/powerpc/kernel/pci-common.c
arch/powerpc/kvm/book3s_64_mmu.c
arch/s390/defconfig
arch/s390/include/asm/param.h
arch/score/mm/init.c
arch/sh/Kconfig
arch/sh/include/asm/Kbuild
arch/sh/include/asm/fpu.h
arch/sh/include/asm/hw_breakpoint.h [new file with mode: 0644]
arch/sh/include/asm/kdebug.h
arch/sh/include/asm/processor_32.h
arch/sh/include/asm/ptrace.h
arch/sh/include/asm/system.h
arch/sh/include/asm/thread_info.h
arch/sh/include/asm/ubc.h [deleted file]
arch/sh/include/cpu-sh2/cpu/ubc.h [deleted file]
arch/sh/include/cpu-sh3/cpu/ubc.h [deleted file]
arch/sh/include/cpu-sh4/cpu/ubc.h [deleted file]
arch/sh/kernel/Makefile
arch/sh/kernel/cpu/Makefile
arch/sh/kernel/cpu/fpu.c [new file with mode: 0644]
arch/sh/kernel/cpu/init.c
arch/sh/kernel/cpu/sh2a/fpu.c
arch/sh/kernel/cpu/sh3/ex.S
arch/sh/kernel/cpu/sh4/fpu.c
arch/sh/kernel/cpu/sh4a/Makefile
arch/sh/kernel/cpu/sh4a/ubc.c [new file with mode: 0644]
arch/sh/kernel/debugtraps.S
arch/sh/kernel/hw_breakpoint.c [new file with mode: 0644]
arch/sh/kernel/kgdb.c
arch/sh/kernel/process.c [new file with mode: 0644]
arch/sh/kernel/process_32.c
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/signal_32.c
arch/sh/kernel/traps_32.c
arch/sh/math-emu/math.c
arch/sh/mm/init.c
arch/sparc/kernel/nmi.c
arch/sparc/kernel/perf_event.c
arch/x86/Kconfig
arch/x86/Kconfig.cpu
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/misc.c
arch/x86/include/asm/kvm.h
arch/x86/include/asm/uaccess_32.h
arch/x86/include/asm/uaccess_64.h
arch/x86/include/asm/uv/uv_hub.h
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/probe_64.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/e820.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kvm/lapic.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/x86.c
arch/x86/mm/init_32.c
arch/x86/mm/kmemcheck/error.c
arch/x86/pci/bus_numa.c
arch/x86/pci/intel_bus.c
arch/x86/tools/chkobjdump.awk
block/blk-barrier.c
block/blk-settings.c
block/cfq-iosched.c
crypto/async_tx/raid6test.c
drivers/Kconfig
drivers/acpi/sleep.c
drivers/acpi/video.c
drivers/base/power/main.c
drivers/block/DAC960.c
drivers/block/aoe/aoecmd.c
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_proc.c
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_worker.c
drivers/block/mg_disk.c
drivers/char/agp/amd64-agp.c
drivers/char/agp/backend.c
drivers/char/agp/hp-agp.c
drivers/char/hw_random/core.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/sonypi.c
drivers/char/toshiba.c
drivers/cpuidle/governors/menu.c
drivers/dma/at_hdmac.c
drivers/dma/coh901318.c
drivers/dma/dw_dmac.c
drivers/dma/ioat/dma.c
drivers/dma/ioat/dma.h
drivers/dma/ioat/dma_v2.c
drivers/dma/ioat/dma_v2.h
drivers/dma/ioat/dma_v3.c
drivers/dma/ioat/registers.h
drivers/dma/shdma.c
drivers/dma/shdma.h
drivers/firewire/Kconfig
drivers/firewire/core-cdev.c
drivers/firewire/core-transaction.c
drivers/firewire/ohci.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/adp5588-gpio.c [new file with mode: 0644]
drivers/gpio/gpiolib.c
drivers/gpu/drm/ati_pcigart.c
drivers/gpu/drm/drm_bufs.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/nouveau/Kconfig
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_channel.c
drivers/gpu/drm/nouveau/nouveau_dma.c
drivers/gpu/drm/nouveau/nouveau_dma.h
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_fbcon.h
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_irq.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_object.c
drivers/gpu/drm/nouveau/nouveau_reg.h
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nouveau_ttm.c
drivers/gpu/drm/nouveau/nv04_dac.c
drivers/gpu/drm/nouveau/nv04_fbcon.c
drivers/gpu/drm/nouveau/nv04_fifo.c
drivers/gpu/drm/nouveau/nv04_graph.c
drivers/gpu/drm/nouveau/nv10_fb.c
drivers/gpu/drm/nouveau/nv10_graph.c
drivers/gpu/drm/nouveau/nv17_tv.c
drivers/gpu/drm/nouveau/nv20_graph.c
drivers/gpu/drm/nouveau/nv40_fb.c
drivers/gpu/drm/nouveau/nv40_graph.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_fbcon.c
drivers/gpu/drm/nouveau/nv50_fifo.c
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/ObjectID.h
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/mkregtable.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_blit_kms.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_agp.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_irq.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_legacy_tv.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/reg_srcs/r420 [new file with mode: 0644]
drivers/gpu/drm/radeon/reg_srcs/rs600
drivers/gpu/drm/radeon/reg_srcs/rv515
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/adt7462.c
drivers/hwmon/amc6821.c [new file with mode: 0644]
drivers/hwmon/asus_atk0110.c
drivers/hwmon/coretemp.c
drivers/hwmon/k10temp.c
drivers/hwmon/k8temp.c
drivers/hwmon/sis5595.c
drivers/hwmon/via686a.c
drivers/hwmon/vt8231.c
drivers/ieee1394/Kconfig
drivers/infiniband/core/cma.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mlx4/srq.c
drivers/input/ff-memless.c
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/joystick/iforce/iforce.h
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/matrix_keypad.c
drivers/input/keyboard/twl4030_keypad.c
drivers/input/misc/twl4030-pwrbutton.c
drivers/input/misc/wistron_btns.c
drivers/input/mouse/Kconfig
drivers/input/mouse/hgpk.c
drivers/input/mouse/lifebook.c
drivers/input/mouse/psmouse-base.c
drivers/input/serio/serio.c
drivers/lguest/segments.c
drivers/md/md.c
drivers/media/dvb/firewire/firedtv-fw.c
drivers/message/i2o/i2o_config.c
drivers/mfd/twl4030-irq.c
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/core/mmc.c
drivers/net/3c507.c
drivers/net/Kconfig
drivers/net/arm/Kconfig
drivers/net/benet/be.h
drivers/net/benet/be_cmds.c
drivers/net/benet/be_cmds.h
drivers/net/benet/be_ethtool.c
drivers/net/bnx2x_main.c
drivers/net/bonding/bond_3ad.c
drivers/net/gianfar.c
drivers/net/ibmlana.c
drivers/net/igb/e1000_82575.c
drivers/net/igb/e1000_phy.c
drivers/net/igb/igb_ethtool.c
drivers/net/igb/igb_main.c
drivers/net/igbvf/netdev.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/mlx4/main.c
drivers/net/pcnet32.c
drivers/net/sfc/efx.c
drivers/net/sfc/falcon.c
drivers/net/sfc/falcon_xmac.c
drivers/net/sfc/mcdi_phy.c
drivers/net/sfc/net_driver.h
drivers/net/sfc/nic.c
drivers/net/sfc/qt202x_phy.c
drivers/net/sfc/siena.c
drivers/net/sfc/tenxpress.c
drivers/net/sfc/tx.c
drivers/net/sky2.c
drivers/net/tun.c
drivers/net/ucc_geth.c
drivers/net/via-rhine.c
drivers/net/vxge/vxge-main.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/mac.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/dma.h
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-3945.h
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000-hw.h
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-csr.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-eeprom.c
drivers/net/wireless/iwlwifi/iwl-eeprom.h
drivers/net/wireless/iwlwifi/iwl-hcmd.c
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/iwmc3200wifi/iwm.h
drivers/net/wireless/iwmc3200wifi/netdev.c
drivers/net/wireless/iwmc3200wifi/rx.c
drivers/net/wireless/libertas/mesh.c
drivers/net/wireless/libertas/scan.c
drivers/net/wireless/libertas/wext.c
drivers/net/wireless/libertas_tf/main.c
drivers/net/wireless/orinoco/wext.c
drivers/net/wireless/rt2x00/rt2800.h
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rtl818x/rtl8180_dev.c
drivers/net/wireless/wl12xx/wl1251_boot.c
drivers/net/wireless/wl12xx/wl1271_cmd.c
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/net/wireless/zd1211rw/zd_chip.h
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/pci/hotplug/shpchp.h
drivers/pci/intel-iommu.c
drivers/pci/intr_remapping.c
drivers/pci/pci-acpi.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/Kconfig.debug
drivers/pci/pcie/aer/aer_inject.c
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/aer/aerdrv_acpi.c
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aer/aerdrv_errprint.c
drivers/pci/pcie/aspm.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/quirks.c
drivers/pci/search.c
drivers/pcmcia/cardbus.c
drivers/platform/x86/Kconfig
drivers/platform/x86/dell-wmi.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/msi-wmi.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/wmi.c
drivers/rtc/rtc-cmos.c
drivers/s390/cio/Makefile
drivers/s390/cio/qdio.h
drivers/s390/cio/qdio_debug.c
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_perf.c [deleted file]
drivers/s390/cio/qdio_perf.h [deleted file]
drivers/s390/cio/qdio_thinint.c
drivers/sbus/char/bbc_envctrl.c
drivers/scsi/cxgb3i/cxgb3i_offload.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw4.h [changed mode: 0644->0755]
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/lpfc/lpfc_vport.c
drivers/scsi/pmcraid.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/stex.c
drivers/video/backlight/omap1_bl.c
drivers/video/pxafb.c
fs/binfmt_elf_fdpic.c
fs/cifs/CHANGES
fs/cifs/cifsfs.c
fs/cifs/connect.c
fs/exofs/inode.c
fs/exofs/pnfs.h
fs/ext4/Kconfig
fs/ext4/block_validity.c
fs/ext4/ext4.h
fs/ext4/ext4_extents.h
fs/ext4/extents.c
fs/ext4/fsync.c
fs/ext4/inode.c
fs/ext4/mballoc.h
fs/ext4/super.c
fs/ext4/xattr.c
fs/fs-writeback.c
fs/gfs2/file.c
fs/gfs2/meta_io.c
fs/gfs2/ops_inode.c
fs/gfs2/xattr.c
fs/jbd2/checkpoint.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/namei.c
fs/nfs/dir.c
fs/nfsd/vfs.c
fs/nilfs2/bmap.c
fs/nilfs2/cpfile.c
fs/nilfs2/direct.c
fs/nilfs2/ioctl.c
fs/ocfs2/file.c
fs/proc/array.c
fs/proc/task_mmu.c
fs/quota/dquot.c
fs/reiserfs/bitmap.c
fs/reiserfs/inode.c
fs/reiserfs/ioctl.c
fs/reiserfs/journal.c
fs/reiserfs/lock.c
fs/reiserfs/namei.c
fs/reiserfs/xattr.c
fs/reiserfs/xattr_acl.c
fs/sysfs/dir.c
fs/sysfs/sysfs.h
fs/xfs/linux-2.6/xfs_acl.c
fs/xfs/linux-2.6/xfs_trace.h
fs/xfs/xfs_alloc.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_vnodeops.c
include/drm/drmP.h
include/drm/drm_mode.h
include/drm/i915_drm.h
include/linux/acpi.h
include/linux/blkdev.h
include/linux/decompress/unlzo.h [new file with mode: 0644]
include/linux/firewire-cdev.h
include/linux/firewire.h
include/linux/highmem.h
include/linux/i2c/adp5588.h
include/linux/ieee80211.h
include/linux/inetdevice.h
include/linux/jbd2.h
include/linux/kfifo.h
include/linux/kgdb.h
include/linux/kmemcheck.h
include/linux/mm_types.h
include/linux/pci.h
include/linux/poison.h
include/linux/reiserfs_fs.h
include/linux/resource.h
include/linux/sched.h
include/linux/syscalls.h
include/linux/sysctl.h
include/linux/uaccess.h
include/linux/writeback.h
include/net/mac80211.h
include/scsi/libsrp.h
include/trace/ftrace.h
init/Kconfig
kernel/cgroup.c
kernel/hw_breakpoint.c
kernel/kmod.c
kernel/kprobes.c
kernel/module.c
kernel/perf_event.c
kernel/signal.c
kernel/trace/Kconfig
kernel/trace/trace.c
kernel/trace/trace_export.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_ksym.c
lib/Kconfig
lib/Makefile
lib/decompress.c
lib/decompress_unlzo.c [new file with mode: 0644]
lib/dma-debug.c
lib/lzo/lzo1x_decompress.c
lib/rational.c
lib/vsprintf.c
lib/zlib_inflate/inffast.c
mm/hugetlb.c
mm/maccess.c
mm/mmap.c
mm/nommu.c
mm/percpu.c
mm/slab.c
mm/util.c
net/core/pktgen.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/mac80211/ht.c
net/mac80211/ibss.c
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/tx.c
net/mac80211/util.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_mech_switch.c
net/sunrpc/svc_xprt.c
net/wireless/mlme.c
net/wireless/scan.c
net/xfrm/xfrm_policy.c
scripts/Makefile.lib
scripts/get_maintainer.pl
security/selinux/hooks.c
sound/arm/aaci.c
sound/core/pcm_native.c
sound/pci/hda/hda_beep.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_sigmatel.c
sound/soc/codecs/ac97.c
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8974.c
sound/soc/sh/fsi-ak4642.c
tools/perf/Makefile
tools/perf/builtin-buildid-list.c
tools/perf/builtin-diff.c
tools/perf/builtin-kmem.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-trace.c
tools/perf/design.txt
usr/Kconfig
virt/kvm/assigned-dev.c
virt/kvm/kvm_main.c

index fb2190c61af0982ae9b8792b51d970bddaafdf5f..de6344e15706280de410cd83372f997720d0947a 100644 (file)
@@ -37,6 +37,7 @@ modules.builtin
 tags
 TAGS
 vmlinux
+vmlinuz
 System.map
 Module.markers
 Module.symvers
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
deleted file mode 100644 (file)
index ecad88d..0000000
+++ /dev/null
@@ -1,766 +0,0 @@
-                       Dynamic DMA mapping
-                       ===================
-
-                David S. Miller <davem@redhat.com>
-                Richard Henderson <rth@cygnus.com>
-                 Jakub Jelinek <jakub@redhat.com>
-
-This document describes the DMA mapping system in terms of the pci_
-API.  For a similar API that works for generic devices, see
-DMA-API.txt.
-
-Most of the 64bit platforms have special hardware that translates bus
-addresses (DMA addresses) into physical addresses.  This is similar to
-how page tables and/or a TLB translates virtual addresses to physical
-addresses on a CPU.  This is needed so that e.g. PCI devices can
-access with a Single Address Cycle (32bit DMA address) any page in the
-64bit physical address space.  Previously in Linux those 64bit
-platforms had to set artificial limits on the maximum RAM size in the
-system, so that the virt_to_bus() static scheme works (the DMA address
-translation tables were simply filled on bootup to map each bus
-address to the physical page __pa(bus_to_virt())).
-
-So that Linux can use the dynamic DMA mapping, it needs some help from the
-drivers, namely it has to take into account that DMA addresses should be
-mapped only for the time they are actually used and unmapped after the DMA
-transfer.
-
-The following API will work of course even on platforms where no such
-hardware exists, see e.g. arch/x86/include/asm/pci.h for how it is implemented on
-top of the virt_to_bus interface.
-
-First of all, you should make sure
-
-#include <linux/pci.h>
-
-is in your driver. This file will obtain for you the definition of the
-dma_addr_t (which can hold any valid DMA address for the platform)
-type which should be used everywhere you hold a DMA (bus) address
-returned from the DMA mapping functions.
-
-                        What memory is DMA'able?
-
-The first piece of information you must know is what kernel memory can
-be used with the DMA mapping facilities.  There has been an unwritten
-set of rules regarding this, and this text is an attempt to finally
-write them down.
-
-If you acquired your memory via the page allocator
-(i.e. __get_free_page*()) or the generic memory allocators
-(i.e. kmalloc() or kmem_cache_alloc()) then you may DMA to/from
-that memory using the addresses returned from those routines.
-
-This means specifically that you may _not_ use the memory/addresses
-returned from vmalloc() for DMA.  It is possible to DMA to the
-_underlying_ memory mapped into a vmalloc() area, but this requires
-walking page tables to get the physical addresses, and then
-translating each of those pages back to a kernel address using
-something like __va().  [ EDIT: Update this when we integrate
-Gerd Knorr's generic code which does this. ]
-
-This rule also means that you may use neither kernel image addresses
-(items in data/text/bss segments), nor module image addresses, nor
-stack addresses for DMA.  These could all be mapped somewhere entirely
-different than the rest of physical memory.  Even if those classes of
-memory could physically work with DMA, you'd need to ensure the I/O
-buffers were cacheline-aligned.  Without that, you'd see cacheline
-sharing problems (data corruption) on CPUs with DMA-incoherent caches.
-(The CPU could write to one word, DMA would write to a different one
-in the same cache line, and one of them could be overwritten.)
-
-Also, this means that you cannot take the return of a kmap()
-call and DMA to/from that.  This is similar to vmalloc().
-
-What about block I/O and networking buffers?  The block I/O and
-networking subsystems make sure that the buffers they use are valid
-for you to DMA from/to.
-
-                       DMA addressing limitations
-
-Does your device have any DMA addressing limitations?  For example, is
-your device only capable of driving the low order 24-bits of address
-on the PCI bus for SAC DMA transfers?  If so, you need to inform the
-PCI layer of this fact.
-
-By default, the kernel assumes that your device can address the full
-32-bits in a SAC cycle.  For a 64-bit DAC capable device, this needs
-to be increased.  And for a device with limitations, as discussed in
-the previous paragraph, it needs to be decreased.
-
-pci_alloc_consistent() by default will return 32-bit DMA addresses.
-PCI-X specification requires PCI-X devices to support 64-bit
-addressing (DAC) for all transactions. And at least one platform (SGI
-SN2) requires 64-bit consistent allocations to operate correctly when
-the IO bus is in PCI-X mode. Therefore, like with pci_set_dma_mask(),
-it's good practice to call pci_set_consistent_dma_mask() to set the
-appropriate mask even if your device only supports 32-bit DMA
-(default) and especially if it's a PCI-X device.
-
-For correct operation, you must interrogate the PCI layer in your
-device probe routine to see if the PCI controller on the machine can
-properly support the DMA addressing limitation your device has.  It is
-good style to do this even if your device holds the default setting,
-because this shows that you did think about these issues wrt. your
-device.
-
-The query is performed via a call to pci_set_dma_mask():
-
-       int pci_set_dma_mask(struct pci_dev *pdev, u64 device_mask);
-
-The query for consistent allocations is performed via a call to
-pci_set_consistent_dma_mask():
-
-       int pci_set_consistent_dma_mask(struct pci_dev *pdev, u64 device_mask);
-
-Here, pdev is a pointer to the PCI device struct of your device, and
-device_mask is a bit mask describing which bits of a PCI address your
-device supports.  It returns zero if your card can perform DMA
-properly on the machine given the address mask you provided.
-
-If it returns non-zero, your device cannot perform DMA properly on
-this platform, and attempting to do so will result in undefined
-behavior.  You must either use a different mask, or not use DMA.
-
-This means that in the failure case, you have three options:
-
-1) Use another DMA mask, if possible (see below).
-2) Use some non-DMA mode for data transfer, if possible.
-3) Ignore this device and do not initialize it.
-
-It is recommended that your driver print a kernel KERN_WARNING message
-when you end up performing either #2 or #3.  In this manner, if a user
-of your driver reports that performance is bad or that the device is not
-even detected, you can ask them for the kernel messages to find out
-exactly why.
-
-The standard 32-bit addressing PCI device would do something like
-this:
-
-       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
-               printk(KERN_WARNING
-                      "mydev: No suitable DMA available.\n");
-               goto ignore_this_device;
-       }
-
-Another common scenario is a 64-bit capable device.  The approach
-here is to try for 64-bit DAC addressing, but back down to a
-32-bit mask should that fail.  The PCI platform code may fail the
-64-bit mask not because the platform is not capable of 64-bit
-addressing.  Rather, it may fail in this case simply because
-32-bit SAC addressing is done more efficiently than DAC addressing.
-Sparc64 is one platform which behaves in this way.
-
-Here is how you would handle a 64-bit capable device which can drive
-all 64-bits when accessing streaming DMA:
-
-       int using_dac;
-
-       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-               using_dac = 1;
-       } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
-               using_dac = 0;
-       } else {
-               printk(KERN_WARNING
-                      "mydev: No suitable DMA available.\n");
-               goto ignore_this_device;
-       }
-
-If a card is capable of using 64-bit consistent allocations as well,
-the case would look like this:
-
-       int using_dac, consistent_using_dac;
-
-       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-               using_dac = 1;
-               consistent_using_dac = 1;
-               pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
-       } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
-               using_dac = 0;
-               consistent_using_dac = 0;
-               pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-       } else {
-               printk(KERN_WARNING
-                      "mydev: No suitable DMA available.\n");
-               goto ignore_this_device;
-       }
-
-pci_set_consistent_dma_mask() will always be able to set the same or a
-smaller mask as pci_set_dma_mask(). However for the rare case that a
-device driver only uses consistent allocations, one would have to
-check the return value from pci_set_consistent_dma_mask().
-
-Finally, if your device can only drive the low 24-bits of
-address during PCI bus mastering you might do something like:
-
-       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(24))) {
-               printk(KERN_WARNING
-                      "mydev: 24-bit DMA addressing not available.\n");
-               goto ignore_this_device;
-       }
-
-When pci_set_dma_mask() is successful, and returns zero, the PCI layer
-saves away this mask you have provided.  The PCI layer will use this
-information later when you make DMA mappings.
-
-There is a case which we are aware of at this time, which is worth
-mentioning in this documentation.  If your device supports multiple
-functions (for example a sound card provides playback and record
-functions) and the various different functions have _different_
-DMA addressing limitations, you may wish to probe each mask and
-only provide the functionality which the machine can handle.  It
-is important that the last call to pci_set_dma_mask() be for the
-most specific mask.
-
-Here is pseudo-code showing how this might be done:
-
-       #define PLAYBACK_ADDRESS_BITS   DMA_BIT_MASK(32)
-       #define RECORD_ADDRESS_BITS     DMA_BIT_MASK(24)
-
-       struct my_sound_card *card;
-       struct pci_dev *pdev;
-
-       ...
-       if (!pci_set_dma_mask(pdev, PLAYBACK_ADDRESS_BITS)) {
-               card->playback_enabled = 1;
-       } else {
-               card->playback_enabled = 0;
-               printk(KERN_WARNING "%s: Playback disabled due to DMA limitations.\n",
-                      card->name);
-       }
-       if (!pci_set_dma_mask(pdev, RECORD_ADDRESS_BITS)) {
-               card->record_enabled = 1;
-       } else {
-               card->record_enabled = 0;
-               printk(KERN_WARNING "%s: Record disabled due to DMA limitations.\n",
-                      card->name);
-       }
-
-A sound card was used as an example here because this genre of PCI
-devices seems to be littered with ISA chips given a PCI front end,
-and thus retaining the 16MB DMA addressing limitations of ISA.
-
-                       Types of DMA mappings
-
-There are two types of DMA mappings:
-
-- Consistent DMA mappings which are usually mapped at driver
-  initialization, unmapped at the end and for which the hardware should
-  guarantee that the device and the CPU can access the data
-  in parallel and will see updates made by each other without any
-  explicit software flushing.
-
-  Think of "consistent" as "synchronous" or "coherent".
-
-  The current default is to return consistent memory in the low 32
-  bits of the PCI bus space.  However, for future compatibility you
-  should set the consistent mask even if this default is fine for your
-  driver.
-
-  Good examples of what to use consistent mappings for are:
-
-       - Network card DMA ring descriptors.
-       - SCSI adapter mailbox command data structures.
-       - Device firmware microcode executed out of
-         main memory.
-
-  The invariant these examples all require is that any CPU store
-  to memory is immediately visible to the device, and vice
-  versa.  Consistent mappings guarantee this.
-
-  IMPORTANT: Consistent DMA memory does not preclude the usage of
-             proper memory barriers.  The CPU may reorder stores to
-            consistent memory just as it may normal memory.  Example:
-            if it is important for the device to see the first word
-            of a descriptor updated before the second, you must do
-            something like:
-
-               desc->word0 = address;
-               wmb();
-               desc->word1 = DESC_VALID;
-
-             in order to get correct behavior on all platforms.
-
-            Also, on some platforms your driver may need to flush CPU write
-            buffers in much the same way as it needs to flush write buffers
-            found in PCI bridges (such as by reading a register's value
-            after writing it).
-
-- Streaming DMA mappings which are usually mapped for one DMA transfer,
-  unmapped right after it (unless you use pci_dma_sync_* below) and for which
-  hardware can optimize for sequential accesses.
-
-  This of "streaming" as "asynchronous" or "outside the coherency
-  domain".
-
-  Good examples of what to use streaming mappings for are:
-
-       - Networking buffers transmitted/received by a device.
-       - Filesystem buffers written/read by a SCSI device.
-
-  The interfaces for using this type of mapping were designed in
-  such a way that an implementation can make whatever performance
-  optimizations the hardware allows.  To this end, when using
-  such mappings you must be explicit about what you want to happen.
-
-Neither type of DMA mapping has alignment restrictions that come
-from PCI, although some devices may have such restrictions.
-Also, systems with caches that aren't DMA-coherent will work better
-when the underlying buffers don't share cache lines with other data.
-
-
-                Using Consistent DMA mappings.
-
-To allocate and map large (PAGE_SIZE or so) consistent DMA regions,
-you should do:
-
-       dma_addr_t dma_handle;
-
-       cpu_addr = pci_alloc_consistent(pdev, size, &dma_handle);
-
-where pdev is a struct pci_dev *. This may be called in interrupt context.
-You should use dma_alloc_coherent (see DMA-API.txt) for buses
-where devices don't have struct pci_dev (like ISA, EISA).
-
-This argument is needed because the DMA translations may be bus
-specific (and often is private to the bus which the device is attached
-to).
-
-Size is the length of the region you want to allocate, in bytes.
-
-This routine will allocate RAM for that region, so it acts similarly to
-__get_free_pages (but takes size instead of a page order).  If your
-driver needs regions sized smaller than a page, you may prefer using
-the pci_pool interface, described below.
-
-The consistent DMA mapping interfaces, for non-NULL pdev, will by
-default return a DMA address which is SAC (Single Address Cycle)
-addressable.  Even if the device indicates (via PCI dma mask) that it
-may address the upper 32-bits and thus perform DAC cycles, consistent
-allocation will only return > 32-bit PCI addresses for DMA if the
-consistent dma mask has been explicitly changed via
-pci_set_consistent_dma_mask().  This is true of the pci_pool interface
-as well.
-
-pci_alloc_consistent returns two values: the virtual address which you
-can use to access it from the CPU and dma_handle which you pass to the
-card.
-
-The cpu return address and the DMA bus master address are both
-guaranteed to be aligned to the smallest PAGE_SIZE order which
-is greater than or equal to the requested size.  This invariant
-exists (for example) to guarantee that if you allocate a chunk
-which is smaller than or equal to 64 kilobytes, the extent of the
-buffer you receive will not cross a 64K boundary.
-
-To unmap and free such a DMA region, you call:
-
-       pci_free_consistent(pdev, size, cpu_addr, dma_handle);
-
-where pdev, size are the same as in the above call and cpu_addr and
-dma_handle are the values pci_alloc_consistent returned to you.
-This function may not be called in interrupt context.
-
-If your driver needs lots of smaller memory regions, you can write
-custom code to subdivide pages returned by pci_alloc_consistent,
-or you can use the pci_pool API to do that.  A pci_pool is like
-a kmem_cache, but it uses pci_alloc_consistent not __get_free_pages.
-Also, it understands common hardware constraints for alignment,
-like queue heads needing to be aligned on N byte boundaries.
-
-Create a pci_pool like this:
-
-       struct pci_pool *pool;
-
-       pool = pci_pool_create(name, pdev, size, align, alloc);
-
-The "name" is for diagnostics (like a kmem_cache name); pdev and size
-are as above.  The device's hardware alignment requirement for this
-type of data is "align" (which is expressed in bytes, and must be a
-power of two).  If your device has no boundary crossing restrictions,
-pass 0 for alloc; passing 4096 says memory allocated from this pool
-must not cross 4KByte boundaries (but at that time it may be better to
-go for pci_alloc_consistent directly instead).
-
-Allocate memory from a pci pool like this:
-
-       cpu_addr = pci_pool_alloc(pool, flags, &dma_handle);
-
-flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor
-holding SMP locks), SLAB_ATOMIC otherwise.  Like pci_alloc_consistent,
-this returns two values, cpu_addr and dma_handle.
-
-Free memory that was allocated from a pci_pool like this:
-
-       pci_pool_free(pool, cpu_addr, dma_handle);
-
-where pool is what you passed to pci_pool_alloc, and cpu_addr and
-dma_handle are the values pci_pool_alloc returned. This function
-may be called in interrupt context.
-
-Destroy a pci_pool by calling:
-
-       pci_pool_destroy(pool);
-
-Make sure you've called pci_pool_free for all memory allocated
-from a pool before you destroy the pool. This function may not
-be called in interrupt context.
-
-                       DMA Direction
-
-The interfaces described in subsequent portions of this document
-take a DMA direction argument, which is an integer and takes on
-one of the following values:
-
- PCI_DMA_BIDIRECTIONAL
- PCI_DMA_TODEVICE
- PCI_DMA_FROMDEVICE
- PCI_DMA_NONE
-
-One should provide the exact DMA direction if you know it.
-
-PCI_DMA_TODEVICE means "from main memory to the PCI device"
-PCI_DMA_FROMDEVICE means "from the PCI device to main memory"
-It is the direction in which the data moves during the DMA
-transfer.
-
-You are _strongly_ encouraged to specify this as precisely
-as you possibly can.
-
-If you absolutely cannot know the direction of the DMA transfer,
-specify PCI_DMA_BIDIRECTIONAL.  It means that the DMA can go in
-either direction.  The platform guarantees that you may legally
-specify this, and that it will work, but this may be at the
-cost of performance for example.
-
-The value PCI_DMA_NONE is to be used for debugging.  One can
-hold this in a data structure before you come to know the
-precise direction, and this will help catch cases where your
-direction tracking logic has failed to set things up properly.
-
-Another advantage of specifying this value precisely (outside of
-potential platform-specific optimizations of such) is for debugging.
-Some platforms actually have a write permission boolean which DMA
-mappings can be marked with, much like page protections in the user
-program address space.  Such platforms can and do report errors in the
-kernel logs when the PCI controller hardware detects violation of the
-permission setting.
-
-Only streaming mappings specify a direction, consistent mappings
-implicitly have a direction attribute setting of
-PCI_DMA_BIDIRECTIONAL.
-
-The SCSI subsystem tells you the direction to use in the
-'sc_data_direction' member of the SCSI command your driver is
-working on.
-
-For Networking drivers, it's a rather simple affair.  For transmit
-packets, map/unmap them with the PCI_DMA_TODEVICE direction
-specifier.  For receive packets, just the opposite, map/unmap them
-with the PCI_DMA_FROMDEVICE direction specifier.
-
-                 Using Streaming DMA mappings
-
-The streaming DMA mapping routines can be called from interrupt
-context.  There are two versions of each map/unmap, one which will
-map/unmap a single memory region, and one which will map/unmap a
-scatterlist.
-
-To map a single region, you do:
-
-       struct pci_dev *pdev = mydev->pdev;
-       dma_addr_t dma_handle;
-       void *addr = buffer->ptr;
-       size_t size = buffer->len;
-
-       dma_handle = pci_map_single(pdev, addr, size, direction);
-
-and to unmap it:
-
-       pci_unmap_single(pdev, dma_handle, size, direction);
-
-You should call pci_unmap_single when the DMA activity is finished, e.g.
-from the interrupt which told you that the DMA transfer is done.
-
-Using cpu pointers like this for single mappings has a disadvantage,
-you cannot reference HIGHMEM memory in this way.  Thus, there is a
-map/unmap interface pair akin to pci_{map,unmap}_single.  These
-interfaces deal with page/offset pairs instead of cpu pointers.
-Specifically:
-
-       struct pci_dev *pdev = mydev->pdev;
-       dma_addr_t dma_handle;
-       struct page *page = buffer->page;
-       unsigned long offset = buffer->offset;
-       size_t size = buffer->len;
-
-       dma_handle = pci_map_page(pdev, page, offset, size, direction);
-
-       ...
-
-       pci_unmap_page(pdev, dma_handle, size, direction);
-
-Here, "offset" means byte offset within the given page.
-
-With scatterlists, you map a region gathered from several regions by:
-
-       int i, count = pci_map_sg(pdev, sglist, nents, direction);
-       struct scatterlist *sg;
-
-       for_each_sg(sglist, sg, count, i) {
-               hw_address[i] = sg_dma_address(sg);
-               hw_len[i] = sg_dma_len(sg);
-       }
-
-where nents is the number of entries in the sglist.
-
-The implementation is free to merge several consecutive sglist entries
-into one (e.g. if DMA mapping is done with PAGE_SIZE granularity, any
-consecutive sglist entries can be merged into one provided the first one
-ends and the second one starts on a page boundary - in fact this is a huge
-advantage for cards which either cannot do scatter-gather or have very
-limited number of scatter-gather entries) and returns the actual number
-of sg entries it mapped them to. On failure 0 is returned.
-
-Then you should loop count times (note: this can be less than nents times)
-and use sg_dma_address() and sg_dma_len() macros where you previously
-accessed sg->address and sg->length as shown above.
-
-To unmap a scatterlist, just call:
-
-       pci_unmap_sg(pdev, sglist, nents, direction);
-
-Again, make sure DMA activity has already finished.
-
-PLEASE NOTE:  The 'nents' argument to the pci_unmap_sg call must be
-              the _same_ one you passed into the pci_map_sg call,
-             it should _NOT_ be the 'count' value _returned_ from the
-              pci_map_sg call.
-
-Every pci_map_{single,sg} call should have its pci_unmap_{single,sg}
-counterpart, because the bus address space is a shared resource (although
-in some ports the mapping is per each BUS so less devices contend for the
-same bus address space) and you could render the machine unusable by eating
-all bus addresses.
-
-If you need to use the same streaming DMA region multiple times and touch
-the data in between the DMA transfers, the buffer needs to be synced
-properly in order for the cpu and device to see the most uptodate and
-correct copy of the DMA buffer.
-
-So, firstly, just map it with pci_map_{single,sg}, and after each DMA
-transfer call either:
-
-       pci_dma_sync_single_for_cpu(pdev, dma_handle, size, direction);
-
-or:
-
-       pci_dma_sync_sg_for_cpu(pdev, sglist, nents, direction);
-
-as appropriate.
-
-Then, if you wish to let the device get at the DMA area again,
-finish accessing the data with the cpu, and then before actually
-giving the buffer to the hardware call either:
-
-       pci_dma_sync_single_for_device(pdev, dma_handle, size, direction);
-
-or:
-
-       pci_dma_sync_sg_for_device(dev, sglist, nents, direction);
-
-as appropriate.
-
-After the last DMA transfer call one of the DMA unmap routines
-pci_unmap_{single,sg}. If you don't touch the data from the first pci_map_*
-call till pci_unmap_*, then you don't have to call the pci_dma_sync_*
-routines at all.
-
-Here is pseudo code which shows a situation in which you would need
-to use the pci_dma_sync_*() interfaces.
-
-       my_card_setup_receive_buffer(struct my_card *cp, char *buffer, int len)
-       {
-               dma_addr_t mapping;
-
-               mapping = pci_map_single(cp->pdev, buffer, len, PCI_DMA_FROMDEVICE);
-
-               cp->rx_buf = buffer;
-               cp->rx_len = len;
-               cp->rx_dma = mapping;
-
-               give_rx_buf_to_card(cp);
-       }
-
-       ...
-
-       my_card_interrupt_handler(int irq, void *devid, struct pt_regs *regs)
-       {
-               struct my_card *cp = devid;
-
-               ...
-               if (read_card_status(cp) == RX_BUF_TRANSFERRED) {
-                       struct my_card_header *hp;
-
-                       /* Examine the header to see if we wish
-                        * to accept the data.  But synchronize
-                        * the DMA transfer with the CPU first
-                        * so that we see updated contents.
-                        */
-                       pci_dma_sync_single_for_cpu(cp->pdev, cp->rx_dma,
-                                                   cp->rx_len,
-                                                   PCI_DMA_FROMDEVICE);
-
-                       /* Now it is safe to examine the buffer. */
-                       hp = (struct my_card_header *) cp->rx_buf;
-                       if (header_is_ok(hp)) {
-                               pci_unmap_single(cp->pdev, cp->rx_dma, cp->rx_len,
-                                                PCI_DMA_FROMDEVICE);
-                               pass_to_upper_layers(cp->rx_buf);
-                               make_and_setup_new_rx_buf(cp);
-                       } else {
-                               /* Just sync the buffer and give it back
-                                * to the card.
-                                */
-                               pci_dma_sync_single_for_device(cp->pdev,
-                                                              cp->rx_dma,
-                                                              cp->rx_len,
-                                                              PCI_DMA_FROMDEVICE);
-                               give_rx_buf_to_card(cp);
-                       }
-               }
-       }
-
-Drivers converted fully to this interface should not use virt_to_bus any
-longer, nor should they use bus_to_virt. Some drivers have to be changed a
-little bit, because there is no longer an equivalent to bus_to_virt in the
-dynamic DMA mapping scheme - you have to always store the DMA addresses
-returned by the pci_alloc_consistent, pci_pool_alloc, and pci_map_single
-calls (pci_map_sg stores them in the scatterlist itself if the platform
-supports dynamic DMA mapping in hardware) in your driver structures and/or
-in the card registers.
-
-All PCI drivers should be using these interfaces with no exceptions.
-It is planned to completely remove virt_to_bus() and bus_to_virt() as
-they are entirely deprecated.  Some ports already do not provide these
-as it is impossible to correctly support them.
-
-               Optimizing Unmap State Space Consumption
-
-On many platforms, pci_unmap_{single,page}() is simply a nop.
-Therefore, keeping track of the mapping address and length is a waste
-of space.  Instead of filling your drivers up with ifdefs and the like
-to "work around" this (which would defeat the whole purpose of a
-portable API) the following facilities are provided.
-
-Actually, instead of describing the macros one by one, we'll
-transform some example code.
-
-1) Use DECLARE_PCI_UNMAP_{ADDR,LEN} in state saving structures.
-   Example, before:
-
-       struct ring_state {
-               struct sk_buff *skb;
-               dma_addr_t mapping;
-               __u32 len;
-       };
-
-   after:
-
-       struct ring_state {
-               struct sk_buff *skb;
-               DECLARE_PCI_UNMAP_ADDR(mapping)
-               DECLARE_PCI_UNMAP_LEN(len)
-       };
-
-   NOTE: DO NOT put a semicolon at the end of the DECLARE_*()
-         macro.
-
-2) Use pci_unmap_{addr,len}_set to set these values.
-   Example, before:
-
-       ringp->mapping = FOO;
-       ringp->len = BAR;
-
-   after:
-
-       pci_unmap_addr_set(ringp, mapping, FOO);
-       pci_unmap_len_set(ringp, len, BAR);
-
-3) Use pci_unmap_{addr,len} to access these values.
-   Example, before:
-
-       pci_unmap_single(pdev, ringp->mapping, ringp->len,
-                        PCI_DMA_FROMDEVICE);
-
-   after:
-
-       pci_unmap_single(pdev,
-                        pci_unmap_addr(ringp, mapping),
-                        pci_unmap_len(ringp, len),
-                        PCI_DMA_FROMDEVICE);
-
-It really should be self-explanatory.  We treat the ADDR and LEN
-separately, because it is possible for an implementation to only
-need the address in order to perform the unmap operation.
-
-                       Platform Issues
-
-If you are just writing drivers for Linux and do not maintain
-an architecture port for the kernel, you can safely skip down
-to "Closing".
-
-1) Struct scatterlist requirements.
-
-   Struct scatterlist must contain, at a minimum, the following
-   members:
-
-       struct page *page;
-       unsigned int offset;
-       unsigned int length;
-
-   The base address is specified by a "page+offset" pair.
-
-   Previous versions of struct scatterlist contained a "void *address"
-   field that was sometimes used instead of page+offset.  As of Linux
-   2.5., page+offset is always used, and the "address" field has been
-   deleted.
-
-2) More to come...
-
-                       Handling Errors
-
-DMA address space is limited on some architectures and an allocation
-failure can be determined by:
-
-- checking if pci_alloc_consistent returns NULL or pci_map_sg returns 0
-
-- checking the returned dma_addr_t of pci_map_single and pci_map_page
-  by using pci_dma_mapping_error():
-
-       dma_addr_t dma_handle;
-
-       dma_handle = pci_map_single(pdev, addr, size, direction);
-       if (pci_dma_mapping_error(pdev, dma_handle)) {
-               /*
-                * reduce current DMA mapping usage,
-                * delay and try again later or
-                * reset driver.
-                */
-       }
-
-                          Closing
-
-This document, and the API itself, would not be in it's current
-form without the feedback and suggestions from numerous individuals.
-We would like to specifically mention, in no particular order, the
-following people:
-
-       Russell King <rmk@arm.linux.org.uk>
-       Leo Dagum <dagum@barrel.engr.sgi.com>
-       Ralf Baechle <ralf@oss.sgi.com>
-       Grant Grundler <grundler@cup.hp.com>
-       Jay Estabrook <Jay.Estabrook@compaq.com>
-       Thomas Sailer <sailer@ife.ee.ethz.ch>
-       Andrea Arcangeli <andrea@suse.de>
-       Jens Axboe <jens.axboe@oracle.com>
-       David Mosberger-Tang <davidm@hpl.hp.com>
index f508a8a27feaf26354812297b378aa612ea3fc39..5e7d84b48505c16a15e11c4cd2f058ec4a6c6e84 100644 (file)
                </para>
                <programlisting>
 static struct mtd_info *board_mtd;
-static unsigned long baseaddr;
+static void __iomem *baseaddr;
                </programlisting>
                <para>
                        Static example
@@ -182,7 +182,7 @@ static unsigned long baseaddr;
                <programlisting>
 static struct mtd_info board_mtd;
 static struct nand_chip board_chip;
-static unsigned long baseaddr;
+static void __iomem *baseaddr;
                </programlisting>
        </sect1>
        <sect1 id="Partition_defines">
@@ -283,8 +283,8 @@ int __init board_init (void)
        }
 
        /* map physical address */
-       baseaddr = (unsigned long)ioremap(CHIP_PHYSICAL_ADDRESS, 1024);
-       if(!baseaddr){
+       baseaddr = ioremap(CHIP_PHYSICAL_ADDRESS, 1024);
+       if (!baseaddr) {
                printk("Ioremap to access NAND chip failed\n");
                err = -EIO;
                goto out_mtd;
@@ -316,7 +316,7 @@ int __init board_init (void)
        goto out;
 
 out_ior:
-       iounmap((void *)baseaddr);
+       iounmap(baseaddr);
 out_mtd:
        kfree (board_mtd);
 out:
@@ -341,7 +341,7 @@ static void __exit board_cleanup (void)
        nand_release (board_mtd);
 
        /* unmap physical address */
-       iounmap((void *)baseaddr);
+       iounmap(baseaddr);
        
        /* Free the MTD device structure */
        kfree (board_mtd);
index 78a440695e11876287ec04e46c275e141082f5d9..1b5aa10df84564ee5f3278abbe5b836a521839d2 100644 (file)
@@ -157,7 +157,7 @@ For such memory, you can do things like
         * access only the 640k-1MB area, so anything else
         * has to be remapped.
         */
-       char * baseptr = ioremap(0xFC000000, 1024*1024);
+       void __iomem *baseptr = ioremap(0xFC000000, 1024*1024);
 
        /* write a 'A' to the offset 10 of the area */
        writeb('A',baseptr+10);
diff --git a/Documentation/PCI/PCI-DMA-mapping.txt b/Documentation/PCI/PCI-DMA-mapping.txt
new file mode 100644 (file)
index 0000000..ecad88d
--- /dev/null
@@ -0,0 +1,766 @@
+                       Dynamic DMA mapping
+                       ===================
+
+                David S. Miller <davem@redhat.com>
+                Richard Henderson <rth@cygnus.com>
+                 Jakub Jelinek <jakub@redhat.com>
+
+This document describes the DMA mapping system in terms of the pci_
+API.  For a similar API that works for generic devices, see
+DMA-API.txt.
+
+Most of the 64bit platforms have special hardware that translates bus
+addresses (DMA addresses) into physical addresses.  This is similar to
+how page tables and/or a TLB translates virtual addresses to physical
+addresses on a CPU.  This is needed so that e.g. PCI devices can
+access with a Single Address Cycle (32bit DMA address) any page in the
+64bit physical address space.  Previously in Linux those 64bit
+platforms had to set artificial limits on the maximum RAM size in the
+system, so that the virt_to_bus() static scheme works (the DMA address
+translation tables were simply filled on bootup to map each bus
+address to the physical page __pa(bus_to_virt())).
+
+So that Linux can use the dynamic DMA mapping, it needs some help from the
+drivers, namely it has to take into account that DMA addresses should be
+mapped only for the time they are actually used and unmapped after the DMA
+transfer.
+
+The following API will work of course even on platforms where no such
+hardware exists, see e.g. arch/x86/include/asm/pci.h for how it is implemented on
+top of the virt_to_bus interface.
+
+First of all, you should make sure
+
+#include <linux/pci.h>
+
+is in your driver. This file will obtain for you the definition of the
+dma_addr_t (which can hold any valid DMA address for the platform)
+type which should be used everywhere you hold a DMA (bus) address
+returned from the DMA mapping functions.
+
+                        What memory is DMA'able?
+
+The first piece of information you must know is what kernel memory can
+be used with the DMA mapping facilities.  There has been an unwritten
+set of rules regarding this, and this text is an attempt to finally
+write them down.
+
+If you acquired your memory via the page allocator
+(i.e. __get_free_page*()) or the generic memory allocators
+(i.e. kmalloc() or kmem_cache_alloc()) then you may DMA to/from
+that memory using the addresses returned from those routines.
+
+This means specifically that you may _not_ use the memory/addresses
+returned from vmalloc() for DMA.  It is possible to DMA to the
+_underlying_ memory mapped into a vmalloc() area, but this requires
+walking page tables to get the physical addresses, and then
+translating each of those pages back to a kernel address using
+something like __va().  [ EDIT: Update this when we integrate
+Gerd Knorr's generic code which does this. ]
+
+This rule also means that you may use neither kernel image addresses
+(items in data/text/bss segments), nor module image addresses, nor
+stack addresses for DMA.  These could all be mapped somewhere entirely
+different than the rest of physical memory.  Even if those classes of
+memory could physically work with DMA, you'd need to ensure the I/O
+buffers were cacheline-aligned.  Without that, you'd see cacheline
+sharing problems (data corruption) on CPUs with DMA-incoherent caches.
+(The CPU could write to one word, DMA would write to a different one
+in the same cache line, and one of them could be overwritten.)
+
+Also, this means that you cannot take the return of a kmap()
+call and DMA to/from that.  This is similar to vmalloc().
+
+What about block I/O and networking buffers?  The block I/O and
+networking subsystems make sure that the buffers they use are valid
+for you to DMA from/to.
+
+                       DMA addressing limitations
+
+Does your device have any DMA addressing limitations?  For example, is
+your device only capable of driving the low order 24-bits of address
+on the PCI bus for SAC DMA transfers?  If so, you need to inform the
+PCI layer of this fact.
+
+By default, the kernel assumes that your device can address the full
+32-bits in a SAC cycle.  For a 64-bit DAC capable device, this needs
+to be increased.  And for a device with limitations, as discussed in
+the previous paragraph, it needs to be decreased.
+
+pci_alloc_consistent() by default will return 32-bit DMA addresses.
+PCI-X specification requires PCI-X devices to support 64-bit
+addressing (DAC) for all transactions. And at least one platform (SGI
+SN2) requires 64-bit consistent allocations to operate correctly when
+the IO bus is in PCI-X mode. Therefore, like with pci_set_dma_mask(),
+it's good practice to call pci_set_consistent_dma_mask() to set the
+appropriate mask even if your device only supports 32-bit DMA
+(default) and especially if it's a PCI-X device.
+
+For correct operation, you must interrogate the PCI layer in your
+device probe routine to see if the PCI controller on the machine can
+properly support the DMA addressing limitation your device has.  It is
+good style to do this even if your device holds the default setting,
+because this shows that you did think about these issues wrt. your
+device.
+
+The query is performed via a call to pci_set_dma_mask():
+
+       int pci_set_dma_mask(struct pci_dev *pdev, u64 device_mask);
+
+The query for consistent allocations is performed via a call to
+pci_set_consistent_dma_mask():
+
+       int pci_set_consistent_dma_mask(struct pci_dev *pdev, u64 device_mask);
+
+Here, pdev is a pointer to the PCI device struct of your device, and
+device_mask is a bit mask describing which bits of a PCI address your
+device supports.  It returns zero if your card can perform DMA
+properly on the machine given the address mask you provided.
+
+If it returns non-zero, your device cannot perform DMA properly on
+this platform, and attempting to do so will result in undefined
+behavior.  You must either use a different mask, or not use DMA.
+
+This means that in the failure case, you have three options:
+
+1) Use another DMA mask, if possible (see below).
+2) Use some non-DMA mode for data transfer, if possible.
+3) Ignore this device and do not initialize it.
+
+It is recommended that your driver print a kernel KERN_WARNING message
+when you end up performing either #2 or #3.  In this manner, if a user
+of your driver reports that performance is bad or that the device is not
+even detected, you can ask them for the kernel messages to find out
+exactly why.
+
+The standard 32-bit addressing PCI device would do something like
+this:
+
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               printk(KERN_WARNING
+                      "mydev: No suitable DMA available.\n");
+               goto ignore_this_device;
+       }
+
+Another common scenario is a 64-bit capable device.  The approach
+here is to try for 64-bit DAC addressing, but back down to a
+32-bit mask should that fail.  The PCI platform code may fail the
+64-bit mask not because the platform is not capable of 64-bit
+addressing.  Rather, it may fail in this case simply because
+32-bit SAC addressing is done more efficiently than DAC addressing.
+Sparc64 is one platform which behaves in this way.
+
+Here is how you would handle a 64-bit capable device which can drive
+all 64-bits when accessing streaming DMA:
+
+       int using_dac;
+
+       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+               using_dac = 1;
+       } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               using_dac = 0;
+       } else {
+               printk(KERN_WARNING
+                      "mydev: No suitable DMA available.\n");
+               goto ignore_this_device;
+       }
+
+If a card is capable of using 64-bit consistent allocations as well,
+the case would look like this:
+
+       int using_dac, consistent_using_dac;
+
+       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+               using_dac = 1;
+               consistent_using_dac = 1;
+               pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+       } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               using_dac = 0;
+               consistent_using_dac = 0;
+               pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       } else {
+               printk(KERN_WARNING
+                      "mydev: No suitable DMA available.\n");
+               goto ignore_this_device;
+       }
+
+pci_set_consistent_dma_mask() will always be able to set the same or a
+smaller mask as pci_set_dma_mask(). However for the rare case that a
+device driver only uses consistent allocations, one would have to
+check the return value from pci_set_consistent_dma_mask().
+
+Finally, if your device can only drive the low 24-bits of
+address during PCI bus mastering you might do something like:
+
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(24))) {
+               printk(KERN_WARNING
+                      "mydev: 24-bit DMA addressing not available.\n");
+               goto ignore_this_device;
+       }
+
+When pci_set_dma_mask() is successful, and returns zero, the PCI layer
+saves away this mask you have provided.  The PCI layer will use this
+information later when you make DMA mappings.
+
+There is a case which we are aware of at this time, which is worth
+mentioning in this documentation.  If your device supports multiple
+functions (for example a sound card provides playback and record
+functions) and the various different functions have _different_
+DMA addressing limitations, you may wish to probe each mask and
+only provide the functionality which the machine can handle.  It
+is important that the last call to pci_set_dma_mask() be for the
+most specific mask.
+
+Here is pseudo-code showing how this might be done:
+
+       #define PLAYBACK_ADDRESS_BITS   DMA_BIT_MASK(32)
+       #define RECORD_ADDRESS_BITS     DMA_BIT_MASK(24)
+
+       struct my_sound_card *card;
+       struct pci_dev *pdev;
+
+       ...
+       if (!pci_set_dma_mask(pdev, PLAYBACK_ADDRESS_BITS)) {
+               card->playback_enabled = 1;
+       } else {
+               card->playback_enabled = 0;
+               printk(KERN_WARNING "%s: Playback disabled due to DMA limitations.\n",
+                      card->name);
+       }
+       if (!pci_set_dma_mask(pdev, RECORD_ADDRESS_BITS)) {
+               card->record_enabled = 1;
+       } else {
+               card->record_enabled = 0;
+               printk(KERN_WARNING "%s: Record disabled due to DMA limitations.\n",
+                      card->name);
+       }
+
+A sound card was used as an example here because this genre of PCI
+devices seems to be littered with ISA chips given a PCI front end,
+and thus retaining the 16MB DMA addressing limitations of ISA.
+
+                       Types of DMA mappings
+
+There are two types of DMA mappings:
+
+- Consistent DMA mappings which are usually mapped at driver
+  initialization, unmapped at the end and for which the hardware should
+  guarantee that the device and the CPU can access the data
+  in parallel and will see updates made by each other without any
+  explicit software flushing.
+
+  Think of "consistent" as "synchronous" or "coherent".
+
+  The current default is to return consistent memory in the low 32
+  bits of the PCI bus space.  However, for future compatibility you
+  should set the consistent mask even if this default is fine for your
+  driver.
+
+  Good examples of what to use consistent mappings for are:
+
+       - Network card DMA ring descriptors.
+       - SCSI adapter mailbox command data structures.
+       - Device firmware microcode executed out of
+         main memory.
+
+  The invariant these examples all require is that any CPU store
+  to memory is immediately visible to the device, and vice
+  versa.  Consistent mappings guarantee this.
+
+  IMPORTANT: Consistent DMA memory does not preclude the usage of
+             proper memory barriers.  The CPU may reorder stores to
+            consistent memory just as it may normal memory.  Example:
+            if it is important for the device to see the first word
+            of a descriptor updated before the second, you must do
+            something like:
+
+               desc->word0 = address;
+               wmb();
+               desc->word1 = DESC_VALID;
+
+             in order to get correct behavior on all platforms.
+
+            Also, on some platforms your driver may need to flush CPU write
+            buffers in much the same way as it needs to flush write buffers
+            found in PCI bridges (such as by reading a register's value
+            after writing it).
+
+- Streaming DMA mappings which are usually mapped for one DMA transfer,
+  unmapped right after it (unless you use pci_dma_sync_* below) and for which
+  hardware can optimize for sequential accesses.
+
+  This of "streaming" as "asynchronous" or "outside the coherency
+  domain".
+
+  Good examples of what to use streaming mappings for are:
+
+       - Networking buffers transmitted/received by a device.
+       - Filesystem buffers written/read by a SCSI device.
+
+  The interfaces for using this type of mapping were designed in
+  such a way that an implementation can make whatever performance
+  optimizations the hardware allows.  To this end, when using
+  such mappings you must be explicit about what you want to happen.
+
+Neither type of DMA mapping has alignment restrictions that come
+from PCI, although some devices may have such restrictions.
+Also, systems with caches that aren't DMA-coherent will work better
+when the underlying buffers don't share cache lines with other data.
+
+
+                Using Consistent DMA mappings.
+
+To allocate and map large (PAGE_SIZE or so) consistent DMA regions,
+you should do:
+
+       dma_addr_t dma_handle;
+
+       cpu_addr = pci_alloc_consistent(pdev, size, &dma_handle);
+
+where pdev is a struct pci_dev *. This may be called in interrupt context.
+You should use dma_alloc_coherent (see DMA-API.txt) for buses
+where devices don't have struct pci_dev (like ISA, EISA).
+
+This argument is needed because the DMA translations may be bus
+specific (and often is private to the bus which the device is attached
+to).
+
+Size is the length of the region you want to allocate, in bytes.
+
+This routine will allocate RAM for that region, so it acts similarly to
+__get_free_pages (but takes size instead of a page order).  If your
+driver needs regions sized smaller than a page, you may prefer using
+the pci_pool interface, described below.
+
+The consistent DMA mapping interfaces, for non-NULL pdev, will by
+default return a DMA address which is SAC (Single Address Cycle)
+addressable.  Even if the device indicates (via PCI dma mask) that it
+may address the upper 32-bits and thus perform DAC cycles, consistent
+allocation will only return > 32-bit PCI addresses for DMA if the
+consistent dma mask has been explicitly changed via
+pci_set_consistent_dma_mask().  This is true of the pci_pool interface
+as well.
+
+pci_alloc_consistent returns two values: the virtual address which you
+can use to access it from the CPU and dma_handle which you pass to the
+card.
+
+The cpu return address and the DMA bus master address are both
+guaranteed to be aligned to the smallest PAGE_SIZE order which
+is greater than or equal to the requested size.  This invariant
+exists (for example) to guarantee that if you allocate a chunk
+which is smaller than or equal to 64 kilobytes, the extent of the
+buffer you receive will not cross a 64K boundary.
+
+To unmap and free such a DMA region, you call:
+
+       pci_free_consistent(pdev, size, cpu_addr, dma_handle);
+
+where pdev, size are the same as in the above call and cpu_addr and
+dma_handle are the values pci_alloc_consistent returned to you.
+This function may not be called in interrupt context.
+
+If your driver needs lots of smaller memory regions, you can write
+custom code to subdivide pages returned by pci_alloc_consistent,
+or you can use the pci_pool API to do that.  A pci_pool is like
+a kmem_cache, but it uses pci_alloc_consistent not __get_free_pages.
+Also, it understands common hardware constraints for alignment,
+like queue heads needing to be aligned on N byte boundaries.
+
+Create a pci_pool like this:
+
+       struct pci_pool *pool;
+
+       pool = pci_pool_create(name, pdev, size, align, alloc);
+
+The "name" is for diagnostics (like a kmem_cache name); pdev and size
+are as above.  The device's hardware alignment requirement for this
+type of data is "align" (which is expressed in bytes, and must be a
+power of two).  If your device has no boundary crossing restrictions,
+pass 0 for alloc; passing 4096 says memory allocated from this pool
+must not cross 4KByte boundaries (but at that time it may be better to
+go for pci_alloc_consistent directly instead).
+
+Allocate memory from a pci pool like this:
+
+       cpu_addr = pci_pool_alloc(pool, flags, &dma_handle);
+
+flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor
+holding SMP locks), SLAB_ATOMIC otherwise.  Like pci_alloc_consistent,
+this returns two values, cpu_addr and dma_handle.
+
+Free memory that was allocated from a pci_pool like this:
+
+       pci_pool_free(pool, cpu_addr, dma_handle);
+
+where pool is what you passed to pci_pool_alloc, and cpu_addr and
+dma_handle are the values pci_pool_alloc returned. This function
+may be called in interrupt context.
+
+Destroy a pci_pool by calling:
+
+       pci_pool_destroy(pool);
+
+Make sure you've called pci_pool_free for all memory allocated
+from a pool before you destroy the pool. This function may not
+be called in interrupt context.
+
+                       DMA Direction
+
+The interfaces described in subsequent portions of this document
+take a DMA direction argument, which is an integer and takes on
+one of the following values:
+
+ PCI_DMA_BIDIRECTIONAL
+ PCI_DMA_TODEVICE
+ PCI_DMA_FROMDEVICE
+ PCI_DMA_NONE
+
+One should provide the exact DMA direction if you know it.
+
+PCI_DMA_TODEVICE means "from main memory to the PCI device"
+PCI_DMA_FROMDEVICE means "from the PCI device to main memory"
+It is the direction in which the data moves during the DMA
+transfer.
+
+You are _strongly_ encouraged to specify this as precisely
+as you possibly can.
+
+If you absolutely cannot know the direction of the DMA transfer,
+specify PCI_DMA_BIDIRECTIONAL.  It means that the DMA can go in
+either direction.  The platform guarantees that you may legally
+specify this, and that it will work, but this may be at the
+cost of performance for example.
+
+The value PCI_DMA_NONE is to be used for debugging.  One can
+hold this in a data structure before you come to know the
+precise direction, and this will help catch cases where your
+direction tracking logic has failed to set things up properly.
+
+Another advantage of specifying this value precisely (outside of
+potential platform-specific optimizations of such) is for debugging.
+Some platforms actually have a write permission boolean which DMA
+mappings can be marked with, much like page protections in the user
+program address space.  Such platforms can and do report errors in the
+kernel logs when the PCI controller hardware detects violation of the
+permission setting.
+
+Only streaming mappings specify a direction, consistent mappings
+implicitly have a direction attribute setting of
+PCI_DMA_BIDIRECTIONAL.
+
+The SCSI subsystem tells you the direction to use in the
+'sc_data_direction' member of the SCSI command your driver is
+working on.
+
+For Networking drivers, it's a rather simple affair.  For transmit
+packets, map/unmap them with the PCI_DMA_TODEVICE direction
+specifier.  For receive packets, just the opposite, map/unmap them
+with the PCI_DMA_FROMDEVICE direction specifier.
+
+                 Using Streaming DMA mappings
+
+The streaming DMA mapping routines can be called from interrupt
+context.  There are two versions of each map/unmap, one which will
+map/unmap a single memory region, and one which will map/unmap a
+scatterlist.
+
+To map a single region, you do:
+
+       struct pci_dev *pdev = mydev->pdev;
+       dma_addr_t dma_handle;
+       void *addr = buffer->ptr;
+       size_t size = buffer->len;
+
+       dma_handle = pci_map_single(pdev, addr, size, direction);
+
+and to unmap it:
+
+       pci_unmap_single(pdev, dma_handle, size, direction);
+
+You should call pci_unmap_single when the DMA activity is finished, e.g.
+from the interrupt which told you that the DMA transfer is done.
+
+Using cpu pointers like this for single mappings has a disadvantage,
+you cannot reference HIGHMEM memory in this way.  Thus, there is a
+map/unmap interface pair akin to pci_{map,unmap}_single.  These
+interfaces deal with page/offset pairs instead of cpu pointers.
+Specifically:
+
+       struct pci_dev *pdev = mydev->pdev;
+       dma_addr_t dma_handle;
+       struct page *page = buffer->page;
+       unsigned long offset = buffer->offset;
+       size_t size = buffer->len;
+
+       dma_handle = pci_map_page(pdev, page, offset, size, direction);
+
+       ...
+
+       pci_unmap_page(pdev, dma_handle, size, direction);
+
+Here, "offset" means byte offset within the given page.
+
+With scatterlists, you map a region gathered from several regions by:
+
+       int i, count = pci_map_sg(pdev, sglist, nents, direction);
+       struct scatterlist *sg;
+
+       for_each_sg(sglist, sg, count, i) {
+               hw_address[i] = sg_dma_address(sg);
+               hw_len[i] = sg_dma_len(sg);
+       }
+
+where nents is the number of entries in the sglist.
+
+The implementation is free to merge several consecutive sglist entries
+into one (e.g. if DMA mapping is done with PAGE_SIZE granularity, any
+consecutive sglist entries can be merged into one provided the first one
+ends and the second one starts on a page boundary - in fact this is a huge
+advantage for cards which either cannot do scatter-gather or have very
+limited number of scatter-gather entries) and returns the actual number
+of sg entries it mapped them to. On failure 0 is returned.
+
+Then you should loop count times (note: this can be less than nents times)
+and use sg_dma_address() and sg_dma_len() macros where you previously
+accessed sg->address and sg->length as shown above.
+
+To unmap a scatterlist, just call:
+
+       pci_unmap_sg(pdev, sglist, nents, direction);
+
+Again, make sure DMA activity has already finished.
+
+PLEASE NOTE:  The 'nents' argument to the pci_unmap_sg call must be
+              the _same_ one you passed into the pci_map_sg call,
+             it should _NOT_ be the 'count' value _returned_ from the
+              pci_map_sg call.
+
+Every pci_map_{single,sg} call should have its pci_unmap_{single,sg}
+counterpart, because the bus address space is a shared resource (although
+in some ports the mapping is per each BUS so less devices contend for the
+same bus address space) and you could render the machine unusable by eating
+all bus addresses.
+
+If you need to use the same streaming DMA region multiple times and touch
+the data in between the DMA transfers, the buffer needs to be synced
+properly in order for the cpu and device to see the most uptodate and
+correct copy of the DMA buffer.
+
+So, firstly, just map it with pci_map_{single,sg}, and after each DMA
+transfer call either:
+
+       pci_dma_sync_single_for_cpu(pdev, dma_handle, size, direction);
+
+or:
+
+       pci_dma_sync_sg_for_cpu(pdev, sglist, nents, direction);
+
+as appropriate.
+
+Then, if you wish to let the device get at the DMA area again,
+finish accessing the data with the cpu, and then before actually
+giving the buffer to the hardware call either:
+
+       pci_dma_sync_single_for_device(pdev, dma_handle, size, direction);
+
+or:
+
+       pci_dma_sync_sg_for_device(dev, sglist, nents, direction);
+
+as appropriate.
+
+After the last DMA transfer call one of the DMA unmap routines
+pci_unmap_{single,sg}. If you don't touch the data from the first pci_map_*
+call till pci_unmap_*, then you don't have to call the pci_dma_sync_*
+routines at all.
+
+Here is pseudo code which shows a situation in which you would need
+to use the pci_dma_sync_*() interfaces.
+
+       my_card_setup_receive_buffer(struct my_card *cp, char *buffer, int len)
+       {
+               dma_addr_t mapping;
+
+               mapping = pci_map_single(cp->pdev, buffer, len, PCI_DMA_FROMDEVICE);
+
+               cp->rx_buf = buffer;
+               cp->rx_len = len;
+               cp->rx_dma = mapping;
+
+               give_rx_buf_to_card(cp);
+       }
+
+       ...
+
+       my_card_interrupt_handler(int irq, void *devid, struct pt_regs *regs)
+       {
+               struct my_card *cp = devid;
+
+               ...
+               if (read_card_status(cp) == RX_BUF_TRANSFERRED) {
+                       struct my_card_header *hp;
+
+                       /* Examine the header to see if we wish
+                        * to accept the data.  But synchronize
+                        * the DMA transfer with the CPU first
+                        * so that we see updated contents.
+                        */
+                       pci_dma_sync_single_for_cpu(cp->pdev, cp->rx_dma,
+                                                   cp->rx_len,
+                                                   PCI_DMA_FROMDEVICE);
+
+                       /* Now it is safe to examine the buffer. */
+                       hp = (struct my_card_header *) cp->rx_buf;
+                       if (header_is_ok(hp)) {
+                               pci_unmap_single(cp->pdev, cp->rx_dma, cp->rx_len,
+                                                PCI_DMA_FROMDEVICE);
+                               pass_to_upper_layers(cp->rx_buf);
+                               make_and_setup_new_rx_buf(cp);
+                       } else {
+                               /* Just sync the buffer and give it back
+                                * to the card.
+                                */
+                               pci_dma_sync_single_for_device(cp->pdev,
+                                                              cp->rx_dma,
+                                                              cp->rx_len,
+                                                              PCI_DMA_FROMDEVICE);
+                               give_rx_buf_to_card(cp);
+                       }
+               }
+       }
+
+Drivers converted fully to this interface should not use virt_to_bus any
+longer, nor should they use bus_to_virt. Some drivers have to be changed a
+little bit, because there is no longer an equivalent to bus_to_virt in the
+dynamic DMA mapping scheme - you have to always store the DMA addresses
+returned by the pci_alloc_consistent, pci_pool_alloc, and pci_map_single
+calls (pci_map_sg stores them in the scatterlist itself if the platform
+supports dynamic DMA mapping in hardware) in your driver structures and/or
+in the card registers.
+
+All PCI drivers should be using these interfaces with no exceptions.
+It is planned to completely remove virt_to_bus() and bus_to_virt() as
+they are entirely deprecated.  Some ports already do not provide these
+as it is impossible to correctly support them.
+
+               Optimizing Unmap State Space Consumption
+
+On many platforms, pci_unmap_{single,page}() is simply a nop.
+Therefore, keeping track of the mapping address and length is a waste
+of space.  Instead of filling your drivers up with ifdefs and the like
+to "work around" this (which would defeat the whole purpose of a
+portable API) the following facilities are provided.
+
+Actually, instead of describing the macros one by one, we'll
+transform some example code.
+
+1) Use DECLARE_PCI_UNMAP_{ADDR,LEN} in state saving structures.
+   Example, before:
+
+       struct ring_state {
+               struct sk_buff *skb;
+               dma_addr_t mapping;
+               __u32 len;
+       };
+
+   after:
+
+       struct ring_state {
+               struct sk_buff *skb;
+               DECLARE_PCI_UNMAP_ADDR(mapping)
+               DECLARE_PCI_UNMAP_LEN(len)
+       };
+
+   NOTE: DO NOT put a semicolon at the end of the DECLARE_*()
+         macro.
+
+2) Use pci_unmap_{addr,len}_set to set these values.
+   Example, before:
+
+       ringp->mapping = FOO;
+       ringp->len = BAR;
+
+   after:
+
+       pci_unmap_addr_set(ringp, mapping, FOO);
+       pci_unmap_len_set(ringp, len, BAR);
+
+3) Use pci_unmap_{addr,len} to access these values.
+   Example, before:
+
+       pci_unmap_single(pdev, ringp->mapping, ringp->len,
+                        PCI_DMA_FROMDEVICE);
+
+   after:
+
+       pci_unmap_single(pdev,
+                        pci_unmap_addr(ringp, mapping),
+                        pci_unmap_len(ringp, len),
+                        PCI_DMA_FROMDEVICE);
+
+It really should be self-explanatory.  We treat the ADDR and LEN
+separately, because it is possible for an implementation to only
+need the address in order to perform the unmap operation.
+
+                       Platform Issues
+
+If you are just writing drivers for Linux and do not maintain
+an architecture port for the kernel, you can safely skip down
+to "Closing".
+
+1) Struct scatterlist requirements.
+
+   Struct scatterlist must contain, at a minimum, the following
+   members:
+
+       struct page *page;
+       unsigned int offset;
+       unsigned int length;
+
+   The base address is specified by a "page+offset" pair.
+
+   Previous versions of struct scatterlist contained a "void *address"
+   field that was sometimes used instead of page+offset.  As of Linux
+   2.5., page+offset is always used, and the "address" field has been
+   deleted.
+
+2) More to come...
+
+                       Handling Errors
+
+DMA address space is limited on some architectures and an allocation
+failure can be determined by:
+
+- checking if pci_alloc_consistent returns NULL or pci_map_sg returns 0
+
+- checking the returned dma_addr_t of pci_map_single and pci_map_page
+  by using pci_dma_mapping_error():
+
+       dma_addr_t dma_handle;
+
+       dma_handle = pci_map_single(pdev, addr, size, direction);
+       if (pci_dma_mapping_error(pdev, dma_handle)) {
+               /*
+                * reduce current DMA mapping usage,
+                * delay and try again later or
+                * reset driver.
+                */
+       }
+
+                          Closing
+
+This document, and the API itself, would not be in it's current
+form without the feedback and suggestions from numerous individuals.
+We would like to specifically mention, in no particular order, the
+following people:
+
+       Russell King <rmk@arm.linux.org.uk>
+       Leo Dagum <dagum@barrel.engr.sgi.com>
+       Ralf Baechle <ralf@oss.sgi.com>
+       Grant Grundler <grundler@cup.hp.com>
+       Jay Estabrook <Jay.Estabrook@compaq.com>
+       Thomas Sailer <sailer@ife.ee.ethz.ch>
+       Andrea Arcangeli <andrea@suse.de>
+       Jens Axboe <jens.axboe@oracle.com>
+       David Mosberger-Tang <davidm@hpl.hp.com>
index 961a0513f8c34a4328313094b7d6fff179f17e32..a406286f6f3e64e5d2cf043be83dd2e206e28633 100644 (file)
@@ -1,7 +1,5 @@
 00-INDEX
        - This file
-as-iosched.txt
-       - Anticipatory IO scheduler
 barrier.txt
        - I/O Barriers
 biodoc.txt
diff --git a/Documentation/block/as-iosched.txt b/Documentation/block/as-iosched.txt
deleted file mode 100644 (file)
index 738b72b..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-Anticipatory IO scheduler
--------------------------
-Nick Piggin <piggin@cyberone.com.au>    13 Sep 2003
-
-Attention! Database servers, especially those using "TCQ" disks should
-investigate performance with the 'deadline' IO scheduler. Any system with high
-disk performance requirements should do so, in fact.
-
-If you see unusual performance characteristics of your disk systems, or you
-see big performance regressions versus the deadline scheduler, please email
-me. Database users don't bother unless you're willing to test a lot of patches
-from me ;) its a known issue.
-
-Also, users with hardware RAID controllers, doing striping, may find
-highly variable performance results with using the as-iosched. The
-as-iosched anticipatory implementation is based on the notion that a disk
-device has only one physical seeking head.  A striped RAID controller
-actually has a head for each physical device in the logical RAID device.
-
-However, setting the antic_expire (see tunable parameters below) produces
-very similar behavior to the deadline IO scheduler.
-
-Selecting IO schedulers
------------------------
-Refer to Documentation/block/switching-sched.txt for information on
-selecting an io scheduler on a per-device basis.
-
-Anticipatory IO scheduler Policies
-----------------------------------
-The as-iosched implementation implements several layers of policies
-to determine when an IO request is dispatched to the disk controller.
-Here are the policies outlined, in order of application.
-
-1. one-way Elevator algorithm.
-
-The elevator algorithm is similar to that used in deadline scheduler, with
-the addition that it allows limited backward movement of the elevator
-(i.e. seeks backwards).  A seek backwards can occur when choosing between
-two IO requests where one is behind the elevator's current position, and
-the other is in front of the elevator's position. If the seek distance to
-the request in back of the elevator is less than half the seek distance to
-the request in front of the elevator, then the request in back can be chosen.
-Backward seeks are also limited to a maximum of MAXBACK (1024*1024) sectors.
-This favors forward movement of the elevator, while allowing opportunistic
-"short" backward seeks.
-
-2. FIFO expiration times for reads and for writes.
-
-This is again very similar to the deadline IO scheduler.  The expiration
-times for requests on these lists is tunable using the parameters read_expire
-and write_expire discussed below.  When a read or a write expires in this way,
-the IO scheduler will interrupt its current elevator sweep or read anticipation
-to service the expired request.
-
-3. Read and write request batching
-
-A batch is a collection of read requests or a collection of write
-requests.  The as scheduler alternates dispatching read and write batches
-to the driver.  In the case a read batch, the scheduler submits read
-requests to the driver as long as there are read requests to submit, and
-the read batch time limit has not been exceeded (read_batch_expire).
-The read batch time limit begins counting down only when there are
-competing write requests pending.
-
-In the case of a write batch, the scheduler submits write requests to
-the driver as long as there are write requests available, and the
-write batch time limit has not been exceeded (write_batch_expire).
-However, the length of write batches will be gradually shortened
-when read batches frequently exceed their time limit.
-
-When changing between batch types, the scheduler waits for all requests
-from the previous batch to complete before scheduling requests for the
-next batch.
-
-The read and write fifo expiration times described in policy 2 above
-are checked only when in scheduling IO of a batch for the corresponding
-(read/write) type.  So for example, the read FIFO timeout values are
-tested only during read batches.  Likewise, the write FIFO timeout
-values are tested only during write batches.  For this reason,
-it is generally not recommended for the read batch time
-to be longer than the write expiration time, nor for the write batch
-time to exceed the read expiration time (see tunable parameters below).
-
-When the IO scheduler changes from a read to a write batch,
-it begins the elevator from the request that is on the head of the
-write expiration FIFO.  Likewise, when changing from a write batch to
-a read batch, scheduler begins the elevator from the first entry
-on the read expiration FIFO.
-
-4. Read anticipation.
-
-Read anticipation occurs only when scheduling a read batch.
-This implementation of read anticipation allows only one read request
-to be dispatched to the disk controller at a time.  In
-contrast, many write requests may be dispatched to the disk controller
-at a time during a write batch.  It is this characteristic that can make
-the anticipatory scheduler perform anomalously with controllers supporting
-TCQ, or with hardware striped RAID devices. Setting the antic_expire
-queue parameter (see below) to zero disables this behavior, and the 
-anticipatory scheduler behaves essentially like the deadline scheduler.
-
-When read anticipation is enabled (antic_expire is not zero), reads
-are dispatched to the disk controller one at a time.
-At the end of each read request, the IO scheduler examines its next
-candidate read request from its sorted read list.  If that next request
-is from the same process as the request that just completed,
-or if the next request in the queue is "very close" to the
-just completed request, it is dispatched immediately.  Otherwise,
-statistics (average think time, average seek distance) on the process
-that submitted the just completed request are examined.  If it seems
-likely that that process will submit another request soon, and that
-request is likely to be near the just completed request, then the IO
-scheduler will stop dispatching more read requests for up to (antic_expire)
-milliseconds, hoping that process will submit a new request near the one
-that just completed.  If such a request is made, then it is dispatched
-immediately.  If the antic_expire wait time expires, then the IO scheduler
-will dispatch the next read request from the sorted read queue.
-
-To decide whether an anticipatory wait is worthwhile, the scheduler
-maintains statistics for each process that can be used to compute
-mean "think time" (the time between read requests), and mean seek
-distance for that process.  One observation is that these statistics
-are associated with each process, but those statistics are not associated
-with a specific IO device.  So for example, if a process is doing IO
-on several file systems on separate devices, the statistics will be
-a combination of IO behavior from all those devices.
-
-
-Tuning the anticipatory IO scheduler
-------------------------------------
-When using 'as', the anticipatory IO scheduler there are 5 parameters under
-/sys/block/*/queue/iosched/. All are units of milliseconds.
-
-The parameters are:
-* read_expire
-    Controls how long until a read request becomes "expired". It also controls the
-    interval between which expired requests are served, so set to 50, a request
-    might take anywhere < 100ms to be serviced _if_ it is the next on the
-    expired list. Obviously request expiration strategies won't make the disk
-    go faster. The result basically equates to the timeslice a single reader
-    gets in the presence of other IO. 100*((seek time / read_expire) + 1) is
-    very roughly the % streaming read efficiency your disk should get with
-    multiple readers.
-
-* read_batch_expire
-    Controls how much time a batch of reads is given before pending writes are
-    served. A higher value is more efficient. This might be set below read_expire
-    if writes are to be given higher priority than reads, but reads are to be
-    as efficient as possible when there are no writes. Generally though, it
-    should be some multiple of read_expire.
-
-* write_expire, and
-* write_batch_expire are equivalent to the above, for writes.
-
-* antic_expire
-    Controls the maximum amount of time we can anticipate a good read (one
-    with a short seek distance from the most recently completed request) before
-    giving up. Many other factors may cause anticipation to be stopped early,
-    or some processes will not be "anticipated" at all. Should be a bit higher
-    for big seek time devices though not a linear correspondence - most
-    processes have only a few ms thinktime.
-
-In addition to the tunables above there is a read-only file named est_time
-which, when read, will show:
-
-    - The probability of a task exiting without a cooperating task
-      submitting an anticipated IO.
-
-    - The current mean think time.
-
-    - The seek distance used to determine if an incoming IO is better.
-
index 8d2158a1c6aaf433e8063650309be1667954f062..6fab97ea7e6b0ecd4b3973cd0787257f14647617 100644 (file)
@@ -186,7 +186,7 @@ a virtual address mapping (unlike the earlier scheme of virtual address
 do not have a corresponding kernel virtual address space mapping) and
 low-memory pages.
 
-Note: Please refer to Documentation/DMA-mapping.txt for a discussion
+Note: Please refer to Documentation/PCI/PCI-DMA-mapping.txt for a discussion
 on PCI high mem DMA aspects and mapping of scatter gather lists, and support
 for 64 bit PCI.
 
index af6885c3c821f621f5827a46cb0728c61a9e768c..e1def1786e5074e5d8f3cf89b5f14cbfc9fab4af 100644 (file)
@@ -196,7 +196,7 @@ nobarrier           This also requires an IO stack which can support
                        also be used to enable or disable barriers, for
                        consistency with other ext4 mount options.
 
-inode_readahead=n      This tuning parameter controls the maximum
+inode_readahead_blks=n This tuning parameter controls the maximum
                        number of inode table blocks that ext4's inode
                        table readahead algorithm will pre-read into
                        the buffer cache.  The default value is 32 blocks.
index 4949fcaa6b6a94f6d8b42d483a86c9a5984e0420..839efd8a8a8c19ddce029661e2c166a434f5f080 100644 (file)
@@ -28,7 +28,7 @@ described in the man pages included in the package.
 Project web page:    http://www.nilfs.org/en/
 Download page:       http://www.nilfs.org/en/download.html
 Git tree web page:   http://www.nilfs.org/git/
-NILFS mailing lists: http://www.nilfs.org/mailman/listinfo/users
+List info:           http://vger.kernel.org/vger-lists.html#linux-nilfs
 
 Caveats
 =======
index 220cc6376ef80e0c9bcfec162d45552e729cdf5a..0d07513a67a661440fc1599121bb1dc38560bc33 100644 (file)
@@ -177,7 +177,6 @@ read the file /proc/PID/status:
   CapBnd: ffffffffffffffff
   voluntary_ctxt_switches:        0
   nonvoluntary_ctxt_switches:     1
-  Stack usage:    12 kB
 
 This shows you nearly the same information you would get if you viewed it with
 the ps  command.  In  fact,  ps  uses  the  proc  file  system  to  obtain its
@@ -231,7 +230,6 @@ Table 1-2: Contents of the statm files (as of 2.6.30-rc7)
  Mems_allowed_list           Same as previous, but in "list format"
  voluntary_ctxt_switches     number of voluntary context switches
  nonvoluntary_ctxt_switches  number of non voluntary context switches
- Stack usage:                stack usage high water mark (round up to page size)
 ..............................................................................
 
 Table 1-3: Contents of the statm files (as of 2.6.8-rc3)
diff --git a/Documentation/hwmon/amc6821 b/Documentation/hwmon/amc6821
new file mode 100644 (file)
index 0000000..ced8359
--- /dev/null
@@ -0,0 +1,102 @@
+Kernel driver amc6821
+=====================
+
+Supported chips:
+       Texas Instruments AMC6821
+       Prefix: 'amc6821'
+       Addresses scanned: 0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e, 0x4c, 0x4d, 0x4e
+       Datasheet: http://focus.ti.com/docs/prod/folders/print/amc6821.html
+
+Authors:
+       Tomaz Mertelj <tomaz.mertelj@guest.arnes.si>
+
+
+Description
+-----------
+
+This driver implements support for the Texas Instruments amc6821 chip.
+The chip has one on-chip and one remote temperature sensor and one pwm fan
+regulator.
+The pwm can be controlled either from software or automatically.
+
+The driver provides the following sensor accesses in sysfs:
+
+temp1_input            ro      on-chip temperature
+temp1_min              rw      "
+temp1_max              rw      "
+temp1_crit             rw      "
+temp1_min_alarm                ro      "
+temp1_max_alarm                ro      "
+temp1_crit_alarm       ro      "
+
+temp2_input            ro      remote temperature
+temp2_min              rw      "
+temp2_max              rw      "
+temp2_crit             rw      "
+temp2_min_alarm                ro      "
+temp2_max_alarm                ro      "
+temp2_crit_alarm       ro      "
+temp2_fault            ro      "
+
+fan1_input             ro      tachometer speed
+fan1_min               rw      "
+fan1_max               rw      "
+fan1_fault             ro      "
+fan1_div               rw      Fan divisor can be either 2 or 4.
+
+pwm1                   rw      pwm1
+pwm1_enable            rw      regulator mode, 1=open loop, 2=fan controlled
+                               by remote temperature, 3=fan controlled by
+                               combination of the on-chip temperature and
+                               remote-sensor temperature,
+pwm1_auto_channels_temp ro     1 if pwm_enable==2, 3 if pwm_enable==3
+pwm1_auto_point1_pwm   ro      Hardwired to 0, shared for both
+                               temperature channels.
+pwm1_auto_point2_pwm   rw      This value is shared for both temperature
+                               channels.
+pwm1_auto_point3_pwm   rw      Hardwired to 255, shared for both
+                               temperature channels.
+
+temp1_auto_point1_temp ro      Hardwired to temp2_auto_point1_temp
+                               which is rw. Below this temperature fan stops.
+temp1_auto_point2_temp rw      The low-temperature limit of the proportional
+                               range. Below this temperature
+                               pwm1 = pwm1_auto_point2_pwm. It can go from
+                               0 degree C to 124 degree C in steps of
+                               4 degree C. Read it out after writing to get
+                               the actual value.
+temp1_auto_point3_temp rw      Above this temperature fan runs at maximum
+                               speed. It can go from temp1_auto_point2_temp.
+                               It can only have certain discrete values
+                               which depend on temp1_auto_point2_temp and
+                               pwm1_auto_point2_pwm. Read it out after
+                               writing to get the actual value.
+
+temp2_auto_point1_temp rw      Must be between 0 degree C and 63 degree C and
+                               it defines the passive cooling temperature.
+                               Below this temperature the fan stops in
+                               the closed loop mode.
+temp2_auto_point2_temp rw      The low-temperature limit of the proportional
+                               range. Below this temperature
+                               pwm1 = pwm1_auto_point2_pwm. It can go from
+                               0 degree C to 124 degree C in steps
+                               of 4 degree C.
+
+temp2_auto_point3_temp rw      Above this temperature fan runs at maximum
+                               speed. It can only have certain discrete
+                               values which depend on temp2_auto_point2_temp
+                               and pwm1_auto_point2_pwm. Read it out after
+                               writing to get actual value.
+
+
+Module parameters
+-----------------
+
+If your board has a BIOS that initializes the amc6821 correctly, you should
+load the module with: init=0.
+
+If your board BIOS doesn't initialize the chip, or you want
+different settings, you can set the following parameters:
+init=1,
+pwminv: 0 default pwm output, 1 inverts pwm output.
+
index a7a18d453a51c5ba3c5828867c035a4c337b67b6..6526eee525a67b9e0966c614dfb626cd2877ef7d 100644 (file)
@@ -3,8 +3,8 @@ Kernel driver k10temp
 
 Supported chips:
 * AMD Family 10h processors:
-  Socket F: Quad-Core/Six-Core/Embedded Opteron
-  Socket AM2+: Opteron, Phenom (II) X3/X4
+  Socket F: Quad-Core/Six-Core/Embedded Opteron (but see below)
+  Socket AM2+: Quad-Core Opteron, Phenom (II) X3/X4, Athlon X2 (but see below)
   Socket AM3: Quad-Core Opteron, Athlon/Phenom II X2/X3/X4, Sempron II
   Socket S1G3: Athlon II, Sempron, Turion II
 * AMD Family 11h processors:
@@ -36,10 +36,15 @@ Description
 This driver permits reading of the internal temperature sensor of AMD
 Family 10h and 11h processors.
 
-All these processors have a sensor, but on older revisions of Family 10h
-processors, the sensor may return inconsistent values (erratum 319). The
-driver will refuse to load on these revisions unless you specify the
-"force=1" module parameter.
+All these processors have a sensor, but on those for Socket F or AM2+,
+the sensor may return inconsistent values (erratum 319).  The driver
+will refuse to load on these revisions unless you specify the "force=1"
+module parameter.
+
+Due to technical reasons, the driver can detect only the mainboard's
+socket type, not the processor's actual capabilities.  Therefore, if you
+are using an AM3 processor on an AM2+ mainboard, you can safely use the
+"force=1" parameter.
 
 There is one temperature measurement value, available as temp1_input in
 sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree.
index 947374977ca5a2ef72e59cdb730d9d50c7f6b0b2..35cf64d4436d0731c4365902a31278dee824f17a 100644 (file)
@@ -56,10 +56,11 @@ Following this convention is good because:
 (5) When following the convention, the driver code can use generic
     code to copy the parameters between user and kernel space.
 
-This table lists ioctls visible from user land for Linux/i386.  It contains
-most drivers up to 2.3.14, but I know I am missing some.
+This table lists ioctls visible from user land for Linux/x86.  It contains
+most drivers up to 2.6.31, but I know I am missing some.  There has been
+no attempt to list non-X86 architectures or ioctls from drivers/staging/.
 
-Code   Seq#    Include File            Comments
+Code  Seq#(hex)        Include File            Comments
 ========================================================
 0x00   00-1F   linux/fs.h              conflict!
 0x00   00-1F   scsi/scsi_ioctl.h       conflict!
@@ -69,119 +70,228 @@ Code      Seq#    Include File            Comments
 0x03   all     linux/hdreg.h
 0x04   D2-DC   linux/umsdos_fs.h       Dead since 2.6.11, but don't reuse these.
 0x06   all     linux/lp.h
-0x09   all     linux/md.h
+0x09   all     linux/raid/md_u.h
+0x10   00-0F   drivers/char/s390/vmcp.h
 0x12   all     linux/fs.h
                linux/blkpg.h
 0x1b   all     InfiniBand Subsystem    <http://www.openib.org/>
 0x20   all     drivers/cdrom/cm206.h
 0x22   all     scsi/sg.h
 '#'    00-3F   IEEE 1394 Subsystem     Block for the entire subsystem
+'$'    00-0F   linux/perf_counter.h, linux/perf_event.h
 '1'    00-1F   <linux/timepps.h>       PPS kit from Ulrich Windl
                                        <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
+'2'    01-04   linux/i2o.h
+'3'    00-0F   drivers/s390/char/raw3270.h     conflict!
+'3'    00-1F   linux/suspend_ioctls.h  conflict!
+               and kernel/power/user.c
 '8'    all                             SNP8023 advanced NIC card
                                        <mailto:mcr@solidum.com>
-'A'    00-1F   linux/apm_bios.h
+'@'    00-0F   linux/radeonfb.h        conflict!
+'@'    00-0F   drivers/video/aty/aty128fb.c    conflict!
+'A'    00-1F   linux/apm_bios.h        conflict!
+'A'    00-0F   linux/agpgart.h         conflict!
+               and drivers/char/agp/compat_ioctl.h
+'A'    00-7F   sound/asound.h          conflict!
+'B'    00-1F   linux/cciss_ioctl.h     conflict!
+'B'    00-0F   include/linux/pmu.h     conflict!
 'B'    C0-FF                           advanced bbus
                                        <mailto:maassen@uni-freiburg.de>
-'C'    all     linux/soundcard.h
+'C'    all     linux/soundcard.h       conflict!
+'C'    01-2F   linux/capi.h            conflict!
+'C'    F0-FF   drivers/net/wan/cosa.h  conflict!
 'D'    all     arch/s390/include/asm/dasd.h
-'E'    all     linux/input.h
-'F'    all     linux/fb.h
-'H'    all     linux/hiddev.h
-'I'    all     linux/isdn.h
+'D'    40-5F   drivers/scsi/dpt/dtpi_ioctl.h
+'D'    05      drivers/scsi/pmcraid.h
+'E'    all     linux/input.h           conflict!
+'E'    00-0F   xen/evtchn.h            conflict!
+'F'    all     linux/fb.h              conflict!
+'F'    01-02   drivers/scsi/pmcraid.h  conflict!
+'F'    20      drivers/video/fsl-diu-fb.h      conflict!
+'F'    20      drivers/video/intelfb/intelfb.h conflict!
+'F'    20      linux/ivtvfb.h          conflict!
+'F'    20      linux/matroxfb.h        conflict!
+'F'    20      drivers/video/aty/atyfb_base.c  conflict!
+'F'    00-0F   video/da8xx-fb.h        conflict!
+'F'    80-8F   linux/arcfb.h           conflict!
+'F'    DD      video/sstfb.h           conflict!
+'G'    00-3F   drivers/misc/sgi-gru/grulib.h   conflict!
+'G'    00-0F   linux/gigaset_dev.h     conflict!
+'H'    00-7F   linux/hiddev.h          conflict!
+'H'    00-0F   linux/hidraw.h          conflict!
+'H'    00-0F   sound/asound.h          conflict!
+'H'    20-40   sound/asound_fm.h       conflict!
+'H'    80-8F   sound/sfnt_info.h       conflict!
+'H'    10-8F   sound/emu10k1.h         conflict!
+'H'    10-1F   sound/sb16_csp.h        conflict!
+'H'    10-1F   sound/hda_hwdep.h       conflict!
+'H'    40-4F   sound/hdspm.h           conflict!
+'H'    40-4F   sound/hdsp.h            conflict!
+'H'    90      sound/usb/usx2y/usb_stream.h
+'H'    C0-F0   net/bluetooth/hci.h     conflict!
+'H'    C0-DF   net/bluetooth/hidp/hidp.h       conflict!
+'H'    C0-DF   net/bluetooth/cmtp/cmtp.h       conflict!
+'H'    C0-DF   net/bluetooth/bnep/bnep.h       conflict!
+'I'    all     linux/isdn.h            conflict!
+'I'    00-0F   drivers/isdn/divert/isdn_divert.h       conflict!
+'I'    40-4F   linux/mISDNif.h         conflict!
 'J'    00-1F   drivers/scsi/gdth_ioctl.h
 'K'    all     linux/kd.h
-'L'    00-1F   linux/loop.h
-'L'    20-2F   driver/usb/misc/vstusb.h
+'L'    00-1F   linux/loop.h            conflict!
+'L'    10-1F   drivers/scsi/mpt2sas/mpt2sas_ctl.h      conflict!
+'L'    20-2F   linux/usb/vstusb.h
 'L'    E0-FF   linux/ppdd.h            encrypted disk device driver
                                        <http://linux01.gwdg.de/~alatham/ppdd.html>
-'M'    all     linux/soundcard.h
+'M'    all     linux/soundcard.h       conflict!
+'M'    01-16   mtd/mtd-abi.h           conflict!
+               and drivers/mtd/mtdchar.c
+'M'    01-03   drivers/scsi/megaraid/megaraid_sas.h
+'M'    00-0F   drivers/video/fsl-diu-fb.h      conflict!
 'N'    00-1F   drivers/usb/scanner.h
-'O'     00-02   include/mtd/ubi-user.h UBI
-'P'    all     linux/soundcard.h
+'O'     00-06   mtd/ubi-user.h         UBI
+'P'    all     linux/soundcard.h       conflict!
+'P'    60-6F   sound/sscape_ioctl.h    conflict!
+'P'    00-0F   drivers/usb/class/usblp.c       conflict!
 'Q'    all     linux/soundcard.h
-'R'    00-1F   linux/random.h
+'R'    00-1F   linux/random.h          conflict!
+'R'    01      linux/rfkill.h          conflict!
+'R'    01-0F   media/rds.h             conflict!
+'R'    C0-DF   net/bluetooth/rfcomm.h
 'S'    all     linux/cdrom.h           conflict!
 'S'    80-81   scsi/scsi_ioctl.h       conflict!
 'S'    82-FF   scsi/scsi.h             conflict!
+'S'    00-7F   sound/asequencer.h      conflict!
 'T'    all     linux/soundcard.h       conflict!
+'T'    00-AF   sound/asound.h          conflict!
 'T'    all     arch/x86/include/asm/ioctls.h   conflict!
-'U'    00-EF   linux/drivers/usb/usb.h
-'V'    all     linux/vt.h
+'T'    C0-DF   linux/if_tun.h          conflict!
+'U'    all     sound/asound.h          conflict!
+'U'    00-0F   drivers/media/video/uvc/uvcvideo.h      conflict!
+'U'    00-CF   linux/uinput.h          conflict!
+'U'    00-EF   linux/usbdevice_fs.h
+'U'    C0-CF   drivers/bluetooth/hci_uart.h
+'V'    all     linux/vt.h              conflict!
+'V'    all     linux/videodev2.h       conflict!
+'V'    C0      linux/ivtvfb.h          conflict!
+'V'    C0      linux/ivtv.h            conflict!
+'V'    C0      media/davinci/vpfe_capture.h    conflict!
+'V'    C0      media/si4713.h          conflict!
+'V'    C0-CF   drivers/media/video/mxb.h       conflict!
 'W'    00-1F   linux/watchdog.h        conflict!
 'W'    00-1F   linux/wanrouter.h       conflict!
-'X'    all     linux/xfs_fs.h
+'W'    00-3F   sound/asound.h          conflict!
+'X'    all     fs/xfs/xfs_fs.h         conflict!
+               and fs/xfs/linux-2.6/xfs_ioctl32.h
+               and include/linux/falloc.h
+               and linux/fs.h
+'X'    all     fs/ocfs2/ocfs_fs.h      conflict!
+'X'    01      linux/pktcdvd.h         conflict!
 'Y'    all     linux/cyclades.h
-'['    00-07   linux/usb/usbtmc.h      USB Test and Measurement Devices
+'Z'    14-15   drivers/message/fusion/mptctl.h
+'['    00-07   linux/usb/tmc.h         USB Test and Measurement Devices
                                        <mailto:gregkh@suse.de>
-'a'    all                             ATM on linux
+'a'    all     linux/atm*.h, linux/sonet.h     ATM on linux
                                        <http://lrcwww.epfl.ch/linux-atm/magic.html>
-'b'    00-FF                           bit3 vme host bridge
+'b'    00-FF                           conflict! bit3 vme host bridge
                                        <mailto:natalia@nikhefk.nikhef.nl>
+'b'    00-0F   media/bt819.h           conflict!
+'c'    all     linux/cm4000_cs.h       conflict!
 'c'    00-7F   linux/comstats.h        conflict!
 'c'    00-7F   linux/coda.h            conflict!
-'c'    80-9F   arch/s390/include/asm/chsc.h
-'c'    A0-AF   arch/x86/include/asm/msr.h
+'c'    00-1F   linux/chio.h            conflict!
+'c'    80-9F   arch/s390/include/asm/chsc.h    conflict!
+'c'    A0-AF   arch/x86/include/asm/msr.h      conflict!
 'd'    00-FF   linux/char/drm/drm/h    conflict!
+'d'    02-40   pcmcia/ds.h             conflict!
+'d'    10-3F   drivers/media/video/dabusb.h    conflict!
+'d'    C0-CF   drivers/media/video/saa7191.h   conflict!
 'd'    F0-FF   linux/digi1.h
 'e'    all     linux/digi1.h           conflict!
-'e'    00-1F   net/irda/irtty.h        conflict!
-'f'    00-1F   linux/ext2_fs.h
-'h'    00-7F                           Charon filesystem
+'e'    00-1F   drivers/net/irda/irtty-sir.h    conflict!
+'f'    00-1F   linux/ext2_fs.h         conflict!
+'f'    00-1F   linux/ext3_fs.h         conflict!
+'f'    00-0F   fs/jfs/jfs_dinode.h     conflict!
+'f'    00-0F   fs/ext4/ext4.h          conflict!
+'f'    00-0F   linux/fs.h              conflict!
+'f'    00-0F   fs/ocfs2/ocfs2_fs.h     conflict!
+'g'    00-0F   linux/usb/gadgetfs.h
+'g'    20-2F   linux/usb/g_printer.h
+'h'    00-7F                           conflict! Charon filesystem
                                        <mailto:zapman@interlan.net>
-'i'    00-3F   linux/i2o.h
+'h'    00-1F   linux/hpet.h            conflict!
+'i'    00-3F   linux/i2o-dev.h         conflict!
+'i'    0B-1F   linux/ipmi.h            conflict!
+'i'    80-8F   linux/i8k.h
 'j'    00-3F   linux/joystick.h
+'k'    00-0F   linux/spi/spidev.h      conflict!
+'k'    00-05   video/kyro.h            conflict!
 'l'    00-3F   linux/tcfs_fs.h         transparent cryptographic file system
                                        <http://mikonos.dia.unisa.it/tcfs>
 'l'    40-7F   linux/udf_fs_i.h        in development:
                                        <http://sourceforge.net/projects/linux-udf/>
-'m'    00-09   linux/mmtimer.h
+'m'    00-09   linux/mmtimer.h         conflict!
 'm'    all     linux/mtio.h            conflict!
 'm'    all     linux/soundcard.h       conflict!
 'm'    all     linux/synclink.h        conflict!
+'m'    00-19   drivers/message/fusion/mptctl.h conflict!
+'m'    00      drivers/scsi/megaraid/megaraid_ioctl.h  conflict!
 'm'    00-1F   net/irda/irmod.h        conflict!
-'n'    00-7F   linux/ncp_fs.h
+'n'    00-7F   linux/ncp_fs.h and fs/ncpfs/ioctl.c
 'n'    80-8F   linux/nilfs2_fs.h       NILFS2
-'n'    E0-FF   video/matrox.h          matroxfb
+'n'    E0-FF   linux/matroxfb.h        matroxfb
 'o'    00-1F   fs/ocfs2/ocfs2_fs.h     OCFS2
-'o'     00-03   include/mtd/ubi-user.h  conflict! (OCFS2 and UBI overlaps)
-'o'     40-41   include/mtd/ubi-user.h  UBI
-'o'     01-A1   include/linux/dvb/*.h DVB
+'o'     00-03   mtd/ubi-user.h         conflict! (OCFS2 and UBI overlaps)
+'o'     40-41   mtd/ubi-user.h         UBI
+'o'     01-A1   linux/dvb/*.h          DVB
 'p'    00-0F   linux/phantom.h         conflict! (OpenHaptics needs this)
+'p'    00-1F   linux/rtc.h             conflict!
 'p'    00-3F   linux/mc146818rtc.h     conflict!
 'p'    40-7F   linux/nvram.h
-'p'    80-9F                           user-space parport
+'p'    80-9F   linux/ppdev.h           user-space parport
                                        <mailto:tim@cyberelk.net>
-'p'    a1-a4   linux/pps.h             LinuxPPS
+'p'    A1-A4   linux/pps.h             LinuxPPS
                                        <mailto:giometti@linux.it>
 'q'    00-1F   linux/serio.h
-'q'    80-FF                           Internet PhoneJACK, Internet LineJACK
-                                       <http://www.quicknet.net>
-'r'    00-1F   linux/msdos_fs.h
+'q'    80-FF   linux/telephony.h       Internet PhoneJACK, Internet LineJACK
+               linux/ixjuser.h         <http://www.quicknet.net>
+'r'    00-1F   linux/msdos_fs.h and fs/fat/dir.c
 's'    all     linux/cdk.h
 't'    00-7F   linux/if_ppp.h
 't'    80-8F   linux/isdn_ppp.h
+'t'    90      linux/toshiba.h
 'u'    00-1F   linux/smb_fs.h
-'v'    00-1F   linux/ext2_fs.h         conflict!
 'v'    all     linux/videodev.h        conflict!
+'v'    00-1F   linux/ext2_fs.h         conflict!
+'v'    00-1F   linux/fs.h              conflict!
+'v'    00-0F   linux/sonypi.h          conflict!
+'v'    C0-CF   drivers/media/video/ov511.h     conflict!
+'v'    C0-DF   media/pwc-ioctl.h       conflict!
+'v'    C0-FF   linux/meye.h            conflict!
+'v'    C0-CF   drivers/media/video/zoran/zoran.h       conflict!
+'v'    D0-DF   drivers/media/video/cpia2/cpia2dev.h    conflict!
 'w'    all                             CERN SCI driver
 'y'    00-1F                           packet based user level communications
                                        <mailto:zapman@interlan.net>
-'z'    00-3F                           CAN bus card
+'z'    00-3F                           CAN bus card    conflict!
                                        <mailto:hdstich@connectu.ulm.circular.de>
-'z'    40-7F                           CAN bus card
+'z'    40-7F                           CAN bus card    conflict!
                                        <mailto:oe@port.de>
+'z'    10-4F   drivers/s390/crypto/zcrypt_api.h        conflict!
 0x80   00-1F   linux/fb.h
 0x81   00-1F   linux/videotext.h
+0x88   00-3F   media/ovcamchip.h
 0x89   00-06   arch/x86/include/asm/sockios.h
 0x89   0B-DF   linux/sockios.h
 0x89   E0-EF   linux/sockios.h         SIOCPROTOPRIVATE range
+0x89   E0-EF   linux/dn.h              PROTOPRIVATE range
 0x89   F0-FF   linux/sockios.h         SIOCDEVPRIVATE range
 0x8B   all     linux/wireless.h
 0x8C   00-3F                           WiNRADiO driver
                                        <http://www.proximity.com.au/~brian/winradio/>
 0x90   00      drivers/cdrom/sbpcd.h
+0x92   00-0F   drivers/usb/mon/mon_bin.c
 0x93   60-7F   linux/auto_fs.h
+0x94   all     fs/btrfs/ioctl.h
 0x99   00-0F                           537-Addinboard driver
                                        <mailto:buk@buks.ipn.de>
 0xA0   all     linux/sdp/sdp.h         Industrial Device Project
@@ -192,17 +302,22 @@ Code      Seq#    Include File            Comments
 0xAB   00-1F   linux/nbd.h
 0xAC   00-1F   linux/raw.h
 0xAD   00      Netfilter device        in development:
-                                       <mailto:rusty@rustcorp.com.au>  
+                                       <mailto:rusty@rustcorp.com.au>
 0xAE   all     linux/kvm.h             Kernel-based Virtual Machine
                                        <mailto:kvm@vger.kernel.org>
 0xB0   all     RATIO devices           in development:
                                        <mailto:vgo@ratio.de>
 0xB1   00-1F   PPPoX                   <mailto:mostrows@styx.uwaterloo.ca>
+0xC0   00-0F   linux/usb/iowarrior.h
 0xCB   00-1F   CBM serial IEC bus      in development:
                                        <mailto:michael.klein@puffin.lb.shuttle.de>
+0xCD   01      linux/reiserfs_fs.h
+0xCF   02      fs/cifs/ioctl.c
+0xDB   00-0F   drivers/char/mwave/mwavepub.h
 0xDD   00-3F   ZFCP device driver      see drivers/s390/scsi/
                                        <mailto:aherrman@de.ibm.com>
-0xF3   00-3F   video/sisfb.h           sisfb (in development)
+0xF3   00-3F   drivers/usb/misc/sisusbvga/sisusb.h     sisfb (in development)
                                        <mailto:thomas@winischhofer.net>
 0xF4   00-1F   video/mbxfb.h           mbxfb
                                        <mailto:raph@8d.com>
+0xFD   all     linux/dm-ioctl.h
index 348b9e5e28fcd48c4249c10cdd8f0b1da4010df4..27a52b35d55bf1b6009551c97f400da5c14f59bc 100644 (file)
@@ -214,11 +214,13 @@ The format of the block comment is like this:
  * (section header: (section description)? )*
 (*)?*/
 
-The short function description ***cannot be multiline***, but the other
-descriptions can be (and they can contain blank lines).  If you continue
-that initial short description onto a second line, that second line will
-appear further down at the beginning of the description section, which is
-almost certainly not what you had in mind.
+All "description" text can span multiple lines, although the
+function_name & its short description are traditionally on a single line.
+Description text may also contain blank lines (i.e., lines that contain
+only a "*").
+
+"section header:" names must be unique per function (or struct,
+union, typedef, enum).
 
 Avoid putting a spurious blank line after the function name, or else the
 description will be repeated!
index 5ba4d9dff113f78bf8084a43d9fa4e380a67bf39..736d45602886ea7b08024f246f06e9c7c6dc1a05 100644 (file)
@@ -240,7 +240,7 @@ and is between 256 and 4096 characters. It is defined in the file
 
        acpi_sleep=     [HW,ACPI] Sleep options
                        Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
-                                 old_ordering, s4_nonvs }
+                                 old_ordering, s4_nonvs, sci_force_enable }
                        See Documentation/power/video.txt for information on
                        s3_bios and s3_mode.
                        s3_beep is for debugging; it makes the PC's speaker beep
@@ -253,6 +253,9 @@ and is between 256 and 4096 characters. It is defined in the file
                        of _PTS is used by default).
                        s4_nonvs prevents the kernel from saving/restoring the
                        ACPI NVS memory during hibernation.
+                       sci_force_enable causes the kernel to set SCI_EN directly
+                       on resume from S1/S3 (which is against the ACPI spec,
+                       but some broken systems don't work without it).
 
        acpi_use_timer_override [HW,ACPI]
                        Use timer override. For some broken Nvidia NF5 boards
index e1a114161027d6598234959e2605af08018f6fc6..2811e452f7566f5f5fe4fa6242f8724a9970ba11 100644 (file)
@@ -685,7 +685,7 @@ struct kvm_vcpu_events {
                __u8 pad;
        } nmi;
        __u32 sipi_vector;
-       __u32 flags;   /* must be zero */
+       __u32 flags;
 };
 
 4.30 KVM_SET_VCPU_EVENTS
@@ -701,6 +701,14 @@ vcpu.
 
 See KVM_GET_VCPU_EVENTS for the data structure.
 
+Fields that may be modified asynchronously by running VCPUs can be excluded
+from the update. These fields are nmi.pending and sipi_vector. Keep the
+corresponding bits in the flags field cleared to suppress overwriting the
+current in-kernel state. The bits are:
+
+KVM_VCPUEVENT_VALID_NMI_PENDING - transfer nmi.pending to the kernel
+KVM_VCPUEVENT_VALID_SIPI_VECTOR - transfer sipi_vector
+
 
 5. The kvm_run structure
 
index 169091f75e6d2122d1b7cb9d2bf99e5a055af00e..75afa1229fd7e72059ffce02b8c450192617e0c7 100644 (file)
@@ -1092,8 +1092,8 @@ WARNING:
     its level up and down at every change.
 
 
-Volume control
---------------
+Volume control (Console Audio control)
+--------------------------------------
 
 procfs: /proc/acpi/ibm/volume
 ALSA: "ThinkPad Console Audio Control", default ID: "ThinkPadEC"
@@ -1110,9 +1110,53 @@ the desktop environment to just provide on-screen-display feedback.
 Software volume control should be done only in the main AC97/HDA
 mixer.
 
-This feature allows volume control on ThinkPad models with a digital
-volume knob (when available, not all models have it), as well as
-mute/unmute control.  The available commands are:
+
+About the ThinkPad Console Audio control:
+
+ThinkPads have a built-in amplifier and muting circuit that drives the
+console headphone and speakers.  This circuit is after the main AC97
+or HDA mixer in the audio path, and under exclusive control of the
+firmware.
+
+ThinkPads have three special hotkeys to interact with the console
+audio control: volume up, volume down and mute.
+
+It is worth noting that the normal way the mute function works (on
+ThinkPads that do not have a "mute LED") is:
+
+1. Press mute to mute.  It will *always* mute, you can press it as
+   many times as you want, and the sound will remain mute.
+
+2. Press either volume key to unmute the ThinkPad (it will _not_
+   change the volume, it will just unmute).
+
+This is a very superior design when compared to the cheap software-only
+mute-toggle solution found on normal consumer laptops:  you can be
+absolutely sure the ThinkPad will not make noise if you press the mute
+button, no matter the previous state.
+
+The IBM ThinkPads, and the earlier Lenovo ThinkPads have variable-gain
+amplifiers driving the speakers and headphone output, and the firmware
+also handles volume control for the headphone and speakers on these
+ThinkPads without any help from the operating system (this volume
+control stage exists after the main AC97 or HDA mixer in the audio
+path).
+
+The newer Lenovo models only have firmware mute control, and depend on
+the main HDA mixer to do volume control (which is done by the operating
+system).  In this case, the volume keys are filtered out for unmute
+key press (there are some firmware bugs in this area) and delivered as
+normal key presses to the operating system (thinkpad-acpi is not
+involved).
+
+
+The ThinkPad-ACPI volume control:
+
+The preferred way to interact with the Console Audio control is the
+ALSA interface.
+
+The legacy procfs interface allows one to read the current state,
+and if volume control is enabled, accepts the following commands:
 
        echo up   >/proc/acpi/ibm/volume
        echo down >/proc/acpi/ibm/volume
@@ -1121,12 +1165,10 @@ mute/unmute control.  The available commands are:
        echo 'level <level>' >/proc/acpi/ibm/volume
 
 The <level> number range is 0 to 14 although not all of them may be
-distinct. The unmute the volume after the mute command, use either the
+distinct. To unmute the volume after the mute command, use either the
 up or down command (the level command will not unmute the volume), or
 the unmute command.
 
-The current volume level and mute state is shown in the file.
-
 You can use the volume_capabilities parameter to tell the driver
 whether your thinkpad has volume control or mute-only control:
 volume_capabilities=1 for mixers with mute and volume control,
index 719a819f8cc2c0e597e27b2b8bcd7caa17638ea2..07301de12cc4d7c6048f50f5e8cef7b99d8846df 100644 (file)
@@ -95,7 +95,7 @@ card*/pcm*/xrun_debug
        It takes an integer value, can be changed by writing to this
        file, such as
 
-                # cat 5 > /proc/asound/card0/pcm0p/xrun_debug
+                # echo 5 > /proc/asound/card0/pcm0p/xrun_debug
 
        The value consists of the following bit flags:
          bit 0 = Enable XRUN/jiffies debug messages
index 641a1ef2a7ffa1ba9dc688f6ae9873a728712994..239f14b2b55a28213e1a7170db4b870ab82ff1b9 100644 (file)
@@ -53,14 +53,14 @@ size of the mcount call that is embedded in the function).
 For example, if the function foo() calls bar(), when the bar() function calls
 mcount(), the arguments mcount() will pass to the tracer are:
        "frompc" - the address bar() will use to return to foo()
-       "selfpc" - the address bar() (with _mcount() size adjustment)
+       "selfpc" - the address bar() (with mcount() size adjustment)
 
 Also keep in mind that this mcount function will be called *a lot*, so
 optimizing for the default case of no tracer will help the smooth running of
 your system when tracing is disabled.  So the start of the mcount function is
-typically the bare min with checking things before returning.  That also means
-the code flow should usually kept linear (i.e. no branching in the nop case).
-This is of course an optimization and not a hard requirement.
+typically the bare minimum with checking things before returning.  That also
+means the code flow should usually be kept linear (i.e. no branching in the nop
+case).  This is of course an optimization and not a hard requirement.
 
 Here is some pseudo code that should help (these functions should actually be
 implemented in assembly):
@@ -131,10 +131,10 @@ some functions to save (hijack) and restore the return address.
 
 The mcount function should check the function pointers ftrace_graph_return
 (compare to ftrace_stub) and ftrace_graph_entry (compare to
-ftrace_graph_entry_stub).  If either of those are not set to the relevant stub
+ftrace_graph_entry_stub).  If either of those is not set to the relevant stub
 function, call the arch-specific function ftrace_graph_caller which in turn
 calls the arch-specific function prepare_ftrace_return.  Neither of these
-function names are strictly required, but you should use them anyways to stay
+function names is strictly required, but you should use them anyway to stay
 consistent across the architecture ports -- easier to compare & contrast
 things.
 
@@ -144,7 +144,7 @@ but the first argument should be a pointer to the "frompc".  Typically this is
 located on the stack.  This allows the function to hijack the return address
 temporarily to have it point to the arch-specific function return_to_handler.
 That function will simply call the common ftrace_return_to_handler function and
-that will return the original return address with which, you can return to the
+that will return the original return address with which you can return to the
 original call site.
 
 Here is the updated mcount pseudo code:
index 162effbfbdec09b947a914b27cc7197cc87f1ba9..664e7386d89e780b237077e9c490b0fe6c633a1a 100644 (file)
@@ -44,7 +44,8 @@ Check for lost events.
 Usage
 -----
 
-Make sure debugfs is mounted to /sys/kernel/debug. If not, (requires root privileges)
+Make sure debugfs is mounted to /sys/kernel/debug.
+If not (requires root privileges):
 $ mount -t debugfs debugfs /sys/kernel/debug
 
 Check that the driver you are about to trace is not loaded.
@@ -91,7 +92,7 @@ $ dmesg > dmesg.txt
 $ tar zcf pciid-nick-mmiotrace.tar.gz mydump.txt lspci.txt dmesg.txt
 and then send the .tar.gz file. The trace compresses considerably. Replace
 "pciid" and "nick" with the PCI ID or model name of your piece of hardware
-under investigation and your nick name.
+under investigation and your nickname.
 
 
 How Mmiotrace Works
@@ -100,7 +101,7 @@ How Mmiotrace Works
 Access to hardware IO-memory is gained by mapping addresses from PCI bus by
 calling one of the ioremap_*() functions. Mmiotrace is hooked into the
 __ioremap() function and gets called whenever a mapping is created. Mapping is
-an event that is recorded into the trace log. Note, that ISA range mappings
+an event that is recorded into the trace log. Note that ISA range mappings
 are not caught, since the mapping always exists and is returned directly.
 
 MMIO accesses are recorded via page faults. Just before __ioremap() returns,
@@ -122,11 +123,11 @@ Trace Log Format
 ----------------
 
 The raw log is text and easily filtered with e.g. grep and awk. One record is
-one line in the log. A record starts with a keyword, followed by keyword
-dependant arguments. Arguments are separated by a space, or continue until the
+one line in the log. A record starts with a keyword, followed by keyword-
+dependent arguments. Arguments are separated by a space, or continue until the
 end of line. The format for version 20070824 is as follows:
 
-Explanation    Keyword Space separated arguments
+Explanation    Keyword Space-separated arguments
 ---------------------------------------------------------------------------
 
 read event     R       width, timestamp, map id, physical, value, PC, PID
@@ -136,7 +137,7 @@ iounmap event       UNMAP   timestamp, map id, PC, PID
 marker         MARK    timestamp, text
 version                VERSION the string "20070824"
 info for reader        LSPCI   one line from lspci -v
-PCI address map        PCIDEV  space separated /proc/bus/pci/devices data
+PCI address map        PCIDEV  space-separated /proc/bus/pci/devices data
 unk. opcode    UNKNOWN timestamp, map id, physical, data, PC, PID
 
 Timestamp is in seconds with decimals. Physical is a PCI bus address, virtual
index 5b1d23d604c592a9e5a31bc8552f0f046b1110f7..d299ff31df57f0b4f1ea25cf328e77390eee50ee 100644 (file)
@@ -33,9 +33,9 @@ head_page - a pointer to the page that the reader will use next
 
 tail_page - a pointer to the page that will be written to next
 
-commit_page - a pointer to the page with the last finished non nested write.
+commit_page - a pointer to the page with the last finished non-nested write.
 
-cmpxchg - hardware assisted atomic transaction that performs the following:
+cmpxchg - hardware-assisted atomic transaction that performs the following:
 
    A = B iff previous A == C
 
@@ -52,15 +52,15 @@ The Generic Ring Buffer
 The ring buffer can be used in either an overwrite mode or in
 producer/consumer mode.
 
-Producer/consumer mode is where the producer were to fill up the
+Producer/consumer mode is where if the producer were to fill up the
 buffer before the consumer could free up anything, the producer
 will stop writing to the buffer. This will lose most recent events.
 
-Overwrite mode is where the produce were to fill up the buffer
+Overwrite mode is where if the producer were to fill up the buffer
 before the consumer could free up anything, the producer will
 overwrite the older data. This will lose the oldest events.
 
-No two writers can write at the same time (on the same per cpu buffer),
+No two writers can write at the same time (on the same per-cpu buffer),
 but a writer may interrupt another writer, but it must finish writing
 before the previous writer may continue. This is very important to the
 algorithm. The writers act like a "stack". The way interrupts works
@@ -79,16 +79,16 @@ the interrupt doing a write as well.
 
 Readers can happen at any time. But no two readers may run at the
 same time, nor can a reader preempt/interrupt another reader. A reader
-can not preempt/interrupt a writer, but it may read/consume from the
+cannot preempt/interrupt a writer, but it may read/consume from the
 buffer at the same time as a writer is writing, but the reader must be
 on another processor to do so. A reader may read on its own processor
 and can be preempted by a writer.
 
-A writer can preempt a reader, but a reader can not preempt a writer.
+A writer can preempt a reader, but a reader cannot preempt a writer.
 But a reader can read the buffer at the same time (on another processor)
 as a writer.
 
-The ring buffer is made up of a list of pages held together by a link list.
+The ring buffer is made up of a list of pages held together by a linked list.
 
 At initialization a reader page is allocated for the reader that is not
 part of the ring buffer.
@@ -102,7 +102,7 @@ the head page.
 
 The reader has its own page to use. At start up time, this page is
 allocated but is not attached to the list. When the reader wants
-to read from the buffer, if its page is empty (like it is on start up)
+to read from the buffer, if its page is empty (like it is on start-up),
 it will swap its page with the head_page. The old reader page will
 become part of the ring buffer and the head_page will be removed.
 The page after the inserted page (old reader_page) will become the
@@ -206,7 +206,7 @@ The main pointers:
 
   commit page - the page that last finished a write.
 
-The commit page only is updated by the outer most writer in the
+The commit page only is updated by the outermost writer in the
 writer stack. A writer that preempts another writer will not move the
 commit page.
 
@@ -281,7 +281,7 @@ with the previous write.
 The commit pointer points to the last write location that was
 committed without preempting another write. When a write that
 preempted another write is committed, it only becomes a pending commit
-and will not be a full commit till all writes have been committed.
+and will not be a full commit until all writes have been committed.
 
 The commit page points to the page that has the last full commit.
 The tail page points to the page with the last write (before
@@ -292,7 +292,7 @@ be several pages ahead. If the tail page catches up to the commit
 page then no more writes may take place (regardless of the mode
 of the ring buffer: overwrite and produce/consumer).
 
-The order of pages are:
+The order of pages is:
 
  head page
  commit page
@@ -311,7 +311,7 @@ Possible scenario:
 There is a special case that the head page is after either the commit page
 and possibly the tail page. That is when the commit (and tail) page has been
 swapped with the reader page. This is because the head page is always
-part of the ring buffer, but the reader page is not. When ever there
+part of the ring buffer, but the reader page is not. Whenever there
 has been less than a full page that has been committed inside the ring buffer,
 and a reader swaps out a page, it will be swapping out the commit page.
 
@@ -338,7 +338,7 @@ and a reader swaps out a page, it will be swapping out the commit page.
 In this case, the head page will not move when the tail and commit
 move back into the ring buffer.
 
-The reader can not swap a page into the ring buffer if the commit page
+The reader cannot swap a page into the ring buffer if the commit page
 is still on that page. If the read meets the last commit (real commit
 not pending or reserved), then there is nothing more to read.
 The buffer is considered empty until another full commit finishes.
@@ -395,7 +395,7 @@ The main idea behind the lockless algorithm is to combine the moving
 of the head_page pointer with the swapping of pages with the reader.
 State flags are placed inside the pointer to the page. To do this,
 each page must be aligned in memory by 4 bytes. This will allow the 2
-least significant bits of the address to be used as flags. Since
+least significant bits of the address to be used as flags, since
 they will always be zero for the address. To get the address,
 simply mask out the flags.
 
@@ -460,7 +460,7 @@ When the reader tries to swap the page with the ring buffer, it
 will also use cmpxchg. If the flag bit in the pointer to the
 head page does not have the HEADER flag set, the compare will fail
 and the reader will need to look for the new head page and try again.
-Note, the flag UPDATE and HEADER are never set at the same time.
+Note, the flags UPDATE and HEADER are never set at the same time.
 
 The reader swaps the reader page as follows:
 
@@ -539,7 +539,7 @@ updated to the reader page.
     |  +-----------------------------+   |
     +------------------------------------+
 
-Another important point. The page that the reader page points back to
+Another important point: The page that the reader page points back to
 by its previous pointer (the one that now points to the new head page)
 never points back to the reader page. That is because the reader page is
 not part of the ring buffer. Traversing the ring buffer via the next pointers
@@ -572,7 +572,7 @@ not be able to swap the head page from the buffer, nor will it be able to
 move the head page, until the writer is finished with the move.
 
 This eliminates any races that the reader can have on the writer. The reader
-must spin, and this is why the reader can not preempt the writer.
+must spin, and this is why the reader cannot preempt the writer.
 
             tail page
                |
@@ -659,9 +659,9 @@ before pushing the head page. If it is, then it can be assumed that the
 tail page wrapped the buffer, and we must drop new writes.
 
 This is not a race condition, because the commit page can only be moved
-by the outter most writer (the writer that was preempted).
+by the outermost writer (the writer that was preempted).
 This means that the commit will not move while a writer is moving the
-tail page. The reader can not swap the reader page if it is also being
+tail page. The reader cannot swap the reader page if it is also being
 used as the commit page. The reader can simply check that the commit
 is off the reader page. Once the commit page leaves the reader page
 it will never go back on it unless a reader does another swap with the
@@ -733,7 +733,7 @@ The write converts the head page pointer to UPDATE.
 --->|   |<---|   |<---|   |<---|   |<---
     +---+    +---+    +---+    +---+
 
-But if a nested writer preempts here. It will see that the next
+But if a nested writer preempts here, it will see that the next
 page is a head page, but it is also nested. It will detect that
 it is nested and will save that information. The detection is the
 fact that it sees the UPDATE flag instead of a HEADER or NORMAL
@@ -761,7 +761,7 @@ to NORMAL.
 --->|   |<---|   |<---|   |<---|   |<---
     +---+    +---+    +---+    +---+
 
-After the nested writer finishes, the outer most writer will convert
+After the nested writer finishes, the outermost writer will convert
 the UPDATE pointer to NORMAL.
 
 
@@ -812,7 +812,7 @@ head page.
     +---+    +---+    +---+    +---+
 
 The nested writer moves the tail page forward. But does not set the old
-update page to NORMAL because it is not the outer most writer.
+update page to NORMAL because it is not the outermost writer.
 
                     tail page
                         |
@@ -892,7 +892,7 @@ It will return to the first writer.
 --->|   |<---|   |<---|   |<---|   |<---
     +---+    +---+    +---+    +---+
 
-The first writer can not know atomically test if the tail page moved
+The first writer cannot know atomically if the tail page moved
 while it updates the HEAD page. It will then update the head page to
 what it thinks is the new head page.
 
@@ -923,9 +923,9 @@ if the tail page is either where it use to be or on the next page:
 --->|   |<---|   |<---|   |<---|   |<---
     +---+    +---+    +---+    +---+
 
-If tail page != A and tail page does not equal B, then it must reset the
-pointer back to NORMAL. The fact that it only needs to worry about
-nested writers, it only needs to check this after setting the HEAD page.
+If tail page != A and tail page != B, then it must reset the pointer
+back to NORMAL. The fact that it only needs to worry about nested
+writers means that it only needs to check this after setting the HEAD page.
 
 
 (first writer)
@@ -939,7 +939,7 @@ nested writers, it only needs to check this after setting the HEAD page.
     +---+    +---+    +---+    +---+
 
 Now the writer can update the head page. This is also why the head page must
-remain in UPDATE and only reset by the outer most writer. This prevents
+remain in UPDATE and only reset by the outermost writer. This prevents
 the reader from seeing the incorrect head page.
 
 
index 5eb4e487e667d1396bcede6af11e0bd5c60f0711..87bee3c129ba71f8c359b5e849bafd177f421136 100644 (file)
@@ -10,8 +10,8 @@ Tracepoints (see Documentation/trace/tracepoints.txt) can be used without
 creating custom kernel modules to register probe functions using the event
 tracing infrastructure.
 
-Simplistically, tracepoints will represent an important event that when can
-be taken in conjunction with other tracepoints to build a "Big Picture" of
+Simplistically, tracepoints represent important events that can be
+taken in conjunction with other tracepoints to build a "Big Picture" of
 what is going on within the system. There are a large number of methods for
 gathering and interpreting these events. Lacking any current Best Practises,
 this document describes some of the methods that can be used.
@@ -33,12 +33,12 @@ calling
 
 will give a fair indication of the number of events available.
 
-2.2 PCL
+2.2 PCL (Performance Counters for Linux)
 -------
 
-Discovery and enumeration of all counters and events, including tracepoints
+Discovery and enumeration of all counters and events, including tracepoints,
 are available with the perf tool. Getting a list of available events is a
-simple case of
+simple case of:
 
   $ perf list 2>&1 | grep Tracepoint
   ext4:ext4_free_inode                     [Tracepoint event]
@@ -49,19 +49,19 @@ simple case of
   [ .... remaining output snipped .... ]
 
 
-2. Enabling Events
+3. Enabling Events
 ==================
 
-2.1 System-Wide Event Enabling
+3.1 System-Wide Event Enabling
 ------------------------------
 
 See Documentation/trace/events.txt for a proper description on how events
 can be enabled system-wide. A short example of enabling all events related
-to page allocation would look something like
+to page allocation would look something like:
 
   $ for i in `find /sys/kernel/debug/tracing/events -name "enable" | grep mm_`; do echo 1 > $i; done
 
-2.2 System-Wide Event Enabling with SystemTap
+3.2 System-Wide Event Enabling with SystemTap
 ---------------------------------------------
 
 In SystemTap, tracepoints are accessible using the kernel.trace() function
@@ -86,7 +86,7 @@ were allocating the pages.
           print_count()
   }
 
-2.3 System-Wide Event Enabling with PCL
+3.3 System-Wide Event Enabling with PCL
 ---------------------------------------
 
 By specifying the -a switch and analysing sleep, the system-wide events
@@ -107,16 +107,16 @@ for a duration of time can be examined.
 Similarly, one could execute a shell and exit it as desired to get a report
 at that point.
 
-2.4 Local Event Enabling
+3.4 Local Event Enabling
 ------------------------
 
 Documentation/trace/ftrace.txt describes how to enable events on a per-thread
 basis using set_ftrace_pid.
 
-2.5 Local Event Enablement with PCL
+3.5 Local Event Enablement with PCL
 -----------------------------------
 
-Events can be activate and tracked for the duration of a process on a local
+Events can be activated and tracked for the duration of a process on a local
 basis using PCL such as follows.
 
   $ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
@@ -131,18 +131,18 @@ basis using PCL such as follows.
 
     0.973913387  seconds time elapsed
 
-3. Event Filtering
+4. Event Filtering
 ==================
 
 Documentation/trace/ftrace.txt covers in-depth how to filter events in
 ftrace.  Obviously using grep and awk of trace_pipe is an option as well
 as any script reading trace_pipe.
 
-4. Analysing Event Variances with PCL
+5. Analysing Event Variances with PCL
 =====================================
 
 Any workload can exhibit variances between runs and it can be important
-to know what the standard deviation in. By and large, this is left to the
+to know what the standard deviation is. By and large, this is left to the
 performance analyst to do it by hand. In the event that the discrete event
 occurrences are useful to the performance analyst, then perf can be used.
 
@@ -166,7 +166,7 @@ In the event that some higher-level event is required that depends on some
 aggregation of discrete events, then a script would need to be developed.
 
 Using --repeat, it is also possible to view how events are fluctuating over
-time on a system wide basis using -a and sleep.
+time on a system-wide basis using -a and sleep.
 
   $ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
                -e kmem:mm_pagevec_free \
@@ -180,7 +180,7 @@ time on a system wide basis using -a and sleep.
 
     1.002251757  seconds time elapsed   ( +-   0.005% )
 
-5. Higher-Level Analysis with Helper Scripts
+6. Higher-Level Analysis with Helper Scripts
 ============================================
 
 When events are enabled the events that are triggering can be read from
@@ -190,11 +190,11 @@ be gathered on-line as appropriate. Examples of post-processing might include
 
   o Reading information from /proc for the PID that triggered the event
   o Deriving a higher-level event from a series of lower-level events.
-  o Calculate latencies between two events
+  o Calculating latencies between two events
 
 Documentation/trace/postprocess/trace-pagealloc-postprocess.pl is an example
 script that can read trace_pipe from STDIN or a copy of a trace. When used
-on-line, it can be interrupted once to generate a report without existing
+on-line, it can be interrupted once to generate a report without exiting
 and twice to exit.
 
 Simplistically, the script just reads STDIN and counts up events but it
@@ -212,12 +212,12 @@ also can do more such as
     processes, the parent process responsible for creating all the helpers
     can be identified
 
-6. Lower-Level Analysis with PCL
+7. Lower-Level Analysis with PCL
 ================================
 
-There may also be a requirement to identify what functions with a program
+There may also be a requirement to identify what functions within a program
 were generating events within the kernel. To begin this sort of analysis, the
-data must be recorded. At the time of writing, this required root
+data must be recorded. At the time of writing, this required root:
 
   $ perf record -c 1 \
        -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
@@ -253,11 +253,11 @@ perf report.
   # (For more details, try: perf report --sort comm,dso,symbol)
   #
 
-According to this, the vast majority of events occured triggered on events
-within the VDSO. With simple binaries, this will often be the case so lets
+According to this, the vast majority of events triggered on events
+within the VDSO. With simple binaries, this will often be the case so let's
 take a slightly different example. In the course of writing this, it was
-noticed that X was generating an insane amount of page allocations so lets look
-at it
+noticed that X was generating an insane amount of page allocations so let's look
+at it:
 
   $ perf record -c 1 -f \
                -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
@@ -280,8 +280,8 @@ This was interrupted after a few seconds and
   # (For more details, try: perf report --sort comm,dso,symbol)
   #
 
-So, almost half of the events are occuring in a library. To get an idea which
-symbol.
+So, almost half of the events are occurring in a library. To get an idea which
+symbol:
 
   $ perf report --sort comm,dso,symbol
   # Samples: 27666
@@ -297,7 +297,7 @@ symbol.
        0.01%     Xorg  /opt/gfx-test/lib/libpixman-1.so.0.13.1  [.] get_fast_path
        0.00%     Xorg  [kernel]                                 [k] ftrace_trace_userstack
 
-To see where within the function pixmanFillsse2 things are going wrong
+To see where within the function pixmanFillsse2 things are going wrong:
 
   $ perf annotate pixmanFillsse2
   [ ... ]
index 987f9b0a5ecea5b2d5768571fb91b59249860d2c..43a9b0694fddbc5b65b8c4286ab6feb8f9c4cc26 100644 (file)
@@ -103,7 +103,7 @@ I.2 libpciaccess
 ----------------
 
 To use the vga arbiter char device it was implemented an API inside the
-libpciaccess library. One fieldd was added to struct pci_device (each device
+libpciaccess library. One field was added to struct pci_device (each device
 on the system):
 
     /* the type of resource decoded by the device */
index 66f5f7dab285660aa1aa970c8e8f09de85a2ff37..6914588eef89575ba94ab97d1116f170e4b88bf9 100644 (file)
@@ -2169,10 +2169,9 @@ F:       drivers/hwmon/f75375s.c
 F:     include/linux/f75375s.h
 
 FIREWIRE SUBSYSTEM
-M:     Kristian Hoegsberg <krh@redhat.com>
 M:     Stefan Richter <stefanr@s5r6.in-berlin.de>
 L:     linux1394-devel@lists.sourceforge.net
-W:     http://www.linux1394.org/
+W:     http://ieee1394.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
 S:     Maintained
 F:     drivers/firewire/
@@ -2705,22 +2704,14 @@ S:      Supported
 F:     drivers/idle/i7300_idle.c
 
 IEEE 1394 SUBSYSTEM
-M:     Ben Collins <ben.collins@ubuntu.com>
 M:     Stefan Richter <stefanr@s5r6.in-berlin.de>
 L:     linux1394-devel@lists.sourceforge.net
-W:     http://www.linux1394.org/
+W:     http://ieee1394.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
-S:     Maintained
+S:     Obsolete
 F:     Documentation/debugging-via-ohci1394.txt
 F:     drivers/ieee1394/
 
-IEEE 1394 RAW I/O DRIVER
-M:     Dan Dennedy <dan@dennedy.org>
-M:     Stefan Richter <stefanr@s5r6.in-berlin.de>
-L:     linux1394-devel@lists.sourceforge.net
-S:     Maintained
-F:     drivers/ieee1394/raw1394*
-
 IEEE 802.15.4 SUBSYSTEM
 M:     Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 M:     Sergey Lapin <slapin@ossfans.org>
@@ -3882,7 +3873,7 @@ F:        drivers/net/ni5010.*
 
 NILFS2 FILESYSTEM
 M:     KONISHI Ryusuke <konishi.ryusuke@lab.ntt.co.jp>
-L:     users@nilfs.org
+L:     linux-nilfs@vger.kernel.org
 W:     http://www.nilfs.org/en/
 S:     Supported
 F:     Documentation/filesystems/nilfs2.txt
index c628a5cfe422d3109c7a0dfca812c03b58639e8c..12310947156e862784783c3cbbbc4cc33baa9d90 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 33
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Man-Eating Seals of Antiquity
 
 # *DOCUMENTATION*
index 233a222752c0c507a3879109b3c81d0793d3bf76..c2238cd474c784e52872627586632f65608281a1 100644 (file)
@@ -18,6 +18,8 @@ config ARM
        select HAVE_KRETPROBES if (HAVE_KPROBES)
        select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
        select HAVE_GENERIC_DMA_COHERENT
+       select HAVE_KERNEL_GZIP
+       select HAVE_KERNEL_LZO
        help
          The ARM series is a line of low-power-consumption RISC chip designs
          licensed by ARM Ltd and targeted at embedded applications and
@@ -688,6 +690,7 @@ config ARCH_DAVINCI
        select HAVE_IDE
        select COMMON_CLKDEV
        select GENERIC_ALLOCATOR
+       select ARCH_HAS_HOLES_MEMORYMODEL
        help
          Support for TI's DaVinci platform.
 
index ce39dc5400858891dc17be16de158fb6db041627..2d4d88ba73bf9533598b074b08cce94ee85ae26c 100644 (file)
@@ -63,8 +63,12 @@ endif
 
 SEDFLAGS       = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
 
-targets       := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
-                head.o misc.o $(OBJS)
+suffix_$(CONFIG_KERNEL_GZIP) = gzip
+suffix_$(CONFIG_KERNEL_LZO)  = lzo
+
+targets       := vmlinux vmlinux.lds \
+                piggy.$(suffix_y) piggy.$(suffix_y).o \
+                font.o font.c head.o misc.o $(OBJS)
 
 ifeq ($(CONFIG_FUNCTION_TRACER),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
@@ -87,22 +91,34 @@ endif
 ifneq ($(PARAMS_PHYS),)
 LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS)
 endif
-LDFLAGS_vmlinux += -p --no-undefined -X \
-       $(shell $(CC) $(KBUILD_CFLAGS) --print-libgcc-file-name) -T
+# ?
+LDFLAGS_vmlinux += -p
+# Report unresolved symbol references
+LDFLAGS_vmlinux += --no-undefined
+# Delete all temporary local symbols
+LDFLAGS_vmlinux += -X
+# Next argument is a linker script
+LDFLAGS_vmlinux += -T
+
+# For __aeabi_uidivmod
+lib1funcs = $(obj)/lib1funcs.o
+
+$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
+       $(call cmd,shipped)
 
 # Don't allow any static data in misc.o, which
 # would otherwise mess up our GOT table
 CFLAGS_misc.o := -Dstatic=
 
-$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \
-               $(addprefix $(obj)/, $(OBJS)) FORCE
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
+               $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
        $(call if_changed,ld)
        @:
 
-$(obj)/piggy.gz: $(obj)/../Image FORCE
-       $(call if_changed,gzip)
+$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE
+       $(call if_changed,$(suffix_y))
 
-$(obj)/piggy.o:  $(obj)/piggy.gz FORCE
+$(obj)/piggy.$(suffix_y).o:  $(obj)/piggy.$(suffix_y) FORCE
 
 CFLAGS_font.o := -Dstatic=
 
index 17153b54613b4c5948db2f66b1cbf7a0716b2309..7e0fe4d42c7b4f8965c08661206736b6eea8c659 100644 (file)
 
 unsigned int __machine_arch_type;
 
+#define _LINUX_STRING_H_
+
 #include <linux/compiler.h>    /* for inline */
 #include <linux/types.h>       /* for size_t */
 #include <linux/stddef.h>      /* for NULL */
 #include <asm/string.h>
+#include <linux/linkage.h>
+
+#include <asm/unaligned.h>
 
 #ifdef STANDALONE_DEBUG
 #define putstr printf
@@ -188,34 +193,8 @@ static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
 /*
  * gzip delarations
  */
-#define OF(args)  args
 #define STATIC static
 
-typedef unsigned char  uch;
-typedef unsigned short ush;
-typedef unsigned long  ulg;
-
-#define WSIZE 0x8000           /* Window size must be at least 32k, */
-                               /* and a power of two */
-
-static uch *inbuf;             /* input buffer */
-static uch window[WSIZE];      /* Sliding window buffer */
-
-static unsigned insize;                /* valid bytes in inbuf */
-static unsigned inptr;         /* index of next byte to be processed in inbuf */
-static unsigned outcnt;                /* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
-#define COMMENT      0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
-#define RESERVED     0xC0 /* bit 6,7:   reserved */
-
-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
 /* Diagnostic functions */
 #ifdef DEBUG
 #  define Assert(cond,msg) {if(!(cond)) error(msg);}
@@ -233,24 +212,20 @@ static unsigned outcnt;           /* bytes in output buffer */
 #  define Tracecv(c,x)
 #endif
 
-static int  fill_inbuf(void);
-static void flush_window(void);
 static void error(char *m);
 
 extern char input_data[];
 extern char input_data_end[];
 
-static uch *output_data;
-static ulg output_ptr;
-static ulg bytes_out;
+static unsigned char *output_data;
+static unsigned long output_ptr;
 
 static void error(char *m);
 
 static void putstr(const char *);
 
-extern int end;
-static ulg free_mem_ptr;
-static ulg free_mem_end_ptr;
+static unsigned long free_mem_ptr;
+static unsigned long free_mem_end_ptr;
 
 #ifdef STANDALONE_DEBUG
 #define NO_INFLATE_MALLOC
@@ -258,46 +233,13 @@ static ulg free_mem_end_ptr;
 
 #define ARCH_HAS_DECOMP_WDOG
 
-#include "../../../../lib/inflate.c"
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-int fill_inbuf(void)
-{
-       if (insize != 0)
-               error("ran out of input data");
-
-       inbuf = input_data;
-       insize = &input_data_end[0] - &input_data[0];
-
-       inptr = 1;
-       return inbuf[0];
-}
+#ifdef CONFIG_KERNEL_GZIP
+#include "../../../../lib/decompress_inflate.c"
+#endif
 
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-void flush_window(void)
-{
-       ulg c = crc;
-       unsigned n;
-       uch *in, *out, ch;
-
-       in = window;
-       out = &output_data[output_ptr];
-       for (n = 0; n < outcnt; n++) {
-               ch = *out++ = *in++;
-               c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
-       }
-       crc = c;
-       bytes_out += (ulg)outcnt;
-       output_ptr += (ulg)outcnt;
-       outcnt = 0;
-       putstr(".");
-}
+#ifdef CONFIG_KERNEL_LZO
+#include "../../../../lib/decompress_unlzo.c"
+#endif
 
 #ifndef arch_error
 #define arch_error(x)
@@ -314,22 +256,33 @@ static void error(char *x)
        while(1);       /* Halt */
 }
 
+asmlinkage void __div0(void)
+{
+       error("Attempting division by 0!");
+}
+
 #ifndef STANDALONE_DEBUG
 
-ulg
-decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
-                 int arch_id)
+unsigned long
+decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
+               unsigned long free_mem_ptr_end_p,
+               int arch_id)
 {
-       output_data             = (uch *)output_start;  /* Points to kernel start */
+       unsigned char *tmp;
+
+       output_data             = (unsigned char *)output_start;
        free_mem_ptr            = free_mem_ptr_p;
        free_mem_end_ptr        = free_mem_ptr_end_p;
        __machine_arch_type     = arch_id;
 
        arch_decomp_setup();
 
-       makecrc();
+       tmp = (unsigned char *) (((unsigned long)input_data_end) - 4);
+       output_ptr = get_unaligned_le32(tmp);
+
        putstr("Uncompressing Linux...");
-       gunzip();
+       decompress(input_data, input_data_end - input_data,
+                       NULL, NULL, output_data, NULL, error);
        putstr(" done, booting the kernel.\n");
        return output_ptr;
 }
@@ -341,11 +294,10 @@ int main()
 {
        output_data = output_buffer;
 
-       makecrc();
        putstr("Uncompressing Linux...");
-       gunzip();
+       decompress(input_data, input_data_end - input_data,
+                       NULL, NULL, output_data, NULL, error);
        putstr("done.\n");
        return 0;
 }
 #endif
-       
diff --git a/arch/arm/boot/compressed/piggy.S b/arch/arm/boot/compressed/piggy.S
deleted file mode 100644 (file)
index 54c9518..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-       .section .piggydata,#alloc
-       .globl  input_data
-input_data:
-       .incbin "arch/arm/boot/compressed/piggy.gz"
-       .globl  input_data_end
-input_data_end:
diff --git a/arch/arm/boot/compressed/piggy.gzip.S b/arch/arm/boot/compressed/piggy.gzip.S
new file mode 100644 (file)
index 0000000..a68adf9
--- /dev/null
@@ -0,0 +1,6 @@
+       .section .piggydata,#alloc
+       .globl  input_data
+input_data:
+       .incbin "arch/arm/boot/compressed/piggy.gzip"
+       .globl  input_data_end
+input_data_end:
diff --git a/arch/arm/boot/compressed/piggy.lzo.S b/arch/arm/boot/compressed/piggy.lzo.S
new file mode 100644 (file)
index 0000000..a425ad9
--- /dev/null
@@ -0,0 +1,6 @@
+       .section .piggydata,#alloc
+       .globl  input_data
+input_data:
+       .incbin "arch/arm/boot/compressed/piggy.lzo"
+       .globl  input_data_end
+input_data_end:
index a9b650dcc1729246d41d54d9b2383ec130f80084..077ecf4fecda9fb21dc98e002f4f236a8488fed9 100644 (file)
@@ -236,6 +236,7 @@ static struct vpfe_subdev_info vpfe_sub_devs[] = {
 
 static struct vpfe_config vpfe_cfg = {
        .num_subdevs = ARRAY_SIZE(vpfe_sub_devs),
+       .i2c_adapter_id = 1,
        .sub_devs = vpfe_sub_devs,
        .card_name = "DM355 EVM",
        .ccdc = "DM355 CCDC",
index 289fe1b7d25a564624c19638a923a3fabf316e2d..b476395d2cd4369581e4307eb0df6dccba65f71d 100644 (file)
@@ -192,7 +192,11 @@ static struct davinci_i2c_platform_data i2c_pdata = {
        .bus_delay      = 0     /* usec */,
 };
 
-#ifdef CONFIG_KEYBOARD_DAVINCI
+static int dm365evm_keyscan_enable(struct device *dev)
+{
+       return davinci_cfg_reg(DM365_KEYSCAN);
+}
+
 static unsigned short dm365evm_keymap[] = {
        KEY_KP2,
        KEY_LEFT,
@@ -214,6 +218,7 @@ static unsigned short dm365evm_keymap[] = {
 };
 
 static struct davinci_ks_platform_data dm365evm_ks_data = {
+       .device_enable  = dm365evm_keyscan_enable,
        .keymap         = dm365evm_keymap,
        .keymapsize     = ARRAY_SIZE(dm365evm_keymap),
        .rep            = 1,
@@ -222,7 +227,6 @@ static struct davinci_ks_platform_data dm365evm_ks_data = {
        .interval       = 0x2,
        .matrix_type    = DAVINCI_KEYSCAN_MATRIX_4X4,
 };
-#endif
 
 static int cpld_mmc_get_cd(int module)
 {
@@ -511,10 +515,7 @@ static __init void dm365_evm_init(void)
 
        dm365_init_asp(&dm365_evm_snd_data);
        dm365_init_rtc();
-
-#ifdef CONFIG_KEYBOARD_DAVINCI
        dm365_init_ks(&dm365evm_ks_data);
-#endif
 }
 
 static __init void dm365_evm_irq_init(void)
index fd0398bc6db35075d2c5d5436cc2e73797b72068..e9612cf727b7cc9c6bb19a570ed0bc0b6d92ad52 100644 (file)
@@ -247,6 +247,7 @@ static struct vpfe_subdev_info vpfe_sub_devs[] = {
 
 static struct vpfe_config vpfe_cfg = {
        .num_subdevs = ARRAY_SIZE(vpfe_sub_devs),
+       .i2c_adapter_id = 1,
        .sub_devs = vpfe_sub_devs,
        .card_name = "DM6446 EVM",
        .ccdc = "DM6446 CCDC",
index 52b287cf3a42723a69040f53c20c4f79d29387d6..37311d1830eb4cd0752539431c3051e7ef44bbdf 100644 (file)
@@ -81,12 +81,23 @@ static int cp_intc_set_irq_type(unsigned int irq, unsigned int flow_type)
        return 0;
 }
 
+/*
+ * Faking this allows us to to work with suspend functions of
+ * generic drivers which call {enable|disable}_irq_wake for
+ * wake up interrupt sources (eg RTC on DA850).
+ */
+static int cp_intc_set_wake(unsigned int irq, unsigned int on)
+{
+       return 0;
+}
+
 static struct irq_chip cp_intc_irq_chip = {
        .name           = "cp_intc",
        .ack            = cp_intc_ack_irq,
        .mask           = cp_intc_mask_irq,
        .unmask         = cp_intc_unmask_irq,
        .set_type       = cp_intc_set_irq_type,
+       .set_wake       = cp_intc_set_wake,
 };
 
 void __init cp_intc_init(void __iomem *base, unsigned short num_irq,
index dd2d32c4ce8679fdf5995b8210b294d87b96f10a..a5105f03fd866055de3205a36ae18d8b30cf733c 100644 (file)
@@ -481,11 +481,18 @@ static struct platform_device da8xx_rtc_device = {
 
 int da8xx_register_rtc(void)
 {
+       int ret;
+
        /* Unlock the rtc's registers */
        __raw_writel(0x83e70b13, IO_ADDRESS(DA8XX_RTC_BASE + 0x6c));
        __raw_writel(0x95a4f1e0, IO_ADDRESS(DA8XX_RTC_BASE + 0x70));
 
-       return platform_device_register(&da8xx_rtc_device);
+       ret = platform_device_register(&da8xx_rtc_device);
+       if (!ret)
+               /* Atleast on DA850, RTC is a wakeup source */
+               device_init_wakeup(&da8xx_rtc_device.dev, true);
+
+       return ret;
 }
 
 static struct resource da8xx_cpuidle_resources[] = {
index 2ec619ec1657b1001ec97e46c4e41a156c9bd8ec..f53735cb922ebf756f17f29692ce56bf752430f6 100644 (file)
@@ -993,7 +993,6 @@ void __init dm365_init_asp(struct snd_platform_data *pdata)
 
 void __init dm365_init_ks(struct davinci_ks_platform_data *pdata)
 {
-       davinci_cfg_reg(DM365_KEYSCAN);
        dm365_ks_device.dev.platform_data = pdata;
        platform_device_register(&dm365_ks_device);
 }
index 8f49b2b12608934d96d6b2d894c79e80cf01120e..b22dec4abf78e3597c78b7e44c5922baf07d51e0 100644 (file)
@@ -24,8 +24,6 @@
 
 #include "common.h"
 
-#define ARRAY_AND_SIZE(x)       (x), ARRAY_SIZE(x)
-
 static unsigned long ttc_dkb_pin_config[] __initdata = {
        /* UART2 */
        GPIO47_UART2_RXD,
index 03dbbdc9895587ed3716c4e133c15c5f63885f46..8bcc1a5b88296d7460ee43b9af04ec5ca51bf9e3 100644 (file)
@@ -58,21 +58,6 @@ static unsigned int mxt_td60_pins[] __initdata = {
        PE9_PF_UART3_RXD,
        PE10_PF_UART3_CTS,
        PE11_PF_UART3_RTS,
-       /* UART3 */
-       PB26_AF_UART4_RTS,
-       PB28_AF_UART4_TXD,
-       PB29_AF_UART4_CTS,
-       PB31_AF_UART4_RXD,
-       /* UART4 */
-       PB18_AF_UART5_TXD,
-       PB19_AF_UART5_RXD,
-       PB20_AF_UART5_CTS,
-       PB21_AF_UART5_RTS,
-       /* UART5 */
-       PB10_AF_UART6_TXD,
-       PB12_AF_UART6_CTS,
-       PB11_AF_UART6_RXD,
-       PB13_AF_UART6_RTS,
        /* FEC */
        PD0_AIN_FEC_TXD0,
        PD1_AIN_FEC_TXD1,
@@ -261,12 +246,6 @@ static struct imxuart_platform_data uart_pdata[] = {
                .flags = IMXUART_HAVE_RTSCTS,
        }, {
                .flags = IMXUART_HAVE_RTSCTS,
-       }, {
-               .flags = IMXUART_HAVE_RTSCTS,
-       }, {
-               .flags = IMXUART_HAVE_RTSCTS,
-       }, {
-               .flags = IMXUART_HAVE_RTSCTS,
        },
 };
 
@@ -278,9 +257,6 @@ static void __init mxt_td60_board_init(void)
        mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
        mxc_register_device(&mxc_uart_device1, &uart_pdata[1]);
        mxc_register_device(&mxc_uart_device2, &uart_pdata[2]);
-       mxc_register_device(&mxc_uart_device3, &uart_pdata[3]);
-       mxc_register_device(&mxc_uart_device4, &uart_pdata[4]);
-       mxc_register_device(&mxc_uart_device5, &uart_pdata[5]);
        mxc_register_device(&mxc_nand_device, &mxt_td60_nand_board_info);
 
        i2c_register_board_info(0, mxt_td60_i2c_devices,
index ef26951a527564c81eccc57b2f98dd0047d51bdf..6e838b857712733784ceb3f00cff790d4ba80c84 100644 (file)
@@ -173,6 +173,7 @@ DEFINE_CLOCK(pwm4_clk,       0, CCM_CGCR2,  2, get_rate_ipg, NULL);
 DEFINE_CLOCK(kpp_clk,   0, CCM_CGCR1, 28, get_rate_ipg, NULL);
 DEFINE_CLOCK(tsc_clk,   0, CCM_CGCR2, 13, get_rate_ipg, NULL);
 DEFINE_CLOCK(i2c_clk,   0, CCM_CGCR0,  6, get_rate_i2c, NULL);
+DEFINE_CLOCK(fec_clk,   0, CCM_CGCR0, 23, get_rate_ipg, NULL);
 
 #define _REGISTER_CLOCK(d, n, c)       \
        {                               \
@@ -204,6 +205,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
        _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk)
        _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk)
+       _REGISTER_CLOCK("fec.0", NULL, fec_clk)
 };
 
 int __init mx25_clocks_init(unsigned long fref)
index 63511de3a5592c9cdbccd8ca4345bedf602c7f7c..9fdeea1c083b893dfb8b26f392c8e11d2b0047e6 100644 (file)
@@ -419,3 +419,22 @@ int __init mxc_register_gpios(void)
        return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
 }
 
+static struct resource mx25_fec_resources[] = {
+       {
+               .start  = MX25_FEC_BASE_ADDR,
+               .end    = MX25_FEC_BASE_ADDR + 0xfff,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = MX25_INT_FEC,
+               .end    = MX25_INT_FEC,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device mx25_fec_device = {
+       .name   = "fec",
+       .id     = 0,
+       .num_resources  = ARRAY_SIZE(mx25_fec_resources),
+       .resource       = mx25_fec_resources,
+};
index fe6bf88ad1dd3bc844a9b95716b297532cda23aa..fe5420fcd11fbc6e44b027653d71cf3b65e08c42 100644 (file)
@@ -17,3 +17,4 @@ extern struct platform_device mxc_keypad_device;
 extern struct platform_device mxc_i2c_device0;
 extern struct platform_device mxc_i2c_device1;
 extern struct platform_device mxc_i2c_device2;
+extern struct platform_device mx25_fec_device;
index d23ae571c03f83d948b57c635ddab5a126a18a3c..921bc99ea231f3c3dde70419a065c0b3c80294c2 100644 (file)
 
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
-#include <linux/smsc911x.h>
+#include <linux/fec.h>
 #include <linux/platform_device.h>
 
 #include <mach/hardware.h>
 #include <mach/mx25.h>
 #include <mach/mxc_nand.h>
 #include "devices.h"
-#include <mach/iomux-v3.h>
+#include <mach/iomux.h>
 
 static struct imxuart_platform_data uart_pdata = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
+static struct pad_desc mx25pdk_pads[] = {
+       MX25_PAD_FEC_MDC__FEC_MDC,
+       MX25_PAD_FEC_MDIO__FEC_MDIO,
+       MX25_PAD_FEC_TDATA0__FEC_TDATA0,
+       MX25_PAD_FEC_TDATA1__FEC_TDATA1,
+       MX25_PAD_FEC_TX_EN__FEC_TX_EN,
+       MX25_PAD_FEC_RDATA0__FEC_RDATA0,
+       MX25_PAD_FEC_RDATA1__FEC_RDATA1,
+       MX25_PAD_FEC_RX_DV__FEC_RX_DV,
+       MX25_PAD_FEC_TX_CLK__FEC_TX_CLK,
+       MX25_PAD_A17__GPIO_2_3, /* FEC_EN, GPIO 35 */
+       MX25_PAD_D12__GPIO_4_8, /* FEC_RESET_B, GPIO 104 */
+};
+
+static struct fec_platform_data mx25_fec_pdata = {
+        .phy    = PHY_INTERFACE_MODE_RMII,
+};
+
+#define FEC_ENABLE_GPIO                35
+#define FEC_RESET_B_GPIO       104
+
+static void __init mx25pdk_fec_reset(void)
+{
+       gpio_request(FEC_ENABLE_GPIO, "FEC PHY enable");
+       gpio_request(FEC_RESET_B_GPIO, "FEC PHY reset");
+
+       gpio_direction_output(FEC_ENABLE_GPIO, 0);  /* drop PHY power */
+       gpio_direction_output(FEC_RESET_B_GPIO, 0); /* assert reset */
+       udelay(2);
+
+       /* turn on PHY power and lift reset */
+       gpio_set_value(FEC_ENABLE_GPIO, 1);
+       gpio_set_value(FEC_RESET_B_GPIO, 1);
+}
+
 static void __init mx25pdk_init(void)
 {
+       mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
+                       ARRAY_SIZE(mx25pdk_pads));
+
        mxc_register_device(&mxc_uart_device0, &uart_pdata);
        mxc_register_device(&mxc_usbh2, NULL);
+
+       mx25pdk_fec_reset();
+       mxc_register_device(&mx25_fec_device, &mx25_fec_pdata);
 }
 
 static void __init mx25pdk_timer_init(void)
index ea8ed109a7c2fa57c9c85d1fc2224549bb83b3a6..28294416b0afb684bae13487c8452ce2f91084f9 100644 (file)
@@ -49,6 +49,7 @@ config MACH_PCM037_EET
 config MACH_MX31LITE
        bool "Support MX31 LITEKIT (LogicPD)"
        select ARCH_MX31
+       select MXC_ULPI if USB_ULPI
        help
          Include support for MX31 LITEKIT platform. This includes specific
          configurations for the board and its peripherals.
@@ -63,7 +64,7 @@ config MACH_MX31_3DS
 config MACH_MX31MOBOARD
        bool "Support mx31moboard platforms (EPFL Mobots group)"
        select ARCH_MX31
-       select MXC_ULPI
+       select MXC_ULPI if USB_ULPI
        help
          Include support for mx31moboard platform. This includes specific
          configurations for the board and its peripherals.
index bedf5b8d976aa46a043a6a6b38112dfd1d3abdd1..6858a4f9806cd69f3f0ffe95641d87d342cdd899 100644 (file)
@@ -65,6 +65,11 @@ static struct map_desc mxc_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(AIPS2_BASE_ADDR),
                .length         = AIPS2_SIZE,
                .type           = MT_DEVICE_NONSHARED
+       }, {
+               .virtual = SPBA0_BASE_ADDR_VIRT,
+               .pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
+               .length = SPBA0_SIZE,
+               .type = MT_DEVICE_NONSHARED
        },
 };
 
index 0497c152be18cffe809bddec8924e41868ad9e7c..3e7bafa2ddbbf4fda5bb2e79dca81dda10e41c92 100644 (file)
@@ -494,11 +494,6 @@ static void mxc_init_i2c(void)
  */
 static struct map_desc mx31ads_io_desc[] __initdata = {
        {
-               .virtual        = SPBA0_BASE_ADDR_VIRT,
-               .pfn            = __phys_to_pfn(SPBA0_BASE_ADDR),
-               .length         = SPBA0_SIZE,
-               .type           = MT_DEVICE_NONSHARED
-       }, {
                .virtual        = CS4_BASE_ADDR_VIRT,
                .pfn            = __phys_to_pfn(CS4_BASE_ADDR),
                .length         = CS4_SIZE / 2,
index def6b67365946dbe4cfe07e3b7244c4d44305ce3..789b20d1730fda384a73552d457bd260772f28f1 100644 (file)
@@ -135,6 +135,7 @@ static struct spi_board_info mc13783_spi_dev __initdata = {
  * USB
  */
 
+#if defined(CONFIG_USB_ULPI)
 #define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
                        PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 
@@ -180,6 +181,7 @@ static struct mxc_usbh_platform_data usbh2_pdata = {
        .portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
        .flags  = MXC_EHCI_POWER_PINS_ENABLED,
 };
+#endif
 
 /*
  * NOR flash
@@ -212,11 +214,6 @@ static struct platform_device physmap_flash_device = {
  */
 static struct map_desc mx31lite_io_desc[] __initdata = {
        {
-               .virtual = SPBA0_BASE_ADDR_VIRT,
-               .pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
-               .length = SPBA0_SIZE,
-               .type = MT_DEVICE_NONSHARED
-       }, {
                .virtual = CS4_BASE_ADDR_VIRT,
                .pfn = __phys_to_pfn(CS4_BASE_ADDR),
                .length = CS4_SIZE,
@@ -261,11 +258,13 @@ static void __init mxc_board_init(void)
        mxc_register_device(&mxc_spi_device1, &spi1_pdata);
        spi_register_board_info(&mc13783_spi_dev, 1);
 
+#if defined(CONFIG_USB_ULPI)
        /* USB */
        usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
                                USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
 
        mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+#endif
 
        /* SMSC9117 IRQ pin */
        ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_SFS6), "sms9117-irq");
index 8fc624f141cb334b9dbf162c39b87103902d782f..438428eaf769c8f2a3cccb4bd8e80de02d447ea6 100644 (file)
@@ -179,7 +179,7 @@ static int __init devboard_usbh1_init(void)
 
        usbh1_pdata.otg = otg;
 
-       return mxc_register_device(&mx31_usbh1, &usbh1_pdata);
+       return mxc_register_device(&mxc_usbh1, &usbh1_pdata);
 }
 
 /*
index 85184a35e67415c16538fd77a7f130901488f9e0..1f44b9ccbb0f77108ebee20c745a322f58c715ae 100644 (file)
@@ -294,7 +294,7 @@ static int __init marxbot_usbh1_init(void)
 
        usbh1_pdata.otg = otg;
 
-       return mxc_register_device(&mx31_usbh1, &usbh1_pdata);
+       return mxc_register_device(&mxc_usbh1, &usbh1_pdata);
 }
 
 /*
index b70529145936f3f5d49ffe8acb1685c860e49382..cfd605d078ecf5969b8e2bbaf4b7d380de418d1d 100644 (file)
@@ -346,6 +346,8 @@ static struct fsl_usb2_platform_data usb_pdata = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
+#if defined(CONFIG_USB_ULPI)
+
 #define USBH2_EN_B IOMUX_TO_GPIO(MX31_PIN_SCK6)
 
 static int moboard_usbh2_hw_init(struct platform_device *pdev)
@@ -392,8 +394,11 @@ static int __init moboard_usbh2_init(void)
        usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
                        USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
 
-       return mxc_register_device(&mx31_usbh2, &usbh2_pdata);
+       return mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 }
+#else
+static inline int moboard_usbh2_init(void) { return 0; }
+#endif
 
 
 static struct gpio_led mx31moboard_leds[] = {
index 0f7a2f06bc2d778821da3b3696c94d0255bdad03..18715f1aa7eb65596b8111293680638937b09d9b 100644 (file)
@@ -211,11 +211,6 @@ static int __init mx31pdk_init_expio(void)
  */
 static struct map_desc mx31pdk_io_desc[] __initdata = {
        {
-               .virtual = SPBA0_BASE_ADDR_VIRT,
-               .pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
-               .length = SPBA0_SIZE,
-               .type = MT_DEVICE_NONSHARED,
-       }, {
                .virtual = CS5_BASE_ADDR_VIRT,
                .pfn = __phys_to_pfn(CS5_BASE_ADDR),
                .length = CS5_SIZE,
index 6cbaabedf386549b70483b37201df3323cb79c14..5be396917c999ff17ee314230d0dbc4325bd7a69 100644 (file)
@@ -322,16 +322,25 @@ static int pcm037_camera_power(struct device *dev, int on)
        return 0;
 }
 
-static struct i2c_board_info pcm037_i2c_2_devices[] = {
+static struct i2c_board_info pcm037_i2c_camera[] = {
        {
                I2C_BOARD_INFO("mt9t031", 0x5d),
+       }, {
+               I2C_BOARD_INFO("mt9v022", 0x48),
        },
 };
 
-static struct soc_camera_link iclink = {
+static struct soc_camera_link iclink_mt9v022 = {
+       .bus_id         = 0,            /* Must match with the camera ID */
+       .board_info     = &pcm037_i2c_camera[1],
+       .i2c_adapter_id = 2,
+       .module_name    = "mt9v022",
+};
+
+static struct soc_camera_link iclink_mt9t031 = {
        .bus_id         = 0,            /* Must match with the camera ID */
        .power          = pcm037_camera_power,
-       .board_info     = &pcm037_i2c_2_devices[0],
+       .board_info     = &pcm037_i2c_camera[0],
        .i2c_adapter_id = 2,
        .module_name    = "mt9t031",
 };
@@ -345,11 +354,19 @@ static struct i2c_board_info pcm037_i2c_devices[] = {
        }
 };
 
-static struct platform_device pcm037_camera = {
+static struct platform_device pcm037_mt9t031 = {
        .name   = "soc-camera-pdrv",
        .id     = 0,
        .dev    = {
-               .platform_data = &iclink,
+               .platform_data = &iclink_mt9t031,
+       },
+};
+
+static struct platform_device pcm037_mt9v022 = {
+       .name   = "soc-camera-pdrv",
+       .id     = 1,
+       .dev    = {
+               .platform_data = &iclink_mt9v022,
        },
 };
 
@@ -449,7 +466,8 @@ static int __init pcm037_camera_alloc_dma(const size_t buf_size)
 static struct platform_device *devices[] __initdata = {
        &pcm037_flash,
        &pcm037_sram_device,
-       &pcm037_camera,
+       &pcm037_mt9t031,
+       &pcm037_mt9v022,
 };
 
 static struct ipu_platform_data mx3_ipu_data = {
@@ -599,7 +617,7 @@ static void __init mxc_board_init(void)
        if (!ret)
                gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), 1);
        else
-               iclink.power = NULL;
+               iclink_mt9t031.power = NULL;
 
        if (!pcm037_camera_alloc_dma(4 * 1024 * 1024))
                mxc_register_device(&mx3_camera, &camera_pdata);
index ab995a9c606caf889d793eb1e6b53384994a919d..65e7b5b85d832a2799f5511a75ae82117dce1449 100644 (file)
@@ -599,7 +599,7 @@ static struct clk i2c_ick = {
 static struct omap_clk omap_clks[] = {
        /* non-ULPD clocks */
        CLK(NULL,       "ck_ref",       &ck_ref,        CK_16XX | CK_1510 | CK_310 | CK_7XX),
-       CLK(NULL,       "ck_dpll1",     &ck_dpll1,      CK_16XX | CK_1510 | CK_310),
+       CLK(NULL,       "ck_dpll1",     &ck_dpll1,      CK_16XX | CK_1510 | CK_310 | CK_7XX),
        /* CK_GEN1 clocks */
        CLK(NULL,       "ck_dpll1out",  &ck_dpll1out.clk, CK_16XX),
        CLK(NULL,       "ck_sossi",     &sossi_ck,      CK_16XX),
@@ -627,7 +627,7 @@ static struct omap_clk omap_clks[] = {
        CLK(NULL,       "tc2_ck",       &tc2_ck,        CK_16XX),
        CLK(NULL,       "dma_ck",       &dma_ck,        CK_16XX | CK_1510 | CK_310),
        CLK(NULL,       "dma_lcdfree_ck", &dma_lcdfree_ck, CK_16XX),
-       CLK(NULL,       "api_ck",       &api_ck.clk,    CK_16XX | CK_1510 | CK_310),
+       CLK(NULL,       "api_ck",       &api_ck.clk,    CK_16XX | CK_1510 | CK_310 | CK_7XX),
        CLK(NULL,       "lb_ck",        &lb_ck.clk,     CK_1510 | CK_310),
        CLK(NULL,       "rhea1_ck",     &rhea1_ck,      CK_16XX),
        CLK(NULL,       "rhea2_ck",     &rhea2_ck,      CK_16XX),
@@ -658,6 +658,10 @@ static struct omap_clk omap_clks[] = {
        CLK("i2c_omap.1", "fck",        &i2c_fck,       CK_16XX | CK_1510 | CK_310 | CK_7XX),
        CLK("i2c_omap.1", "ick",        &i2c_ick,       CK_16XX),
        CLK("i2c_omap.1", "ick",        &dummy_ck,      CK_1510 | CK_310 | CK_7XX),
+       CLK("omap1_spi100k.1", "fck",   &dummy_ck,      CK_7XX),
+       CLK("omap1_spi100k.1", "ick",   &dummy_ck,      CK_7XX),
+       CLK("omap1_spi100k.2", "fck",   &dummy_ck,      CK_7XX),
+       CLK("omap1_spi100k.2", "ick",   &dummy_ck,      CK_7XX),
        CLK("omap_uwire", "fck",        &armxor_ck.clk, CK_16XX | CK_1510 | CK_310),
        CLK("omap-mcbsp.1", "ick",      &dspper_ck,     CK_16XX),
        CLK("omap-mcbsp.1", "ick",      &dummy_ck,      CK_1510 | CK_310),
@@ -674,7 +678,7 @@ static struct omap_clk omap_clks[] = {
  * init
  */
 
-static struct clk_functions omap1_clk_functions __initdata = {
+static struct clk_functions omap1_clk_functions = {
        .clk_enable             = omap1_clk_enable,
        .clk_disable            = omap1_clk_disable,
        .clk_round_rate         = omap1_clk_round_rate,
index 23ded2d49600d8eb316179365b53322674e40af3..a2d07aa75c9e98e5b53951e158a0aca5f12b12ae 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/spi/spi.h>
 
 #include <mach/hardware.h>
 #include <asm/mach/map.h>
@@ -23,6 +24,7 @@
 #include <plat/mux.h>
 #include <mach/gpio.h>
 #include <plat/mmc.h>
+#include <plat/omap7xx.h>
 
 /*-------------------------------------------------------------------------*/
 
@@ -196,6 +198,38 @@ void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
 
 /*-------------------------------------------------------------------------*/
 
+/* OMAP7xx SPI support */
+#if defined(CONFIG_SPI_OMAP_100K) || defined(CONFIG_SPI_OMAP_100K_MODULE)
+
+struct platform_device omap_spi1 = {
+       .name           = "omap1_spi100k",
+       .id             = 1,
+};
+
+struct platform_device omap_spi2 = {
+       .name           = "omap1_spi100k",
+       .id             = 2,
+};
+
+static void omap_init_spi100k(void)
+{
+       omap_spi1.dev.platform_data = ioremap(OMAP7XX_SPI1_BASE, 0x7ff);
+       if (omap_spi1.dev.platform_data)
+               platform_device_register(&omap_spi1);
+
+       omap_spi2.dev.platform_data = ioremap(OMAP7XX_SPI2_BASE, 0x7ff);
+       if (omap_spi2.dev.platform_data)
+               platform_device_register(&omap_spi2);
+}
+
+#else
+static inline void omap_init_spi100k(void)
+{
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 #if defined(CONFIG_OMAP_STI)
 
 #define OMAP1_STI_BASE         0xfffea000
@@ -263,6 +297,7 @@ static int __init omap1_init_devices(void)
 
        omap_init_mbox();
        omap_init_rtc();
+       omap_init_spi100k();
        omap_init_sti();
 
        return 0;
index 07212cc621ae27716c43b4bbf6a81f5ff9c990d5..84341377232db2ac2706cc5494b2aad7ab0ab34d 100644 (file)
@@ -62,6 +62,14 @@ MUX_CFG_7XX("MMC_7XX_DAT0",        2,   17,    0,   16,   1, 0)
 /* I2C interface */
 MUX_CFG_7XX("I2C_7XX_SCL",         5,    1,    0,    0,   1, 0)
 MUX_CFG_7XX("I2C_7XX_SDA",         5,    5,    0,    0,   1, 0)
+
+/* SPI pins */
+MUX_CFG_7XX("SPI_7XX_1",           6,    5,    4,    4,   1, 0)
+MUX_CFG_7XX("SPI_7XX_2",           6,    9,    4,    8,   1, 0)
+MUX_CFG_7XX("SPI_7XX_3",           6,   13,    4,   12,   1, 0)
+MUX_CFG_7XX("SPI_7XX_4",           6,   17,    4,   16,   1, 0)
+MUX_CFG_7XX("SPI_7XX_5",           8,   25,    0,   24,   0, 0)
+MUX_CFG_7XX("SPI_7XX_6",           9,    5,    0,    4,   0, 0)
 };
 #define OMAP7XX_PINS_SZ                ARRAY_SIZE(omap7xx_pins)
 #else
index 10eafa70a909de702361949de09f30069da8fd88..606bf04f51b60a9acdebd3d40aa8ad757868e2c5 100644 (file)
@@ -80,6 +80,7 @@ config MACH_OVERO
 config MACH_OMAP3EVM
        bool "OMAP 3530 EVM board"
        depends on ARCH_OMAP3 && ARCH_OMAP34XX
+       select OMAP_PACKAGE_CBB
 
 config MACH_OMAP3517EVM
        bool "OMAP3517/ AM3517 EVM board"
index 8dd277c36661dc39f0833151ce77218824599785..1e3dfb652acc08c22d3da12b5aa335c85ad51e89 100755 (executable)
@@ -63,21 +63,21 @@ static int board_keymap[] = {
        KEY(5, 1, KEY_H),
        KEY(5, 2, KEY_J),
        KEY(5, 3, KEY_F3),
+       KEY(5, 4, KEY_UNKNOWN),
        KEY(5, 5, KEY_VOLUMEDOWN),
        KEY(5, 6, KEY_M),
-       KEY(5, 7, KEY_ENTER),
+       KEY(5, 7, KEY_RIGHT),
        KEY(6, 0, KEY_Q),
        KEY(6, 1, KEY_A),
        KEY(6, 2, KEY_N),
        KEY(6, 3, KEY_BACKSPACE),
        KEY(6, 6, KEY_P),
-       KEY(6, 7, KEY_SELECT),
+       KEY(6, 7, KEY_UP),
        KEY(7, 0, KEY_PROG1),   /*MACRO 1 <User defined> */
        KEY(7, 1, KEY_PROG2),   /*MACRO 2 <User defined> */
        KEY(7, 2, KEY_PROG3),   /*MACRO 3 <User defined> */
        KEY(7, 3, KEY_PROG4),   /*MACRO 4 <User defined> */
-       KEY(7, 5, KEY_RIGHT),
-       KEY(7, 6, KEY_UP),
+       KEY(7, 6, KEY_SELECT),
        KEY(7, 7, KEY_DOWN)
 };
 
index d0e3fb7f92983fcbc41bedf0e9378b194aebb616..5420356eb40734128bf904ab9ac387e6b277f182 100644 (file)
@@ -449,40 +449,78 @@ int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 #ifdef CONFIG_CPU_FREQ
 /*
  * Walk PRCM rate table and fillout cpufreq freq_table
+ * XXX This should be replaced by an OPP layer in the near future
  */
-static struct cpufreq_frequency_table freq_table[ARRAY_SIZE(rate_table)];
+static struct cpufreq_frequency_table *freq_table;
 
 void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
 {
-       struct prcm_config *prcm;
+       const struct prcm_config *prcm;
+       long sys_ck_rate;
        int i = 0;
+       int tbl_sz = 0;
+
+       sys_ck_rate = clk_get_rate(sclk);
 
        for (prcm = rate_table; prcm->mpu_speed; prcm++) {
                if (!(prcm->flags & cpu_mask))
                        continue;
-               if (prcm->xtal_speed != sys_ck.rate)
+               if (prcm->xtal_speed != sys_ck_rate)
                        continue;
 
                /* don't put bypass rates in table */
                if (prcm->dpll_speed == prcm->xtal_speed)
                        continue;
 
-               freq_table[i].index = i;
-               freq_table[i].frequency = prcm->mpu_speed / 1000;
-               i++;
+               tbl_sz++;
        }
 
-       if (i == 0) {
-               printk(KERN_WARNING "%s: failed to initialize frequency "
-                      "table\n", __func__);
+       /*
+        * XXX Ensure that we're doing what CPUFreq expects for this error
+        * case and the following one
+        */
+       if (tbl_sz == 0) {
+               pr_warning("%s: no matching entries in rate_table\n",
+                          __func__);
+               return;
+       }
+
+       /* Include the CPUFREQ_TABLE_END terminator entry */
+       tbl_sz++;
+
+       freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * tbl_sz,
+                            GFP_ATOMIC);
+       if (!freq_table) {
+               pr_err("%s: could not kzalloc frequency table\n", __func__);
                return;
        }
 
+       for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+               if (!(prcm->flags & cpu_mask))
+                       continue;
+               if (prcm->xtal_speed != sys_ck_rate)
+                       continue;
+
+               /* don't put bypass rates in table */
+               if (prcm->dpll_speed == prcm->xtal_speed)
+                       continue;
+
+               freq_table[i].index = i;
+               freq_table[i].frequency = prcm->mpu_speed / 1000;
+               i++;
+       }
+
        freq_table[i].index = i;
        freq_table[i].frequency = CPUFREQ_TABLE_END;
 
        *table = &freq_table[0];
 }
+
+void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
+{
+       kfree(freq_table);
+}
+
 #endif
 
 struct clk_functions omap2_clk_functions = {
@@ -494,6 +532,7 @@ struct clk_functions omap2_clk_functions = {
        .clk_disable_unused     = omap2_clk_disable_unused,
 #ifdef CONFIG_CPU_FREQ
        .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table,
+       .clk_exit_cpufreq_table = omap2_clk_exit_cpufreq_table,
 #endif
 };
 
index ded32364f32b0cfe270873252a4e4702409ed828..d4217b93e10befee1360785af72e277c9af203ab 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/div64.h>
 #include <asm/clkdev.h>
 
-#include <plat/sdrc.h>
 #include "clock.h"
 #include "clock34xx.h"
 #include "sdrc.h"
index 8bdcc9cc7f9af0e1b6d092374278fec743c23487..c6031d74d6f68bd5710d85e0c87c30f80c7cec47 100644 (file)
@@ -776,6 +776,8 @@ static struct clk dpll4_m5_ck = {
        .clksel_mask    = OMAP3430_CLKSEL_CAM_MASK,
        .clksel         = div16_dpll4_clksel,
        .clkdm_name     = "dpll4_clkdm",
+       .set_rate       = &omap2_clksel_set_rate,
+       .round_rate     = &omap2_clksel_round_rate,
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -1500,6 +1502,7 @@ static struct clk uart2_fck = {
        .parent         = &core_48m_fck,
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430_EN_UART2_SHIFT,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1509,6 +1512,7 @@ static struct clk uart1_fck = {
        .parent         = &core_48m_fck,
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430_EN_UART1_SHIFT,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2745,7 +2749,7 @@ static struct clk mcbsp4_ick = {
 };
 
 static const struct clksel mcbsp_234_clksel[] = {
-       { .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates },
+       { .parent = &per_96m_fck,  .rates = common_mcbsp_96m_rates },
        { .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
        { .parent = NULL }
 };
index 1a45ed1e8ba1096e33e8b3dd5a3d1432a3547149..dd285f00146715177d1a51593f3097fd7218c901 100644 (file)
@@ -559,7 +559,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
         * downstream clocks for debugging purposes?
         */
 
-       if (!clkdm || !clk)
+       if (!clkdm || !clk || !clkdm->clktrctrl_mask)
                return -EINVAL;
 
        if (atomic_inc_return(&clkdm->usecount) > 1)
@@ -610,7 +610,7 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
         * downstream clocks for debugging purposes?
         */
 
-       if (!clkdm || !clk)
+       if (!clkdm || !clk || !clkdm->clktrctrl_mask)
                return -EINVAL;
 
 #ifdef DEBUG
index a8749e8017b95974102cf620ca596f6463163961..5a7996402c53c793ccddbf85636ee84d28ac3e9b 100644 (file)
@@ -33,7 +33,6 @@
 #include <plat/sdrc.h>
 #include <plat/gpmc.h>
 #include <plat/serial.h>
-#include <plat/mux.h>
 #include <plat/vram.h>
 
 #include "clock.h"
@@ -73,21 +72,21 @@ static struct map_desc omap24xx_io_desc[] __initdata = {
 #ifdef CONFIG_ARCH_OMAP2420
 static struct map_desc omap242x_io_desc[] __initdata = {
        {
-               .virtual        = DSP_MEM_24XX_VIRT,
-               .pfn            = __phys_to_pfn(DSP_MEM_24XX_PHYS),
-               .length         = DSP_MEM_24XX_SIZE,
+               .virtual        = DSP_MEM_2420_VIRT,
+               .pfn            = __phys_to_pfn(DSP_MEM_2420_PHYS),
+               .length         = DSP_MEM_2420_SIZE,
                .type           = MT_DEVICE
        },
        {
-               .virtual        = DSP_IPI_24XX_VIRT,
-               .pfn            = __phys_to_pfn(DSP_IPI_24XX_PHYS),
-               .length         = DSP_IPI_24XX_SIZE,
+               .virtual        = DSP_IPI_2420_VIRT,
+               .pfn            = __phys_to_pfn(DSP_IPI_2420_PHYS),
+               .length         = DSP_IPI_2420_SIZE,
                .type           = MT_DEVICE
        },
        {
-               .virtual        = DSP_MMU_24XX_VIRT,
-               .pfn            = __phys_to_pfn(DSP_MMU_24XX_PHYS),
-               .length         = DSP_MMU_24XX_SIZE,
+               .virtual        = DSP_MMU_2420_VIRT,
+               .pfn            = __phys_to_pfn(DSP_MMU_2420_PHYS),
+               .length         = DSP_MMU_2420_SIZE,
                .type           = MT_DEVICE
        },
 };
index e071b3fd1878681d377037bb97880617721c0c76..459ef23ab8a818539aaa0da0464d5cf9e7af49bd 100644 (file)
@@ -994,8 +994,10 @@ int __init omap_mux_init(u32 mux_pbase, u32 mux_size,
        }
 
 #ifdef CONFIG_OMAP_MUX
-       omap_mux_package_fixup(package_subset, superset);
-       omap_mux_package_init_balls(package_balls, superset);
+       if (package_subset)
+               omap_mux_package_fixup(package_subset, superset);
+       if (package_balls)
+               omap_mux_package_init_balls(package_balls, superset);
        omap_mux_set_cmdline_signals();
        omap_mux_set_board_signals(board_mux);
 #endif
index 126a9396b3a8e9c8b39609c71e136c15a2aa2756..e6dda694fd5ca6e960bd8e7e4cd8294b27185509 100644 (file)
@@ -9,45 +9,47 @@
  * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
  * These configurations are characterized by voltage and speed for clocks.
  * The device is only validated for certain combinations. One way to express
- * these combinations is via the 'ratio's' which the clocks operate with
+ * these combinations is via the 'ratios' which the clocks operate with
  * respect to each other. These ratio sets are for a given voltage/DPLL
- * setting. All configurations can be described by a DPLL setting and a ratio
- * There are 3 ratio sets for the 2430 and X ratio sets for 2420.
- *
- * 2430 differs from 2420 in that there are no more phase synchronizers used.
- * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs
- * 2430 (iva2.1, NOdsp, mdm)
+ * setting. All configurations can be described by a DPLL setting and a ratio.
  *
  * XXX Missing voltage data.
+ * XXX Missing 19.2MHz sys_clk rate sets (needed for N800/N810)
  *
  * THe format described in this file is deprecated.  Once a reasonable
  * OPP API exists, the data in this file should be converted to use it.
  *
  * This is technically part of the OMAP2xxx clock code.
+ *
+ * Considerable work is still needed to fully support dynamic frequency
+ * changes on OMAP2xxx-series chips.  Readers interested in such a
+ * project are encouraged to review the Maemo Diablo RX-34 and RX-44
+ * kernel source at:
+ *     http://repository.maemo.org/pool/diablo/free/k/kernel-source-diablo/
  */
 
 #include "opp2xxx.h"
 #include "sdrc.h"
 #include "clock.h"
 
-/*-------------------------------------------------------------------------
- * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
+/*
+ * Key dividers which make up a PRCM set. Ratios for a PRCM are mandated.
  * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,
  * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL,
  * CM_CLKSEL2_PLL, CM_CLKSEL_MDM
  *
- * Filling in table based on H4 boards and 2430-SDPs variants available.
- * There are quite a few more rates combinations which could be defined.
+ * Filling in table based on H4 boards available.  There are quite a
+ * few more rate combinations which could be defined.
  *
- * When multiple values are defined the start up will try and choose the
- * fastest one. If a 'fast' value is defined, then automatically, the /2
- * one should be included as it can be used.   Generally having more that
- * one fast set does not make sense, as static timings need to be changed
- * to change the set.   The exception is the bypass setting which is
- * availble for low power bypass.
+ * When multiple values are defined the start up will try and choose
+ * the fastest one. If a 'fast' value is defined, then automatically,
+ * the /2 one should be included as it can be used.  Generally having
+ * more than one fast set does not make sense, as static timings need
+ * to be changed to change the set.  The exception is the bypass
+ * setting which is available for low power bypass.
  *
  * Note: This table needs to be sorted, fastest to slowest.
- *-------------------------------------------------------------------------*/
+ **/
 const struct prcm_config omap2420_rate_table[] = {
        /* PRCM I - FAST */
        {S12M, S660M, S330M, RI_CM_CLKSEL_MPU_VAL,              /* 330MHz ARM */
index edb81672c8446f3a334986d1604985e48b37c50f..1b9596ae201ef5f05fa3cf6ab003abd5f82f17c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * opp2420_data.c - old-style "OPP" table for OMAP2420
+ * opp2430_data.c - old-style "OPP" table for OMAP2430
  *
  * Copyright (C) 2005-2009 Texas Instruments, Inc.
  * Copyright (C) 2004-2009 Nokia Corporation
@@ -9,16 +9,16 @@
  * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
  * These configurations are characterized by voltage and speed for clocks.
  * The device is only validated for certain combinations. One way to express
- * these combinations is via the 'ratio's' which the clocks operate with
+ * these combinations is via the 'ratios' which the clocks operate with
  * respect to each other. These ratio sets are for a given voltage/DPLL
- * setting. All configurations can be described by a DPLL setting and a ratio
- * There are 3 ratio sets for the 2430 and X ratio sets for 2420.
+ * setting. All configurations can be described by a DPLL setting and a ratio.
  *
  * 2430 differs from 2420 in that there are no more phase synchronizers used.
  * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs
  * 2430 (iva2.1, NOdsp, mdm)
  *
  * XXX Missing voltage data.
+ * XXX Missing 19.2MHz sys_clk rate sets.
  *
  * THe format described in this file is deprecated.  Once a reasonable
  * OPP API exists, the data in this file should be converted to use it.
 #include "sdrc.h"
 #include "clock.h"
 
-/*-------------------------------------------------------------------------
- * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
+/*
+ * Key dividers which make up a PRCM set. Ratios for a PRCM are mandated.
  * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,
  * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL,
  * CM_CLKSEL2_PLL, CM_CLKSEL_MDM
  *
- * Filling in table based on H4 boards and 2430-SDPs variants available.
- * There are quite a few more rates combinations which could be defined.
+ * Filling in table based on 2430-SDPs variants available.  There are
+ * quite a few more rate combinations which could be defined.
  *
- * When multiple values are defined the start up will try and choose the
- * fastest one. If a 'fast' value is defined, then automatically, the /2
- * one should be included as it can be used.   Generally having more that
- * one fast set does not make sense, as static timings need to be changed
- * to change the set.   The exception is the bypass setting which is
- * availble for low power bypass.
+ * When multiple values are defined the start up will try and choose
+ * the fastest one. If a 'fast' value is defined, then automatically,
+ * the /2 one should be included as it can be used.  Generally having
+ * more than one fast set does not make sense, as static timings need
+ * to be changed to change the set.  The exception is the bypass
+ * setting which is available for low power bypass.
  *
  * Note: This table needs to be sorted, fastest to slowest.
- *-------------------------------------------------------------------------*/
+ */
 const struct prcm_config omap2430_rate_table[] = {
        /* PRCM #4 - ratio2 (ES2.1) - FAST */
        {S13M, S798M, S399M, R2_CM_CLKSEL_MPU_VAL,              /* 399MHz ARM */
index 81ed252a0f8aeb4f4811858d0f9d39b76e1cc464..c6cc809afb790fa5a0624f5a3e2f118c4aba3fa3 100644 (file)
@@ -124,8 +124,8 @@ static void omap3_core_save_context(void)
        control_padconf_off |= START_PADCONF_SAVE;
        omap_ctrl_writel(control_padconf_off, OMAP343X_CONTROL_PADCONF_OFF);
        /* wait for the save to complete */
-       while (!omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
-                       & PADCONF_SAVE_DONE)
+       while (!(omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
+                       & PADCONF_SAVE_DONE))
                ;
        /* Save the Interrupt controller context */
        omap_intc_save_context();
index 19805a7de06c7f5e9858c664b5164b86df10b508..8c964bec8159771099e4958c4cd6d96e618a99b1 100644 (file)
@@ -125,6 +125,13 @@ static struct plat_serial8250_port serial_platform_data3[] = {
        }
 };
 #endif
+static inline unsigned int __serial_read_reg(struct uart_port *up,
+                                          int offset)
+{
+       offset <<= up->regshift;
+       return (unsigned int)__raw_readb(up->membase + offset);
+}
+
 static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
                                           int offset)
 {
@@ -583,11 +590,12 @@ static unsigned int serial_in_override(struct uart_port *up, int offset)
 {
        if (UART_RX == offset) {
                unsigned int lsr;
-               lsr = serial_read_reg(omap_uart[up->line].p, UART_LSR);
+               lsr = __serial_read_reg(up, UART_LSR);
                if (!(lsr & UART_LSR_DR))
                        return -EPERM;
        }
-       return serial_read_reg(omap_uart[up->line].p, offset);
+
+       return __serial_read_reg(up, offset);
 }
 
 void __init omap_serial_early_init(void)
index 8a0837ea0294218a6f9ed85d43ba4862d4afc3fd..dee92182749b9ba1f475bed9d47f9b0557236a8e 100644 (file)
@@ -37,6 +37,8 @@ config MACH_ZYLONITE320
 config MACH_LITTLETON
        bool "PXA3xx Form Factor Platform (aka Littleton)"
        select PXA3xx
+       select CPU_PXA300
+       select CPU_PXA310
        select PXA_SSP
 
 config MACH_TAVOREVB
index bf6785adccf45a02e725422994d17d77138d2bf9..9edf645368d65989376ca144a2d49a1fbc2d0f74 100644 (file)
@@ -8,13 +8,6 @@
 /* the following variables are processor specific and initialized
  * by the corresponding zylonite_pxa3xx_init()
  */
-struct platform_mmc_slot {
-       int gpio_cd;
-       int gpio_wp;
-};
-
-extern struct platform_mmc_slot zylonite_mmc_slot[];
-
 extern int gpio_eth_irq;
 extern int gpio_debug_led1;
 extern int gpio_debug_led2;
index f28c1715b910f385ecfc062519b4a2df19c858b8..fa527b258d6116b77779e797a5df13967ad2d6b5 100644 (file)
@@ -110,6 +110,12 @@ static mfp_cfg_t littleton_mfp_cfg[] __initdata = {
        GPIO7_MMC1_CLK,
        GPIO8_MMC1_CMD,
        GPIO15_GPIO, /* card detect */
+
+       /* UART3 */
+       GPIO107_UART3_CTS,
+       GPIO108_UART3_RTS,
+       GPIO109_UART3_TXD,
+       GPIO110_UART3_RXD,
 };
 
 static struct resource smc91x_resources[] = {
index e5eeb3a62d0177324b6e7d922d79319aaad77011..c2b938a4d5c96d9fe72e30510d4eb1e08489bcac 100644 (file)
@@ -293,7 +293,7 @@ static struct pxamci_platform_data poodle_mci_platform_data = {
        .init                   = poodle_mci_init,
        .setpower               = poodle_mci_setpower,
        .exit                   = poodle_mci_exit,
-       .gpio_card_detect       = POODLE_IRQ_GPIO_nSD_DETECT,
+       .gpio_card_detect       = POODLE_GPIO_nSD_DETECT,
        .gpio_card_ro           = POODLE_GPIO_nSD_WP,
        .gpio_power             = -1,
 };
index 5b986a8bd9e62a41a057b533da7e978549a7dc82..75f2a37f945df03afd4d8e50d10e627fbea701f0 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
+#include <linux/apm-emulation.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -626,8 +627,27 @@ static void zeus_power_off(void)
        pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP);
 }
 
-int zeus_get_pcb_info(struct i2c_client *client, unsigned gpio,
-                     unsigned ngpio, void *context)
+#ifdef CONFIG_APM_EMULATION
+static void zeus_get_power_status(struct apm_power_info *info)
+{
+       /* Power supply is always present */
+       info->ac_line_status    = APM_AC_ONLINE;
+       info->battery_status    = APM_BATTERY_STATUS_NOT_PRESENT;
+       info->battery_flag      = APM_BATTERY_FLAG_NOT_PRESENT;
+}
+
+static inline void zeus_setup_apm(void)
+{
+       apm_get_power_status = zeus_get_power_status;
+}
+#else
+static inline void zeus_setup_apm(void)
+{
+}
+#endif
+
+static int zeus_get_pcb_info(struct i2c_client *client, unsigned gpio,
+                            unsigned ngpio, void *context)
 {
        int i;
        u8 pcb_info = 0;
@@ -726,9 +746,18 @@ static mfp_cfg_t zeus_pin_config[] __initdata = {
        GPIO99_GPIO,            /* CF RDY */
 };
 
+/*
+ * DM9k MSCx settings: SRAM, 16 bits
+ *                     17 cycles delay first access
+ *                      5 cycles delay next access
+ *                     13 cycles recovery time
+ *                     faster device
+ */
+#define DM9K_MSC_VALUE         0xe4c9
+
 static void __init zeus_init(void)
 {
-       u16 dm9000_msc = 0xe279;
+       u16 dm9000_msc = DM9K_MSC_VALUE;
 
        system_rev = __raw_readw(ZEUS_CPLD_VERSION);
        pr_info("Zeus CPLD V%dI%d\n", (system_rev & 0xf0) >> 4, (system_rev & 0x0f));
@@ -738,6 +767,7 @@ static void __init zeus_init(void)
        MSC1 = (MSC1 & 0xffff0000) | dm9000_msc;
 
        pm_power_off = zeus_power_off;
+       zeus_setup_apm();
 
        pxa2xx_mfp_config(ARRAY_AND_SIZE(zeus_pin_config));
 
index b66e9e2d06e7ff2e2a5f9fae6752414ed631e80d..2b4043c04d0c68befbf1133454fd154ffc191b5c 100644 (file)
@@ -36,9 +36,6 @@
 #include "devices.h"
 #include "generic.h"
 
-#define MAX_SLOTS      3
-struct platform_mmc_slot zylonite_mmc_slot[MAX_SLOTS];
-
 int gpio_eth_irq;
 int gpio_debug_led1;
 int gpio_debug_led2;
@@ -220,84 +217,28 @@ static inline void zylonite_init_lcd(void) {}
 #endif
 
 #if defined(CONFIG_MMC)
-static int zylonite_mci_ro(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-
-       return gpio_get_value(zylonite_mmc_slot[pdev->id].gpio_wp);
-}
-
-static int zylonite_mci_init(struct device *dev,
-                            irq_handler_t zylonite_detect_int,
-                            void *data)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       int err, cd_irq, gpio_cd, gpio_wp;
-
-       cd_irq = gpio_to_irq(zylonite_mmc_slot[pdev->id].gpio_cd);
-       gpio_cd = zylonite_mmc_slot[pdev->id].gpio_cd;
-       gpio_wp = zylonite_mmc_slot[pdev->id].gpio_wp;
-
-       /*
-        * setup GPIO for Zylonite MMC controller
-        */
-       err = gpio_request(gpio_cd, "mmc card detect");
-       if (err)
-               goto err_request_cd;
-       gpio_direction_input(gpio_cd);
-
-       err = gpio_request(gpio_wp, "mmc write protect");
-       if (err)
-               goto err_request_wp;
-       gpio_direction_input(gpio_wp);
-
-       err = request_irq(cd_irq, zylonite_detect_int,
-                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                         "MMC card detect", data);
-       if (err) {
-               printk(KERN_ERR "%s: MMC/SD/SDIO: "
-                               "can't request card detect IRQ\n", __func__);
-               goto err_request_irq;
-       }
-
-       return 0;
-
-err_request_irq:
-       gpio_free(gpio_wp);
-err_request_wp:
-       gpio_free(gpio_cd);
-err_request_cd:
-       return err;
-}
-
-static void zylonite_mci_exit(struct device *dev, void *data)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       int cd_irq, gpio_cd, gpio_wp;
-
-       cd_irq = gpio_to_irq(zylonite_mmc_slot[pdev->id].gpio_cd);
-       gpio_cd = zylonite_mmc_slot[pdev->id].gpio_cd;
-       gpio_wp = zylonite_mmc_slot[pdev->id].gpio_wp;
-
-       free_irq(cd_irq, data);
-       gpio_free(gpio_cd);
-       gpio_free(gpio_wp);
-}
-
 static struct pxamci_platform_data zylonite_mci_platform_data = {
        .detect_delay   = 20,
        .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
-       .init           = zylonite_mci_init,
-       .exit           = zylonite_mci_exit,
-       .get_ro         = zylonite_mci_ro,
-       .gpio_card_detect = -1,
-       .gpio_card_ro   = -1,
+       .gpio_card_detect = EXT_GPIO(0),
+       .gpio_card_ro   = EXT_GPIO(2),
        .gpio_power     = -1,
 };
 
 static struct pxamci_platform_data zylonite_mci2_platform_data = {
        .detect_delay   = 20,
        .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
+       .gpio_card_detect = EXT_GPIO(1),
+       .gpio_card_ro   = EXT_GPIO(3),
+       .gpio_power     = -1,
+};
+
+static struct pxamci_platform_data zylonite_mci3_platform_data = {
+       .detect_delay   = 20,
+       .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
+       .gpio_card_detect = EXT_GPIO(30),
+       .gpio_card_ro   = EXT_GPIO(31),
+       .gpio_power     = -1,
 };
 
 static void __init zylonite_init_mmc(void)
@@ -305,7 +246,7 @@ static void __init zylonite_init_mmc(void)
        pxa_set_mci_info(&zylonite_mci_platform_data);
        pxa3xx_set_mci2_info(&zylonite_mci2_platform_data);
        if (cpu_is_pxa310())
-               pxa3xx_set_mci3_info(&zylonite_mci_platform_data);
+               pxa3xx_set_mci3_info(&zylonite_mci3_platform_data);
 }
 #else
 static inline void zylonite_init_mmc(void) {}
index 84095440a87870477e78da5cfe0349fb69993efd..3aa73b3e33f27dd1db5747578d7eefe5a2304104 100644 (file)
@@ -129,8 +129,8 @@ static mfp_cfg_t common_mfp_cfg[] __initdata = {
        GPIO22_I2C_SDA,
 
        /* GPIO */
-       GPIO18_GPIO,    /* GPIO Expander #0 INT_N */
-       GPIO19_GPIO,    /* GPIO Expander #1 INT_N */
+       GPIO18_GPIO | MFP_PULL_HIGH,    /* GPIO Expander #0 INT_N */
+       GPIO19_GPIO | MFP_PULL_HIGH,    /* GPIO Expander #1 INT_N */
 };
 
 static mfp_cfg_t pxa300_mfp_cfg[] __initdata = {
@@ -258,10 +258,6 @@ void __init zylonite_pxa300_init(void)
                /* detect LCD panel */
                zylonite_detect_lcd_panel();
 
-               /* MMC card detect & write protect for controller 0 */
-               zylonite_mmc_slot[0].gpio_cd  = EXT_GPIO(0);
-               zylonite_mmc_slot[0].gpio_wp  = EXT_GPIO(2);
-
                /* WM9713 IRQ */
                wm9713_irq = mfp_to_gpio(MFP_PIN_GPIO26);
 
@@ -276,10 +272,6 @@ void __init zylonite_pxa300_init(void)
        if (cpu_is_pxa310()) {
                pxa3xx_mfp_config(ARRAY_AND_SIZE(pxa310_mfp_cfg));
                gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO102);
-
-               /* MMC card detect & write protect for controller 2 */
-               zylonite_mmc_slot[2].gpio_cd = EXT_GPIO(30);
-               zylonite_mmc_slot[2].gpio_wp = EXT_GPIO(31);
        }
 
        /* GPIOs for Debug LEDs */
index 60d08f23f5e4ed3933e2ad9855efb8b5b9ad7332..9942bac4cf7d776d99a0756200d3ef272a3d526c 100644 (file)
@@ -209,10 +209,6 @@ void __init zylonite_pxa320_init(void)
                gpio_debug_led1 = mfp_to_gpio(MFP_PIN_GPIO1_2);
                gpio_debug_led2 = mfp_to_gpio(MFP_PIN_GPIO4_2);
 
-               /* MMC card detect & write protect for controller 0 */
-               zylonite_mmc_slot[0].gpio_cd  = mfp_to_gpio(MFP_PIN_GPIO1);
-               zylonite_mmc_slot[0].gpio_wp  = mfp_to_gpio(MFP_PIN_GPIO5);
-
                /* WM9713 IRQ */
                wm9713_irq = mfp_to_gpio(MFP_PIN_GPIO15);
        }
diff --git a/arch/arm/mach-s3c2410/include/mach/ts.h b/arch/arm/mach-s3c2410/include/mach/ts.h
new file mode 100644 (file)
index 0000000..dc36170
--- /dev/null
@@ -0,0 +1,21 @@
+/* linux/include/asm/arch-s3c2410/ts.h
+ *
+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * 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 __ASM_ARM_TS_H
+#define __ASM_ARM_TS_H
+
+struct s3c2410_ts_mach_info {
+       int             delay;
+       int             presc;
+       int             oversampling_shift;
+};
+
+extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *);
+
+#endif /* __ASM_ARM_TS_H */
index 4c79ac8a6c336bb9efd5a9d45452bb4670bf3139..97162fdd05906c2c7d8bc464f4ec6697694f8399 100644 (file)
@@ -279,6 +279,7 @@ static struct s3c2410_nand_set __initdata bast_nand_sets[] = {
                .name           = "SmartMedia",
                .nr_chips       = 1,
                .nr_map         = smartmedia_map,
+               .options        = NAND_SCAN_SILENT_NODEV,
                .nr_partitions  = ARRAY_SIZE(bast_default_nand_part),
                .partitions     = bast_default_nand_part,
        },
@@ -293,6 +294,7 @@ static struct s3c2410_nand_set __initdata bast_nand_sets[] = {
                .name           = "chip1",
                .nr_chips       = 1,
                .nr_map         = chip1_map,
+               .options        = NAND_SCAN_SILENT_NODEV,
                .nr_partitions  = ARRAY_SIZE(bast_default_nand_part),
                .partitions     = bast_default_nand_part,
        },
@@ -300,6 +302,7 @@ static struct s3c2410_nand_set __initdata bast_nand_sets[] = {
                .name           = "chip2",
                .nr_chips       = 1,
                .nr_map         = chip2_map,
+               .options        = NAND_SCAN_SILENT_NODEV,
                .nr_partitions  = ARRAY_SIZE(bast_default_nand_part),
                .partitions     = bast_default_nand_part,
        }
index 49053254c98d2041a9e66e70b1699e24e66ae26a..1e34abe1a19e8b0f1dc2b4b2e486c8299a385818 100644 (file)
@@ -46,6 +46,7 @@
 #include <mach/h1940.h>
 #include <mach/h1940-latch.h>
 #include <mach/fb.h>
+#include <mach/ts.h>
 #include <plat/udc.h>
 #include <plat/iic.h>
 
@@ -140,6 +141,11 @@ static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
        .vbus_pin_inverted      = 1,
 };
 
+static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
+               .delay = 10000,
+               .presc = 49,
+               .oversampling_shift = 2,
+};
 
 /**
  * Set lcd on or off
@@ -265,6 +271,7 @@ static struct platform_device h1940_lcd_powerdev = {
 };
 
 static struct platform_device *h1940_devices[] __initdata = {
+       &s3c_device_ts,
        &s3c_device_usb,
        &s3c_device_lcd,
        &s3c_device_wdt,
@@ -305,6 +312,7 @@ static void __init h1940_init(void)
 
        s3c24xx_fb_set_platdata(&h1940_fb_info);
        s3c24xx_udc_set_platdata(&h1940_udc_cfg);
+       s3c24xx_ts_set_platdata(&h1940_ts_cfg);
        s3c_i2c0_set_platdata(NULL);
 
        s3c_device_sdi.dev.platform_data = &h1940_mmc_cfg;
index 015dfb2a80dad6e9becda57be95a326a4ee518db..f35371db33f5006dea335a8a2e27407e6c8ad471 100644 (file)
@@ -208,6 +208,7 @@ static struct s3c2410_nand_set __initdata osiris_nand_sets[] = {
                .name           = "External",
                .nr_chips       = 1,
                .nr_map         = external_map,
+               .options        = NAND_SCAN_SILENT_NODEV,
                .nr_partitions  = ARRAY_SIZE(osiris_default_nand_part),
                .partitions     = osiris_default_nand_part,
        },
@@ -222,6 +223,7 @@ static struct s3c2410_nand_set __initdata osiris_nand_sets[] = {
                .name           = "chip1",
                .nr_chips       = 1,
                .nr_map         = chip1_map,
+               .options        = NAND_SCAN_SILENT_NODEV,
                .nr_partitions  = ARRAY_SIZE(osiris_default_nand_part),
                .partitions     = osiris_default_nand_part,
        },
index 940640066857c9d9c5244aced58c830fa5616edd..ce228bdc66dd64ca3cf10d410138d68c6b25edc5 100644 (file)
  *
  */
 
+#include <linux/io.h>
 #include <asm/proc-fns.h>
+#include <mach/map.h>
+#include <mach/regs-timer.h>
+
+#define        WTCR    (TMR_BA + 0x1C)
+#define        WTCLK   (1 << 10)
+#define        WTE     (1 << 7)
+#define        WTRE    (1 << 1)
 
 static void arch_idle(void)
 {
@@ -23,6 +31,11 @@ static void arch_idle(void)
 
 static void arch_reset(char mode, const char *cmd)
 {
-       cpu_reset(0);
+       if (mode == 's') {
+               /* Jump into ROM at address 0 */
+               cpu_reset(0);
+       } else {
+               __raw_writel(WTE | WTRE | WTCLK, WTCR);
+       }
 }
 
index 4128af870b41a0d343d209d6ac74ce7dc1d432ec..b80f769bc1356509ca4fb36b198c5db13f245593 100644 (file)
 #define TICKS_PER_SEC  100
 #define PRESCALE       0x63 /* Divider = prescale + 1 */
 
-unsigned int timer0_load;
+#define        TDR_SHIFT       24
+#define        TDR_MASK        ((1 << TDR_SHIFT) - 1)
+
+static unsigned int timer0_load;
 
 static void nuc900_clockevent_setmode(enum clock_event_mode mode,
                struct clock_event_device *clk)
@@ -88,7 +91,7 @@ static int nuc900_clockevent_setnextevent(unsigned long evt,
 static struct clock_event_device nuc900_clockevent_device = {
        .name           = "nuc900-timer0",
        .shift          = 32,
-       .features       = CLOCK_EVT_MODE_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .set_mode       = nuc900_clockevent_setmode,
        .set_next_event = nuc900_clockevent_setnextevent,
        .rating         = 300,
@@ -112,8 +115,23 @@ static struct irqaction nuc900_timer0_irq = {
        .handler        = nuc900_timer0_interrupt,
 };
 
-static void __init nuc900_clockevents_init(unsigned int rate)
+static void __init nuc900_clockevents_init(void)
 {
+       unsigned int rate;
+       struct clk *clk = clk_get(NULL, "timer0");
+
+       BUG_ON(IS_ERR(clk));
+
+       __raw_writel(0x00, REG_TCSR0);
+
+       clk_enable(clk);
+       rate = clk_get_rate(clk) / (PRESCALE + 1);
+
+       timer0_load = (rate / TICKS_PER_SEC);
+
+       __raw_writel(RESETINT, REG_TISR);
+       setup_irq(IRQ_TIMER0, &nuc900_timer0_irq);
+
        nuc900_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC,
                                        nuc900_clockevent_device.shift);
        nuc900_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff,
@@ -127,26 +145,35 @@ static void __init nuc900_clockevents_init(unsigned int rate)
 
 static cycle_t nuc900_get_cycles(struct clocksource *cs)
 {
-       return ~__raw_readl(REG_TDR1);
+       return (~__raw_readl(REG_TDR1)) & TDR_MASK;
 }
 
 static struct clocksource clocksource_nuc900 = {
        .name   = "nuc900-timer1",
        .rating = 200,
        .read   = nuc900_get_cycles,
-       .mask   = CLOCKSOURCE_MASK(32),
-       .shift  = 20,
+       .mask   = CLOCKSOURCE_MASK(TDR_SHIFT),
+       .shift  = 10,
        .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static void __init nuc900_clocksource_init(unsigned int rate)
+static void __init nuc900_clocksource_init(void)
 {
        unsigned int val;
+       unsigned int rate;
+       struct clk *clk = clk_get(NULL, "timer1");
+
+       BUG_ON(IS_ERR(clk));
+
+       __raw_writel(0x00, REG_TCSR1);
+
+       clk_enable(clk);
+       rate = clk_get_rate(clk) / (PRESCALE + 1);
 
        __raw_writel(0xffffffff, REG_TICR1);
 
        val = __raw_readl(REG_TCSR1);
-       val |= (COUNTEN | PERIOD);
+       val |= (COUNTEN | PERIOD | PRESCALE);
        __raw_writel(val, REG_TCSR1);
 
        clocksource_nuc900.mult =
@@ -156,25 +183,8 @@ static void __init nuc900_clocksource_init(unsigned int rate)
 
 static void __init nuc900_timer_init(void)
 {
-       struct clk *ck_ext = clk_get(NULL, "ext");
-       unsigned int    rate;
-
-       BUG_ON(IS_ERR(ck_ext));
-
-       rate = clk_get_rate(ck_ext);
-       clk_put(ck_ext);
-       rate = rate / (PRESCALE + 0x01);
-
-        /* set a known state */
-       __raw_writel(0x00, REG_TCSR0);
-       __raw_writel(0x00, REG_TCSR1);
-       __raw_writel(RESETINT, REG_TISR);
-       timer0_load = (rate / TICKS_PER_SEC);
-
-       setup_irq(IRQ_TIMER0, &nuc900_timer0_irq);
-
-       nuc900_clocksource_init(rate);
-       nuc900_clockevents_init(rate);
+       nuc900_clocksource_init();
+       nuc900_clockevents_init();
 }
 
 struct sys_timer nuc900_timer = {
index 52c40d15567242177b40c5c60943cf63c18e3ee1..a04ffbbbe2536309ee73442db96fd271a46561a4 100644 (file)
@@ -616,7 +616,7 @@ void __init mem_init(void)
                "%dK data, %dK init, %luK highmem)\n",
                nr_free_pages() << (PAGE_SHIFT-10), codesize >> 10,
                datasize >> 10, initsize >> 10,
-               (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+               totalhigh_pages << (PAGE_SHIFT-10));
 
        if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
                extern int sysctl_overcommit_memory;
index a26a605b73bd91688417dddc00378f286bfc6a33..0cb1848bd876010a850edf2f9831cdf855f01c50 100644 (file)
@@ -40,7 +40,6 @@ ENTRY(v7wbi_flush_user_tlb_range)
        asid    r3, r3                          @ mask ASID
        orr     r0, r3, r0, lsl #PAGE_SHIFT     @ Create initial MVA
        mov     r1, r1, lsl #PAGE_SHIFT
-       vma_vm_flags r2, r2                     @ get vma->vm_flags
 1:
 #ifdef CONFIG_SMP
        mcr     p15, 0, r0, c8, c3, 1           @ TLB invalidate U MVA (shareable) 
index 810c47f56e77e4d1d5782c05962566e842bdf01f..9af494f0ab3daecdc5717ae825fe3ee9f94bc6e0 100644 (file)
 
 #define MX25_PAD_A18__A18              IOMUX_PAD(0x23c, 0x020, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_A18__GPIO_2_4         IOMUX_PAD(0x23c, 0x020, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A18__FEC_COL          IOMUX_PAD(0x23c, 0x020, 0x17, 0x504, 0, NO_PAD_CTL)
+#define MX25_PAD_A18__FEC_COL          IOMUX_PAD(0x23c, 0x020, 0x17, 0x504, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_A19__A19              IOMUX_PAD(0x240, 0x024, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A19__FEC_RX_ER                IOMUX_PAD(0x240, 0x024, 0x17, 0x518, 0, NO_PAD_CTL)
+#define MX25_PAD_A19__FEC_RX_ER                IOMUX_PAD(0x240, 0x024, 0x17, 0x518, 0, NO_PAD_CTRL)
 #define MX25_PAD_A19__GPIO_2_5         IOMUX_PAD(0x240, 0x024, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_A20__A20              IOMUX_PAD(0x244, 0x028, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_A20__GPIO_2_6         IOMUX_PAD(0x244, 0x028, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A20__FEC_RDATA2       IOMUX_PAD(0x244, 0x028, 0x17, 0x50c, 0, NO_PAD_CTL)
+#define MX25_PAD_A20__FEC_RDATA2       IOMUX_PAD(0x244, 0x028, 0x17, 0x50c, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_A21__A21              IOMUX_PAD(0x248, 0x02c, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_A21__GPIO_2_7         IOMUX_PAD(0x248, 0x02c, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A21__FEC_RDATA3       IOMUX_PAD(0x248, 0x02c, 0x17, 0x510, 0, NO_PAD_CTL)
+#define MX25_PAD_A21__FEC_RDATA3       IOMUX_PAD(0x248, 0x02c, 0x17, 0x510, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_A22__A22              IOMUX_PAD(0x000, 0x030, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_A22__GPIO_2_8         IOMUX_PAD(0x000, 0x030, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_A24__A24              IOMUX_PAD(0x250, 0x038, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_A24__GPIO_2_10                IOMUX_PAD(0x250, 0x038, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A24__FEC_RX_CLK       IOMUX_PAD(0x250, 0x038, 0x17, 0x514, 0, NO_PAD_CTL)
+#define MX25_PAD_A24__FEC_RX_CLK       IOMUX_PAD(0x250, 0x038, 0x17, 0x514, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_A25__A25              IOMUX_PAD(0x254, 0x03c, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_A25__GPIO_2_11                IOMUX_PAD(0x254, 0x03c, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A25__FEC_CRS          IOMUX_PAD(0x254, 0x03c, 0x17, 0x508, 0, NO_PAD_CTL)
+#define MX25_PAD_A25__FEC_CRS          IOMUX_PAD(0x254, 0x03c, 0x17, 0x508, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_EB0__EB0              IOMUX_PAD(0x258, 0x040, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_EB0__AUD4_TXD         IOMUX_PAD(0x258, 0x040, 0x14, 0x464, 0, NO_PAD_CTRL)
 #define MX25_PAD_CS5__UART5_RTS                IOMUX_PAD(0x268, 0x058, 0x13, 0x574, 0, NO_PAD_CTRL)
 #define MX25_PAD_CS5__GPIO_3_21                IOMUX_PAD(0x268, 0x058, 0x15, 0, 0, NO_PAD_CTRL)
 
-#define MX25_PAD_NF_CE0__NF_CE0                IOMUX_PAD(0x26c, 0x05c, 0x10, 0, 0, NO_PAD_CTL)
+#define MX25_PAD_NF_CE0__NF_CE0                IOMUX_PAD(0x26c, 0x05c, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_NF_CE0__GPIO_3_22     IOMUX_PAD(0x26c, 0x05c, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_ECB__ECB              IOMUX_PAD(0x270, 0x060, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_LD7__GPIO_1_21                IOMUX_PAD(0x2dc, 0x0e4, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_LD8__LD8              IOMUX_PAD(0x2e0, 0x0e8, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD8__FEC_TX_ERR       IOMUX_PAD(0x2e0, 0x0e8, 0x15, 0, 0, NO_PAD_CTL)
+#define MX25_PAD_LD8__FEC_TX_ERR       IOMUX_PAD(0x2e0, 0x0e8, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_LD9__LD9              IOMUX_PAD(0x2e4, 0x0ec, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD9__FEC_COL          IOMUX_PAD(0x2e4, 0x0ec, 0x15, 0x504, 1, NO_PAD_CTL)
+#define MX25_PAD_LD9__FEC_COL          IOMUX_PAD(0x2e4, 0x0ec, 0x15, 0x504, 1, NO_PAD_CTRL)
 
 #define MX25_PAD_LD10__LD10            IOMUX_PAD(0x2e8, 0x0f0, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD10__FEC_RX_ER       IOMUX_PAD(0x2e8, 0x0f0, 0x15, 0x518, 1, NO_PAD_CTL)
+#define MX25_PAD_LD10__FEC_RX_ER       IOMUX_PAD(0x2e8, 0x0f0, 0x15, 0x518, 1, NO_PAD_CTRL)
 
 #define MX25_PAD_LD11__LD11            IOMUX_PAD(0x2ec, 0x0f4, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD11__FEC_RDATA2      IOMUX_PAD(0x2ec, 0x0f4, 0x15, 0x50c, 1, NO_PAD_CTL)
+#define MX25_PAD_LD11__FEC_RDATA2      IOMUX_PAD(0x2ec, 0x0f4, 0x15, 0x50c, 1, NO_PAD_CTRL)
 
 #define MX25_PAD_LD12__LD12            IOMUX_PAD(0x2f0, 0x0f8, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD12__FEC_RDATA3      IOMUX_PAD(0x2f0, 0x0f8, 0x15, 0x510, 1, NO_PAD_CTL)
+#define MX25_PAD_LD12__FEC_RDATA3      IOMUX_PAD(0x2f0, 0x0f8, 0x15, 0x510, 1, NO_PAD_CTRL)
 
 #define MX25_PAD_LD13__LD13            IOMUX_PAD(0x2f4, 0x0fc, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD13__FEC_TDATA2      IOMUX_PAD(0x2f4, 0x0fc, 0x15, 0, 0, NO_PAD_CTL)
+#define MX25_PAD_LD13__FEC_TDATA2      IOMUX_PAD(0x2f4, 0x0fc, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_LD14__LD14            IOMUX_PAD(0x2f8, 0x100, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD14__FEC_TDATA3      IOMUX_PAD(0x2f8, 0x100, 0x15, 0, 0, NO_PAD_CTL)
+#define MX25_PAD_LD14__FEC_TDATA3      IOMUX_PAD(0x2f8, 0x100, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_LD15__LD15            IOMUX_PAD(0x2fc, 0x104, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD15__FEC_RX_CLK      IOMUX_PAD(0x2fc, 0x104, 0x15, 0x514, 1, NO_PAD_CTL)
+#define MX25_PAD_LD15__FEC_RX_CLK      IOMUX_PAD(0x2fc, 0x104, 0x15, 0x514, 1, NO_PAD_CTRL)
 
 #define MX25_PAD_HSYNC__HSYNC          IOMUX_PAD(0x300, 0x108, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_HSYNC__GPIO_1_22      IOMUX_PAD(0x300, 0x108, 0x15, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_OE_ACD__GPIO_1_25     IOMUX_PAD(0x30c, 0x114, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_CONTRAST__CONTRAST    IOMUX_PAD(0x310, 0x118, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CONTRAST__FEC_CRS     IOMUX_PAD(0x310, 0x118, 0x15, 0x508, 1, NO_PAD_CTL)
+#define MX25_PAD_CONTRAST__FEC_CRS     IOMUX_PAD(0x310, 0x118, 0x15, 0x508, 1, NO_PAD_CTRL)
 
 #define MX25_PAD_PWM__PWM              IOMUX_PAD(0x314, 0x11c, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_PWM__GPIO_1_26                IOMUX_PAD(0x314, 0x11c, 0x15, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_UART2_TXD__GPIO_4_27  IOMUX_PAD(0x37c, 0x184, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_UART2_RTS__UART2_RTS  IOMUX_PAD(0x380, 0x188, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART2_RTS__FEC_COL    IOMUX_PAD(0x380, 0x188, 0x12, 0x504, 2, NO_PAD_CTL)
+#define MX25_PAD_UART2_RTS__FEC_COL    IOMUX_PAD(0x380, 0x188, 0x12, 0x504, 2, NO_PAD_CTRL)
 #define MX25_PAD_UART2_RTS__GPIO_4_28  IOMUX_PAD(0x380, 0x188, 0x15, 0, 0, NO_PAD_CTRL)
 
-#define MX25_PAD_UART2_CTS__FEC_RX_ER  IOMUX_PAD(0x384, 0x18c, 0x12, 0x518, 2, NO_PAD_CTL)
+#define MX25_PAD_UART2_CTS__FEC_RX_ER  IOMUX_PAD(0x384, 0x18c, 0x12, 0x518, 2, NO_PAD_CTRL)
 #define MX25_PAD_UART2_CTS__UART2_CTS  IOMUX_PAD(0x384, 0x18c, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_UART2_CTS__GPIO_4_29  IOMUX_PAD(0x384, 0x18c, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_SD1_CMD__SD1_CMD      IOMUX_PAD(0x388, 0x190, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_CMD__FEC_RDATA2   IOMUX_PAD(0x388, 0x190, 0x12, 0x50c, 2, NO_PAD_CTL)
+#define MX25_PAD_SD1_CMD__FEC_RDATA2   IOMUX_PAD(0x388, 0x190, 0x12, 0x50c, 2, NO_PAD_CTRL)
 #define MX25_PAD_SD1_CMD__GPIO_2_23    IOMUX_PAD(0x388, 0x190, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_SD1_CLK__SD1_CLK      IOMUX_PAD(0x38c, 0x194, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_CLK__FEC_RDATA3   IOMUX_PAD(0x38c, 0x194, 0x12, 0x510, 2, NO_PAD_CTL)
+#define MX25_PAD_SD1_CLK__FEC_RDATA3   IOMUX_PAD(0x38c, 0x194, 0x12, 0x510, 2, NO_PAD_CTRL)
 #define MX25_PAD_SD1_CLK__GPIO_2_24    IOMUX_PAD(0x38c, 0x194, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_SD1_DATA0__SD1_DATA0  IOMUX_PAD(0x390, 0x198, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
 #define MX25_PAD_SD1_DATA1__GPIO_2_26  IOMUX_PAD(0x394, 0x19c, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_SD1_DATA2__SD1_DATA2  IOMUX_PAD(0x398, 0x1a0, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_DATA2__FEC_RX_CLK IOMUX_PAD(0x398, 0x1a0, 0x15, 0x514, 2, NO_PAD_CTL)
+#define MX25_PAD_SD1_DATA2__FEC_RX_CLK IOMUX_PAD(0x398, 0x1a0, 0x15, 0x514, 2, NO_PAD_CTRL)
 #define MX25_PAD_SD1_DATA2__GPIO_2_27  IOMUX_PAD(0x398, 0x1a0, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_SD1_DATA3__SD1_DATA3  IOMUX_PAD(0x39c, 0x1a4, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_DATA3__FEC_CRS    IOMUX_PAD(0x39c, 0x1a4, 0x10, 0x508, 2, NO_PAD_CTL)
+#define MX25_PAD_SD1_DATA3__FEC_CRS    IOMUX_PAD(0x39c, 0x1a4, 0x10, 0x508, 2, NO_PAD_CTRL)
 #define MX25_PAD_SD1_DATA3__GPIO_2_28  IOMUX_PAD(0x39c, 0x1a4, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_KPP_ROW0__KPP_ROW0    IOMUX_PAD(0x3a0, 0x1a8, 0x10, 0, 0, PAD_CTL_PKE)
 #define MX25_PAD_KPP_COL3__KPP_COL3    IOMUX_PAD(0x3bc, 0x1c4, 0x10, 0, 0, PAD_CTL_PKE | PAD_CTL_ODE)
 #define MX25_PAD_KPP_COL3__GPIO_3_4    IOMUX_PAD(0x3bc, 0x1c4, 0x15, 0, 0, NO_PAD_CTRL)
 
-#define MX25_PAD_FEC_MDC__FEC_MDC      IOMUX_PAD(0x3c0, 0x1c8, 0x10, 0, 0, NO_PAD_CTL)
+#define MX25_PAD_FEC_MDC__FEC_MDC      IOMUX_PAD(0x3c0, 0x1c8, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_FEC_MDC__AUD4_TXD     IOMUX_PAD(0x3c0, 0x1c8, 0x12, 0x464, 1, NO_PAD_CTRL)
 #define MX25_PAD_FEC_MDC__GPIO_3_5     IOMUX_PAD(0x3c0, 0x1c8, 0x15, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_FEC_MDIO__AUD4_RXD    IOMUX_PAD(0x3c4, 0x1cc, 0x12, 0x460, 1, NO_PAD_CTRL)
 #define MX25_PAD_FEC_MDIO__GPIO_3_6    IOMUX_PAD(0x3c4, 0x1cc, 0x15, 0, 0, NO_PAD_CTRL)
 
-#define MX25_PAD_FEC_TDATA0__FEC_TDATA0        IOMUX_PAD(0x3c8, 0x1d0, 0x10, 0, 0, NO_PAD_CTL)
+#define MX25_PAD_FEC_TDATA0__FEC_TDATA0        IOMUX_PAD(0x3c8, 0x1d0, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_FEC_TDATA0__GPIO_3_7  IOMUX_PAD(0x3c8, 0x1d0, 0x15, 0, 0, NO_PAD_CTRL)
 
-#define MX25_PAD_FEC_TDATA1__FEC_TDATA1        IOMUX_PAD(0x3cc, 0x1d4, 0x10, 0, 0, NO_PAD_CTL)
+#define MX25_PAD_FEC_TDATA1__FEC_TDATA1        IOMUX_PAD(0x3cc, 0x1d4, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_FEC_TDATA1__AUD4_TXFS IOMUX_PAD(0x3cc, 0x1d4, 0x12, 0x474, 1, NO_PAD_CTRL)
 #define MX25_PAD_FEC_TDATA1__GPIO_3_8  IOMUX_PAD(0x3cc, 0x1d4, 0x15, 0, 0, NO_PAD_CTRL)
 
-#define MX25_PAD_FEC_TX_EN__FEC_TX_EN  IOMUX_PAD(0x3d0, 0x1d8, 0x10, 0, 0, NO_PAD_CTL)
+#define MX25_PAD_FEC_TX_EN__FEC_TX_EN  IOMUX_PAD(0x3d0, 0x1d8, 0x10, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_FEC_TX_EN__GPIO_3_9           IOMUX_PAD(0x3d0, 0x1d8, 0x15, 0, 0, NO_PAD_CTRL)
 
-#define MX25_PAD_FEC_RDATA0__FEC_RDATA0        IOMUX_PAD(0x3d4, 0x1dc, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTL)
+#define MX25_PAD_FEC_RDATA0__FEC_RDATA0        IOMUX_PAD(0x3d4, 0x1dc, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
 #define MX25_PAD_FEC_RDATA0__GPIO_3_10 IOMUX_PAD(0x3d4, 0x1dc, 0x15, 0, 0, NO_PAD_CTRL)
 
-#define MX25_PAD_FEC_RDATA1__FEC_RDATA1        IOMUX_PAD(0x3d8, 0x1e0, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTL)
+#define MX25_PAD_FEC_RDATA1__FEC_RDATA1        IOMUX_PAD(0x3d8, 0x1e0, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
 #define MX25_PAD_FEC_RDATA1__GPIO_3_11 IOMUX_PAD(0x3d8, 0x1e0, 0x15, 0, 0, NO_PAD_CTRL)
 
-#define MX25_PAD_FEC_RX_DV__FEC_RX_DV  IOMUX_PAD(0x3dc, 0x1e4, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTL)
+#define MX25_PAD_FEC_RX_DV__FEC_RX_DV  IOMUX_PAD(0x3dc, 0x1e4, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
 #define MX25_PAD_FEC_RX_DV__CAN2_RX    IOMUX_PAD(0x3dc, 0x1e4, 0x14, 0x484, 0, PAD_CTL_PUS_22K_UP)
 #define MX25_PAD_FEC_RX_DV__GPIO_3_12  IOMUX_PAD(0x3dc, 0x1e4, 0x15, 0, 0, NO_PAD_CTRL)
 
index 91e738144804d1d17960673b413c86117eaee1cf..854e2dc58481627af17a640896ef7d2e27087c22 100644 (file)
@@ -41,4 +41,8 @@
 #define UART1_BASE_ADDR                        0x43f90000
 #define UART2_BASE_ADDR                        0x43f94000
 
+#define MX25_FEC_BASE_ADDR             0x50038000
+
+#define MX25_INT_FEC   57
+
 #endif /* __MACH_MX25_H__ */
index 89cafc9372496d2d33989be36f2ea38b657d0949..d9f8c844c385fa18f7b92aa88431296df9f75140 100644 (file)
@@ -36,10 +36,6 @@ static struct clk_functions *arch_clock;
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
 
-/* This functions is moved to arch/arm/common/clkdev.c. For OMAP4 since
- * clock framework is not up , it is defined here to avoid rework in
- * every driver. Also dummy prcm reset function is added */
-
 int clk_enable(struct clk *clk)
 {
        unsigned long flags;
@@ -305,7 +301,6 @@ void clk_enable_init_clocks(void)
                        clk_enable(clkp);
        }
 }
-EXPORT_SYMBOL(clk_enable_init_clocks);
 
 /*
  * Low level helpers
@@ -334,7 +329,16 @@ void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
                arch_clock->clk_init_cpufreq_table(table);
        spin_unlock_irqrestore(&clockfw_lock, flags);
 }
-EXPORT_SYMBOL(clk_init_cpufreq_table);
+
+void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&clockfw_lock, flags);
+       if (arch_clock->clk_exit_cpufreq_table)
+               arch_clock->clk_exit_cpufreq_table(table);
+       spin_unlock_irqrestore(&clockfw_lock, flags);
+}
 #endif
 
 /*-------------------------------------------------------------------------*/
index f8ddbdd8b076e9ae5b830aab3a5615b8fc1fc7ea..6d3d3336005600a301dc78220b91b2bfd37ce17b 100644 (file)
@@ -134,6 +134,7 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy)
 
 static int omap_cpu_exit(struct cpufreq_policy *policy)
 {
+       clk_exit_cpufreq_table(&freq_table);
        clk_put(mpu_clk);
        return 0;
 }
index 04846811d0aaf83696e2b6c641785d902af7f1c5..d17620c50c286a9a7aa5f3e80a05872042acdd79 100644 (file)
@@ -192,6 +192,7 @@ struct gpio_bank {
        u32 saved_risingdetect;
 #endif
        u32 level_mask;
+       u32 toggle_mask;
        spinlock_t lock;
        struct gpio_chip chip;
        struct clk *dbck;
@@ -749,6 +750,44 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
 }
 #endif
 
+/*
+ * This only applies to chips that can't do both rising and falling edge
+ * detection at once.  For all other chips, this function is a noop.
+ */
+static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
+{
+       void __iomem *reg = bank->base;
+       u32 l = 0;
+
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_GPIO_INT_EDGE;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_INT_CONTROL;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_INT_CONTROL;
+               break;
+#endif
+       default:
+               return;
+       }
+
+       l = __raw_readl(reg);
+       if ((l >> gpio) & 1)
+               l &= ~(1 << gpio);
+       else
+               l |= 1 << gpio;
+
+       __raw_writel(l, reg);
+}
+
 static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
 {
        void __iomem *reg = bank->base;
@@ -759,6 +798,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
        case METHOD_MPUIO:
                reg += OMAP_MPUIO_GPIO_INT_EDGE;
                l = __raw_readl(reg);
+               if (trigger & IRQ_TYPE_EDGE_BOTH)
+                       bank->toggle_mask |= 1 << gpio;
                if (trigger & IRQ_TYPE_EDGE_RISING)
                        l |= 1 << gpio;
                else if (trigger & IRQ_TYPE_EDGE_FALLING)
@@ -771,6 +812,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
        case METHOD_GPIO_1510:
                reg += OMAP1510_GPIO_INT_CONTROL;
                l = __raw_readl(reg);
+               if (trigger & IRQ_TYPE_EDGE_BOTH)
+                       bank->toggle_mask |= 1 << gpio;
                if (trigger & IRQ_TYPE_EDGE_RISING)
                        l |= 1 << gpio;
                else if (trigger & IRQ_TYPE_EDGE_FALLING)
@@ -803,6 +846,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
        case METHOD_GPIO_7XX:
                reg += OMAP7XX_GPIO_INT_CONTROL;
                l = __raw_readl(reg);
+               if (trigger & IRQ_TYPE_EDGE_BOTH)
+                       bank->toggle_mask |= 1 << gpio;
                if (trigger & IRQ_TYPE_EDGE_RISING)
                        l |= 1 << gpio;
                else if (trigger & IRQ_TYPE_EDGE_FALLING)
@@ -1072,7 +1117,7 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
  */
 static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
 {
-       unsigned long flags;
+       unsigned long uninitialized_var(flags);
 
        switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP16XX
@@ -1217,7 +1262,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        void __iomem *isr_reg = NULL;
        u32 isr;
-       unsigned int gpio_irq;
+       unsigned int gpio_irq, gpio_index;
        struct gpio_bank *bank;
        u32 retrigger = 0;
        int unmasked = 0;
@@ -1284,9 +1329,23 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
                gpio_irq = bank->virtual_irq_start;
                for (; isr != 0; isr >>= 1, gpio_irq++) {
+                       gpio_index = get_gpio_index(irq_to_gpio(gpio_irq));
+
                        if (!(isr & 1))
                                continue;
 
+#ifdef CONFIG_ARCH_OMAP1
+                       /*
+                        * Some chips can't respond to both rising and falling
+                        * at the same time.  If this irq was requested with
+                        * both flags, we need to flip the ICR data for the IRQ
+                        * to respond to the IRQ for the opposite direction.
+                        * This will be indicated in the bank toggle_mask.
+                        */
+                       if (bank->toggle_mask & (1 << gpio_index))
+                               _toggle_gpio_edge_triggering(bank, gpio_index);
+#endif
+
                        generic_handle_irq(gpio_irq);
                }
        }
index 376ce18216ff8ee4ac613b9e2dff5bf285995bc6..5cd622039da0db81f4a7b1275449ddd11f830bb1 100644 (file)
@@ -99,7 +99,6 @@ struct fb_info;
 struct omap_backlight_config {
        int default_intensity;
        int (*set_power)(struct device *dev, int state);
-       int (*check_fb)(struct fb_info *fb);
 };
 
 struct omap_fbmem_config {
index 309b6d1dccdba8670ae0b63a8de4b13d7ea92053..94fe2a0ce40a8502f6cf2a2006717300d1818163 100644 (file)
@@ -119,6 +119,7 @@ struct clk_functions {
        void            (*clk_disable_unused)(struct clk *clk);
 #ifdef CONFIG_CPU_FREQ
        void            (*clk_init_cpufreq_table)(struct cpufreq_frequency_table **);
+       void            (*clk_exit_cpufreq_table)(struct cpufreq_frequency_table **);
 #endif
 };
 
@@ -135,6 +136,7 @@ extern unsigned long followparent_recalc(struct clk *clk);
 extern void clk_enable_init_clocks(void);
 #ifdef CONFIG_CPU_FREQ
 extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
+extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
 #endif
 
 extern const struct clkops clkops_null;
index 2ae884378638659d211af495a9ce513245ca82e1..a745d62fad0d3782efe7d06ab271635d48f00f26 100644 (file)
 #define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
 #define OMAP343X_CONTROL_IVA2_BOOTMOD  (OMAP2_CONTROL_GENERAL + 0x0194)
 #define OMAP343X_CONTROL_DEBOBS(i)     (OMAP2_CONTROL_GENERAL + 0x01B0 \
-                                       + ((i) >> 1) * 4 + (!(i) & 1) * 2)
+                                       + ((i) >> 1) * 4 + (!((i) & 1)) * 2)
 #define OMAP343X_CONTROL_PROG_IO0      (OMAP2_CONTROL_GENERAL + 0x01D4)
 #define OMAP343X_CONTROL_PROG_IO1      (OMAP2_CONTROL_GENERAL + 0x01D8)
 #define OMAP343X_CONTROL_DSS_DPLL_SPREADING    (OMAP2_CONTROL_GENERAL + 0x01E0)
index 7e5319f907d1298dc247ddc3ce9ffd919bf274e4..a3e7b471bcba93e2b25119a4b04bfc2af5e44f7c 100644 (file)
 #define OMAP243X_SMS_VIRT      (OMAP243X_SMS_PHYS + OMAP2_L3_IO_OFFSET)
 #define OMAP243X_SMS_SIZE      SZ_1M
 
-/* DSP */
-#define DSP_MEM_24XX_PHYS      OMAP2420_DSP_MEM_BASE   /* 0x58000000 */
-#define DSP_MEM_24XX_VIRT      0xe0000000
-#define DSP_MEM_24XX_SIZE      0x28000
-#define DSP_IPI_24XX_PHYS      OMAP2420_DSP_IPI_BASE   /* 0x59000000 */
-#define DSP_IPI_24XX_VIRT      0xe1000000
-#define DSP_IPI_24XX_SIZE      SZ_4K
-#define DSP_MMU_24XX_PHYS      OMAP2420_DSP_MMU_BASE   /* 0x5a000000 */
-#define DSP_MMU_24XX_VIRT      0xe2000000
-#define DSP_MMU_24XX_SIZE      SZ_4K
+/* 2420 IVA */
+#define DSP_MEM_2420_PHYS      OMAP2420_DSP_MEM_BASE
+                                               /* 0x58000000 --> 0xfc100000 */
+#define DSP_MEM_2420_VIRT      0xfc100000
+#define DSP_MEM_2420_SIZE      0x28000
+#define DSP_IPI_2420_PHYS      OMAP2420_DSP_IPI_BASE
+                                               /* 0x59000000 --> 0xfc128000 */
+#define DSP_IPI_2420_VIRT      0xfc128000
+#define DSP_IPI_2420_SIZE      SZ_4K
+#define DSP_MMU_2420_PHYS      OMAP2420_DSP_MMU_BASE
+                                               /* 0x5a000000 --> 0xfc129000 */
+#define DSP_MMU_2420_VIRT      0xfc129000
+#define DSP_MMU_2420_SIZE      SZ_4K
+
+/* 2430 IVA2.1 - currently unmapped */
 
 /*
  * ----------------------------------------------------------------------------
 #define OMAP343X_SDRC_VIRT     (OMAP343X_SDRC_PHYS + OMAP2_L3_IO_OFFSET)
 #define OMAP343X_SDRC_SIZE     SZ_1M
 
-/* DSP */
-#define DSP_MEM_34XX_PHYS      OMAP34XX_DSP_MEM_BASE   /* 0x58000000 */
-#define DSP_MEM_34XX_VIRT      0xe0000000
-#define DSP_MEM_34XX_SIZE      0x28000
-#define DSP_IPI_34XX_PHYS      OMAP34XX_DSP_IPI_BASE   /* 0x59000000 */
-#define DSP_IPI_34XX_VIRT      0xe1000000
-#define DSP_IPI_34XX_SIZE      SZ_4K
-#define DSP_MMU_34XX_PHYS      OMAP34XX_DSP_MMU_BASE   /* 0x5a000000 */
-#define DSP_MMU_34XX_VIRT      0xe2000000
-#define DSP_MMU_34XX_SIZE      SZ_4K
+/* 3430 IVA - currently unmapped */
 
 /*
  * ----------------------------------------------------------------------------
index 8f069cc803504dc5a45263635c4ad4f5e1dc93c1..692c90e89ac3376d14eba9614ce3dc0a82b2b91e 100644 (file)
@@ -183,6 +183,14 @@ enum omap7xx_index {
        /* I2C */
        I2C_7XX_SCL,
        I2C_7XX_SDA,
+
+       /* SPI */
+       SPI_7XX_1,
+       SPI_7XX_2,
+       SPI_7XX_3,
+       SPI_7XX_4,
+       SPI_7XX_5,
+       SPI_7XX_6,
 };
 
 enum omap1xxx_index {
index 53f52414b0e979f512ff48ccd571d4e3fda62289..48e4757e1e301cc0558e2a965b2c9ba801d28a0d 100644 (file)
@@ -46,6 +46,9 @@
 #define OMAP7XX_DSPREG_SIZE    SZ_128K
 #define OMAP7XX_DSPREG_START   0xE1000000
 
+#define OMAP7XX_SPI1_BASE      0xfffc0800
+#define OMAP7XX_SPI2_BASE      0xfffc1000
+
 /*
  * ----------------------------------------------------------------------------
  * OMAP7XX specific configuration registers
index 11f5d7961c731d0b6fc69da3c357eb6cd3304153..0cfd54f519c4012eb0eb6fe518bf19ce0d3ebf42 100644 (file)
@@ -66,12 +66,12 @@ void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type)
                        return XLATE(p, L4_24XX_PHYS, L4_24XX_VIRT);
        }
        if (cpu_is_omap2420()) {
-               if (BETWEEN(p, DSP_MEM_24XX_PHYS, DSP_MEM_24XX_SIZE))
-                       return XLATE(p, DSP_MEM_24XX_PHYS, DSP_MEM_24XX_VIRT);
-               if (BETWEEN(p, DSP_IPI_24XX_PHYS, DSP_IPI_24XX_SIZE))
-                       return XLATE(p, DSP_IPI_24XX_PHYS, DSP_IPI_24XX_SIZE);
-               if (BETWEEN(p, DSP_MMU_24XX_PHYS, DSP_MMU_24XX_SIZE))
-                       return XLATE(p, DSP_MMU_24XX_PHYS, DSP_MMU_24XX_VIRT);
+               if (BETWEEN(p, DSP_MEM_2420_PHYS, DSP_MEM_2420_SIZE))
+                       return XLATE(p, DSP_MEM_2420_PHYS, DSP_MEM_2420_VIRT);
+               if (BETWEEN(p, DSP_IPI_2420_PHYS, DSP_IPI_2420_SIZE))
+                       return XLATE(p, DSP_IPI_2420_PHYS, DSP_IPI_2420_SIZE);
+               if (BETWEEN(p, DSP_MMU_2420_PHYS, DSP_MMU_2420_SIZE))
+                       return XLATE(p, DSP_MMU_2420_PHYS, DSP_MMU_2420_VIRT);
        }
        if (cpu_is_omap2430()) {
                if (BETWEEN(p, L4_WK_243X_PHYS, L4_WK_243X_SIZE))
index c0ff1e39d8934d443db9780e7cdf9e6c75ae7bff..463d6386aff21172413e96ff0ed3ba0885821c15 100644 (file)
@@ -827,7 +827,7 @@ EXPORT_SYMBOL_GPL(iommu_get);
  **/
 void iommu_put(struct iommu *obj)
 {
-       if (!obj && IS_ERR(obj))
+       if (!obj || IS_ERR(obj))
                return;
 
        mutex_lock(&obj->iommu_lock);
index 2cc1cc328bac1e477851c3705acfe98fb98dfa2b..f75767278fc3d0c245e599ec62a54477344e71a5 100644 (file)
@@ -436,7 +436,7 @@ int omap_mcbsp_request(unsigned int id)
                        dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
                                        "for McBSP%d\n", mcbsp->tx_irq,
                                        mcbsp->id);
-                       return err;
+                       goto error;
                }
 
                init_completion(&mcbsp->rx_irq_completion);
@@ -446,12 +446,26 @@ int omap_mcbsp_request(unsigned int id)
                        dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
                                        "for McBSP%d\n", mcbsp->rx_irq,
                                        mcbsp->id);
-                       free_irq(mcbsp->tx_irq, (void *)mcbsp);
-                       return err;
+                       goto tx_irq;
                }
        }
 
        return 0;
+tx_irq:
+       free_irq(mcbsp->tx_irq, (void *)mcbsp);
+error:
+       if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
+                       mcbsp->pdata->ops->free(id);
+
+       /* Do procedure specific to omap34xx arch, if applicable */
+       omap34xx_mcbsp_free(mcbsp);
+
+       clk_disable(mcbsp->fclk);
+       clk_disable(mcbsp->iclk);
+
+       mcbsp->free = 1;
+
+       return err;
 }
 EXPORT_SYMBOL(omap_mcbsp_request);
 
index a9eabdcfa163b57cc8fdd27953b135cf61d98063..51dc5c8106c0cc84dd38aa89faf176f46303f019 100644 (file)
@@ -204,14 +204,14 @@ static int __devinit pwm_probe(struct platform_device *pdev)
                goto err_free_clk;
        }
 
-       r = request_mem_region(r->start, r->end - r->start + 1, pdev->name);
+       r = request_mem_region(r->start, resource_size(r), pdev->name);
        if (r == NULL) {
                dev_err(&pdev->dev, "failed to request memory resource\n");
                ret = -EBUSY;
                goto err_free_clk;
        }
 
-       pwm->mmio_base = ioremap(r->start, r->end - r->start + 1);
+       pwm->mmio_base = ioremap(r->start, resource_size(r));
        if (pwm->mmio_base == NULL) {
                dev_err(&pdev->dev, "failed to ioremap() registers\n");
                ret = -ENODEV;
@@ -241,7 +241,7 @@ static int __devinit pwm_probe(struct platform_device *pdev)
        return 0;
 
 err_free_mem:
-       release_mem_region(r->start, r->end - r->start + 1);
+       release_mem_region(r->start, resource_size(r));
 err_free_clk:
        clk_put(pwm->clk);
 err_free:
@@ -271,7 +271,7 @@ static int __devexit pwm_remove(struct platform_device *pdev)
        iounmap(pwm->mmio_base);
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(r->start, r->end - r->start + 1);
+       release_mem_region(r->start, resource_size(r));
 
        clk_put(pwm->clk);
        kfree(pwm);
index e771e77dcd54011f82e70e11f6810c7953ab44f4..84808ccda70ebf8e528d6aa5e44ba36048b17a2c 100644 (file)
@@ -114,7 +114,7 @@ void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
                
                for (i = 0; i < npd->nr_sets; i++) {
                        ret = s3c_nand_copy_set(to);
-                       if (!ret) {
+                       if (ret) {
                                printk(KERN_ERR "%s: failed to copy set %d\n",
                                __func__, i);
                                return;
@@ -122,6 +122,8 @@ void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
                        to++;
                }
        }
+
+       s3c_device_nand.dev.platform_data = npd;
 }
 
 EXPORT_SYMBOL_GPL(s3c_nand_set_platdata);
index 932cbbbb4273a0c34daaa0875b4f7c86887af2e4..c1c20b023917e32db4e4eed39e07f7ec235c0f83 100644 (file)
@@ -31,6 +31,7 @@ extern struct platform_device s3c64xx_device_iisv4;
 extern struct platform_device s3c64xx_device_pcm0;
 extern struct platform_device s3c64xx_device_pcm1;
 
+extern struct platform_device s3c_device_ts;
 extern struct platform_device s3c_device_fb;
 extern struct platform_device s3c_device_usb;
 extern struct platform_device s3c_device_lcd;
index f52a92ce8ddaea471576ad1c5d6ef9e127f475f3..7f686a31e67235066dd3bc3a4624656656c77187 100644 (file)
@@ -37,6 +37,8 @@
 #include <plat/cpu.h>
 #include <plat/regs-spi.h>
 
+#include <mach/ts.h>
+
 /* Serial port registrations */
 
 static struct resource s3c2410_uart0_resource[] = {
@@ -182,6 +184,22 @@ void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
        }
 }
 
+/* Touchscreen */
+struct platform_device s3c_device_ts = {
+       .name             = "s3c2410-ts",
+       .id               = -1,
+};
+EXPORT_SYMBOL(s3c_device_ts);
+
+static struct s3c2410_ts_mach_info s3c2410ts_info;
+
+void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
+{
+       memcpy(&s3c2410ts_info, hard_s3c2410ts_info, sizeof(struct s3c2410_ts_mach_info));
+       s3c_device_ts.dev.platform_data = &s3c2410ts_info;
+}
+EXPORT_SYMBOL(s3c24xx_ts_set_platdata);
+
 /* USB Device (Gadget)*/
 
 static struct resource s3c_usbgadget_resource[] = {
index 1364317d421e3e2dec2e8e7b7140b1a2b7ec59dd..12623a474b548955ac30bb6602ba298b61012e44 100644 (file)
@@ -70,6 +70,7 @@ void __init s3c244x_map_io(void)
        s3c_device_sdi.name  = "s3c2440-sdi";
        s3c_device_i2c0.name  = "s3c2440-i2c";
        s3c_device_nand.name = "s3c2440-nand";
+       s3c_device_ts.name = "s3c2440-ts";
        s3c_device_usbgadget.name = "s3c2440-usbgadget";
 }
 
index 6ffa21eb1b917296d5db50ac4322fd75940ebe5b..ffd56deb9e81a8c36a42a970ff57db24c55f4e37 100644 (file)
@@ -46,6 +46,7 @@ static struct clk clk_ext_xtal_mux = {
 #define clk_fin_epll clk_ext_xtal_mux
 
 #define clk_fout_mpll  clk_mpll
+#define clk_fout_epll  clk_epll
 
 struct clk_sources {
        unsigned int    nr_sources;
@@ -88,11 +89,6 @@ static struct clksrc_clk clk_mout_apll = {
        .sources        = &clk_src_apll,
 };
 
-static struct clk clk_fout_epll = {
-       .name           = "fout_epll",
-       .id             = -1,
-};
-
 static struct clk *clk_src_epll_list[] = {
        [0] = &clk_fin_epll,
        [1] = &clk_fout_epll,
@@ -715,7 +711,6 @@ static struct clk *clks[] __initdata = {
        &clk_iis_cd1,
        &clk_pcm_cd,
        &clk_mout_epll.clk,
-       &clk_fout_epll,
        &clk_mout_mpll.clk,
        &clk_dout_mpll,
        &clk_mmc0.clk,
@@ -760,7 +755,4 @@ void __init s3c6400_register_clocks(unsigned armclk_divlimit)
                               clkp->name, ret);
                }
        }
-
-       clk_mpll.parent = &clk_mout_mpll.clk;
-       clk_epll.parent = &clk_mout_epll.clk;
 }
index 944a07c6cfd6084500347ef3b440786d2d546bd9..1d04e4078340c5617f67ba7bbc92d6a4975dc06a 100644 (file)
@@ -10,4 +10,9 @@
 #include <asm-generic/page.h>
 #define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
 
+#define VM_DATA_DEFAULT_FLAGS \
+       (VM_READ | VM_WRITE | \
+       ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
+                VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
 #endif
index f1036b6b92936fbfb5eba7a74f2026613c3c3d49..34c7c3ed2c9c5e7eafc7453c5a7a7bfacea5329a 100644 (file)
@@ -6,23 +6,9 @@
  * Licensed under the GPL-2 or later.
  */
 
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
 #include <linux/ptrace.h>              /* for linux pt_regs struct */
 #include <linux/kgdb.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/irq.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
-#include <asm/traps.h>
-#include <asm/blackfin.h>
-#include <asm/dma.h>
 
 void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
 {
@@ -147,7 +133,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
        regs->lb1 = gdb_regs[BFIN_LB1];
        regs->usp = gdb_regs[BFIN_USP];
        regs->syscfg = gdb_regs[BFIN_SYSCFG];
-       regs->retx = gdb_regs[BFIN_PC];
+       regs->retx = gdb_regs[BFIN_RETX];
        regs->retn = gdb_regs[BFIN_RETN];
        regs->rete = gdb_regs[BFIN_RETE];
        regs->pc = gdb_regs[BFIN_PC];
@@ -424,182 +410,6 @@ struct kgdb_arch arch_kgdb_ops = {
        .correct_hw_break = bfin_correct_hw_break,
 };
 
-static int hex(char ch)
-{
-       if ((ch >= 'a') && (ch <= 'f'))
-               return ch - 'a' + 10;
-       if ((ch >= '0') && (ch <= '9'))
-               return ch - '0';
-       if ((ch >= 'A') && (ch <= 'F'))
-               return ch - 'A' + 10;
-       return -1;
-}
-
-static int validate_memory_access_address(unsigned long addr, int size)
-{
-       if (size < 0 || addr == 0)
-               return -EFAULT;
-       return bfin_mem_access_type(addr, size);
-}
-
-static int bfin_probe_kernel_read(char *dst, char *src, int size)
-{
-       unsigned long lsrc = (unsigned long)src;
-       int mem_type;
-
-       mem_type = validate_memory_access_address(lsrc, size);
-       if (mem_type < 0)
-               return mem_type;
-
-       if (lsrc >= SYSMMR_BASE) {
-               if (size == 2 && lsrc % 2 == 0) {
-                       u16 mmr = bfin_read16(src);
-                       memcpy(dst, &mmr, sizeof(mmr));
-                       return 0;
-               } else if (size == 4 && lsrc % 4 == 0) {
-                       u32 mmr = bfin_read32(src);
-                       memcpy(dst, &mmr, sizeof(mmr));
-                       return 0;
-               }
-       } else {
-               switch (mem_type) {
-                       case BFIN_MEM_ACCESS_CORE:
-                       case BFIN_MEM_ACCESS_CORE_ONLY:
-                               return probe_kernel_read(dst, src, size);
-                       /* XXX: should support IDMA here with SMP */
-                       case BFIN_MEM_ACCESS_DMA:
-                               if (dma_memcpy(dst, src, size))
-                                       return 0;
-                               break;
-                       case BFIN_MEM_ACCESS_ITEST:
-                               if (isram_memcpy(dst, src, size))
-                                       return 0;
-                               break;
-               }
-       }
-
-       return -EFAULT;
-}
-
-static int bfin_probe_kernel_write(char *dst, char *src, int size)
-{
-       unsigned long ldst = (unsigned long)dst;
-       int mem_type;
-
-       mem_type = validate_memory_access_address(ldst, size);
-       if (mem_type < 0)
-               return mem_type;
-
-       if (ldst >= SYSMMR_BASE) {
-               if (size == 2 && ldst % 2 == 0) {
-                       u16 mmr;
-                       memcpy(&mmr, src, sizeof(mmr));
-                       bfin_write16(dst, mmr);
-                       return 0;
-               } else if (size == 4 && ldst % 4 == 0) {
-                       u32 mmr;
-                       memcpy(&mmr, src, sizeof(mmr));
-                       bfin_write32(dst, mmr);
-                       return 0;
-               }
-       } else {
-               switch (mem_type) {
-                       case BFIN_MEM_ACCESS_CORE:
-                       case BFIN_MEM_ACCESS_CORE_ONLY:
-                               return probe_kernel_write(dst, src, size);
-                       /* XXX: should support IDMA here with SMP */
-                       case BFIN_MEM_ACCESS_DMA:
-                               if (dma_memcpy(dst, src, size))
-                                       return 0;
-                               break;
-                       case BFIN_MEM_ACCESS_ITEST:
-                               if (isram_memcpy(dst, src, size))
-                                       return 0;
-                               break;
-               }
-       }
-
-       return -EFAULT;
-}
-
-/*
- * Convert the memory pointed to by mem into hex, placing result in buf.
- * Return a pointer to the last char put in buf (null). May return an error.
- */
-int kgdb_mem2hex(char *mem, char *buf, int count)
-{
-       char *tmp;
-       int err;
-
-       /*
-        * We use the upper half of buf as an intermediate buffer for the
-        * raw memory copy.  Hex conversion will work against this one.
-        */
-       tmp = buf + count;
-
-       err = bfin_probe_kernel_read(tmp, mem, count);
-       if (!err) {
-               while (count > 0) {
-                       buf = pack_hex_byte(buf, *tmp);
-                       tmp++;
-                       count--;
-               }
-
-               *buf = 0;
-       }
-
-       return err;
-}
-
-/*
- * Copy the binary array pointed to by buf into mem.  Fix $, #, and
- * 0x7d escaped with 0x7d.  Return a pointer to the character after
- * the last byte written.
- */
-int kgdb_ebin2mem(char *buf, char *mem, int count)
-{
-       char *tmp_old, *tmp_new;
-       int size;
-
-       tmp_old = tmp_new = buf;
-
-       for (size = 0; size < count; ++size) {
-               if (*tmp_old == 0x7d)
-                       *tmp_new = *(++tmp_old) ^ 0x20;
-               else
-                       *tmp_new = *tmp_old;
-               tmp_new++;
-               tmp_old++;
-       }
-
-       return bfin_probe_kernel_write(mem, buf, count);
-}
-
-/*
- * Convert the hex array pointed to by buf into binary to be placed in mem.
- * Return a pointer to the character AFTER the last byte written.
- * May return an error.
- */
-int kgdb_hex2mem(char *buf, char *mem, int count)
-{
-       char *tmp_raw, *tmp_hex;
-
-       /*
-        * We use the upper half of buf as an intermediate buffer for the
-        * raw memory that is converted from hex.
-        */
-       tmp_raw = buf + count * 2;
-
-       tmp_hex = tmp_raw - 1;
-       while (tmp_hex >= buf) {
-               tmp_raw--;
-               *tmp_raw = hex(*tmp_hex--);
-               *tmp_raw |= hex(*tmp_hex--) << 4;
-       }
-
-       return bfin_probe_kernel_write(mem, tmp_raw, count);
-}
-
 #define IN_MEM(addr, size, l1_addr, l1_size) \
 ({ \
        unsigned long __addr = (unsigned long)(addr); \
@@ -629,21 +439,6 @@ int kgdb_validate_break_address(unsigned long addr)
        return -EFAULT;
 }
 
-int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
-{
-       int err = bfin_probe_kernel_read(saved_instr, (char *)addr,
-                                        BREAK_INSTR_SIZE);
-       if (err)
-               return err;
-       return bfin_probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
-                                      BREAK_INSTR_SIZE);
-}
-
-int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
-{
-       return bfin_probe_kernel_write((char *)addr, bundle, BREAK_INSTR_SIZE);
-}
-
 int kgdb_arch_init(void)
 {
        kgdb_single_step = 0;
index d489f894f4b1d7451fc7cdedb8cf1ce9049b371b..4c011b1f661fc0c542cdd44b385168705111836f 100644 (file)
@@ -2,4 +2,4 @@
 # arch/blackfin/mm/Makefile
 #
 
-obj-y := sram-alloc.o isram-driver.o init.o
+obj-y := sram-alloc.o isram-driver.o init.o maccess.o
diff --git a/arch/blackfin/mm/maccess.c b/arch/blackfin/mm/maccess.c
new file mode 100644 (file)
index 0000000..b71cebc
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * safe read and write memory routines callable while atomic
+ *
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/uaccess.h>
+#include <asm/dma.h>
+
+static int validate_memory_access_address(unsigned long addr, int size)
+{
+       if (size < 0 || addr == 0)
+               return -EFAULT;
+       return bfin_mem_access_type(addr, size);
+}
+
+long probe_kernel_read(void *dst, void *src, size_t size)
+{
+       unsigned long lsrc = (unsigned long)src;
+       int mem_type;
+
+       mem_type = validate_memory_access_address(lsrc, size);
+       if (mem_type < 0)
+               return mem_type;
+
+       if (lsrc >= SYSMMR_BASE) {
+               if (size == 2 && lsrc % 2 == 0) {
+                       u16 mmr = bfin_read16(src);
+                       memcpy(dst, &mmr, sizeof(mmr));
+                       return 0;
+               } else if (size == 4 && lsrc % 4 == 0) {
+                       u32 mmr = bfin_read32(src);
+                       memcpy(dst, &mmr, sizeof(mmr));
+                       return 0;
+               }
+       } else {
+               switch (mem_type) {
+               case BFIN_MEM_ACCESS_CORE:
+               case BFIN_MEM_ACCESS_CORE_ONLY:
+                       return __probe_kernel_read(dst, src, size);
+                       /* XXX: should support IDMA here with SMP */
+               case BFIN_MEM_ACCESS_DMA:
+                       if (dma_memcpy(dst, src, size))
+                               return 0;
+                       break;
+               case BFIN_MEM_ACCESS_ITEST:
+                       if (isram_memcpy(dst, src, size))
+                               return 0;
+                       break;
+               }
+       }
+
+       return -EFAULT;
+}
+
+long probe_kernel_write(void *dst, void *src, size_t size)
+{
+       unsigned long ldst = (unsigned long)dst;
+       int mem_type;
+
+       mem_type = validate_memory_access_address(ldst, size);
+       if (mem_type < 0)
+               return mem_type;
+
+       if (ldst >= SYSMMR_BASE) {
+               if (size == 2 && ldst % 2 == 0) {
+                       u16 mmr;
+                       memcpy(&mmr, src, sizeof(mmr));
+                       bfin_write16(dst, mmr);
+                       return 0;
+               } else if (size == 4 && ldst % 4 == 0) {
+                       u32 mmr;
+                       memcpy(&mmr, src, sizeof(mmr));
+                       bfin_write32(dst, mmr);
+                       return 0;
+               }
+       } else {
+               switch (mem_type) {
+               case BFIN_MEM_ACCESS_CORE:
+               case BFIN_MEM_ACCESS_CORE_ONLY:
+                       return __probe_kernel_write(dst, src, size);
+                       /* XXX: should support IDMA here with SMP */
+               case BFIN_MEM_ACCESS_DMA:
+                       if (dma_memcpy(dst, src, size))
+                               return 0;
+                       break;
+               case BFIN_MEM_ACCESS_ITEST:
+                       if (isram_memcpy(dst, src, size))
+                               return 0;
+                       break;
+               }
+       }
+
+       return -EFAULT;
+}
index 25c6a5002355da190f88b90c5d8954b912453a6f..8c97068ac8fc4543cf288629cf9e85db57887431 100644 (file)
@@ -63,12 +63,10 @@ extern unsigned long max_pfn;
 #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
 
-#ifdef CONFIG_MMU
 #define VM_DATA_DEFAULT_FLAGS \
        (VM_READ | VM_WRITE | \
        ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#endif
 
 #endif /* __ASSEMBLY__ */
 
index d20db3c2a656719cc44a3ee3a9559737234c7a4b..fbd1a2470cae0cc9152621a3765814cbd53c2858 100644 (file)
@@ -8,7 +8,6 @@
 extern void _mcount(unsigned long pfs, unsigned long r1, unsigned long b0, unsigned long r0);
 #define mcount _mcount
 
-#include <asm/kprobes.h>
 /* In IA64, MCOUNT_ADDR is set in link time, so it's not a constant at compile time */
 #define MCOUNT_ADDR (((struct fnptr *)mcount)->ip)
 #define FTRACE_ADDR (((struct fnptr *)ftrace_caller)->ip)
index dbf83fb28db318849f3a148d215e4977d6fd1760..d5505d6f2382bd00d298639595730000b9347021 100644 (file)
@@ -103,11 +103,6 @@ typedef struct kprobe_opcode {
        bundle_t bundle;
 } kprobe_opcode_t;
 
-struct fnptr {
-       unsigned long ip;
-       unsigned long gp;
-};
-
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
        /* copy of the instruction to be emulated */
index 85d965cb19a0835ace573551d667053fcc8fa260..23cce999eb1cadaef129afa9d342ca3bc87c2d54 100644 (file)
@@ -74,7 +74,7 @@ struct ia64_tr_entry {
 extern int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size);
 extern void ia64_ptr_entry(u64 target_mask, int slot);
 
-extern struct ia64_tr_entry __per_cpu_idtrs[NR_CPUS][2][IA64_TR_ALLOC_MAX];
+extern struct ia64_tr_entry *ia64_idtrs[NR_CPUS];
 
 /*
  region register macros
index 3ddb4e709dbadb1c36523e696a6ce32927c1c459..d323071d0f915e95ad60d6c45974a4e9788aedae 100644 (file)
@@ -33,7 +33,9 @@
 /*
  * Returns a bitmask of CPUs on Node 'node'.
  */
-#define cpumask_of_node(node) (&node_to_cpu_mask[node])
+#define cpumask_of_node(node) ((node) == -1 ?                          \
+                              cpu_all_mask :                           \
+                              &node_to_cpu_mask[node])
 
 /*
  * Returns the number of the node containing Node 'nid'.
index bcd260e597de32aa0a99e637cc0e01338ea721ae..93773fd37be0fec66fbc10f702da8aad4c91f62c 100644 (file)
@@ -35,6 +35,11 @@ typedef unsigned int umode_t;
  */
 # ifdef __KERNEL__
 
+struct fnptr {
+       unsigned long ip;
+       unsigned long gp;
+};
+
 /* DMA addresses are 64-bits wide, in general.  */
 typedef u64 dma_addr_t;
 
index 32f2639e9b0af540948a85ceb9878d33efd866c8..378b4833024f110ac7e11265341774f3a6ee75be 100644 (file)
@@ -1225,9 +1225,12 @@ static void mca_insert_tr(u64 iord)
        unsigned long psr;
        int cpu = smp_processor_id();
 
+       if (!ia64_idtrs[cpu])
+               return;
+
        psr = ia64_clear_ic();
        for (i = IA64_TR_ALLOC_BASE; i < IA64_TR_ALLOC_MAX; i++) {
-               p = &__per_cpu_idtrs[cpu][iord-1][i];
+               p = ia64_idtrs[cpu] + (iord - 1) * IA64_TR_ALLOC_MAX;
                if (p->pte & 0x1) {
                        old_rr = ia64_get_rr(p->ifa);
                        if (old_rr != p->rr) {
index 5246285a95fb253187c774093743df35b76239aa..6bcbe215b9a418e555cad4793e20a6723d7b88f9 100644 (file)
@@ -2293,7 +2293,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t
         * if ((mm->total_vm << PAGE_SHIFT) + len> task->rlim[RLIMIT_AS].rlim_cur)
         *      return -ENOMEM;
         */
-       if (size > task->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
+       if (size > task_rlimit(task, RLIMIT_MEMLOCK))
                return -ENOMEM;
 
        /*
index 360724d3ae699d38681da70c1b750c6318f87a81..988911b4cc7abd9f0f60993ef5419b62d0ea062b 100644 (file)
@@ -388,6 +388,9 @@ static inline u64 __gpfn_is_io(u64 gpfn)
 #define _vmm_raw_spin_lock(x)   do {}while(0)
 #define _vmm_raw_spin_unlock(x) do {}while(0)
 #else
+typedef struct {
+       volatile unsigned int lock;
+} vmm_spinlock_t;
 #define _vmm_raw_spin_lock(x)                                          \
        do {                                                            \
                __u32 *ia64_spinlock_ptr = (__u32 *) (x);               \
@@ -405,12 +408,12 @@ static inline u64 __gpfn_is_io(u64 gpfn)
 
 #define _vmm_raw_spin_unlock(x)                                \
        do { barrier();                         \
-               ((spinlock_t *)x)->raw_lock.lock = 0; } \
+               ((vmm_spinlock_t *)x)->lock = 0; } \
 while (0)
 #endif
 
-void vmm_spin_lock(spinlock_t *lock);
-void vmm_spin_unlock(spinlock_t *lock);
+void vmm_spin_lock(vmm_spinlock_t *lock);
+void vmm_spin_unlock(vmm_spinlock_t *lock);
 enum {
        I_TLB = 1,
        D_TLB = 2
index f4b4c899bb6ce9d77d42d7a796931cb13e47ab03..7a62f75778c535f7421fc16ec4525407e3686e9b 100644 (file)
@@ -60,12 +60,12 @@ static void __exit kvm_vmm_exit(void)
        return ;
 }
 
-void vmm_spin_lock(spinlock_t *lock)
+void vmm_spin_lock(vmm_spinlock_t *lock)
 {
        _vmm_raw_spin_lock(lock);
 }
 
-void vmm_spin_unlock(spinlock_t *lock)
+void vmm_spin_unlock(vmm_spinlock_t *lock)
 {
        _vmm_raw_spin_unlock(lock);
 }
index 20b3852f7a6ec50d765fe3911fa0b6e6a0ef4859..4332f7ee5203f27179db08b5a95d372c6509e681 100644 (file)
@@ -182,7 +182,7 @@ void mark_pages_dirty(struct kvm_vcpu *v, u64 pte, u64 ps)
 {
        u64 i, dirty_pages = 1;
        u64 base_gfn = (pte&_PAGE_PPN_MASK) >> PAGE_SHIFT;
-       spinlock_t *lock = __kvm_va(v->arch.dirty_log_lock_pa);
+       vmm_spinlock_t *lock = __kvm_va(v->arch.dirty_log_lock_pa);
        void *dirty_bitmap = (void *)KVM_MEM_DIRTY_LOG_BASE;
 
        dirty_pages <<= ps <= PAGE_SHIFT ? 0 : ps - PAGE_SHIFT;
index b9609c69343a373f5e742be333bcac7d24cf4381..7c0d4814a68dc12a2f5f2dca9b16f1631a7f8314 100644 (file)
@@ -91,7 +91,7 @@ dma_mark_clean(void *addr, size_t size)
 inline void
 ia64_set_rbs_bot (void)
 {
-       unsigned long stack_size = current->signal->rlim[RLIMIT_STACK].rlim_max & -16;
+       unsigned long stack_size = rlimit_max(RLIMIT_STACK) & -16;
 
        if (stack_size > MAX_USER_STACK_SIZE)
                stack_size = MAX_USER_STACK_SIZE;
index ee09d261f2e6c0be4071e1de30aee0339d6b9706..f3de9d7a98b481c632fa4960211213f0a3ee307d 100644 (file)
@@ -48,7 +48,7 @@ DEFINE_PER_CPU(u8, ia64_need_tlb_flush);
 DEFINE_PER_CPU(u8, ia64_tr_num);  /*Number of TR slots in current processor*/
 DEFINE_PER_CPU(u8, ia64_tr_used); /*Max Slot number used by kernel*/
 
-struct ia64_tr_entry __per_cpu_idtrs[NR_CPUS][2][IA64_TR_ALLOC_MAX];
+struct ia64_tr_entry *ia64_idtrs[NR_CPUS];
 
 /*
  * Initializes the ia64_ctx.bitmap array based on max_ctx+1.
@@ -429,10 +429,16 @@ int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size)
        struct ia64_tr_entry *p;
        int cpu = smp_processor_id();
 
+       if (!ia64_idtrs[cpu]) {
+               ia64_idtrs[cpu] = kmalloc(2 * IA64_TR_ALLOC_MAX *
+                               sizeof (struct ia64_tr_entry), GFP_KERNEL);
+               if (!ia64_idtrs[cpu])
+                       return -ENOMEM;
+       }
        r = -EINVAL;
        /*Check overlap with existing TR entries*/
        if (target_mask & 0x1) {
-               p = &__per_cpu_idtrs[cpu][0][0];
+               p = ia64_idtrs[cpu];
                for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
                                                                i++, p++) {
                        if (p->pte & 0x1)
@@ -444,7 +450,7 @@ int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size)
                }
        }
        if (target_mask & 0x2) {
-               p = &__per_cpu_idtrs[cpu][1][0];
+               p = ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX;
                for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
                                                                i++, p++) {
                        if (p->pte & 0x1)
@@ -459,16 +465,16 @@ int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size)
        for (i = IA64_TR_ALLOC_BASE; i < per_cpu(ia64_tr_num, cpu); i++) {
                switch (target_mask & 0x3) {
                case 1:
-                       if (!(__per_cpu_idtrs[cpu][0][i].pte & 0x1))
+                       if (!((ia64_idtrs[cpu] + i)->pte & 0x1))
                                goto found;
                        continue;
                case 2:
-                       if (!(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
+                       if (!((ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX + i)->pte & 0x1))
                                goto found;
                        continue;
                case 3:
-                       if (!(__per_cpu_idtrs[cpu][0][i].pte & 0x1) &&
-                               !(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
+                       if (!((ia64_idtrs[cpu] + i)->pte & 0x1) &&
+                           !((ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX + i)->pte & 0x1))
                                goto found;
                        continue;
                default:
@@ -488,7 +494,7 @@ found:
        if (target_mask & 0x1) {
                ia64_itr(0x1, i, va, pte, log_size);
                ia64_srlz_i();
-               p = &__per_cpu_idtrs[cpu][0][i];
+               p = ia64_idtrs[cpu] + i;
                p->ifa = va;
                p->pte = pte;
                p->itir = log_size << 2;
@@ -497,7 +503,7 @@ found:
        if (target_mask & 0x2) {
                ia64_itr(0x2, i, va, pte, log_size);
                ia64_srlz_i();
-               p = &__per_cpu_idtrs[cpu][1][i];
+               p = ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX + i;
                p->ifa = va;
                p->pte = pte;
                p->itir = log_size << 2;
@@ -528,7 +534,7 @@ void ia64_ptr_entry(u64 target_mask, int slot)
                return;
 
        if (target_mask & 0x1) {
-               p = &__per_cpu_idtrs[cpu][0][slot];
+               p = ia64_idtrs[cpu] + slot;
                if ((p->pte&0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
                        p->pte = 0;
                        ia64_ptr(0x1, p->ifa, p->itir>>2);
@@ -537,7 +543,7 @@ void ia64_ptr_entry(u64 target_mask, int slot)
        }
 
        if (target_mask & 0x2) {
-               p = &__per_cpu_idtrs[cpu][1][slot];
+               p = ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX + slot;
                if ((p->pte & 0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
                        p->pte = 0;
                        ia64_ptr(0x2, p->ifa, p->itir>>2);
@@ -546,8 +552,8 @@ void ia64_ptr_entry(u64 target_mask, int slot)
        }
 
        for (i = per_cpu(ia64_tr_used, cpu); i >= IA64_TR_ALLOC_BASE; i--) {
-               if ((__per_cpu_idtrs[cpu][0][i].pte & 0x1) ||
-                               (__per_cpu_idtrs[cpu][1][i].pte & 0x1))
+               if (((ia64_idtrs[cpu] + i)->pte & 0x1) ||
+                   ((ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX + i)->pte & 0x1))
                        break;
        }
        per_cpu(ia64_tr_used, cpu) = i;
index 9e8d00389eef18e0c99b4e2343632d1533554a42..1651942f7febe79eeea81927f34264e01c7c4217 100644 (file)
@@ -424,7 +424,7 @@ void __init mem_init(void)
               reservedpages << (PAGE_SHIFT-10),
               datasize >> 10,
               initsize >> 10,
-              (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+              totalhigh_pages << (PAGE_SHIFT-10));
 }
 #endif /* !CONFIG_NEED_MULTIPLE_NODES */
 
index f61c164d1e67f5dbda40d8d84a9101216e4c359a..bc1297109cc54e61487f3645f0237114c126e685 100644 (file)
@@ -505,5 +505,5 @@ void __init mem_init(void)
               (num_physpages - tmp) << (PAGE_SHIFT-10),
               datasize >> 10,
               initsize >> 10,
-              (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+              totalhigh_pages << (PAGE_SHIFT-10));
 }
index dd0c8ff52a682b6c622bdc3cd9be939760c0b561..ac5c6bdb2f05c6535ab802cf34000f206995badb 100644 (file)
@@ -19,7 +19,7 @@ CCDIR := $(strip $(patsubst %/specs,%,$(CCSPECS)))
 KBUILD_CPPFLAGS += -nostdinc -I$(CCDIR)/include
 
 LDFLAGS                :=
-OBJCOPYFLAGS   := -O binary -R .note -R .comment -S
+OBJCOPYFLAGS   := -O binary -R .note -R .comment -R .GCC-command-line -R .note.gnu.build-id -S
 #LDFLAGS_vmlinux := -Map linkmap.txt
 CHECKFLAGS     +=
 
index 3acce23708b0dac8da538cd28f0d0f720c3c19d0..441920d8ff58a91e3b966172eb6da4c7df527fc6 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Sat Apr 18 11:13:22 2009
+# Linux kernel version: 2.6.33-rc1
+# Tue Dec 22 19:26:25 2009
 #
 CONFIG_MN10300=y
 CONFIG_AM33=y
@@ -22,6 +22,7 @@ CONFIG_GENERIC_HARDIRQS=y
 # CONFIG_HOTPLUG_CPU is not set
 CONFIG_HZ=1000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -43,11 +44,10 @@ CONFIG_BSD_PROCESS_ACCT=y
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
 # CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_PREEMPT_RCU is not set
+CONFIG_TINY_RCU=y
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
@@ -62,7 +62,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-CONFIG_STRIP_ASM_SYMS=y
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -75,14 +74,22 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -90,6 +97,35 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 # CONFIG_BLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -145,9 +181,8 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=1
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
-CONFIG_HAVE_MLOCK=y
-CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Power management options
@@ -202,6 +237,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -216,6 +252,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -341,7 +378,6 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_SCSI_DMA is not set
 # CONFIG_SCSI_NETLINK is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -362,14 +398,11 @@ CONFIG_SMC91X=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
+# CONFIG_WLAN is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -430,11 +463,15 @@ CONFIG_RTC=y
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
 
@@ -451,22 +488,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -490,11 +512,17 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
 # File systems
 #
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -539,6 +567,7 @@ CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
@@ -561,13 +590,13 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_STRIP_ASM_SYMS=y
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
 # CONFIG_SAMPLES is not set
 
@@ -577,7 +606,11 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
 # CONFIG_CRYPTO is not set
 # CONFIG_BINARY_PRINTF is not set
 
index 0b610f482abb9fbe0622e9b6758cbc758e046de3..f49ac49e09adc079adaabdd9893258ae9b795b7f 100644 (file)
@@ -165,7 +165,7 @@ static inline __attribute__((const))
 unsigned long __ffs(unsigned long x)
 {
        int bit;
-       asm("bsch %2,%0" : "=r"(bit) : "0"(0), "r"(x & -x));
+       asm("bsch %2,%0" : "=r"(bit) : "0"(0), "r"(x & -x) : "cc");
        return bit;
 }
 
@@ -177,7 +177,7 @@ static inline __attribute__((const))
 int __ilog2_u32(u32 n)
 {
        int bit;
-       asm("bsch %2,%0" : "=r"(bit) : "0"(0), "r"(n));
+       asm("bsch %2,%0" : "=r"(bit) : "0"(0), "r"(n) : "cc");
        return bit;
 }
 
index 3a8329b3e8694493c6b018eea7820873d04110f8..34dcb8e68309e0331b12d5ce2051a05da04e4c3f 100644 (file)
@@ -72,6 +72,7 @@ unsigned __muldiv64u(unsigned val, unsigned mult, unsigned div)
                                         * MDR = MDR:val%div */
            : "=r"(result)
            : "0"(val), "ir"(mult), "r"(div)
+           : "cc"
            );
 
        return result;
@@ -92,6 +93,7 @@ signed __muldiv64s(signed val, signed mult, signed div)
                                         * MDR = MDR:val%div */
            : "=r"(result)
            : "0"(val), "ir"(mult), "r"(div)
+           : "cc"
            );
 
        return result;
index 8214fb7e7fe4747a5cd6962201efeefa2d00e094..3636c054dcd526202a3028c389c8515a450ffa98 100644 (file)
@@ -143,6 +143,7 @@ do {                                                                        \
                "       mov     %0,epsw         \n"                     \
                : "=&d"(tmp)                                            \
                : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw)        \
+               : "cc"                                                  \
                );                                                      \
 } while (0)
 
index e0239865abcbe28946e82f6fa0c5d5900a42464b..1a7e29281c5d0642ca0e66b91ca054f8353989b1 100644 (file)
@@ -22,7 +22,7 @@ do {                                                          \
                 "      mov %0,%1               \n"             \
                 : "=d"(w)                                      \
                 : "m"(MMUCTR), "i"(MMUCTR_IIV|MMUCTR_DIV)      \
-                : "memory"                                     \
+                : "cc", "memory"                               \
                 );                                             \
 } while (0)
 
index 167e10ff06d99ddb57175117e552bb9b4835faa1..197a7af3dd8aeaa7014df5856877de3f0924ee71 100644 (file)
@@ -316,7 +316,7 @@ do {                                                                        \
                        "       .previous\n"                            \
                        : "=a"(__from), "=a"(__to), "=r"(size), "=&r"(w)\
                        : "0"(__from), "1"(__to), "2"(size)             \
-                       : "memory");                                    \
+                       : "cc", "memory");                              \
        }                                                               \
 } while (0)
 
@@ -352,7 +352,7 @@ do {                                                                        \
                        "       .previous\n"                            \
                        : "=a"(__from), "=a"(__to), "=r"(size), "=&r"(w)\
                        : "0"(__from), "1"(__to), "2"(size)             \
-                       : "memory");                                    \
+                       : "cc", "memory");                              \
        }                                                               \
 } while (0)
 
index 2a983931c11f492958e606510b4d25b56a4d3f17..c05acb95c2a9385b392502c300d4338f208ba88f 100644 (file)
 #define __NR_pwritev           335
 #define __NR_rt_tgsigqueueinfo 336
 #define __NR_perf_event_open   337
+#define __NR_recvmmsg          338
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 338
+#define NR_syscalls 339
 
 /*
  * specify the deprecated syscalls we want to support on this arch
index c9ee6c009d795aa1fde9c44b2bc56b5a5f1beba5..88e3e1c3cc217eb44176aa315266c04c818fda5f 100644 (file)
@@ -724,6 +724,7 @@ ENTRY(sys_call_table)
        .long sys_pwritev               /* 335 */
        .long sys_rt_tgsigqueueinfo
        .long sys_perf_event_open
+       .long sys_recvmmsg
 
 
 nr_syscalls=(.-sys_call_table)/4
index 229b710fc5d5a65c0c6ed20f269fbb60dc709e31..ef34d5a0f8bd35c8d88cf1e46c54455d0cc97b31 100644 (file)
@@ -380,7 +380,8 @@ static int mask_test_and_clear(volatile u8 *ptr, u8 mask)
        u32 epsw;
        asm volatile("  bclr    %1,(%2)         \n"
                     "  mov     epsw,%0         \n"
-                    : "=d"(epsw) : "d"(mask), "a"(ptr));
+                    : "=d"(epsw) : "d"(mask), "a"(ptr)
+                    : "cc", "memory");
        return !(epsw & EPSW_FLAG_Z);
 }
 
index a21f43bc68e269cf412e6ae3b0c0293c0dcd96c0..717db14c2cc32d8905a45e6cfae4bf2a00d38abd 100644 (file)
@@ -264,7 +264,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
 
        /* this is the X/Open sanctioned signal stack switching.  */
        if (ka->sa.sa_flags & SA_ONSTACK) {
-               if (!on_sig_stack(sp))
+               if (sas_ss_flags(sp) == 0)
                        sp = current->sas_ss_sp + current->sas_ss_size;
        }
 
index 274f29ec33c1de3d0e9070bddad0570a07716056..b6580f5d89eef78aa00a9ad0e68ab76002af6704 100644 (file)
@@ -22,6 +22,7 @@ static inline unsigned short from32to16(__wsum sum)
            "   addc    0xffff,%0       \n"
            : "=r" (sum)
            : "r" (sum << 16), "0" (sum & 0xffff0000)
+           : "cc"
            );
        return sum >> 16;
 }
index cce66bc0822d71c1ca41f4ab91d441df9b355b62..fdf6f710f94ec388f8c230afc8bff6139cc6295b 100644 (file)
@@ -28,7 +28,8 @@ void __delay(unsigned long loops)
                "2:     add     -1,%0   \n"
                "       bne     2b      \n"
                : "=&d" (d0)
-               : "0" (loops));
+               : "0" (loops)
+               : "cc");
 }
 EXPORT_SYMBOL(__delay);
 
index a75b203059c1b358434f616ae7b3a7243cb65d33..7826e6c364e74f0075e43081e5db367062baef30 100644 (file)
@@ -62,7 +62,7 @@ do {                                                          \
                "       .previous"                              \
                :"=&r"(res), "=r"(count), "=&r"(w)              \
                :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst)   \
-               :"memory");                                     \
+               : "memory", "cc");                                      \
 } while (0)
 
 long
@@ -109,7 +109,7 @@ do {                                                \
                ".previous\n"                   \
                : "+r"(size), "=&r"(w)          \
                : "a"(addr), "d"(0)             \
-               : "memory");                    \
+               : "memory", "cc");              \
 } while (0)
 
 unsigned long
@@ -161,6 +161,6 @@ long strnlen_user(const char *s, long n)
                ".previous\n"
                :"=d"(res), "=&r"(w)
                :"0"(0), "a"(s), "r"(n)
-               :"memory");
+               : "memory", "cc");
        return res;
 }
index f3649d8f50e363b701de98092455aa63a0e6917c..ee82d624b3c63e8f034112b88729c41fd2a4e161 100644 (file)
 #include <linux/pci.h>
 #include <asm/io.h>
 
+static unsigned long pci_sram_allocated = 0xbc000000;
+
 void *dma_alloc_coherent(struct device *dev, size_t size,
                         dma_addr_t *dma_handle, int gfp)
 {
        unsigned long addr;
        void *ret;
 
+       printk("dma_alloc_coherent(%s,%zu,,%x)\n", dev_name(dev), size, gfp);
+
+       if (0xbe000000 - pci_sram_allocated >= size) {
+               size = (size + 255) & ~255;
+               addr = pci_sram_allocated;
+               pci_sram_allocated += size;
+               ret = (void *) addr;
+               goto done;
+       }
+
        /* ignore region specifiers */
        gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
@@ -41,7 +53,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
        /* write back and evict all cache lines covering this region */
        mn10300_dcache_flush_inv_range2(virt_to_phys((void *) addr), PAGE_SIZE);
 
+done:
        *dma_handle = virt_to_bus((void *) addr);
+       printk("dma_alloc_coherent() = %p [%x]\n", ret, *dma_handle);
        return ret;
 }
 EXPORT_SYMBOL(dma_alloc_coherent);
@@ -51,6 +65,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
 {
        unsigned long addr = (unsigned long) vaddr & ~0x20000000;
 
+       if (addr >= 0x9c000000)
+               return;
+
        free_pages(addr, get_order(size));
 }
 EXPORT_SYMBOL(dma_free_coherent);
index ec1420562dc7d5e2789a025fa246abf1a5608e61..dd27a9a35152ff9ab853cd381c035890cb77a176 100644 (file)
@@ -118,8 +118,7 @@ void __init mem_init(void)
               reservedpages << (PAGE_SHIFT - 10),
               datasize >> 10,
               initsize >> 10,
-              (unsigned long) (totalhigh_pages << (PAGE_SHIFT - 10))
-              );
+              totalhigh_pages << (PAGE_SHIFT - 10));
 }
 
 /*
index 30016251f658507ec5a6501c35028dd74be22716..6dffbf97ac2601d40ceb91a2e4a5116fd1bceeb8 100644 (file)
@@ -633,13 +633,13 @@ static int misalignment_addr(unsigned long *registers, unsigned long sp,
                        goto displace_or_inc;
                case SD24:
                        tmp = disp << 8;
-                       asm("asr 8,%0" : "=r"(tmp) : "0"(tmp));
+                       asm("asr 8,%0" : "=r"(tmp) : "0"(tmp) : "cc");
                        disp = (long) tmp;
                        goto displace_or_inc;
                case SIMM4_2:
                        tmp = opcode >> 4 & 0x0f;
                        tmp <<= 28;
-                       asm("asr 28,%0" : "=r"(tmp) : "0"(tmp));
+                       asm("asr 28,%0" : "=r"(tmp) : "0"(tmp) : "cc");
                        disp = (long) tmp;
                        goto displace_or_inc;
                case IMM8:
index 3bfc909387873d0586a34a4a1a38541e83eb5dd5..8086cc092cecca946aac943387c0a019e8be8c4a 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef _ASM_UNIT_SERIAL_H
 #define _ASM_UNIT_SERIAL_H
 
-#include <asm/cpu/cpu-regs.h>
+#include <asm/cpu-regs.h>
 #include <proc/irq.h>
 #include <linux/serial_reg.h>
 
index a71c49aa85ebff419664b4db389788b8be5ad94f..d1c72d59fa9fa92e4ce0710979c14b9c879d5e6d 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/irq.h>
 #endif /* __ASSEMBLY__ */
 
-#include <asm/cpu/timer-regs.h>
+#include <asm/timer-regs.h>
 #include <unit/clock.h>
 
 /*
index d345ff9042d5943853769b581af0301b7ae7936f..6f8de99540263a2f68a52d3fab69ed5db1eb3b81 100644 (file)
@@ -13,8 +13,8 @@
 #include <linux/init.h>
 #include <asm/io.h>
 #include <asm/processor.h>
-#include <asm/cpu/intctl-regs.h>
-#include <asm/cpu/rtc-regs.h>
+#include <asm/intctl-regs.h>
+#include <asm/rtc-regs.h>
 #include <unit/leds.h>
 
 static const u8 asb2305_led_hex_tbl[16] = {
index d100ca7884681e95bc28c213d963185c3ed68f68..78cd134ddf7dc19f5c51b4ebd5ce48f8c9d01847 100644 (file)
@@ -218,45 +218,6 @@ void __init pcibios_resource_survey(void)
        pcibios_allocate_resources(1);
 }
 
-int pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
-       u16 cmd, old_cmd;
-       int idx;
-       struct resource *r;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       old_cmd = cmd;
-
-       for (idx = 0; idx < 6; idx++) {
-               /* Only set up the requested stuff */
-               if (!(mask & (1 << idx)))
-                       continue;
-
-               r = &dev->resource[idx];
-
-               if (!r->start && r->end) {
-                       printk(KERN_ERR
-                              "PCI: Device %s not available because of"
-                              " resource collisions\n",
-                              pci_name(dev));
-                       return -EINVAL;
-               }
-
-               if (r->flags & IORESOURCE_IO)
-                       cmd |= PCI_COMMAND_IO;
-               if (r->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-
-       if (dev->resource[PCI_ROM_RESOURCE].start)
-               cmd |= PCI_COMMAND_MEMORY;
-
-       if (cmd != old_cmd)
-               pci_write_config_word(dev, PCI_COMMAND, cmd);
-
-       return 0;
-}
-
 /*
  *  If we set up a device for bus mastering, we need to check the latency
  *  timer as certain crappy BIOSes forget to set it properly.
index 9763d1ce343a6f601d69bc6a21df9b8de4b98592..c3fa294b6e2840ecb39556c6064cfde2ae68797e 100644 (file)
@@ -34,7 +34,6 @@ extern unsigned int pci_probe;
 extern unsigned int pcibios_max_latency;
 
 extern void pcibios_resource_survey(void);
-extern int pcibios_enable_resources(struct pci_dev *dev, int mask);
 
 /* pci.c */
 
index 07dbbcda3b2e5dc57f71ee2ba376f6da83010d63..2cb7e75ba1c0164bf34a0174adc67b136a847e08 100644 (file)
@@ -26,6 +26,29 @@ int pcibios_last_bus = -1;
 struct pci_bus *pci_root_bus;
 struct pci_ops *pci_root_ops;
 
+/*
+ * The accessible PCI window does not cover the entire CPU address space, but
+ * there are devices we want to access outside of that window, so we need to
+ * insert specific PCI bus resources instead of using the platform-level bus
+ * resources directly for the PCI root bus.
+ *
+ * These are configured and inserted by pcibios_init() and are attached to the
+ * root bus by pcibios_fixup_bus().
+ */
+static struct resource pci_ioport_resource = {
+       .name   = "PCI IO",
+       .start  = 0xbe000000,
+       .end    = 0xbe03ffff,
+       .flags  = IORESOURCE_IO,
+};
+
+static struct resource pci_iomem_resource = {
+       .name   = "PCI mem",
+       .start  = 0xb8000000,
+       .end    = 0xbbffffff,
+       .flags  = IORESOURCE_MEM,
+};
+
 /*
  * Functions for accessing PCI configuration space
  */
@@ -279,7 +302,7 @@ static int __init pci_sanity_check(struct pci_ops *o)
             (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)))
                return 1;
 
-       printk(KERN_ERROR "PCI: Sanity check failed\n");
+       printk(KERN_ERR "PCI: Sanity check failed\n");
        return 0;
 }
 
@@ -297,6 +320,7 @@ static int __init pci_check_direct(void)
                printk(KERN_INFO "PCI: Using configuration ampci\n");
                request_mem_region(0xBE040000, 256, "AMPCI bridge");
                request_mem_region(0xBFFFFFF4, 12, "PCI ampci");
+               request_mem_region(0xBC000000, 32 * 1024 * 1024, "PCI SRAM");
                return 0;
        }
 
@@ -358,6 +382,11 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
+       if (bus->number == 0) {
+               bus->resource[0] = &pci_ioport_resource;
+               bus->resource[1] = &pci_iomem_resource;
+       }
+
        if (bus->self) {
                pci_read_bridge_bases(bus);
                pcibios_fixup_device_resources(bus->self);
@@ -380,6 +409,11 @@ static int __init pcibios_init(void)
        iomem_resource.start    = 0xA0000000;
        iomem_resource.end      = 0xDFFFFFFF;
 
+       if (insert_resource(&iomem_resource, &pci_iomem_resource) < 0)
+               panic("Unable to insert PCI IOMEM resource\n");
+       if (insert_resource(&ioport_resource, &pci_ioport_resource) < 0)
+               panic("Unable to insert PCI IOPORT resource\n");
+
        if (!pci_probe)
                return 0;
 
@@ -391,32 +425,11 @@ static int __init pcibios_init(void)
        printk(KERN_INFO "PCI: Probing PCI hardware [mempage %08x]\n",
               MEM_PAGING_REG);
 
-       {
-#if 0
-               static struct pci_bus am33_root_bus = {
-                       .children  = LIST_HEAD_INIT(am33_root_bus.children),
-                       .devices   = LIST_HEAD_INIT(am33_root_bus.devices),
-                       .number    = 0,
-                       .secondary = 0,
-                       .resource = { &ioport_resource, &iomem_resource },
-               };
-
-               am33_root_bus.ops = pci_root_ops;
-               list_add_tail(&am33_root_bus.node, &pci_root_buses);
-
-               am33_root_bus.subordinate = pci_do_scan_bus(0);
-
-               pci_root_bus = &am33_root_bus;
-#else
-               pci_root_bus = pci_scan_bus(0, &pci_direct_ampci, NULL);
-#endif
-       }
+       pci_root_bus = pci_scan_bus(0, &pci_direct_ampci, NULL);
 
        pcibios_irq_init();
        pcibios_fixup_irqs();
-#if 0
        pcibios_resource_survey();
-#endif
        return 0;
 }
 
@@ -440,7 +453,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
        int err;
 
-       err = pcibios_enable_resources(dev, mask);
+       err = pci_enable_resources(dev, mask);
        if (err == 0)
                pcibios_enable_irq(dev);
        return err;
@@ -455,6 +468,7 @@ static void __init unit_disable_pcnet(struct pci_bus *bus, struct pci_ops *o)
 
        bus->number = 0;
 
+       o->read (bus, PCI_DEVFN(2, 0), PCI_VENDOR_ID,           4, &x);
        o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND,             2, &x);
        x |= PCI_COMMAND_MASTER |
                PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
index 1c452cc3f6e99c783dd108df11e80ebabd3af4fc..a76c8e0ab90ff3aaf9a30d573b01259911d53edd 100644 (file)
@@ -15,9 +15,8 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <asm/processor.h>
-#include <asm/cpu/intctl-regs.h>
-#include <asm/cpu/rtc-regs.h>
-#include <asm/cpu/serial-regs.h>
+#include <asm/intctl-regs.h>
+#include <asm/serial-regs.h>
 #include <unit/serial.h>
 
 /*
index bb2465bcb32766598c663ddca9d0893399891564..826a30a00f5966386fb98140787657a1e7088859 100644 (file)
@@ -20,7 +20,7 @@
 all: $(obj)/zImage
 
 BOOTCFLAGS    := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-                -fno-strict-aliasing -Os -msoft-float -pipe \
+                -fno-strict-aliasing -Os -msoft-float -pipe -D__KERNEL__\
                 -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \
                 -isystem $(shell $(CROSS32CC) -print-file-name=include)
 BOOTAFLAGS     := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
@@ -34,6 +34,8 @@ BOOTCFLAGS    += -fno-stack-protector
 endif
 
 BOOTCFLAGS     += -I$(obj) -I$(srctree)/$(obj)
+BOOTCFLAGS     += -include include/linux/autoconf.h -Iarch/powerpc/include
+BOOTCFLAGS     += -Iinclude
 
 DTS_FLAGS      ?= -p 1024
 
index e8dfdbd9327aec5c2fe3fc77903d4a1b9155e694..cadbed679fbbc17cc8cac85426a50c6cc631db34 100644 (file)
@@ -1107,6 +1107,12 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
        list_for_each_entry(dev, &bus->devices, bus_list) {
                struct dev_archdata *sd = &dev->dev.archdata;
 
+               /* Cardbus can call us to add new devices to a bus, so ignore
+                * those who are already fully discovered
+                */
+               if (dev->is_added)
+                       continue;
+
                /* Setup OF node pointer in archdata */
                sd->of_node = pci_device_to_OF_node(dev);
 
@@ -1147,6 +1153,13 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
+void __devinit pci_fixup_cardbus(struct pci_bus *bus)
+{
+       /* Now fixup devices on that bus */
+       pcibios_setup_bus_devices(bus);
+}
+
+
 static int skip_isa_ioresource_align(struct pci_dev *dev)
 {
        if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
index 5598f88f142e6332877e7a4a84947fbba93b9dc6..e4beeb371a732fecdf3fc5fe1291ae01aa40b2a6 100644 (file)
@@ -390,6 +390,26 @@ static void kvmppc_mmu_book3s_64_mtsrin(struct kvm_vcpu *vcpu, u32 srnum,
 {
        u64 rb = 0, rs = 0;
 
+       /*
+        * According to Book3 2.01 mtsrin is implemented as:
+        *
+        * The SLB entry specified by (RB)32:35 is loaded from register
+        * RS, as follows.
+        *
+        * SLBE Bit     Source                  SLB Field
+        *
+        * 0:31         0x0000_0000             ESID-0:31
+        * 32:35        (RB)32:35               ESID-32:35
+        * 36           0b1                     V
+        * 37:61        0x00_0000|| 0b0         VSID-0:24
+        * 62:88        (RS)37:63               VSID-25:51
+        * 89:91        (RS)33:35               Ks Kp N
+        * 92           (RS)36                  L ((RS)36 must be 0b0)
+        * 93           0b0                     C
+        */
+
+       dprintk("KVM MMU: mtsrin(0x%x, 0x%lx)\n", srnum, value);
+
        /* ESID = srnum */
        rb |= (srnum & 0xf) << 28;
        /* Set the valid bit */
@@ -400,7 +420,7 @@ static void kvmppc_mmu_book3s_64_mtsrin(struct kvm_vcpu *vcpu, u32 srnum,
        /* VSID = VSID */
        rs |= (value & 0xfffffff) << 12;
        /* flags = flags */
-       rs |= ((value >> 27) & 0xf) << 9;
+       rs |= ((value >> 28) & 0x7) << 9;
 
        kvmppc_mmu_book3s_64_slbmte(vcpu, rs, rb);
 }
index f4e53c6708dcbe2fc33cba2f077b21bc9c0caf5c..b416aa11b91eb506a0d5c6bcbc1108ae231e664f 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.31
-# Tue Sep 22 17:43:13 2009
+# Linux kernel version: 2.6.33-rc2
+# Mon Jan  4 09:03:07 2010
 #
 CONFIG_SCHED_MC=y
 CONFIG_MMU=y
@@ -51,6 +51,7 @@ CONFIG_AUDIT=y
 #
 CONFIG_TREE_RCU=y
 # CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
 # CONFIG_RCU_TRACE is not set
 CONFIG_RCU_FANOUT=64
 # CONFIG_RCU_FANOUT_EXACT is not set
@@ -113,7 +114,6 @@ CONFIG_HAVE_PERF_EVENTS=y
 # CONFIG_PERF_EVENTS is not set
 # CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -149,21 +149,78 @@ CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
 CONFIG_BLK_DEV_BSG=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CGROUP is not set
 CONFIG_BLOCK_COMPAT=y
 
 #
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
+# CONFIG_CFQ_GROUP_IOSCHED is not set
 CONFIG_DEFAULT_DEADLINE=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="deadline"
 CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_ARCH_INLINE_SPIN_TRYLOCK=y
+CONFIG_ARCH_INLINE_SPIN_TRYLOCK_BH=y
+CONFIG_ARCH_INLINE_SPIN_LOCK=y
+CONFIG_ARCH_INLINE_SPIN_LOCK_BH=y
+CONFIG_ARCH_INLINE_SPIN_LOCK_IRQ=y
+CONFIG_ARCH_INLINE_SPIN_LOCK_IRQSAVE=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_BH=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE=y
+CONFIG_ARCH_INLINE_READ_TRYLOCK=y
+CONFIG_ARCH_INLINE_READ_LOCK=y
+CONFIG_ARCH_INLINE_READ_LOCK_BH=y
+CONFIG_ARCH_INLINE_READ_LOCK_IRQ=y
+CONFIG_ARCH_INLINE_READ_LOCK_IRQSAVE=y
+CONFIG_ARCH_INLINE_READ_UNLOCK=y
+CONFIG_ARCH_INLINE_READ_UNLOCK_BH=y
+CONFIG_ARCH_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_ARCH_INLINE_READ_UNLOCK_IRQRESTORE=y
+CONFIG_ARCH_INLINE_WRITE_TRYLOCK=y
+CONFIG_ARCH_INLINE_WRITE_LOCK=y
+CONFIG_ARCH_INLINE_WRITE_LOCK_BH=y
+CONFIG_ARCH_INLINE_WRITE_LOCK_IRQ=y
+CONFIG_ARCH_INLINE_WRITE_LOCK_IRQSAVE=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_BH=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE=y
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
 CONFIG_FREEZER=y
 
 #
@@ -227,14 +284,13 @@ CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTPLUG_SPARSE=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_SPLIT_PTLOCK_CPUS=999999
 CONFIG_MIGRATION=y
 CONFIG_PHYS_ADDR_T_64BIT=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_HAVE_MLOCK=y
-CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
 CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
@@ -339,6 +395,7 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=y
 CONFIG_INET6_XFRM_MODE_BEET=y
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
 CONFIG_IPV6_NDISC_NODETYPE=y
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
@@ -504,6 +561,10 @@ CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=m
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_OSD is not set
 CONFIG_BLK_DEV_RAM=y
@@ -710,7 +771,6 @@ CONFIG_S390_VMUR=m
 # CONFIG_PPS is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 # CONFIG_REGULATOR is not set
 # CONFIG_MEMSTICK is not set
@@ -864,6 +924,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=2048
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
@@ -931,7 +992,6 @@ CONFIG_BRANCH_PROFILE_NONE=y
 CONFIG_SAMPLES=y
 # CONFIG_SAMPLE_KOBJECT is not set
 # CONFIG_SAMPLE_KPROBES is not set
-# CONFIG_KMEMCHECK is not set
 
 #
 # Security options
@@ -939,7 +999,11 @@ CONFIG_SAMPLES=y
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
 CONFIG_CRYPTO=y
 
 #
index 34aaa4603347f46f4125a2d787ef256a854037d3..c616821bf2ac46dcbf018ed8adfb274b1db10dde 100644 (file)
@@ -1,30 +1,6 @@
-/*
- *  include/asm-s390/param.h
- *
- *  S390 version
- *
- *  Derived from "include/asm-i386/param.h"
- */
-
 #ifndef _ASMS390_PARAM_H
 #define _ASMS390_PARAM_H
 
-#ifdef __KERNEL__
-# define HZ            CONFIG_HZ       /* Internal kernel timer frequency */
-# define USER_HZ       100             /* .. some user interfaces are in "ticks" */
-# define CLOCKS_PER_SEC        (USER_HZ)       /* like times() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE  4096
-
-#ifndef NOGROUP
-#define NOGROUP                (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64      /* max length of hostname */
+#include <asm-generic/param.h>
 
-#endif
+#endif /* _ASMS390_PARAM_H */
index 8c15b2c85d5a1d6afb6d7996f16b08948a21baee..dfaf458d6702459ba9b5f85d7be5e30b1528a2ba 100644 (file)
@@ -106,7 +106,7 @@ void __init mem_init(void)
                        ram << (PAGE_SHIFT-10), codesize >> 10,
                        reservedpages << (PAGE_SHIFT-10), datasize >> 10,
                        initsize >> 10,
-                       (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+                       totalhigh_pages << (PAGE_SHIFT-10));
 }
 #endif /* !CONFIG_NEED_MULTIPLE_NODES */
 
index ae6c73689036ced70c2fa8740a9ced72426cb84d..4eaf3401a15e732256c4f2923fd94662ba1ce24c 100644 (file)
@@ -42,6 +42,8 @@ config SUPERH32
        select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_ARCH_KGDB
+       select HAVE_HW_BREAKPOINT
+       select PERF_EVENTS if HAVE_HW_BREAKPOINT
        select ARCH_HIBERNATION_POSSIBLE if MMU
 
 config SUPERH64
index e121c30f797d8e54a4254ab5b8a9b1cdfaf0bb4f..46cb93477bcb1f11a1994c8950bc5b40e61ab346 100644 (file)
@@ -1,6 +1,8 @@
 include include/asm-generic/Kbuild.asm
 
-header-y += cachectl.h cpu-features.h
+header-y += cachectl.h
+header-y += cpu-features.h
+header-y += hw_breakpoint.h
 
 unifdef-y += unistd_32.h
 unifdef-y += unistd_64.h
index fb6bbb9b1cc8e704191f5a6fb73ce001d3c9644f..06c4281aab65604af414c5081dde2b9871a3f952 100644 (file)
@@ -2,8 +2,8 @@
 #define __ASM_SH_FPU_H
 
 #ifndef __ASSEMBLY__
-#include <linux/preempt.h>
-#include <asm/ptrace.h>
+
+struct task_struct;
 
 #ifdef CONFIG_SH_FPU
 static inline void release_fpu(struct pt_regs *regs)
@@ -16,22 +16,23 @@ static inline void grab_fpu(struct pt_regs *regs)
        regs->sr &= ~SR_FD;
 }
 
-struct task_struct;
-
 extern void save_fpu(struct task_struct *__tsk);
-void fpu_state_restore(struct pt_regs *regs);
+extern void restore_fpu(struct task_struct *__tsk);
+extern void fpu_state_restore(struct pt_regs *regs);
+extern void __fpu_state_restore(void);
 #else
-
-#define save_fpu(tsk)          do { } while (0)
-#define release_fpu(regs)      do { } while (0)
-#define grab_fpu(regs)         do { } while (0)
-#define fpu_state_restore(regs)        do { } while (0)
-
+#define save_fpu(tsk)                  do { } while (0)
+#define restore_fpu(tsk)               do { } while (0)
+#define release_fpu(regs)              do { } while (0)
+#define grab_fpu(regs)                 do { } while (0)
+#define fpu_state_restore(regs)                do { } while (0)
+#define __fpu_state_restore(regs)      do { } while (0)
 #endif
 
 struct user_regset;
 
 extern int do_fpu_inst(unsigned short, struct pt_regs *);
+extern int init_fpu(struct task_struct *);
 
 extern int fpregs_get(struct task_struct *target,
                      const struct user_regset *regset,
@@ -65,18 +66,6 @@ static inline void clear_fpu(struct task_struct *tsk, struct pt_regs *regs)
        preempt_enable();
 }
 
-static inline int init_fpu(struct task_struct *tsk)
-{
-       if (tsk_used_math(tsk)) {
-               if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
-                       unlazy_fpu(tsk, task_pt_regs(tsk));
-               return 0;
-       }
-
-       set_stopped_child_used_math(tsk);
-       return 0;
-}
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_SH_FPU_H */
diff --git a/arch/sh/include/asm/hw_breakpoint.h b/arch/sh/include/asm/hw_breakpoint.h
new file mode 100644 (file)
index 0000000..7295d62
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef __ASM_SH_HW_BREAKPOINT_H
+#define __ASM_SH_HW_BREAKPOINT_H
+
+#include <linux/kdebug.h>
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+#define __ARCH_HW_BREAKPOINT_H
+
+struct arch_hw_breakpoint {
+       char            *name; /* Contains name of the symbol to set bkpt */
+       unsigned long   address;
+       u16             len;
+       u16             type;
+};
+
+enum {
+       SH_BREAKPOINT_READ      = (1 << 1),
+       SH_BREAKPOINT_WRITE     = (1 << 2),
+       SH_BREAKPOINT_RW        = SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
+
+       SH_BREAKPOINT_LEN_1     = (1 << 12),
+       SH_BREAKPOINT_LEN_2     = (1 << 13),
+       SH_BREAKPOINT_LEN_4     = SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
+       SH_BREAKPOINT_LEN_8     = (1 << 14),
+};
+
+struct sh_ubc {
+       const char      *name;
+       unsigned int    num_events;
+       unsigned int    trap_nr;
+       void            (*enable)(struct arch_hw_breakpoint *, int);
+       void            (*disable)(struct arch_hw_breakpoint *, int);
+       void            (*enable_all)(unsigned long);
+       void            (*disable_all)(void);
+       unsigned long   (*active_mask)(void);
+       unsigned long   (*triggered_mask)(void);
+       void            (*clear_triggered_mask)(unsigned long);
+       struct clk      *clk;   /* optional interface clock / MSTP bit */
+};
+
+struct perf_event;
+struct task_struct;
+struct pmu;
+
+/* Maximum number of UBC channels */
+#define HBP_NUM                2
+
+/* arch/sh/kernel/hw_breakpoint.c */
+extern int arch_check_va_in_userspace(unsigned long va, u16 hbp_len);
+extern int arch_validate_hwbkpt_settings(struct perf_event *bp,
+                                        struct task_struct *tsk);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+                                          unsigned long val, void *data);
+
+int arch_install_hw_breakpoint(struct perf_event *bp);
+void arch_uninstall_hw_breakpoint(struct perf_event *bp);
+void hw_breakpoint_pmu_read(struct perf_event *bp);
+void hw_breakpoint_pmu_unthrottle(struct perf_event *bp);
+
+extern void arch_fill_perf_breakpoint(struct perf_event *bp);
+extern int register_sh_ubc(struct sh_ubc *);
+
+extern struct pmu perf_ops_bp;
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_HW_BREAKPOINT_H */
index 985219f9759ef0aaa908e7308930627730498d6c..5f6d2e9ccb7c24f16e4420ab3153d5746e0d66e9 100644 (file)
@@ -6,6 +6,8 @@ enum die_val {
        DIE_TRAP,
        DIE_NMI,
        DIE_OOPS,
+       DIE_BREAKPOINT,
+       DIE_SSTEP,
 };
 
 #endif /* __ASM_SH_KDEBUG_H */
index 1f3d6fab660c9bf1ecebb76e3bd3a60f8445dbe4..5fd83125fb89b62e633f6289d33950a27bcb226b 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/page.h>
 #include <asm/types.h>
 #include <asm/ptrace.h>
+#include <asm/hw_breakpoint.h>
 
 /*
  * Default implementation of macro that returns current
@@ -90,48 +91,40 @@ struct sh_fpu_soft_struct {
        unsigned long entry_pc;
 };
 
-union sh_fpu_union {
-       struct sh_fpu_hard_struct hard;
-       struct sh_fpu_soft_struct soft;
+union thread_xstate {
+       struct sh_fpu_hard_struct hardfpu;
+       struct sh_fpu_soft_struct softfpu;
 };
 
+extern unsigned int xstate_size;
+extern void free_thread_xstate(struct task_struct *);
+extern struct kmem_cache *task_xstate_cachep;
+
 struct thread_struct {
        /* Saved registers when thread is descheduled */
        unsigned long sp;
        unsigned long pc;
 
-       /* Hardware debugging registers */
-       unsigned long ubc_pc;
-
-       /* floating point info */
-       union sh_fpu_union fpu;
+       /* Save middle states of ptrace breakpoints */
+       struct perf_event       *ptrace_bps[HBP_NUM];
 
 #ifdef CONFIG_SH_DSP
        /* Dsp status information */
        struct sh_dsp_struct dsp_status;
 #endif
-};
 
-/* Count of active tasks with UBC settings */
-extern int ubc_usercnt;
+       /* Extended processor state */
+       union thread_xstate *xstate;
+};
 
 #define INIT_THREAD  {                                         \
        .sp = sizeof(init_stack) + (long) &init_stack,          \
 }
 
-/*
- * Do necessary setup to start up a newly executed thread.
- */
-#define start_thread(_regs, new_pc, new_sp)     \
-       set_fs(USER_DS);                         \
-       _regs->pr = 0;                           \
-       _regs->sr = SR_FD;      /* User mode. */ \
-       _regs->pc = new_pc;                      \
-       _regs->regs[15] = new_sp
-
 /* Forward declaration, a strange C thing */
 struct task_struct;
-struct mm_struct;
+
+extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned long new_sp);
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
index 1dc12cb44a2d7acfa6b918c0f14e5487ed8785ff..201d11ef211f1311152e911b10ff13ff6fff155b 100644 (file)
@@ -124,6 +124,12 @@ struct task_struct;
 extern void user_enable_single_step(struct task_struct *);
 extern void user_disable_single_step(struct task_struct *);
 
+struct perf_event;
+struct perf_sample_data;
+
+extern void ptrace_triggered(struct perf_event *bp, int nmi,
+                     struct perf_sample_data *data, struct pt_regs *regs);
+
 #define task_pt_regs(task) \
        ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE) - 1)
 
index b74d2532cc27427f044207236eac4da3cf19783d..62e4fc1e4409d923910e460dc344033a579ae398 100644 (file)
@@ -144,8 +144,6 @@ void per_cpu_trap_init(void);
 void default_idle(void);
 void cpu_idle_wait(void);
 
-asmlinkage void break_point_trap(void);
-
 #ifdef CONFIG_SUPERH32
 #define BUILD_TRAP_HANDLER(name)                                       \
 asmlinkage void name##_trap_handler(unsigned long r4, unsigned long r5,        \
index 1f3d927e22659c1a99564958a584db4aafe042c2..55a36fef6875d2cb3bb985143d3ea07781887e76 100644 (file)
@@ -93,14 +93,16 @@ static inline struct thread_info *current_thread_info(void)
 
 #define THREAD_SIZE_ORDER      (THREAD_SHIFT - PAGE_SHIFT)
 
-#else /* THREAD_SHIFT < PAGE_SHIFT */
-
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+#endif
 
 extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
 extern void free_thread_info(struct thread_info *ti);
+extern void arch_task_cache_init(void);
+#define arch_task_cache_init arch_task_cache_init
+extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
+extern void init_thread_xstate(void);
 
-#endif /* THREAD_SHIFT < PAGE_SHIFT */
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/sh/include/asm/ubc.h b/arch/sh/include/asm/ubc.h
deleted file mode 100644 (file)
index 9bf9616..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * include/asm-sh/ubc.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2002, 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_SH_UBC_H
-#define __ASM_SH_UBC_H
-#ifdef __KERNEL__
-
-#include <cpu/ubc.h>
-
-/* User Break Controller */
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
-#define UBC_TYPE_SH7729        (current_cpu_data.type == CPU_SH7729)
-#else
-#define UBC_TYPE_SH7729        0
-#endif
-
-#define BAMR_ASID              (1 << 2)
-#define BAMR_NONE              0
-#define BAMR_10                        0x1
-#define BAMR_12                        0x2
-#define BAMR_ALL               0x3
-#define BAMR_16                        0x8
-#define BAMR_20                        0x9
-
-#define BBR_INST               (1 << 4)
-#define BBR_DATA               (2 << 4)
-#define BBR_READ               (1 << 2)
-#define BBR_WRITE              (2 << 2)
-#define BBR_BYTE               0x1
-#define BBR_HALF               0x2
-#define BBR_LONG               0x3
-#define BBR_QUAD               (1 << 6)        /* SH7750 */
-#define BBR_CPU                        (1 << 6)        /* SH7709A,SH7729 */
-#define BBR_DMA                        (2 << 6)        /* SH7709A,SH7729 */
-
-#define BRCR_CMFA              (1 << 15)
-#define BRCR_CMFB              (1 << 14)
-
-#if defined CONFIG_CPU_SH2A
-#define BRCR_CMFCA             (1 << 15)
-#define BRCR_CMFCB             (1 << 14)
-#define BRCR_CMFDA             (1 << 13)
-#define BRCR_CMFDB             (1 << 12)
-#define BRCR_PCBB              (1 << 6)        /* 1: after execution */
-#define BRCR_PCBA              (1 << 5)        /* 1: after execution */
-#define BRCR_PCTE              0
-#else
-#define BRCR_PCTE              (1 << 11)
-#define BRCR_PCBA              (1 << 10)       /* 1: after execution */
-#define BRCR_DBEB              (1 << 7)
-#define BRCR_PCBB              (1 << 6)
-#define BRCR_SEQ               (1 << 3)
-#define BRCR_UBDE              (1 << 0)
-#endif
-
-#endif /* __KERNEL__ */
-#endif /* __ASM_SH_UBC_H */
diff --git a/arch/sh/include/cpu-sh2/cpu/ubc.h b/arch/sh/include/cpu-sh2/cpu/ubc.h
deleted file mode 100644 (file)
index ba0e87f..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * include/asm-sh/cpu-sh2/ubc.h
- *
- * Copyright (C) 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_CPU_SH2_UBC_H
-#define __ASM_CPU_SH2_UBC_H
-
-#define UBC_BARA                0xffffff40
-#define UBC_BAMRA               0xffffff44
-#define UBC_BBRA                0xffffff48
-#define UBC_BARB                0xffffff60
-#define UBC_BAMRB               0xffffff64
-#define UBC_BBRB                0xffffff68
-#define UBC_BDRB                0xffffff70
-#define UBC_BDMRB               0xffffff74
-#define UBC_BRCR                0xffffff78
-
-/*
- * We don't have any ASID changes to make in the UBC on the SH-2.
- *
- * Make these purposely invalid to track misuse.
- */
-#define UBC_BASRA              0x00000000
-#define UBC_BASRB              0x00000000
-
-#endif /* __ASM_CPU_SH2_UBC_H */
-
diff --git a/arch/sh/include/cpu-sh3/cpu/ubc.h b/arch/sh/include/cpu-sh3/cpu/ubc.h
deleted file mode 100644 (file)
index 4e6381d..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * include/asm-sh/cpu-sh3/ubc.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_CPU_SH3_UBC_H
-#define __ASM_CPU_SH3_UBC_H
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7710) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
-#define UBC_BARA               0xa4ffffb0
-#define UBC_BAMRA              0xa4ffffb4
-#define UBC_BBRA               0xa4ffffb8
-#define UBC_BASRA              0xffffffe4
-#define UBC_BARB               0xa4ffffa0
-#define UBC_BAMRB              0xa4ffffa4
-#define UBC_BBRB               0xa4ffffa8
-#define UBC_BASRB              0xffffffe8
-#define UBC_BDRB               0xa4ffff90
-#define UBC_BDMRB              0xa4ffff94
-#define UBC_BRCR               0xa4ffff98
-#else
-#define UBC_BARA                0xffffffb0
-#define UBC_BAMRA               0xffffffb4
-#define UBC_BBRA                0xffffffb8
-#define UBC_BASRA               0xffffffe4
-#define UBC_BARB                0xffffffa0
-#define UBC_BAMRB               0xffffffa4
-#define UBC_BBRB                0xffffffa8
-#define UBC_BASRB               0xffffffe8
-#define UBC_BDRB                0xffffff90
-#define UBC_BDMRB               0xffffff94
-#define UBC_BRCR                0xffffff98
-#endif
-
-#endif /* __ASM_CPU_SH3_UBC_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/ubc.h b/arch/sh/include/cpu-sh4/cpu/ubc.h
deleted file mode 100644 (file)
index c86e170..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * include/asm-sh/cpu-sh4/ubc.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2003 Paul Mundt
- * Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_CPU_SH4_UBC_H
-#define __ASM_CPU_SH4_UBC_H
-
-#if defined(CONFIG_CPU_SH4A)
-#define UBC_CBR0               0xff200000
-#define UBC_CRR0               0xff200004
-#define UBC_CAR0               0xff200008
-#define UBC_CAMR0              0xff20000c
-#define UBC_CBR1               0xff200020
-#define UBC_CRR1               0xff200024
-#define UBC_CAR1               0xff200028
-#define UBC_CAMR1              0xff20002c
-#define UBC_CDR1               0xff200030
-#define UBC_CDMR1              0xff200034
-#define UBC_CETR1              0xff200038
-#define UBC_CCMFR              0xff200600
-#define UBC_CBCR               0xff200620
-
-/* CBR */
-#define UBC_CBR_AIE            (0x01<<30)
-#define UBC_CBR_ID_INST                (0x01<<4)
-#define UBC_CBR_RW_READ                (0x01<<1)
-#define UBC_CBR_CE             (0x01)
-
-#define        UBC_CBR_AIV_MASK        (0x00FF0000)
-#define        UBC_CBR_AIV_SHIFT       (16)
-#define UBC_CBR_AIV_SET(asid)  (((asid)<<UBC_CBR_AIV_SHIFT) & UBC_CBR_AIV_MASK)
-
-#define UBC_CBR_INIT           0x20000000
-
-/* CRR */
-#define UBC_CRR_RES            (0x01<<13)
-#define UBC_CRR_PCB            (0x01<<1)
-#define UBC_CRR_BIE            (0x01)
-
-#define UBC_CRR_INIT           0x00002000
-
-#else  /* CONFIG_CPU_SH4 */
-#define UBC_BARA               0xff200000
-#define UBC_BAMRA              0xff200004
-#define UBC_BBRA               0xff200008
-#define UBC_BASRA              0xff000014
-#define UBC_BARB               0xff20000c
-#define UBC_BAMRB              0xff200010
-#define UBC_BBRB               0xff200014
-#define UBC_BASRB              0xff000018
-#define UBC_BDRB               0xff200018
-#define UBC_BDMRB              0xff20001c
-#define UBC_BRCR               0xff200020
-#endif /* CONFIG_CPU_SH4 */
-
-#endif /* __ASM_CPU_SH4_UBC_H */
-
index 5bec10c8bd7462b91384cf158b8956ba1e2a33a9..56704a6d723abebdef63a70638aff225db27b5f1 100644 (file)
@@ -13,8 +13,8 @@ CFLAGS_REMOVE_return_address.o = -pg
 
 obj-y  := debugtraps.o dma-nommu.o dumpstack.o                         \
           idle.o io.o io_generic.o irq.o                               \
-          irq_$(BITS).o machvec.o nmi_debug.o process_$(BITS).o        \
-          ptrace_$(BITS).o return_address.o                            \
+          irq_$(BITS).o machvec.o nmi_debug.o process.o                \
+          process_$(BITS).o ptrace_$(BITS).o return_address.o          \
           setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o            \
           syscalls_$(BITS).o time.o topology.o traps.o                 \
           traps_$(BITS).o unwinder.o
@@ -39,6 +39,7 @@ obj-$(CONFIG_HIBERNATION)     += swsusp.o
 obj-$(CONFIG_DWARF_UNWINDER)   += dwarf.o
 obj-$(CONFIG_PERF_EVENTS)      += perf_event.o perf_callchain.o
 
+obj-$(CONFIG_HAVE_HW_BREAKPOINT)               += hw_breakpoint.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += localtimer.o
 
 EXTRA_CFLAGS += -Werror
index d97c803719ecb939431c910d084a3c774b366ddd..0e48bc61c272e4eb4ebc1dfe4e1a8b7c755a0cd5 100644 (file)
@@ -17,5 +17,7 @@ obj-$(CONFIG_ARCH_SHMOBILE)   += shmobile/
 
 obj-$(CONFIG_SH_ADC)           += adc.o
 obj-$(CONFIG_SH_CLK_CPG)       += clock-cpg.o
+obj-$(CONFIG_SH_FPU)           += fpu.o
+obj-$(CONFIG_SH_FPU_EMU)       += fpu.o
 
 obj-y  += irq/ init.o clock.o hwblk.o
diff --git a/arch/sh/kernel/cpu/fpu.c b/arch/sh/kernel/cpu/fpu.c
new file mode 100644 (file)
index 0000000..c23e672
--- /dev/null
@@ -0,0 +1,82 @@
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/fpu.h>
+
+int init_fpu(struct task_struct *tsk)
+{
+       if (tsk_used_math(tsk)) {
+               if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
+                       unlazy_fpu(tsk, task_pt_regs(tsk));
+               return 0;
+       }
+
+       /*
+        * Memory allocation at the first usage of the FPU and other state.
+        */
+       if (!tsk->thread.xstate) {
+               tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
+                                                     GFP_KERNEL);
+               if (!tsk->thread.xstate)
+                       return -ENOMEM;
+       }
+
+       if (boot_cpu_data.flags & CPU_HAS_FPU) {
+               struct sh_fpu_hard_struct *fp = &tsk->thread.xstate->hardfpu;
+               memset(fp, 0, xstate_size);
+               fp->fpscr = FPSCR_INIT;
+       } else {
+               struct sh_fpu_soft_struct *fp = &tsk->thread.xstate->softfpu;
+               memset(fp, 0, xstate_size);
+               fp->fpscr = FPSCR_INIT;
+       }
+
+       set_stopped_child_used_math(tsk);
+       return 0;
+}
+
+#ifdef CONFIG_SH_FPU
+void __fpu_state_restore(void)
+{
+       struct task_struct *tsk = current;
+
+       restore_fpu(tsk);
+
+       task_thread_info(tsk)->status |= TS_USEDFPU;
+       tsk->fpu_counter++;
+}
+
+void fpu_state_restore(struct pt_regs *regs)
+{
+       struct task_struct *tsk = current;
+
+       if (unlikely(!user_mode(regs))) {
+               printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
+               BUG();
+               return;
+       }
+
+       if (!tsk_used_math(tsk)) {
+               /*
+                * does a slab alloc which can sleep
+                */
+               if (init_fpu(tsk)) {
+                       /*
+                        * ran out of memory!
+                        */
+                       do_group_exit(SIGKILL);
+                       return;
+               }
+       }
+
+       grab_fpu(regs);
+
+       __fpu_state_restore();
+}
+
+BUILD_TRAP_HANDLER(fpu_state_restore)
+{
+       TRAP_HANDLER_DECL;
+
+       fpu_state_restore(regs);
+}
+#endif /* CONFIG_SH_FPU */
index 89b4b76c0d763d58f6c77229ddc8963fbc8d5508..a5bb0550bbf32ba3e48ef73a3b5cd2ba8cd42e06 100644 (file)
 #include <asm/elf.h>
 #include <asm/io.h>
 #include <asm/smp.h>
-#ifdef CONFIG_SUPERH32
-#include <asm/ubc.h>
+
+#ifdef CONFIG_SH_FPU
+#define cpu_has_fpu    1
+#else
+#define cpu_has_fpu    0
+#endif
+
+#ifdef CONFIG_SH_DSP
+#define cpu_has_dsp    1
+#else
+#define cpu_has_dsp    0
 #endif
 
 /*
  * Generic wrapper for command line arguments to disable on-chip
  * peripherals (nofpu, nodsp, and so forth).
  */
-#define onchip_setup(x)                                \
-static int x##_disabled __initdata = 0;                \
-                                               \
-static int __init x##_setup(char *opts)                \
-{                                              \
-       x##_disabled = 1;                       \
-       return 1;                               \
-}                                              \
+#define onchip_setup(x)                                        \
+static int x##_disabled __initdata = !cpu_has_##x;     \
+                                                       \
+static int __init x##_setup(char *opts)                        \
+{                                                      \
+       x##_disabled = 1;                               \
+       return 1;                                       \
+}                                                      \
 __setup("no" __stringify(x), x##_setup);
 
 onchip_setup(fpu);
@@ -207,6 +216,18 @@ static void detect_cache_shape(void)
                l2_cache_shape = -1; /* No S-cache */
 }
 
+static void __init fpu_init(void)
+{
+       /* Disable the FPU */
+       if (fpu_disabled && (current_cpu_data.flags & CPU_HAS_FPU)) {
+               printk("FPU Disabled\n");
+               current_cpu_data.flags &= ~CPU_HAS_FPU;
+       }
+
+       disable_fpu();
+       clear_used_math();
+}
+
 #ifdef CONFIG_SH_DSP
 static void __init release_dsp(void)
 {
@@ -244,28 +265,35 @@ static void __init dsp_init(void)
        if (sr & SR_DSP)
                current_cpu_data.flags |= CPU_HAS_DSP;
 
+       /* Disable the DSP */
+       if (dsp_disabled && (current_cpu_data.flags & CPU_HAS_DSP)) {
+               printk("DSP Disabled\n");
+               current_cpu_data.flags &= ~CPU_HAS_DSP;
+       }
+
        /* Now that we've determined the DSP status, clear the DSP bit. */
        release_dsp();
 }
+#else
+static inline void __init dsp_init(void) { }
 #endif /* CONFIG_SH_DSP */
 
 /**
  * sh_cpu_init
  *
- * This is our initial entry point for each CPU, and is invoked on the boot
- * CPU prior to calling start_kernel(). For SMP, a combination of this and
- * start_secondary() will bring up each processor to a ready state prior
- * to hand forking the idle loop.
+ * This is our initial entry point for each CPU, and is invoked on the
+ * boot CPU prior to calling start_kernel(). For SMP, a combination of
+ * this and start_secondary() will bring up each processor to a ready
+ * state prior to hand forking the idle loop.
  *
- * We do all of the basic processor init here, including setting up the
- * caches, FPU, DSP, kicking the UBC, etc. By the time start_kernel() is
- * hit (and subsequently platform_setup()) things like determining the
- * CPU subtype and initial configuration will all be done.
+ * We do all of the basic processor init here, including setting up
+ * the caches, FPU, DSP, etc. By the time start_kernel() is hit (and
+ * subsequently platform_setup()) things like determining the CPU
+ * subtype and initial configuration will all be done.
  *
  * Each processor family is still responsible for doing its own probing
  * and cache configuration in detect_cpu_and_cache_system().
  */
-
 asmlinkage void __init sh_cpu_init(void)
 {
        current_thread_info()->cpu = hard_smp_processor_id();
@@ -302,18 +330,8 @@ asmlinkage void __init sh_cpu_init(void)
                detect_cache_shape();
        }
 
-       /* Disable the FPU */
-       if (fpu_disabled) {
-               printk("FPU Disabled\n");
-               current_cpu_data.flags &= ~CPU_HAS_FPU;
-       }
-
-       /* FPU initialization */
-       disable_fpu();
-       if ((current_cpu_data.flags & CPU_HAS_FPU)) {
-               current_thread_info()->status &= ~TS_USEDFPU;
-               clear_used_math();
-       }
+       fpu_init();
+       dsp_init();
 
        /*
         * Initialize the per-CPU ASID cache very early, since the
@@ -321,18 +339,12 @@ asmlinkage void __init sh_cpu_init(void)
         */
        current_cpu_data.asid_cache = NO_CONTEXT;
 
-#ifdef CONFIG_SH_DSP
-       /* Probe for DSP */
-       dsp_init();
-
-       /* Disable the DSP */
-       if (dsp_disabled) {
-               printk("DSP Disabled\n");
-               current_cpu_data.flags &= ~CPU_HAS_DSP;
-               release_dsp();
-       }
-#endif
-
        speculative_execution_init();
        expmask_init();
+
+       /*
+        * Boot processor to setup the FP and extended state context info.
+        */
+       if (raw_smp_processor_id() == 0)
+               init_thread_xstate();
 }
index d395ce5740e7dff1cd66c3f786e592a0ba9c97b2..488d24e0cdf0b1aa59988a17afc7a9edd9a7e898 100644 (file)
@@ -26,8 +26,7 @@
 /*
  * Save FPU registers onto task structure.
  */
-void
-save_fpu(struct task_struct *tsk)
+void save_fpu(struct task_struct *tsk)
 {
        unsigned long dummy;
 
@@ -52,7 +51,7 @@ save_fpu(struct task_struct *tsk)
                     "fmov.s    fr0, @-%0\n\t"
                     "lds       %3, fpscr\n\t"
                     : "=r" (dummy)
-                    : "0" ((char *)(&tsk->thread.fpu.hard.status)),
+                    : "0" ((char *)(&tsk->thread.xstate->hardfpu.status)),
                       "r" (FPSCR_RCHG),
                       "r" (FPSCR_INIT)
                     : "memory");
@@ -60,8 +59,7 @@ save_fpu(struct task_struct *tsk)
        disable_fpu();
 }
 
-static void
-restore_fpu(struct task_struct *tsk)
+void restore_fpu(struct task_struct *tsk)
 {
        unsigned long dummy;
 
@@ -85,44 +83,11 @@ restore_fpu(struct task_struct *tsk)
                     "lds.l     @%0+, fpscr\n\t"
                     "lds.l     @%0+, fpul\n\t"
                     : "=r" (dummy)
-                    : "0" (&tsk->thread.fpu), "r" (FPSCR_RCHG)
+                    : "0" (tsk->thread.xstate), "r" (FPSCR_RCHG)
                     : "memory");
        disable_fpu();
 }
 
-/*
- * Load the FPU with signalling NANS.  This bit pattern we're using
- * has the property that no matter wether considered as single or as
- * double precission represents signaling NANS.
- */
-
-static void
-fpu_init(void)
-{
-       enable_fpu();
-       asm volatile("lds       %0, fpul\n\t"
-                    "fsts      fpul, fr0\n\t"
-                    "fsts      fpul, fr1\n\t"
-                    "fsts      fpul, fr2\n\t"
-                    "fsts      fpul, fr3\n\t"
-                    "fsts      fpul, fr4\n\t"
-                    "fsts      fpul, fr5\n\t"
-                    "fsts      fpul, fr6\n\t"
-                    "fsts      fpul, fr7\n\t"
-                    "fsts      fpul, fr8\n\t"
-                    "fsts      fpul, fr9\n\t"
-                    "fsts      fpul, fr10\n\t"
-                    "fsts      fpul, fr11\n\t"
-                    "fsts      fpul, fr12\n\t"
-                    "fsts      fpul, fr13\n\t"
-                    "fsts      fpul, fr14\n\t"
-                    "fsts      fpul, fr15\n\t"
-                    "lds       %2, fpscr\n\t"
-                    : /* no output */
-                    : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT));
-       disable_fpu();
-}
-
 /*
  *     Emulate arithmetic ops on denormalized number for some FPU insns.
  */
@@ -490,9 +455,9 @@ ieee_fpe_handler (struct pt_regs *regs)
        if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
                struct task_struct *tsk = current;
 
-               if ((tsk->thread.fpu.hard.fpscr & FPSCR_FPU_ERROR)) {
+               if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_FPU_ERROR)) {
                        /* FPU error */
-                       denormal_to_double (&tsk->thread.fpu.hard,
+                       denormal_to_double (&tsk->thread.xstate->hardfpu,
                                            (finsn >> 8) & 0xf);
                } else
                        return 0;
@@ -507,9 +472,9 @@ ieee_fpe_handler (struct pt_regs *regs)
 
                n = (finsn >> 8) & 0xf;
                m = (finsn >> 4) & 0xf;
-               hx = tsk->thread.fpu.hard.fp_regs[n];
-               hy = tsk->thread.fpu.hard.fp_regs[m];
-               fpscr = tsk->thread.fpu.hard.fpscr;
+               hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+               hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+               fpscr = tsk->thread.xstate->hardfpu.fpscr;
                prec = fpscr & (1 << 19);
 
                if ((fpscr & FPSCR_FPU_ERROR)
@@ -519,15 +484,15 @@ ieee_fpe_handler (struct pt_regs *regs)
 
                        /* FPU error because of denormal */
                        llx = ((long long) hx << 32)
-                              | tsk->thread.fpu.hard.fp_regs[n+1];
+                              | tsk->thread.xstate->hardfpu.fp_regs[n+1];
                        lly = ((long long) hy << 32)
-                              | tsk->thread.fpu.hard.fp_regs[m+1];
+                              | tsk->thread.xstate->hardfpu.fp_regs[m+1];
                        if ((hx & 0x7fffffff) >= 0x00100000)
                                llx = denormal_muld(lly, llx);
                        else
                                llx = denormal_muld(llx, lly);
-                       tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
-                       tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff;
+                       tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+                       tsk->thread.xstate->hardfpu.fp_regs[n+1] = llx & 0xffffffff;
                } else if ((fpscr & FPSCR_FPU_ERROR)
                     && (!prec && ((hx & 0x7fffffff) < 0x00800000
                                   || (hy & 0x7fffffff) < 0x00800000))) {
@@ -536,7 +501,7 @@ ieee_fpe_handler (struct pt_regs *regs)
                                hx = denormal_mulf(hy, hx);
                        else
                                hx = denormal_mulf(hx, hy);
-                       tsk->thread.fpu.hard.fp_regs[n] = hx;
+                       tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
                } else
                        return 0;
 
@@ -550,9 +515,9 @@ ieee_fpe_handler (struct pt_regs *regs)
 
                n = (finsn >> 8) & 0xf;
                m = (finsn >> 4) & 0xf;
-               hx = tsk->thread.fpu.hard.fp_regs[n];
-               hy = tsk->thread.fpu.hard.fp_regs[m];
-               fpscr = tsk->thread.fpu.hard.fpscr;
+               hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+               hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+               fpscr = tsk->thread.xstate->hardfpu.fpscr;
                prec = fpscr & (1 << 19);
 
                if ((fpscr & FPSCR_FPU_ERROR)
@@ -562,15 +527,15 @@ ieee_fpe_handler (struct pt_regs *regs)
 
                        /* FPU error because of denormal */
                        llx = ((long long) hx << 32)
-                              | tsk->thread.fpu.hard.fp_regs[n+1];
+                              | tsk->thread.xstate->hardfpu.fp_regs[n+1];
                        lly = ((long long) hy << 32)
-                              | tsk->thread.fpu.hard.fp_regs[m+1];
+                              | tsk->thread.xstate->hardfpu.fp_regs[m+1];
                        if ((finsn & 0xf00f) == 0xf000)
                                llx = denormal_addd(llx, lly);
                        else
                                llx = denormal_addd(llx, lly ^ (1LL << 63));
-                       tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
-                       tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff;
+                       tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+                       tsk->thread.xstate->hardfpu.fp_regs[n+1] = llx & 0xffffffff;
                } else if ((fpscr & FPSCR_FPU_ERROR)
                     && (!prec && ((hx & 0x7fffffff) < 0x00800000
                                   || (hy & 0x7fffffff) < 0x00800000))) {
@@ -579,7 +544,7 @@ ieee_fpe_handler (struct pt_regs *regs)
                                hx = denormal_addf(hx, hy);
                        else
                                hx = denormal_addf(hx, hy ^ 0x80000000);
-                       tsk->thread.fpu.hard.fp_regs[n] = hx;
+                       tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
                } else
                        return 0;
 
@@ -597,7 +562,7 @@ BUILD_TRAP_HANDLER(fpu_error)
 
        __unlazy_fpu(tsk, regs);
        if (ieee_fpe_handler(regs)) {
-               tsk->thread.fpu.hard.fpscr &=
+               tsk->thread.xstate->hardfpu.fpscr &=
                        ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
                grab_fpu(regs);
                restore_fpu(tsk);
@@ -607,33 +572,3 @@ BUILD_TRAP_HANDLER(fpu_error)
 
        force_sig(SIGFPE, tsk);
 }
-
-void fpu_state_restore(struct pt_regs *regs)
-{
-       struct task_struct *tsk = current;
-
-       grab_fpu(regs);
-       if (unlikely(!user_mode(regs))) {
-               printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
-               BUG();
-               return;
-       }
-
-       if (likely(used_math())) {
-               /* Using the FPU again.  */
-               restore_fpu(tsk);
-       } else  {
-               /* First time FPU user.  */
-               fpu_init();
-               set_used_math();
-       }
-       task_thread_info(tsk)->status |= TS_USEDFPU;
-       tsk->fpu_counter++;
-}
-
-BUILD_TRAP_HANDLER(fpu_state_restore)
-{
-       TRAP_HANDLER_DECL;
-
-       fpu_state_restore(regs);
-}
index 46610c35c232e8f5d051a485dfff69ff214bb1bc..99b4d020179a5a0c17b52e9927cbda49d225ed38 100644 (file)
@@ -49,7 +49,7 @@ ENTRY(exception_handling_table)
        .long   exception_error ! reserved_instruction (filled by trap_init) /* 180 */
        .long   exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
        .long   nmi_trap_handler        /* 1C0 */       ! Allow trap to debugger
-       .long   break_point_trap        /* 1E0 */
+       .long   breakpoint_trap_handler /* 1E0 */
 
        /*
         * Pad the remainder of the table out, exceptions residing in far
index e97857aec8a0461c496d5512170a55e7c54816d1..447482d7f65e6bdf573c33dabe67317afbe19cdd 100644 (file)
@@ -85,14 +85,14 @@ void save_fpu(struct task_struct *tsk)
                      "fmov.s   fr1, @-%0\n\t"
                      "fmov.s   fr0, @-%0\n\t"
                      "lds      %3, fpscr\n\t":"=r" (dummy)
-                     :"0"((char *)(&tsk->thread.fpu.hard.status)),
+                     :"0"((char *)(&tsk->thread.xstate->hardfpu.status)),
                      "r"(FPSCR_RCHG), "r"(FPSCR_INIT)
                      :"memory");
 
        disable_fpu();
 }
 
-static void restore_fpu(struct task_struct *tsk)
+void restore_fpu(struct task_struct *tsk)
 {
        unsigned long dummy;
 
@@ -135,62 +135,11 @@ static void restore_fpu(struct task_struct *tsk)
                      "lds.l    @%0+, fpscr\n\t"
                      "lds.l    @%0+, fpul\n\t"
                      :"=r" (dummy)
-                     :"0"(&tsk->thread.fpu), "r"(FPSCR_RCHG)
+                     :"0" (tsk->thread.xstate), "r" (FPSCR_RCHG)
                      :"memory");
        disable_fpu();
 }
 
-/*
- * Load the FPU with signalling NANS.  This bit pattern we're using
- * has the property that no matter wether considered as single or as
- * double precision represents signaling NANS.
- */
-
-static void fpu_init(void)
-{
-       enable_fpu();
-       asm volatile (  "lds    %0, fpul\n\t"
-                       "lds    %1, fpscr\n\t"
-                       "fsts   fpul, fr0\n\t"
-                       "fsts   fpul, fr1\n\t"
-                       "fsts   fpul, fr2\n\t"
-                       "fsts   fpul, fr3\n\t"
-                       "fsts   fpul, fr4\n\t"
-                       "fsts   fpul, fr5\n\t"
-                       "fsts   fpul, fr6\n\t"
-                       "fsts   fpul, fr7\n\t"
-                       "fsts   fpul, fr8\n\t"
-                       "fsts   fpul, fr9\n\t"
-                       "fsts   fpul, fr10\n\t"
-                       "fsts   fpul, fr11\n\t"
-                       "fsts   fpul, fr12\n\t"
-                       "fsts   fpul, fr13\n\t"
-                       "fsts   fpul, fr14\n\t"
-                       "fsts   fpul, fr15\n\t"
-                       "frchg\n\t"
-                       "fsts   fpul, fr0\n\t"
-                       "fsts   fpul, fr1\n\t"
-                       "fsts   fpul, fr2\n\t"
-                       "fsts   fpul, fr3\n\t"
-                       "fsts   fpul, fr4\n\t"
-                       "fsts   fpul, fr5\n\t"
-                       "fsts   fpul, fr6\n\t"
-                       "fsts   fpul, fr7\n\t"
-                       "fsts   fpul, fr8\n\t"
-                       "fsts   fpul, fr9\n\t"
-                       "fsts   fpul, fr10\n\t"
-                       "fsts   fpul, fr11\n\t"
-                       "fsts   fpul, fr12\n\t"
-                       "fsts   fpul, fr13\n\t"
-                       "fsts   fpul, fr14\n\t"
-                       "fsts   fpul, fr15\n\t"
-                       "frchg\n\t"
-                       "lds    %2, fpscr\n\t"
-                       :       /* no output */
-                       :"r" (0), "r"(FPSCR_RCHG), "r"(FPSCR_INIT));
-       disable_fpu();
-}
-
 /**
  *      denormal_to_double - Given denormalized float number,
  *                           store double float
@@ -282,9 +231,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
                /* fcnvsd */
                struct task_struct *tsk = current;
 
-               if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR))
+               if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_CAUSE_ERROR))
                        /* FPU error */
-                       denormal_to_double(&tsk->thread.fpu.hard,
+                       denormal_to_double(&tsk->thread.xstate->hardfpu,
                                           (finsn >> 8) & 0xf);
                else
                        return 0;
@@ -300,9 +249,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
 
                n = (finsn >> 8) & 0xf;
                m = (finsn >> 4) & 0xf;
-               hx = tsk->thread.fpu.hard.fp_regs[n];
-               hy = tsk->thread.fpu.hard.fp_regs[m];
-               fpscr = tsk->thread.fpu.hard.fpscr;
+               hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+               hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+               fpscr = tsk->thread.xstate->hardfpu.fpscr;
                prec = fpscr & FPSCR_DBL_PRECISION;
 
                if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -312,18 +261,18 @@ static int ieee_fpe_handler(struct pt_regs *regs)
 
                        /* FPU error because of denormal (doubles) */
                        llx = ((long long)hx << 32)
-                           | tsk->thread.fpu.hard.fp_regs[n + 1];
+                           | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
                        lly = ((long long)hy << 32)
-                           | tsk->thread.fpu.hard.fp_regs[m + 1];
+                           | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
                        llx = float64_mul(llx, lly);
-                       tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
-                       tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff;
+                       tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+                       tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
                } else if ((fpscr & FPSCR_CAUSE_ERROR)
                           && (!prec && ((hx & 0x7fffffff) < 0x00800000
                                         || (hy & 0x7fffffff) < 0x00800000))) {
                        /* FPU error because of denormal (floats) */
                        hx = float32_mul(hx, hy);
-                       tsk->thread.fpu.hard.fp_regs[n] = hx;
+                       tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
                } else
                        return 0;
 
@@ -338,9 +287,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
 
                n = (finsn >> 8) & 0xf;
                m = (finsn >> 4) & 0xf;
-               hx = tsk->thread.fpu.hard.fp_regs[n];
-               hy = tsk->thread.fpu.hard.fp_regs[m];
-               fpscr = tsk->thread.fpu.hard.fpscr;
+               hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+               hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+               fpscr = tsk->thread.xstate->hardfpu.fpscr;
                prec = fpscr & FPSCR_DBL_PRECISION;
 
                if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -350,15 +299,15 @@ static int ieee_fpe_handler(struct pt_regs *regs)
 
                        /* FPU error because of denormal (doubles) */
                        llx = ((long long)hx << 32)
-                           | tsk->thread.fpu.hard.fp_regs[n + 1];
+                           | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
                        lly = ((long long)hy << 32)
-                           | tsk->thread.fpu.hard.fp_regs[m + 1];
+                           | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
                        if ((finsn & 0xf00f) == 0xf000)
                                llx = float64_add(llx, lly);
                        else
                                llx = float64_sub(llx, lly);
-                       tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
-                       tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff;
+                       tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+                       tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
                } else if ((fpscr & FPSCR_CAUSE_ERROR)
                           && (!prec && ((hx & 0x7fffffff) < 0x00800000
                                         || (hy & 0x7fffffff) < 0x00800000))) {
@@ -367,7 +316,7 @@ static int ieee_fpe_handler(struct pt_regs *regs)
                                hx = float32_add(hx, hy);
                        else
                                hx = float32_sub(hx, hy);
-                       tsk->thread.fpu.hard.fp_regs[n] = hx;
+                       tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
                } else
                        return 0;
 
@@ -382,9 +331,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
 
                n = (finsn >> 8) & 0xf;
                m = (finsn >> 4) & 0xf;
-               hx = tsk->thread.fpu.hard.fp_regs[n];
-               hy = tsk->thread.fpu.hard.fp_regs[m];
-               fpscr = tsk->thread.fpu.hard.fpscr;
+               hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+               hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+               fpscr = tsk->thread.xstate->hardfpu.fpscr;
                prec = fpscr & FPSCR_DBL_PRECISION;
 
                if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -394,20 +343,20 @@ static int ieee_fpe_handler(struct pt_regs *regs)
 
                        /* FPU error because of denormal (doubles) */
                        llx = ((long long)hx << 32)
-                           | tsk->thread.fpu.hard.fp_regs[n + 1];
+                           | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
                        lly = ((long long)hy << 32)
-                           | tsk->thread.fpu.hard.fp_regs[m + 1];
+                           | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
 
                        llx = float64_div(llx, lly);
 
-                       tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
-                       tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff;
+                       tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+                       tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
                } else if ((fpscr & FPSCR_CAUSE_ERROR)
                           && (!prec && ((hx & 0x7fffffff) < 0x00800000
                                         || (hy & 0x7fffffff) < 0x00800000))) {
                        /* FPU error because of denormal (floats) */
                        hx = float32_div(hx, hy);
-                       tsk->thread.fpu.hard.fp_regs[n] = hx;
+                       tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
                } else
                        return 0;
 
@@ -420,17 +369,17 @@ static int ieee_fpe_handler(struct pt_regs *regs)
                unsigned int hx;
 
                m = (finsn >> 8) & 0x7;
-               hx = tsk->thread.fpu.hard.fp_regs[m];
+               hx = tsk->thread.xstate->hardfpu.fp_regs[m];
 
-               if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)
+               if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_CAUSE_ERROR)
                        && ((hx & 0x7fffffff) < 0x00100000)) {
                        /* subnormal double to float conversion */
                        long long llx;
 
-                       llx = ((long long)tsk->thread.fpu.hard.fp_regs[m] << 32)
-                           | tsk->thread.fpu.hard.fp_regs[m + 1];
+                       llx = ((long long)tsk->thread.xstate->hardfpu.fp_regs[m] << 32)
+                           | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
 
-                       tsk->thread.fpu.hard.fpul = float64_to_float32(llx);
+                       tsk->thread.xstate->hardfpu.fpul = float64_to_float32(llx);
                } else
                        return 0;
 
@@ -449,7 +398,7 @@ void float_raise(unsigned int flags)
 int float_rounding_mode(void)
 {
        struct task_struct *tsk = current;
-       int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.fpu.hard.fpscr);
+       int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.xstate->hardfpu.fpscr);
        return roundingMode;
 }
 
@@ -461,16 +410,16 @@ BUILD_TRAP_HANDLER(fpu_error)
        __unlazy_fpu(tsk, regs);
        fpu_exception_flags = 0;
        if (ieee_fpe_handler(regs)) {
-               tsk->thread.fpu.hard.fpscr &=
+               tsk->thread.xstate->hardfpu.fpscr &=
                    ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
-               tsk->thread.fpu.hard.fpscr |= fpu_exception_flags;
+               tsk->thread.xstate->hardfpu.fpscr |= fpu_exception_flags;
                /* Set the FPSCR flag as well as cause bits - simply
                 * replicate the cause */
-               tsk->thread.fpu.hard.fpscr |= (fpu_exception_flags >> 10);
+               tsk->thread.xstate->hardfpu.fpscr |= (fpu_exception_flags >> 10);
                grab_fpu(regs);
                restore_fpu(tsk);
                task_thread_info(tsk)->status |= TS_USEDFPU;
-               if ((((tsk->thread.fpu.hard.fpscr & FPSCR_ENABLE_MASK) >> 7) &
+               if ((((tsk->thread.xstate->hardfpu.fpscr & FPSCR_ENABLE_MASK) >> 7) &
                     (fpu_exception_flags >> 2)) == 0) {
                        return;
                }
@@ -478,33 +427,3 @@ BUILD_TRAP_HANDLER(fpu_error)
 
        force_sig(SIGFPE, tsk);
 }
-
-void fpu_state_restore(struct pt_regs *regs)
-{
-       struct task_struct *tsk = current;
-
-       grab_fpu(regs);
-       if (unlikely(!user_mode(regs))) {
-               printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
-               BUG();
-               return;
-       }
-
-       if (likely(used_math())) {
-               /* Using the FPU again.  */
-               restore_fpu(tsk);
-       } else {
-               /* First time FPU user.  */
-               fpu_init();
-               set_used_math();
-       }
-       task_thread_info(tsk)->status |= TS_USEDFPU;
-       tsk->fpu_counter++;
-}
-
-BUILD_TRAP_HANDLER(fpu_state_restore)
-{
-       TRAP_HANDLER_DECL;
-
-       fpu_state_restore(regs);
-}
index 33bab477d2e2de42bbd51a635ab0fb63e82f382c..b144e8af89dc696b8285bbb5e60fbb032a1d2bb6 100644 (file)
@@ -41,7 +41,8 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7757)   := pinmux-sh7757.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7785)    := pinmux-sh7785.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7786)    := pinmux-sh7786.o
 
-obj-y                          += $(clock-y)
-obj-$(CONFIG_SMP)              += $(smp-y)
-obj-$(CONFIG_GENERIC_GPIO)     += $(pinmux-y)
-obj-$(CONFIG_PERF_EVENTS)      += perf_event.o
+obj-y                                  += $(clock-y)
+obj-$(CONFIG_SMP)                      += $(smp-y)
+obj-$(CONFIG_GENERIC_GPIO)             += $(pinmux-y)
+obj-$(CONFIG_PERF_EVENTS)              += perf_event.o
+obj-$(CONFIG_HAVE_HW_BREAKPOINT)       += ubc.o
diff --git a/arch/sh/kernel/cpu/sh4a/ubc.c b/arch/sh/kernel/cpu/sh4a/ubc.c
new file mode 100644 (file)
index 0000000..efb2745
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/ubc.c
+ *
+ * On-chip UBC support for SH-4A CPUs.
+ *
+ * Copyright (C) 2009 - 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/hw_breakpoint.h>
+
+#define UBC_CBR(idx)   (0xff200000 + (0x20 * idx))
+#define UBC_CRR(idx)   (0xff200004 + (0x20 * idx))
+#define UBC_CAR(idx)   (0xff200008 + (0x20 * idx))
+#define UBC_CAMR(idx)  (0xff20000c + (0x20 * idx))
+
+#define UBC_CCMFR      0xff200600
+#define UBC_CBCR       0xff200620
+
+/* CRR */
+#define UBC_CRR_PCB    (1 << 1)
+#define UBC_CRR_BIE    (1 << 0)
+
+/* CBR */
+#define UBC_CBR_CE     (1 << 0)
+
+static struct sh_ubc sh4a_ubc;
+
+static void sh4a_ubc_enable(struct arch_hw_breakpoint *info, int idx)
+{
+       __raw_writel(UBC_CBR_CE | info->len | info->type, UBC_CBR(idx));
+       __raw_writel(info->address, UBC_CAR(idx));
+}
+
+static void sh4a_ubc_disable(struct arch_hw_breakpoint *info, int idx)
+{
+       __raw_writel(0, UBC_CBR(idx));
+       __raw_writel(0, UBC_CAR(idx));
+}
+
+static void sh4a_ubc_enable_all(unsigned long mask)
+{
+       int i;
+
+       for (i = 0; i < sh4a_ubc.num_events; i++)
+               if (mask & (1 << i))
+                       __raw_writel(__raw_readl(UBC_CBR(i)) | UBC_CBR_CE,
+                                    UBC_CBR(i));
+}
+
+static void sh4a_ubc_disable_all(void)
+{
+       int i;
+
+       for (i = 0; i < sh4a_ubc.num_events; i++)
+               __raw_writel(__raw_readl(UBC_CBR(i)) & ~UBC_CBR_CE,
+                            UBC_CBR(i));
+}
+
+static unsigned long sh4a_ubc_active_mask(void)
+{
+       unsigned long active = 0;
+       int i;
+
+       for (i = 0; i < sh4a_ubc.num_events; i++)
+               if (__raw_readl(UBC_CBR(i)) & UBC_CBR_CE)
+                       active |= (1 << i);
+
+       return active;
+}
+
+static unsigned long sh4a_ubc_triggered_mask(void)
+{
+       return __raw_readl(UBC_CCMFR);
+}
+
+static void sh4a_ubc_clear_triggered_mask(unsigned long mask)
+{
+       __raw_writel(__raw_readl(UBC_CCMFR) & ~mask, UBC_CCMFR);
+}
+
+static struct sh_ubc sh4a_ubc = {
+       .name                   = "SH-4A",
+       .num_events             = 2,
+       .trap_nr                = 0x1e0,
+       .enable                 = sh4a_ubc_enable,
+       .disable                = sh4a_ubc_disable,
+       .enable_all             = sh4a_ubc_enable_all,
+       .disable_all            = sh4a_ubc_disable_all,
+       .active_mask            = sh4a_ubc_active_mask,
+       .triggered_mask         = sh4a_ubc_triggered_mask,
+       .clear_triggered_mask   = sh4a_ubc_clear_triggered_mask,
+};
+
+static int __init sh4a_ubc_init(void)
+{
+       struct clk *ubc_iclk = clk_get(NULL, "ubc0");
+       int i;
+
+       /*
+        * The UBC MSTP bit is optional, as not all platforms will have
+        * it. Just ignore it if we can't find it.
+        */
+       if (IS_ERR(ubc_iclk))
+               ubc_iclk = NULL;
+
+       clk_enable(ubc_iclk);
+
+       __raw_writel(0, UBC_CBCR);
+
+       for (i = 0; i < sh4a_ubc.num_events; i++) {
+               __raw_writel(0, UBC_CAMR(i));
+               __raw_writel(0, UBC_CBR(i));
+
+               __raw_writel(UBC_CRR_BIE | UBC_CRR_PCB, UBC_CRR(i));
+
+               /* dummy read for write posting */
+               (void)__raw_readl(UBC_CRR(i));
+       }
+
+       clk_disable(ubc_iclk);
+
+       sh4a_ubc.clk = ubc_iclk;
+
+       return register_sh_ubc(&sh4a_ubc);
+}
+arch_initcall(sh4a_ubc_init);
index 591741383ee6addd2fe537aa800d869b24ac26c0..7a1b46fec0f46c08c540f5c6e8f99e17275669f5 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/linkage.h>
 
 #if !defined(CONFIG_KGDB)
-#define breakpoint_trap_handler                debug_trap_handler
 #define singlestep_trap_handler                debug_trap_handler
 #endif
 
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c
new file mode 100644 (file)
index 0000000..e2f1753
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * arch/sh/kernel/hw_breakpoint.c
+ *
+ * Unified kernel/user-space hardware breakpoint facility for the on-chip UBC.
+ *
+ * Copyright (C) 2009 - 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
+#include <linux/percpu.h>
+#include <linux/kallsyms.h>
+#include <linux/notifier.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <asm/hw_breakpoint.h>
+#include <asm/mmu_context.h>
+#include <asm/ptrace.h>
+
+/*
+ * Stores the breakpoints currently in use on each breakpoint address
+ * register for each cpus
+ */
+static DEFINE_PER_CPU(struct perf_event *, bp_per_reg[HBP_NUM]);
+
+/*
+ * A dummy placeholder for early accesses until the CPUs get a chance to
+ * register their UBCs later in the boot process.
+ */
+static struct sh_ubc ubc_dummy = { .num_events = 0 };
+
+static struct sh_ubc *sh_ubc __read_mostly = &ubc_dummy;
+
+/*
+ * Install a perf counter breakpoint.
+ *
+ * We seek a free UBC channel and use it for this breakpoint.
+ *
+ * Atomic: we hold the counter->ctx->lock and we only handle variables
+ * and registers local to this cpu.
+ */
+int arch_install_hw_breakpoint(struct perf_event *bp)
+{
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+       int i;
+
+       for (i = 0; i < sh_ubc->num_events; i++) {
+               struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]);
+
+               if (!*slot) {
+                       *slot = bp;
+                       break;
+               }
+       }
+
+       if (WARN_ONCE(i == sh_ubc->num_events, "Can't find any breakpoint slot"))
+               return -EBUSY;
+
+       clk_enable(sh_ubc->clk);
+       sh_ubc->enable(info, i);
+
+       return 0;
+}
+
+/*
+ * Uninstall the breakpoint contained in the given counter.
+ *
+ * First we search the debug address register it uses and then we disable
+ * it.
+ *
+ * Atomic: we hold the counter->ctx->lock and we only handle variables
+ * and registers local to this cpu.
+ */
+void arch_uninstall_hw_breakpoint(struct perf_event *bp)
+{
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+       int i;
+
+       for (i = 0; i < sh_ubc->num_events; i++) {
+               struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]);
+
+               if (*slot == bp) {
+                       *slot = NULL;
+                       break;
+               }
+       }
+
+       if (WARN_ONCE(i == sh_ubc->num_events, "Can't find any breakpoint slot"))
+               return;
+
+       sh_ubc->disable(info, i);
+       clk_disable(sh_ubc->clk);
+}
+
+static int get_hbp_len(u16 hbp_len)
+{
+       unsigned int len_in_bytes = 0;
+
+       switch (hbp_len) {
+       case SH_BREAKPOINT_LEN_1:
+               len_in_bytes = 1;
+               break;
+       case SH_BREAKPOINT_LEN_2:
+               len_in_bytes = 2;
+               break;
+       case SH_BREAKPOINT_LEN_4:
+               len_in_bytes = 4;
+               break;
+       case SH_BREAKPOINT_LEN_8:
+               len_in_bytes = 8;
+               break;
+       }
+       return len_in_bytes;
+}
+
+/*
+ * Check for virtual address in user space.
+ */
+int arch_check_va_in_userspace(unsigned long va, u16 hbp_len)
+{
+       unsigned int len;
+
+       len = get_hbp_len(hbp_len);
+
+       return (va <= TASK_SIZE - len);
+}
+
+/*
+ * Check for virtual address in kernel space.
+ */
+static int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len)
+{
+       unsigned int len;
+
+       len = get_hbp_len(hbp_len);
+
+       return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
+}
+
+/*
+ * Store a breakpoint's encoded address, length, and type.
+ */
+static int arch_store_info(struct perf_event *bp)
+{
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+       /*
+        * User-space requests will always have the address field populated
+        * For kernel-addresses, either the address or symbol name can be
+        * specified.
+        */
+       if (info->name)
+               info->address = (unsigned long)kallsyms_lookup_name(info->name);
+       if (info->address)
+               return 0;
+
+       return -EINVAL;
+}
+
+int arch_bp_generic_fields(int sh_len, int sh_type,
+                          int *gen_len, int *gen_type)
+{
+       /* Len */
+       switch (sh_len) {
+       case SH_BREAKPOINT_LEN_1:
+               *gen_len = HW_BREAKPOINT_LEN_1;
+               break;
+       case SH_BREAKPOINT_LEN_2:
+               *gen_len = HW_BREAKPOINT_LEN_2;
+               break;
+       case SH_BREAKPOINT_LEN_4:
+               *gen_len = HW_BREAKPOINT_LEN_4;
+               break;
+       case SH_BREAKPOINT_LEN_8:
+               *gen_len = HW_BREAKPOINT_LEN_8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Type */
+       switch (sh_type) {
+       case SH_BREAKPOINT_READ:
+               *gen_type = HW_BREAKPOINT_R;
+       case SH_BREAKPOINT_WRITE:
+               *gen_type = HW_BREAKPOINT_W;
+               break;
+       case SH_BREAKPOINT_RW:
+               *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int arch_build_bp_info(struct perf_event *bp)
+{
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+       info->address = bp->attr.bp_addr;
+
+       /* Len */
+       switch (bp->attr.bp_len) {
+       case HW_BREAKPOINT_LEN_1:
+               info->len = SH_BREAKPOINT_LEN_1;
+               break;
+       case HW_BREAKPOINT_LEN_2:
+               info->len = SH_BREAKPOINT_LEN_2;
+               break;
+       case HW_BREAKPOINT_LEN_4:
+               info->len = SH_BREAKPOINT_LEN_4;
+               break;
+       case HW_BREAKPOINT_LEN_8:
+               info->len = SH_BREAKPOINT_LEN_8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Type */
+       switch (bp->attr.bp_type) {
+       case HW_BREAKPOINT_R:
+               info->type = SH_BREAKPOINT_READ;
+               break;
+       case HW_BREAKPOINT_W:
+               info->type = SH_BREAKPOINT_WRITE;
+               break;
+       case HW_BREAKPOINT_W | HW_BREAKPOINT_R:
+               info->type = SH_BREAKPOINT_RW;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * Validate the arch-specific HW Breakpoint register settings
+ */
+int arch_validate_hwbkpt_settings(struct perf_event *bp,
+                                 struct task_struct *tsk)
+{
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+       unsigned int align;
+       int ret;
+
+       ret = arch_build_bp_info(bp);
+       if (ret)
+               return ret;
+
+       ret = -EINVAL;
+
+       switch (info->len) {
+       case SH_BREAKPOINT_LEN_1:
+               align = 0;
+               break;
+       case SH_BREAKPOINT_LEN_2:
+               align = 1;
+               break;
+       case SH_BREAKPOINT_LEN_4:
+               align = 3;
+               break;
+       case SH_BREAKPOINT_LEN_8:
+               align = 7;
+               break;
+       default:
+               return ret;
+       }
+
+       ret = arch_store_info(bp);
+
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Check that the low-order bits of the address are appropriate
+        * for the alignment implied by len.
+        */
+       if (info->address & align)
+               return -EINVAL;
+
+       /* Check that the virtual address is in the proper range */
+       if (tsk) {
+               if (!arch_check_va_in_userspace(info->address, info->len))
+                       return -EFAULT;
+       } else {
+               if (!arch_check_va_in_kernelspace(info->address, info->len))
+                       return -EFAULT;
+       }
+
+       return 0;
+}
+
+/*
+ * Release the user breakpoints used by ptrace
+ */
+void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+       int i;
+       struct thread_struct *t = &tsk->thread;
+
+       for (i = 0; i < sh_ubc->num_events; i++) {
+               unregister_hw_breakpoint(t->ptrace_bps[i]);
+               t->ptrace_bps[i] = NULL;
+       }
+}
+
+static int __kprobes hw_breakpoint_handler(struct die_args *args)
+{
+       int cpu, i, rc = NOTIFY_STOP;
+       struct perf_event *bp;
+       unsigned int cmf, resume_mask;
+
+       /*
+        * Do an early return if none of the channels triggered.
+        */
+       cmf = sh_ubc->triggered_mask();
+       if (unlikely(!cmf))
+               return NOTIFY_DONE;
+
+       /*
+        * By default, resume all of the active channels.
+        */
+       resume_mask = sh_ubc->active_mask();
+
+       /*
+        * Disable breakpoints during exception handling.
+        */
+       sh_ubc->disable_all();
+
+       cpu = get_cpu();
+       for (i = 0; i < sh_ubc->num_events; i++) {
+               unsigned long event_mask = (1 << i);
+
+               if (likely(!(cmf & event_mask)))
+                       continue;
+
+               /*
+                * The counter may be concurrently released but that can only
+                * occur from a call_rcu() path. We can then safely fetch
+                * the breakpoint, use its callback, touch its counter
+                * while we are in an rcu_read_lock() path.
+                */
+               rcu_read_lock();
+
+               bp = per_cpu(bp_per_reg[i], cpu);
+               if (bp)
+                       rc = NOTIFY_DONE;
+
+               /*
+                * Reset the condition match flag to denote completion of
+                * exception handling.
+                */
+               sh_ubc->clear_triggered_mask(event_mask);
+
+               /*
+                * bp can be NULL due to concurrent perf counter
+                * removing.
+                */
+               if (!bp) {
+                       rcu_read_unlock();
+                       break;
+               }
+
+               /*
+                * Don't restore the channel if the breakpoint is from
+                * ptrace, as it always operates in one-shot mode.
+                */
+               if (bp->overflow_handler == ptrace_triggered)
+                       resume_mask &= ~(1 << i);
+
+               perf_bp_event(bp, args->regs);
+
+               /* Deliver the signal to userspace */
+               if (arch_check_va_in_userspace(bp->attr.bp_addr,
+                                              bp->attr.bp_len)) {
+                       siginfo_t info;
+
+                       info.si_signo = args->signr;
+                       info.si_errno = notifier_to_errno(rc);
+                       info.si_code = TRAP_HWBKPT;
+
+                       force_sig_info(args->signr, &info, current);
+               }
+
+               rcu_read_unlock();
+       }
+
+       if (cmf == 0)
+               rc = NOTIFY_DONE;
+
+       sh_ubc->enable_all(resume_mask);
+
+       put_cpu();
+
+       return rc;
+}
+
+BUILD_TRAP_HANDLER(breakpoint)
+{
+       unsigned long ex = lookup_exception_vector();
+       TRAP_HANDLER_DECL;
+
+       notify_die(DIE_BREAKPOINT, "breakpoint", regs, 0, ex, SIGTRAP);
+}
+
+/*
+ * Handle debug exception notifications.
+ */
+int __kprobes hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+                                   unsigned long val, void *data)
+{
+       struct die_args *args = data;
+
+       if (val != DIE_BREAKPOINT)
+               return NOTIFY_DONE;
+
+       /*
+        * If the breakpoint hasn't been triggered by the UBC, it's
+        * probably from a debugger, so don't do anything more here.
+        *
+        * This also permits the UBC interface clock to remain off for
+        * non-UBC breakpoints, as we don't need to check the triggered
+        * or active channel masks.
+        */
+       if (args->trapnr != sh_ubc->trap_nr)
+               return NOTIFY_DONE;
+
+       return hw_breakpoint_handler(data);
+}
+
+void hw_breakpoint_pmu_read(struct perf_event *bp)
+{
+       /* TODO */
+}
+
+void hw_breakpoint_pmu_unthrottle(struct perf_event *bp)
+{
+       /* TODO */
+}
+
+int register_sh_ubc(struct sh_ubc *ubc)
+{
+       /* Bail if it's already assigned */
+       if (sh_ubc != &ubc_dummy)
+               return -EBUSY;
+       sh_ubc = ubc;
+
+       pr_info("HW Breakpoints: %s UBC support registered\n", ubc->name);
+
+       WARN_ON(ubc->num_events > HBP_NUM);
+
+       return 0;
+}
index 3e532d0d4a5cde48288b5d7081405ada2590860e..70c69659b8466b50ce8f3f4773f42320e765f176 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SuperH KGDB support
  *
- * Copyright (C) 2008  Paul Mundt
+ * Copyright (C) 2008 - 2009  Paul Mundt
  *
  * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel.
  *
@@ -251,24 +251,60 @@ BUILD_TRAP_HANDLER(singlestep)
        local_irq_restore(flags);
 }
 
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+       int ret;
+
+       switch (cmd) {
+       case DIE_BREAKPOINT:
+               /*
+                * This means a user thread is single stepping
+                * a system call which should be ignored
+                */
+               if (test_thread_flag(TIF_SINGLESTEP))
+                       return NOTIFY_DONE;
+
+               ret = kgdb_handle_exception(args->trapnr & 0xff, args->signr,
+                                           args->err, args->regs);
+               if (ret)
+                       return NOTIFY_DONE;
+
+               break;
+       }
 
-BUILD_TRAP_HANDLER(breakpoint)
+       return NOTIFY_STOP;
+}
+
+static int
+kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
 {
        unsigned long flags;
-       TRAP_HANDLER_DECL;
+       int ret;
 
        local_irq_save(flags);
-       kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs);
+       ret = __kgdb_notify(ptr, cmd);
        local_irq_restore(flags);
+
+       return ret;
 }
 
+static struct notifier_block kgdb_notifier = {
+       .notifier_call  = kgdb_notify,
+
+       /*
+        * Lowest-prio notifier priority, we want to be notified last:
+        */
+       .priority       = -INT_MAX,
+};
+
 int kgdb_arch_init(void)
 {
-       return 0;
+       return register_die_notifier(&kgdb_notifier);
 }
 
 void kgdb_arch_exit(void)
 {
+       unregister_die_notifier(&kgdb_notifier);
 }
 
 struct kgdb_arch arch_kgdb_ops = {
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
new file mode 100644 (file)
index 0000000..81add9b
--- /dev/null
@@ -0,0 +1,100 @@
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+struct kmem_cache *task_xstate_cachep = NULL;
+unsigned int xstate_size;
+
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+{
+       *dst = *src;
+
+       if (src->thread.xstate) {
+               dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
+                                                     GFP_KERNEL);
+               if (!dst->thread.xstate)
+                       return -ENOMEM;
+               memcpy(dst->thread.xstate, src->thread.xstate, xstate_size);
+       }
+
+       return 0;
+}
+
+void free_thread_xstate(struct task_struct *tsk)
+{
+       if (tsk->thread.xstate) {
+               kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
+               tsk->thread.xstate = NULL;
+       }
+}
+
+#if THREAD_SHIFT < PAGE_SHIFT
+static struct kmem_cache *thread_info_cache;
+
+struct thread_info *alloc_thread_info(struct task_struct *tsk)
+{
+       struct thread_info *ti;
+
+       ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
+       if (unlikely(ti == NULL))
+               return NULL;
+#ifdef CONFIG_DEBUG_STACK_USAGE
+       memset(ti, 0, THREAD_SIZE);
+#endif
+       return ti;
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+       free_thread_xstate(ti->task);
+       kmem_cache_free(thread_info_cache, ti);
+}
+
+void thread_info_cache_init(void)
+{
+       thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
+                                             THREAD_SIZE, SLAB_PANIC, NULL);
+}
+#else
+struct thread_info *alloc_thread_info(struct task_struct *tsk)
+{
+#ifdef CONFIG_DEBUG_STACK_USAGE
+       gfp_t mask = GFP_KERNEL | __GFP_ZERO;
+#else
+       gfp_t mask = GFP_KERNEL;
+#endif
+       return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER);
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+       free_thread_xstate(ti->task);
+       free_pages((unsigned long)ti, THREAD_SIZE_ORDER);
+}
+#endif /* THREAD_SHIFT < PAGE_SHIFT */
+
+void arch_task_cache_init(void)
+{
+       if (!xstate_size)
+               return;
+
+       task_xstate_cachep = kmem_cache_create("task_xstate", xstate_size,
+                                              __alignof__(union thread_xstate),
+                                              SLAB_PANIC | SLAB_NOTRACK, NULL);
+}
+
+#ifdef CONFIG_SH_FPU_EMU
+# define HAVE_SOFTFP   1
+#else
+# define HAVE_SOFTFP   0
+#endif
+
+void init_thread_xstate(void)
+{
+       if (boot_cpu_data.flags & CPU_HAS_FPU)
+               xstate_size = sizeof(struct sh_fpu_hard_struct);
+       else if (HAVE_SOFTFP)
+               xstate_size = sizeof(struct sh_fpu_soft_struct);
+       else
+               xstate_size = 0;
+}
index d8af889366a44c21b225cc53c24a1f45df2f9f46..856010f9ebc99f01186b3470e29752e9c53a6277 100644 (file)
 #include <linux/fs.h>
 #include <linux/ftrace.h>
 #include <linux/preempt.h>
+#include <linux/hw_breakpoint.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
 #include <asm/system.h>
-#include <asm/ubc.h>
 #include <asm/fpu.h>
 #include <asm/syscalls.h>
 #include <asm/watchdog.h>
 
-int ubc_usercnt = 0;
-
 #ifdef CONFIG_32BIT
 static void watchdog_trigger_immediate(void)
 {
@@ -147,21 +145,34 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 }
 EXPORT_SYMBOL(kernel_thread);
 
+void start_thread(struct pt_regs *regs, unsigned long new_pc,
+                 unsigned long new_sp)
+{
+       set_fs(USER_DS);
+
+       regs->pr = 0;
+       regs->sr = SR_FD;
+       regs->pc = new_pc;
+       regs->regs[15] = new_sp;
+
+       free_thread_xstate(current);
+}
+EXPORT_SYMBOL(start_thread);
+
 /*
  * Free current thread data structures etc..
  */
 void exit_thread(void)
 {
-       if (current->thread.ubc_pc) {
-               current->thread.ubc_pc = 0;
-               ubc_usercnt -= 1;
-       }
 }
 
 void flush_thread(void)
 {
-#if defined(CONFIG_SH_FPU)
        struct task_struct *tsk = current;
+
+       flush_ptrace_hw_breakpoint(tsk);
+
+#if defined(CONFIG_SH_FPU)
        /* Forget lazy FPU state */
        clear_fpu(tsk, task_pt_regs(tsk));
        clear_used_math();
@@ -209,11 +220,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 {
        struct thread_info *ti = task_thread_info(p);
        struct pt_regs *childregs;
+
 #if defined(CONFIG_SH_DSP)
        struct task_struct *tsk = current;
-#endif
 
-#if defined(CONFIG_SH_DSP)
        if (is_dsp_enabled(tsk)) {
                /* We can use the __save_dsp or just copy the struct:
                 * __save_dsp(p);
@@ -244,53 +254,11 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        p->thread.sp = (unsigned long) childregs;
        p->thread.pc = (unsigned long) ret_from_fork;
 
-       p->thread.ubc_pc = 0;
+       memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
 
        return 0;
 }
 
-/* Tracing by user break controller.  */
-static void ubc_set_tracing(int asid, unsigned long pc)
-{
-#if defined(CONFIG_CPU_SH4A)
-       unsigned long val;
-
-       val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE);
-       val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid));
-
-       ctrl_outl(val, UBC_CBR0);
-       ctrl_outl(pc,  UBC_CAR0);
-       ctrl_outl(0x0, UBC_CAMR0);
-       ctrl_outl(0x0, UBC_CBCR);
-
-       val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);
-       ctrl_outl(val, UBC_CRR0);
-
-       /* Read UBC register that we wrote last, for checking update */
-       val = ctrl_inl(UBC_CRR0);
-
-#else  /* CONFIG_CPU_SH4A */
-       ctrl_outl(pc, UBC_BARA);
-
-#ifdef CONFIG_MMU
-       ctrl_outb(asid, UBC_BASRA);
-#endif
-
-       ctrl_outl(0, UBC_BAMRA);
-
-       if (current_cpu_data.type == CPU_SH7729 ||
-           current_cpu_data.type == CPU_SH7710 ||
-           current_cpu_data.type == CPU_SH7712 ||
-           current_cpu_data.type == CPU_SH7203){
-               ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
-               ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
-       } else {
-               ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
-               ctrl_outw(BRCR_PCBA, UBC_BRCR);
-       }
-#endif /* CONFIG_CPU_SH4A */
-}
-
 /*
  *     switch_to(x,y) should switch tasks from x to y.
  *
@@ -304,7 +272,7 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
 
        /* we're going to use this soon, after a few expensive things */
        if (next->fpu_counter > 5)
-               prefetch(&next_t->fpu.hard);
+               prefetch(next_t->xstate);
 
 #ifdef CONFIG_MMU
        /*
@@ -316,32 +284,13 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
                     : "r" (task_thread_info(next)));
 #endif
 
-       /* If no tasks are using the UBC, we're done */
-       if (ubc_usercnt == 0)
-               /* If no tasks are using the UBC, we're done */;
-       else if (next->thread.ubc_pc && next->mm) {
-               int asid = 0;
-#ifdef CONFIG_MMU
-               asid |= cpu_asid(smp_processor_id(), next->mm);
-#endif
-               ubc_set_tracing(asid, next->thread.ubc_pc);
-       } else {
-#if defined(CONFIG_CPU_SH4A)
-               ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
-               ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
-#else
-               ctrl_outw(0, UBC_BBRA);
-               ctrl_outw(0, UBC_BBRB);
-#endif
-       }
-
        /*
         * If the task has used fpu the last 5 timeslices, just do a full
         * restore of the math state immediately to avoid the trap; the
         * chances of needing FPU soon are obviously high now
         */
        if (next->fpu_counter > 5)
-               fpu_state_restore(task_pt_regs(next));
+               __fpu_state_restore();
 
        return prev;
 }
@@ -434,20 +383,3 @@ unsigned long get_wchan(struct task_struct *p)
 
        return pc;
 }
-
-asmlinkage void break_point_trap(void)
-{
-       /* Clear tracing.  */
-#if defined(CONFIG_CPU_SH4A)
-       ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
-       ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
-#else
-       ctrl_outw(0, UBC_BBRA);
-       ctrl_outw(0, UBC_BBRB);
-       ctrl_outl(0, UBC_BRCR);
-#endif
-       current->thread.ubc_pc = 0;
-       ubc_usercnt -= 1;
-
-       force_sig(SIGTRAP, current);
-}
index 9be35f34809356f40b006c91fea36ba77deea458..c625cdab76dd4143d6001f8b3913699c26e351df 100644 (file)
@@ -2,7 +2,7 @@
  * SuperH process tracing
  *
  * Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
- * Copyright (C) 2002 - 2008  Paul Mundt
+ * Copyright (C) 2002 - 2009  Paul Mundt
  *
  * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp>
  *
@@ -26,6 +26,7 @@
 #include <linux/tracehook.h>
 #include <linux/elf.h>
 #include <linux/regset.h>
+#include <linux/hw_breakpoint.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -63,33 +64,64 @@ static inline int put_stack_long(struct task_struct *task, int offset,
        return 0;
 }
 
-void user_enable_single_step(struct task_struct *child)
+void ptrace_triggered(struct perf_event *bp, int nmi,
+                     struct perf_sample_data *data, struct pt_regs *regs)
 {
-       /* Next scheduling will set up UBC */
-       if (child->thread.ubc_pc == 0)
-               ubc_usercnt += 1;
+       struct perf_event_attr attr;
+
+       /*
+        * Disable the breakpoint request here since ptrace has defined a
+        * one-shot behaviour for breakpoint exceptions.
+        */
+       attr = bp->attr;
+       attr.disabled = true;
+       modify_user_hw_breakpoint(bp, &attr);
+}
+
+static int set_single_step(struct task_struct *tsk, unsigned long addr)
+{
+       struct thread_struct *thread = &tsk->thread;
+       struct perf_event *bp;
+       struct perf_event_attr attr;
+
+       bp = thread->ptrace_bps[0];
+       if (!bp) {
+               hw_breakpoint_init(&attr);
+
+               attr.bp_addr = addr;
+               attr.bp_len = HW_BREAKPOINT_LEN_2;
+               attr.bp_type = HW_BREAKPOINT_R;
+
+               bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk);
+               if (IS_ERR(bp))
+                       return PTR_ERR(bp);
+
+               thread->ptrace_bps[0] = bp;
+       } else {
+               int err;
+
+               attr = bp->attr;
+               attr.bp_addr = addr;
+               err = modify_user_hw_breakpoint(bp, &attr);
+               if (unlikely(err))
+                       return err;
+       }
+
+       return 0;
+}
 
-       child->thread.ubc_pc = get_stack_long(child,
-                               offsetof(struct pt_regs, pc));
+void user_enable_single_step(struct task_struct *child)
+{
+       unsigned long pc = get_stack_long(child, offsetof(struct pt_regs, pc));
 
        set_tsk_thread_flag(child, TIF_SINGLESTEP);
+
+       set_single_step(child, pc);
 }
 
 void user_disable_single_step(struct task_struct *child)
 {
        clear_tsk_thread_flag(child, TIF_SINGLESTEP);
-
-       /*
-        * Ensure the UBC is not programmed at the next context switch.
-        *
-        * Normally this is not needed but there are sequences such as
-        * singlestep, signal delivery, and continue that leave the
-        * ubc_pc non-zero leading to spurious SIGTRAPs.
-        */
-       if (child->thread.ubc_pc != 0) {
-               ubc_usercnt -= 1;
-               child->thread.ubc_pc = 0;
-       }
 }
 
 /*
@@ -163,10 +195,10 @@ int fpregs_get(struct task_struct *target,
 
        if ((boot_cpu_data.flags & CPU_HAS_FPU))
                return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-                                          &target->thread.fpu.hard, 0, -1);
+                                          &target->thread.xstate->hardfpu, 0, -1);
 
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-                                  &target->thread.fpu.soft, 0, -1);
+                                  &target->thread.xstate->softfpu, 0, -1);
 }
 
 static int fpregs_set(struct task_struct *target,
@@ -184,10 +216,10 @@ static int fpregs_set(struct task_struct *target,
 
        if ((boot_cpu_data.flags & CPU_HAS_FPU))
                return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                                         &target->thread.fpu.hard, 0, -1);
+                                         &target->thread.xstate->hardfpu, 0, -1);
 
        return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                                 &target->thread.fpu.soft, 0, -1);
+                                 &target->thread.xstate->softfpu, 0, -1);
 }
 
 static int fpregs_active(struct task_struct *target,
@@ -333,7 +365,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                                else
                                        tmp = 0;
                        } else
-                               tmp = ((long *)&child->thread.fpu)
+                               tmp = ((long *)child->thread.xstate)
                                        [(addr - (long)&dummy->fpu) >> 2];
                } else if (addr == (long) &dummy->u_fpvalid)
                        tmp = !!tsk_used_math(child);
@@ -362,7 +394,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                else if (addr >= (long) &dummy->fpu &&
                         addr < (long) &dummy->u_fpvalid) {
                        set_stopped_child_used_math(child);
-                       ((long *)&child->thread.fpu)
+                       ((long *)child->thread.xstate)
                                [(addr - (long)&dummy->fpu) >> 2] = data;
                        ret = 0;
                } else if (addr == (long) &dummy->u_fpvalid) {
index 12815ce01ecd935022eb2f13779d26eb6e74e59a..6a7cce79eb4ed9561f04f6d64ead03593e6ff510 100644 (file)
@@ -150,7 +150,7 @@ static inline int restore_sigcontext_fpu(struct sigcontext __user *sc)
                return 0;
 
        set_used_math();
-       return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0],
+       return __copy_from_user(&tsk->thread.xstate->hardfpu, &sc->sc_fpregs[0],
                                sizeof(long)*(16*2+2));
 }
 
@@ -175,7 +175,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
        clear_used_math();
 
        unlazy_fpu(tsk, regs);
-       return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard,
+       return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.xstate->hardfpu,
                              sizeof(long)*(16*2+2));
 }
 #endif /* CONFIG_SH_FPU */
index 204def6ecb6ad322487591385a372250f9043759..9c090cb68878c6391508b0caa22e31da842ee654 100644 (file)
@@ -846,7 +846,7 @@ void __init trap_init(void)
 #endif
 
 #ifdef TRAP_UBC
-       set_exception_table_vec(TRAP_UBC, break_point_trap);
+       set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler);
 #endif
 
        /* Save off the BIOS VBR, if there is one */
index d6c15cae0912b487549efc059a7370fb76cacc73..1fcdb12209754ed20fb92721ca7906a05b7d3bb9 100644 (file)
@@ -471,10 +471,10 @@ static int fpu_emulate(u16 code, struct sh_fpu_soft_struct *fregs, struct pt_reg
  *     denormal_to_double - Given denormalized float number,
  *                          store double float
  *
- *     @fpu: Pointer to sh_fpu_hard structure
+ *     @fpu: Pointer to sh_fpu_soft structure
  *     @n: Index to FP register
  */
-static void denormal_to_double(struct sh_fpu_hard_struct *fpu, int n)
+static void denormal_to_double(struct sh_fpu_soft_struct *fpu, int n)
 {
        unsigned long du, dl;
        unsigned long x = fpu->fpul;
@@ -552,11 +552,11 @@ static int ieee_fpe_handler(struct pt_regs *regs)
        if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
                struct task_struct *tsk = current;
 
-               if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) {
+               if ((tsk->thread.xstate->softfpu.fpscr & (1 << 17))) {
                        /* FPU error */
-                       denormal_to_double (&tsk->thread.fpu.hard,
+                       denormal_to_double (&tsk->thread.xstate->softfpu,
                                            (finsn >> 8) & 0xf);
-                       tsk->thread.fpu.hard.fpscr &=
+                       tsk->thread.xstate->softfpu.fpscr &=
                                ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
                        task_thread_info(tsk)->status |= TS_USEDFPU;
                } else {
@@ -617,7 +617,7 @@ static void fpu_init(struct sh_fpu_soft_struct *fpu)
 int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
 {
        struct task_struct *tsk = current;
-       struct sh_fpu_soft_struct *fpu = &(tsk->thread.fpu.soft);
+       struct sh_fpu_soft_struct *fpu = &(tsk->thread.xstate->softfpu);
 
        if (!(task_thread_info(tsk)->status & TS_USEDFPU)) {
                /* initialize once. */
index 761910d142f8e11e5d2ae3f51de8c40dfa8aeda7..d5fb014279ad21758cd0e96f45c7585077c4e661 100644 (file)
@@ -283,35 +283,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 }
 #endif
 
-#if THREAD_SHIFT < PAGE_SHIFT
-static struct kmem_cache *thread_info_cache;
-
-struct thread_info *alloc_thread_info(struct task_struct *tsk)
-{
-       struct thread_info *ti;
-
-       ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
-       if (unlikely(ti == NULL))
-               return NULL;
-#ifdef CONFIG_DEBUG_STACK_USAGE
-       memset(ti, 0, THREAD_SIZE);
-#endif
-       return ti;
-}
-
-void free_thread_info(struct thread_info *ti)
-{
-       kmem_cache_free(thread_info_cache, ti);
-}
-
-void thread_info_cache_init(void)
-{
-       thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
-                                             THREAD_SIZE, 0, NULL);
-       BUG_ON(thread_info_cache == NULL);
-}
-#endif /* THREAD_SHIFT < PAGE_SHIFT */
-
 #ifdef CONFIG_MEMORY_HOTPLUG
 int arch_add_memory(int nid, u64 start, u64 size)
 {
index f30f4a1ead23d373afb51161f3303dfeae9fbe17..d242a734054102f7f61b45c0e45976cde22c9a50 100644 (file)
@@ -96,7 +96,6 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
        int cpu = smp_processor_id();
 
        clear_softint(1 << irq);
-       pcr_ops->write(PCR_PIC_PRIV);
 
        local_cpu_data().__nmi_count++;
 
@@ -105,6 +104,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
        if (notify_die(DIE_NMI, "nmi", regs, 0,
                       pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
                touched = 1;
+       else
+               pcr_ops->write(PCR_PIC_PRIV);
 
        sum = kstat_irqs_cpu(0, cpu);
        if (__get_cpu_var(nmi_touch)) {
index fa5936e1c3b9e8d632c024d5dd6ea0ce8863eba1..198fb4e79ba2875289a58cae60acb47c3442fb23 100644 (file)
@@ -986,6 +986,17 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
        data.addr = 0;
 
        cpuc = &__get_cpu_var(cpu_hw_events);
+
+       /* If the PMU has the TOE IRQ enable bits, we need to do a
+        * dummy write to the %pcr to clear the overflow bits and thus
+        * the interrupt.
+        *
+        * Do this before we peek at the counters to determine
+        * overflow so we don't lose any events.
+        */
+       if (sparc_pmu->irq_bit)
+               pcr_ops->write(cpuc->pcr);
+
        for (idx = 0; idx < MAX_HWEVENTS; idx++) {
                struct perf_event *event = cpuc->events[idx];
                struct hw_perf_event *hwc;
index 55298e891571edc6d07486f235a46ffddd622729..cbcbfdee3ee08695b8dbdbf873755dac7762d324 100644 (file)
@@ -49,6 +49,7 @@ config X86
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_BZIP2
        select HAVE_KERNEL_LZMA
+       select HAVE_KERNEL_LZO
        select HAVE_HW_BREAKPOINT
        select PERF_EVENTS
        select ANON_INODES
@@ -1246,6 +1247,11 @@ config ARCH_MEMORY_PROBE
        def_bool X86_64
        depends on MEMORY_HOTPLUG
 
+config ILLEGAL_POINTER_VALUE
+       hex
+       default 0 if X86_32
+       default 0xdead000000000000 if X86_64
+
 source "mm/Kconfig"
 
 config HIGHPTE
index 08e442bc3ab914951a4faa4c29c616f7018b0cf7..f20ddf84a89397c322d4f35657400d5590891832 100644 (file)
@@ -396,7 +396,7 @@ config X86_TSC
 
 config X86_CMPXCHG64
        def_bool y
-       depends on !M386 && !M486
+       depends on X86_PAE || X86_64 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM
 
 # this should be set for all -march=.. options where the compiler
 # generates cmov.
index f8ed0658404cc559d7c65a261330dba620017f38..fbb47daf2459d4aed21a1ef1d106965199a98436 100644 (file)
@@ -4,11 +4,12 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o
+targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.lzo head_$(BITS).o misc.o piggy.o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
+cflags-$(CONFIG_X86_32) := -march=i386
 cflags-$(CONFIG_X86_64) := -mcmodel=small
 KBUILD_CFLAGS += $(cflags-y)
 KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
@@ -48,10 +49,13 @@ $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE
        $(call if_changed,bzip2)
 $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE
        $(call if_changed,lzma)
+$(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE
+       $(call if_changed,lzo)
 
 suffix-$(CONFIG_KERNEL_GZIP)   := gz
 suffix-$(CONFIG_KERNEL_BZIP2)  := bz2
 suffix-$(CONFIG_KERNEL_LZMA)   := lzma
+suffix-$(CONFIG_KERNEL_LZO)    := lzo
 
 quiet_cmd_mkpiggy = MKPIGGY $@
       cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false )
index 842b2a36174a2a2b6347851d7f1069878fb5cb4b..3b22fe8ab91bc90d2e25f2d33e53d315860e3c30 100644 (file)
@@ -162,6 +162,10 @@ static int lines, cols;
 #include "../../../../lib/decompress_unlzma.c"
 #endif
 
+#ifdef CONFIG_KERNEL_LZO
+#include "../../../../lib/decompress_unlzo.c"
+#endif
+
 static void scroll(void)
 {
        int i;
index 950df434763f5b2ea3fa407d3511f0020e9cb67b..f46b79f6c16c873a337013fa8a18e18f85c4ee22 100644 (file)
@@ -254,6 +254,10 @@ struct kvm_reinject_control {
        __u8 reserved[31];
 };
 
+/* When set in flags, include corresponding fields on KVM_SET_VCPU_EVENTS */
+#define KVM_VCPUEVENT_VALID_NMI_PENDING        0x00000001
+#define KVM_VCPUEVENT_VALID_SIPI_VECTOR        0x00000002
+
 /* for KVM_GET/SET_VCPU_EVENTS */
 struct kvm_vcpu_events {
        struct {
index 0c9825e97f361fd40032ac8d3417318288a864b2..088d09fb1615af8081872b04e9b2b3ec15e1fbad 100644 (file)
@@ -205,14 +205,13 @@ static inline unsigned long __must_check copy_from_user(void *to,
                                          unsigned long n)
 {
        int sz = __compiletime_object_size(to);
-       int ret = -EFAULT;
 
        if (likely(sz == -1 || sz >= n))
-               ret = _copy_from_user(to, from, n);
+               n = _copy_from_user(to, from, n);
        else
                copy_from_user_overflow();
 
-       return ret;
+       return n;
 }
 
 long __must_check strncpy_from_user(char *dst, const char __user *src,
index 46324c6a4f6e3da0aba2f3a6576ade498c3ea57b..535e421498f6148ed36adaf698f54a13c58393de 100644 (file)
@@ -30,16 +30,15 @@ static inline unsigned long __must_check copy_from_user(void *to,
                                          unsigned long n)
 {
        int sz = __compiletime_object_size(to);
-       int ret = -EFAULT;
 
        might_fault();
        if (likely(sz == -1 || sz >= n))
-               ret = _copy_from_user(to, from, n);
+               n = _copy_from_user(to, from, n);
 #ifdef CONFIG_DEBUG_VM
        else
                WARN(1, "Buffer overflow detected!\n");
 #endif
-       return ret;
+       return n;
 }
 
 static __always_inline __must_check
index 811bfabc80b7e91ce3c02bf56acdbb4809f4e1a3..bc54fa965af3a053530b85c65852784375d04a51 100644 (file)
  *               contiguous (although various IO spaces may punch holes in
  *               it)..
  *
- *     N       - Number of bits in the node portion of a socket physical
- *               address.
+ *     N       - Number of bits in the node portion of a socket physical
+ *               address.
  *
- *     NASID   - network ID of a router, Mbrick or Cbrick. Nasid values of
- *               routers always have low bit of 1, C/MBricks have low bit
- *               equal to 0. Most addressing macros that target UV hub chips
- *               right shift the NASID by 1 to exclude the always-zero bit.
- *               NASIDs contain up to 15 bits.
+ *     NASID   - network ID of a router, Mbrick or Cbrick. Nasid values of
+ *               routers always have low bit of 1, C/MBricks have low bit
+ *               equal to 0. Most addressing macros that target UV hub chips
+ *               right shift the NASID by 1 to exclude the always-zero bit.
+ *               NASIDs contain up to 15 bits.
  *
  *     GNODE   - NASID right shifted by 1 bit. Most mmrs contain gnodes instead
  *               of nasids.
  *
- *     PNODE   - the low N bits of the GNODE. The PNODE is the most useful variant
- *               of the nasid for socket usage.
+ *     PNODE   - the low N bits of the GNODE. The PNODE is the most useful variant
+ *               of the nasid for socket usage.
  *
  *
  *  NumaLink Global Physical Address Format:
  *
  *
  * APICID format
- *     NOTE!!!!!! This is the current format of the APICID. However, code
- *     should assume that this will change in the future. Use functions
- *     in this file for all APICID bit manipulations and conversion.
+ *     NOTE!!!!!! This is the current format of the APICID. However, code
+ *     should assume that this will change in the future. Use functions
+ *     in this file for all APICID bit manipulations and conversion.
  *
- *             1111110000000000
- *             5432109876543210
+ *             1111110000000000
+ *             5432109876543210
  *             pppppppppplc0cch
  *             sssssssssss
  *
@@ -89,9 +89,9 @@
  *     Note: Processor only supports 12 bits in the APICID register. The ACPI
  *           tables hold all 16 bits. Software needs to be aware of this.
  *
- *           Unless otherwise specified, all references to APICID refer to
- *           the FULL value contained in ACPI tables, not the subset in the
- *           processor APICID register.
+ *           Unless otherwise specified, all references to APICID refer to
+ *           the FULL value contained in ACPI tables, not the subset in the
+ *           processor APICID register.
  */
 
 
@@ -151,16 +151,16 @@ struct uv_hub_info_s {
 };
 
 DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
-#define uv_hub_info            (&__get_cpu_var(__uv_hub_info))
+#define uv_hub_info            (&__get_cpu_var(__uv_hub_info))
 #define uv_cpu_hub_info(cpu)   (&per_cpu(__uv_hub_info, cpu))
 
 /*
  * Local & Global MMR space macros.
- *     Note: macros are intended to be used ONLY by inline functions
- *     in this file - not by other kernel code.
- *             n -  NASID (full 15-bit global nasid)
- *             g -  GNODE (full 15-bit global nasid, right shifted 1)
- *             p -  PNODE (local part of nsids, right shifted 1)
+ *     Note: macros are intended to be used ONLY by inline functions
+ *     in this file - not by other kernel code.
+ *             n -  NASID (full 15-bit global nasid)
+ *             g -  GNODE (full 15-bit global nasid, right shifted 1)
+ *             p -  PNODE (local part of nsids, right shifted 1)
  */
 #define UV_NASID_TO_PNODE(n)           (((n) >> 1) & uv_hub_info->pnode_mask)
 #define UV_PNODE_TO_GNODE(p)           ((p) |uv_hub_info->gnode_extra)
@@ -215,8 +215,8 @@ DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
 /*
  * Macros for converting between kernel virtual addresses, socket local physical
  * addresses, and UV global physical addresses.
- *     Note: use the standard __pa() & __va() macros for converting
- *           between socket virtual and socket physical addresses.
+ *     Note: use the standard __pa() & __va() macros for converting
+ *           between socket virtual and socket physical addresses.
  */
 
 /* socket phys RAM --> UV global physical address */
@@ -287,21 +287,18 @@ static inline int uv_apicid_to_pnode(int apicid)
  * Access global MMRs using the low memory MMR32 space. This region supports
  * faster MMR access but not all MMRs are accessible in this space.
  */
-static inline unsigned long *uv_global_mmr32_address(int pnode,
-                               unsigned long offset)
+static inline unsigned long *uv_global_mmr32_address(int pnode, unsigned long offset)
 {
        return __va(UV_GLOBAL_MMR32_BASE |
                       UV_GLOBAL_MMR32_PNODE_BITS(pnode) | offset);
 }
 
-static inline void uv_write_global_mmr32(int pnode, unsigned long offset,
-                                unsigned long val)
+static inline void uv_write_global_mmr32(int pnode, unsigned long offset, unsigned long val)
 {
        writeq(val, uv_global_mmr32_address(pnode, offset));
 }
 
-static inline unsigned long uv_read_global_mmr32(int pnode,
-                                                unsigned long offset)
+static inline unsigned long uv_read_global_mmr32(int pnode, unsigned long offset)
 {
        return readq(uv_global_mmr32_address(pnode, offset));
 }
@@ -310,21 +307,18 @@ static inline unsigned long uv_read_global_mmr32(int pnode,
  * Access Global MMR space using the MMR space located at the top of physical
  * memory.
  */
-static inline unsigned long *uv_global_mmr64_address(int pnode,
-                               unsigned long offset)
+static inline unsigned long *uv_global_mmr64_address(int pnode, unsigned long offset)
 {
        return __va(UV_GLOBAL_MMR64_BASE |
                    UV_GLOBAL_MMR64_PNODE_BITS(pnode) | offset);
 }
 
-static inline void uv_write_global_mmr64(int pnode, unsigned long offset,
-                               unsigned long val)
+static inline void uv_write_global_mmr64(int pnode, unsigned long offset, unsigned long val)
 {
        writeq(val, uv_global_mmr64_address(pnode, offset));
 }
 
-static inline unsigned long uv_read_global_mmr64(int pnode,
-                                                unsigned long offset)
+static inline unsigned long uv_read_global_mmr64(int pnode, unsigned long offset)
 {
        return readq(uv_global_mmr64_address(pnode, offset));
 }
@@ -338,6 +332,16 @@ static inline unsigned long uv_global_gru_mmr_address(int pnode, unsigned long o
        return UV_GLOBAL_GRU_MMR_BASE | offset | (pnode << uv_hub_info->m_val);
 }
 
+static inline void uv_write_global_mmr8(int pnode, unsigned long offset, unsigned char val)
+{
+       writeb(val, uv_global_mmr64_address(pnode, offset));
+}
+
+static inline unsigned char uv_read_global_mmr8(int pnode, unsigned long offset)
+{
+       return readb(uv_global_mmr64_address(pnode, offset));
+}
+
 /*
  * Access hub local MMRs. Faster than using global space but only local MMRs
  * are accessible.
@@ -457,11 +461,17 @@ static inline void uv_set_scir_bits(unsigned char value)
        }
 }
 
+static inline unsigned long uv_scir_offset(int apicid)
+{
+       return SCIR_LOCAL_MMR_BASE | (apicid & 0x3f);
+}
+
 static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value)
 {
        if (uv_cpu_hub_info(cpu)->scir.state != value) {
+               uv_write_global_mmr8(uv_cpu_to_pnode(cpu),
+                               uv_cpu_hub_info(cpu)->scir.offset, value);
                uv_cpu_hub_info(cpu)->scir.state = value;
-               uv_write_local_mmr8(uv_cpu_hub_info(cpu)->scir.offset, value);
        }
 }
 
index 82e508677b91116ec8428e434ae164a8390084bf..f9961034e55793b1619edac03f2e34ed57ef7798 100644 (file)
@@ -162,6 +162,8 @@ static int __init acpi_sleep_setup(char *str)
 #endif
                if (strncmp(str, "old_ordering", 12) == 0)
                        acpi_old_suspend_ordering();
+               if (strncmp(str, "sci_force_enable", 16) == 0)
+                       acpi_set_sci_en_on_resume();
                str = strchr(str, ',');
                if (str != NULL)
                        str += strspn(str, ", \t");
index 1dca9c34eaeb4417ebe336810edb648a738a5e1a..fb490ce7dd55193b88b6f4d359cbfaa79a26eafe 100644 (file)
@@ -137,6 +137,11 @@ int amd_iommus_present;
 /* IOMMUs have a non-present cache? */
 bool amd_iommu_np_cache __read_mostly;
 
+/*
+ * Set to true if ACPI table parsing and hardware intialization went properly
+ */
+static bool amd_iommu_initialized;
+
 /*
  * List of protection domains - used during resume
  */
@@ -929,6 +934,8 @@ static int __init init_iommu_all(struct acpi_table_header *table)
        }
        WARN_ON(p != end);
 
+       amd_iommu_initialized = true;
+
        return 0;
 }
 
@@ -1263,6 +1270,9 @@ static int __init amd_iommu_init(void)
        if (acpi_table_parse("IVRS", init_iommu_all) != 0)
                goto free;
 
+       if (!amd_iommu_initialized)
+               goto free;
+
        if (acpi_table_parse("IVRS", init_memory_definitions) != 0)
                goto free;
 
index aa57c079c98f6c345e91313e37f3f52e8d3f26bb..e80f291472a4158535e44ed9afac24f8400453b8 100644 (file)
@@ -62,7 +62,7 @@ unsigned int boot_cpu_physical_apicid = -1U;
 /*
  * The highest APIC ID seen during enumeration.
  *
- * On AMD, this determines the messaging protocol we can use: if all APIC IDs
+ * This determines the messaging protocol we can use: if all APIC IDs
  * are in the 0 ... 7 range, then we can use logical addressing which
  * has some performance advantages (better broadcasting).
  *
@@ -1898,14 +1898,24 @@ void __cpuinit generic_processor_info(int apicid, int version)
                max_physical_apicid = apicid;
 
 #ifdef CONFIG_X86_32
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_INTEL:
-               if (num_processors > 8)
-                       def_to_bigsmp = 1;
-               break;
-       case X86_VENDOR_AMD:
-               if (max_physical_apicid >= 8)
+       /*
+        * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
+        * but we need to work other dependencies like SMP_SUSPEND etc
+        * before this can be done without some confusion.
+        * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
+        *       - Ashok Raj <ashok.raj@intel.com>
+        */
+       if (max_physical_apicid >= 8) {
+               switch (boot_cpu_data.x86_vendor) {
+               case X86_VENDOR_INTEL:
+                       if (!APIC_XAPIC(version)) {
+                               def_to_bigsmp = 0;
+                               break;
+                       }
+                       /* If P4 and above fall through */
+               case X86_VENDOR_AMD:
                        def_to_bigsmp = 1;
+               }
        }
 #endif
 
index de00c4619a55b85060a362a5640b141a7492d501..53243ca7816d131ee2821733b722ec0e4d8bd0b3 100644 (file)
@@ -2434,6 +2434,13 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
                cfg = irq_cfg(irq);
                raw_spin_lock(&desc->lock);
 
+               /*
+                * Check if the irq migration is in progress. If so, we
+                * haven't received the cleanup request yet for this irq.
+                */
+               if (cfg->move_in_progress)
+                       goto unlock;
+
                if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
                        goto unlock;
 
index c4cbd3080c1c36e0c798d10a4652427fa4e09603..65edc180fc8297be82347bec05e3cd62d155a86d 100644 (file)
@@ -64,23 +64,16 @@ void __init default_setup_apic_routing(void)
                        apic = &apic_x2apic_phys;
                else
                        apic = &apic_x2apic_cluster;
+               printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
        }
 #endif
 
        if (apic == &apic_flat) {
-               switch (boot_cpu_data.x86_vendor) {
-               case X86_VENDOR_INTEL:
-                       if (num_processors > 8)
-                               apic = &apic_physflat;
-                       break;
-               case X86_VENDOR_AMD:
-                       if (max_physical_apicid >= 8)
-                               apic = &apic_physflat;
-               }
+               if (max_physical_apicid >= 8)
+                       apic = &apic_physflat;
+               printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
        }
 
-       printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
-
        if (is_vsmp_box()) {
                /* need to update phys_pkg_id */
                apic->phys_pkg_id = apicid_phys_pkg_id;
index d56b0efb205706fcc76fb7602b00309020f79e4f..5f92494dab613b9fff4c987b270fed149e4e90f9 100644 (file)
@@ -629,8 +629,10 @@ void __init uv_system_init(void)
        uv_rtc_init();
 
        for_each_present_cpu(cpu) {
+               int apicid = per_cpu(x86_cpu_to_apicid, cpu);
+
                nid = cpu_to_node(cpu);
-               pnode = uv_apicid_to_pnode(per_cpu(x86_cpu_to_apicid, cpu));
+               pnode = uv_apicid_to_pnode(apicid);
                blade = boot_pnode_to_blade(pnode);
                lcpu = uv_blade_info[blade].nr_possible_cpus;
                uv_blade_info[blade].nr_possible_cpus++;
@@ -651,15 +653,13 @@ void __init uv_system_init(void)
                uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra;
                uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
                uv_cpu_hub_info(cpu)->coherency_domain_number = sn_coherency_id;
-               uv_cpu_hub_info(cpu)->scir.offset = SCIR_LOCAL_MMR_BASE + lcpu;
+               uv_cpu_hub_info(cpu)->scir.offset = uv_scir_offset(apicid);
                uv_node_to_blade[nid] = blade;
                uv_cpu_to_blade[cpu] = blade;
                max_pnode = max(pnode, max_pnode);
 
-               printk(KERN_DEBUG "UV: cpu %d, apicid 0x%x, pnode %d, nid %d, "
-                       "lcpu %d, blade %d\n",
-                       cpu, per_cpu(x86_cpu_to_apicid, cpu), pnode, nid,
-                       lcpu, blade);
+               printk(KERN_DEBUG "UV: cpu %d, apicid 0x%x, pnode %d, nid %d, lcpu %d, blade %d\n",
+                       cpu, apicid, pnode, nid, lcpu, blade);
        }
 
        /* Add blade/pnode info for nodes without cpus */
index c223b7e895d9722d720790bd1452d994b7f4d9e0..d616c06e99b4098f9836b28ecd200194bfcd1445 100644 (file)
@@ -2347,7 +2347,7 @@ perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)
        callchain_store(entry, PERF_CONTEXT_KERNEL);
        callchain_store(entry, regs->ip);
 
-       dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry);
+       dump_trace(NULL, regs, NULL, regs->bp, &backtrace_ops, entry);
 }
 
 /*
index 05ed7ab2ca489578c9433930f9df0f03f7526375..a1a7876cadcbfa2b0fdbfa9d9416ee62c14cd85c 100644 (file)
@@ -733,13 +733,13 @@ struct early_res {
 };
 static struct early_res early_res[MAX_EARLY_RES] __initdata = {
        { 0, PAGE_SIZE, "BIOS data page", 1 },  /* BIOS data page */
-#ifdef CONFIG_X86_32
+#if defined(CONFIG_X86_32) && defined(CONFIG_X86_TRAMPOLINE)
        /*
         * But first pinch a few for the stack/trampoline stuff
         * FIXME: Don't need the extra page at 4K, but need to fix
         * trampoline before removing it. (see the GDT stuff)
         */
-       { PAGE_SIZE, PAGE_SIZE, "EX TRAMPOLINE", 1 },
+       { PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE", 1 },
 #endif
 
        {}
index 98c2cdeb599e71ecf2f26f177a8bc6f64cad4cc8..c6ee241c8a980043ff8291cf64c5ae2c84fb5ce5 100644 (file)
@@ -103,8 +103,8 @@ void show_regs_common(void)
        if (!product)
                product = "";
 
-       printk("\n");
-       printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s/%s\n",
+       printk(KERN_CONT "\n");
+       printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s %s/%s\n",
                current->pid, current->comm, print_tainted(),
                init_utsname()->release,
                (int)strcspn(init_utsname()->version, " "),
index 9c517b5858f0943065260484ff2f151846197b13..37ad1e046aae81a7ecdcb367078081adfb647065 100644 (file)
@@ -139,16 +139,16 @@ void __show_regs(struct pt_regs *regs, int all)
 
        show_regs_common();
 
-       printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
+       printk(KERN_DEFAULT "EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
                        (u16)regs->cs, regs->ip, regs->flags,
                        smp_processor_id());
        print_symbol("EIP is at %s\n", regs->ip);
 
-       printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+       printk(KERN_DEFAULT "EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
                regs->ax, regs->bx, regs->cx, regs->dx);
-       printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
+       printk(KERN_DEFAULT "ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
                regs->si, regs->di, regs->bp, sp);
-       printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
+       printk(KERN_DEFAULT " DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
               (u16)regs->ds, (u16)regs->es, (u16)regs->fs, gs, ss);
 
        if (!all)
@@ -158,19 +158,19 @@ void __show_regs(struct pt_regs *regs, int all)
        cr2 = read_cr2();
        cr3 = read_cr3();
        cr4 = read_cr4_safe();
-       printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n",
+       printk(KERN_DEFAULT "CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n",
                        cr0, cr2, cr3, cr4);
 
        get_debugreg(d0, 0);
        get_debugreg(d1, 1);
        get_debugreg(d2, 2);
        get_debugreg(d3, 3);
-       printk("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
+       printk(KERN_DEFAULT "DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
                        d0, d1, d2, d3);
 
        get_debugreg(d6, 6);
        get_debugreg(d7, 7);
-       printk("DR6: %08lx DR7: %08lx\n",
+       printk(KERN_DEFAULT "DR6: %08lx DR7: %08lx\n",
                        d6, d7);
 }
 
index 52fbd0c601987bed689e40693c14e6c38c4f687d..f9e033150cdf9b78e9f46f118092c51b45c4ffc8 100644 (file)
@@ -161,19 +161,19 @@ void __show_regs(struct pt_regs *regs, int all)
        unsigned int ds, cs, es;
 
        show_regs_common();
-       printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
+       printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
        printk_address(regs->ip, 1);
-       printk(KERN_INFO "RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss,
+       printk(KERN_DEFAULT "RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss,
                        regs->sp, regs->flags);
-       printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
+       printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n",
               regs->ax, regs->bx, regs->cx);
-       printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
+       printk(KERN_DEFAULT "RDX: %016lx RSI: %016lx RDI: %016lx\n",
               regs->dx, regs->si, regs->di);
-       printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
+       printk(KERN_DEFAULT "RBP: %016lx R08: %016lx R09: %016lx\n",
               regs->bp, regs->r8, regs->r9);
-       printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
+       printk(KERN_DEFAULT "R10: %016lx R11: %016lx R12: %016lx\n",
               regs->r10, regs->r11, regs->r12);
-       printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
+       printk(KERN_DEFAULT "R13: %016lx R14: %016lx R15: %016lx\n",
               regs->r13, regs->r14, regs->r15);
 
        asm("movl %%ds,%0" : "=r" (ds));
@@ -194,21 +194,21 @@ void __show_regs(struct pt_regs *regs, int all)
        cr3 = read_cr3();
        cr4 = read_cr4();
 
-       printk(KERN_INFO "FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
+       printk(KERN_DEFAULT "FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
               fs, fsindex, gs, gsindex, shadowgs);
-       printk(KERN_INFO "CS:  %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds,
+       printk(KERN_DEFAULT "CS:  %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds,
                        es, cr0);
-       printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3,
+       printk(KERN_DEFAULT "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3,
                        cr4);
 
        get_debugreg(d0, 0);
        get_debugreg(d1, 1);
        get_debugreg(d2, 2);
-       printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
+       printk(KERN_DEFAULT "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
        get_debugreg(d3, 3);
        get_debugreg(d6, 6);
        get_debugreg(d7, 7);
-       printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
+       printk(KERN_DEFAULT "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
 }
 
 void show_regs(struct pt_regs *regs)
index cd60c0bd1b32b158d70f43e373fcd6e477883b10..3063a0c4858b462a23dd8e2b7d6b81342a203fc1 100644 (file)
@@ -1150,6 +1150,7 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
        hrtimer_cancel(&apic->lapic_timer.timer);
        update_divide_count(apic);
        start_apic_timer(apic);
+       apic->irr_pending = true;
 }
 
 void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
index a6017132fba8e8dd9a8600fbc898e4e9e9fbb319..58a0f1e8859655154da07037604ebd5fb1872c7f 100644 (file)
@@ -455,8 +455,6 @@ out_unlock:
 static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
 {
        struct kvm_shadow_walk_iterator iterator;
-       pt_element_t gpte;
-       gpa_t pte_gpa = -1;
        int level;
        u64 *sptep;
        int need_flush = 0;
@@ -470,10 +468,6 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
                if (level == PT_PAGE_TABLE_LEVEL  ||
                    ((level == PT_DIRECTORY_LEVEL && is_large_pte(*sptep))) ||
                    ((level == PT_PDPE_LEVEL && is_large_pte(*sptep)))) {
-                       struct kvm_mmu_page *sp = page_header(__pa(sptep));
-
-                       pte_gpa = (sp->gfn << PAGE_SHIFT);
-                       pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t);
 
                        if (is_shadow_present_pte(*sptep)) {
                                rmap_remove(vcpu->kvm, sptep);
@@ -492,18 +486,6 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
        if (need_flush)
                kvm_flush_remote_tlbs(vcpu->kvm);
        spin_unlock(&vcpu->kvm->mmu_lock);
-
-       if (pte_gpa == -1)
-               return;
-       if (kvm_read_guest_atomic(vcpu->kvm, pte_gpa, &gpte,
-                                 sizeof(pt_element_t)))
-               return;
-       if (is_present_gpte(gpte) && (gpte & PT_ACCESSED_MASK)) {
-               if (mmu_topup_memory_caches(vcpu))
-                       return;
-               kvm_mmu_pte_write(vcpu, pte_gpa, (const u8 *)&gpte,
-                                 sizeof(pt_element_t), 0);
-       }
 }
 
 static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
index 9d068966fb2aa491f00152e22ea047e60984f683..6651dbf58675ee7ec8d9e7f3e145dce09953e054 100644 (file)
@@ -1913,7 +1913,8 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
 
        events->sipi_vector = vcpu->arch.sipi_vector;
 
-       events->flags = 0;
+       events->flags = (KVM_VCPUEVENT_VALID_NMI_PENDING
+                        | KVM_VCPUEVENT_VALID_SIPI_VECTOR);
 
        vcpu_put(vcpu);
 }
@@ -1921,7 +1922,8 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
 static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
                                              struct kvm_vcpu_events *events)
 {
-       if (events->flags)
+       if (events->flags & ~(KVM_VCPUEVENT_VALID_NMI_PENDING
+                             | KVM_VCPUEVENT_VALID_SIPI_VECTOR))
                return -EINVAL;
 
        vcpu_load(vcpu);
@@ -1938,10 +1940,12 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
                kvm_pic_clear_isr_ack(vcpu->kvm);
 
        vcpu->arch.nmi_injected = events->nmi.injected;
-       vcpu->arch.nmi_pending = events->nmi.pending;
+       if (events->flags & KVM_VCPUEVENT_VALID_NMI_PENDING)
+               vcpu->arch.nmi_pending = events->nmi.pending;
        kvm_x86_ops->set_nmi_mask(vcpu, events->nmi.masked);
 
-       vcpu->arch.sipi_vector = events->sipi_vector;
+       if (events->flags & KVM_VCPUEVENT_VALID_SIPI_VECTOR)
+               vcpu->arch.sipi_vector = events->sipi_vector;
 
        vcpu_put(vcpu);
 
index c973f8e2a6cf1db740c6f22ec5bc50bfb65bcc67..9a0c258a86be6b023b59d7880e47e7c38290dfac 100644 (file)
@@ -892,8 +892,7 @@ void __init mem_init(void)
                reservedpages << (PAGE_SHIFT-10),
                datasize >> 10,
                initsize >> 10,
-               (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
-              );
+               totalhigh_pages << (PAGE_SHIFT-10));
 
        printk(KERN_INFO "virtual kernel memory layout:\n"
                "    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
index 4901d0dafda6ceeb7deb60f2964c729f18e8b24e..af3b6c8a436f7b7ec49a2366738a28faa58cdfc5 100644 (file)
@@ -106,26 +106,25 @@ void kmemcheck_error_recall(void)
 
        switch (e->type) {
        case KMEMCHECK_ERROR_INVALID_ACCESS:
-               printk(KERN_ERR  "WARNING: kmemcheck: Caught %d-bit read "
-                       "from %s memory (%p)\n",
+               printk(KERN_WARNING "WARNING: kmemcheck: Caught %d-bit read from %s memory (%p)\n",
                        8 * e->size, e->state < ARRAY_SIZE(desc) ?
                                desc[e->state] : "(invalid shadow state)",
                        (void *) e->address);
 
-               printk(KERN_INFO);
+               printk(KERN_WARNING);
                for (i = 0; i < SHADOW_COPY_SIZE; ++i)
-                       printk("%02x", e->memory_copy[i]);
-               printk("\n");
+                       printk(KERN_CONT "%02x", e->memory_copy[i]);
+               printk(KERN_CONT "\n");
 
-               printk(KERN_INFO);
+               printk(KERN_WARNING);
                for (i = 0; i < SHADOW_COPY_SIZE; ++i) {
                        if (e->shadow_copy[i] < ARRAY_SIZE(short_desc))
-                               printk(" %c", short_desc[e->shadow_copy[i]]);
+                               printk(KERN_CONT " %c", short_desc[e->shadow_copy[i]]);
                        else
-                               printk(" ?");
+                               printk(KERN_CONT " ?");
                }
-               printk("\n");
-               printk(KERN_INFO "%*c\n", 2 + 2
+               printk(KERN_CONT "\n");
+               printk(KERN_WARNING "%*c\n", 2 + 2
                        * (int) (e->address & (SHADOW_COPY_SIZE - 1)), '^');
                break;
        case KMEMCHECK_ERROR_BUG:
index 145df00e038759499d2b70b97babf24255fa8285..f939d603adfab4257dca888766584b378c0be5e9 100644 (file)
@@ -51,7 +51,7 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b)
        }
 }
 
-void __init update_res(struct pci_root_info *info, size_t start,
+void __devinit update_res(struct pci_root_info *info, size_t start,
                              size_t end, unsigned long flags, int merge)
 {
        int i;
index b7a55dc55d13f65b9921400b5a53cbd4ee9213f7..f81a2fa8fe256f0b53e4a4abbb27d998af103d75 100644 (file)
@@ -49,6 +49,10 @@ static void __devinit pci_root_bus_res(struct pci_dev *dev)
        u64 mmioh_base, mmioh_end;
        int bus_base, bus_end;
 
+       /* some sys doesn't get mmconf enabled */
+       if (dev->cfg_size < 0x120)
+               return;
+
        if (pci_root_num >= PCI_ROOT_NR) {
                printk(KERN_DEBUG "intel_bus.c: PCI_ROOT_NR is too small\n");
                return;
index 5bbb5a33f22029f39578114adfef535971e4853a..fd1ab80be0dece39b8f99bdb1f5a0b16e06e7de5 100644 (file)
@@ -8,14 +8,24 @@ BEGIN {
        od_sver = 19;
 }
 
-/^GNU/ {
-       split($3, ver, ".");
+/^GNU objdump/ {
+       verstr = ""
+       for (i = 3; i <= NF; i++)
+               if (match($(i), "^[0-9]")) {
+                       verstr = $(i);
+                       break;
+               }
+       if (verstr == "") {
+               printf("Warning: Failed to find objdump version number.\n");
+               exit 0;
+       }
+       split(verstr, ver, ".");
        if (ver[1] > od_ver ||
            (ver[1] == od_ver && ver[2] >= od_sver)) {
                exit 1;
        } else {
                printf("Warning: objdump version %s is older than %d.%d\n",
-                      $4, od_ver, od_sver);
+                      verstr, od_ver, od_sver);
                print("Warning: Skipping posttest.");
                # Logic is inverted, because we just skip test without error.
                exit 0;
index 8873b9b439ffdb0bf695b0077f84bb28c1046a38..8618d8996fea9c9b278b7529d44ac958c24fa465 100644 (file)
@@ -402,7 +402,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
                 * our current implementations need.  If we'll ever need
                 * more the interface will need revisiting.
                 */
-               page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               page = alloc_page(gfp_mask | __GFP_ZERO);
                if (!page)
                        goto out_free_bio;
                if (bio_add_pc_page(q, bio, page, sector_size, 0) < sector_size)
index 6ae118d6e19340ad60782c00d2476eeb9baeede7..d52d4adc440b29e8d428a9f05d59413d2bb421c9 100644 (file)
@@ -505,21 +505,30 @@ static unsigned int lcm(unsigned int a, unsigned int b)
 
 /**
  * blk_stack_limits - adjust queue_limits for stacked devices
- * @t: the stacking driver limits (top)
- * @b:  the underlying queue limits (bottom)
+ * @t: the stacking driver limits (top device)
+ * @b:  the underlying queue limits (bottom, component device)
  * @offset:  offset to beginning of data within component device
  *
  * Description:
- *    Merges two queue_limit structs.  Returns 0 if alignment didn't
- *    change.  Returns -1 if adding the bottom device caused
- *    misalignment.
+ *    This function is used by stacking drivers like MD and DM to ensure
+ *    that all component devices have compatible block sizes and
+ *    alignments.  The stacking driver must provide a queue_limits
+ *    struct (top) and then iteratively call the stacking function for
+ *    all component (bottom) devices.  The stacking function will
+ *    attempt to combine the values and ensure proper alignment.
+ *
+ *    Returns 0 if the top and bottom queue_limits are compatible.  The
+ *    top device's block sizes and alignment offsets may be adjusted to
+ *    ensure alignment with the bottom device. If no compatible sizes
+ *    and alignments exist, -1 is returned and the resulting top
+ *    queue_limits will have the misaligned flag set to indicate that
+ *    the alignment_offset is undefined.
  */
 int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
                     sector_t offset)
 {
-       int ret;
-
-       ret = 0;
+       sector_t alignment;
+       unsigned int top, bottom;
 
        t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
        t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
@@ -537,6 +546,22 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
        t->max_segment_size = min_not_zero(t->max_segment_size,
                                           b->max_segment_size);
 
+       alignment = queue_limit_alignment_offset(b, offset);
+
+       /* Bottom device has different alignment.  Check that it is
+        * compatible with the current top alignment.
+        */
+       if (t->alignment_offset != alignment) {
+
+               top = max(t->physical_block_size, t->io_min)
+                       + t->alignment_offset;
+               bottom = max(b->physical_block_size, b->io_min) + alignment;
+
+               /* Verify that top and bottom intervals line up */
+               if (max(top, bottom) & (min(top, bottom) - 1))
+                       t->misaligned = 1;
+       }
+
        t->logical_block_size = max(t->logical_block_size,
                                    b->logical_block_size);
 
@@ -544,54 +569,64 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
                                     b->physical_block_size);
 
        t->io_min = max(t->io_min, b->io_min);
+       t->io_opt = lcm(t->io_opt, b->io_opt);
+
        t->no_cluster |= b->no_cluster;
        t->discard_zeroes_data &= b->discard_zeroes_data;
 
-       /* Bottom device offset aligned? */
-       if (offset &&
-           (offset & (b->physical_block_size - 1)) != b->alignment_offset) {
+       /* Physical block size a multiple of the logical block size? */
+       if (t->physical_block_size & (t->logical_block_size - 1)) {
+               t->physical_block_size = t->logical_block_size;
                t->misaligned = 1;
-               ret = -1;
        }
 
-       /*
-        * Temporarily disable discard granularity. It's currently buggy
-        * since we default to 0 for discard_granularity, hence this
-        * "failure" will always trigger for non-zero offsets.
-        */
-#if 0
-       if (offset &&
-           (offset & (b->discard_granularity - 1)) != b->discard_alignment) {
-               t->discard_misaligned = 1;
-               ret = -1;
+       /* Minimum I/O a multiple of the physical block size? */
+       if (t->io_min & (t->physical_block_size - 1)) {
+               t->io_min = t->physical_block_size;
+               t->misaligned = 1;
        }
-#endif
-
-       /* If top has no alignment offset, inherit from bottom */
-       if (!t->alignment_offset)
-               t->alignment_offset =
-                       b->alignment_offset & (b->physical_block_size - 1);
 
-       if (!t->discard_alignment)
-               t->discard_alignment =
-                       b->discard_alignment & (b->discard_granularity - 1);
-
-       /* Top device aligned on logical block boundary? */
-       if (t->alignment_offset & (t->logical_block_size - 1)) {
+       /* Optimal I/O a multiple of the physical block size? */
+       if (t->io_opt & (t->physical_block_size - 1)) {
+               t->io_opt = 0;
                t->misaligned = 1;
-               ret = -1;
        }
 
-       /* Find lcm() of optimal I/O size and granularity */
-       t->io_opt = lcm(t->io_opt, b->io_opt);
-       t->discard_granularity = lcm(t->discard_granularity,
-                                    b->discard_granularity);
+       /* Find lowest common alignment_offset */
+       t->alignment_offset = lcm(t->alignment_offset, alignment)
+               & (max(t->physical_block_size, t->io_min) - 1);
 
-       /* Verify that optimal I/O size is a multiple of io_min */
-       if (t->io_min && t->io_opt % t->io_min)
-               ret = -1;
+       /* Verify that new alignment_offset is on a logical block boundary */
+       if (t->alignment_offset & (t->logical_block_size - 1))
+               t->misaligned = 1;
+
+       /* Discard alignment and granularity */
+       if (b->discard_granularity) {
+               unsigned int granularity = b->discard_granularity;
+               offset &= granularity - 1;
+
+               alignment = (granularity + b->discard_alignment - offset)
+                       & (granularity - 1);
+
+               if (t->discard_granularity != 0 &&
+                   t->discard_alignment != alignment) {
+                       top = t->discard_granularity + t->discard_alignment;
+                       bottom = b->discard_granularity + alignment;
+
+                       /* Verify that top and bottom intervals line up */
+                       if (max(top, bottom) & (min(top, bottom) - 1))
+                               t->discard_misaligned = 1;
+               }
+
+               t->max_discard_sectors = min_not_zero(t->max_discard_sectors,
+                                                     b->max_discard_sectors);
+               t->discard_granularity = max(t->discard_granularity,
+                                            b->discard_granularity);
+               t->discard_alignment = lcm(t->discard_alignment, alignment) &
+                       (t->discard_granularity - 1);
+       }
 
-       return ret;
+       return t->misaligned ? -1 : 0;
 }
 EXPORT_SYMBOL(blk_stack_limits);
 
index e2f80463ed0d621df96bef311543f714462d7f7d..918c7fd9aeb1f9c662606a754ddfafa511193897 100644 (file)
@@ -208,8 +208,6 @@ struct cfq_data {
        /* Root service tree for cfq_groups */
        struct cfq_rb_root grp_service_tree;
        struct cfq_group root_group;
-       /* Number of active cfq groups on group service tree */
-       int nr_groups;
 
        /*
         * The priority currently being served
@@ -294,8 +292,7 @@ static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd);
 
 static struct cfq_rb_root *service_tree_for(struct cfq_group *cfqg,
                                            enum wl_prio_t prio,
-                                           enum wl_type_t type,
-                                           struct cfq_data *cfqd)
+                                           enum wl_type_t type)
 {
        if (!cfqg)
                return NULL;
@@ -842,7 +839,6 @@ cfq_group_service_tree_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
 
        __cfq_group_service_tree_add(st, cfqg);
        cfqg->on_st = true;
-       cfqd->nr_groups++;
        st->total_weight += cfqg->weight;
 }
 
@@ -863,7 +859,6 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg)
 
        cfq_log_cfqg(cfqd, cfqg, "del_from_rr group");
        cfqg->on_st = false;
-       cfqd->nr_groups--;
        st->total_weight -= cfqg->weight;
        if (!RB_EMPTY_NODE(&cfqg->rb_node))
                cfq_rb_erase(&cfqg->rb_node, st);
@@ -1150,7 +1145,7 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 #endif
 
        service_tree = service_tree_for(cfqq->cfqg, cfqq_prio(cfqq),
-                                               cfqq_type(cfqq), cfqd);
+                                               cfqq_type(cfqq));
        if (cfq_class_idle(cfqq)) {
                rb_key = CFQ_IDLE_DELAY;
                parent = rb_last(&service_tree->rb);
@@ -1513,9 +1508,6 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq,
        struct cfq_io_context *cic;
        struct cfq_queue *cfqq;
 
-       /* Deny merge if bio and rq don't belong to same cfq group */
-       if ((RQ_CFQQ(rq))->cfqg != cfq_get_cfqg(cfqd, 0))
-               return false;
        /*
         * Disallow merge of a sync bio into an async request.
         */
@@ -1616,7 +1608,7 @@ static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd)
 {
        struct cfq_rb_root *service_tree =
                service_tree_for(cfqd->serving_group, cfqd->serving_prio,
-                                       cfqd->serving_type, cfqd);
+                                       cfqd->serving_type);
 
        if (!cfqd->rq_queued)
                return NULL;
@@ -1675,13 +1667,17 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,
 #define CFQQ_SEEKY(cfqq)       ((cfqq)->seek_mean > CFQQ_SEEK_THR)
 
 static inline int cfq_rq_close(struct cfq_data *cfqd, struct cfq_queue *cfqq,
-                              struct request *rq)
+                              struct request *rq, bool for_preempt)
 {
        sector_t sdist = cfqq->seek_mean;
 
        if (!sample_valid(cfqq->seek_samples))
                sdist = CFQQ_SEEK_THR;
 
+       /* if seek_mean is big, using it as close criteria is meaningless */
+       if (sdist > CFQQ_SEEK_THR && !for_preempt)
+               sdist = CFQQ_SEEK_THR;
+
        return cfq_dist_from_last(cfqd, rq) <= sdist;
 }
 
@@ -1709,7 +1705,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
         * will contain the closest sector.
         */
        __cfqq = rb_entry(parent, struct cfq_queue, p_node);
-       if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq))
+       if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq, false))
                return __cfqq;
 
        if (blk_rq_pos(__cfqq->next_rq) < sector)
@@ -1720,7 +1716,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
                return NULL;
 
        __cfqq = rb_entry(node, struct cfq_queue, p_node);
-       if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq))
+       if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq, false))
                return __cfqq;
 
        return NULL;
@@ -1963,8 +1959,7 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq)
 }
 
 static enum wl_type_t cfq_choose_wl(struct cfq_data *cfqd,
-                               struct cfq_group *cfqg, enum wl_prio_t prio,
-                               bool prio_changed)
+                               struct cfq_group *cfqg, enum wl_prio_t prio)
 {
        struct cfq_queue *queue;
        int i;
@@ -1972,24 +1967,9 @@ static enum wl_type_t cfq_choose_wl(struct cfq_data *cfqd,
        unsigned long lowest_key = 0;
        enum wl_type_t cur_best = SYNC_NOIDLE_WORKLOAD;
 
-       if (prio_changed) {
-               /*
-                * When priorities switched, we prefer starting
-                * from SYNC_NOIDLE (first choice), or just SYNC
-                * over ASYNC
-                */
-               if (service_tree_for(cfqg, prio, cur_best, cfqd)->count)
-                       return cur_best;
-               cur_best = SYNC_WORKLOAD;
-               if (service_tree_for(cfqg, prio, cur_best, cfqd)->count)
-                       return cur_best;
-
-               return ASYNC_WORKLOAD;
-       }
-
-       for (i = 0; i < 3; ++i) {
-               /* otherwise, select the one with lowest rb_key */
-               queue = cfq_rb_first(service_tree_for(cfqg, prio, i, cfqd));
+       for (i = 0; i <= SYNC_WORKLOAD; ++i) {
+               /* select the one with lowest rb_key */
+               queue = cfq_rb_first(service_tree_for(cfqg, prio, i));
                if (queue &&
                    (!key_valid || time_before(queue->rb_key, lowest_key))) {
                        lowest_key = queue->rb_key;
@@ -2003,8 +1983,6 @@ static enum wl_type_t cfq_choose_wl(struct cfq_data *cfqd,
 
 static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
 {
-       enum wl_prio_t previous_prio = cfqd->serving_prio;
-       bool prio_changed;
        unsigned slice;
        unsigned count;
        struct cfq_rb_root *st;
@@ -2032,24 +2010,19 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
         * (SYNC, SYNC_NOIDLE, ASYNC), and to compute a workload
         * expiration time
         */
-       prio_changed = (cfqd->serving_prio != previous_prio);
-       st = service_tree_for(cfqg, cfqd->serving_prio, cfqd->serving_type,
-                               cfqd);
+       st = service_tree_for(cfqg, cfqd->serving_prio, cfqd->serving_type);
        count = st->count;
 
        /*
-        * If priority didn't change, check workload expiration,
-        * and that we still have other queues ready
+        * check workload expiration, and that we still have other queues ready
         */
-       if (!prio_changed && count &&
-           !time_after(jiffies, cfqd->workload_expires))
+       if (count && !time_after(jiffies, cfqd->workload_expires))
                return;
 
        /* otherwise select new workload type */
        cfqd->serving_type =
-               cfq_choose_wl(cfqd, cfqg, cfqd->serving_prio, prio_changed);
-       st = service_tree_for(cfqg, cfqd->serving_prio, cfqd->serving_type,
-                               cfqd);
+               cfq_choose_wl(cfqd, cfqg, cfqd->serving_prio);
+       st = service_tree_for(cfqg, cfqd->serving_prio, cfqd->serving_type);
        count = st->count;
 
        /*
@@ -3143,7 +3116,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
         * if this request is as-good as one we would expect from the
         * current cfqq, let it preempt
         */
-       if (cfq_rq_close(cfqd, cfqq, rq))
+       if (cfq_rq_close(cfqd, cfqq, rq, true))
                return true;
 
        return false;
index 3ec27c7e62eaff1d541a08b06154d8b197988620..f84f6b4301d98df03dd02c05db9d4351885bc39e 100644 (file)
@@ -214,6 +214,13 @@ static int raid6_test(void)
                err += test(4, &tests);
        if (NDISKS > 5)
                err += test(5, &tests);
+       /* the 11 and 12 disk cases are special for ioatdma (p-disabled
+        * q-continuation without extended descriptor)
+        */
+       if (NDISKS > 12) {
+               err += test(11, &tests);
+               err += test(12, &tests);
+       }
        err += test(NDISKS, &tests);
 
        pr("\n");
index 8a07363417ed8aaa924c10f2c7ae0551968fd971..368ae6d3a096f4fb8f9efd34a1edfe5200bbbb30 100644 (file)
@@ -28,7 +28,7 @@ source "drivers/md/Kconfig"
 
 source "drivers/message/fusion/Kconfig"
 
-source "drivers/ieee1394/Kconfig"
+source "drivers/firewire/Kconfig"
 
 source "drivers/message/i2o/Kconfig"
 
index 5f2c379ab7bfba1903158f5c3f94cf37631a6c44..79d33d908b5a1d2dc586a6536107ffea393c467d 100644 (file)
@@ -80,6 +80,23 @@ static int acpi_sleep_prepare(u32 acpi_state)
 
 #ifdef CONFIG_ACPI_SLEEP
 static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+/*
+ * According to the ACPI specification the BIOS should make sure that ACPI is
+ * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states.  Still,
+ * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
+ * on such systems during resume.  Unfortunately that doesn't help in
+ * particularly pathological cases in which SCI_EN has to be set directly on
+ * resume, although the specification states very clearly that this flag is
+ * owned by the hardware.  The set_sci_en_on_resume variable will be set in such
+ * cases.
+ */
+static bool set_sci_en_on_resume;
+
+void __init acpi_set_sci_en_on_resume(void)
+{
+       set_sci_en_on_resume = true;
+}
+
 /*
  * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
  * user to request that behavior by using the 'acpi_old_suspend_ordering'
@@ -170,18 +187,6 @@ static void acpi_pm_end(void)
 #endif /* CONFIG_ACPI_SLEEP */
 
 #ifdef CONFIG_SUSPEND
-/*
- * According to the ACPI specification the BIOS should make sure that ACPI is
- * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states.  Still,
- * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
- * on such systems during resume.  Unfortunately that doesn't help in
- * particularly pathological cases in which SCI_EN has to be set directly on
- * resume, although the specification states very clearly that this flag is
- * owned by the hardware.  The set_sci_en_on_resume variable will be set in such
- * cases.
- */
-static bool set_sci_en_on_resume;
-
 extern void do_suspend_lowlevel(void);
 
 static u32 acpi_suspend_states[] = {
index 05dff631591c943918749aee95d86c474c781c62..72e76b4b6538f2da73ca4b9060e3cf12ce1808fc 100644 (file)
@@ -999,8 +999,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                sprintf(name, "acpi_video%d", count++);
                device->backlight = backlight_device_register(name,
                        NULL, device, &acpi_backlight_ops);
-               device->backlight->props.max_brightness = device->brightness->count-3;
                kfree(name);
+               if (IS_ERR(device->backlight))
+                       return;
+               device->backlight->props.max_brightness = device->brightness->count-3;
 
                result = sysfs_create_link(&device->backlight->dev.kobj,
                                           &device->dev->dev.kobj, "device");
@@ -1979,6 +1981,10 @@ 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())
+               return 0;
+
        if (!device->brightness)
                goto out;
 
index 48adf80926a086111127a2d49fa370b0a7888947..a5142bddef412e079c3083dec37ffeb82c163cd5 100644 (file)
@@ -446,8 +446,8 @@ EXPORT_SYMBOL_GPL(dpm_resume_noirq);
 
 /**
  * legacy_resume - Execute a legacy (bus or class) resume callback for device.
- * dev: Device to resume.
- * cb: Resume callback to execute.
+ * @dev: Device to resume.
+ * @cb: Resume callback to execute.
  */
 static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
 {
@@ -711,8 +711,9 @@ EXPORT_SYMBOL_GPL(dpm_suspend_noirq);
 
 /**
  * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
- * dev: Device to suspend.
- * cb: Suspend callback to execute.
+ * @dev: Device to suspend.
+ * @state: PM transition of the system being carried out.
+ * @cb: Suspend callback to execute.
  */
 static int legacy_suspend(struct device *dev, pm_message_t state,
                          int (*cb)(struct device *dev, pm_message_t state))
index eb4fa19439444097875d8492ceb6996569e40d45..ce1fa923c414efa246aecde97b95bc7722a46879 100644 (file)
@@ -7101,7 +7101,7 @@ static struct DAC960_privdata DAC960_BA_privdata = {
 
 static struct DAC960_privdata DAC960_LP_privdata = {
        .HardwareType =         DAC960_LP_Controller,
-       .FirmwareType   =       DAC960_LP_Controller,
+       .FirmwareType   =       DAC960_V2_Controller,
        .InterruptHandler =     DAC960_LP_InterruptHandler,
        .MemoryWindowSize =     DAC960_LP_RegisterWindowSize,
 };
index 13bb69d2abb3307d8cb95c9f21e04e0c7b2e9ae8..64a223b0cc2229fb14250dd60fd572b8f8bd9c59 100644 (file)
@@ -735,21 +735,6 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector
        part_stat_unlock();
 }
 
-/*
- * Ensure we don't create aliases in VI caches
- */
-static inline void
-killalias(struct bio *bio)
-{
-       struct bio_vec *bv;
-       int i;
-
-       if (bio_data_dir(bio) == READ)
-               __bio_for_each_segment(bv, bio, i, 0) {
-                       flush_dcache_page(bv->bv_page);
-               }
-}
-
 void
 aoecmd_ata_rsp(struct sk_buff *skb)
 {
@@ -871,7 +856,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
                if (buf->flags & BUFFL_FAIL)
                        bio_endio(buf->bio, -EIO);
                else {
-                       killalias(buf->bio);
+                       bio_flush_dcache_pages(buf->bio);
                        bio_endio(buf->bio, 0);
                }
                mempool_free(buf, d->bufpool);
index 2312d782fe990df0f0db5ca83aa82de5ea1045e2..c9755876343088cb6e0c1ad74f06f8a4cac84f0f 100644 (file)
@@ -1490,7 +1490,7 @@ void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo);
 
 /* drbd_proc.c */
 extern struct proc_dir_entry *drbd_proc;
-extern struct file_operations drbd_proc_fops;
+extern const struct file_operations drbd_proc_fops;
 extern const char *drbd_conn_str(enum drbd_conns s);
 extern const char *drbd_role_str(enum drbd_role s);
 
index 157d1e4343c23a957c751778cd7781cca1ee7833..9348f33f6242e9088f7094ea836d7b0d19e24f0f 100644 (file)
@@ -27,7 +27,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/drbd.h>
 #include <asm/uaccess.h>
 #include <asm/types.h>
@@ -151,7 +150,7 @@ wait_queue_head_t drbd_pp_wait;
 
 DEFINE_RATELIMIT_STATE(drbd_ratelimit_state, 5 * HZ, 5);
 
-static struct block_device_operations drbd_ops = {
+static const struct block_device_operations drbd_ops = {
        .owner =   THIS_MODULE,
        .open =    drbd_open,
        .release = drbd_release,
@@ -3623,7 +3622,7 @@ _drbd_fault_random(struct fault_random_state *rsp)
 {
        long refresh;
 
-       if (--rsp->count < 0) {
+       if (!rsp->count--) {
                get_random_bytes(&refresh, sizeof(refresh));
                rsp->state += refresh;
                rsp->count = FAULT_RANDOM_REFRESH;
index bdd0b4943b1033b931b44b74697017a9976d1178..df8ad9660d8f969adff252371ce86be9f2ab4aab 100644 (file)
@@ -38,7 +38,7 @@ static int drbd_proc_open(struct inode *inode, struct file *file);
 
 
 struct proc_dir_entry *drbd_proc;
-struct file_operations drbd_proc_fops = {
+const struct file_operations drbd_proc_fops = {
        .owner          = THIS_MODULE,
        .open           = drbd_proc_open,
        .read           = seq_read,
index c548f24f54a19a8262bce0f4200a54291b84cbca..259c1351b1528da954d446edc4b984bcea2e2a39 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/uaccess.h>
 #include <net/sock.h>
 
-#include <linux/version.h>
 #include <linux/drbd.h>
 #include <linux/fs.h>
 #include <linux/file.h>
index ed8796f1112d933004a6feea740765d3251cce65..b453c2bca3be5d3740c81be7e41d2ff953bb937d 100644 (file)
@@ -24,7 +24,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/drbd.h>
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
@@ -34,7 +33,6 @@
 #include <linux/mm_inline.h>
 #include <linux/slab.h>
 #include <linux/random.h>
-#include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/scatterlist.h>
 
index e0339aaa18154303316c8405d72c08af4b036ffd..02b2583df7fc225184dbf704a28aade8d24128ec 100644 (file)
@@ -860,7 +860,7 @@ static int mg_probe(struct platform_device *plat_dev)
                err = -EINVAL;
                goto probe_err_2;
        }
-       host->dev_base = ioremap(rsc->start , rsc->end + 1);
+       host->dev_base = ioremap(rsc->start, resource_size(rsc));
        if (!host->dev_base) {
                printk(KERN_ERR "%s:%d ioremap fail\n",
                                __func__, __LINE__);
index 2fb2e6cc322aab1a36164de3fc99674559dea9ed..5aa7a586a7ffc2716004ea771f191a6d548efc15 100644 (file)
@@ -725,9 +725,14 @@ static struct pci_driver agp_amd64_pci_driver = {
 int __init agp_amd64_init(void)
 {
        int err = 0;
+       static int done = 0;
 
        if (agp_off)
                return -EINVAL;
+
+       if (done++)
+               return agp_bridges_found ? 0 : -ENODEV;
+
        err = pci_register_driver(&agp_amd64_pci_driver);
        if (err < 0)
                return err;
@@ -771,12 +776,8 @@ static void __exit agp_amd64_cleanup(void)
        pci_unregister_driver(&agp_amd64_pci_driver);
 }
 
-/* On AMD64 the PCI driver needs to initialize this driver early
-   for the IOMMU, so it has to be called via a backdoor. */
-#ifndef CONFIG_GART_IOMMU
 module_init(agp_amd64_init);
 module_exit(agp_amd64_cleanup);
-#endif
 
 MODULE_AUTHOR("Dave Jones <davej@redhat.com>, Andi Kleen");
 module_param(agp_try_unsupported, bool, 0);
index a56ca080e108f20e6680bc774f4fb7eb680edf21..c3ab46da51a35da4bfb5a6965a02e4c5d8c96401 100644 (file)
@@ -285,18 +285,22 @@ int agp_add_bridge(struct agp_bridge_data *bridge)
 {
        int error;
 
-       if (agp_off)
-               return -ENODEV;
+       if (agp_off) {
+               error = -ENODEV;
+               goto err_put_bridge;
+       }
 
        if (!bridge->dev) {
                printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n");
-               return -EINVAL;
+               error = -EINVAL;
+               goto err_put_bridge;
        }
 
        /* Grab reference on the chipset driver. */
        if (!try_module_get(bridge->driver->owner)) {
                dev_info(&bridge->dev->dev, "can't lock chipset driver\n");
-               return -EINVAL;
+               error = -EINVAL;
+               goto err_put_bridge;
        }
 
        error = agp_backend_initialize(bridge);
@@ -326,6 +330,7 @@ frontend_err:
        agp_backend_cleanup(bridge);
 err_out:
        module_put(bridge->driver->owner);
+err_put_bridge:
        agp_put_bridge(bridge);
        return error;
 }
index 9047b2714653c54ef3c0130f30e09cd98e0bc534..58752b70efead7a76ca65c1441574dfa50931a07 100644 (file)
@@ -488,9 +488,8 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
        handle = obj;
        do {
                status = acpi_get_object_info(handle, &info);
-               if (ACPI_SUCCESS(status)) {
+               if (ACPI_SUCCESS(status) && (info->valid & ACPI_VALID_HID)) {
                        /* TBD check _CID also */
-                       info->hardware_id.string[sizeof(info->hardware_id.length)-1] = '\0';
                        match = (strcmp(info->hardware_id.string, "HWP0001") == 0);
                        kfree(info);
                        if (match) {
@@ -509,6 +508,9 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
                handle = parent;
        } while (ACPI_SUCCESS(status));
 
+       if (ACPI_FAILURE(status))
+               return AE_OK;   /* found no enclosing IOC */
+
        if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa))
                return AE_OK;
 
index e989f67bb61f14b84fd66f90f1a87008ff9117dc..3d9c61e5acbf2adb354a70e0a8ba532568ef06d0 100644 (file)
@@ -158,10 +158,11 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
                        goto out;
                }
        }
-out_unlock:
-       mutex_unlock(&rng_mutex);
 out:
        return ret ? : err;
+out_unlock:
+       mutex_unlock(&rng_mutex);
+       goto out;
 }
 
 
index 679cd08b80b4444ed02d640793251aaa25806f6e..176f1751237f57807f3023d9427972dcb6614392 100644 (file)
@@ -3204,7 +3204,7 @@ static __devinit int init_ipmi_si(void)
 #ifdef CONFIG_ACPI
        spmi_find_bmc();
 #endif
-#ifdef CONFIG_PNP
+#ifdef CONFIG_ACPI
        pnp_register_driver(&ipmi_pnp_driver);
 #endif
 
@@ -3330,7 +3330,7 @@ static __exit void cleanup_ipmi_si(void)
 #ifdef CONFIG_PCI
        pci_unregister_driver(&ipmi_pci_driver);
 #endif
-#ifdef CONFIG_PNP
+#ifdef CONFIG_ACPI
        pnp_unregister_driver(&ipmi_pnp_driver);
 #endif
 
index 0798754a607cea4dbf6414f3b3cff0792108f731..bba727c3807e355391df8df0c54385be0af07e5a 100644 (file)
@@ -50,7 +50,6 @@
 #include <linux/err.h>
 #include <linux/kfifo.h>
 #include <linux/platform_device.h>
-#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -905,14 +904,13 @@ static int sonypi_misc_release(struct inode *inode, struct file *file)
 
 static int sonypi_misc_open(struct inode *inode, struct file *file)
 {
-       lock_kernel();
        mutex_lock(&sonypi_device.lock);
        /* Flush input queue on first open */
        if (!sonypi_device.open_count)
                kfifo_reset(&sonypi_device.fifo);
        sonypi_device.open_count++;
        mutex_unlock(&sonypi_device.lock);
-       unlock_kernel();
+
        return 0;
 }
 
@@ -955,10 +953,10 @@ static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
        return 0;
 }
 
-static int sonypi_misc_ioctl(struct inode *ip, struct file *fp,
+static long sonypi_misc_ioctl(struct file *fp,
                             unsigned int cmd, unsigned long arg)
 {
-       int ret = 0;
+       long ret = 0;
        void __user *argp = (void __user *)arg;
        u8 val8;
        u16 val16;
@@ -1074,7 +1072,8 @@ static const struct file_operations sonypi_misc_fops = {
        .open           = sonypi_misc_open,
        .release        = sonypi_misc_release,
        .fasync         = sonypi_misc_fasync,
-       .ioctl          = sonypi_misc_ioctl,
+       .unlocked_ioctl = sonypi_misc_ioctl,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice sonypi_misc_device = {
index 663cd15d7c78fa5a0cbd548179f61b352ba53e38..f8bc79f6de34875cba7ac1e74e9110ff3c236d53 100644 (file)
@@ -68,7 +68,7 @@
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-
+#include <linux/smp_lock.h>
 #include <linux/toshiba.h>
 
 #define TOSH_MINOR_DEV 181
@@ -88,13 +88,13 @@ static int tosh_date;
 static int tosh_sci;
 static int tosh_fan;
 
-static int tosh_ioctl(struct inode *, struct file *, unsigned int,
+static long tosh_ioctl(struct file *, unsigned int,
        unsigned long);
 
 
 static const struct file_operations tosh_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = tosh_ioctl,
+       .unlocked_ioctl = tosh_ioctl,
 };
 
 static struct miscdevice tosh_device = {
@@ -252,8 +252,7 @@ int tosh_smm(SMMRegisters *regs)
 EXPORT_SYMBOL(tosh_smm);
 
 
-static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-       unsigned long arg)
+static long tosh_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 {
        SMMRegisters regs;
        SMMRegisters __user *argp = (SMMRegisters __user *)arg;
@@ -275,13 +274,16 @@ static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
                                return -EINVAL;
 
                        /* do we need to emulate the fan ? */
+                       lock_kernel();
                        if (tosh_fan==1) {
                                if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) {
                                        err = tosh_emulate_fan(&regs);
+                                       unlock_kernel();
                                        break;
                                }
                        }
                        err = tosh_smm(&regs);
+                       unlock_kernel();
                        break;
                default:
                        return -EINVAL;
index 68104434ebb51c98c4b3b81e599df006840891ce..73655aeb3a60993e28fbbf9ea7930128e5a23407 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
 #include <linux/sched.h>
+#include <linux/math64.h>
 
 #define BUCKETS 12
 #define RESOLUTION 1024
@@ -169,6 +170,12 @@ static DEFINE_PER_CPU(struct menu_device, menu_devices);
 
 static void menu_update(struct cpuidle_device *dev);
 
+/* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */
+static u64 div_round64(u64 dividend, u32 divisor)
+{
+       return div_u64(dividend + (divisor / 2), divisor);
+}
+
 /**
  * menu_select - selects the next idle state to enter
  * @dev: the CPU
@@ -209,9 +216,8 @@ static int menu_select(struct cpuidle_device *dev)
                data->correction_factor[data->bucket] = RESOLUTION * DECAY;
 
        /* Make sure to round up for half microseconds */
-       data->predicted_us = DIV_ROUND_CLOSEST(
-               data->expected_us * data->correction_factor[data->bucket],
-               RESOLUTION * DECAY);
+       data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket],
+                                        RESOLUTION * DECAY);
 
        /*
         * We want to default to C1 (hlt), not to busy polling
index f15112569c1d686b5a1f6ea9213a7fabd6065f3c..efc1a61ca2310bec0b517d20d7675c3f800f0717 100644 (file)
@@ -815,7 +815,7 @@ atc_is_tx_complete(struct dma_chan *chan,
        dev_vdbg(chan2dev(chan), "is_tx_complete: %d (d%d, u%d)\n",
                        cookie, done ? *done : 0, used ? *used : 0);
 
-       spin_lock_bh(atchan->lock);
+       spin_lock_bh(&atchan->lock);
 
        last_complete = atchan->completed_cookie;
        last_used = chan->cookie;
@@ -830,7 +830,7 @@ atc_is_tx_complete(struct dma_chan *chan,
                ret = dma_async_is_complete(cookie, last_complete, last_used);
        }
 
-       spin_unlock_bh(atchan->lock);
+       spin_unlock_bh(&atchan->lock);
 
        if (done)
                *done = last_complete;
index 4a99cd94536b7219199811e6d00006c7cef5c679..b5f2ee0f8e2c60e8389527e19cc522058b777b52 100644 (file)
@@ -1294,8 +1294,8 @@ static int __exit coh901318_remove(struct platform_device *pdev)
        dma_async_device_unregister(&base->dma_slave);
        coh901318_pool_destroy(&base->pool);
        free_irq(platform_get_irq(pdev, 0), base);
-       kfree(base);
        iounmap(base->virtbase);
+       kfree(base);
        release_mem_region(pdev->resource->start,
                           resource_size(pdev->resource));
        return 0;
index 285bed0fe17bbae3e672a9b4d1cebe844cb4888a..d28369f7afd2ba8a2da690b235c0318a89719a82 100644 (file)
@@ -1270,8 +1270,6 @@ static int __init dw_probe(struct platform_device *pdev)
                goto err_kfree;
        }
 
-       memset(dw, 0, sizeof *dw);
-
        dw->regs = ioremap(io->start, DW_REGLEN);
        if (!dw->regs) {
                err = -ENOMEM;
index c524d36d3c2e199db83e5b2a9a8a7b7bf1939a21..dcc4ab78b32b79a5d54fc3e8dab9f7af6b61ecc4 100644 (file)
@@ -1032,7 +1032,7 @@ int __devinit ioat_probe(struct ioatdma_device *device)
        dma->dev = &pdev->dev;
 
        if (!dma->chancnt) {
-               dev_err(dev, "zero channels detected\n");
+               dev_err(dev, "channel enumeration error\n");
                goto err_setup_interrupts;
        }
 
index 45edde99648070e8c9a0ca14f214ead551cbfc84..bbc3e78ef3334f60f025cbb9361d95fb46b38249 100644 (file)
@@ -60,6 +60,7 @@
  * @dca: direct cache access context
  * @intr_quirk: interrupt setup quirk (for ioat_v1 devices)
  * @enumerate_channels: hw version specific channel enumeration
+ * @reset_hw: hw version specific channel (re)initialization
  * @cleanup_tasklet: select between the v2 and v3 cleanup routines
  * @timer_fn: select between the v2 and v3 timer watchdog routines
  * @self_test: hardware version specific self test for each supported op type
@@ -78,6 +79,7 @@ struct ioatdma_device {
        struct dca_provider *dca;
        void (*intr_quirk)(struct ioatdma_device *device);
        int (*enumerate_channels)(struct ioatdma_device *device);
+       int (*reset_hw)(struct ioat_chan_common *chan);
        void (*cleanup_tasklet)(unsigned long data);
        void (*timer_fn)(unsigned long data);
        int (*self_test)(struct ioatdma_device *device);
@@ -264,6 +266,22 @@ static inline void ioat_suspend(struct ioat_chan_common *chan)
        writeb(IOAT_CHANCMD_SUSPEND, chan->reg_base + IOAT_CHANCMD_OFFSET(ver));
 }
 
+static inline void ioat_reset(struct ioat_chan_common *chan)
+{
+       u8 ver = chan->device->version;
+
+       writeb(IOAT_CHANCMD_RESET, chan->reg_base + IOAT_CHANCMD_OFFSET(ver));
+}
+
+static inline bool ioat_reset_pending(struct ioat_chan_common *chan)
+{
+       u8 ver = chan->device->version;
+       u8 cmd;
+
+       cmd = readb(chan->reg_base + IOAT_CHANCMD_OFFSET(ver));
+       return (cmd & IOAT_CHANCMD_RESET) == IOAT_CHANCMD_RESET;
+}
+
 static inline void ioat_set_chainaddr(struct ioat_dma_chan *ioat, u64 addr)
 {
        struct ioat_chan_common *chan = &ioat->base;
index 8f1f7f05deaadaac6cd428cbef09e35e161ededc..5f7a500e18d02636f1b94650202f6b2614323bb7 100644 (file)
@@ -239,20 +239,50 @@ void __ioat2_restart_chan(struct ioat2_dma_chan *ioat)
                __ioat2_start_null_desc(ioat);
 }
 
-static void ioat2_restart_channel(struct ioat2_dma_chan *ioat)
+int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo)
 {
-       struct ioat_chan_common *chan = &ioat->base;
-       unsigned long phys_complete;
+       unsigned long end = jiffies + tmo;
+       int err = 0;
        u32 status;
 
        status = ioat_chansts(chan);
        if (is_ioat_active(status) || is_ioat_idle(status))
                ioat_suspend(chan);
        while (is_ioat_active(status) || is_ioat_idle(status)) {
+               if (end && time_after(jiffies, end)) {
+                       err = -ETIMEDOUT;
+                       break;
+               }
                status = ioat_chansts(chan);
                cpu_relax();
        }
 
+       return err;
+}
+
+int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo)
+{
+       unsigned long end = jiffies + tmo;
+       int err = 0;
+
+       ioat_reset(chan);
+       while (ioat_reset_pending(chan)) {
+               if (end && time_after(jiffies, end)) {
+                       err = -ETIMEDOUT;
+                       break;
+               }
+               cpu_relax();
+       }
+
+       return err;
+}
+
+static void ioat2_restart_channel(struct ioat2_dma_chan *ioat)
+{
+       struct ioat_chan_common *chan = &ioat->base;
+       unsigned long phys_complete;
+
+       ioat2_quiesce(chan, 0);
        if (ioat_cleanup_preamble(chan, &phys_complete))
                __cleanup(ioat, phys_complete);
 
@@ -318,6 +348,19 @@ void ioat2_timer_event(unsigned long data)
        spin_unlock_bh(&chan->cleanup_lock);
 }
 
+static int ioat2_reset_hw(struct ioat_chan_common *chan)
+{
+       /* throw away whatever the channel was doing and get it initialized */
+       u32 chanerr;
+
+       ioat2_quiesce(chan, msecs_to_jiffies(100));
+
+       chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
+       writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET);
+
+       return ioat2_reset_sync(chan, msecs_to_jiffies(200));
+}
+
 /**
  * ioat2_enumerate_channels - find and initialize the device's channels
  * @device: the device to be enumerated
@@ -360,6 +403,10 @@ int ioat2_enumerate_channels(struct ioatdma_device *device)
                                  (unsigned long) ioat);
                ioat->xfercap_log = xfercap_log;
                spin_lock_init(&ioat->ring_lock);
+               if (device->reset_hw(&ioat->base)) {
+                       i = 0;
+                       break;
+               }
        }
        dma->chancnt = i;
        return i;
@@ -467,7 +514,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c)
        struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
        struct ioat_chan_common *chan = &ioat->base;
        struct ioat_ring_ent **ring;
-       u32 chanerr;
        int order;
 
        /* have we already been set up? */
@@ -477,12 +523,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c)
        /* Setup register to interrupt and write completion status on error */
        writew(IOAT_CHANCTRL_RUN, chan->reg_base + IOAT_CHANCTRL_OFFSET);
 
-       chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
-       if (chanerr) {
-               dev_err(to_dev(chan), "CHANERR = %x, clearing\n", chanerr);
-               writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET);
-       }
-
        /* allocate a completion writeback area */
        /* doing 2 32bit writes to mmio since 1 64b write doesn't work */
        chan->completion = pci_pool_alloc(chan->device->completion_pool,
@@ -746,13 +786,7 @@ void ioat2_free_chan_resources(struct dma_chan *c)
        tasklet_disable(&chan->cleanup_task);
        del_timer_sync(&chan->timer);
        device->cleanup_tasklet((unsigned long) ioat);
-
-       /* Delay 100ms after reset to allow internal DMA logic to quiesce
-        * before removing DMA descriptor resources.
-        */
-       writeb(IOAT_CHANCMD_RESET,
-              chan->reg_base + IOAT_CHANCMD_OFFSET(chan->device->version));
-       mdelay(100);
+       device->reset_hw(chan);
 
        spin_lock_bh(&ioat->ring_lock);
        descs = ioat2_ring_space(ioat);
@@ -839,6 +873,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca)
        int err;
 
        device->enumerate_channels = ioat2_enumerate_channels;
+       device->reset_hw = ioat2_reset_hw;
        device->cleanup_tasklet = ioat2_cleanup_tasklet;
        device->timer_fn = ioat2_timer_event;
        device->self_test = ioat_dma_self_test;
index 1d849ef74d5f7ff3a14bc7350ce58ce7d42be9c8..3afad8da43ccf1a71354fc2400cd7eca9beb2901 100644 (file)
@@ -185,6 +185,8 @@ bool reshape_ring(struct ioat2_dma_chan *ioat, int order);
 void __ioat2_issue_pending(struct ioat2_dma_chan *ioat);
 void ioat2_cleanup_tasklet(unsigned long data);
 void ioat2_timer_event(unsigned long data);
+int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo);
+int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo);
 extern struct kobj_type ioat2_ktype;
 extern struct kmem_cache *ioat2_cache;
 #endif /* IOATDMA_V2_H */
index 42f6f10fb0cc249b2b07854f00e556f8335029d7..9908c9e94b2d0c9ba150eeefb507e48cb6cc0a5b 100644 (file)
@@ -650,9 +650,11 @@ __ioat3_prep_pq_lock(struct dma_chan *c, enum sum_check_flags *result,
 
        num_descs = ioat2_xferlen_to_descs(ioat, len);
        /* we need 2x the number of descriptors to cover greater than 3
-        * sources
+        * sources (we need 1 extra source in the q-only continuation
+        * case and 3 extra sources in the p+q continuation case.
         */
-       if (src_cnt > 3 || flags & DMA_PREP_CONTINUE) {
+       if (src_cnt + dmaf_p_disabled_continue(flags) > 3 ||
+           (dmaf_continue(flags) && !dmaf_p_disabled_continue(flags))) {
                with_ext = 1;
                num_descs *= 2;
        } else
@@ -1128,6 +1130,45 @@ static int __devinit ioat3_dma_self_test(struct ioatdma_device *device)
        return 0;
 }
 
+static int ioat3_reset_hw(struct ioat_chan_common *chan)
+{
+       /* throw away whatever the channel was doing and get it
+        * initialized, with ioat3 specific workarounds
+        */
+       struct ioatdma_device *device = chan->device;
+       struct pci_dev *pdev = device->pdev;
+       u32 chanerr;
+       u16 dev_id;
+       int err;
+
+       ioat2_quiesce(chan, msecs_to_jiffies(100));
+
+       chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
+       writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET);
+
+       /* -= IOAT ver.3 workarounds =- */
+       /* Write CHANERRMSK_INT with 3E07h to mask out the errors
+        * that can cause stability issues for IOAT ver.3, and clear any
+        * pending errors
+        */
+       pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07);
+       err = pci_read_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, &chanerr);
+       if (err) {
+               dev_err(&pdev->dev, "channel error register unreachable\n");
+               return err;
+       }
+       pci_write_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, chanerr);
+
+       /* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit
+        * (workaround for spurious config parity error after restart)
+        */
+       pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id);
+       if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0)
+               pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10);
+
+       return ioat2_reset_sync(chan, msecs_to_jiffies(200));
+}
+
 int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)
 {
        struct pci_dev *pdev = device->pdev;
@@ -1137,10 +1178,10 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)
        struct ioat_chan_common *chan;
        bool is_raid_device = false;
        int err;
-       u16 dev_id;
        u32 cap;
 
        device->enumerate_channels = ioat2_enumerate_channels;
+       device->reset_hw = ioat3_reset_hw;
        device->self_test = ioat3_dma_self_test;
        dma = &device->common;
        dma->device_prep_dma_memcpy = ioat2_dma_prep_memcpy_lock;
@@ -1216,19 +1257,6 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)
        dma->device_prep_dma_xor_val = NULL;
        #endif
 
-       /* -= IOAT ver.3 workarounds =- */
-       /* Write CHANERRMSK_INT with 3E07h to mask out the errors
-        * that can cause stability issues for IOAT ver.3
-        */
-       pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07);
-
-       /* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit
-        * (workaround for spurious config parity error after restart)
-        */
-       pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id);
-       if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0)
-               pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10);
-
        err = ioat_probe(device);
        if (err)
                return err;
index f015ec1967004ed103149c5e93b8ad2d670eae80..e8ae63baf5887f6fed78f7d2fa33ffbf61a89301 100644 (file)
@@ -27,6 +27,7 @@
 
 #define IOAT_PCI_DEVICE_ID_OFFSET              0x02
 #define IOAT_PCI_DMAUNCERRSTS_OFFSET           0x148
+#define IOAT_PCI_CHANERR_INT_OFFSET            0x180
 #define IOAT_PCI_CHANERRMASK_INT_OFFSET                0x184
 
 /* MMIO Device Registers */
index 2e4a54c8afeb842d63deceee9fa5d50030aa713e..d10cc899c460619b072466805c078cb989c496dd 100644 (file)
 #include <linux/dmaengine.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
 #include <linux/platform_device.h>
 #include <cpu/dma.h>
 #include <asm/dma-sh.h>
 #include "shdma.h"
 
 /* DMA descriptor control */
-#define DESC_LAST      (-1)
-#define DESC_COMP      (1)
-#define DESC_NCOMP     (0)
+enum sh_dmae_desc_status {
+       DESC_IDLE,
+       DESC_PREPARED,
+       DESC_SUBMITTED,
+       DESC_COMPLETED, /* completed, have to call callback */
+       DESC_WAITING,   /* callback called, waiting for ack / re-submit */
+};
 
 #define NR_DESCS_PER_CHANNEL 32
 /*
@@ -45,6 +48,8 @@
  */
 #define RS_DEFAULT  (RS_DUAL)
 
+static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
+
 #define SH_DMAC_CHAN_BASE(id) (dma_base_addr[id])
 static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
 {
@@ -106,11 +111,11 @@ static inline unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan)
        return ts_shift[(chcr & CHCR_TS_MASK) >> CHCR_TS_SHIFT];
 }
 
-static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs hw)
+static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
 {
-       sh_dmae_writel(sh_chan, hw.sar, SAR);
-       sh_dmae_writel(sh_chan, hw.dar, DAR);
-       sh_dmae_writel(sh_chan, hw.tcr >> calc_xmit_shift(sh_chan), TCR);
+       sh_dmae_writel(sh_chan, hw->sar, SAR);
+       sh_dmae_writel(sh_chan, hw->dar, DAR);
+       sh_dmae_writel(sh_chan, hw->tcr >> calc_xmit_shift(sh_chan), TCR);
 }
 
 static void dmae_start(struct sh_dmae_chan *sh_chan)
@@ -184,8 +189,9 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
 
 static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
 {
-       struct sh_desc *desc = tx_to_sh_desc(tx);
+       struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c;
        struct sh_dmae_chan *sh_chan = to_sh_chan(tx->chan);
+       dma_async_tx_callback callback = tx->callback;
        dma_cookie_t cookie;
 
        spin_lock_bh(&sh_chan->desc_lock);
@@ -195,45 +201,53 @@ static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
        if (cookie < 0)
                cookie = 1;
 
-       /* If desc only in the case of 1 */
-       if (desc->async_tx.cookie != -EBUSY)
-               desc->async_tx.cookie = cookie;
-       sh_chan->common.cookie = desc->async_tx.cookie;
+       sh_chan->common.cookie = cookie;
+       tx->cookie = cookie;
+
+       /* Mark all chunks of this descriptor as submitted, move to the queue */
+       list_for_each_entry_safe(chunk, c, desc->node.prev, node) {
+               /*
+                * All chunks are on the global ld_free, so, we have to find
+                * the end of the chain ourselves
+                */
+               if (chunk != desc && (chunk->mark == DESC_IDLE ||
+                                     chunk->async_tx.cookie > 0 ||
+                                     chunk->async_tx.cookie == -EBUSY ||
+                                     &chunk->node == &sh_chan->ld_free))
+                       break;
+               chunk->mark = DESC_SUBMITTED;
+               /* Callback goes to the last chunk */
+               chunk->async_tx.callback = NULL;
+               chunk->cookie = cookie;
+               list_move_tail(&chunk->node, &sh_chan->ld_queue);
+               last = chunk;
+       }
+
+       last->async_tx.callback = callback;
+       last->async_tx.callback_param = tx->callback_param;
 
-       list_splice_init(&desc->tx_list, sh_chan->ld_queue.prev);
+       dev_dbg(sh_chan->dev, "submit #%d@%p on %d: %x[%d] -> %x\n",
+               tx->cookie, &last->async_tx, sh_chan->id,
+               desc->hw.sar, desc->hw.tcr, desc->hw.dar);
 
        spin_unlock_bh(&sh_chan->desc_lock);
 
        return cookie;
 }
 
+/* Called with desc_lock held */
 static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan)
 {
-       struct sh_desc *desc, *_desc, *ret = NULL;
+       struct sh_desc *desc;
 
-       spin_lock_bh(&sh_chan->desc_lock);
-       list_for_each_entry_safe(desc, _desc, &sh_chan->ld_free, node) {
-               if (async_tx_test_ack(&desc->async_tx)) {
+       list_for_each_entry(desc, &sh_chan->ld_free, node)
+               if (desc->mark != DESC_PREPARED) {
+                       BUG_ON(desc->mark != DESC_IDLE);
                        list_del(&desc->node);
-                       ret = desc;
-                       break;
+                       return desc;
                }
-       }
-       spin_unlock_bh(&sh_chan->desc_lock);
-
-       return ret;
-}
-
-static void sh_dmae_put_desc(struct sh_dmae_chan *sh_chan, struct sh_desc *desc)
-{
-       if (desc) {
-               spin_lock_bh(&sh_chan->desc_lock);
-
-               list_splice_init(&desc->tx_list, &sh_chan->ld_free);
-               list_add(&desc->node, &sh_chan->ld_free);
 
-               spin_unlock_bh(&sh_chan->desc_lock);
-       }
+       return NULL;
 }
 
 static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
@@ -252,11 +266,10 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
                dma_async_tx_descriptor_init(&desc->async_tx,
                                        &sh_chan->common);
                desc->async_tx.tx_submit = sh_dmae_tx_submit;
-               desc->async_tx.flags = DMA_CTRL_ACK;
-               INIT_LIST_HEAD(&desc->tx_list);
-               sh_dmae_put_desc(sh_chan, desc);
+               desc->mark = DESC_IDLE;
 
                spin_lock_bh(&sh_chan->desc_lock);
+               list_add(&desc->node, &sh_chan->ld_free);
                sh_chan->descs_allocated++;
        }
        spin_unlock_bh(&sh_chan->desc_lock);
@@ -273,7 +286,10 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
        struct sh_desc *desc, *_desc;
        LIST_HEAD(list);
 
-       BUG_ON(!list_empty(&sh_chan->ld_queue));
+       /* Prepared and not submitted descriptors can still be on the queue */
+       if (!list_empty(&sh_chan->ld_queue))
+               sh_dmae_chan_ld_cleanup(sh_chan, true);
+
        spin_lock_bh(&sh_chan->desc_lock);
 
        list_splice_init(&sh_chan->ld_free, &list);
@@ -292,6 +308,8 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
        struct sh_dmae_chan *sh_chan;
        struct sh_desc *first = NULL, *prev = NULL, *new;
        size_t copy_size;
+       LIST_HEAD(tx_list);
+       int chunks = (len + SH_DMA_TCR_MAX) / (SH_DMA_TCR_MAX + 1);
 
        if (!chan)
                return NULL;
@@ -301,108 +319,189 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
 
        sh_chan = to_sh_chan(chan);
 
+       /* Have to lock the whole loop to protect against concurrent release */
+       spin_lock_bh(&sh_chan->desc_lock);
+
+       /*
+        * Chaining:
+        * first descriptor is what user is dealing with in all API calls, its
+        *      cookie is at first set to -EBUSY, at tx-submit to a positive
+        *      number
+        * if more than one chunk is needed further chunks have cookie = -EINVAL
+        * the last chunk, if not equal to the first, has cookie = -ENOSPC
+        * all chunks are linked onto the tx_list head with their .node heads
+        *      only during this function, then they are immediately spliced
+        *      back onto the free list in form of a chain
+        */
        do {
-               /* Allocate the link descriptor from DMA pool */
+               /* Allocate the link descriptor from the free list */
                new = sh_dmae_get_desc(sh_chan);
                if (!new) {
                        dev_err(sh_chan->dev,
                                "No free memory for link descriptor\n");
-                       goto err_get_desc;
+                       list_for_each_entry(new, &tx_list, node)
+                               new->mark = DESC_IDLE;
+                       list_splice(&tx_list, &sh_chan->ld_free);
+                       spin_unlock_bh(&sh_chan->desc_lock);
+                       return NULL;
                }
 
-               copy_size = min(len, (size_t)SH_DMA_TCR_MAX);
+               copy_size = min(len, (size_t)SH_DMA_TCR_MAX + 1);
 
                new->hw.sar = dma_src;
                new->hw.dar = dma_dest;
                new->hw.tcr = copy_size;
-               if (!first)
+               if (!first) {
+                       /* First desc */
+                       new->async_tx.cookie = -EBUSY;
                        first = new;
+               } else {
+                       /* Other desc - invisible to the user */
+                       new->async_tx.cookie = -EINVAL;
+               }
 
-               new->mark = DESC_NCOMP;
-               async_tx_ack(&new->async_tx);
+               dev_dbg(sh_chan->dev,
+                       "chaining %u of %u with %p, dst %x, cookie %d\n",
+                       copy_size, len, &new->async_tx, dma_dest,
+                       new->async_tx.cookie);
+
+               new->mark = DESC_PREPARED;
+               new->async_tx.flags = flags;
+               new->chunks = chunks--;
 
                prev = new;
                len -= copy_size;
                dma_src += copy_size;
                dma_dest += copy_size;
                /* Insert the link descriptor to the LD ring */
-               list_add_tail(&new->node, &first->tx_list);
+               list_add_tail(&new->node, &tx_list);
        } while (len);
 
-       new->async_tx.flags = flags; /* client is in control of this ack */
-       new->async_tx.cookie = -EBUSY; /* Last desc */
+       if (new != first)
+               new->async_tx.cookie = -ENOSPC;
 
-       return &first->async_tx;
+       /* Put them back on the free list, so, they don't get lost */
+       list_splice_tail(&tx_list, &sh_chan->ld_free);
 
-err_get_desc:
-       sh_dmae_put_desc(sh_chan, first);
-       return NULL;
+       spin_unlock_bh(&sh_chan->desc_lock);
 
+       return &first->async_tx;
 }
 
-/*
- * sh_chan_ld_cleanup - Clean up link descriptors
- *
- * This function clean up the ld_queue of DMA channel.
- */
-static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan)
+static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
 {
        struct sh_desc *desc, *_desc;
+       /* Is the "exposed" head of a chain acked? */
+       bool head_acked = false;
+       dma_cookie_t cookie = 0;
+       dma_async_tx_callback callback = NULL;
+       void *param = NULL;
 
        spin_lock_bh(&sh_chan->desc_lock);
        list_for_each_entry_safe(desc, _desc, &sh_chan->ld_queue, node) {
-               dma_async_tx_callback callback;
-               void *callback_param;
-
-               /* non send data */
-               if (desc->mark == DESC_NCOMP)
+               struct dma_async_tx_descriptor *tx = &desc->async_tx;
+
+               BUG_ON(tx->cookie > 0 && tx->cookie != desc->cookie);
+               BUG_ON(desc->mark != DESC_SUBMITTED &&
+                      desc->mark != DESC_COMPLETED &&
+                      desc->mark != DESC_WAITING);
+
+               /*
+                * queue is ordered, and we use this loop to (1) clean up all
+                * completed descriptors, and to (2) update descriptor flags of
+                * any chunks in a (partially) completed chain
+                */
+               if (!all && desc->mark == DESC_SUBMITTED &&
+                   desc->cookie != cookie)
                        break;
 
-               /* send data sesc */
-               callback = desc->async_tx.callback;
-               callback_param = desc->async_tx.callback_param;
+               if (tx->cookie > 0)
+                       cookie = tx->cookie;
 
-               /* Remove from ld_queue list */
-               list_splice_init(&desc->tx_list, &sh_chan->ld_free);
+               if (desc->mark == DESC_COMPLETED && desc->chunks == 1) {
+                       BUG_ON(sh_chan->completed_cookie != desc->cookie - 1);
+                       sh_chan->completed_cookie = desc->cookie;
+               }
 
-               dev_dbg(sh_chan->dev, "link descriptor %p will be recycle.\n",
-                               desc);
+               /* Call callback on the last chunk */
+               if (desc->mark == DESC_COMPLETED && tx->callback) {
+                       desc->mark = DESC_WAITING;
+                       callback = tx->callback;
+                       param = tx->callback_param;
+                       dev_dbg(sh_chan->dev, "descriptor #%d@%p on %d callback\n",
+                               tx->cookie, tx, sh_chan->id);
+                       BUG_ON(desc->chunks != 1);
+                       break;
+               }
 
-               list_move(&desc->node, &sh_chan->ld_free);
-               /* Run the link descriptor callback function */
-               if (callback) {
-                       spin_unlock_bh(&sh_chan->desc_lock);
-                       dev_dbg(sh_chan->dev, "link descriptor %p callback\n",
-                                       desc);
-                       callback(callback_param);
-                       spin_lock_bh(&sh_chan->desc_lock);
+               if (tx->cookie > 0 || tx->cookie == -EBUSY) {
+                       if (desc->mark == DESC_COMPLETED) {
+                               BUG_ON(tx->cookie < 0);
+                               desc->mark = DESC_WAITING;
+                       }
+                       head_acked = async_tx_test_ack(tx);
+               } else {
+                       switch (desc->mark) {
+                       case DESC_COMPLETED:
+                               desc->mark = DESC_WAITING;
+                               /* Fall through */
+                       case DESC_WAITING:
+                               if (head_acked)
+                                       async_tx_ack(&desc->async_tx);
+                       }
+               }
+
+               dev_dbg(sh_chan->dev, "descriptor %p #%d completed.\n",
+                       tx, tx->cookie);
+
+               if (((desc->mark == DESC_COMPLETED ||
+                     desc->mark == DESC_WAITING) &&
+                    async_tx_test_ack(&desc->async_tx)) || all) {
+                       /* Remove from ld_queue list */
+                       desc->mark = DESC_IDLE;
+                       list_move(&desc->node, &sh_chan->ld_free);
                }
        }
        spin_unlock_bh(&sh_chan->desc_lock);
+
+       if (callback)
+               callback(param);
+
+       return callback;
+}
+
+/*
+ * sh_chan_ld_cleanup - Clean up link descriptors
+ *
+ * This function cleans up the ld_queue of DMA channel.
+ */
+static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
+{
+       while (__ld_cleanup(sh_chan, all))
+               ;
 }
 
 static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
 {
-       struct list_head *ld_node;
-       struct sh_dmae_regs hw;
+       struct sh_desc *sd;
 
+       spin_lock_bh(&sh_chan->desc_lock);
        /* DMA work check */
-       if (dmae_is_busy(sh_chan))
+       if (dmae_is_busy(sh_chan)) {
+               spin_unlock_bh(&sh_chan->desc_lock);
                return;
+       }
 
        /* Find the first un-transfer desciptor */
-       for (ld_node = sh_chan->ld_queue.next;
-               (ld_node != &sh_chan->ld_queue)
-                       && (to_sh_desc(ld_node)->mark == DESC_COMP);
-               ld_node = ld_node->next)
-               cpu_relax();
-
-       if (ld_node != &sh_chan->ld_queue) {
-               /* Get the ld start address from ld_queue */
-               hw = to_sh_desc(ld_node)->hw;
-               dmae_set_reg(sh_chan, hw);
-               dmae_start(sh_chan);
-       }
+       list_for_each_entry(sd, &sh_chan->ld_queue, node)
+               if (sd->mark == DESC_SUBMITTED) {
+                       /* Get the ld start address from ld_queue */
+                       dmae_set_reg(sh_chan, &sd->hw);
+                       dmae_start(sh_chan);
+                       break;
+               }
+
+       spin_unlock_bh(&sh_chan->desc_lock);
 }
 
 static void sh_dmae_memcpy_issue_pending(struct dma_chan *chan)
@@ -420,12 +519,11 @@ static enum dma_status sh_dmae_is_complete(struct dma_chan *chan,
        dma_cookie_t last_used;
        dma_cookie_t last_complete;
 
-       sh_dmae_chan_ld_cleanup(sh_chan);
+       sh_dmae_chan_ld_cleanup(sh_chan, false);
 
        last_used = chan->cookie;
        last_complete = sh_chan->completed_cookie;
-       if (last_complete == -EBUSY)
-               last_complete = last_used;
+       BUG_ON(last_complete < 0);
 
        if (done)
                *done = last_complete;
@@ -480,11 +578,13 @@ static irqreturn_t sh_dmae_err(int irq, void *data)
                err = sh_dmae_rst(0);
                if (err)
                        return err;
+#ifdef SH_DMAC_BASE1
                if (shdev->pdata.mode & SHDMA_DMAOR1) {
                        err = sh_dmae_rst(1);
                        if (err)
                                return err;
                }
+#endif
                disable_irq(irq);
                return IRQ_HANDLED;
        }
@@ -494,35 +594,25 @@ static irqreturn_t sh_dmae_err(int irq, void *data)
 static void dmae_do_tasklet(unsigned long data)
 {
        struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;
-       struct sh_desc *desc, *_desc, *cur_desc = NULL;
+       struct sh_desc *desc;
        u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
 
-       list_for_each_entry_safe(desc, _desc,
-                                &sh_chan->ld_queue, node) {
-               if ((desc->hw.sar + desc->hw.tcr) == sar_buf) {
-                       cur_desc = desc;
+       spin_lock(&sh_chan->desc_lock);
+       list_for_each_entry(desc, &sh_chan->ld_queue, node) {
+               if ((desc->hw.sar + desc->hw.tcr) == sar_buf &&
+                   desc->mark == DESC_SUBMITTED) {
+                       dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n",
+                               desc->async_tx.cookie, &desc->async_tx,
+                               desc->hw.dar);
+                       desc->mark = DESC_COMPLETED;
                        break;
                }
        }
+       spin_unlock(&sh_chan->desc_lock);
 
-       if (cur_desc) {
-               switch (cur_desc->async_tx.cookie) {
-               case 0: /* other desc data */
-                       break;
-               case -EBUSY: /* last desc */
-               sh_chan->completed_cookie =
-                               cur_desc->async_tx.cookie;
-                       break;
-               default: /* first desc ( 0 < )*/
-                       sh_chan->completed_cookie =
-                               cur_desc->async_tx.cookie - 1;
-                       break;
-               }
-               cur_desc->mark = DESC_COMP;
-       }
        /* Next desc */
        sh_chan_xfer_ld_queue(sh_chan);
-       sh_dmae_chan_ld_cleanup(sh_chan);
+       sh_dmae_chan_ld_cleanup(sh_chan, false);
 }
 
 static unsigned int get_dmae_irq(unsigned int id)
index 60b81e529b4219f69b8eac6c34d80228c1f8e7b5..108f1cffb6f5337fc0616858efdae82ec849a0b9 100644 (file)
@@ -13,9 +13,9 @@
 #ifndef __DMA_SHDMA_H
 #define __DMA_SHDMA_H
 
-#include <linux/device.h>
-#include <linux/dmapool.h>
 #include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
 
 #define SH_DMA_TCR_MAX 0x00FFFFFF      /* 16MB */
 
@@ -26,13 +26,16 @@ struct sh_dmae_regs {
 };
 
 struct sh_desc {
-       struct list_head tx_list;
        struct sh_dmae_regs hw;
        struct list_head node;
        struct dma_async_tx_descriptor async_tx;
+       dma_cookie_t cookie;
+       int chunks;
        int mark;
 };
 
+struct device;
+
 struct sh_dmae_chan {
        dma_cookie_t completed_cookie;  /* The maximum cookie completed */
        spinlock_t desc_lock;           /* Descriptor operation lock */
index 13efcd3620724cf8fdf52fc0fd267db3e53adbe7..a9371b36a9b9c3074f5b31d7bdacf1bda72a15dd 100644 (file)
@@ -1,5 +1,10 @@
+menu "IEEE 1394 (FireWire) support"
+       depends on PCI || BROKEN
+       # firewire-core does not depend on PCI but is
+       # not useful without PCI controller driver
+
 comment "You can enable one or both FireWire driver stacks."
-comment "See the help texts for more information."
+comment "The newer stack is recommended."
 
 config FIREWIRE
        tristate "FireWire driver stack"
@@ -15,16 +20,6 @@ config FIREWIRE
          To compile this driver as a module, say M here: the module will be
          called firewire-core.
 
-         This module functionally replaces ieee1394, raw1394, and video1394.
-         To access it from application programs, you generally need at least
-         libraw1394 v2.  IIDC/DCAM applications need libdc1394 v2.
-         No libraries are required to access storage devices through the
-         firewire-sbp2 driver.
-
-         NOTE:
-         FireWire audio devices currently require the old drivers (ieee1394,
-         ohci1394, raw1394).
-
 config FIREWIRE_OHCI
        tristate "OHCI-1394 controllers"
        depends on PCI && FIREWIRE
@@ -34,22 +29,7 @@ config FIREWIRE_OHCI
          is the only chipset in use, so say Y here.
 
          To compile this driver as a module, say M here:  The module will be
-         called firewire-ohci.  It replaces ohci1394 of the classic IEEE 1394
-         stack.
-
-         NOTE:
-         If you want to install firewire-ohci and ohci1394 together, you
-         should configure them only as modules and blacklist the driver(s)
-         which you don't want to have auto-loaded.  Add either
-
-             blacklist firewire-ohci
-         or
-             blacklist ohci1394
-             blacklist video1394
-             blacklist dv1394
-
-         to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf
-         depending on your distribution.
+         called firewire-ohci.
 
 config FIREWIRE_OHCI_DEBUG
        bool
@@ -66,8 +46,7 @@ config FIREWIRE_SBP2
          like scanners.
 
          To compile this driver as a module, say M here:  The module will be
-         called firewire-sbp2.  It replaces sbp2 of the classic IEEE 1394
-         stack.
+         called firewire-sbp2.
 
          You should also enable support for disks, CD-ROMs, etc. in the SCSI
          configuration section.
@@ -83,5 +62,8 @@ config FIREWIRE_NET
          NOTE, this driver is not stable yet!
 
          To compile this driver as a module, say M here:  The module will be
-         called firewire-net.  It replaces eth1394 of the classic IEEE 1394
-         stack.
+         called firewire-net.
+
+source "drivers/ieee1394/Kconfig"
+
+endmenu
index 231e6ee5ba4397c6aa511ad8ff2df4f54129799b..e6d63849e78ee44302e436c26f871e5b3dd3eef7 100644 (file)
@@ -601,8 +601,9 @@ static void release_request(struct client *client,
        struct inbound_transaction_resource *r = container_of(resource,
                        struct inbound_transaction_resource, resource);
 
-       fw_send_response(client->device->card, r->request,
-                        RCODE_CONFLICT_ERROR);
+       if (r->request)
+               fw_send_response(client->device->card, r->request,
+                                RCODE_CONFLICT_ERROR);
        kfree(r);
 }
 
@@ -645,7 +646,8 @@ static void handle_request(struct fw_card *card, struct fw_request *request,
  failed:
        kfree(r);
        kfree(e);
-       fw_send_response(card, request, RCODE_CONFLICT_ERROR);
+       if (request)
+               fw_send_response(card, request, RCODE_CONFLICT_ERROR);
 }
 
 static void release_address_handler(struct client *client,
@@ -715,15 +717,18 @@ static int ioctl_send_response(struct client *client, void *buffer)
 
        r = container_of(resource, struct inbound_transaction_resource,
                         resource);
-       if (request->length < r->length)
-               r->length = request->length;
-
-       if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) {
-               ret = -EFAULT;
-               goto out;
+       if (r->request) {
+               if (request->length < r->length)
+                       r->length = request->length;
+               if (copy_from_user(r->data, u64_to_uptr(request->data),
+                                  r->length)) {
+                       ret = -EFAULT;
+                       kfree(r->request);
+                       goto out;
+               }
+               fw_send_response(client->device->card, r->request,
+                                request->rcode);
        }
-
-       fw_send_response(client->device->card, r->request, request->rcode);
  out:
        kfree(r);
 
index 842739df23e26cbb3f6a8caeec780c0872dc60fa..495849eb13cc2a3858f3675dc81b1359af706a72 100644 (file)
@@ -432,14 +432,20 @@ static struct fw_address_handler *lookup_overlapping_address_handler(
        return NULL;
 }
 
+static bool is_enclosing_handler(struct fw_address_handler *handler,
+                                unsigned long long offset, size_t length)
+{
+       return handler->offset <= offset &&
+               offset + length <= handler->offset + handler->length;
+}
+
 static struct fw_address_handler *lookup_enclosing_address_handler(
        struct list_head *list, unsigned long long offset, size_t length)
 {
        struct fw_address_handler *handler;
 
        list_for_each_entry(handler, list, link) {
-               if (handler->offset <= offset &&
-                   offset + length <= handler->offset + handler->length)
+               if (is_enclosing_handler(handler, offset, length))
                        return handler;
        }
 
@@ -465,6 +471,12 @@ const struct fw_address_region fw_unit_space_region =
        { .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, };
 #endif  /*  0  */
 
+static bool is_in_fcp_region(u64 offset, size_t length)
+{
+       return offset >= (CSR_REGISTER_BASE | CSR_FCP_COMMAND) &&
+               offset + length <= (CSR_REGISTER_BASE | CSR_FCP_END);
+}
+
 /**
  * fw_core_add_address_handler - register for incoming requests
  * @handler: callback
@@ -477,8 +489,11 @@ const struct fw_address_region fw_unit_space_region =
  * give the details of the particular request.
  *
  * Return value:  0 on success, non-zero otherwise.
+ *
  * The start offset of the handler's address region is determined by
  * fw_core_add_address_handler() and is returned in handler->offset.
+ *
+ * Address allocations are exclusive, except for the FCP registers.
  */
 int fw_core_add_address_handler(struct fw_address_handler *handler,
                                const struct fw_address_region *region)
@@ -498,10 +513,12 @@ int fw_core_add_address_handler(struct fw_address_handler *handler,
 
        handler->offset = region->start;
        while (handler->offset + handler->length <= region->end) {
-               other =
-                   lookup_overlapping_address_handler(&address_handler_list,
-                                                      handler->offset,
-                                                      handler->length);
+               if (is_in_fcp_region(handler->offset, handler->length))
+                       other = NULL;
+               else
+                       other = lookup_overlapping_address_handler
+                                       (&address_handler_list,
+                                        handler->offset, handler->length);
                if (other != NULL) {
                        handler->offset += other->length;
                } else {
@@ -668,6 +685,9 @@ static struct fw_request *allocate_request(struct fw_packet *p)
 void fw_send_response(struct fw_card *card,
                      struct fw_request *request, int rcode)
 {
+       if (WARN_ONCE(!request, "invalid for FCP address handlers"))
+               return;
+
        /* unified transaction or broadcast transaction: don't respond */
        if (request->ack != ACK_PENDING ||
            HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) {
@@ -686,26 +706,15 @@ void fw_send_response(struct fw_card *card,
 }
 EXPORT_SYMBOL(fw_send_response);
 
-void fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
+static void handle_exclusive_region_request(struct fw_card *card,
+                                           struct fw_packet *p,
+                                           struct fw_request *request,
+                                           unsigned long long offset)
 {
        struct fw_address_handler *handler;
-       struct fw_request *request;
-       unsigned long long offset;
        unsigned long flags;
        int tcode, destination, source;
 
-       if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE)
-               return;
-
-       request = allocate_request(p);
-       if (request == NULL) {
-               /* FIXME: send statically allocated busy packet. */
-               return;
-       }
-
-       offset      =
-               ((unsigned long long)
-                HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | p->header[2];
        tcode       = HEADER_GET_TCODE(p->header[0]);
        destination = HEADER_GET_DESTINATION(p->header[0]);
        source      = HEADER_GET_SOURCE(p->header[1]);
@@ -732,6 +741,73 @@ void fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
                                          request->data, request->length,
                                          handler->callback_data);
 }
+
+static void handle_fcp_region_request(struct fw_card *card,
+                                     struct fw_packet *p,
+                                     struct fw_request *request,
+                                     unsigned long long offset)
+{
+       struct fw_address_handler *handler;
+       unsigned long flags;
+       int tcode, destination, source;
+
+       if ((offset != (CSR_REGISTER_BASE | CSR_FCP_COMMAND) &&
+            offset != (CSR_REGISTER_BASE | CSR_FCP_RESPONSE)) ||
+           request->length > 0x200) {
+               fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+
+               return;
+       }
+
+       tcode       = HEADER_GET_TCODE(p->header[0]);
+       destination = HEADER_GET_DESTINATION(p->header[0]);
+       source      = HEADER_GET_SOURCE(p->header[1]);
+
+       if (tcode != TCODE_WRITE_QUADLET_REQUEST &&
+           tcode != TCODE_WRITE_BLOCK_REQUEST) {
+               fw_send_response(card, request, RCODE_TYPE_ERROR);
+
+               return;
+       }
+
+       spin_lock_irqsave(&address_handler_lock, flags);
+       list_for_each_entry(handler, &address_handler_list, link) {
+               if (is_enclosing_handler(handler, offset, request->length))
+                       handler->address_callback(card, NULL, tcode,
+                                                 destination, source,
+                                                 p->generation, p->speed,
+                                                 offset, request->data,
+                                                 request->length,
+                                                 handler->callback_data);
+       }
+       spin_unlock_irqrestore(&address_handler_lock, flags);
+
+       fw_send_response(card, request, RCODE_COMPLETE);
+}
+
+void fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
+{
+       struct fw_request *request;
+       unsigned long long offset;
+
+       if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE)
+               return;
+
+       request = allocate_request(p);
+       if (request == NULL) {
+               /* FIXME: send statically allocated busy packet. */
+               return;
+       }
+
+       offset = ((u64)HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) |
+               p->header[2];
+
+       if (!is_in_fcp_region(offset, request->length))
+               handle_exclusive_region_request(card, p, request, offset);
+       else
+               handle_fcp_region_request(card, p, request, offset);
+
+}
 EXPORT_SYMBOL(fw_core_handle_request);
 
 void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
index 96768e160866a55ac4e2a1a5ef1fdd412c2133f2..a61571c63c595161f1aceb004a3d99677971b403 100644 (file)
@@ -2226,7 +2226,6 @@ static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
        if (rest == 0)
                return -EINVAL;
 
-       /* FIXME: make packet-per-buffer/dual-buffer a context option */
        while (rest > 0) {
                d = context_get_descriptors(&ctx->context,
                                            z + header_z, &d_bus);
@@ -2470,7 +2469,10 @@ static int __devinit pci_probe(struct pci_dev *dev,
        }
 
        version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
+#if 0
+       /* FIXME: make it a context option or remove dual-buffer mode */
        ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
+#endif
 
        /* dual-buffer mode is broken if more than one IR context is active */
        if (dev->vendor == PCI_VENDOR_ID_AGERE &&
index a019b49ecc9b0b06816d64d2c5d1e2fa2ddac08c..1f1d88ae68d6af2659d4fbfef2f8cad589d0d349 100644 (file)
@@ -172,6 +172,15 @@ config GPIO_ADP5520
          To compile this driver as a module, choose M here: the module will
          be called adp5520-gpio.
 
+config GPIO_ADP5588
+       tristate "ADP5588 I2C GPIO expander"
+       depends on I2C
+       help
+         This option enables support for 18 GPIOs found
+         on Analog Devices ADP5588 GPIO Expanders.
+         To compile this driver as a module, choose M here: the module will be
+         called adp5588-gpio.
+
 comment "PCI GPIO expanders:"
 
 config GPIO_CS5535
index 52fe4cf734c77498b3d66417eb2260b1bd1c3681..48687238edb13dffe015fbeef2d1f8eefbf66711 100644 (file)
@@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)    += -DDEBUG
 obj-$(CONFIG_GPIOLIB)          += gpiolib.o
 
 obj-$(CONFIG_GPIO_ADP5520)     += adp5520-gpio.o
+obj-$(CONFIG_GPIO_ADP5588)     += adp5588-gpio.o
 obj-$(CONFIG_GPIO_LANGWELL)    += langwell_gpio.o
 obj-$(CONFIG_GPIO_MAX7301)     += max7301.o
 obj-$(CONFIG_GPIO_MAX732X)     += max732x.o
diff --git a/drivers/gpio/adp5588-gpio.c b/drivers/gpio/adp5588-gpio.c
new file mode 100644 (file)
index 0000000..afc097a
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * GPIO Chip driver for Analog Devices
+ * ADP5588 I/O Expander and QWERTY Keypad Controller
+ *
+ * Copyright 2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+
+#include <linux/i2c/adp5588.h>
+
+#define DRV_NAME               "adp5588-gpio"
+#define MAXGPIO                        18
+#define ADP_BANK(offs)         ((offs) >> 3)
+#define ADP_BIT(offs)          (1u << ((offs) & 0x7))
+
+struct adp5588_gpio {
+       struct i2c_client *client;
+       struct gpio_chip gpio_chip;
+       struct mutex lock;      /* protect cached dir, dat_out */
+       unsigned gpio_start;
+       uint8_t dat_out[3];
+       uint8_t dir[3];
+};
+
+static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
+{
+       int ret = i2c_smbus_read_byte_data(client, reg);
+
+       if (ret < 0)
+               dev_err(&client->dev, "Read Error\n");
+
+       return ret;
+}
+
+static int adp5588_gpio_write(struct i2c_client *client, u8 reg, u8 val)
+{
+       int ret = i2c_smbus_write_byte_data(client, reg, val);
+
+       if (ret < 0)
+               dev_err(&client->dev, "Write Error\n");
+
+       return ret;
+}
+
+static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
+{
+       struct adp5588_gpio *dev =
+           container_of(chip, struct adp5588_gpio, gpio_chip);
+
+       return !!(adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + ADP_BANK(off))
+                 & ADP_BIT(off));
+}
+
+static void adp5588_gpio_set_value(struct gpio_chip *chip,
+                                  unsigned off, int val)
+{
+       unsigned bank, bit;
+       struct adp5588_gpio *dev =
+           container_of(chip, struct adp5588_gpio, gpio_chip);
+
+       bank = ADP_BANK(off);
+       bit = ADP_BIT(off);
+
+       mutex_lock(&dev->lock);
+       if (val)
+               dev->dat_out[bank] |= bit;
+       else
+               dev->dat_out[bank] &= ~bit;
+
+       adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
+                          dev->dat_out[bank]);
+       mutex_unlock(&dev->lock);
+}
+
+static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
+{
+       int ret;
+       unsigned bank;
+       struct adp5588_gpio *dev =
+           container_of(chip, struct adp5588_gpio, gpio_chip);
+
+       bank = ADP_BANK(off);
+
+       mutex_lock(&dev->lock);
+       dev->dir[bank] &= ~ADP_BIT(off);
+       ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]);
+       mutex_unlock(&dev->lock);
+
+       return ret;
+}
+
+static int adp5588_gpio_direction_output(struct gpio_chip *chip,
+                                        unsigned off, int val)
+{
+       int ret;
+       unsigned bank, bit;
+       struct adp5588_gpio *dev =
+           container_of(chip, struct adp5588_gpio, gpio_chip);
+
+       bank = ADP_BANK(off);
+       bit = ADP_BIT(off);
+
+       mutex_lock(&dev->lock);
+       dev->dir[bank] |= bit;
+
+       if (val)
+               dev->dat_out[bank] |= bit;
+       else
+               dev->dat_out[bank] &= ~bit;
+
+       ret = adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
+                                dev->dat_out[bank]);
+       ret |= adp5588_gpio_write(dev->client, GPIO_DIR1 + bank,
+                                dev->dir[bank]);
+       mutex_unlock(&dev->lock);
+
+       return ret;
+}
+
+static int __devinit adp5588_gpio_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+       struct adp5588_gpio *dev;
+       struct gpio_chip *gc;
+       int ret, i, revid;
+
+       if (pdata == NULL) {
+               dev_err(&client->dev, "missing platform data\n");
+               return -ENODEV;
+       }
+
+       if (!i2c_check_functionality(client->adapter,
+                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+               return -EIO;
+       }
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&client->dev, "failed to alloc memory\n");
+               return -ENOMEM;
+       }
+
+       dev->client = client;
+
+       gc = &dev->gpio_chip;
+       gc->direction_input = adp5588_gpio_direction_input;
+       gc->direction_output = adp5588_gpio_direction_output;
+       gc->get = adp5588_gpio_get_value;
+       gc->set = adp5588_gpio_set_value;
+       gc->can_sleep = 1;
+
+       gc->base = pdata->gpio_start;
+       gc->ngpio = MAXGPIO;
+       gc->label = client->name;
+       gc->owner = THIS_MODULE;
+
+       mutex_init(&dev->lock);
+
+
+       ret = adp5588_gpio_read(dev->client, DEV_ID);
+       if (ret < 0)
+               goto err;
+
+       revid = ret & ADP5588_DEVICE_ID_MASK;
+
+       for (i = 0, ret = 0; i <= ADP_BANK(MAXGPIO); i++) {
+               dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i);
+               dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i);
+               ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0);
+               ret |= adp5588_gpio_write(client, GPIO_PULL1 + i,
+                               (pdata->pullup_dis_mask >> (8 * i)) & 0xFF);
+
+               if (ret)
+                       goto err;
+       }
+
+       ret = gpiochip_add(&dev->gpio_chip);
+       if (ret)
+               goto err;
+
+       dev_info(&client->dev, "gpios %d..%d on a %s Rev. %d\n",
+                       gc->base, gc->base + gc->ngpio - 1,
+                       client->name, revid);
+
+       if (pdata->setup) {
+               ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context);
+               if (ret < 0)
+                       dev_warn(&client->dev, "setup failed, %d\n", ret);
+       }
+
+       i2c_set_clientdata(client, dev);
+       return 0;
+
+err:
+       kfree(dev);
+       return ret;
+}
+
+static int __devexit adp5588_gpio_remove(struct i2c_client *client)
+{
+       struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+       struct adp5588_gpio *dev = i2c_get_clientdata(client);
+       int ret;
+
+       if (pdata->teardown) {
+               ret = pdata->teardown(client,
+                                     dev->gpio_chip.base, dev->gpio_chip.ngpio,
+                                     pdata->context);
+               if (ret < 0) {
+                       dev_err(&client->dev, "teardown failed %d\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = gpiochip_remove(&dev->gpio_chip);
+       if (ret) {
+               dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);
+               return ret;
+       }
+
+       kfree(dev);
+       return 0;
+}
+
+static const struct i2c_device_id adp5588_gpio_id[] = {
+       {DRV_NAME, 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id);
+
+static struct i2c_driver adp5588_gpio_driver = {
+       .driver = {
+                  .name = DRV_NAME,
+                  },
+       .probe = adp5588_gpio_probe,
+       .remove = __devexit_p(adp5588_gpio_remove),
+       .id_table = adp5588_gpio_id,
+};
+
+static int __init adp5588_gpio_init(void)
+{
+       return i2c_add_driver(&adp5588_gpio_driver);
+}
+
+module_init(adp5588_gpio_init);
+
+static void __exit adp5588_gpio_exit(void)
+{
+       i2c_del_driver(&adp5588_gpio_driver);
+}
+
+module_exit(adp5588_gpio_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("GPIO ADP5588 Driver");
+MODULE_LICENSE("GPL");
index a25ad284a272799d2b4f91634fa8d985e41a885c..350842ad3632abc46469cd9c6835488a03b771db 100644 (file)
@@ -858,8 +858,6 @@ int gpio_sysfs_set_active_low(unsigned gpio, int value)
        desc = &gpio_desc[gpio];
 
        if (test_bit(FLAG_EXPORT, &desc->flags)) {
-               struct device *dev;
-
                dev = class_find_device(&gpio_class, NULL, desc, match_export);
                if (dev == NULL) {
                        status = -ENODEV;
index 628eae3e9b8354a14ba1f74c2e6c21f01039085f..a1fce68e3bbe65aded6adf7bb05f3c465b3e5d92 100644 (file)
@@ -39,8 +39,7 @@ static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
                                       struct drm_ati_pcigart_info *gart_info)
 {
        gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size,
-                                               PAGE_SIZE,
-                                               gart_info->table_mask);
+                                               PAGE_SIZE);
        if (gart_info->table_handle == NULL)
                return -ENOMEM;
 
@@ -112,6 +111,13 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
        if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
                DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
 
+               if (pci_set_dma_mask(dev->pdev, gart_info->table_mask)) {
+                       DRM_ERROR("fail to set dma mask to 0x%Lx\n",
+                                 gart_info->table_mask);
+                       ret = 1;
+                       goto done;
+               }
+
                ret = drm_ati_alloc_pcigart_table(dev, gart_info);
                if (ret) {
                        DRM_ERROR("cannot allocate PCI GART page!\n");
index 3d09e304f6f47c6ad91061761230b4c4ab7ccfb0..8417cc4c43f1104a5ae6bfe35e28936db9f5235a 100644 (file)
@@ -326,7 +326,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
                 * As we're limiting the address to 2^32-1 (or less),
                 * casting it down to 32 bits is no problem, but we
                 * need to point to a 64bit variable first. */
-               dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
+               dmah = drm_pci_alloc(dev, map->size, map->size);
                if (!dmah) {
                        kfree(map);
                        return -ENOMEM;
@@ -885,7 +885,7 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
 
        while (entry->buf_count < count) {
 
-               dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful);
+               dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000);
 
                if (!dmah) {
                        /* Set count correctly so we free the proper amount. */
index 5124401f266a168ea5202acfe24684ae9a339b1a..d91fb8c0b7b31673f43b885e8b0c38b0c1b6ec50 100644 (file)
@@ -158,6 +158,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
        { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 },
        { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 },
        { DRM_MODE_CONNECTOR_TV, "TV", 0 },
+       { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort", 0 },
 };
 
 static struct drm_prop_enum_list drm_encoder_enum_list[] =
index 4231d6db72ec41dd0556d506f7a6d96c426b6c3c..077313f0d47fa0e4e201841230432efae304deb0 100644 (file)
@@ -216,7 +216,7 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
 EXPORT_SYMBOL(drm_helper_crtc_in_use);
 
 /**
- * drm_disable_unused_functions - disable unused objects
+ * drm_helper_disable_unused_functions - disable unused objects
  * @dev: DRM device
  *
  * LOCKING:
@@ -1032,7 +1032,7 @@ bool drm_helper_initial_config(struct drm_device *dev)
        /*
         * we shouldn't end up with no modes here.
         */
-       WARN(!count, "No connectors reported connected with modes\n");
+       printk(KERN_INFO "No connectors reported conncted with modes\n");
 
        drm_setup_crtcs(dev);
 
@@ -1162,6 +1162,9 @@ EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
 int drm_helper_resume_force_mode(struct drm_device *dev)
 {
        struct drm_crtc *crtc;
+       struct drm_encoder *encoder;
+       struct drm_encoder_helper_funcs *encoder_funcs;
+       struct drm_crtc_helper_funcs *crtc_funcs;
        int ret;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -1174,6 +1177,25 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
 
                if (ret == false)
                        DRM_ERROR("failed to set mode on crtc %p\n", crtc);
+
+               /* Turn off outputs that were already powered off */
+               if (drm_helper_choose_crtc_dpms(crtc)) {
+                       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+
+                               if(encoder->crtc != crtc)
+                                       continue;
+
+                               encoder_funcs = encoder->helper_private;
+                               if (encoder_funcs->dpms)
+                                       (*encoder_funcs->dpms) (encoder,
+                                                               drm_helper_choose_encoder_dpms(encoder));
+
+                               crtc_funcs = crtc->helper_private;
+                               if (crtc_funcs->dpms)
+                                       (*crtc_funcs->dpms) (crtc,
+                                                            drm_helper_choose_crtc_dpms(crtc));
+                       }
+               }
        }
        /* disable the unused connectors while restoring the modesetting */
        drm_helper_disable_unused_functions(dev);
index 5c9f79877cbf0a361111d2d16cccb6aee7b4483a..defcaf108460b59ac9e5cba023d26e6e7bef6f13 100644 (file)
@@ -911,23 +911,27 @@ static int drm_cvt_modes(struct drm_connector *connector,
        struct drm_device *dev = connector->dev;
        struct cvt_timing *cvt;
        const int rates[] = { 60, 85, 75, 60, 50 };
+       const u8 empty[3] = { 0, 0, 0 };
 
        for (i = 0; i < 4; i++) {
                int uninitialized_var(width), height;
                cvt = &(timing->data.other_data.data.cvt[i]);
 
-               height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 8) + 1) * 2;
-               switch (cvt->code[1] & 0xc0) {
+               if (!memcmp(cvt->code, empty, 3))
+                       continue;
+
+               height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2;
+               switch (cvt->code[1] & 0x0c) {
                case 0x00:
                        width = height * 4 / 3;
                        break;
-               case 0x40:
+               case 0x04:
                        width = height * 16 / 9;
                        break;
-               case 0x80:
+               case 0x08:
                        width = height * 16 / 10;
                        break;
-               case 0xc0:
+               case 0x0c:
                        width = height * 15 / 9;
                        break;
                }
index 1b49fa055f4f39c2e8f363793a9feeea902ac105..1c2b7d44ec05c90bb295e35448b97c3cbda02a6f 100644 (file)
@@ -156,7 +156,7 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *con
                        force = DRM_FORCE_ON;
                        break;
                case 'D':
-                       if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) ||
+                       if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
                            (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
                                force = DRM_FORCE_ON;
                        else
@@ -606,11 +606,10 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
                return -EINVAL;
 
        /* Need to resize the fb object !!! */
-       if (var->xres > fb->width || var->yres > fb->height) {
-               DRM_ERROR("Requested width/height is greater than current fb "
-                          "object %dx%d > %dx%d\n", var->xres, var->yres,
-                          fb->width, fb->height);
-               DRM_ERROR("Need resizing code.\n");
+       if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) {
+               DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
+                         "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel,
+                         fb->width, fb->height, fb->bits_per_pixel);
                return -EINVAL;
        }
 
index 7998ee66b3179889273a87b3c1198ce3d0b41d70..b98384dbd9a7ace015a358c6085b01dc5de0a620 100644 (file)
@@ -115,6 +115,7 @@ void drm_vblank_cleanup(struct drm_device *dev)
 
        dev->num_crtcs = 0;
 }
+EXPORT_SYMBOL(drm_vblank_cleanup);
 
 int drm_vblank_init(struct drm_device *dev, int num_crtcs)
 {
@@ -163,7 +164,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
        }
 
        dev->vblank_disable_allowed = 0;
-
        return 0;
 
 err:
@@ -493,6 +493,9 @@ EXPORT_SYMBOL(drm_vblank_off);
  */
 void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
 {
+       /* vblank is not initialized (IRQ not installed ?) */
+       if (!dev->num_crtcs)
+               return;
        /*
         * To avoid all the problems that might happen if interrupts
         * were enabled/disabled around or between these calls, we just
index 577094fb1995807528b81e457bb089440c583f7a..e68ebf92fa2a5187c0e6b56a5e089a26d0516da2 100644 (file)
@@ -47,8 +47,7 @@
 /**
  * \brief Allocate a PCI consistent memory block, for DMA.
  */
-drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align,
-                               dma_addr_t maxaddr)
+drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align)
 {
        drm_dma_handle_t *dmah;
 #if 1
@@ -63,11 +62,6 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali
        if (align > size)
                return NULL;
 
-       if (pci_set_dma_mask(dev->pdev, maxaddr) != 0) {
-               DRM_ERROR("Setting pci dma mask failed\n");
-               return NULL;
-       }
-
        dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
        if (!dmah)
                return NULL;
index 18476bf0b5805add492f00178baa2a96829d7ecc..9c9998c4dcebba0fd4efffabc2da954ac46d2cc7 100644 (file)
@@ -272,7 +272,7 @@ static void i915_dump_pages(struct seq_file *m, struct page **pages, int page_co
                mem = kmap_atomic(pages[page], KM_USER0);
                for (i = 0; i < PAGE_SIZE; i += 4)
                        seq_printf(m, "%08x :  %08x\n", i, mem[i / 4]);
-               kunmap_atomic(pages[page], KM_USER0);
+               kunmap_atomic(mem, KM_USER0);
        }
 }
 
@@ -386,34 +386,6 @@ out:
        return 0;
 }
 
-static int i915_registers_info(struct seq_file *m, void *data) {
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct drm_device *dev = node->minor->dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       uint32_t reg;
-
-#define DUMP_RANGE(start, end) \
-       for (reg=start; reg < end; reg += 4) \
-       seq_printf(m, "%08x\t%08x\n", reg, I915_READ(reg));
-
-       DUMP_RANGE(0x00000, 0x00fff);   /* VGA registers */
-       DUMP_RANGE(0x02000, 0x02fff);   /* instruction, memory, interrupt control registers */
-       DUMP_RANGE(0x03000, 0x031ff);   /* FENCE and PPGTT control registers */
-       DUMP_RANGE(0x03200, 0x03fff);   /* frame buffer compression registers */
-       DUMP_RANGE(0x05000, 0x05fff);   /* I/O control registers */
-       DUMP_RANGE(0x06000, 0x06fff);   /* clock control registers */
-       DUMP_RANGE(0x07000, 0x07fff);   /* 3D internal debug registers */
-       DUMP_RANGE(0x07400, 0x088ff);   /* GPE debug registers */
-       DUMP_RANGE(0x0a000, 0x0afff);   /* display palette registers */
-       DUMP_RANGE(0x10000, 0x13fff);   /* MMIO MCHBAR */
-       DUMP_RANGE(0x30000, 0x3ffff);   /* overlay registers */
-       DUMP_RANGE(0x60000, 0x6ffff);   /* display engine pipeline registers */
-       DUMP_RANGE(0x70000, 0x72fff);   /* display and cursor registers */
-       DUMP_RANGE(0x73000, 0x73fff);   /* performance counters */
-
-       return 0;
-}
-
 static int
 i915_wedged_open(struct inode *inode,
                 struct file *filp)
@@ -519,7 +491,6 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor)
 }
 
 static struct drm_info_list i915_debugfs_list[] = {
-       {"i915_regs", i915_registers_info, 0},
        {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
        {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
        {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
index 701bfeac7f5702f3774a86b1c1f156fd1abf3e9a..bbe47812e4b6b210479cbeec80c11f194ac71337 100644 (file)
@@ -123,7 +123,7 @@ static int i915_init_phys_hws(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        /* Program Hardware Status Page */
        dev_priv->status_page_dmah =
-               drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+               drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE);
 
        if (!dev_priv->status_page_dmah) {
                DRM_ERROR("Can not allocate hardware status page\n");
@@ -813,9 +813,13 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_PAGEFLIPPING:
                value = 1;
                break;
+       case I915_PARAM_HAS_EXECBUF2:
+               /* depends on GEM */
+               value = dev_priv->has_gem;
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
-                                       param->param);
+                                param->param);
                return -EINVAL;
        }
 
@@ -1117,7 +1121,8 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_mm_node *compressed_fb, *compressed_llb;
-       unsigned long cfb_base, ll_base;
+       unsigned long cfb_base;
+       unsigned long ll_base = 0;
 
        /* Leave 1M for line length buffer & misc. */
        compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0);
@@ -1200,14 +1205,6 @@ static int i915_load_modeset_init(struct drm_device *dev,
        dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
                0xff000000;
 
-       if (IS_MOBILE(dev) || IS_I9XX(dev))
-               dev_priv->cursor_needs_physical = true;
-       else
-               dev_priv->cursor_needs_physical = false;
-
-       if (IS_I965G(dev) || IS_G33(dev))
-               dev_priv->cursor_needs_physical = false;
-
        /* Basic memrange allocator for stolen space (aka vram) */
        drm_mm_init(&dev_priv->vram, 0, prealloc_size);
        DRM_INFO("set up %ldM of stolen space\n", prealloc_size / (1024*1024));
@@ -1257,6 +1254,8 @@ static int i915_load_modeset_init(struct drm_device *dev,
        if (ret)
                goto destroy_ringbuffer;
 
+       intel_modeset_init(dev);
+
        ret = drm_irq_install(dev);
        if (ret)
                goto destroy_ringbuffer;
@@ -1271,8 +1270,6 @@ static int i915_load_modeset_init(struct drm_device *dev,
 
        I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
 
-       intel_modeset_init(dev);
-
        drm_helper_initial_config(dev);
 
        return 0;
@@ -1360,7 +1357,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        resource_size_t base, size;
-       int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
+       int ret = 0, mmio_bar;
        uint32_t agp_size, prealloc_size, prealloc_start;
 
        /* i915 has 4 more counters */
@@ -1376,8 +1373,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        dev->dev_private = (void *)dev_priv;
        dev_priv->dev = dev;
+       dev_priv->info = (struct intel_device_info *) flags;
 
        /* Add register map (needed for suspend/resume) */
+       mmio_bar = IS_I9XX(dev) ? 0 : 1;
        base = drm_get_resource_start(dev, mmio_bar);
        size = drm_get_resource_len(dev, mmio_bar);
 
@@ -1652,6 +1651,7 @@ struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
index 24286ca168fc41f56bf4fb92ad4576812e1e50bd..be631cc3e4dcaacc0c5770b31d8ede561c9927b4 100644 (file)
@@ -33,7 +33,6 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 
-#include "drm_pciids.h"
 #include <linux/console.h>
 #include "drm_crtc_helper.h"
 
@@ -48,8 +47,124 @@ module_param_named(powersave, i915_powersave, int, 0400);
 
 static struct drm_driver driver;
 
-static struct pci_device_id pciidlist[] = {
-       i915_PCI_IDS
+#define INTEL_VGA_DEVICE(id, info) {           \
+       .class = PCI_CLASS_DISPLAY_VGA << 8,    \
+       .class_mask = 0xffff00,                 \
+       .vendor = 0x8086,                       \
+       .device = id,                           \
+       .subvendor = PCI_ANY_ID,                \
+       .subdevice = PCI_ANY_ID,                \
+       .driver_data = (unsigned long) info }
+
+const static struct intel_device_info intel_i830_info = {
+       .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
+};
+
+const static struct intel_device_info intel_845g_info = {
+       .is_i8xx = 1,
+};
+
+const static struct intel_device_info intel_i85x_info = {
+       .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
+};
+
+const static struct intel_device_info intel_i865g_info = {
+       .is_i8xx = 1,
+};
+
+const static struct intel_device_info intel_i915g_info = {
+       .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
+};
+const static struct intel_device_info intel_i915gm_info = {
+       .is_i9xx = 1,  .is_mobile = 1, .has_fbc = 1,
+       .cursor_needs_physical = 1,
+};
+const static struct intel_device_info intel_i945g_info = {
+       .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
+};
+const static struct intel_device_info intel_i945gm_info = {
+       .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1,
+       .has_hotplug = 1, .cursor_needs_physical = 1,
+};
+
+const static struct intel_device_info intel_i965g_info = {
+       .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_i965gm_info = {
+       .is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1,
+       .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_g33_info = {
+       .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_g45_info = {
+       .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+       .has_pipe_cxsr = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_gm45_info = {
+       .is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1,
+       .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
+       .has_pipe_cxsr = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_pineview_info = {
+       .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
+       .has_pipe_cxsr = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_ironlake_d_info = {
+       .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+       .has_pipe_cxsr = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_ironlake_m_info = {
+       .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
+       .need_gfx_hws = 1, .has_rc6 = 1,
+       .has_hotplug = 1,
+};
+
+const static struct pci_device_id pciidlist[] = {
+       INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
+       INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
+       INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
+       INTEL_VGA_DEVICE(0x35e8, &intel_i85x_info),
+       INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),
+       INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),
+       INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),
+       INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),
+       INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),
+       INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),
+       INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),
+       INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),
+       INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),
+       INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),
+       INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),
+       INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),
+       INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),
+       INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),
+       INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),
+       INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),
+       INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),
+       INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),
+       INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),
+       INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),
+       INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),
+       INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),
+       INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
+       INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
+       INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
+       INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
+       {0, 0, 0}
 };
 
 #if defined(CONFIG_DRM_I915_KMS)
@@ -284,6 +399,52 @@ i915_pci_resume(struct pci_dev *pdev)
        return i915_resume(dev);
 }
 
+static int
+i915_pm_suspend(struct device *dev)
+{
+       return i915_pci_suspend(to_pci_dev(dev), PMSG_SUSPEND);
+}
+
+static int
+i915_pm_resume(struct device *dev)
+{
+       return i915_pci_resume(to_pci_dev(dev));
+}
+
+static int
+i915_pm_freeze(struct device *dev)
+{
+       return i915_pci_suspend(to_pci_dev(dev), PMSG_FREEZE);
+}
+
+static int
+i915_pm_thaw(struct device *dev)
+{
+       /* thaw during hibernate, do nothing! */
+       return 0;
+}
+
+static int
+i915_pm_poweroff(struct device *dev)
+{
+       return i915_pci_suspend(to_pci_dev(dev), PMSG_HIBERNATE);
+}
+
+static int
+i915_pm_restore(struct device *dev)
+{
+       return i915_pci_resume(to_pci_dev(dev));
+}
+
+const struct dev_pm_ops i915_pm_ops = {
+     .suspend = i915_pm_suspend,
+     .resume = i915_pm_resume,
+     .freeze = i915_pm_freeze,
+     .thaw = i915_pm_thaw,
+     .poweroff = i915_pm_poweroff,
+     .restore = i915_pm_restore,
+};
+
 static struct vm_operations_struct i915_gem_vm_ops = {
        .fault = i915_gem_fault,
        .open = drm_gem_vm_open,
@@ -344,10 +505,7 @@ static struct drm_driver driver = {
                 .id_table = pciidlist,
                 .probe = i915_pci_probe,
                 .remove = i915_pci_remove,
-#ifdef CONFIG_PM
-                .resume = i915_pci_resume,
-                .suspend = i915_pci_suspend,
-#endif
+                .driver.pm = &i915_pm_ops,
        },
 
        .name = DRIVER_NAME,
index fbecac72f5bb1ba08477486d5f89914e164f98d2..29dd676269675edb34efeace6ee605dc600a8e7e 100644 (file)
@@ -172,9 +172,31 @@ struct drm_i915_display_funcs {
 
 struct intel_overlay;
 
+struct intel_device_info {
+       u8 is_mobile : 1;
+       u8 is_i8xx : 1;
+       u8 is_i915g : 1;
+       u8 is_i9xx : 1;
+       u8 is_i945gm : 1;
+       u8 is_i965g : 1;
+       u8 is_i965gm : 1;
+       u8 is_g33 : 1;
+       u8 need_gfx_hws : 1;
+       u8 is_g4x : 1;
+       u8 is_pineview : 1;
+       u8 is_ironlake : 1;
+       u8 has_fbc : 1;
+       u8 has_rc6 : 1;
+       u8 has_pipe_cxsr : 1;
+       u8 has_hotplug : 1;
+       u8 cursor_needs_physical : 1;
+};
+
 typedef struct drm_i915_private {
        struct drm_device *dev;
 
+       const struct intel_device_info *info;
+
        int has_gem;
 
        void __iomem *regs;
@@ -232,8 +254,6 @@ typedef struct drm_i915_private {
        int hangcheck_count;
        uint32_t last_acthd;
 
-       bool cursor_needs_physical;
-
        struct drm_mm vram;
 
        unsigned long cfb_size;
@@ -287,8 +307,6 @@ typedef struct drm_i915_private {
        u32 saveDSPACNTR;
        u32 saveDSPBCNTR;
        u32 saveDSPARB;
-       u32 saveRENDERSTANDBY;
-       u32 savePWRCTXA;
        u32 saveHWS;
        u32 savePIPEACONF;
        u32 savePIPEBCONF;
@@ -561,6 +579,7 @@ typedef struct drm_i915_private {
        u16 orig_clock;
        int child_dev_num;
        struct child_device_config *child_dev;
+       struct drm_connector *int_lvds_connector;
 } drm_i915_private_t;
 
 /** driver private structure attached to each drm_gem_object */
@@ -794,6 +813,8 @@ int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
                             struct drm_file *file_priv);
 int i915_gem_execbuffer(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
+int i915_gem_execbuffer2(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
 int i915_gem_pin_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv);
 int i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
@@ -860,6 +881,9 @@ void i915_gem_shrinker_exit(void);
 void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
 void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj);
 void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj);
+bool i915_tiling_ok(struct drm_device *dev, int stride, int size,
+                   int tiling_mode);
+bool i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj);
 
 /* i915_gem_debug.c */
 void i915_gem_dump_object(struct drm_gem_object *obj, int len,
@@ -982,67 +1006,33 @@ extern void g4x_disable_fbc(struct drm_device *dev);
 extern int i915_wrap_ring(struct drm_device * dev);
 extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
-#define IS_I830(dev) ((dev)->pci_device == 0x3577)
-#define IS_845G(dev) ((dev)->pci_device == 0x2562)
-#define IS_I85X(dev) ((dev)->pci_device == 0x3582)
-#define IS_I865G(dev) ((dev)->pci_device == 0x2572)
-#define IS_I8XX(dev) (IS_I830(dev) || IS_845G(dev) || IS_I85X(dev) || IS_I865G(dev))
-
-#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a)
-#define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
-#define IS_I945G(dev) ((dev)->pci_device == 0x2772)
-#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2 ||\
-                       (dev)->pci_device == 0x27AE)
-#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
-                      (dev)->pci_device == 0x2982 || \
-                      (dev)->pci_device == 0x2992 || \
-                      (dev)->pci_device == 0x29A2 || \
-                      (dev)->pci_device == 0x2A02 || \
-                      (dev)->pci_device == 0x2A12 || \
-                      (dev)->pci_device == 0x2A42 || \
-                      (dev)->pci_device == 0x2E02 || \
-                      (dev)->pci_device == 0x2E12 || \
-                      (dev)->pci_device == 0x2E22 || \
-                      (dev)->pci_device == 0x2E32 || \
-                      (dev)->pci_device == 0x2E42 || \
-                      (dev)->pci_device == 0x0042 || \
-                      (dev)->pci_device == 0x0046)
-
-#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02 || \
-                       (dev)->pci_device == 0x2A12)
-
-#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
-
-#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
-                    (dev)->pci_device == 0x2E12 || \
-                    (dev)->pci_device == 0x2E22 || \
-                    (dev)->pci_device == 0x2E32 || \
-                    (dev)->pci_device == 0x2E42 || \
-                    IS_GM45(dev))
-
-#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001)
-#define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011)
-#define IS_PINEVIEW(dev) (IS_PINEVIEW_G(dev) || IS_PINEVIEW_M(dev))
-
-#define IS_G33(dev)    ((dev)->pci_device == 0x29C2 || \
-                       (dev)->pci_device == 0x29B2 ||  \
-                       (dev)->pci_device == 0x29D2 ||  \
-                       (IS_PINEVIEW(dev)))
-
+#define INTEL_INFO(dev)        (((struct drm_i915_private *) (dev)->dev_private)->info)
+
+#define IS_I830(dev)           ((dev)->pci_device == 0x3577)
+#define IS_845G(dev)           ((dev)->pci_device == 0x2562)
+#define IS_I85X(dev)           ((dev)->pci_device == 0x3582)
+#define IS_I865G(dev)          ((dev)->pci_device == 0x2572)
+#define IS_I8XX(dev)           (INTEL_INFO(dev)->is_i8xx)
+#define IS_I915G(dev)          (INTEL_INFO(dev)->is_i915g)
+#define IS_I915GM(dev)         ((dev)->pci_device == 0x2592)
+#define IS_I945G(dev)          ((dev)->pci_device == 0x2772)
+#define IS_I945GM(dev)         (INTEL_INFO(dev)->is_i945gm)
+#define IS_I965G(dev)          (INTEL_INFO(dev)->is_i965g)
+#define IS_I965GM(dev)         (INTEL_INFO(dev)->is_i965gm)
+#define IS_GM45(dev)           ((dev)->pci_device == 0x2A42)
+#define IS_G4X(dev)            (INTEL_INFO(dev)->is_g4x)
+#define IS_PINEVIEW_G(dev)     ((dev)->pci_device == 0xa001)
+#define IS_PINEVIEW_M(dev)     ((dev)->pci_device == 0xa011)
+#define IS_PINEVIEW(dev)       (INTEL_INFO(dev)->is_pineview)
+#define IS_G33(dev)            (INTEL_INFO(dev)->is_g33)
 #define IS_IRONLAKE_D(dev)     ((dev)->pci_device == 0x0042)
 #define IS_IRONLAKE_M(dev)     ((dev)->pci_device == 0x0046)
-#define IS_IRONLAKE(dev)       (IS_IRONLAKE_D(dev) || IS_IRONLAKE_M(dev))
-
-#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
-                     IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev) || \
-                     IS_IRONLAKE(dev))
+#define IS_IRONLAKE(dev)       (INTEL_INFO(dev)->is_ironlake)
+#define IS_I9XX(dev)           (INTEL_INFO(dev)->is_i9xx)
+#define IS_MOBILE(dev)         (INTEL_INFO(dev)->is_mobile)
 
-#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
-                       IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \
-                       IS_PINEVIEW(dev) || IS_IRONLAKE_M(dev))
+#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
 
-#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev) || \
-                               IS_IRONLAKE(dev))
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
  * rows, which changed the alignment requirements and fence programming.
  */
@@ -1054,17 +1044,14 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 #define SUPPORTS_EDP(dev)              (IS_IRONLAKE_M(dev))
 #define SUPPORTS_TV(dev)               (IS_I9XX(dev) && IS_MOBILE(dev) && \
                                        !IS_IRONLAKE(dev) && !IS_PINEVIEW(dev))
-#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev) || IS_I965G(dev))
+#define I915_HAS_HOTPLUG(dev)           (INTEL_INFO(dev)->has_hotplug)
 /* dsparb controlled by hw only */
 #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
 
 #define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IRONLAKE(dev))
-#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
-#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && \
-                          (IS_I9XX(dev) || IS_GM45(dev)) && \
-                          !IS_PINEVIEW(dev) && \
-                          !IS_IRONLAKE(dev))
-#define I915_HAS_RC6(dev) (IS_I965GM(dev) || IS_GM45(dev) || IS_IRONLAKE_M(dev))
+#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
+#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
+#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)
 
 #define PRIMARY_RINGBUFFER_SIZE         (128*1024)
 
index 8c463cf2050a8dfc57e308a6d8376670c84fd45a..2748609f05b386c4c314fa10810276e22e3aa888 100644 (file)
@@ -2021,9 +2021,6 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
        /* blow away mappings if mapped through GTT */
        i915_gem_release_mmap(obj);
 
-       if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
-               i915_gem_clear_fence_reg(obj);
-
        /* Move the object to the CPU domain to ensure that
         * any possible CPU writes while it's not in the GTT
         * are flushed when we go to remap it. This will
@@ -2039,6 +2036,10 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
 
        BUG_ON(obj_priv->active);
 
+       /* release the fence reg _after_ flushing */
+       if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
+               i915_gem_clear_fence_reg(obj);
+
        if (obj_priv->agp_mem != NULL) {
                drm_unbind_agp(obj_priv->agp_mem);
                drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE);
@@ -2581,9 +2582,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
        bool retry_alloc = false;
        int ret;
 
-       if (dev_priv->mm.suspended)
-               return -EBUSY;
-
        if (obj_priv->madv != I915_MADV_WILLNEED) {
                DRM_ERROR("Attempting to bind a purgeable object\n");
                return -EINVAL;
@@ -3198,7 +3196,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
 static int
 i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                                 struct drm_file *file_priv,
-                                struct drm_i915_gem_exec_object *entry,
+                                struct drm_i915_gem_exec_object2 *entry,
                                 struct drm_i915_gem_relocation_entry *relocs)
 {
        struct drm_device *dev = obj->dev;
@@ -3206,12 +3204,35 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
        struct drm_i915_gem_object *obj_priv = obj->driver_private;
        int i, ret;
        void __iomem *reloc_page;
+       bool need_fence;
+
+       need_fence = entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
+                    obj_priv->tiling_mode != I915_TILING_NONE;
+
+       /* Check fence reg constraints and rebind if necessary */
+       if (need_fence && !i915_obj_fenceable(dev, obj))
+               i915_gem_object_unbind(obj);
 
        /* Choose the GTT offset for our buffer and put it there. */
        ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
        if (ret)
                return ret;
 
+       /*
+        * Pre-965 chips need a fence register set up in order to
+        * properly handle blits to/from tiled surfaces.
+        */
+       if (need_fence) {
+               ret = i915_gem_object_get_fence_reg(obj);
+               if (ret != 0) {
+                       if (ret != -EBUSY && ret != -ERESTARTSYS)
+                               DRM_ERROR("Failure to install fence: %d\n",
+                                         ret);
+                       i915_gem_object_unpin(obj);
+                       return ret;
+               }
+       }
+
        entry->offset = obj_priv->gtt_offset;
 
        /* Apply the relocations, using the GTT aperture to avoid cache
@@ -3373,7 +3394,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
  */
 static int
 i915_dispatch_gem_execbuffer(struct drm_device *dev,
-                             struct drm_i915_gem_execbuffer *exec,
+                             struct drm_i915_gem_execbuffer2 *exec,
                              struct drm_clip_rect *cliprects,
                              uint64_t exec_offset)
 {
@@ -3463,7 +3484,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
 }
 
 static int
-i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
+i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object2 *exec_list,
                              uint32_t buffer_count,
                              struct drm_i915_gem_relocation_entry **relocs)
 {
@@ -3478,8 +3499,10 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
        }
 
        *relocs = drm_calloc_large(reloc_count, sizeof(**relocs));
-       if (*relocs == NULL)
+       if (*relocs == NULL) {
+               DRM_ERROR("failed to alloc relocs, count %d\n", reloc_count);
                return -ENOMEM;
+       }
 
        for (i = 0; i < buffer_count; i++) {
                struct drm_i915_gem_relocation_entry __user *user_relocs;
@@ -3503,7 +3526,7 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
 }
 
 static int
-i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list,
+i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object2 *exec_list,
                            uint32_t buffer_count,
                            struct drm_i915_gem_relocation_entry *relocs)
 {
@@ -3536,7 +3559,7 @@ err:
 }
 
 static int
-i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec,
+i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec,
                           uint64_t exec_offset)
 {
        uint32_t exec_start, exec_len;
@@ -3589,18 +3612,18 @@ i915_gem_wait_for_pending_flip(struct drm_device *dev,
 }
 
 int
-i915_gem_execbuffer(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv)
+i915_gem_do_execbuffer(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv,
+                      struct drm_i915_gem_execbuffer2 *args,
+                      struct drm_i915_gem_exec_object2 *exec_list)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_i915_gem_execbuffer *args = data;
-       struct drm_i915_gem_exec_object *exec_list = NULL;
        struct drm_gem_object **object_list = NULL;
        struct drm_gem_object *batch_obj;
        struct drm_i915_gem_object *obj_priv;
        struct drm_clip_rect *cliprects = NULL;
        struct drm_i915_gem_relocation_entry *relocs;
-       int ret, ret2, i, pinned = 0;
+       int ret = 0, ret2, i, pinned = 0;
        uint64_t exec_offset;
        uint32_t seqno, flush_domains, reloc_index;
        int pin_tries, flips;
@@ -3614,25 +3637,13 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
                DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
                return -EINVAL;
        }
-       /* Copy in the exec list from userland */
-       exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
        object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count);
-       if (exec_list == NULL || object_list == NULL) {
-               DRM_ERROR("Failed to allocate exec or object list "
-                         "for %d buffers\n",
+       if (object_list == NULL) {
+               DRM_ERROR("Failed to allocate object list for %d buffers\n",
                          args->buffer_count);
                ret = -ENOMEM;
                goto pre_mutex_err;
        }
-       ret = copy_from_user(exec_list,
-                            (struct drm_i915_relocation_entry __user *)
-                            (uintptr_t) args->buffers_ptr,
-                            sizeof(*exec_list) * args->buffer_count);
-       if (ret != 0) {
-               DRM_ERROR("copy %d exec entries failed %d\n",
-                         args->buffer_count, ret);
-               goto pre_mutex_err;
-       }
 
        if (args->num_cliprects != 0) {
                cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects),
@@ -3884,20 +3895,6 @@ err:
 
        mutex_unlock(&dev->struct_mutex);
 
-       if (!ret) {
-               /* Copy the new buffer offsets back to the user's exec list. */
-               ret = copy_to_user((struct drm_i915_relocation_entry __user *)
-                                  (uintptr_t) args->buffers_ptr,
-                                  exec_list,
-                                  sizeof(*exec_list) * args->buffer_count);
-               if (ret) {
-                       ret = -EFAULT;
-                       DRM_ERROR("failed to copy %d exec entries "
-                                 "back to user (%d)\n",
-                                 args->buffer_count, ret);
-               }
-       }
-
        /* Copy the updated relocations out regardless of current error
         * state.  Failure to update the relocs would mean that the next
         * time userland calls execbuf, it would do so with presumed offset
@@ -3914,12 +3911,158 @@ err:
 
 pre_mutex_err:
        drm_free_large(object_list);
-       drm_free_large(exec_list);
        kfree(cliprects);
 
        return ret;
 }
 
+/*
+ * Legacy execbuffer just creates an exec2 list from the original exec object
+ * list array and passes it to the real function.
+ */
+int
+i915_gem_execbuffer(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
+{
+       struct drm_i915_gem_execbuffer *args = data;
+       struct drm_i915_gem_execbuffer2 exec2;
+       struct drm_i915_gem_exec_object *exec_list = NULL;
+       struct drm_i915_gem_exec_object2 *exec2_list = NULL;
+       int ret, i;
+
+#if WATCH_EXEC
+       DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
+                 (int) args->buffers_ptr, args->buffer_count, args->batch_len);
+#endif
+
+       if (args->buffer_count < 1) {
+               DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
+               return -EINVAL;
+       }
+
+       /* Copy in the exec list from userland */
+       exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
+       exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
+       if (exec_list == NULL || exec2_list == NULL) {
+               DRM_ERROR("Failed to allocate exec list for %d buffers\n",
+                         args->buffer_count);
+               drm_free_large(exec_list);
+               drm_free_large(exec2_list);
+               return -ENOMEM;
+       }
+       ret = copy_from_user(exec_list,
+                            (struct drm_i915_relocation_entry __user *)
+                            (uintptr_t) args->buffers_ptr,
+                            sizeof(*exec_list) * args->buffer_count);
+       if (ret != 0) {
+               DRM_ERROR("copy %d exec entries failed %d\n",
+                         args->buffer_count, ret);
+               drm_free_large(exec_list);
+               drm_free_large(exec2_list);
+               return -EFAULT;
+       }
+
+       for (i = 0; i < args->buffer_count; i++) {
+               exec2_list[i].handle = exec_list[i].handle;
+               exec2_list[i].relocation_count = exec_list[i].relocation_count;
+               exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr;
+               exec2_list[i].alignment = exec_list[i].alignment;
+               exec2_list[i].offset = exec_list[i].offset;
+               if (!IS_I965G(dev))
+                       exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE;
+               else
+                       exec2_list[i].flags = 0;
+       }
+
+       exec2.buffers_ptr = args->buffers_ptr;
+       exec2.buffer_count = args->buffer_count;
+       exec2.batch_start_offset = args->batch_start_offset;
+       exec2.batch_len = args->batch_len;
+       exec2.DR1 = args->DR1;
+       exec2.DR4 = args->DR4;
+       exec2.num_cliprects = args->num_cliprects;
+       exec2.cliprects_ptr = args->cliprects_ptr;
+       exec2.flags = 0;
+
+       ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list);
+       if (!ret) {
+               /* Copy the new buffer offsets back to the user's exec list. */
+               for (i = 0; i < args->buffer_count; i++)
+                       exec_list[i].offset = exec2_list[i].offset;
+               /* ... and back out to userspace */
+               ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+                                  (uintptr_t) args->buffers_ptr,
+                                  exec_list,
+                                  sizeof(*exec_list) * args->buffer_count);
+               if (ret) {
+                       ret = -EFAULT;
+                       DRM_ERROR("failed to copy %d exec entries "
+                                 "back to user (%d)\n",
+                                 args->buffer_count, ret);
+               }
+       } else {
+               DRM_ERROR("i915_gem_do_execbuffer returns %d\n", ret);
+       }
+
+       drm_free_large(exec_list);
+       drm_free_large(exec2_list);
+       return ret;
+}
+
+int
+i915_gem_execbuffer2(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
+{
+       struct drm_i915_gem_execbuffer2 *args = data;
+       struct drm_i915_gem_exec_object2 *exec2_list = NULL;
+       int ret;
+
+#if WATCH_EXEC
+       DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
+                 (int) args->buffers_ptr, args->buffer_count, args->batch_len);
+#endif
+
+       if (args->buffer_count < 1) {
+               DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count);
+               return -EINVAL;
+       }
+
+       exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
+       if (exec2_list == NULL) {
+               DRM_ERROR("Failed to allocate exec list for %d buffers\n",
+                         args->buffer_count);
+               return -ENOMEM;
+       }
+       ret = copy_from_user(exec2_list,
+                            (struct drm_i915_relocation_entry __user *)
+                            (uintptr_t) args->buffers_ptr,
+                            sizeof(*exec2_list) * args->buffer_count);
+       if (ret != 0) {
+               DRM_ERROR("copy %d exec entries failed %d\n",
+                         args->buffer_count, ret);
+               drm_free_large(exec2_list);
+               return -EFAULT;
+       }
+
+       ret = i915_gem_do_execbuffer(dev, data, file_priv, args, exec2_list);
+       if (!ret) {
+               /* Copy the new buffer offsets back to the user's exec list. */
+               ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+                                  (uintptr_t) args->buffers_ptr,
+                                  exec2_list,
+                                  sizeof(*exec2_list) * args->buffer_count);
+               if (ret) {
+                       ret = -EFAULT;
+                       DRM_ERROR("failed to copy %d exec entries "
+                                 "back to user (%d)\n",
+                                 args->buffer_count, ret);
+               }
+       }
+
+       drm_free_large(exec2_list);
+       return ret;
+}
+
 int
 i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
 {
@@ -3933,19 +4076,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
                if (ret)
                        return ret;
        }
-       /*
-        * Pre-965 chips need a fence register set up in order to
-        * properly handle tiled surfaces.
-        */
-       if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) {
-               ret = i915_gem_object_get_fence_reg(obj);
-               if (ret != 0) {
-                       if (ret != -EBUSY && ret != -ERESTARTSYS)
-                               DRM_ERROR("Failure to install fence: %d\n",
-                                         ret);
-                       return ret;
-               }
-       }
+
        obj_priv->pin_count++;
 
        /* If the object is not active and not pending a flush,
@@ -4708,7 +4839,7 @@ int i915_gem_init_phys_object(struct drm_device *dev,
 
        phys_obj->id = id;
 
-       phys_obj->handle = drm_pci_alloc(dev, size, 0, 0xffffffff);
+       phys_obj->handle = drm_pci_alloc(dev, size, 0);
        if (!phys_obj->handle) {
                ret = -ENOMEM;
                goto kfree_obj;
index 30d6af6c09bbe33e2fc8a333252b838f1817488c..df278b2685bff16c4da8b1a26eb6982149fce4e1 100644 (file)
@@ -304,35 +304,39 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
 
 
 /**
- * Returns the size of the fence for a tiled object of the given size.
+ * Returns whether an object is currently fenceable.  If not, it may need
+ * to be unbound and have its pitch adjusted.
  */
-static int
-i915_get_fence_size(struct drm_device *dev, int size)
+bool
+i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj)
 {
-       int i;
-       int start;
+       struct drm_i915_gem_object *obj_priv = obj->driver_private;
 
        if (IS_I965G(dev)) {
                /* The 965 can have fences at any page boundary. */
-               return ALIGN(size, 4096);
+               if (obj->size & 4095)
+                       return false;
+               return true;
+       } else if (IS_I9XX(dev)) {
+               if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
+                       return false;
        } else {
-               /* Align the size to a power of two greater than the smallest
-                * fence size.
-                */
-               if (IS_I9XX(dev))
-                       start = 1024 * 1024;
-               else
-                       start = 512 * 1024;
+               if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
+                       return false;
+       }
 
-               for (i = start; i < size; i <<= 1)
-                       ;
+       /* Power of two sized... */
+       if (obj->size & (obj->size - 1))
+               return false;
 
-               return i;
-       }
+       /* Objects must be size aligned as well */
+       if (obj_priv->gtt_offset & (obj->size - 1))
+               return false;
+       return true;
 }
 
 /* Check pitch constriants for all chips & tiling formats */
-static bool
+bool
 i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
 {
        int tile_width;
@@ -384,12 +388,6 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
        if (stride & (stride - 1))
                return false;
 
-       /* We don't 0handle the aperture area covered by the fence being bigger
-        * than the object size.
-        */
-       if (i915_get_fence_size(dev, size) != size)
-               return false;
-
        return true;
 }
 
index 85f4c5de97e2d438d3c05bd942ff0deb481e64eb..7cd8110051b6e22e26bc487418533c6b9f47d806 100644 (file)
@@ -313,6 +313,8 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
                        dev_priv->mm.irq_gem_seqno = seqno;
                        trace_i915_gem_request_complete(dev, seqno);
                        DRM_WAKEUP(&dev_priv->irq_queue);
+                       dev_priv->hangcheck_count = 0;
+                       mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
                }
 
                if (de_iir & DE_GSE)
@@ -1084,6 +1086,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
        (void) I915_READ(IER);
 }
 
+/*
+ * Must be called after intel_modeset_init or hotplug interrupts won't be
+ * enabled correctly.
+ */
 int i915_driver_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1106,19 +1112,23 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
        if (I915_HAS_HOTPLUG(dev)) {
                u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
 
-               /* Leave other bits alone */
-               hotplug_en |= HOTPLUG_EN_MASK;
+               /* Note HDMI and DP share bits */
+               if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMID_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+                       hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+                       hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
+                       hotplug_en |= CRT_HOTPLUG_INT_EN;
+               /* Ignore TV since it's buggy */
+
                I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
 
-               dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS |
-                       TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS |
-                       SDVOB_HOTPLUG_INT_STATUS;
-               if (IS_G4X(dev)) {
-                       dev_priv->hotplug_supported_mask |=
-                               HDMIB_HOTPLUG_INT_STATUS |
-                               HDMIC_HOTPLUG_INT_STATUS |
-                               HDMID_HOTPLUG_INT_STATUS;
-               }
                /* Enable in IER... */
                enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
                /* and unmask in IMR */
index 974b3cf706184d46c4cc170cc1c606ccda75e561..149d360d64a33f83cd5e03ef7eca7c76fa0fb67e 100644 (file)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV       (1 << 2)
 #define CRT_HOTPLUG_MASK                       (0x3fc) /* Bits 9-2 */
 #define CRT_FORCE_HOTPLUG_MASK                 0xfffffe1f
-#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \
-                        HDMIC_HOTPLUG_INT_EN |   \
-                        HDMID_HOTPLUG_INT_EN |   \
-                        SDVOB_HOTPLUG_INT_EN |   \
-                        SDVOC_HOTPLUG_INT_EN |   \
-                        CRT_HOTPLUG_INT_EN)
-
 
 #define PORT_HOTPLUG_STAT      0x61114
 #define   HDMIB_HOTPLUG_INT_STATUS             (1 << 29)
 #define   LVDS_PORT_EN                 (1 << 31)
 /* Selects pipe B for LVDS data.  Must be set on pre-965. */
 #define   LVDS_PIPEB_SELECT            (1 << 30)
+/* LVDS dithering flag on 965/g4x platform */
+#define   LVDS_ENABLE_DITHER           (1 << 25)
 /* Enable border for unscaled (or aspect-scaled) display */
 #define   LVDS_BORDER_ENABLE           (1 << 15)
 /*
 
 /* Display & cursor control */
 
+/* dithering flag on Ironlake */
+#define PIPE_ENABLE_DITHER     (1 << 4)
 /* Pipe A */
 #define PIPEADSL               0x70000
 #define PIPEACONF              0x70008
index d5ebb00a9d49de32e379afb8602d46d279799e65..a3b90c9561dc6623b6671ad4aaefbfd957e65ed8 100644 (file)
@@ -732,12 +732,6 @@ int i915_save_state(struct drm_device *dev)
 
        pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
 
-       /* Render Standby */
-       if (I915_HAS_RC6(dev)) {
-               dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
-               dev_priv->savePWRCTXA = I915_READ(PWRCTXA);
-       }
-
        /* Hardware status page */
        dev_priv->saveHWS = I915_READ(HWS_PGA);
 
@@ -793,12 +787,6 @@ int i915_restore_state(struct drm_device *dev)
 
        pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
 
-       /* Render Standby */
-       if (I915_HAS_RC6(dev)) {
-               I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
-               I915_WRITE(PWRCTXA, dev_priv->savePWRCTXA);
-       }
-
        /* Hardware status page */
        I915_WRITE(HWS_PGA, dev_priv->saveHWS);
 
index 9f3d3e56341488fc8f18900bd6cf96836e8ad7f5..ddefc871edfe4806714a07d44444f1e08e5422af 100644 (file)
@@ -548,4 +548,6 @@ void intel_crt_init(struct drm_device *dev)
        drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
        drm_sysfs_connector_add(connector);
+
+       dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
 }
index 52cd9b006da21a5c749c97952d9431a8450d497c..002612fae717c0ac7c795698e71068e704ca530d 100644 (file)
@@ -262,6 +262,14 @@ struct intel_limit {
 #define IRONLAKE_P2_LVDS_FAST    7  /* double channel */
 #define IRONLAKE_P2_DOT_LIMIT    225000 /* 225Mhz */
 
+#define IRONLAKE_P_DISPLAY_PORT_MIN    10
+#define IRONLAKE_P_DISPLAY_PORT_MAX    20
+#define IRONLAKE_P2_DISPLAY_PORT_FAST  10
+#define IRONLAKE_P2_DISPLAY_PORT_SLOW  10
+#define IRONLAKE_P2_DISPLAY_PORT_LIMIT 0
+#define IRONLAKE_P1_DISPLAY_PORT_MIN   1
+#define IRONLAKE_P1_DISPLAY_PORT_MAX   2
+
 static bool
 intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                    int target, int refclk, intel_clock_t *best_clock);
@@ -271,9 +279,6 @@ intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 static bool
 intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                        int target, int refclk, intel_clock_t *best_clock);
-static bool
-intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                            int target, int refclk, intel_clock_t *best_clock);
 
 static bool
 intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
@@ -496,7 +501,7 @@ static const intel_limit_t intel_limits_ironlake_sdvo = {
        .p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
                 .p2_slow = IRONLAKE_P2_SDVO_DAC_SLOW,
                 .p2_fast = IRONLAKE_P2_SDVO_DAC_FAST },
-       .find_pll = intel_ironlake_find_best_PLL,
+       .find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_ironlake_lvds = {
@@ -511,7 +516,30 @@ static const intel_limit_t intel_limits_ironlake_lvds = {
        .p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
                 .p2_slow = IRONLAKE_P2_LVDS_SLOW,
                 .p2_fast = IRONLAKE_P2_LVDS_FAST },
-       .find_pll = intel_ironlake_find_best_PLL,
+       .find_pll = intel_g4x_find_best_PLL,
+};
+
+static const intel_limit_t intel_limits_ironlake_display_port = {
+        .dot = { .min = IRONLAKE_DOT_MIN,
+                 .max = IRONLAKE_DOT_MAX },
+        .vco = { .min = IRONLAKE_VCO_MIN,
+                 .max = IRONLAKE_VCO_MAX},
+        .n   = { .min = IRONLAKE_N_MIN,
+                 .max = IRONLAKE_N_MAX },
+        .m   = { .min = IRONLAKE_M_MIN,
+                 .max = IRONLAKE_M_MAX },
+        .m1  = { .min = IRONLAKE_M1_MIN,
+                 .max = IRONLAKE_M1_MAX },
+        .m2  = { .min = IRONLAKE_M2_MIN,
+                 .max = IRONLAKE_M2_MAX },
+        .p   = { .min = IRONLAKE_P_DISPLAY_PORT_MIN,
+                 .max = IRONLAKE_P_DISPLAY_PORT_MAX },
+        .p1  = { .min = IRONLAKE_P1_DISPLAY_PORT_MIN,
+                 .max = IRONLAKE_P1_DISPLAY_PORT_MAX},
+        .p2  = { .dot_limit = IRONLAKE_P2_DISPLAY_PORT_LIMIT,
+                 .p2_slow = IRONLAKE_P2_DISPLAY_PORT_SLOW,
+                 .p2_fast = IRONLAKE_P2_DISPLAY_PORT_FAST },
+        .find_pll = intel_find_pll_ironlake_dp,
 };
 
 static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc)
@@ -519,6 +547,9 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc)
        const intel_limit_t *limit;
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
                limit = &intel_limits_ironlake_lvds;
+       else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+                       HAS_eDP)
+               limit = &intel_limits_ironlake_display_port;
        else
                limit = &intel_limits_ironlake_sdvo;
 
@@ -791,7 +822,13 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
        found = false;
 
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-               if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+               int lvds_reg;
+
+               if (IS_IRONLAKE(dev))
+                       lvds_reg = PCH_LVDS;
+               else
+                       lvds_reg = LVDS;
+               if ((I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) ==
                    LVDS_CLKB_POWER_UP)
                        clock.p2 = limit->p2.p2_fast;
                else
@@ -839,6 +876,11 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        intel_clock_t clock;
+
+       /* return directly when it is eDP */
+       if (HAS_eDP)
+               return true;
+
        if (target < 200000) {
                clock.n = 1;
                clock.p1 = 2;
@@ -857,68 +899,6 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
        return true;
 }
 
-static bool
-intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                            int target, int refclk, intel_clock_t *best_clock)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       intel_clock_t clock;
-       int err_most = 47;
-       int err_min = 10000;
-
-       /* eDP has only 2 clock choice, no n/m/p setting */
-       if (HAS_eDP)
-               return true;
-
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
-               return intel_find_pll_ironlake_dp(limit, crtc, target,
-                                              refclk, best_clock);
-
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-               if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
-                   LVDS_CLKB_POWER_UP)
-                       clock.p2 = limit->p2.p2_fast;
-               else
-                       clock.p2 = limit->p2.p2_slow;
-       } else {
-               if (target < limit->p2.dot_limit)
-                       clock.p2 = limit->p2.p2_slow;
-               else
-                       clock.p2 = limit->p2.p2_fast;
-       }
-
-       memset(best_clock, 0, sizeof(*best_clock));
-       for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
-               /* based on hardware requriment prefer smaller n to precision */
-               for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
-                       /* based on hardware requirment prefere larger m1,m2 */
-                       for (clock.m1 = limit->m1.max;
-                            clock.m1 >= limit->m1.min; clock.m1--) {
-                               for (clock.m2 = limit->m2.max;
-                                    clock.m2 >= limit->m2.min; clock.m2--) {
-                                       int this_err;
-
-                                       intel_clock(dev, refclk, &clock);
-                                       if (!intel_PLL_is_valid(crtc, &clock))
-                                               continue;
-                                       this_err = abs((10000 - (target*10000/clock.dot)));
-                                       if (this_err < err_most) {
-                                               *best_clock = clock;
-                                               /* found on first matching */
-                                               goto out;
-                                       } else if (this_err < err_min) {
-                                               *best_clock = clock;
-                                               err_min = this_err;
-                                       }
-                               }
-                       }
-               }
-       }
-out:
-       return true;
-}
-
 /* DisplayPort has only two frequencies, 162MHz and 270MHz */
 static bool
 intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
@@ -1493,6 +1473,10 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
        int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
        u32 temp;
        int tries = 5, j, n;
+       u32 pipe_bpc;
+
+       temp = I915_READ(pipeconf_reg);
+       pipe_bpc = temp & PIPE_BPC_MASK;
 
        /* XXX: When our outputs are all unaware of DPMS modes other than off
         * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
@@ -1524,6 +1508,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 
                        /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
                        temp = I915_READ(fdi_rx_reg);
+                       /*
+                        * make the BPC in FDI Rx be consistent with that in
+                        * pipeconf reg.
+                        */
+                       temp &= ~(0x7 << 16);
+                       temp |= (pipe_bpc << 11);
                        I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
                                        FDI_SEL_PCDCLK |
                                        FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
@@ -1666,6 +1656,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 
                        /* enable PCH transcoder */
                        temp = I915_READ(transconf_reg);
+                       /*
+                        * make the BPC in transcoder be consistent with
+                        * that in pipeconf reg.
+                        */
+                       temp &= ~PIPE_BPC_MASK;
+                       temp |= pipe_bpc;
                        I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
                        I915_READ(transconf_reg);
 
@@ -1745,6 +1741,9 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
                I915_READ(fdi_tx_reg);
 
                temp = I915_READ(fdi_rx_reg);
+               /* BPC in FDI rx is consistent with that in pipeconf */
+               temp &= ~(0x07 << 16);
+               temp |= (pipe_bpc << 11);
                I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
                I915_READ(fdi_rx_reg);
 
@@ -1789,7 +1788,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
                                }
                        }
                }
-
+               temp = I915_READ(transconf_reg);
+               /* BPC in transcoder is consistent with that in pipeconf */
+               temp &= ~PIPE_BPC_MASK;
+               temp |= pipe_bpc;
+               I915_WRITE(transconf_reg, temp);
+               I915_READ(transconf_reg);
                udelay(100);
 
                /* disable PCH DPLL */
@@ -2448,7 +2452,7 @@ static void pineview_enable_cxsr(struct drm_device *dev, unsigned long clock,
  * A value of 5us seems to be a good balance; safe for very low end
  * platforms but not overly aggressive on lower latency configs.
  */
-const static int latency_ns = 5000;
+static const int latency_ns = 5000;
 
 static int i9xx_get_fifo_size(struct drm_device *dev, int plane)
 {
@@ -2559,7 +2563,7 @@ static void g4x_update_wm(struct drm_device *dev,  int planea_clock,
        /* Calc sr entries for one plane configs */
        if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
                /* self-refresh has much higher latency */
-               const static int sr_latency_ns = 12000;
+               static const int sr_latency_ns = 12000;
 
                sr_clock = planea_clock ? planea_clock : planeb_clock;
                line_time_us = ((sr_hdisplay * 1000) / sr_clock);
@@ -2598,7 +2602,7 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
        /* Calc sr entries for one plane configs */
        if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
                /* self-refresh has much higher latency */
-               const static int sr_latency_ns = 12000;
+               static const int sr_latency_ns = 12000;
 
                sr_clock = planea_clock ? planea_clock : planeb_clock;
                line_time_us = ((sr_hdisplay * 1000) / sr_clock);
@@ -2667,7 +2671,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
        if (HAS_FW_BLC(dev) && sr_hdisplay &&
            (!planea_clock || !planeb_clock)) {
                /* self-refresh has much higher latency */
-               const static int sr_latency_ns = 6000;
+               static const int sr_latency_ns = 6000;
 
                sr_clock = planea_clock ? planea_clock : planeb_clock;
                line_time_us = ((sr_hdisplay * 1000) / sr_clock);
@@ -2969,6 +2973,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
                /* determine panel color depth */
                temp = I915_READ(pipeconf_reg);
+               temp &= ~PIPE_BPC_MASK;
+               if (is_lvds) {
+                       int lvds_reg = I915_READ(PCH_LVDS);
+                       /* the BPC will be 6 if it is 18-bit LVDS panel */
+                       if ((lvds_reg & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
+                               temp |= PIPE_8BPC;
+                       else
+                               temp |= PIPE_6BPC;
+               } else
+                       temp |= PIPE_8BPC;
+               I915_WRITE(pipeconf_reg, temp);
+               I915_READ(pipeconf_reg);
 
                switch (temp & PIPE_BPC_MASK) {
                case PIPE_8BPC:
@@ -3195,7 +3211,20 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                 * appropriately here, but we need to look more thoroughly into how
                 * panels behave in the two modes.
                 */
-
+               /* set the dithering flag */
+               if (IS_I965G(dev)) {
+                       if (dev_priv->lvds_dither) {
+                               if (IS_IRONLAKE(dev))
+                                       pipeconf |= PIPE_ENABLE_DITHER;
+                               else
+                                       lvds |= LVDS_ENABLE_DITHER;
+                       } else {
+                               if (IS_IRONLAKE(dev))
+                                       pipeconf &= ~PIPE_ENABLE_DITHER;
+                               else
+                                       lvds &= ~LVDS_ENABLE_DITHER;
+                       }
+               }
                I915_WRITE(lvds_reg, lvds);
                I915_READ(lvds_reg);
        }
@@ -3385,7 +3414,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 
        /* we only need to pin inside GTT if cursor is non-phy */
        mutex_lock(&dev->struct_mutex);
-       if (!dev_priv->cursor_needs_physical) {
+       if (!dev_priv->info->cursor_needs_physical) {
                ret = i915_gem_object_pin(bo, PAGE_SIZE);
                if (ret) {
                        DRM_ERROR("failed to pin cursor bo\n");
@@ -3420,7 +3449,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        I915_WRITE(base, addr);
 
        if (intel_crtc->cursor_bo) {
-               if (dev_priv->cursor_needs_physical) {
+               if (dev_priv->info->cursor_needs_physical) {
                        if (intel_crtc->cursor_bo != bo)
                                i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
                } else
@@ -3779,125 +3808,6 @@ static void intel_gpu_idle_timer(unsigned long arg)
        queue_work(dev_priv->wq, &dev_priv->idle_work);
 }
 
-void intel_increase_renderclock(struct drm_device *dev, bool schedule)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       if (IS_IRONLAKE(dev))
-               return;
-
-       if (!dev_priv->render_reclock_avail) {
-               DRM_DEBUG_DRIVER("not reclocking render clock\n");
-               return;
-       }
-
-       /* Restore render clock frequency to original value */
-       if (IS_G4X(dev) || IS_I9XX(dev))
-               pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock);
-       else if (IS_I85X(dev))
-               pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock);
-       DRM_DEBUG_DRIVER("increasing render clock frequency\n");
-
-       /* Schedule downclock */
-       if (schedule)
-               mod_timer(&dev_priv->idle_timer, jiffies +
-                         msecs_to_jiffies(GPU_IDLE_TIMEOUT));
-}
-
-void intel_decrease_renderclock(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       if (IS_IRONLAKE(dev))
-               return;
-
-       if (!dev_priv->render_reclock_avail) {
-               DRM_DEBUG_DRIVER("not reclocking render clock\n");
-               return;
-       }
-
-       if (IS_G4X(dev)) {
-               u16 gcfgc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-               /* Down to minimum... */
-               gcfgc &= ~GM45_GC_RENDER_CLOCK_MASK;
-               gcfgc |= GM45_GC_RENDER_CLOCK_266_MHZ;
-
-               pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-       } else if (IS_I965G(dev)) {
-               u16 gcfgc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-               /* Down to minimum... */
-               gcfgc &= ~I965_GC_RENDER_CLOCK_MASK;
-               gcfgc |= I965_GC_RENDER_CLOCK_267_MHZ;
-
-               pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-       } else if (IS_I945G(dev) || IS_I945GM(dev)) {
-               u16 gcfgc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-               /* Down to minimum... */
-               gcfgc &= ~I945_GC_RENDER_CLOCK_MASK;
-               gcfgc |= I945_GC_RENDER_CLOCK_166_MHZ;
-
-               pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-       } else if (IS_I915G(dev)) {
-               u16 gcfgc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-               /* Down to minimum... */
-               gcfgc &= ~I915_GC_RENDER_CLOCK_MASK;
-               gcfgc |= I915_GC_RENDER_CLOCK_166_MHZ;
-
-               pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-       } else if (IS_I85X(dev)) {
-               u16 hpllcc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, HPLLCC, &hpllcc);
-
-               /* Up to maximum... */
-               hpllcc &= ~GC_CLOCK_CONTROL_MASK;
-               hpllcc |= GC_CLOCK_133_200;
-
-               pci_write_config_word(dev->pdev, HPLLCC, hpllcc);
-       }
-       DRM_DEBUG_DRIVER("decreasing render clock frequency\n");
-}
-
-/* Note that no increase function is needed for this - increase_renderclock()
- *  will also rewrite these bits
- */
-void intel_decrease_displayclock(struct drm_device *dev)
-{
-       if (IS_IRONLAKE(dev))
-               return;
-
-       if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) ||
-           IS_I915GM(dev)) {
-               u16 gcfgc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-               /* Down to minimum... */
-               gcfgc &= ~0xf0;
-               gcfgc |= 0x80;
-
-               pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-       }
-}
-
 #define CRTC_IDLE_TIMEOUT 1000 /* ms */
 
 static void intel_crtc_idle_timer(unsigned long arg)
@@ -4011,12 +3921,6 @@ static void intel_idle_update(struct work_struct *work)
 
        mutex_lock(&dev->struct_mutex);
 
-       /* GPU isn't processing, downclock it. */
-       if (!dev_priv->busy) {
-               intel_decrease_renderclock(dev);
-               intel_decrease_displayclock(dev);
-       }
-
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                /* Skip inactive CRTCs */
                if (!crtc->fb)
@@ -4050,13 +3954,11 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return;
 
-       if (!dev_priv->busy) {
+       if (!dev_priv->busy)
                dev_priv->busy = true;
-               intel_increase_renderclock(dev, true);
-       } else {
+       else
                mod_timer(&dev_priv->idle_timer, jiffies +
                          msecs_to_jiffies(GPU_IDLE_TIMEOUT));
-       }
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                if (!crtc->fb)
@@ -4400,29 +4302,43 @@ static void intel_setup_outputs(struct drm_device *dev)
                bool found = false;
 
                if (I915_READ(SDVOB) & SDVO_DETECTED) {
+                       DRM_DEBUG_KMS("probing SDVOB\n");
                        found = intel_sdvo_init(dev, SDVOB);
-                       if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
+                       if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
+                               DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
                                intel_hdmi_init(dev, SDVOB);
+                       }
 
-                       if (!found && SUPPORTS_INTEGRATED_DP(dev))
+                       if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
+                               DRM_DEBUG_KMS("probing DP_B\n");
                                intel_dp_init(dev, DP_B);
+                       }
                }
 
                /* Before G4X SDVOC doesn't have its own detect register */
 
-               if (I915_READ(SDVOB) & SDVO_DETECTED)
+               if (I915_READ(SDVOB) & SDVO_DETECTED) {
+                       DRM_DEBUG_KMS("probing SDVOC\n");
                        found = intel_sdvo_init(dev, SDVOC);
+               }
 
                if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
 
-                       if (SUPPORTS_INTEGRATED_HDMI(dev))
+                       if (SUPPORTS_INTEGRATED_HDMI(dev)) {
+                               DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
                                intel_hdmi_init(dev, SDVOC);
-                       if (SUPPORTS_INTEGRATED_DP(dev))
+                       }
+                       if (SUPPORTS_INTEGRATED_DP(dev)) {
+                               DRM_DEBUG_KMS("probing DP_C\n");
                                intel_dp_init(dev, DP_C);
+                       }
                }
 
-               if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
+               if (SUPPORTS_INTEGRATED_DP(dev) &&
+                   (I915_READ(DP_D) & DP_DETECTED)) {
+                       DRM_DEBUG_KMS("probing DP_D\n");
                        intel_dp_init(dev, DP_D);
+               }
        } else if (IS_I8XX(dev))
                intel_dvo_init(dev);
 
@@ -4527,6 +4443,42 @@ static const struct drm_mode_config_funcs intel_mode_funcs = {
        .fb_changed = intelfb_probe,
 };
 
+static struct drm_gem_object *
+intel_alloc_power_context(struct drm_device *dev)
+{
+       struct drm_gem_object *pwrctx;
+       int ret;
+
+       pwrctx = drm_gem_object_alloc(dev, 4096);
+       if (!pwrctx) {
+               DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
+               return NULL;
+       }
+
+       mutex_lock(&dev->struct_mutex);
+       ret = i915_gem_object_pin(pwrctx, 4096);
+       if (ret) {
+               DRM_ERROR("failed to pin power context: %d\n", ret);
+               goto err_unref;
+       }
+
+       ret = i915_gem_object_set_to_gtt_domain(pwrctx, 1);
+       if (ret) {
+               DRM_ERROR("failed to set-domain on power context: %d\n", ret);
+               goto err_unpin;
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       return pwrctx;
+
+err_unpin:
+       i915_gem_object_unpin(pwrctx);
+err_unref:
+       drm_gem_object_unreference(pwrctx);
+       mutex_unlock(&dev->struct_mutex);
+       return NULL;
+}
+
 void intel_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4579,42 +4531,27 @@ void intel_init_clock_gating(struct drm_device *dev)
         * GPU can automatically power down the render unit if given a page
         * to save state.
         */
-       if (I915_HAS_RC6(dev)) {
-               struct drm_gem_object *pwrctx;
-               struct drm_i915_gem_object *obj_priv;
-               int ret;
+       if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) {
+               struct drm_i915_gem_object *obj_priv = NULL;
 
                if (dev_priv->pwrctx) {
                        obj_priv = dev_priv->pwrctx->driver_private;
                } else {
-                       pwrctx = drm_gem_object_alloc(dev, 4096);
-                       if (!pwrctx) {
-                               DRM_DEBUG("failed to alloc power context, "
-                                         "RC6 disabled\n");
-                               goto out;
-                       }
+                       struct drm_gem_object *pwrctx;
 
-                       ret = i915_gem_object_pin(pwrctx, 4096);
-                       if (ret) {
-                               DRM_ERROR("failed to pin power context: %d\n",
-                                         ret);
-                               drm_gem_object_unreference(pwrctx);
-                               goto out;
+                       pwrctx = intel_alloc_power_context(dev);
+                       if (pwrctx) {
+                               dev_priv->pwrctx = pwrctx;
+                               obj_priv = pwrctx->driver_private;
                        }
-
-                       i915_gem_object_set_to_gtt_domain(pwrctx, 1);
-
-                       dev_priv->pwrctx = pwrctx;
-                       obj_priv = pwrctx->driver_private;
                }
 
-               I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN);
-               I915_WRITE(MCHBAR_RENDER_STANDBY,
-                          I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);
+               if (obj_priv) {
+                       I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN);
+                       I915_WRITE(MCHBAR_RENDER_STANDBY,
+                                  I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);
+               }
        }
-
-out:
-       return;
 }
 
 /* Set up chip specific display functions */
@@ -4770,7 +4707,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
                del_timer_sync(&intel_crtc->idle_timer);
        }
 
-       intel_increase_renderclock(dev, false);
        del_timer_sync(&dev_priv->idle_timer);
 
        if (dev_priv->display.disable_fbc)
index 4e7aa8b7b938ba36ea101b4284a577c60b7145c0..1349d9fd01c4aaea6ae1a6af1a3ab5f4b09dc718 100644 (file)
@@ -1402,14 +1402,20 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                        break;
                case DP_B:
                case PCH_DP_B:
+                       dev_priv->hotplug_supported_mask |=
+                               HDMIB_HOTPLUG_INT_STATUS;
                        name = "DPDDC-B";
                        break;
                case DP_C:
                case PCH_DP_C:
+                       dev_priv->hotplug_supported_mask |=
+                               HDMIC_HOTPLUG_INT_STATUS;
                        name = "DPDDC-C";
                        break;
                case DP_D:
                case PCH_DP_D:
+                       dev_priv->hotplug_supported_mask |=
+                               HDMID_HOTPLUG_INT_STATUS;
                        name = "DPDDC-D";
                        break;
        }
index f04dbbe7d4005c6b123bfedc3dde6bc43bda9d18..06431941b23314975eb55caad23419c48674e341 100644 (file)
@@ -303,21 +303,26 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
        if (sdvox_reg == SDVOB) {
                intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
+               dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == SDVOC) {
                intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
+               dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == HDMIB) {
                intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
                                                                "HDMIB");
+               dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == HDMIC) {
                intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
                                                                "HDMIC");
+               dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == HDMID) {
                intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
                                                                "HDMID");
+               dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
        }
        if (!intel_output->ddc_bus)
                goto err_connector;
index 3118ce274e67a6f2723e21a6c3bd873c160405d1..f4b4aa242df182c9c2c0b1f314d8e2d217844f23 100644 (file)
@@ -608,6 +608,13 @@ static const struct dmi_system_id bad_lid_status[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"),
                },
        },
+       {
+               .ident = "PC-81005",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MALATA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PC-81005"),
+               },
+       },
        { }
 };
 
@@ -679,7 +686,14 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
        struct drm_i915_private *dev_priv =
                container_of(nb, struct drm_i915_private, lid_notifier);
        struct drm_device *dev = dev_priv->dev;
+       struct drm_connector *connector = dev_priv->int_lvds_connector;
 
+       /*
+        * check and update the status of LVDS connector after receiving
+        * the LID nofication event.
+        */
+       if (connector)
+               connector->status = connector->funcs->detect(connector);
        if (!acpi_lid_open()) {
                dev_priv->modeset_on_lid = 1;
                return NOTIFY_OK;
@@ -854,65 +868,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
        { }     /* terminating entry */
 };
 
-#ifdef CONFIG_ACPI
-/*
- * check_lid_device -- check whether @handle is an ACPI LID device.
- * @handle: ACPI device handle
- * @level : depth in the ACPI namespace tree
- * @context: the number of LID device when we find the device
- * @rv: a return value to fill if desired (Not use)
- */
-static acpi_status
-check_lid_device(acpi_handle handle, u32 level, void *context,
-                       void **return_value)
-{
-       struct acpi_device *acpi_dev;
-       int *lid_present = context;
-
-       acpi_dev = NULL;
-       /* Get the acpi device for device handle */
-       if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) {
-               /* If there is no ACPI device for handle, return */
-               return AE_OK;
-       }
-
-       if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7))
-               *lid_present = 1;
-
-       return AE_OK;
-}
-
-/**
- * check whether there exists the ACPI LID device by enumerating the ACPI
- * device tree.
- */
-static int intel_lid_present(void)
-{
-       int lid_present = 0;
-
-       if (acpi_disabled) {
-               /* If ACPI is disabled, there is no ACPI device tree to
-                * check, so assume the LID device would have been present.
-                */
-               return 1;
-       }
-
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                               ACPI_UINT32_MAX,
-                               check_lid_device, NULL, &lid_present, NULL);
-
-       return lid_present;
-}
-#else
-static int intel_lid_present(void)
-{
-       /* In the absence of ACPI built in, assume that the LID device would
-        * have been present.
-        */
-       return 1;
-}
-#endif
-
 /**
  * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
  * @dev: drm device
@@ -1031,12 +986,8 @@ void intel_lvds_init(struct drm_device *dev)
        if (dmi_check_system(intel_no_lvds))
                return;
 
-       /*
-        * Assume LVDS is present if there's an ACPI lid device or if the
-        * device is present in the VBT.
-        */
-       if (!lvds_is_present_in_vbt(dev) && !intel_lid_present()) {
-               DRM_DEBUG_KMS("LVDS is not present in VBT and no lid detected\n");
+       if (!lvds_is_present_in_vbt(dev)) {
+               DRM_DEBUG_KMS("LVDS is not present in VBT\n");
                return;
        }
 
@@ -1180,6 +1131,8 @@ out:
                DRM_DEBUG_KMS("lid notifier registration failed\n");
                dev_priv->lid_notifier.notifier_call = NULL;
        }
+       /* keep the LVDS connector */
+       dev_priv->int_lvds_connector = connector;
        drm_sysfs_connector_add(connector);
        return;
 
index 24a3dc99716c5c8e5490ded0abd503312a544f2a..de5144c8c153cc974f36de35b40ebd7f73da31b6 100644 (file)
@@ -2662,6 +2662,7 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
 
 bool intel_sdvo_init(struct drm_device *dev, int output_device)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_connector *connector;
        struct intel_output *intel_output;
        struct intel_sdvo_priv *sdvo_priv;
@@ -2708,10 +2709,12 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
                sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
                                                "SDVOB/VGA DDC BUS");
+               dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
        } else {
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
                sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
                                                "SDVOC/VGA DDC BUS");
+               dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
        }
 
        if (intel_output->ddc_bus == NULL)
index 552ec110b74197c2394058ef4c89b144bc3e3137..1d5b9b7b033f25756f052b2143721894443d216a 100644 (file)
@@ -1840,6 +1840,8 @@ intel_tv_init(struct drm_device *dev)
        drm_connector_attach_property(connector,
                                   dev->mode_config.tv_bottom_margin_property,
                                   tv_priv->margin[TV_MARGIN_BOTTOM]);
+
+       dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS;
 out:
        drm_sysfs_connector_add(connector);
 }
index b1bc1ea182b80362dea6dee9f3c098d96e9744f4..1175429da1029bf18feb23813aaa223cae651283 100644 (file)
@@ -30,12 +30,11 @@ config DRM_NOUVEAU_DEBUG
          via debugfs.
 
 menu "I2C encoder or helper chips"
-     depends on DRM && I2C
+     depends on DRM && DRM_KMS_HELPER && I2C
 
 config DRM_I2C_CH7006
        tristate "Chrontel ch7006 TV encoder"
-       depends on DRM_NOUVEAU
-       default m
+       default m if DRM_NOUVEAU
        help
          Support for Chrontel ch7006 and similar TV encoders, found
          on some nVidia video cards.
index 0cad6d834eb28cc386ca82e4df36b83374371e98..e342a418d434d41b9807ad2dd27683e0d4744084 100644 (file)
 #include "nouveau_drv.h"
 #include "nouveau_dma.h"
 
+#include <linux/log2.h>
+
 static void
 nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
 {
        struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+       struct drm_device *dev = dev_priv->dev;
        struct nouveau_bo *nvbo = nouveau_bo(bo);
 
        ttm_bo_kunmap(&nvbo->kmap);
@@ -44,12 +47,87 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
        if (unlikely(nvbo->gem))
                DRM_ERROR("bo %p still attached to GEM object\n", bo);
 
+       if (nvbo->tile)
+               nv10_mem_expire_tiling(dev, nvbo->tile, NULL);
+
        spin_lock(&dev_priv->ttm.bo_list_lock);
        list_del(&nvbo->head);
        spin_unlock(&dev_priv->ttm.bo_list_lock);
        kfree(nvbo);
 }
 
+static void
+nouveau_bo_fixup_align(struct drm_device *dev,
+                      uint32_t tile_mode, uint32_t tile_flags,
+                      int *align, int *size)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       /*
+        * Some of the tile_flags have a periodic structure of N*4096 bytes,
+        * align to to that as well as the page size. Overallocate memory to
+        * avoid corruption of other buffer objects.
+        */
+       if (dev_priv->card_type == NV_50) {
+               uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15;
+               int i;
+
+               switch (tile_flags) {
+               case 0x1800:
+               case 0x2800:
+               case 0x4800:
+               case 0x7a00:
+                       *size = roundup(*size, block_size);
+                       if (is_power_of_2(block_size)) {
+                               *size += 3 * block_size;
+                               for (i = 1; i < 10; i++) {
+                                       *align = 12 * i * block_size;
+                                       if (!(*align % 65536))
+                                               break;
+                               }
+                       } else {
+                               *size += 6 * block_size;
+                               for (i = 1; i < 10; i++) {
+                                       *align = 8 * i * block_size;
+                                       if (!(*align % 65536))
+                                               break;
+                               }
+                       }
+                       break;
+               default:
+                       break;
+               }
+
+       } else {
+               if (tile_mode) {
+                       if (dev_priv->chipset >= 0x40) {
+                               *align = 65536;
+                               *size = roundup(*size, 64 * tile_mode);
+
+                       } else if (dev_priv->chipset >= 0x30) {
+                               *align = 32768;
+                               *size = roundup(*size, 64 * tile_mode);
+
+                       } else if (dev_priv->chipset >= 0x20) {
+                               *align = 16384;
+                               *size = roundup(*size, 64 * tile_mode);
+
+                       } else if (dev_priv->chipset >= 0x10) {
+                               *align = 16384;
+                               *size = roundup(*size, 32 * tile_mode);
+                       }
+               }
+       }
+
+       /* ALIGN works only on powers of two. */
+       *size = roundup(*size, PAGE_SIZE);
+
+       if (dev_priv->card_type == NV_50) {
+               *size = roundup(*size, 65536);
+               *align = max(65536, *align);
+       }
+}
+
 int
 nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
               int size, int align, uint32_t flags, uint32_t tile_mode,
@@ -58,7 +136,7 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_bo *nvbo;
-       int ret, n = 0;
+       int ret = 0;
 
        nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
        if (!nvbo)
@@ -70,59 +148,14 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
        nvbo->tile_mode = tile_mode;
        nvbo->tile_flags = tile_flags;
 
-       /*
-        * Some of the tile_flags have a periodic structure of N*4096 bytes,
-        * align to to that as well as the page size. Overallocate memory to
-        * avoid corruption of other buffer objects.
-        */
-       switch (tile_flags) {
-       case 0x1800:
-       case 0x2800:
-       case 0x4800:
-       case 0x7a00:
-               if (dev_priv->chipset >= 0xA0) {
-                       /* This is based on high end cards with 448 bits
-                        * memory bus, could be different elsewhere.*/
-                       size += 6 * 28672;
-                       /* 8 * 28672 is the actual alignment requirement,
-                        * but we must also align to page size. */
-                       align = 2 * 8 * 28672;
-               } else if (dev_priv->chipset >= 0x90) {
-                       size += 3 * 16384;
-                       align = 12 * 16834;
-               } else {
-                       size += 3 * 8192;
-                       /* 12 * 8192 is the actual alignment requirement,
-                        * but we must also align to page size. */
-                       align = 2 * 12 * 8192;
-               }
-               break;
-       default:
-               break;
-       }
-
+       nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size);
        align >>= PAGE_SHIFT;
 
-       size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-       if (dev_priv->card_type == NV_50) {
-               size = (size + 65535) & ~65535;
-               if (align < (65536 / PAGE_SIZE))
-                       align = (65536 / PAGE_SIZE);
-       }
-
-       if (flags & TTM_PL_FLAG_VRAM)
-               nvbo->placements[n++] = TTM_PL_FLAG_VRAM | TTM_PL_MASK_CACHING;
-       if (flags & TTM_PL_FLAG_TT)
-               nvbo->placements[n++] = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
        nvbo->placement.fpfn = 0;
        nvbo->placement.lpfn = mappable ? dev_priv->fb_mappable_pages : 0;
-       nvbo->placement.placement = nvbo->placements;
-       nvbo->placement.busy_placement = nvbo->placements;
-       nvbo->placement.num_placement = n;
-       nvbo->placement.num_busy_placement = n;
+       nouveau_bo_placement_set(nvbo, flags);
 
        nvbo->channel = chan;
-       nouveau_bo_placement_set(nvbo, flags);
        ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
                          ttm_bo_type_device, &nvbo->placement, align, 0,
                          false, NULL, size, nouveau_bo_del_ttm);
@@ -421,6 +454,7 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
 /* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access
  * TTM_PL_{VRAM,TT} directly.
  */
+
 static int
 nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
                              struct nouveau_bo *nvbo, bool evict, bool no_wait,
@@ -455,11 +489,12 @@ nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan,
 }
 
 static int
-nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, int no_wait,
-                    struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
+nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
+                    int no_wait, struct ttm_mem_reg *new_mem)
 {
        struct nouveau_bo *nvbo = nouveau_bo(bo);
        struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+       struct ttm_mem_reg *old_mem = &bo->mem;
        struct nouveau_channel *chan;
        uint64_t src_offset, dst_offset;
        uint32_t page_count;
@@ -547,7 +582,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
 
        placement.fpfn = placement.lpfn = 0;
        placement.num_placement = placement.num_busy_placement = 1;
-       placement.placement = &placement_memtype;
+       placement.placement = placement.busy_placement = &placement_memtype;
 
        tmp_mem = *new_mem;
        tmp_mem.mm_node = NULL;
@@ -559,7 +594,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
        if (ret)
                goto out;
 
-       ret = nouveau_bo_move_m2mf(bo, true, no_wait, &bo->mem, &tmp_mem);
+       ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait, &tmp_mem);
        if (ret)
                goto out;
 
@@ -585,7 +620,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr,
 
        placement.fpfn = placement.lpfn = 0;
        placement.num_placement = placement.num_busy_placement = 1;
-       placement.placement = &placement_memtype;
+       placement.placement = placement.busy_placement = &placement_memtype;
 
        tmp_mem = *new_mem;
        tmp_mem.mm_node = NULL;
@@ -597,7 +632,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr,
        if (ret)
                goto out;
 
-       ret = nouveau_bo_move_m2mf(bo, true, no_wait, &bo->mem, new_mem);
+       ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait, new_mem);
        if (ret)
                goto out;
 
@@ -612,52 +647,106 @@ out:
 }
 
 static int
-nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
-               bool no_wait, struct ttm_mem_reg *new_mem)
+nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
+                  struct nouveau_tile_reg **new_tile)
 {
        struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
-       struct nouveau_bo *nvbo = nouveau_bo(bo);
        struct drm_device *dev = dev_priv->dev;
-       struct ttm_mem_reg *old_mem = &bo->mem;
+       struct nouveau_bo *nvbo = nouveau_bo(bo);
+       uint64_t offset;
        int ret;
 
-       if (dev_priv->card_type == NV_50 && new_mem->mem_type == TTM_PL_VRAM &&
-           !nvbo->no_vm) {
-               uint64_t offset = new_mem->mm_node->start << PAGE_SHIFT;
+       if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) {
+               /* Nothing to do. */
+               *new_tile = NULL;
+               return 0;
+       }
+
+       offset = new_mem->mm_node->start << PAGE_SHIFT;
 
+       if (dev_priv->card_type == NV_50) {
                ret = nv50_mem_vm_bind_linear(dev,
                                              offset + dev_priv->vm_vram_base,
                                              new_mem->size, nvbo->tile_flags,
                                              offset);
                if (ret)
                        return ret;
+
+       } else if (dev_priv->card_type >= NV_10) {
+               *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size,
+                                               nvbo->tile_mode);
        }
 
+       return 0;
+}
+
+static void
+nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
+                     struct nouveau_tile_reg *new_tile,
+                     struct nouveau_tile_reg **old_tile)
+{
+       struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+       struct drm_device *dev = dev_priv->dev;
+
+       if (dev_priv->card_type >= NV_10 &&
+           dev_priv->card_type < NV_50) {
+               if (*old_tile)
+                       nv10_mem_expire_tiling(dev, *old_tile, bo->sync_obj);
+
+               *old_tile = new_tile;
+       }
+}
+
+static int
+nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
+               bool no_wait, struct ttm_mem_reg *new_mem)
+{
+       struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+       struct nouveau_bo *nvbo = nouveau_bo(bo);
+       struct ttm_mem_reg *old_mem = &bo->mem;
+       struct nouveau_tile_reg *new_tile = NULL;
+       int ret = 0;
+
+       ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile);
+       if (ret)
+               return ret;
+
+       /* Software copy if the card isn't up and running yet. */
        if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE ||
-           !dev_priv->channel)
-               return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+           !dev_priv->channel) {
+               ret = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+               goto out;
+       }
 
+       /* Fake bo copy. */
        if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
                BUG_ON(bo->mem.mm_node != NULL);
                bo->mem = *new_mem;
                new_mem->mm_node = NULL;
-               return 0;
+               goto out;
        }
 
-       if (new_mem->mem_type == TTM_PL_SYSTEM) {
-               if (old_mem->mem_type == TTM_PL_SYSTEM)
-                       return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-               if (nouveau_bo_move_flipd(bo, evict, intr, no_wait, new_mem))
-                       return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-       } else if (old_mem->mem_type == TTM_PL_SYSTEM) {
-               if (nouveau_bo_move_flips(bo, evict, intr, no_wait, new_mem))
-                       return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-       } else {
-               if (nouveau_bo_move_m2mf(bo, evict, no_wait, old_mem, new_mem))
-                       return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-       }
+       /* Hardware assisted copy. */
+       if (new_mem->mem_type == TTM_PL_SYSTEM)
+               ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait, new_mem);
+       else if (old_mem->mem_type == TTM_PL_SYSTEM)
+               ret = nouveau_bo_move_flips(bo, evict, intr, no_wait, new_mem);
+       else
+               ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait, new_mem);
 
-       return 0;
+       if (!ret)
+               goto out;
+
+       /* Fallback to software copy. */
+       ret = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+
+out:
+       if (ret)
+               nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
+       else
+               nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile);
+
+       return ret;
 }
 
 static int
index 9aaa972f882248002d59b4d02d7bbc8f47ba17b8..343d718a9667625e4900f78f2bb757a1ebdd4fd9 100644 (file)
@@ -158,6 +158,8 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
                return ret;
        }
 
+       nouveau_dma_pre_init(chan);
+
        /* Locate channel's user control regs */
        if (dev_priv->card_type < NV_40)
                user = NV03_USER(channel);
@@ -235,47 +237,6 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
        return 0;
 }
 
-int
-nouveau_channel_idle(struct nouveau_channel *chan)
-{
-       struct drm_device *dev = chan->dev;
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_engine *engine = &dev_priv->engine;
-       uint32_t caches;
-       int idle;
-
-       if (!chan) {
-               NV_ERROR(dev, "no channel...\n");
-               return 1;
-       }
-
-       caches = nv_rd32(dev, NV03_PFIFO_CACHES);
-       nv_wr32(dev, NV03_PFIFO_CACHES, caches & ~1);
-
-       if (engine->fifo.channel_id(dev) != chan->id) {
-               struct nouveau_gpuobj *ramfc =
-                       chan->ramfc ? chan->ramfc->gpuobj : NULL;
-
-               if (!ramfc) {
-                       NV_ERROR(dev, "No RAMFC for channel %d\n", chan->id);
-                       return 1;
-               }
-
-               engine->instmem.prepare_access(dev, false);
-               if (nv_ro32(dev, ramfc, 0) != nv_ro32(dev, ramfc, 1))
-                       idle = 0;
-               else
-                       idle = 1;
-               engine->instmem.finish_access(dev);
-       } else {
-               idle = (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET) ==
-                       nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
-       }
-
-       nv_wr32(dev, NV03_PFIFO_CACHES, caches);
-       return idle;
-}
-
 /* stops a fifo */
 void
 nouveau_channel_free(struct nouveau_channel *chan)
@@ -414,7 +375,9 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
                init->subchan[0].grclass = 0x0039;
        else
                init->subchan[0].grclass = 0x5039;
-       init->nr_subchan = 1;
+       init->subchan[1].handle = NvSw;
+       init->subchan[1].grclass = NV_SW;
+       init->nr_subchan = 2;
 
        /* Named memory object area */
        ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem,
index 703553687b205a543b7d0963744a87ba0a58e3d0..7afbe8b40d511f39f034d29b62e971ac6eab2a79 100644 (file)
 #include "nouveau_drv.h"
 #include "nouveau_dma.h"
 
+void
+nouveau_dma_pre_init(struct nouveau_channel *chan)
+{
+       chan->dma.max  = (chan->pushbuf_bo->bo.mem.size >> 2) - 2;
+       chan->dma.put  = 0;
+       chan->dma.cur  = chan->dma.put;
+       chan->dma.free = chan->dma.max - chan->dma.cur;
+}
+
 int
 nouveau_dma_init(struct nouveau_channel *chan)
 {
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_gpuobj *m2mf = NULL;
+       struct nouveau_gpuobj *nvsw = NULL;
        int ret, i;
 
        /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
@@ -47,6 +57,15 @@ nouveau_dma_init(struct nouveau_channel *chan)
        if (ret)
                return ret;
 
+       /* Create an NV_SW object for various sync purposes */
+       ret = nouveau_gpuobj_sw_new(chan, NV_SW, &nvsw);
+       if (ret)
+               return ret;
+
+       ret = nouveau_gpuobj_ref_add(dev, chan, NvSw, nvsw, NULL);
+       if (ret)
+               return ret;
+
        /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */
        ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy);
        if (ret)
@@ -64,12 +83,6 @@ nouveau_dma_init(struct nouveau_channel *chan)
                        return ret;
        }
 
-       /* Initialise DMA vars */
-       chan->dma.max  = (chan->pushbuf_bo->bo.mem.size >> 2) - 2;
-       chan->dma.put  = 0;
-       chan->dma.cur  = chan->dma.put;
-       chan->dma.free = chan->dma.max - chan->dma.cur;
-
        /* Insert NOPS for NOUVEAU_DMA_SKIPS */
        ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS);
        if (ret)
@@ -87,6 +100,13 @@ nouveau_dma_init(struct nouveau_channel *chan)
        BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
        OUT_RING(chan, NvNotify0);
 
+       /* Initialise NV_SW */
+       ret = RING_SPACE(chan, 2);
+       if (ret)
+               return ret;
+       BEGIN_RING(chan, NvSubSw, 0, 1);
+       OUT_RING(chan, NvSw);
+
        /* Sit back and pray the channel works.. */
        FIRE_RING(chan);
 
@@ -113,7 +133,7 @@ READ_GET(struct nouveau_channel *chan, uint32_t *get)
 
        val = nvchan_rd32(chan, chan->user_get);
        if (val < chan->pushbuf_base ||
-           val >= chan->pushbuf_base + chan->pushbuf_bo->bo.mem.size) {
+           val > chan->pushbuf_base + (chan->dma.max << 2)) {
                /* meaningless to dma_wait() except to know whether the
                 * GPU has stalled or not
                 */
index 04e85d8f757e80ccb5d62769b6596762d209e174..dabfd655f93ec84e0a7f74a27f031c87c6234bfb 100644 (file)
 /* Hardcoded object assignments to subchannels (subchannel id). */
 enum {
        NvSubM2MF       = 0,
-       NvSub2D         = 1,
-       NvSubCtxSurf2D  = 1,
-       NvSubGdiRect    = 2,
-       NvSubImageBlit  = 3
+       NvSubSw         = 1,
+       NvSub2D         = 2,
+       NvSubCtxSurf2D  = 2,
+       NvSubGdiRect    = 3,
+       NvSubImageBlit  = 4
 };
 
 /* Object handles. */
@@ -67,6 +68,7 @@ enum {
        NvClipRect      = 0x8000000b,
        NvGdiRect       = 0x8000000c,
        NvImageBlit     = 0x8000000d,
+       NvSw            = 0x8000000e,
 
        /* G80+ display objects */
        NvEvoVRAM       = 0x01000000,
index 5f8cbb79c499169be20c6ec3c0af06efe9894b7c..026419fe8791e3cb941874398872ad23ef7ce811 100644 (file)
@@ -59,11 +59,19 @@ struct nouveau_grctx;
 #define MAX_NUM_DCB_ENTRIES 16
 
 #define NOUVEAU_MAX_CHANNEL_NR 128
+#define NOUVEAU_MAX_TILE_NR 15
 
 #define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL)
 #define NV50_VM_BLOCK    (512*1024*1024ULL)
 #define NV50_VM_VRAM_NR  (NV50_VM_MAX_VRAM / NV50_VM_BLOCK)
 
+struct nouveau_tile_reg {
+       struct nouveau_fence *fence;
+       uint32_t addr;
+       uint32_t size;
+       bool used;
+};
+
 struct nouveau_bo {
        struct ttm_buffer_object bo;
        struct ttm_placement placement;
@@ -83,6 +91,7 @@ struct nouveau_bo {
 
        uint32_t tile_mode;
        uint32_t tile_flags;
+       struct nouveau_tile_reg *tile;
 
        struct drm_gem_object *gem;
        struct drm_file *cpu_filp;
@@ -277,8 +286,13 @@ struct nouveau_timer_engine {
 };
 
 struct nouveau_fb_engine {
+       int num_tiles;
+
        int  (*init)(struct drm_device *dev);
        void (*takedown)(struct drm_device *dev);
+
+       void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
+                                uint32_t size, uint32_t pitch);
 };
 
 struct nouveau_fifo_engine {
@@ -292,6 +306,8 @@ struct nouveau_fifo_engine {
        void (*disable)(struct drm_device *);
        void (*enable)(struct drm_device *);
        bool (*reassign)(struct drm_device *, bool enable);
+       bool (*cache_flush)(struct drm_device *dev);
+       bool (*cache_pull)(struct drm_device *dev, bool enable);
 
        int  (*channel_id)(struct drm_device *);
 
@@ -330,6 +346,9 @@ struct nouveau_pgraph_engine {
        void (*destroy_context)(struct nouveau_channel *);
        int  (*load_context)(struct nouveau_channel *);
        int  (*unload_context)(struct drm_device *);
+
+       void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
+                                 uint32_t size, uint32_t pitch);
 };
 
 struct nouveau_engine {
@@ -548,6 +567,12 @@ struct drm_nouveau_private {
                unsigned long sg_handle;
        } gart_info;
 
+       /* nv10-nv40 tiling regions */
+       struct {
+               struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR];
+               spinlock_t lock;
+       } tile;
+
        /* G8x/G9x virtual address space */
        uint64_t vm_gart_base;
        uint64_t vm_gart_size;
@@ -685,6 +710,13 @@ extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap);
 extern int  nouveau_mem_init(struct drm_device *);
 extern int  nouveau_mem_init_agp(struct drm_device *);
 extern void nouveau_mem_close(struct drm_device *);
+extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev,
+                                                   uint32_t addr,
+                                                   uint32_t size,
+                                                   uint32_t pitch);
+extern void nv10_mem_expire_tiling(struct drm_device *dev,
+                                  struct nouveau_tile_reg *tile,
+                                  struct nouveau_fence *fence);
 extern int  nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt,
                                    uint32_t size, uint32_t flags,
                                    uint64_t phys);
@@ -713,7 +745,6 @@ extern int  nouveau_channel_alloc(struct drm_device *dev,
                                  struct drm_file *file_priv,
                                  uint32_t fb_ctxdma, uint32_t tt_ctxdma);
 extern void nouveau_channel_free(struct nouveau_channel *);
-extern int  nouveau_channel_idle(struct nouveau_channel *chan);
 
 /* nouveau_object.c */
 extern int  nouveau_gpuobj_early_init(struct drm_device *);
@@ -756,6 +787,8 @@ extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *,
                                       uint32_t *o_ret);
 extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class,
                                 struct nouveau_gpuobj **);
+extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class,
+                                struct nouveau_gpuobj **);
 extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data,
                                     struct drm_file *);
 extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data,
@@ -804,6 +837,7 @@ nouveau_debugfs_channel_fini(struct nouveau_channel *chan)
 #endif
 
 /* nouveau_dma.c */
+extern void nouveau_dma_pre_init(struct nouveau_channel *);
 extern int  nouveau_dma_init(struct nouveau_channel *);
 extern int  nouveau_dma_wait(struct nouveau_channel *, int size);
 
@@ -879,16 +913,22 @@ extern void nv04_fb_takedown(struct drm_device *);
 /* nv10_fb.c */
 extern int  nv10_fb_init(struct drm_device *);
 extern void nv10_fb_takedown(struct drm_device *);
+extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t,
+                                     uint32_t, uint32_t);
 
 /* nv40_fb.c */
 extern int  nv40_fb_init(struct drm_device *);
 extern void nv40_fb_takedown(struct drm_device *);
+extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t,
+                                     uint32_t, uint32_t);
 
 /* nv04_fifo.c */
 extern int  nv04_fifo_init(struct drm_device *);
 extern void nv04_fifo_disable(struct drm_device *);
 extern void nv04_fifo_enable(struct drm_device *);
 extern bool nv04_fifo_reassign(struct drm_device *, bool);
+extern bool nv04_fifo_cache_flush(struct drm_device *);
+extern bool nv04_fifo_cache_pull(struct drm_device *, bool);
 extern int  nv04_fifo_channel_id(struct drm_device *);
 extern int  nv04_fifo_create_context(struct nouveau_channel *);
 extern void nv04_fifo_destroy_context(struct nouveau_channel *);
@@ -941,6 +981,8 @@ extern void nv10_graph_destroy_context(struct nouveau_channel *);
 extern int  nv10_graph_load_context(struct nouveau_channel *);
 extern int  nv10_graph_unload_context(struct drm_device *);
 extern void nv10_graph_context_switch(struct drm_device *);
+extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t,
+                                        uint32_t, uint32_t);
 
 /* nv20_graph.c */
 extern struct nouveau_pgraph_object_class nv20_graph_grclass[];
@@ -952,6 +994,8 @@ extern int  nv20_graph_unload_context(struct drm_device *);
 extern int  nv20_graph_init(struct drm_device *);
 extern void nv20_graph_takedown(struct drm_device *);
 extern int  nv30_graph_init(struct drm_device *);
+extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t,
+                                        uint32_t, uint32_t);
 
 /* nv40_graph.c */
 extern struct nouveau_pgraph_object_class nv40_graph_grclass[];
@@ -963,6 +1007,8 @@ extern void nv40_graph_destroy_context(struct nouveau_channel *);
 extern int  nv40_graph_load_context(struct nouveau_channel *);
 extern int  nv40_graph_unload_context(struct drm_device *);
 extern void nv40_grctx_init(struct nouveau_grctx *);
+extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t,
+                                        uint32_t, uint32_t);
 
 /* nv50_graph.c */
 extern struct nouveau_pgraph_object_class nv50_graph_grclass[];
@@ -1030,8 +1076,7 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
 
 /* nv04_dac.c */
 extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry);
-extern enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder,
-                                                struct drm_connector *connector);
+extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
 extern int nv04_dac_output_offset(struct drm_encoder *encoder);
 extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);
 
@@ -1049,9 +1094,6 @@ extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry);
 
 /* nv17_tv.c */
 extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry);
-extern enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder,
-                                               struct drm_connector *connector,
-                                               uint32_t pin_mask);
 
 /* nv04_display.c */
 extern int nv04_display_create(struct drm_device *);
@@ -1290,14 +1332,14 @@ nv_two_reg_pll(struct drm_device *dev)
        return false;
 }
 
-#define NV50_NVSW                                                    0x0000506e
-#define NV50_NVSW_DMA_SEMAPHORE                                      0x00000060
-#define NV50_NVSW_SEMAPHORE_OFFSET                                   0x00000064
-#define NV50_NVSW_SEMAPHORE_ACQUIRE                                  0x00000068
-#define NV50_NVSW_SEMAPHORE_RELEASE                                  0x0000006c
-#define NV50_NVSW_DMA_VBLSEM                                         0x0000018c
-#define NV50_NVSW_VBLSEM_OFFSET                                      0x00000400
-#define NV50_NVSW_VBLSEM_RELEASE_VALUE                               0x00000404
-#define NV50_NVSW_VBLSEM_RELEASE                                     0x00000408
+#define NV_SW                                                        0x0000506e
+#define NV_SW_DMA_SEMAPHORE                                          0x00000060
+#define NV_SW_SEMAPHORE_OFFSET                                       0x00000064
+#define NV_SW_SEMAPHORE_ACQUIRE                                      0x00000068
+#define NV_SW_SEMAPHORE_RELEASE                                      0x0000006c
+#define NV_SW_DMA_VBLSEM                                             0x0000018c
+#define NV_SW_VBLSEM_OFFSET                                          0x00000400
+#define NV_SW_VBLSEM_RELEASE_VALUE                                   0x00000404
+#define NV_SW_VBLSEM_RELEASE                                         0x00000408
 
 #endif /* __NOUVEAU_DRV_H__ */
index 84af25c238b64314997635ce4bab9ae3a9eb5721..0b05c869e0e7644c787b1abb54252f0351fb1f98 100644 (file)
@@ -64,8 +64,7 @@ nouveau_fbcon_sync(struct fb_info *info)
                return 0;
 
        if (RING_SPACE(chan, 4)) {
-               NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
-               info->flags |= FBINFO_HWACCEL_DISABLED;
+               nouveau_fbcon_gpu_lockup(info);
                return 0;
        }
 
@@ -86,8 +85,7 @@ nouveau_fbcon_sync(struct fb_info *info)
        }
 
        if (ret) {
-               NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
-               info->flags |= FBINFO_HWACCEL_DISABLED;
+               nouveau_fbcon_gpu_lockup(info);
                return 0;
        }
 
@@ -212,11 +210,11 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
 
        mode_cmd.bpp = surface_bpp;
        mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
-       mode_cmd.pitch = ALIGN(mode_cmd.pitch, 256);
+       mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
        mode_cmd.depth = surface_depth;
 
        size = mode_cmd.pitch * mode_cmd.height;
-       size = ALIGN(size, PAGE_SIZE);
+       size = roundup(size, PAGE_SIZE);
 
        ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM,
                              0, 0x0000, false, true, &nvbo);
@@ -380,3 +378,12 @@ nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb)
 
        return 0;
 }
+
+void nouveau_fbcon_gpu_lockup(struct fb_info *info)
+{
+       struct nouveau_fbcon_par *par = info->par;
+       struct drm_device *dev = par->dev;
+
+       NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
+       info->flags |= FBINFO_HWACCEL_DISABLED;
+}
index 8531140fedbc7ae2c15a5f4308e19fa680a91c25..462e0b87b4bdb55d371ad8a37069fcdbe871d91d 100644 (file)
@@ -43,5 +43,6 @@ void nouveau_fbcon_zfill(struct drm_device *dev);
 int nv04_fbcon_accel_init(struct fb_info *info);
 int nv50_fbcon_accel_init(struct fb_info *info);
 
+void nouveau_fbcon_gpu_lockup(struct fb_info *info);
 #endif /* __NV50_FBCON_H__ */
 
index dacac9a0842a01c91b25ff091d14ae18b6ef258c..faddf53ff9ed79f0804735c151a28c3fb2d9a7ec 100644 (file)
@@ -142,7 +142,7 @@ nouveau_fence_emit(struct nouveau_fence *fence)
        list_add_tail(&fence->entry, &chan->fence.pending);
        spin_unlock_irqrestore(&chan->fence.lock, flags);
 
-       BEGIN_RING(chan, NvSubM2MF, USE_REFCNT ? 0x0050 : 0x0150, 1);
+       BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1);
        OUT_RING(chan, fence->sequence);
        FIRE_RING(chan);
 
index 18fd8ac9fca7cd4c8341eac4210f6530238b5209..2009db2426c3a87fa21be873a22001eed25e8c35 100644 (file)
@@ -220,7 +220,6 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,
 }
 
 struct validate_op {
-       struct nouveau_fence *fence;
        struct list_head vram_list;
        struct list_head gart_list;
        struct list_head both_list;
@@ -252,17 +251,11 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
 }
 
 static void
-validate_fini(struct validate_op *op, bool success)
+validate_fini(struct validate_op *op, struct nouveau_fence* fence)
 {
-       struct nouveau_fence *fence = op->fence;
-
-       if (unlikely(!success))
-               op->fence = NULL;
-
-       validate_fini_list(&op->vram_list, op->fence);
-       validate_fini_list(&op->gart_list, op->fence);
-       validate_fini_list(&op->both_list, op->fence);
-       nouveau_fence_unref((void *)&fence);
+       validate_fini_list(&op->vram_list, fence);
+       validate_fini_list(&op->gart_list, fence);
+       validate_fini_list(&op->both_list, fence);
 }
 
 static int
@@ -420,10 +413,6 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
        INIT_LIST_HEAD(&op->gart_list);
        INIT_LIST_HEAD(&op->both_list);
 
-       ret = nouveau_fence_new(chan, &op->fence, false);
-       if (ret)
-               return ret;
-
        if (nr_buffers == 0)
                return 0;
 
@@ -541,6 +530,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
        struct drm_nouveau_gem_pushbuf_bo *bo = NULL;
        struct nouveau_channel *chan;
        struct validate_op op;
+       struct nouveau_fence* fence = 0;
        uint32_t *pushbuf = NULL;
        int ret = 0, do_reloc = 0, i;
 
@@ -597,7 +587,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
 
        OUT_RINGp(chan, pushbuf, req->nr_dwords);
 
-       ret = nouveau_fence_emit(op.fence);
+       ret = nouveau_fence_new(chan, &fence, true);
        if (ret) {
                NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
                WIND_RING(chan);
@@ -605,7 +595,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
        }
 
        if (nouveau_gem_pushbuf_sync(chan)) {
-               ret = nouveau_fence_wait(op.fence, NULL, false, false);
+               ret = nouveau_fence_wait(fence, NULL, false, false);
                if (ret) {
                        for (i = 0; i < req->nr_dwords; i++)
                                NV_ERROR(dev, "0x%08x\n", pushbuf[i]);
@@ -614,7 +604,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
        }
 
 out:
-       validate_fini(&op, ret == 0);
+       validate_fini(&op, fence);
+       nouveau_fence_unref((void**)&fence);
        mutex_unlock(&dev->struct_mutex);
        kfree(pushbuf);
        kfree(bo);
@@ -634,6 +625,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
        struct drm_gem_object *gem;
        struct nouveau_bo *pbbo;
        struct validate_op op;
+       struct nouveau_fence* fence = 0;
        int i, ret = 0, do_reloc = 0;
 
        NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
@@ -772,7 +764,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
                        OUT_RING(chan, 0);
        }
 
-       ret = nouveau_fence_emit(op.fence);
+       ret = nouveau_fence_new(chan, &fence, true);
        if (ret) {
                NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
                WIND_RING(chan);
@@ -780,7 +772,8 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
        }
 
 out:
-       validate_fini(&op, ret == 0);
+       validate_fini(&op, fence);
+       nouveau_fence_unref((void**)&fence);
        mutex_unlock(&dev->struct_mutex);
        kfree(bo);
 
index 370c72c968d186ce779306ae20552ef4a6cab715..919a619ca7fa376c70f0a935df029935203e924d 100644 (file)
@@ -635,6 +635,7 @@ nv50_pgraph_irq_handler(struct drm_device *dev)
 
                if ((nv_rd32(dev, 0x400500) & isb) != isb)
                        nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | isb);
+               nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
        }
 
        nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
index 5158a12f7844782acd164797be5f170d45072c2d..fb9bdd6edf1f66a417cd0d209c6b9ab5667c0fec 100644 (file)
@@ -191,6 +191,92 @@ void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap)
        }
 }
 
+/*
+ * NV10-NV40 tiling helpers
+ */
+
+static void
+nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+                          uint32_t size, uint32_t pitch)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+       struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+       struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
+
+       tile->addr = addr;
+       tile->size = size;
+       tile->used = !!pitch;
+       nouveau_fence_unref((void **)&tile->fence);
+
+       if (!pfifo->cache_flush(dev))
+               return;
+
+       pfifo->reassign(dev, false);
+       pfifo->cache_flush(dev);
+       pfifo->cache_pull(dev, false);
+
+       nouveau_wait_for_idle(dev);
+
+       pgraph->set_region_tiling(dev, i, addr, size, pitch);
+       pfb->set_region_tiling(dev, i, addr, size, pitch);
+
+       pfifo->cache_pull(dev, true);
+       pfifo->reassign(dev, true);
+}
+
+struct nouveau_tile_reg *
+nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
+                   uint32_t pitch)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+       struct nouveau_tile_reg *tile = dev_priv->tile.reg, *found = NULL;
+       int i;
+
+       spin_lock(&dev_priv->tile.lock);
+
+       for (i = 0; i < pfb->num_tiles; i++) {
+               if (tile[i].used)
+                       /* Tile region in use. */
+                       continue;
+
+               if (tile[i].fence &&
+                   !nouveau_fence_signalled(tile[i].fence, NULL))
+                       /* Pending tile region. */
+                       continue;
+
+               if (max(tile[i].addr, addr) <
+                   min(tile[i].addr + tile[i].size, addr + size))
+                       /* Kill an intersecting tile region. */
+                       nv10_mem_set_region_tiling(dev, i, 0, 0, 0);
+
+               if (pitch && !found) {
+                       /* Free tile region. */
+                       nv10_mem_set_region_tiling(dev, i, addr, size, pitch);
+                       found = &tile[i];
+               }
+       }
+
+       spin_unlock(&dev_priv->tile.lock);
+
+       return found;
+}
+
+void
+nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile,
+                      struct nouveau_fence *fence)
+{
+       if (fence) {
+               /* Mark it as pending. */
+               tile->fence = fence;
+               nouveau_fence_ref(fence);
+       }
+
+       tile->used = false;
+}
+
 /*
  * NV50 VM helpers
  */
@@ -513,6 +599,7 @@ nouveau_mem_init(struct drm_device *dev)
 
        INIT_LIST_HEAD(&dev_priv->ttm.bo_list);
        spin_lock_init(&dev_priv->ttm.bo_list_lock);
+       spin_lock_init(&dev_priv->tile.lock);
 
        dev_priv->fb_available_size = nouveau_mem_fb_amount(dev);
 
index 93379bb81beae845a0a91a769537cd90b790d87c..6c2cf81716dfc4e4f02aea8fccb4f96d62c176ed 100644 (file)
@@ -881,7 +881,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
        return 0;
 }
 
-static int
+int
 nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
                      struct nouveau_gpuobj **gpuobj_ret)
 {
index fa1b0e7165b9956ea3581c378ba61f13c75afb36..251f1b3b38b927e73a0cef903c913109224d8172 100644 (file)
 #define NV04_PGRAPH_BLEND                                  0x00400824
 #define NV04_PGRAPH_STORED_FMT                             0x00400830
 #define NV04_PGRAPH_PATT_COLORRAM                          0x00400900
-#define NV40_PGRAPH_TILE0(i)                               (0x00400900 + (i*16))
-#define NV40_PGRAPH_TLIMIT0(i)                             (0x00400904 + (i*16))
-#define NV40_PGRAPH_TSIZE0(i)                              (0x00400908 + (i*16))
-#define NV40_PGRAPH_TSTATUS0(i)                            (0x0040090C + (i*16))
+#define NV20_PGRAPH_TILE(i)                                (0x00400900 + (i*16))
+#define NV20_PGRAPH_TLIMIT(i)                              (0x00400904 + (i*16))
+#define NV20_PGRAPH_TSIZE(i)                               (0x00400908 + (i*16))
+#define NV20_PGRAPH_TSTATUS(i)                             (0x0040090C + (i*16))
 #define NV10_PGRAPH_TILE(i)                                (0x00400B00 + (i*16))
 #define NV10_PGRAPH_TLIMIT(i)                              (0x00400B04 + (i*16))
 #define NV10_PGRAPH_TSIZE(i)                               (0x00400B08 + (i*16))
 #define NV10_PGRAPH_TSTATUS(i)                             (0x00400B0C + (i*16))
 #define NV04_PGRAPH_U_RAM                                  0x00400D00
-#define NV47_PGRAPH_TILE0(i)                               (0x00400D00 + (i*16))
-#define NV47_PGRAPH_TLIMIT0(i)                             (0x00400D04 + (i*16))
-#define NV47_PGRAPH_TSIZE0(i)                              (0x00400D08 + (i*16))
-#define NV47_PGRAPH_TSTATUS0(i)                            (0x00400D0C + (i*16))
+#define NV47_PGRAPH_TILE(i)                                (0x00400D00 + (i*16))
+#define NV47_PGRAPH_TLIMIT(i)                              (0x00400D04 + (i*16))
+#define NV47_PGRAPH_TSIZE(i)                               (0x00400D08 + (i*16))
+#define NV47_PGRAPH_TSTATUS(i)                             (0x00400D0C + (i*16))
 #define NV04_PGRAPH_V_RAM                                  0x00400D40
 #define NV04_PGRAPH_W_RAM                                  0x00400D80
 #define NV10_PGRAPH_COMBINER0_IN_ALPHA                     0x00400E40
index e76ec2d207a97f9f7d90c1847bfbfffdc0c7c958..09b9a46dfc0ec0337f1ecf60b04585b8fddddff4 100644 (file)
@@ -76,6 +76,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fifo.disable            = nv04_fifo_disable;
                engine->fifo.enable             = nv04_fifo_enable;
                engine->fifo.reassign           = nv04_fifo_reassign;
+               engine->fifo.cache_flush        = nv04_fifo_cache_flush;
+               engine->fifo.cache_pull         = nv04_fifo_cache_pull;
                engine->fifo.channel_id         = nv04_fifo_channel_id;
                engine->fifo.create_context     = nv04_fifo_create_context;
                engine->fifo.destroy_context    = nv04_fifo_destroy_context;
@@ -100,6 +102,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->timer.takedown          = nv04_timer_takedown;
                engine->fb.init                 = nv10_fb_init;
                engine->fb.takedown             = nv10_fb_takedown;
+               engine->fb.set_region_tiling    = nv10_fb_set_region_tiling;
                engine->graph.grclass           = nv10_graph_grclass;
                engine->graph.init              = nv10_graph_init;
                engine->graph.takedown          = nv10_graph_takedown;
@@ -109,12 +112,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->graph.fifo_access       = nv04_graph_fifo_access;
                engine->graph.load_context      = nv10_graph_load_context;
                engine->graph.unload_context    = nv10_graph_unload_context;
+               engine->graph.set_region_tiling = nv10_graph_set_region_tiling;
                engine->fifo.channels           = 32;
                engine->fifo.init               = nv10_fifo_init;
                engine->fifo.takedown           = nouveau_stub_takedown;
                engine->fifo.disable            = nv04_fifo_disable;
                engine->fifo.enable             = nv04_fifo_enable;
                engine->fifo.reassign           = nv04_fifo_reassign;
+               engine->fifo.cache_flush        = nv04_fifo_cache_flush;
+               engine->fifo.cache_pull         = nv04_fifo_cache_pull;
                engine->fifo.channel_id         = nv10_fifo_channel_id;
                engine->fifo.create_context     = nv10_fifo_create_context;
                engine->fifo.destroy_context    = nv10_fifo_destroy_context;
@@ -139,6 +145,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->timer.takedown          = nv04_timer_takedown;
                engine->fb.init                 = nv10_fb_init;
                engine->fb.takedown             = nv10_fb_takedown;
+               engine->fb.set_region_tiling    = nv10_fb_set_region_tiling;
                engine->graph.grclass           = nv20_graph_grclass;
                engine->graph.init              = nv20_graph_init;
                engine->graph.takedown          = nv20_graph_takedown;
@@ -148,12 +155,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->graph.fifo_access       = nv04_graph_fifo_access;
                engine->graph.load_context      = nv20_graph_load_context;
                engine->graph.unload_context    = nv20_graph_unload_context;
+               engine->graph.set_region_tiling = nv20_graph_set_region_tiling;
                engine->fifo.channels           = 32;
                engine->fifo.init               = nv10_fifo_init;
                engine->fifo.takedown           = nouveau_stub_takedown;
                engine->fifo.disable            = nv04_fifo_disable;
                engine->fifo.enable             = nv04_fifo_enable;
                engine->fifo.reassign           = nv04_fifo_reassign;
+               engine->fifo.cache_flush        = nv04_fifo_cache_flush;
+               engine->fifo.cache_pull         = nv04_fifo_cache_pull;
                engine->fifo.channel_id         = nv10_fifo_channel_id;
                engine->fifo.create_context     = nv10_fifo_create_context;
                engine->fifo.destroy_context    = nv10_fifo_destroy_context;
@@ -178,6 +188,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->timer.takedown          = nv04_timer_takedown;
                engine->fb.init                 = nv10_fb_init;
                engine->fb.takedown             = nv10_fb_takedown;
+               engine->fb.set_region_tiling    = nv10_fb_set_region_tiling;
                engine->graph.grclass           = nv30_graph_grclass;
                engine->graph.init              = nv30_graph_init;
                engine->graph.takedown          = nv20_graph_takedown;
@@ -187,12 +198,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->graph.destroy_context   = nv20_graph_destroy_context;
                engine->graph.load_context      = nv20_graph_load_context;
                engine->graph.unload_context    = nv20_graph_unload_context;
+               engine->graph.set_region_tiling = nv20_graph_set_region_tiling;
                engine->fifo.channels           = 32;
                engine->fifo.init               = nv10_fifo_init;
                engine->fifo.takedown           = nouveau_stub_takedown;
                engine->fifo.disable            = nv04_fifo_disable;
                engine->fifo.enable             = nv04_fifo_enable;
                engine->fifo.reassign           = nv04_fifo_reassign;
+               engine->fifo.cache_flush        = nv04_fifo_cache_flush;
+               engine->fifo.cache_pull         = nv04_fifo_cache_pull;
                engine->fifo.channel_id         = nv10_fifo_channel_id;
                engine->fifo.create_context     = nv10_fifo_create_context;
                engine->fifo.destroy_context    = nv10_fifo_destroy_context;
@@ -218,6 +232,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->timer.takedown          = nv04_timer_takedown;
                engine->fb.init                 = nv40_fb_init;
                engine->fb.takedown             = nv40_fb_takedown;
+               engine->fb.set_region_tiling    = nv40_fb_set_region_tiling;
                engine->graph.grclass           = nv40_graph_grclass;
                engine->graph.init              = nv40_graph_init;
                engine->graph.takedown          = nv40_graph_takedown;
@@ -227,12 +242,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->graph.destroy_context   = nv40_graph_destroy_context;
                engine->graph.load_context      = nv40_graph_load_context;
                engine->graph.unload_context    = nv40_graph_unload_context;
+               engine->graph.set_region_tiling = nv40_graph_set_region_tiling;
                engine->fifo.channels           = 32;
                engine->fifo.init               = nv40_fifo_init;
                engine->fifo.takedown           = nouveau_stub_takedown;
                engine->fifo.disable            = nv04_fifo_disable;
                engine->fifo.enable             = nv04_fifo_enable;
                engine->fifo.reassign           = nv04_fifo_reassign;
+               engine->fifo.cache_flush        = nv04_fifo_cache_flush;
+               engine->fifo.cache_pull         = nv04_fifo_cache_pull;
                engine->fifo.channel_id         = nv10_fifo_channel_id;
                engine->fifo.create_context     = nv40_fifo_create_context;
                engine->fifo.destroy_context    = nv40_fifo_destroy_context;
@@ -624,7 +642,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
                dev_priv->chipset = (reg0 & 0xff00000) >> 20;
        /* NV04 or NV05 */
        } else if ((reg0 & 0xff00fff0) == 0x20004000) {
-               dev_priv->chipset = 0x04;
+               if (reg0 & 0x00f00000)
+                       dev_priv->chipset = 0x05;
+               else
+                       dev_priv->chipset = 0x04;
        } else
                dev_priv->chipset = 0xff;
 
@@ -704,8 +725,8 @@ static void nouveau_close(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-       /* In the case of an error dev_priv may not be be allocated yet */
-       if (dev_priv && dev_priv->card_type)
+       /* In the case of an error dev_priv may not be allocated yet */
+       if (dev_priv)
                nouveau_card_takedown(dev);
 }
 
index 187eb84e4da5269527911556dd0a48335d2b9eae..c385d50f041b0f6ecf6e08cb6c58effba677c942 100644 (file)
 
 #include "nouveau_drv.h"
 
-static struct vm_operations_struct nouveau_ttm_vm_ops;
-static const struct vm_operations_struct *ttm_vm_ops;
-
-static int
-nouveau_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       struct ttm_buffer_object *bo = vma->vm_private_data;
-       int ret;
-
-       if (unlikely(bo == NULL))
-               return VM_FAULT_NOPAGE;
-
-       ret = ttm_vm_ops->fault(vma, vmf);
-       return ret;
-}
-
 int
 nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        struct drm_file *file_priv = filp->private_data;
        struct drm_nouveau_private *dev_priv =
                file_priv->minor->dev->dev_private;
-       int ret;
 
        if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
                return drm_mmap(filp, vma);
 
-       ret = ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev);
-       if (unlikely(ret != 0))
-               return ret;
-
-       if (unlikely(ttm_vm_ops == NULL)) {
-               ttm_vm_ops = vma->vm_ops;
-               nouveau_ttm_vm_ops = *ttm_vm_ops;
-               nouveau_ttm_vm_ops.fault = &nouveau_ttm_fault;
-       }
-
-       vma->vm_ops = &nouveau_ttm_vm_ops;
-       return 0;
+       return ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev);
 }
 
 static int
index d9f32879ba384aa491191a187981f2f62ffe2c51..d0e038d289484d4b0bb01bfaefb081e74abb1e33 100644 (file)
@@ -212,16 +212,15 @@ out:
        return connector_status_disconnected;
 }
 
-enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder,
-                                         struct drm_connector *connector)
+uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
 {
        struct drm_device *dev = encoder->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
-       uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
+       uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
        uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
                saved_rtest_ctrl, saved_gpio0, saved_gpio1, temp, routput;
-       int head, present = 0;
+       int head;
 
 #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
        if (dcb->type == OUTPUT_TV) {
@@ -287,13 +286,7 @@ enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder,
                      temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED);
        msleep(5);
 
-       temp = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
-
-       if (dcb->type == OUTPUT_TV)
-               present = (nv17_tv_detect(encoder, connector, temp)
-                          == connector_status_connected);
-       else
-               present = temp & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI;
+       sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
 
        temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL);
        NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL,
@@ -310,15 +303,25 @@ enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder,
        nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
        nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0);
 
-       if (present) {
-               NV_INFO(dev, "Load detected on output %c\n", '@' + ffs(dcb->or));
+       return sample;
+}
+
+static enum drm_connector_status
+nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
+       uint32_t sample = nv17_dac_sample_load(encoder);
+
+       if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
+               NV_INFO(dev, "Load detected on output %c\n",
+                       '@' + ffs(dcb->or));
                return connector_status_connected;
+       } else {
+               return connector_status_disconnected;
        }
-
-       return connector_status_disconnected;
 }
 
-
 static bool nv04_dac_mode_fixup(struct drm_encoder *encoder,
                                struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode)
index 09a31071ee587e585eb6b2eb192ec7f12d9043c9..d910873c13682986ac5280349ee971c6ea3353cc 100644 (file)
@@ -39,8 +39,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
                return;
 
        if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) {
-               NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
-               info->flags |= FBINFO_HWACCEL_DISABLED;
+               nouveau_fbcon_gpu_lockup(info);
        }
 
        if (info->flags & FBINFO_HWACCEL_DISABLED) {
@@ -62,14 +61,12 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
        struct drm_device *dev = par->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_channel *chan = dev_priv->channel;
-       uint32_t color = ((uint32_t *) info->pseudo_palette)[rect->color];
 
        if (info->state != FBINFO_STATE_RUNNING)
                return;
 
        if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) {
-               NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
-               info->flags |= FBINFO_HWACCEL_DISABLED;
+               nouveau_fbcon_gpu_lockup(info);
        }
 
        if (info->flags & FBINFO_HWACCEL_DISABLED) {
@@ -80,7 +77,11 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
        BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1);
        OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3);
        BEGIN_RING(chan, NvSubGdiRect, 0x03fc, 1);
-       OUT_RING(chan, color);
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+           info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+               OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]);
+       else
+               OUT_RING(chan, rect->color);
        BEGIN_RING(chan, NvSubGdiRect, 0x0400, 2);
        OUT_RING(chan, (rect->dx << 16) | rect->dy);
        OUT_RING(chan, (rect->width << 16) | rect->height);
@@ -109,8 +110,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        }
 
        if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) {
-               NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
-               info->flags |= FBINFO_HWACCEL_DISABLED;
+               nouveau_fbcon_gpu_lockup(info);
        }
 
        if (info->flags & FBINFO_HWACCEL_DISABLED) {
@@ -144,8 +144,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
                int iter_len = dsize > 128 ? 128 : dsize;
 
                if (RING_SPACE(chan, iter_len + 1)) {
-                       NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
-                       info->flags |= FBINFO_HWACCEL_DISABLED;
+                       nouveau_fbcon_gpu_lockup(info);
                        cfb_imageblit(info, image);
                        return;
                }
@@ -184,6 +183,7 @@ nv04_fbcon_accel_init(struct fb_info *info)
        struct drm_device *dev = par->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_channel *chan = dev_priv->channel;
+       const int sub = NvSubCtxSurf2D;
        int surface_fmt, pattern_fmt, rect_fmt;
        int ret;
 
@@ -242,30 +242,29 @@ nv04_fbcon_accel_init(struct fb_info *info)
                return ret;
 
        if (RING_SPACE(chan, 49)) {
-               NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
-               info->flags |= FBINFO_HWACCEL_DISABLED;
+               nouveau_fbcon_gpu_lockup(info);
                return 0;
        }
 
-       BEGIN_RING(chan, 1, 0x0000, 1);
+       BEGIN_RING(chan, sub, 0x0000, 1);
        OUT_RING(chan, NvCtxSurf2D);
-       BEGIN_RING(chan, 1, 0x0184, 2);
+       BEGIN_RING(chan, sub, 0x0184, 2);
        OUT_RING(chan, NvDmaFB);
        OUT_RING(chan, NvDmaFB);
-       BEGIN_RING(chan, 1, 0x0300, 4);
+       BEGIN_RING(chan, sub, 0x0300, 4);
        OUT_RING(chan, surface_fmt);
        OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16));
        OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
        OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
 
-       BEGIN_RING(chan, 1, 0x0000, 1);
+       BEGIN_RING(chan, sub, 0x0000, 1);
        OUT_RING(chan, NvRop);
-       BEGIN_RING(chan, 1, 0x0300, 1);
+       BEGIN_RING(chan, sub, 0x0300, 1);
        OUT_RING(chan, 0x55);
 
-       BEGIN_RING(chan, 1, 0x0000, 1);
+       BEGIN_RING(chan, sub, 0x0000, 1);
        OUT_RING(chan, NvImagePatt);
-       BEGIN_RING(chan, 1, 0x0300, 8);
+       BEGIN_RING(chan, sub, 0x0300, 8);
        OUT_RING(chan, pattern_fmt);
 #ifdef __BIG_ENDIAN
        OUT_RING(chan, 2);
@@ -279,9 +278,9 @@ nv04_fbcon_accel_init(struct fb_info *info)
        OUT_RING(chan, ~0);
        OUT_RING(chan, ~0);
 
-       BEGIN_RING(chan, 1, 0x0000, 1);
+       BEGIN_RING(chan, sub, 0x0000, 1);
        OUT_RING(chan, NvClipRect);
-       BEGIN_RING(chan, 1, 0x0300, 2);
+       BEGIN_RING(chan, sub, 0x0300, 2);
        OUT_RING(chan, 0);
        OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual);
 
index 0c3cd53c73138142bf34e5f78b9ddfddf90bca7c..f31347b8c9b05da1977fcd00b5108c725434f689 100644 (file)
@@ -71,6 +71,40 @@ nv04_fifo_reassign(struct drm_device *dev, bool enable)
        return (reassign == 1);
 }
 
+bool
+nv04_fifo_cache_flush(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+       uint64_t start = ptimer->read(dev);
+
+       do {
+               if (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) ==
+                   nv_rd32(dev, NV03_PFIFO_CACHE1_PUT))
+                       return true;
+
+       } while (ptimer->read(dev) - start < 100000000);
+
+       NV_ERROR(dev, "Timeout flushing the PFIFO cache.\n");
+
+       return false;
+}
+
+bool
+nv04_fifo_cache_pull(struct drm_device *dev, bool enable)
+{
+       uint32_t pull = nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0);
+
+       if (enable) {
+               nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull | 1);
+       } else {
+               nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull & ~1);
+               nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
+       }
+
+       return !!(pull & 1);
+}
+
 int
 nv04_fifo_channel_id(struct drm_device *dev)
 {
index d561d773c0f4e2d41a4a7473ac34b5a8408f0e40..e260986ea65af09281dc72dea034f1e975490b40 100644 (file)
 #include "nouveau_drv.h"
 
 static uint32_t nv04_graph_ctx_regs[] = {
+       0x0040053c,
+       0x00400544,
+       0x00400540,
+       0x00400548,
        NV04_PGRAPH_CTX_SWITCH1,
        NV04_PGRAPH_CTX_SWITCH2,
        NV04_PGRAPH_CTX_SWITCH3,
@@ -102,69 +106,69 @@ static uint32_t nv04_graph_ctx_regs[] = {
        NV04_PGRAPH_PATT_COLOR0,
        NV04_PGRAPH_PATT_COLOR1,
        NV04_PGRAPH_PATT_COLORRAM+0x00,
-       NV04_PGRAPH_PATT_COLORRAM+0x01,
-       NV04_PGRAPH_PATT_COLORRAM+0x02,
-       NV04_PGRAPH_PATT_COLORRAM+0x03,
        NV04_PGRAPH_PATT_COLORRAM+0x04,
-       NV04_PGRAPH_PATT_COLORRAM+0x05,
-       NV04_PGRAPH_PATT_COLORRAM+0x06,
-       NV04_PGRAPH_PATT_COLORRAM+0x07,
        NV04_PGRAPH_PATT_COLORRAM+0x08,
-       NV04_PGRAPH_PATT_COLORRAM+0x09,
-       NV04_PGRAPH_PATT_COLORRAM+0x0A,
-       NV04_PGRAPH_PATT_COLORRAM+0x0B,
-       NV04_PGRAPH_PATT_COLORRAM+0x0C,
-       NV04_PGRAPH_PATT_COLORRAM+0x0D,
-       NV04_PGRAPH_PATT_COLORRAM+0x0E,
-       NV04_PGRAPH_PATT_COLORRAM+0x0F,
+       NV04_PGRAPH_PATT_COLORRAM+0x0c,
        NV04_PGRAPH_PATT_COLORRAM+0x10,
-       NV04_PGRAPH_PATT_COLORRAM+0x11,
-       NV04_PGRAPH_PATT_COLORRAM+0x12,
-       NV04_PGRAPH_PATT_COLORRAM+0x13,
        NV04_PGRAPH_PATT_COLORRAM+0x14,
-       NV04_PGRAPH_PATT_COLORRAM+0x15,
-       NV04_PGRAPH_PATT_COLORRAM+0x16,
-       NV04_PGRAPH_PATT_COLORRAM+0x17,
        NV04_PGRAPH_PATT_COLORRAM+0x18,
-       NV04_PGRAPH_PATT_COLORRAM+0x19,
-       NV04_PGRAPH_PATT_COLORRAM+0x1A,
-       NV04_PGRAPH_PATT_COLORRAM+0x1B,
-       NV04_PGRAPH_PATT_COLORRAM+0x1C,
-       NV04_PGRAPH_PATT_COLORRAM+0x1D,
-       NV04_PGRAPH_PATT_COLORRAM+0x1E,
-       NV04_PGRAPH_PATT_COLORRAM+0x1F,
+       NV04_PGRAPH_PATT_COLORRAM+0x1c,
        NV04_PGRAPH_PATT_COLORRAM+0x20,
-       NV04_PGRAPH_PATT_COLORRAM+0x21,
-       NV04_PGRAPH_PATT_COLORRAM+0x22,
-       NV04_PGRAPH_PATT_COLORRAM+0x23,
        NV04_PGRAPH_PATT_COLORRAM+0x24,
-       NV04_PGRAPH_PATT_COLORRAM+0x25,
-       NV04_PGRAPH_PATT_COLORRAM+0x26,
-       NV04_PGRAPH_PATT_COLORRAM+0x27,
        NV04_PGRAPH_PATT_COLORRAM+0x28,
-       NV04_PGRAPH_PATT_COLORRAM+0x29,
-       NV04_PGRAPH_PATT_COLORRAM+0x2A,
-       NV04_PGRAPH_PATT_COLORRAM+0x2B,
-       NV04_PGRAPH_PATT_COLORRAM+0x2C,
-       NV04_PGRAPH_PATT_COLORRAM+0x2D,
-       NV04_PGRAPH_PATT_COLORRAM+0x2E,
-       NV04_PGRAPH_PATT_COLORRAM+0x2F,
+       NV04_PGRAPH_PATT_COLORRAM+0x2c,
        NV04_PGRAPH_PATT_COLORRAM+0x30,
-       NV04_PGRAPH_PATT_COLORRAM+0x31,
-       NV04_PGRAPH_PATT_COLORRAM+0x32,
-       NV04_PGRAPH_PATT_COLORRAM+0x33,
        NV04_PGRAPH_PATT_COLORRAM+0x34,
-       NV04_PGRAPH_PATT_COLORRAM+0x35,
-       NV04_PGRAPH_PATT_COLORRAM+0x36,
-       NV04_PGRAPH_PATT_COLORRAM+0x37,
        NV04_PGRAPH_PATT_COLORRAM+0x38,
-       NV04_PGRAPH_PATT_COLORRAM+0x39,
-       NV04_PGRAPH_PATT_COLORRAM+0x3A,
-       NV04_PGRAPH_PATT_COLORRAM+0x3B,
-       NV04_PGRAPH_PATT_COLORRAM+0x3C,
-       NV04_PGRAPH_PATT_COLORRAM+0x3D,
-       NV04_PGRAPH_PATT_COLORRAM+0x3E,
-       NV04_PGRAPH_PATT_COLORRAM+0x3F,
+       NV04_PGRAPH_PATT_COLORRAM+0x3c,
+       NV04_PGRAPH_PATT_COLORRAM+0x40,
+       NV04_PGRAPH_PATT_COLORRAM+0x44,
+       NV04_PGRAPH_PATT_COLORRAM+0x48,
+       NV04_PGRAPH_PATT_COLORRAM+0x4c,
+       NV04_PGRAPH_PATT_COLORRAM+0x50,
+       NV04_PGRAPH_PATT_COLORRAM+0x54,
+       NV04_PGRAPH_PATT_COLORRAM+0x58,
+       NV04_PGRAPH_PATT_COLORRAM+0x5c,
+       NV04_PGRAPH_PATT_COLORRAM+0x60,
+       NV04_PGRAPH_PATT_COLORRAM+0x64,
+       NV04_PGRAPH_PATT_COLORRAM+0x68,
+       NV04_PGRAPH_PATT_COLORRAM+0x6c,
+       NV04_PGRAPH_PATT_COLORRAM+0x70,
+       NV04_PGRAPH_PATT_COLORRAM+0x74,
+       NV04_PGRAPH_PATT_COLORRAM+0x78,
+       NV04_PGRAPH_PATT_COLORRAM+0x7c,
+       NV04_PGRAPH_PATT_COLORRAM+0x80,
+       NV04_PGRAPH_PATT_COLORRAM+0x84,
+       NV04_PGRAPH_PATT_COLORRAM+0x88,
+       NV04_PGRAPH_PATT_COLORRAM+0x8c,
+       NV04_PGRAPH_PATT_COLORRAM+0x90,
+       NV04_PGRAPH_PATT_COLORRAM+0x94,
+       NV04_PGRAPH_PATT_COLORRAM+0x98,
+       NV04_PGRAPH_PATT_COLORRAM+0x9c,
+       NV04_PGRAPH_PATT_COLORRAM+0xa0,
+       NV04_PGRAPH_PATT_COLORRAM+0xa4,
+       NV04_PGRAPH_PATT_COLORRAM+0xa8,
+       NV04_PGRAPH_PATT_COLORRAM+0xac,
+       NV04_PGRAPH_PATT_COLORRAM+0xb0,
+       NV04_PGRAPH_PATT_COLORRAM+0xb4,
+       NV04_PGRAPH_PATT_COLORRAM+0xb8,
+       NV04_PGRAPH_PATT_COLORRAM+0xbc,
+       NV04_PGRAPH_PATT_COLORRAM+0xc0,
+       NV04_PGRAPH_PATT_COLORRAM+0xc4,
+       NV04_PGRAPH_PATT_COLORRAM+0xc8,
+       NV04_PGRAPH_PATT_COLORRAM+0xcc,
+       NV04_PGRAPH_PATT_COLORRAM+0xd0,
+       NV04_PGRAPH_PATT_COLORRAM+0xd4,
+       NV04_PGRAPH_PATT_COLORRAM+0xd8,
+       NV04_PGRAPH_PATT_COLORRAM+0xdc,
+       NV04_PGRAPH_PATT_COLORRAM+0xe0,
+       NV04_PGRAPH_PATT_COLORRAM+0xe4,
+       NV04_PGRAPH_PATT_COLORRAM+0xe8,
+       NV04_PGRAPH_PATT_COLORRAM+0xec,
+       NV04_PGRAPH_PATT_COLORRAM+0xf0,
+       NV04_PGRAPH_PATT_COLORRAM+0xf4,
+       NV04_PGRAPH_PATT_COLORRAM+0xf8,
+       NV04_PGRAPH_PATT_COLORRAM+0xfc,
        NV04_PGRAPH_PATTERN,
        0x0040080c,
        NV04_PGRAPH_PATTERN_SHAPE,
@@ -247,14 +251,6 @@ static uint32_t nv04_graph_ctx_regs[] = {
        0x004004f8,
        0x0040047c,
        0x004004fc,
-       0x0040053c,
-       0x00400544,
-       0x00400540,
-       0x00400548,
-       0x00400560,
-       0x00400568,
-       0x00400564,
-       0x0040056c,
        0x00400534,
        0x00400538,
        0x00400514,
@@ -341,9 +337,8 @@ static uint32_t nv04_graph_ctx_regs[] = {
        0x00400500,
        0x00400504,
        NV04_PGRAPH_VALID1,
-       NV04_PGRAPH_VALID2
-
-
+       NV04_PGRAPH_VALID2,
+       NV04_PGRAPH_DEBUG_3
 };
 
 struct graph_state {
@@ -388,6 +383,18 @@ nv04_graph_context_switch(struct drm_device *dev)
        pgraph->fifo_access(dev, true);
 }
 
+static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) {
+               if (nv04_graph_ctx_regs[i] == reg)
+                       return &ctx->nv04[i];
+       }
+
+       return NULL;
+}
+
 int nv04_graph_create_context(struct nouveau_channel *chan)
 {
        struct graph_state *pgraph_ctx;
@@ -398,15 +405,8 @@ int nv04_graph_create_context(struct nouveau_channel *chan)
        if (pgraph_ctx == NULL)
                return -ENOMEM;
 
-       /* dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; */
-       pgraph_ctx->nv04[0] = 0x0001ffff;
-       /* is it really needed ??? */
-#if 0
-       dev_priv->fifos[channel].pgraph_ctx[1] =
-                                       nv_rd32(dev, NV_PGRAPH_DEBUG_4);
-       dev_priv->fifos[channel].pgraph_ctx[2] =
-                                       nv_rd32(dev, 0x004006b0);
-#endif
+       *ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31;
+
        return 0;
 }
 
@@ -429,9 +429,13 @@ int nv04_graph_load_context(struct nouveau_channel *chan)
                nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]);
 
        nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100);
-       nv_wr32(dev, NV04_PGRAPH_CTX_USER, chan->id << 24);
+
+       tmp  = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
+       nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp | chan->id << 24);
+
        tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2);
        nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff);
+
        return 0;
 }
 
@@ -494,7 +498,7 @@ int nv04_graph_init(struct drm_device *dev)
        nv_wr32(dev, NV04_PGRAPH_STATE        , 0xFFFFFFFF);
        nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL  , 0x10000100);
        tmp  = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
-       tmp |= dev_priv->engine.fifo.channels << 24;
+       tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
        nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp);
 
        /* These don't belong here, they're part of a per-channel context */
@@ -533,7 +537,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass,
                              int mthd, uint32_t data)
 {
        struct drm_device *dev = chan->dev;
-       uint32_t instance = nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff;
+       uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
        int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7;
        uint32_t tmp;
 
@@ -547,7 +551,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass,
        return 0;
 }
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_m2mf[] = {
+static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = {
        { 0x0150, nv04_graph_mthd_set_ref },
        {}
 };
@@ -558,7 +562,7 @@ static struct nouveau_pgraph_object_method nv04_graph_mthds_set_operation[] = {
 };
 
 struct nouveau_pgraph_object_class nv04_graph_grclass[] = {
-       { 0x0039, false, nv04_graph_mthds_m2mf },
+       { 0x0039, false, NULL },
        { 0x004a, false, nv04_graph_mthds_set_operation }, /* gdirect */
        { 0x005f, false, nv04_graph_mthds_set_operation }, /* imageblit */
        { 0x0061, false, nv04_graph_mthds_set_operation }, /* ifc */
@@ -574,6 +578,7 @@ struct nouveau_pgraph_object_class nv04_graph_grclass[] = {
        { 0x0053, false, NULL }, /* surf3d */
        { 0x0054, false, NULL }, /* tex_tri */
        { 0x0055, false, NULL }, /* multitex_tri */
+       { 0x506e, true, nv04_graph_mthds_sw },
        {}
 };
 
index 79e2d104d70a0176bffa23d46b25ff68749d8265..cc5cda44e5018bfd7bc0a777fd88f8a94e33794a 100644 (file)
@@ -3,17 +3,37 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 
+void
+nv10_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+                         uint32_t size, uint32_t pitch)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t limit = max(1u, addr + size) - 1;
+
+       if (pitch) {
+               if (dev_priv->card_type >= NV_20)
+                       addr |= 1;
+               else
+                       addr |= 1 << 31;
+       }
+
+       nv_wr32(dev, NV10_PFB_TLIMIT(i), limit);
+       nv_wr32(dev, NV10_PFB_TSIZE(i), pitch);
+       nv_wr32(dev, NV10_PFB_TILE(i), addr);
+}
+
 int
 nv10_fb_init(struct drm_device *dev)
 {
-       uint32_t fb_bar_size;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
        int i;
 
-       fb_bar_size = drm_get_resource_len(dev, 0) - 1;
-       for (i = 0; i < NV10_PFB_TILE__SIZE; i++) {
-               nv_wr32(dev, NV10_PFB_TILE(i), 0);
-               nv_wr32(dev, NV10_PFB_TLIMIT(i), fb_bar_size);
-       }
+       pfb->num_tiles = NV10_PFB_TILE__SIZE;
+
+       /* Turn all the tiling regions off. */
+       for (i = 0; i < pfb->num_tiles; i++)
+               pfb->set_region_tiling(dev, i, 0, 0, 0);
 
        return 0;
 }
index 6870e0ee2e7e315b85c12342f84f5c2732705fa8..fcf2cdd19493bf55dbff29699af17bb40708b70d 100644 (file)
@@ -807,6 +807,20 @@ void nv10_graph_destroy_context(struct nouveau_channel *chan)
        chan->pgraph_ctx = NULL;
 }
 
+void
+nv10_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+                            uint32_t size, uint32_t pitch)
+{
+       uint32_t limit = max(1u, addr + size) - 1;
+
+       if (pitch)
+               addr |= 1 << 31;
+
+       nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), limit);
+       nv_wr32(dev, NV10_PGRAPH_TSIZE(i), pitch);
+       nv_wr32(dev, NV10_PGRAPH_TILE(i), addr);
+}
+
 int nv10_graph_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -838,17 +852,9 @@ int nv10_graph_init(struct drm_device *dev)
        } else
                nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000);
 
-       /* copy tile info from PFB */
-       for (i = 0; i < NV10_PFB_TILE__SIZE; i++) {
-               nv_wr32(dev, NV10_PGRAPH_TILE(i),
-                                       nv_rd32(dev, NV10_PFB_TILE(i)));
-               nv_wr32(dev, NV10_PGRAPH_TLIMIT(i),
-                                       nv_rd32(dev, NV10_PFB_TLIMIT(i)));
-               nv_wr32(dev, NV10_PGRAPH_TSIZE(i),
-                                       nv_rd32(dev, NV10_PFB_TSIZE(i)));
-               nv_wr32(dev, NV10_PGRAPH_TSTATUS(i),
-                                       nv_rd32(dev, NV10_PFB_TSTATUS(i)));
-       }
+       /* Turn all the tiling regions off. */
+       for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
+               nv10_graph_set_region_tiling(dev, i, 0, 0, 0);
 
        nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000);
        nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000);
index 81c01353a9f9fee67e1d6da42f0108b8cc3044c5..58b917c3341b247af0fe569d92df1f79d193b568 100644 (file)
 #include "nouveau_hw.h"
 #include "nv17_tv.h"
 
-enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder,
-                                        struct drm_connector *connector,
-                                        uint32_t pin_mask)
+static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
 {
+       struct drm_device *dev = encoder->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
+       uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
+               fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
+       uint32_t sample = 0;
+       int head;
+
+#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
+       testval = RGB_TEST_DATA(0x82, 0xeb, 0x82);
+       if (dev_priv->vbios->tvdactestval)
+               testval = dev_priv->vbios->tvdactestval;
+
+       dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
+       head = (dacclk & 0x100) >> 8;
+
+       /* Save the previous state. */
+       gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
+       gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
+       fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL);
+       fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START);
+       fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END);
+       fp_control = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL);
+       test_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
+       ctv_1c = NVReadRAMDAC(dev, head, 0x680c1c);
+       ctv_14 = NVReadRAMDAC(dev, head, 0x680c14);
+       ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c);
+
+       /* Prepare the DAC for load detection.  */
+       nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true);
+       nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true);
+
+       NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343);
+       NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047);
+       NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, 1183);
+       NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL,
+                     NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |
+                     NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 |
+                     NV_PRAMDAC_FP_TG_CONTROL_READ_PROG |
+                     NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS |
+                     NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS);
+
+       NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, 0);
+
+       NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset,
+                     (dacclk & ~0xff) | 0x22);
+       msleep(1);
+       NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset,
+                     (dacclk & ~0xff) | 0x21);
+
+       NVWriteRAMDAC(dev, head, 0x680c1c, 1 << 20);
+       NVWriteRAMDAC(dev, head, 0x680c14, 4 << 16);
+
+       /* Sample pin 0x4 (usually S-video luma). */
+       NVWriteRAMDAC(dev, head, 0x680c6c, testval >> 10 & 0x3ff);
+       msleep(20);
+       sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset)
+               & 0x4 << 28;
+
+       /* Sample the remaining pins. */
+       NVWriteRAMDAC(dev, head, 0x680c6c, testval & 0x3ff);
+       msleep(20);
+       sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset)
+               & 0xa << 28;
+
+       /* Restore the previous state. */
+       NVWriteRAMDAC(dev, head, 0x680c1c, ctv_1c);
+       NVWriteRAMDAC(dev, head, 0x680c14, ctv_14);
+       NVWriteRAMDAC(dev, head, 0x680c6c, ctv_6c);
+       NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, dacclk);
+       NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, test_ctrl);
+       NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, fp_control);
+       NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end);
+       NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start);
+       NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal);
+       nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1);
+       nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0);
+
+       return sample;
+}
+
+static enum drm_connector_status
+nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct drm_mode_config *conf = &dev->mode_config;
        struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
+       struct dcb_entry *dcb = tv_enc->base.dcb;
 
-       tv_enc->pin_mask = pin_mask >> 28 & 0xe;
+       if (dev_priv->chipset == 0x42 ||
+           dev_priv->chipset == 0x43)
+               tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe;
+       else
+               tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe;
 
        switch (tv_enc->pin_mask) {
        case 0x2:
@@ -50,7 +140,7 @@ enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder,
                tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO;
                break;
        case 0xe:
-               if (nouveau_encoder(encoder)->dcb->tvconf.has_component_output)
+               if (dcb->tvconf.has_component_output)
                        tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Component;
                else
                        tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SCART;
@@ -61,11 +151,16 @@ enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder,
        }
 
        drm_connector_property_set_value(connector,
-                       encoder->dev->mode_config.tv_subconnector_property,
-                                                       tv_enc->subconnector);
+                                        conf->tv_subconnector_property,
+                                        tv_enc->subconnector);
 
-       return tv_enc->subconnector ? connector_status_connected :
-                                       connector_status_disconnected;
+       if (tv_enc->subconnector) {
+               NV_INFO(dev, "Load detected on output %c\n",
+                       '@' + ffs(dcb->or));
+               return connector_status_connected;
+       } else {
+               return connector_status_disconnected;
+       }
 }
 
 static const struct {
@@ -633,7 +728,7 @@ static struct drm_encoder_helper_funcs nv17_tv_helper_funcs = {
        .prepare = nv17_tv_prepare,
        .commit = nv17_tv_commit,
        .mode_set = nv17_tv_mode_set,
-       .detect = nv17_dac_detect,
+       .detect = nv17_tv_detect,
 };
 
 static struct drm_encoder_slave_funcs nv17_tv_slave_funcs = {
index 18ba74f19703f15100df2da20629b6e0b2523740..d6fc0a82f03dd20ea8b7c21da48d75c98ebb0ad9 100644 (file)
@@ -514,6 +514,27 @@ nv20_graph_rdi(struct drm_device *dev)
        nouveau_wait_for_idle(dev);
 }
 
+void
+nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+                            uint32_t size, uint32_t pitch)
+{
+       uint32_t limit = max(1u, addr + size) - 1;
+
+       if (pitch)
+               addr |= 1;
+
+       nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
+       nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
+       nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
+
+       nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i);
+       nv_wr32(dev, NV10_PGRAPH_RDI_DATA, limit);
+       nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i);
+       nv_wr32(dev, NV10_PGRAPH_RDI_DATA, pitch);
+       nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i);
+       nv_wr32(dev, NV10_PGRAPH_RDI_DATA, addr);
+}
+
 int
 nv20_graph_init(struct drm_device *dev)
 {
@@ -572,27 +593,10 @@ nv20_graph_init(struct drm_device *dev)
                nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030);
        }
 
-       /* copy tile info from PFB */
-       for (i = 0; i < NV10_PFB_TILE__SIZE; i++) {
-               nv_wr32(dev, 0x00400904 + i * 0x10,
-                                       nv_rd32(dev, NV10_PFB_TLIMIT(i)));
-                       /* which is NV40_PGRAPH_TLIMIT0(i) ?? */
-               nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + i * 4);
-               nv_wr32(dev, NV10_PGRAPH_RDI_DATA,
-                                       nv_rd32(dev, NV10_PFB_TLIMIT(i)));
-               nv_wr32(dev, 0x00400908 + i * 0x10,
-                                       nv_rd32(dev, NV10_PFB_TSIZE(i)));
-                       /* which is NV40_PGRAPH_TSIZE0(i) ?? */
-               nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + i * 4);
-               nv_wr32(dev, NV10_PGRAPH_RDI_DATA,
-                                       nv_rd32(dev, NV10_PFB_TSIZE(i)));
-               nv_wr32(dev, 0x00400900 + i * 0x10,
-                                       nv_rd32(dev, NV10_PFB_TILE(i)));
-                       /* which is NV40_PGRAPH_TILE0(i) ?? */
-               nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + i * 4);
-               nv_wr32(dev, NV10_PGRAPH_RDI_DATA,
-                                       nv_rd32(dev, NV10_PFB_TILE(i)));
-       }
+       /* Turn all the tiling regions off. */
+       for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
+               nv20_graph_set_region_tiling(dev, i, 0, 0, 0);
+
        for (i = 0; i < 8; i++) {
                nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4));
                nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4);
@@ -704,18 +708,9 @@ nv30_graph_init(struct drm_device *dev)
 
        nv_wr32(dev, 0x4000c0, 0x00000016);
 
-       /* copy tile info from PFB */
-       for (i = 0; i < NV10_PFB_TILE__SIZE; i++) {
-               nv_wr32(dev, 0x00400904 + i * 0x10,
-                                       nv_rd32(dev, NV10_PFB_TLIMIT(i)));
-                       /* which is NV40_PGRAPH_TLIMIT0(i) ?? */
-               nv_wr32(dev, 0x00400908 + i * 0x10,
-                                       nv_rd32(dev, NV10_PFB_TSIZE(i)));
-                       /* which is NV40_PGRAPH_TSIZE0(i) ?? */
-               nv_wr32(dev, 0x00400900 + i * 0x10,
-                                       nv_rd32(dev, NV10_PFB_TILE(i)));
-                       /* which is NV40_PGRAPH_TILE0(i) ?? */
-       }
+       /* Turn all the tiling regions off. */
+       for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
+               nv20_graph_set_region_tiling(dev, i, 0, 0, 0);
 
        nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
        nv_wr32(dev, NV10_PGRAPH_STATE      , 0xFFFFFFFF);
index ca1d27107a8e4a5a2c097b26aa4882aebfd0b841..3cd07d8d5bd7a93c27f118dc5923991954a35d23 100644 (file)
@@ -3,12 +3,37 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 
+void
+nv40_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+                         uint32_t size, uint32_t pitch)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t limit = max(1u, addr + size) - 1;
+
+       if (pitch)
+               addr |= 1;
+
+       switch (dev_priv->chipset) {
+       case 0x40:
+               nv_wr32(dev, NV10_PFB_TLIMIT(i), limit);
+               nv_wr32(dev, NV10_PFB_TSIZE(i), pitch);
+               nv_wr32(dev, NV10_PFB_TILE(i), addr);
+               break;
+
+       default:
+               nv_wr32(dev, NV40_PFB_TLIMIT(i), limit);
+               nv_wr32(dev, NV40_PFB_TSIZE(i), pitch);
+               nv_wr32(dev, NV40_PFB_TILE(i), addr);
+               break;
+       }
+}
+
 int
 nv40_fb_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       uint32_t fb_bar_size, tmp;
-       int num_tiles;
+       struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+       uint32_t tmp;
        int i;
 
        /* This is strictly a NV4x register (don't know about NV5x). */
@@ -23,35 +48,23 @@ nv40_fb_init(struct drm_device *dev)
        case 0x45:
                tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2);
                nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15));
-               num_tiles = NV10_PFB_TILE__SIZE;
+               pfb->num_tiles = NV10_PFB_TILE__SIZE;
                break;
        case 0x46: /* G72 */
        case 0x47: /* G70 */
        case 0x49: /* G71 */
        case 0x4b: /* G73 */
        case 0x4c: /* C51 (G7X version) */
-               num_tiles = NV40_PFB_TILE__SIZE_1;
+               pfb->num_tiles = NV40_PFB_TILE__SIZE_1;
                break;
        default:
-               num_tiles = NV40_PFB_TILE__SIZE_0;
+               pfb->num_tiles = NV40_PFB_TILE__SIZE_0;
                break;
        }
 
-       fb_bar_size = drm_get_resource_len(dev, 0) - 1;
-       switch (dev_priv->chipset) {
-       case 0x40:
-               for (i = 0; i < num_tiles; i++) {
-                       nv_wr32(dev, NV10_PFB_TILE(i), 0);
-                       nv_wr32(dev, NV10_PFB_TLIMIT(i), fb_bar_size);
-               }
-               break;
-       default:
-               for (i = 0; i < num_tiles; i++) {
-                       nv_wr32(dev, NV40_PFB_TILE(i), 0);
-                       nv_wr32(dev, NV40_PFB_TLIMIT(i), fb_bar_size);
-               }
-               break;
-       }
+       /* Turn all the tiling regions off. */
+       for (i = 0; i < pfb->num_tiles; i++)
+               pfb->set_region_tiling(dev, i, 0, 0, 0);
 
        return 0;
 }
index 2b332bb55acf75b4cce5bafb9dc5110538e47428..53e8afe1dcd1a0dc6fedf5fd9d819edc87e4b918 100644 (file)
@@ -181,6 +181,48 @@ nv40_graph_unload_context(struct drm_device *dev)
        return ret;
 }
 
+void
+nv40_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+                            uint32_t size, uint32_t pitch)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t limit = max(1u, addr + size) - 1;
+
+       if (pitch)
+               addr |= 1;
+
+       switch (dev_priv->chipset) {
+       case 0x44:
+       case 0x4a:
+       case 0x4e:
+               nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
+               nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
+               nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
+               break;
+
+       case 0x46:
+       case 0x47:
+       case 0x49:
+       case 0x4b:
+               nv_wr32(dev, NV47_PGRAPH_TSIZE(i), pitch);
+               nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), limit);
+               nv_wr32(dev, NV47_PGRAPH_TILE(i), addr);
+               nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch);
+               nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit);
+               nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr);
+               break;
+
+       default:
+               nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
+               nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
+               nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
+               nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch);
+               nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit);
+               nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr);
+               break;
+       }
+}
+
 /*
  * G70         0x47
  * G71         0x49
@@ -195,7 +237,8 @@ nv40_graph_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv =
                (struct drm_nouveau_private *)dev->dev_private;
-       uint32_t vramsz, tmp;
+       struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+       uint32_t vramsz;
        int i, j;
 
        nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
@@ -292,74 +335,9 @@ nv40_graph_init(struct drm_device *dev)
        nv_wr32(dev, 0x400b38, 0x2ffff800);
        nv_wr32(dev, 0x400b3c, 0x00006000);
 
-       /* copy tile info from PFB */
-       switch (dev_priv->chipset) {
-       case 0x40: /* vanilla NV40 */
-               for (i = 0; i < NV10_PFB_TILE__SIZE; i++) {
-                       tmp = nv_rd32(dev, NV10_PFB_TILE(i));
-                       nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp);
-                       tmp = nv_rd32(dev, NV10_PFB_TLIMIT(i));
-                       nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp);
-                       tmp = nv_rd32(dev, NV10_PFB_TSIZE(i));
-                       nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp);
-                       tmp = nv_rd32(dev, NV10_PFB_TSTATUS(i));
-                       nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp);
-               }
-               break;
-       case 0x44:
-       case 0x4a:
-       case 0x4e: /* NV44-based cores don't have 0x406900? */
-               for (i = 0; i < NV40_PFB_TILE__SIZE_0; i++) {
-                       tmp = nv_rd32(dev, NV40_PFB_TILE(i));
-                       nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp);
-                       tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i));
-                       nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp);
-                       tmp = nv_rd32(dev, NV40_PFB_TSIZE(i));
-                       nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp);
-                       tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i));
-                       nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp);
-               }
-               break;
-       case 0x46:
-       case 0x47:
-       case 0x49:
-       case 0x4b: /* G7X-based cores */
-               for (i = 0; i < NV40_PFB_TILE__SIZE_1; i++) {
-                       tmp = nv_rd32(dev, NV40_PFB_TILE(i));
-                       nv_wr32(dev, NV47_PGRAPH_TILE0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp);
-                       tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i));
-                       nv_wr32(dev, NV47_PGRAPH_TLIMIT0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp);
-                       tmp = nv_rd32(dev, NV40_PFB_TSIZE(i));
-                       nv_wr32(dev, NV47_PGRAPH_TSIZE0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp);
-                       tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i));
-                       nv_wr32(dev, NV47_PGRAPH_TSTATUS0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp);
-               }
-               break;
-       default: /* everything else */
-               for (i = 0; i < NV40_PFB_TILE__SIZE_0; i++) {
-                       tmp = nv_rd32(dev, NV40_PFB_TILE(i));
-                       nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp);
-                       tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i));
-                       nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp);
-                       tmp = nv_rd32(dev, NV40_PFB_TSIZE(i));
-                       nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp);
-                       tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i));
-                       nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp);
-                       nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp);
-               }
-               break;
-       }
+       /* Turn all the tiling regions off. */
+       for (i = 0; i < pfb->num_tiles; i++)
+               nv40_graph_set_region_tiling(dev, i, 0, 0, 0);
 
        /* begin RAM config */
        vramsz = drm_get_resource_len(dev, 0) - 1;
index a9263d92a231bf0c2c24855be13c79720fcb4f7e..90f0bf59fbcd191dabcb5803f50537938a481405 100644 (file)
@@ -690,9 +690,21 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
                           int pxclk)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_connector *nv_connector = NULL;
+       struct drm_encoder *encoder;
        struct nvbios *bios = &dev_priv->VBIOS;
        uint32_t mc, script = 0, or;
 
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+               if (nv_encoder->dcb != dcbent)
+                       continue;
+
+               nv_connector = nouveau_encoder_connector_get(nv_encoder);
+               break;
+       }
+
        or = ffs(dcbent->or) - 1;
        mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or);
        switch (dcbent->type) {
@@ -711,6 +723,11 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
                        } else
                        if (bios->fp.strapless_is_24bit & 1)
                                script |= 0x0200;
+
+                       if (nv_connector && nv_connector->edid &&
+                           (nv_connector->edid->revision >= 4) &&
+                           (nv_connector->edid->input & 0x70) >= 0x20)
+                               script |= 0x0200;
                }
 
                if (nouveau_uscript_lvds >= 0) {
index 6bcc6d39e9b0bac9560b2e424c73f884bcb4b5c7..e4f279ee61cf4b56324b7d0c5e5e8db39949871b 100644 (file)
@@ -16,9 +16,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 
        if (!(info->flags & FBINFO_HWACCEL_DISABLED) &&
             RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) {
-               NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
-
-               info->flags |= FBINFO_HWACCEL_DISABLED;
+               nouveau_fbcon_gpu_lockup(info);
        }
 
        if (info->flags & FBINFO_HWACCEL_DISABLED) {
@@ -31,7 +29,11 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
                OUT_RING(chan, 1);
        }
        BEGIN_RING(chan, NvSub2D, 0x0588, 1);
-       OUT_RING(chan, rect->color);
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+           info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+               OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]);
+       else
+               OUT_RING(chan, rect->color);
        BEGIN_RING(chan, NvSub2D, 0x0600, 4);
        OUT_RING(chan, rect->dx);
        OUT_RING(chan, rect->dy);
@@ -56,9 +58,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
                return;
 
        if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) {
-               NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
-
-               info->flags |= FBINFO_HWACCEL_DISABLED;
+               nouveau_fbcon_gpu_lockup(info);
        }
 
        if (info->flags & FBINFO_HWACCEL_DISABLED) {
@@ -101,8 +101,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        }
 
        if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) {
-               NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
-               info->flags |= FBINFO_HWACCEL_DISABLED;
+               nouveau_fbcon_gpu_lockup(info);
        }
 
        if (info->flags & FBINFO_HWACCEL_DISABLED) {
@@ -135,9 +134,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
                int push = dwords > 2047 ? 2047 : dwords;
 
                if (RING_SPACE(chan, push + 1)) {
-                       NV_ERROR(dev,
-                                "GPU lockup - switching to software fbcon\n");
-                       info->flags |= FBINFO_HWACCEL_DISABLED;
+                       nouveau_fbcon_gpu_lockup(info);
                        cfb_imageblit(info, image);
                        return;
                }
@@ -199,7 +196,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
 
        ret = RING_SPACE(chan, 59);
        if (ret) {
-               NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
+               nouveau_fbcon_gpu_lockup(info);
                return ret;
        }
 
index b7282284f0806f4db2cb71b57eddda7606e3c055..39caf167587d130ae4bf6346342818550c653f80 100644 (file)
@@ -384,8 +384,8 @@ nv50_fifo_load_context(struct nouveau_channel *chan)
                nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr),
                        nv_ro32(dev, cache, (ptr * 2) + 1));
        }
-       nv_wr32(dev, 0x3210, cnt << 2);
-       nv_wr32(dev, 0x3270, 0);
+       nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, cnt << 2);
+       nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
 
        /* guessing that all the 0x34xx regs aren't on NV50 */
        if (!IS_G80) {
@@ -398,8 +398,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan)
 
        dev_priv->engine.instmem.finish_access(dev);
 
-       nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
-       nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
        nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16));
        return 0;
 }
index b5f5fe75e6af350335f5d8dc59436149647d96ea..1cc7b937b1eaea4cdaac2df729613a6142fa9e90 100644 (file)
@@ -24,6 +24,9 @@ $(obj)/rv515_reg_safe.h: $(src)/reg_srcs/rv515 $(obj)/mkregtable
 $(obj)/r300_reg_safe.h: $(src)/reg_srcs/r300 $(obj)/mkregtable
        $(call if_changed,mkregtable)
 
+$(obj)/r420_reg_safe.h: $(src)/reg_srcs/r420 $(obj)/mkregtable
+       $(call if_changed,mkregtable)
+
 $(obj)/rs600_reg_safe.h: $(src)/reg_srcs/rs600 $(obj)/mkregtable
        $(call if_changed,mkregtable)
 
@@ -35,6 +38,8 @@ $(obj)/rv515.o: $(obj)/rv515_reg_safe.h
 
 $(obj)/r300.o: $(obj)/r300_reg_safe.h
 
+$(obj)/r420.o: $(obj)/r420_reg_safe.h
+
 $(obj)/rs600.o: $(obj)/rs600_reg_safe.h
 
 radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
index 6d0183c61d3bba4d6d1821b11ffeb2be13a92345..c714179d1bfa7019b8e51b6203a95e20d39819cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright 2006-2007 Advanced Micro Devices, Inc.
+* Copyright 2006-2007 Advanced Micro Devices, Inc.  
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 /****************************************************/
 /* Encoder Object ID Definition                     */
 /****************************************************/
-#define ENCODER_OBJECT_ID_NONE                    0x00
+#define ENCODER_OBJECT_ID_NONE                    0x00 
 
 /* Radeon Class Display Hardware */
 #define ENCODER_OBJECT_ID_INTERNAL_LVDS           0x01
 #define ENCODER_OBJECT_ID_INTERNAL_TMDS1          0x02
 #define ENCODER_OBJECT_ID_INTERNAL_TMDS2          0x03
 #define ENCODER_OBJECT_ID_INTERNAL_DAC1           0x04
-#define ENCODER_OBJECT_ID_INTERNAL_DAC2           0x05 /* TV/CV DAC */
+#define ENCODER_OBJECT_ID_INTERNAL_DAC2           0x05     /* TV/CV DAC */
 #define ENCODER_OBJECT_ID_INTERNAL_SDVOA          0x06
 #define ENCODER_OBJECT_ID_INTERNAL_SDVOB          0x07
 
 #define ENCODER_OBJECT_ID_SI170B                  0x08
 #define ENCODER_OBJECT_ID_CH7303                  0x09
 #define ENCODER_OBJECT_ID_CH7301                  0x0A
-#define ENCODER_OBJECT_ID_INTERNAL_DVO1           0x0B /* This belongs to Radeon Class Display Hardware */
+#define ENCODER_OBJECT_ID_INTERNAL_DVO1           0x0B    /* This belongs to Radeon Class Display Hardware */
 #define ENCODER_OBJECT_ID_EXTERNAL_SDVOA          0x0C
 #define ENCODER_OBJECT_ID_EXTERNAL_SDVOB          0x0D
 #define ENCODER_OBJECT_ID_TITFP513                0x0E
-#define ENCODER_OBJECT_ID_INTERNAL_LVTM1          0x0F /* not used for Radeon */
+#define ENCODER_OBJECT_ID_INTERNAL_LVTM1          0x0F    /* not used for Radeon */
 #define ENCODER_OBJECT_ID_VT1623                  0x10
 #define ENCODER_OBJECT_ID_HDMI_SI1930             0x11
 #define ENCODER_OBJECT_ID_HDMI_INTERNAL           0x12
@@ -68,9 +68,9 @@
 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1   0x13
 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1    0x14
 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1    0x15
-#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2    0x16 /* Shared with CV/TV and CRT */
-#define ENCODER_OBJECT_ID_SI178                   0X17 /* External TMDS (dual link, no HDCP.) */
-#define ENCODER_OBJECT_ID_MVPU_FPGA               0x18 /* MVPU FPGA chip */
+#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2    0x16  /* Shared with CV/TV and CRT */
+#define ENCODER_OBJECT_ID_SI178                   0X17  /* External TMDS (dual link, no HDCP.) */
+#define ENCODER_OBJECT_ID_MVPU_FPGA               0x18  /* MVPU FPGA chip */
 #define ENCODER_OBJECT_ID_INTERNAL_DDI            0x19
 #define ENCODER_OBJECT_ID_VT1625                  0x1A
 #define ENCODER_OBJECT_ID_HDMI_SI1932             0x1B
@@ -86,7 +86,7 @@
 /****************************************************/
 /* Connector Object ID Definition                   */
 /****************************************************/
-#define CONNECTOR_OBJECT_ID_NONE                  0x00
+#define CONNECTOR_OBJECT_ID_NONE                  0x00 
 #define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I     0x01
 #define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I       0x02
 #define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D     0x03
@@ -96,7 +96,7 @@
 #define CONNECTOR_OBJECT_ID_SVIDEO                0x07
 #define CONNECTOR_OBJECT_ID_YPbPr                 0x08
 #define CONNECTOR_OBJECT_ID_D_CONNECTOR           0x09
-#define CONNECTOR_OBJECT_ID_9PIN_DIN              0x0A /* Supports both CV & TV */
+#define CONNECTOR_OBJECT_ID_9PIN_DIN              0x0A  /* Supports both CV & TV */
 #define CONNECTOR_OBJECT_ID_SCART                 0x0B
 #define CONNECTOR_OBJECT_ID_HDMI_TYPE_A           0x0C
 #define CONNECTOR_OBJECT_ID_HDMI_TYPE_B           0x0D
 #define CONNECTOR_OBJECT_ID_CROSSFIRE             0x11
 #define CONNECTOR_OBJECT_ID_HARDCODE_DVI          0x12
 #define CONNECTOR_OBJECT_ID_DISPLAYPORT           0x13
+#define CONNECTOR_OBJECT_ID_eDP                   0x14
+#define CONNECTOR_OBJECT_ID_MXM                   0x15
 
 /* deleted */
 
 #define ROUTER_OBJECT_ID_NONE                                                                                  0x00
 #define ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL                             0x01
 
+/****************************************************/
+/* Generic Object ID Definition                     */
+/****************************************************/
+#define GENERIC_OBJECT_ID_NONE                    0x00
+#define GENERIC_OBJECT_ID_GLSYNC                  0x01
+#define GENERIC_OBJECT_ID_PX2_NON_DRIVABLE        0x02
+#define GENERIC_OBJECT_ID_MXM_OPM                 0x03
+
 /****************************************************/
 /* Graphics Object ENUM ID Definition               */
 /****************************************************/
 #define GRAPH_OBJECT_ENUM_ID4                     0x04
 #define GRAPH_OBJECT_ENUM_ID5                     0x05
 #define GRAPH_OBJECT_ENUM_ID6                     0x06
+#define GRAPH_OBJECT_ENUM_ID7                     0x07
 
 /****************************************************/
 /* Graphics Object ID Bit definition                */
 #define RESERVED1_ID_MASK                         0x0800
 #define OBJECT_TYPE_MASK                          0x7000
 #define RESERVED2_ID_MASK                         0x8000
-
+                                                  
 #define OBJECT_ID_SHIFT                           0x00
 #define ENUM_ID_SHIFT                             0x08
 #define OBJECT_TYPE_SHIFT                         0x0C
 
+
 /****************************************************/
 /* Graphics Object family definition                */
 /****************************************************/
-#define CONSTRUCTOBJECTFAMILYID(GRAPHICS_OBJECT_TYPE, GRAPHICS_OBJECT_ID) \
-       (GRAPHICS_OBJECT_TYPE << OBJECT_TYPE_SHIFT | \
-        GRAPHICS_OBJECT_ID   << OBJECT_ID_SHIFT)
+#define CONSTRUCTOBJECTFAMILYID(GRAPHICS_OBJECT_TYPE, GRAPHICS_OBJECT_ID) (GRAPHICS_OBJECT_TYPE << OBJECT_TYPE_SHIFT | \
+                                                                           GRAPHICS_OBJECT_ID   << OBJECT_ID_SHIFT)
 /****************************************************/
 /* GPU Object ID definition - Shared with BIOS      */
 /****************************************************/
-#define GPU_ENUM_ID1   (GRAPH_OBJECT_TYPE_GPU << OBJECT_TYPE_SHIFT |\
-                        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT)
+#define GPU_ENUM_ID1                            ( GRAPH_OBJECT_TYPE_GPU << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT)
 
 /****************************************************/
 /* Encoder Object ID definition - Shared with BIOS  */
 /****************************************************/
 /*
-#define ENCODER_INTERNAL_LVDS_ENUM_ID1        0x2101
+#define ENCODER_INTERNAL_LVDS_ENUM_ID1        0x2101      
 #define ENCODER_INTERNAL_TMDS1_ENUM_ID1       0x2102
 #define ENCODER_INTERNAL_TMDS2_ENUM_ID1       0x2103
 #define ENCODER_INTERNAL_DAC1_ENUM_ID1        0x2104
 #define ENCODER_INTERNAL_DAC2_ENUM_ID1        0x2105
 #define ENCODER_INTERNAL_SDVOA_ENUM_ID1       0x2106
 #define ENCODER_INTERNAL_SDVOB_ENUM_ID1       0x2107
-#define ENCODER_SIL170B_ENUM_ID1              0x2108
+#define ENCODER_SIL170B_ENUM_ID1              0x2108  
 #define ENCODER_CH7303_ENUM_ID1               0x2109
 #define ENCODER_CH7301_ENUM_ID1               0x210A
 #define ENCODER_INTERNAL_DVO1_ENUM_ID1        0x210B
 #define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1   0x2113
 #define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1    0x2114
 #define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1    0x2115
-#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1    0x2116
-#define ENCODER_SI178_ENUM_ID1                   0x2117
+#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1    0x2116  
+#define ENCODER_SI178_ENUM_ID1                   0x2117 
 #define ENCODER_MVPU_FPGA_ENUM_ID1               0x2118
 #define ENCODER_INTERNAL_DDI_ENUM_ID1            0x2119
 #define ENCODER_VT1625_ENUM_ID1                  0x211A
 #define ENCODER_DP_DP501_ENUM_ID1                0x211D
 #define ENCODER_INTERNAL_UNIPHY_ENUM_ID1         0x211E
 */
-#define ENCODER_INTERNAL_LVDS_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_LVDS << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_TMDS1_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_TMDS1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_TMDS2_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_TMDS2 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_DAC1_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_DAC1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_DAC2_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_DAC2 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_SDVOA_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_SDVOA_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_SDVOB_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_SDVOB << OBJECT_ID_SHIFT)
-
-#define ENCODER_SIL170B_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_SI170B << OBJECT_ID_SHIFT)
-
-#define ENCODER_CH7303_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_CH7303 << OBJECT_ID_SHIFT)
-
-#define ENCODER_CH7301_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_CH7301 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_DVO1_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_DVO1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
-
-#define ENCODER_EXTERNAL_SDVOA_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
-
-#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_EXTERNAL_SDVOB << OBJECT_ID_SHIFT)
-
-#define ENCODER_TITFP513_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_TITFP513 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_LVTM1_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_LVTM1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_VT1623_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_VT1623 << OBJECT_ID_SHIFT)
-
-#define ENCODER_HDMI_SI1930_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_HDMI_SI1930 << OBJECT_ID_SHIFT)
-
-#define ENCODER_HDMI_INTERNAL_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_HDMI_INTERNAL << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 << OBJECT_ID_SHIFT) /* Shared with CV/TV and CRT */
-
-#define ENCODER_SI178_ENUM_ID1  \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_SI178 << OBJECT_ID_SHIFT)
-
-#define ENCODER_MVPU_FPGA_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_MVPU_FPGA << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_DDI_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_DDI << OBJECT_ID_SHIFT)
-
-#define ENCODER_VT1625_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_VT1625 << OBJECT_ID_SHIFT)
-
-#define ENCODER_HDMI_SI1932_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_HDMI_SI1932 << OBJECT_ID_SHIFT)
-
-#define ENCODER_DP_DP501_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_DP_DP501 << OBJECT_ID_SHIFT)
-
-#define ENCODER_DP_AN9801_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_DP_AN9801 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_LVTMA_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
-
-#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT)
+#define ENCODER_INTERNAL_LVDS_ENUM_ID1     ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_LVDS << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_TMDS1_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_TMDS1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_TMDS2_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_TMDS2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DAC1_ENUM_ID1     ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_DAC1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DAC2_ENUM_ID1     ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_DAC2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_SDVOA_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_SDVOA_ENUM_ID2    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_SDVOB_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_SDVOB << OBJECT_ID_SHIFT)
+
+#define ENCODER_SIL170B_ENUM_ID1           ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_SI170B << OBJECT_ID_SHIFT)
+
+#define ENCODER_CH7303_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_CH7303 << OBJECT_ID_SHIFT)
+
+#define ENCODER_CH7301_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_CH7301 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DVO1_ENUM_ID1     ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_DVO1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+#define ENCODER_EXTERNAL_SDVOA_ENUM_ID2    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+
+#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_EXTERNAL_SDVOB << OBJECT_ID_SHIFT)
+
+
+#define ENCODER_TITFP513_ENUM_ID1          ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_TITFP513 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_LVTM1_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_LVTM1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_VT1623_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_VT1623 << OBJECT_ID_SHIFT)
+
+#define ENCODER_HDMI_SI1930_ENUM_ID1       ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_HDMI_SI1930 << OBJECT_ID_SHIFT)
+
+#define ENCODER_HDMI_INTERNAL_ENUM_ID1     ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_HDMI_INTERNAL << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1   ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
+
+
+#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID2   ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
+
+
+#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 << OBJECT_ID_SHIFT)  // Shared with CV/TV and CRT
+
+#define ENCODER_SI178_ENUM_ID1                    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_SI178 << OBJECT_ID_SHIFT)  
+
+#define ENCODER_MVPU_FPGA_ENUM_ID1                ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_MVPU_FPGA << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DDI_ENUM_ID1     (  GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_DDI << OBJECT_ID_SHIFT) 
+
+#define ENCODER_VT1625_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_VT1625 << OBJECT_ID_SHIFT)
+
+#define ENCODER_HDMI_SI1932_ENUM_ID1       ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_HDMI_SI1932 << OBJECT_ID_SHIFT)
+
+#define ENCODER_DP_DP501_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_DP_DP501 << OBJECT_ID_SHIFT)
+
+#define ENCODER_DP_AN9801_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_DP_AN9801 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY_ENUM_ID2         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_LVTMA_ENUM_ID1   ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA << OBJECT_ID_SHIFT)  
+
+#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID1         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID2         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID1         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID2         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                  GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                  ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT)
 
 /****************************************************/
 /* Connector Object ID definition - Shared with BIOS */
 #define CONNECTOR_7PIN_DIN_ENUM_ID1                 0x310F
 #define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1           0x3110
 */
-#define CONNECTOR_LVDS_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_VGA_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_VGA_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_COMPOSITE_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SVIDEO_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_YPbPr_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_D_CONNECTOR_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_9PIN_DIN_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SCART_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_7PIN_DIN_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_CROSSFIRE_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_CROSSFIRE_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_HARDCODE_DVI_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_HARDCODE_DVI_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DISPLAYPORT_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DISPLAYPORT_ENUM_ID2 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DISPLAYPORT_ENUM_ID3 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DISPLAYPORT_ENUM_ID4 \
-       (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
-        CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+#define CONNECTOR_LVDS_ENUM_ID1                ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_LVDS_ENUM_ID2                ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_eDP_ENUM_ID1                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_eDP << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_eDP_ENUM_ID2                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_eDP << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1   ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID2   ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID2     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1   ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID2   ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID2     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID3     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_VGA_ENUM_ID1                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_VGA_ENUM_ID2                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_COMPOSITE_ENUM_ID1           ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_COMPOSITE_ENUM_ID2           ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SVIDEO_ENUM_ID1              ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SVIDEO_ENUM_ID2              ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_YPbPr_ENUM_ID1               ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_YPbPr_ENUM_ID2               ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_D_CONNECTOR_ENUM_ID1         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_D_CONNECTOR_ENUM_ID2         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_9PIN_DIN_ENUM_ID1            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_9PIN_DIN_ENUM_ID2            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SCART_ENUM_ID1               ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SCART_ENUM_ID2               ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_A_ENUM_ID2         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_A_ENUM_ID3         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_B_ENUM_ID2         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_7PIN_DIN_ENUM_ID1            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT)
+#define CONNECTOR_7PIN_DIN_ENUM_ID2            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1      ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID2      ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_CROSSFIRE_ENUM_ID1           ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_CROSSFIRE_ENUM_ID2           ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
+
+
+#define CONNECTOR_HARDCODE_DVI_ENUM_ID1        ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HARDCODE_DVI_ENUM_ID2        ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID1         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID2         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID3         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID4         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID5         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID6         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_MXM_ENUM_ID1                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DP_A
+
+#define CONNECTOR_MXM_ENUM_ID2                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DP_B
+
+#define CONNECTOR_MXM_ENUM_ID3                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DP_C
+
+#define CONNECTOR_MXM_ENUM_ID4                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DP_D
+
+#define CONNECTOR_MXM_ENUM_ID5                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_LVDS_TXxx
+
+#define CONNECTOR_MXM_ENUM_ID6                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_LVDS_UXxx
+
+#define CONNECTOR_MXM_ENUM_ID7                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID7 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DAC
 
 /****************************************************/
 /* Router Object ID definition - Shared with BIOS   */
 /****************************************************/
-#define ROUTER_I2C_EXTENDER_CNTL_ENUM_ID1 \
-       (GRAPH_OBJECT_TYPE_ROUTER << OBJECT_TYPE_SHIFT |\
-        GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-        ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL << OBJECT_ID_SHIFT)
+#define ROUTER_I2C_EXTENDER_CNTL_ENUM_ID1      ( GRAPH_OBJECT_TYPE_ROUTER << OBJECT_TYPE_SHIFT |\
+                                                GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL << OBJECT_ID_SHIFT)
 
 /* deleted */
 
+/****************************************************/
+/* Generic Object ID definition - Shared with BIOS  */
+/****************************************************/
+#define GENERICOBJECT_GLSYNC_ENUM_ID1           (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 GENERIC_OBJECT_ID_GLSYNC << OBJECT_ID_SHIFT)
+
+#define GENERICOBJECT_PX2_NON_DRIVABLE_ID1       (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 GENERIC_OBJECT_ID_PX2_NON_DRIVABLE<< OBJECT_ID_SHIFT)
+
+#define GENERICOBJECT_PX2_NON_DRIVABLE_ID2       (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 GENERIC_OBJECT_ID_PX2_NON_DRIVABLE<< OBJECT_ID_SHIFT)
+
+#define GENERICOBJECT_MXM_OPM_ENUM_ID1           (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 GENERIC_OBJECT_ID_MXM_OPM << OBJECT_ID_SHIFT)
+
 /****************************************************/
 /* Object Cap definition - Shared with BIOS         */
 /****************************************************/
 #define GRAPHICS_OBJECT_CAP_I2C                 0x00000001L
 #define GRAPHICS_OBJECT_CAP_TABLE_ID            0x00000002L
 
+
 #define GRAPHICS_OBJECT_I2CCOMMAND_TABLE_ID                   0x01
 #define GRAPHICS_OBJECT_HOTPLUGDETECTIONINTERUPT_TABLE_ID     0x02
 #define GRAPHICS_OBJECT_ENCODER_OUTPUT_PROTECTION_TABLE_ID    0x03
 #pragma pack()
 #endif
 
-#endif /*GRAPHICTYPE */
+#endif  /*GRAPHICTYPE */
+
+
+
+
index 0d63c4436e7cdc0db11a99657463d6f8537becdb..3eb0ca5b3d73406d84c070e5bf9376dd4a1c5fa9 100644 (file)
@@ -468,7 +468,8 @@ void radeon_dp_set_link_config(struct drm_connector *connector,
        struct radeon_connector *radeon_connector;
        struct radeon_connector_atom_dig *dig_connector;
 
-       if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
+       if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) ||
+           (connector->connector_type != DRM_MODE_CONNECTOR_eDP))
                return;
 
        radeon_connector = to_radeon_connector(connector);
@@ -582,7 +583,8 @@ void dp_link_train(struct drm_encoder *encoder,
        u8 train_set[4];
        int i;
 
-       if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
+       if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) ||
+           (connector->connector_type != DRM_MODE_CONNECTOR_eDP))
                return;
 
        if (!radeon_encoder->enc_priv)
index 0d79577c15761759f6634eb636b78c8b711989a8..607241c6a8a9a80d2f477c4dbc5da69eb7cd5952 100644 (file)
@@ -661,8 +661,10 @@ static int parser_auth(struct table *t, const char *filename)
        fseek(file, 0, SEEK_SET);
 
        /* get header */
-       if (fgets(buf, 1024, file) == NULL)
+       if (fgets(buf, 1024, file) == NULL) {
+               fclose(file);
                return -1;
+       }
 
        /* first line will contain the last register
         * and gpu name */
index 71727460968f9d25445c9f179d55e7856729fb5e..8760d66e058a6b60b873fab99f3bdb34efd4f0ea 100644 (file)
@@ -131,7 +131,8 @@ void r100_hpd_init(struct radeon_device *rdev)
                        break;
                }
        }
-       r100_irq_set(rdev);
+       if (rdev->irq.installed)
+               r100_irq_set(rdev);
 }
 
 void r100_hpd_fini(struct radeon_device *rdev)
@@ -243,6 +244,11 @@ int r100_irq_set(struct radeon_device *rdev)
 {
        uint32_t tmp = 0;
 
+       if (!rdev->irq.installed) {
+               WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n");
+               WREG32(R_000040_GEN_INT_CNTL, 0);
+               return -EINVAL;
+       }
        if (rdev->irq.sw_int) {
                tmp |= RADEON_SW_INT_ENABLE;
        }
@@ -356,6 +362,11 @@ void r100_fence_ring_emit(struct radeon_device *rdev,
        /* Wait until IDLE & CLEAN */
        radeon_ring_write(rdev, PACKET0(0x1720, 0));
        radeon_ring_write(rdev, (1 << 16) | (1 << 17));
+       radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+       radeon_ring_write(rdev, rdev->config.r100.hdp_cntl |
+                               RADEON_HDP_READ_BUFFER_INVALIDATE);
+       radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+       radeon_ring_write(rdev, rdev->config.r100.hdp_cntl);
        /* Emit fence sequence & fire IRQ */
        radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0));
        radeon_ring_write(rdev, fence->seq);
@@ -1713,14 +1724,6 @@ void r100_gpu_init(struct radeon_device *rdev)
        r100_hdp_reset(rdev);
 }
 
-void r100_hdp_flush(struct radeon_device *rdev)
-{
-       u32 tmp;
-       tmp = RREG32(RADEON_HOST_PATH_CNTL);
-       tmp |= RADEON_HDP_READ_BUFFER_INVALIDATE;
-       WREG32(RADEON_HOST_PATH_CNTL, tmp);
-}
-
 void r100_hdp_reset(struct radeon_device *rdev)
 {
        uint32_t tmp;
@@ -3313,6 +3316,7 @@ static int r100_startup(struct radeon_device *rdev)
        }
        /* Enable IRQ */
        r100_irq_set(rdev);
+       rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
@@ -3371,6 +3375,7 @@ void r100_fini(struct radeon_device *rdev)
        radeon_gem_fini(rdev);
        if (rdev->flags & RADEON_IS_PCI)
                r100_pci_gart_fini(rdev);
+       radeon_agp_fini(rdev);
        radeon_irq_kms_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_bo_fini(rdev);
index 3f2cc9e2e8d9a9f4a629361a2ea545c5f1b61f2c..0051d11b907c162e011e8ed7795507f4ca0e610f 100644 (file)
 #include "rv350d.h"
 #include "r300_reg_safe.h"
 
-/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380 */
+/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380
+ *
+ * GPU Errata:
+ * - HOST_PATH_CNTL: r300 family seems to dislike write to HOST_PATH_CNTL
+ *   using MMIO to flush host path read cache, this lead to HARDLOCKUP.
+ *   However, scheduling such write to the ring seems harmless, i suspect
+ *   the CP read collide with the flush somehow, or maybe the MC, hard to
+ *   tell. (Jerome Glisse)
+ */
 
 /*
  * rv370,rv380 PCIE GART
@@ -178,6 +186,11 @@ void r300_fence_ring_emit(struct radeon_device *rdev,
        /* Wait until IDLE & CLEAN */
        radeon_ring_write(rdev, PACKET0(0x1720, 0));
        radeon_ring_write(rdev, (1 << 17) | (1 << 16)  | (1 << 9));
+       radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+       radeon_ring_write(rdev, rdev->config.r300.hdp_cntl |
+                               RADEON_HDP_READ_BUFFER_INVALIDATE);
+       radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+       radeon_ring_write(rdev, rdev->config.r300.hdp_cntl);
        /* Emit fence sequence & fire IRQ */
        radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0));
        radeon_ring_write(rdev, fence->seq);
@@ -1258,6 +1271,7 @@ static int r300_startup(struct radeon_device *rdev)
        }
        /* Enable IRQ */
        r100_irq_set(rdev);
+       rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
@@ -1322,6 +1336,7 @@ void r300_fini(struct radeon_device *rdev)
                rv370_pcie_gart_fini(rdev);
        if (rdev->flags & RADEON_IS_PCI)
                r100_pci_gart_fini(rdev);
+       radeon_agp_fini(rdev);
        radeon_irq_kms_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_bo_fini(rdev);
index c05a7270cf0c619fb6f20225c455bf58969ada19..053404e71a9d74bc0b293decf78240bc972f9547 100644 (file)
 #include "radeon_reg.h"
 #include "radeon.h"
 #include "atom.h"
+#include "r100d.h"
 #include "r420d.h"
+#include "r420_reg_safe.h"
+
+static void r420_set_reg_safe(struct radeon_device *rdev)
+{
+       rdev->config.r300.reg_safe_bm = r420_reg_safe_bm;
+       rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm);
+}
 
 int r420_mc_init(struct radeon_device *rdev)
 {
@@ -165,6 +173,34 @@ static void r420_clock_resume(struct radeon_device *rdev)
        WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl);
 }
 
+static void r420_cp_errata_init(struct radeon_device *rdev)
+{
+       /* RV410 and R420 can lock up if CP DMA to host memory happens
+        * while the 2D engine is busy.
+        *
+        * The proper workaround is to queue a RESYNC at the beginning
+        * of the CP init, apparently.
+        */
+       radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch);
+       radeon_ring_lock(rdev, 8);
+       radeon_ring_write(rdev, PACKET0(R300_CP_RESYNC_ADDR, 1));
+       radeon_ring_write(rdev, rdev->config.r300.resync_scratch);
+       radeon_ring_write(rdev, 0xDEADBEEF);
+       radeon_ring_unlock_commit(rdev);
+}
+
+static void r420_cp_errata_fini(struct radeon_device *rdev)
+{
+       /* Catch the RESYNC we dispatched all the way back,
+        * at the very beginning of the CP init.
+        */
+       radeon_ring_lock(rdev, 8);
+       radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+       radeon_ring_write(rdev, R300_RB3D_DC_FINISH);
+       radeon_ring_unlock_commit(rdev);
+       radeon_scratch_free(rdev, rdev->config.r300.resync_scratch);
+}
+
 static int r420_startup(struct radeon_device *rdev)
 {
        int r;
@@ -190,12 +226,14 @@ static int r420_startup(struct radeon_device *rdev)
        r420_pipes_init(rdev);
        /* Enable IRQ */
        r100_irq_set(rdev);
+       rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
                dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
                return r;
        }
+       r420_cp_errata_init(rdev);
        r = r100_wb_init(rdev);
        if (r) {
                dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
@@ -238,6 +276,7 @@ int r420_resume(struct radeon_device *rdev)
 
 int r420_suspend(struct radeon_device *rdev)
 {
+       r420_cp_errata_fini(rdev);
        r100_cp_disable(rdev);
        r100_wb_disable(rdev);
        r100_irq_disable(rdev);
@@ -346,7 +385,7 @@ int r420_init(struct radeon_device *rdev)
                if (r)
                        return r;
        }
-       r300_set_reg_safe(rdev);
+       r420_set_reg_safe(rdev);
        rdev->accel_working = true;
        r = r420_startup(rdev);
        if (r) {
index 0f3843b6dac7669991d4d638c6f002d7204a9054..9a189072f2b93e09299ff63b1464d32e260ba657 100644 (file)
@@ -186,6 +186,7 @@ static int r520_startup(struct radeon_device *rdev)
        }
        /* Enable IRQ */
        rs600_irq_set(rdev);
+       rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
index a0ac3c134b1bb560503b6d60418ce9563f614990..c0651991c3e41ab7dd54ef77a464b7ff8cb889c6 100644 (file)
@@ -285,7 +285,8 @@ void r600_hpd_init(struct radeon_device *rdev)
                        }
                }
        }
-       r600_irq_set(rdev);
+       if (rdev->irq.installed)
+               r600_irq_set(rdev);
 }
 
 void r600_hpd_fini(struct radeon_device *rdev)
@@ -726,6 +727,10 @@ int r600_mc_init(struct radeon_device *rdev)
        a.full = rfixed_const(100);
        rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
        rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+
+       if (rdev->flags & RADEON_IS_IGP)
+               rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+
        return 0;
 }
 
@@ -1384,11 +1389,6 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
        (void)RREG32(PCIE_PORT_DATA);
 }
 
-void r600_hdp_flush(struct radeon_device *rdev)
-{
-       WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
-}
-
 /*
  * CP & Ring
  */
@@ -1785,6 +1785,8 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
        radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2));
        radeon_ring_write(rdev, fence->seq);
+       radeon_ring_write(rdev, PACKET0(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0));
+       radeon_ring_write(rdev, 1);
        /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */
        radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0));
        radeon_ring_write(rdev, RB_INT_STAT);
@@ -2089,8 +2091,7 @@ void r600_fini(struct radeon_device *rdev)
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_clocks_fini(rdev);
-       if (rdev->flags & RADEON_IS_AGP)
-               radeon_agp_fini(rdev);
+       radeon_agp_fini(rdev);
        radeon_bo_fini(rdev);
        radeon_atombios_fini(rdev);
        kfree(rdev->bios);
@@ -2461,6 +2462,10 @@ int r600_irq_set(struct radeon_device *rdev)
        u32 mode_int = 0;
        u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0;
 
+       if (!rdev->irq.installed) {
+               WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n");
+               return -EINVAL;
+       }
        /* don't enable anything if the ih is disabled */
        if (!rdev->ih.enabled)
                return 0;
index 9aecafb51b660947bfd2d2d7d93e92c3b3be1788..8787ea89dc6e0437acf493a48ae93d7e75fce8cc 100644 (file)
@@ -577,9 +577,9 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
        ring_size = num_loops * dwords_per_loop;
        /* set default  + shaders */
        ring_size += 40; /* shaders + def state */
-       ring_size += 5; /* fence emit for VB IB */
+       ring_size += 7; /* fence emit for VB IB */
        ring_size += 5; /* done copy */
-       ring_size += 5; /* fence emit for done copy */
+       ring_size += 7; /* fence emit for done copy */
        r = radeon_ring_lock(rdev, ring_size);
        WARN_ON(r);
 
index 53b55608102b0df5a97fd099fca0d8063d5e13b7..eb5f99b9469debb3941cbc2b1aa91c35283cab9c 100644 (file)
@@ -319,10 +319,12 @@ struct radeon_mc {
        u64                     real_vram_size;
        int                     vram_mtrr;
        bool                    vram_is_ddr;
+       bool                    igp_sideport_enabled;
 };
 
 int radeon_mc_setup(struct radeon_device *rdev);
-
+bool radeon_combios_sideport_present(struct radeon_device *rdev);
+bool radeon_atombios_sideport_present(struct radeon_device *rdev);
 
 /*
  * GPU scratch registers structures, functions & helpers
@@ -654,7 +656,6 @@ struct radeon_asic {
                               uint32_t offset, uint32_t obj_size);
        int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
        void (*bandwidth_update)(struct radeon_device *rdev);
-       void (*hdp_flush)(struct radeon_device *rdev);
        void (*hpd_init)(struct radeon_device *rdev);
        void (*hpd_fini)(struct radeon_device *rdev);
        bool (*hpd_sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
@@ -667,11 +668,14 @@ struct radeon_asic {
 struct r100_asic {
        const unsigned  *reg_safe_bm;
        unsigned        reg_safe_bm_size;
+       u32             hdp_cntl;
 };
 
 struct r300_asic {
        const unsigned  *reg_safe_bm;
        unsigned        reg_safe_bm_size;
+       u32             resync_scratch;
+       u32             hdp_cntl;
 };
 
 struct r600_asic {
@@ -1007,7 +1011,6 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
 #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s)))
 #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r)))
 #define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev))
-#define radeon_hdp_flush(rdev) (rdev)->asic->hdp_flush((rdev))
 #define radeon_hpd_init(rdev) (rdev)->asic->hpd_init((rdev))
 #define radeon_hpd_fini(rdev) (rdev)->asic->hpd_fini((rdev))
 #define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd))
index 54bf49a6d676b6a53c1e301ec5db855d2cf7f4fb..220f454ea9fae8b11a04aa813da2f960ef47b352 100644 (file)
@@ -252,10 +252,8 @@ void radeon_agp_resume(struct radeon_device *rdev)
 void radeon_agp_fini(struct radeon_device *rdev)
 {
 #if __OS_HAS_AGP
-       if (rdev->flags & RADEON_IS_AGP) {
-               if (rdev->ddev->agp && rdev->ddev->agp->acquired) {
-                       drm_agp_release(rdev->ddev);
-               }
+       if (rdev->ddev->agp && rdev->ddev->agp->acquired) {
+               drm_agp_release(rdev->ddev);
        }
 #endif
 }
index eb29217bbf1d51d90f7060c1610e0342b65bb2d9..f2fbd2e4e9df59479660f26811d04a92b8955b95 100644 (file)
@@ -77,7 +77,6 @@ int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
 void r100_bandwidth_update(struct radeon_device *rdev);
 void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int r100_ring_test(struct radeon_device *rdev);
-void r100_hdp_flush(struct radeon_device *rdev);
 void r100_hpd_init(struct radeon_device *rdev);
 void r100_hpd_fini(struct radeon_device *rdev);
 bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
@@ -114,7 +113,6 @@ static struct radeon_asic r100_asic = {
        .set_surface_reg = r100_set_surface_reg,
        .clear_surface_reg = r100_clear_surface_reg,
        .bandwidth_update = &r100_bandwidth_update,
-       .hdp_flush = &r100_hdp_flush,
        .hpd_init = &r100_hpd_init,
        .hpd_fini = &r100_hpd_fini,
        .hpd_sense = &r100_hpd_sense,
@@ -174,7 +172,6 @@ static struct radeon_asic r300_asic = {
        .set_surface_reg = r100_set_surface_reg,
        .clear_surface_reg = r100_clear_surface_reg,
        .bandwidth_update = &r100_bandwidth_update,
-       .hdp_flush = &r100_hdp_flush,
        .hpd_init = &r100_hpd_init,
        .hpd_fini = &r100_hpd_fini,
        .hpd_sense = &r100_hpd_sense,
@@ -218,7 +215,6 @@ static struct radeon_asic r420_asic = {
        .set_surface_reg = r100_set_surface_reg,
        .clear_surface_reg = r100_clear_surface_reg,
        .bandwidth_update = &r100_bandwidth_update,
-       .hdp_flush = &r100_hdp_flush,
        .hpd_init = &r100_hpd_init,
        .hpd_fini = &r100_hpd_fini,
        .hpd_sense = &r100_hpd_sense,
@@ -267,7 +263,6 @@ static struct radeon_asic rs400_asic = {
        .set_surface_reg = r100_set_surface_reg,
        .clear_surface_reg = r100_clear_surface_reg,
        .bandwidth_update = &r100_bandwidth_update,
-       .hdp_flush = &r100_hdp_flush,
        .hpd_init = &r100_hpd_init,
        .hpd_fini = &r100_hpd_fini,
        .hpd_sense = &r100_hpd_sense,
@@ -324,7 +319,6 @@ static struct radeon_asic rs600_asic = {
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
        .bandwidth_update = &rs600_bandwidth_update,
-       .hdp_flush = &r100_hdp_flush,
        .hpd_init = &rs600_hpd_init,
        .hpd_fini = &rs600_hpd_fini,
        .hpd_sense = &rs600_hpd_sense,
@@ -372,7 +366,6 @@ static struct radeon_asic rs690_asic = {
        .set_surface_reg = r100_set_surface_reg,
        .clear_surface_reg = r100_clear_surface_reg,
        .bandwidth_update = &rs690_bandwidth_update,
-       .hdp_flush = &r100_hdp_flush,
        .hpd_init = &rs600_hpd_init,
        .hpd_fini = &rs600_hpd_fini,
        .hpd_sense = &rs600_hpd_sense,
@@ -424,7 +417,6 @@ static struct radeon_asic rv515_asic = {
        .set_surface_reg = r100_set_surface_reg,
        .clear_surface_reg = r100_clear_surface_reg,
        .bandwidth_update = &rv515_bandwidth_update,
-       .hdp_flush = &r100_hdp_flush,
        .hpd_init = &rs600_hpd_init,
        .hpd_fini = &rs600_hpd_fini,
        .hpd_sense = &rs600_hpd_sense,
@@ -467,7 +459,6 @@ static struct radeon_asic r520_asic = {
        .set_surface_reg = r100_set_surface_reg,
        .clear_surface_reg = r100_clear_surface_reg,
        .bandwidth_update = &rv515_bandwidth_update,
-       .hdp_flush = &r100_hdp_flush,
        .hpd_init = &rs600_hpd_init,
        .hpd_fini = &rs600_hpd_fini,
        .hpd_sense = &rs600_hpd_sense,
@@ -508,7 +499,6 @@ int r600_ring_test(struct radeon_device *rdev);
 int r600_copy_blit(struct radeon_device *rdev,
                   uint64_t src_offset, uint64_t dst_offset,
                   unsigned num_pages, struct radeon_fence *fence);
-void r600_hdp_flush(struct radeon_device *rdev);
 void r600_hpd_init(struct radeon_device *rdev);
 void r600_hpd_fini(struct radeon_device *rdev);
 bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
@@ -544,7 +534,6 @@ static struct radeon_asic r600_asic = {
        .set_surface_reg = r600_set_surface_reg,
        .clear_surface_reg = r600_clear_surface_reg,
        .bandwidth_update = &rv515_bandwidth_update,
-       .hdp_flush = &r600_hdp_flush,
        .hpd_init = &r600_hpd_init,
        .hpd_fini = &r600_hpd_fini,
        .hpd_sense = &r600_hpd_sense,
@@ -589,7 +578,6 @@ static struct radeon_asic rv770_asic = {
        .set_surface_reg = r600_set_surface_reg,
        .clear_surface_reg = r600_clear_surface_reg,
        .bandwidth_update = &rv515_bandwidth_update,
-       .hdp_flush = &r600_hdp_flush,
        .hpd_init = &r600_hpd_init,
        .hpd_fini = &r600_hpd_fini,
        .hpd_sense = &r600_hpd_sense,
index 321044bef71c86e9888ee5d0e2f99451009fb818..fa82ca74324e45be7fece1a947ea1ead50a5a77d 100644 (file)
@@ -114,6 +114,7 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
                        i2c.i2c_id = gpio->sucI2cId.ucAccess;
 
                        i2c.valid = true;
+                       break;
                }
        }
 
@@ -345,7 +346,9 @@ const int object_connector_convert[] = {
        DRM_MODE_CONNECTOR_Unknown,
        DRM_MODE_CONNECTOR_Unknown,
        DRM_MODE_CONNECTOR_Unknown,
-       DRM_MODE_CONNECTOR_DisplayPort
+       DRM_MODE_CONNECTOR_DisplayPort,
+       DRM_MODE_CONNECTOR_eDP,
+       DRM_MODE_CONNECTOR_Unknown
 };
 
 bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
@@ -935,6 +938,43 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
        return false;
 }
 
+union igp_info {
+       struct _ATOM_INTEGRATED_SYSTEM_INFO info;
+       struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
+};
+
+bool radeon_atombios_sideport_present(struct radeon_device *rdev)
+{
+       struct radeon_mode_info *mode_info = &rdev->mode_info;
+       int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
+       union igp_info *igp_info;
+       u8 frev, crev;
+       u16 data_offset;
+
+       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
+                              &crev, &data_offset);
+
+       igp_info = (union igp_info *)(mode_info->atom_context->bios +
+                                     data_offset);
+
+       if (igp_info) {
+               switch (crev) {
+               case 1:
+                       if (igp_info->info.ucMemoryType & 0xf0)
+                               return true;
+                       break;
+               case 2:
+                       if (igp_info->info_2.ucMemoryType & 0x0f)
+                               return true;
+                       break;
+               default:
+                       DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
+                       break;
+               }
+       }
+       return false;
+}
+
 bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
                                   struct radeon_encoder_int_tmds *tmds)
 {
@@ -1026,6 +1066,7 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
                                ss->delay = ss_info->asSS_Info[i].ucSS_Delay;
                                ss->range = ss_info->asSS_Info[i].ucSS_Range;
                                ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div;
+                               break;
                        }
                }
        }
index fd94dbca33ac99724dd1c34cab8c0590e5943586..7914455c96ca9024814d152fee0c37439b1129ee 100644 (file)
@@ -595,6 +595,48 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)
        return false;
 }
 
+bool radeon_combios_sideport_present(struct radeon_device *rdev)
+{
+       struct drm_device *dev = rdev->ddev;
+       u16 igp_info;
+
+       igp_info = combios_get_table_offset(dev, COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE);
+
+       if (igp_info) {
+               if (RBIOS16(igp_info + 0x4))
+                       return true;
+       }
+       return false;
+}
+
+static const uint32_t default_primarydac_adj[CHIP_LAST] = {
+       0x00000808,             /* r100  */
+       0x00000808,             /* rv100 */
+       0x00000808,             /* rs100 */
+       0x00000808,             /* rv200 */
+       0x00000808,             /* rs200 */
+       0x00000808,             /* r200  */
+       0x00000808,             /* rv250 */
+       0x00000000,             /* rs300 */
+       0x00000808,             /* rv280 */
+       0x00000808,             /* r300  */
+       0x00000808,             /* r350  */
+       0x00000808,             /* rv350 */
+       0x00000808,             /* rv380 */
+       0x00000808,             /* r420  */
+       0x00000808,             /* r423  */
+       0x00000808,             /* rv410 */
+       0x00000000,             /* rs400 */
+       0x00000000,             /* rs480 */
+};
+
+static void radeon_legacy_get_primary_dac_info_from_table(struct radeon_device *rdev,
+                                                         struct radeon_encoder_primary_dac *p_dac)
+{
+       p_dac->ps2_pdac_adj = default_primarydac_adj[rdev->family];
+       return;
+}
+
 struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
                                                                       radeon_encoder
                                                                       *encoder)
@@ -604,20 +646,20 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
        uint16_t dac_info;
        uint8_t rev, bg, dac;
        struct radeon_encoder_primary_dac *p_dac = NULL;
+       int found = 0;
 
-       if (rdev->bios == NULL)
+       p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac),
+                       GFP_KERNEL);
+
+       if (!p_dac)
                return NULL;
 
+       if (rdev->bios == NULL)
+               goto out;
+
        /* check CRT table */
        dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
        if (dac_info) {
-               p_dac =
-                   kzalloc(sizeof(struct radeon_encoder_primary_dac),
-                           GFP_KERNEL);
-
-               if (!p_dac)
-                       return NULL;
-
                rev = RBIOS8(dac_info) & 0x3;
                if (rev < 2) {
                        bg = RBIOS8(dac_info + 0x2) & 0xf;
@@ -628,9 +670,13 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
                        dac = RBIOS8(dac_info + 0x3) & 0xf;
                        p_dac->ps2_pdac_adj = (bg << 8) | (dac);
                }
-
+               found = 1;
        }
 
+out:
+       if (!found) /* fallback to defaults */
+               radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac);
+
        return p_dac;
 }
 
index 20161567dbff63ddba53379903c0c5a91d6ceb4e..9da10dd5df80e247a03f143c45aaa6ba26781862 100644 (file)
@@ -49,8 +49,10 @@ void radeon_connector_hotplug(struct drm_connector *connector)
        if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
                radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 
-       if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
-               if (radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
+       if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
+           (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
+               if ((radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+                   (radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_eDP)) {
                        if (radeon_dp_needs_link_train(radeon_connector)) {
                                if (connector->encoder)
                                        dp_link_train(connector->encoder, connector);
@@ -615,7 +617,7 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect
                                ret = connector_status_connected;
                }
        } else {
-               if (radeon_connector->dac_load_detect) {
+               if (radeon_connector->dac_load_detect && encoder) {
                        encoder_funcs = encoder->helper_private;
                        ret = encoder_funcs->detect(encoder, connector);
                }
@@ -967,7 +969,8 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
        }
 
        sink_type = radeon_dp_getsinktype(radeon_connector);
-       if (sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
+       if ((sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+           (sink_type == CONNECTOR_OBJECT_ID_eDP)) {
                if (radeon_dp_getdpcd(radeon_connector)) {
                        radeon_dig_connector->dp_sink_type = sink_type;
                        ret = connector_status_connected;
@@ -992,7 +995,8 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,
 
        /* XXX check mode bandwidth */
 
-       if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
+       if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+           (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
                return radeon_dp_mode_valid_helper(radeon_connector, mode);
        else
                return MODE_OK;
@@ -1145,6 +1149,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                subpixel_order = SubPixelHorizontalRGB;
                break;
        case DRM_MODE_CONNECTOR_DisplayPort:
+       case DRM_MODE_CONNECTOR_eDP:
                radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
                if (!radeon_dig_connector)
                        goto failed;
@@ -1157,10 +1162,16 @@ radeon_add_atom_connector(struct drm_device *dev,
                        goto failed;
                if (i2c_bus->valid) {
                        /* add DP i2c bus */
-                       radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
+                       if (connector_type == DRM_MODE_CONNECTOR_eDP)
+                               radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
+                       else
+                               radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
                        if (!radeon_dig_connector->dp_i2c_bus)
                                goto failed;
-                       radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
+                       if (connector_type == DRM_MODE_CONNECTOR_eDP)
+                               radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "eDP");
+                       else
+                               radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
index 0b2f9c2ad2c16a38814286e848135894f17e12c4..06123ba31d31ff564ea4224a2f0de56e87cdbf53 100644 (file)
@@ -2145,6 +2145,7 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master)
                         &master_priv->sarea);
        if (ret) {
                DRM_ERROR("SAREA setup failed\n");
+               kfree(master_priv);
                return ret;
        }
        master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
index 7c6848096bcdf2d345d2fd32e9cf838a9212c261..0c51f8e46613bf1447f86edf59e4dcdc7287ddbb 100644 (file)
@@ -733,16 +733,18 @@ void radeon_device_fini(struct radeon_device *rdev)
  */
 int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 {
-       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_device *rdev;
        struct drm_crtc *crtc;
        int r;
 
-       if (dev == NULL || rdev == NULL) {
+       if (dev == NULL || dev->dev_private == NULL) {
                return -ENODEV;
        }
        if (state.event == PM_EVENT_PRETHAW) {
                return 0;
        }
+       rdev = dev->dev_private;
+
        /* unpin the front buffers */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
index 91d72b70abc9956bacca10b0dffe41fa42868ccb..0ec491ead2ffd49a7169449acad83397192e55e2 100644 (file)
@@ -234,7 +234,7 @@ static const char *encoder_names[34] = {
        "INTERNAL_UNIPHY2",
 };
 
-static const char *connector_names[13] = {
+static const char *connector_names[15] = {
        "Unknown",
        "VGA",
        "DVI-I",
@@ -248,6 +248,8 @@ static const char *connector_names[13] = {
        "DisplayPort",
        "HDMI-A",
        "HDMI-B",
+       "TV",
+       "eDP",
 };
 
 static const char *hpd_names[7] = {
@@ -329,8 +331,11 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
                                ret = radeon_get_atom_connector_info_from_object_table(dev);
                        else
                                ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
-               } else
+               } else {
                        ret = radeon_get_legacy_connector_info_from_bios(dev);
+                       if (ret == false)
+                               ret = radeon_get_legacy_connector_info_from_table(dev);
+               }
        } else {
                if (!ASIC_IS_AVIVO(rdev))
                        ret = radeon_get_legacy_connector_info_from_table(dev);
@@ -349,7 +354,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
 {
        int ret = 0;
 
-       if (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
+       if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
+           (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
                struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
                if (dig->dp_i2c_bus)
                        radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter);
index ccba95f83d11c7dd911dd6a268c5e6104d54a570..82eb551970b92dff7f201ff4cec70beff286eebb 100644 (file)
@@ -596,21 +596,23 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                return ATOM_ENCODER_MODE_LVDS;
                break;
        case DRM_MODE_CONNECTOR_DisplayPort:
+       case DRM_MODE_CONNECTOR_eDP:
                radeon_dig_connector = radeon_connector->con_priv;
-               if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
+               if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+                   (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
                        return ATOM_ENCODER_MODE_DP;
                else if (drm_detect_hdmi_monitor(radeon_connector->edid))
                        return ATOM_ENCODER_MODE_HDMI;
                else
                        return ATOM_ENCODER_MODE_DVI;
                break;
-       case CONNECTOR_DVI_A:
-       case CONNECTOR_VGA:
+       case DRM_MODE_CONNECTOR_DVIA:
+       case DRM_MODE_CONNECTOR_VGA:
                return ATOM_ENCODER_MODE_CRT;
                break;
-       case CONNECTOR_STV:
-       case CONNECTOR_CTV:
-       case CONNECTOR_DIN:
+       case DRM_MODE_CONNECTOR_Composite:
+       case DRM_MODE_CONNECTOR_SVIDEO:
+       case DRM_MODE_CONNECTOR_9PinDIN:
                /* fix me */
                return ATOM_ENCODER_MODE_TV;
                /*return ATOM_ENCODER_MODE_CV;*/
index 4cdd8b4f75492103f330ae021054af4a74182853..8495d4e32e1890daf1626c1c963c978b969d3e61 100644 (file)
@@ -140,16 +140,15 @@ int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence)
 
 bool radeon_fence_signaled(struct radeon_fence *fence)
 {
-       struct radeon_device *rdev = fence->rdev;
        unsigned long irq_flags;
        bool signaled = false;
 
-       if (rdev->gpu_lockup) {
+       if (!fence)
                return true;
-       }
-       if (fence == NULL) {
+
+       if (fence->rdev->gpu_lockup)
                return true;
-       }
+
        write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags);
        signaled = fence->signaled;
        /* if we are shuting down report all fence as signaled */
index 60df2d7e7e4c9dd2572bee249978286ac109a549..0e1325e1853464d4e46552a2a6cfd523d406e4e6 100644 (file)
@@ -131,7 +131,6 @@ int radeon_gem_set_domain(struct drm_gem_object *gobj,
                        printk(KERN_ERR "Failed to wait for object !\n");
                        return r;
                }
-               radeon_hdp_flush(robj->rdev);
        }
        return 0;
 }
@@ -312,7 +311,6 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
        mutex_lock(&dev->struct_mutex);
        drm_gem_object_unreference(gobj);
        mutex_unlock(&dev->struct_mutex);
-       radeon_hdp_flush(robj->rdev);
        return r;
 }
 
index b79ecc4a7cc4da8975e4fe0fb9677d6700870085..2f349a300195992c9450c9ddd1d6e091eed23ef8 100644 (file)
@@ -289,16 +289,16 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr
        drm_radeon_irq_emit_t *emit = data;
        int result;
 
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-               return -EINVAL;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
        if (!dev_priv) {
                DRM_ERROR("called with no initialization\n");
                return -EINVAL;
        }
 
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
+               return -EINVAL;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
        result = radeon_emit_irq(dev);
 
        if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
index 9223296fe37be087253481647ca32c3f3e657061..3cfd60fd00835343f8cacececcb01ba600521133 100644 (file)
@@ -97,6 +97,7 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
        rdev->irq.sw_int = false;
        for (i = 0; i < 2; i++) {
                rdev->irq.crtc_vblank_int[i] = false;
+               rdev->irq.hpd[i] = false;
        }
        radeon_irq_set(rdev);
 }
@@ -128,17 +129,22 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
                        DRM_INFO("radeon: using MSI.\n");
                }
        }
-       drm_irq_install(rdev->ddev);
        rdev->irq.installed = true;
+       r = drm_irq_install(rdev->ddev);
+       if (r) {
+               rdev->irq.installed = false;
+               return r;
+       }
        DRM_INFO("radeon: irq initialized.\n");
        return 0;
 }
 
 void radeon_irq_kms_fini(struct radeon_device *rdev)
 {
+       drm_vblank_cleanup(rdev->ddev);
        if (rdev->irq.installed) {
-               rdev->irq.installed = false;
                drm_irq_uninstall(rdev->ddev);
+               rdev->irq.installed = false;
                if (rdev->msi_enabled)
                        pci_disable_msi(rdev->pdev);
        }
index 3a12bb0c0563daa412aa07ea61bf6ab0368fc4d5..417684daef4cb4009057caffb128b6c7533e85c6 100644 (file)
@@ -77,7 +77,7 @@ struct radeon_tv_mode_constants {
        unsigned pix_to_tv;
 };
 
-static const uint16_t hor_timing_NTSC[] = {
+static const uint16_t hor_timing_NTSC[MAX_H_CODE_TIMING_LEN] = {
        0x0007,
        0x003f,
        0x0263,
@@ -98,7 +98,7 @@ static const uint16_t hor_timing_NTSC[] = {
        0
 };
 
-static const uint16_t vert_timing_NTSC[] = {
+static const uint16_t vert_timing_NTSC[MAX_V_CODE_TIMING_LEN] = {
        0x2001,
        0x200d,
        0x1006,
@@ -115,7 +115,7 @@ static const uint16_t vert_timing_NTSC[] = {
        0
 };
 
-static const uint16_t hor_timing_PAL[] = {
+static const uint16_t hor_timing_PAL[MAX_H_CODE_TIMING_LEN] = {
        0x0007,
        0x0058,
        0x027c,
@@ -136,7 +136,7 @@ static const uint16_t hor_timing_PAL[] = {
        0
 };
 
-static const uint16_t vert_timing_PAL[] =      {
+static const uint16_t vert_timing_PAL[MAX_V_CODE_TIMING_LEN] = {
        0x2001,
        0x200c,
        0x1005,
@@ -623,9 +623,9 @@ void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
        }
        flicker_removal = (tmp + 500) / 1000;
 
-       if (flicker_removal < 3)
-               flicker_removal = 3;
-       for (i = 0; i < 6; ++i) {
+       if (flicker_removal < 2)
+               flicker_removal = 2;
+       for (i = 0; i < ARRAY_SIZE(SLOPE_limit); ++i) {
                if (flicker_removal == SLOPE_limit[i])
                        break;
        }
index 402369db5ba0daa78116d59476bbee160f401ff6..91cb041cb40dae8df07951808558f359d54f05c7 100644 (file)
@@ -46,32 +46,6 @@ struct radeon_device;
 #define to_radeon_encoder(x) container_of(x, struct radeon_encoder, base)
 #define to_radeon_framebuffer(x) container_of(x, struct radeon_framebuffer, base)
 
-enum radeon_connector_type {
-       CONNECTOR_NONE,
-       CONNECTOR_VGA,
-       CONNECTOR_DVI_I,
-       CONNECTOR_DVI_D,
-       CONNECTOR_DVI_A,
-       CONNECTOR_STV,
-       CONNECTOR_CTV,
-       CONNECTOR_LVDS,
-       CONNECTOR_DIGITAL,
-       CONNECTOR_SCART,
-       CONNECTOR_HDMI_TYPE_A,
-       CONNECTOR_HDMI_TYPE_B,
-       CONNECTOR_0XC,
-       CONNECTOR_0XD,
-       CONNECTOR_DIN,
-       CONNECTOR_DISPLAY_PORT,
-       CONNECTOR_UNSUPPORTED
-};
-
-enum radeon_dvi_type {
-       DVI_AUTO,
-       DVI_DIGITAL,
-       DVI_ANALOG
-};
-
 enum radeon_rmx_type {
        RMX_OFF,
        RMX_FULL,
index d9ffe1f56e8fc2aca4acc845b1e470ceb9642203..4e636de877b237b2ca5c53eb15b62d4008a939f6 100644 (file)
@@ -221,8 +221,9 @@ int radeon_bo_unpin(struct radeon_bo *bo)
 int radeon_bo_evict_vram(struct radeon_device *rdev)
 {
        if (rdev->flags & RADEON_IS_IGP) {
-               /* Useless to evict on IGP chips */
-               return 0;
+               if (rdev->mc.igp_sideport_enabled == false)
+                       /* Useless to evict on IGP chips */
+                       return 0;
        }
        return ttm_bo_evict_mm(&rdev->mman.bdev, TTM_PL_VRAM);
 }
diff --git a/drivers/gpu/drm/radeon/reg_srcs/r420 b/drivers/gpu/drm/radeon/reg_srcs/r420
new file mode 100644 (file)
index 0000000..989f7a0
--- /dev/null
@@ -0,0 +1,795 @@
+r420 0x4f60
+0x1434 SRC_Y_X
+0x1438 DST_Y_X
+0x143C DST_HEIGHT_WIDTH
+0x146C DP_GUI_MASTER_CNTL
+0x1474 BRUSH_Y_X
+0x1478 DP_BRUSH_BKGD_CLR
+0x147C DP_BRUSH_FRGD_CLR
+0x1480 BRUSH_DATA0
+0x1484 BRUSH_DATA1
+0x1598 DST_WIDTH_HEIGHT
+0x15C0 CLR_CMP_CNTL
+0x15C4 CLR_CMP_CLR_SRC
+0x15C8 CLR_CMP_CLR_DST
+0x15CC CLR_CMP_MSK
+0x15D8 DP_SRC_FRGD_CLR
+0x15DC DP_SRC_BKGD_CLR
+0x1600 DST_LINE_START
+0x1604 DST_LINE_END
+0x1608 DST_LINE_PATCOUNT
+0x16C0 DP_CNTL
+0x16CC DP_WRITE_MSK
+0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR
+0x16E8 DEFAULT_SC_BOTTOM_RIGHT
+0x16EC SC_TOP_LEFT
+0x16F0 SC_BOTTOM_RIGHT
+0x16F4 SRC_SC_BOTTOM_RIGHT
+0x1714 DSTCACHE_CTLSTAT
+0x1720 WAIT_UNTIL
+0x172C RBBM_GUICNTL
+0x1D98 VAP_VPORT_XSCALE
+0x1D9C VAP_VPORT_XOFFSET
+0x1DA0 VAP_VPORT_YSCALE
+0x1DA4 VAP_VPORT_YOFFSET
+0x1DA8 VAP_VPORT_ZSCALE
+0x1DAC VAP_VPORT_ZOFFSET
+0x2080 VAP_CNTL
+0x2090 VAP_OUT_VTX_FMT_0
+0x2094 VAP_OUT_VTX_FMT_1
+0x20B0 VAP_VTE_CNTL
+0x2138 VAP_VF_MIN_VTX_INDX
+0x2140 VAP_CNTL_STATUS
+0x2150 VAP_PROG_STREAM_CNTL_0
+0x2154 VAP_PROG_STREAM_CNTL_1
+0x2158 VAP_PROG_STREAM_CNTL_2
+0x215C VAP_PROG_STREAM_CNTL_3
+0x2160 VAP_PROG_STREAM_CNTL_4
+0x2164 VAP_PROG_STREAM_CNTL_5
+0x2168 VAP_PROG_STREAM_CNTL_6
+0x216C VAP_PROG_STREAM_CNTL_7
+0x2180 VAP_VTX_STATE_CNTL
+0x2184 VAP_VSM_VTX_ASSM
+0x2188 VAP_VTX_STATE_IND_REG_0
+0x218C VAP_VTX_STATE_IND_REG_1
+0x2190 VAP_VTX_STATE_IND_REG_2
+0x2194 VAP_VTX_STATE_IND_REG_3
+0x2198 VAP_VTX_STATE_IND_REG_4
+0x219C VAP_VTX_STATE_IND_REG_5
+0x21A0 VAP_VTX_STATE_IND_REG_6
+0x21A4 VAP_VTX_STATE_IND_REG_7
+0x21A8 VAP_VTX_STATE_IND_REG_8
+0x21AC VAP_VTX_STATE_IND_REG_9
+0x21B0 VAP_VTX_STATE_IND_REG_10
+0x21B4 VAP_VTX_STATE_IND_REG_11
+0x21B8 VAP_VTX_STATE_IND_REG_12
+0x21BC VAP_VTX_STATE_IND_REG_13
+0x21C0 VAP_VTX_STATE_IND_REG_14
+0x21C4 VAP_VTX_STATE_IND_REG_15
+0x21DC VAP_PSC_SGN_NORM_CNTL
+0x21E0 VAP_PROG_STREAM_CNTL_EXT_0
+0x21E4 VAP_PROG_STREAM_CNTL_EXT_1
+0x21E8 VAP_PROG_STREAM_CNTL_EXT_2
+0x21EC VAP_PROG_STREAM_CNTL_EXT_3
+0x21F0 VAP_PROG_STREAM_CNTL_EXT_4
+0x21F4 VAP_PROG_STREAM_CNTL_EXT_5
+0x21F8 VAP_PROG_STREAM_CNTL_EXT_6
+0x21FC VAP_PROG_STREAM_CNTL_EXT_7
+0x2200 VAP_PVS_VECTOR_INDX_REG
+0x2204 VAP_PVS_VECTOR_DATA_REG
+0x2208 VAP_PVS_VECTOR_DATA_REG_128
+0x221C VAP_CLIP_CNTL
+0x2220 VAP_GB_VERT_CLIP_ADJ
+0x2224 VAP_GB_VERT_DISC_ADJ
+0x2228 VAP_GB_HORZ_CLIP_ADJ
+0x222C VAP_GB_HORZ_DISC_ADJ
+0x2230 VAP_PVS_FLOW_CNTL_ADDRS_0
+0x2234 VAP_PVS_FLOW_CNTL_ADDRS_1
+0x2238 VAP_PVS_FLOW_CNTL_ADDRS_2
+0x223C VAP_PVS_FLOW_CNTL_ADDRS_3
+0x2240 VAP_PVS_FLOW_CNTL_ADDRS_4
+0x2244 VAP_PVS_FLOW_CNTL_ADDRS_5
+0x2248 VAP_PVS_FLOW_CNTL_ADDRS_6
+0x224C VAP_PVS_FLOW_CNTL_ADDRS_7
+0x2250 VAP_PVS_FLOW_CNTL_ADDRS_8
+0x2254 VAP_PVS_FLOW_CNTL_ADDRS_9
+0x2258 VAP_PVS_FLOW_CNTL_ADDRS_10
+0x225C VAP_PVS_FLOW_CNTL_ADDRS_11
+0x2260 VAP_PVS_FLOW_CNTL_ADDRS_12
+0x2264 VAP_PVS_FLOW_CNTL_ADDRS_13
+0x2268 VAP_PVS_FLOW_CNTL_ADDRS_14
+0x226C VAP_PVS_FLOW_CNTL_ADDRS_15
+0x2284 VAP_PVS_STATE_FLUSH_REG
+0x2288 VAP_PVS_VTX_TIMEOUT_REG
+0x2290 VAP_PVS_FLOW_CNTL_LOOP_INDEX_0
+0x2294 VAP_PVS_FLOW_CNTL_LOOP_INDEX_1
+0x2298 VAP_PVS_FLOW_CNTL_LOOP_INDEX_2
+0x229C VAP_PVS_FLOW_CNTL_LOOP_INDEX_3
+0x22A0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_4
+0x22A4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_5
+0x22A8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_6
+0x22AC VAP_PVS_FLOW_CNTL_LOOP_INDEX_7
+0x22B0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_8
+0x22B4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_9
+0x22B8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_10
+0x22BC VAP_PVS_FLOW_CNTL_LOOP_INDEX_11
+0x22C0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_12
+0x22C4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_13
+0x22C8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_14
+0x22CC VAP_PVS_FLOW_CNTL_LOOP_INDEX_15
+0x22D0 VAP_PVS_CODE_CNTL_0
+0x22D4 VAP_PVS_CONST_CNTL
+0x22D8 VAP_PVS_CODE_CNTL_1
+0x22DC VAP_PVS_FLOW_CNTL_OPC
+0x342C RB2D_DSTCACHE_CTLSTAT
+0x4000 GB_VAP_RASTER_VTX_FMT_0
+0x4004 GB_VAP_RASTER_VTX_FMT_1
+0x4008 GB_ENABLE
+0x401C GB_SELECT
+0x4020 GB_AA_CONFIG
+0x4024 GB_FIFO_SIZE
+0x4100 TX_INVALTAGS
+0x4200 GA_POINT_S0
+0x4204 GA_POINT_T0
+0x4208 GA_POINT_S1
+0x420C GA_POINT_T1
+0x4214 GA_TRIANGLE_STIPPLE
+0x421C GA_POINT_SIZE
+0x4230 GA_POINT_MINMAX
+0x4234 GA_LINE_CNTL
+0x4238 GA_LINE_STIPPLE_CONFIG
+0x4260 GA_LINE_STIPPLE_VALUE
+0x4264 GA_LINE_S0
+0x4268 GA_LINE_S1
+0x4278 GA_COLOR_CONTROL
+0x427C GA_SOLID_RG
+0x4280 GA_SOLID_BA
+0x4288 GA_POLY_MODE
+0x428C GA_ROUND_MODE
+0x4290 GA_OFFSET
+0x4294 GA_FOG_SCALE
+0x4298 GA_FOG_OFFSET
+0x42A0 SU_TEX_WRAP
+0x42A4 SU_POLY_OFFSET_FRONT_SCALE
+0x42A8 SU_POLY_OFFSET_FRONT_OFFSET
+0x42AC SU_POLY_OFFSET_BACK_SCALE
+0x42B0 SU_POLY_OFFSET_BACK_OFFSET
+0x42B4 SU_POLY_OFFSET_ENABLE
+0x42B8 SU_CULL_MODE
+0x42C0 SU_DEPTH_SCALE
+0x42C4 SU_DEPTH_OFFSET
+0x42C8 SU_REG_DEST
+0x4300 RS_COUNT
+0x4304 RS_INST_COUNT
+0x4310 RS_IP_0
+0x4314 RS_IP_1
+0x4318 RS_IP_2
+0x431C RS_IP_3
+0x4320 RS_IP_4
+0x4324 RS_IP_5
+0x4328 RS_IP_6
+0x432C RS_IP_7
+0x4330 RS_INST_0
+0x4334 RS_INST_1
+0x4338 RS_INST_2
+0x433C RS_INST_3
+0x4340 RS_INST_4
+0x4344 RS_INST_5
+0x4348 RS_INST_6
+0x434C RS_INST_7
+0x4350 RS_INST_8
+0x4354 RS_INST_9
+0x4358 RS_INST_10
+0x435C RS_INST_11
+0x4360 RS_INST_12
+0x4364 RS_INST_13
+0x4368 RS_INST_14
+0x436C RS_INST_15
+0x43A4 SC_HYPERZ_EN
+0x43A8 SC_EDGERULE
+0x43B0 SC_CLIP_0_A
+0x43B4 SC_CLIP_0_B
+0x43B8 SC_CLIP_1_A
+0x43BC SC_CLIP_1_B
+0x43C0 SC_CLIP_2_A
+0x43C4 SC_CLIP_2_B
+0x43C8 SC_CLIP_3_A
+0x43CC SC_CLIP_3_B
+0x43D0 SC_CLIP_RULE
+0x43E0 SC_SCISSOR0
+0x43E8 SC_SCREENDOOR
+0x4440 TX_FILTER1_0
+0x4444 TX_FILTER1_1
+0x4448 TX_FILTER1_2
+0x444C TX_FILTER1_3
+0x4450 TX_FILTER1_4
+0x4454 TX_FILTER1_5
+0x4458 TX_FILTER1_6
+0x445C TX_FILTER1_7
+0x4460 TX_FILTER1_8
+0x4464 TX_FILTER1_9
+0x4468 TX_FILTER1_10
+0x446C TX_FILTER1_11
+0x4470 TX_FILTER1_12
+0x4474 TX_FILTER1_13
+0x4478 TX_FILTER1_14
+0x447C TX_FILTER1_15
+0x4580 TX_CHROMA_KEY_0
+0x4584 TX_CHROMA_KEY_1
+0x4588 TX_CHROMA_KEY_2
+0x458C TX_CHROMA_KEY_3
+0x4590 TX_CHROMA_KEY_4
+0x4594 TX_CHROMA_KEY_5
+0x4598 TX_CHROMA_KEY_6
+0x459C TX_CHROMA_KEY_7
+0x45A0 TX_CHROMA_KEY_8
+0x45A4 TX_CHROMA_KEY_9
+0x45A8 TX_CHROMA_KEY_10
+0x45AC TX_CHROMA_KEY_11
+0x45B0 TX_CHROMA_KEY_12
+0x45B4 TX_CHROMA_KEY_13
+0x45B8 TX_CHROMA_KEY_14
+0x45BC TX_CHROMA_KEY_15
+0x45C0 TX_BORDER_COLOR_0
+0x45C4 TX_BORDER_COLOR_1
+0x45C8 TX_BORDER_COLOR_2
+0x45CC TX_BORDER_COLOR_3
+0x45D0 TX_BORDER_COLOR_4
+0x45D4 TX_BORDER_COLOR_5
+0x45D8 TX_BORDER_COLOR_6
+0x45DC TX_BORDER_COLOR_7
+0x45E0 TX_BORDER_COLOR_8
+0x45E4 TX_BORDER_COLOR_9
+0x45E8 TX_BORDER_COLOR_10
+0x45EC TX_BORDER_COLOR_11
+0x45F0 TX_BORDER_COLOR_12
+0x45F4 TX_BORDER_COLOR_13
+0x45F8 TX_BORDER_COLOR_14
+0x45FC TX_BORDER_COLOR_15
+0x4600 US_CONFIG
+0x4604 US_PIXSIZE
+0x4608 US_CODE_OFFSET
+0x460C US_RESET
+0x4610 US_CODE_ADDR_0
+0x4614 US_CODE_ADDR_1
+0x4618 US_CODE_ADDR_2
+0x461C US_CODE_ADDR_3
+0x4620 US_TEX_INST_0
+0x4624 US_TEX_INST_1
+0x4628 US_TEX_INST_2
+0x462C US_TEX_INST_3
+0x4630 US_TEX_INST_4
+0x4634 US_TEX_INST_5
+0x4638 US_TEX_INST_6
+0x463C US_TEX_INST_7
+0x4640 US_TEX_INST_8
+0x4644 US_TEX_INST_9
+0x4648 US_TEX_INST_10
+0x464C US_TEX_INST_11
+0x4650 US_TEX_INST_12
+0x4654 US_TEX_INST_13
+0x4658 US_TEX_INST_14
+0x465C US_TEX_INST_15
+0x4660 US_TEX_INST_16
+0x4664 US_TEX_INST_17
+0x4668 US_TEX_INST_18
+0x466C US_TEX_INST_19
+0x4670 US_TEX_INST_20
+0x4674 US_TEX_INST_21
+0x4678 US_TEX_INST_22
+0x467C US_TEX_INST_23
+0x4680 US_TEX_INST_24
+0x4684 US_TEX_INST_25
+0x4688 US_TEX_INST_26
+0x468C US_TEX_INST_27
+0x4690 US_TEX_INST_28
+0x4694 US_TEX_INST_29
+0x4698 US_TEX_INST_30
+0x469C US_TEX_INST_31
+0x46A4 US_OUT_FMT_0
+0x46A8 US_OUT_FMT_1
+0x46AC US_OUT_FMT_2
+0x46B0 US_OUT_FMT_3
+0x46B4 US_W_FMT
+0x46B8 US_CODE_BANK
+0x46BC US_CODE_EXT
+0x46C0 US_ALU_RGB_ADDR_0
+0x46C4 US_ALU_RGB_ADDR_1
+0x46C8 US_ALU_RGB_ADDR_2
+0x46CC US_ALU_RGB_ADDR_3
+0x46D0 US_ALU_RGB_ADDR_4
+0x46D4 US_ALU_RGB_ADDR_5
+0x46D8 US_ALU_RGB_ADDR_6
+0x46DC US_ALU_RGB_ADDR_7
+0x46E0 US_ALU_RGB_ADDR_8
+0x46E4 US_ALU_RGB_ADDR_9
+0x46E8 US_ALU_RGB_ADDR_10
+0x46EC US_ALU_RGB_ADDR_11
+0x46F0 US_ALU_RGB_ADDR_12
+0x46F4 US_ALU_RGB_ADDR_13
+0x46F8 US_ALU_RGB_ADDR_14
+0x46FC US_ALU_RGB_ADDR_15
+0x4700 US_ALU_RGB_ADDR_16
+0x4704 US_ALU_RGB_ADDR_17
+0x4708 US_ALU_RGB_ADDR_18
+0x470C US_ALU_RGB_ADDR_19
+0x4710 US_ALU_RGB_ADDR_20
+0x4714 US_ALU_RGB_ADDR_21
+0x4718 US_ALU_RGB_ADDR_22
+0x471C US_ALU_RGB_ADDR_23
+0x4720 US_ALU_RGB_ADDR_24
+0x4724 US_ALU_RGB_ADDR_25
+0x4728 US_ALU_RGB_ADDR_26
+0x472C US_ALU_RGB_ADDR_27
+0x4730 US_ALU_RGB_ADDR_28
+0x4734 US_ALU_RGB_ADDR_29
+0x4738 US_ALU_RGB_ADDR_30
+0x473C US_ALU_RGB_ADDR_31
+0x4740 US_ALU_RGB_ADDR_32
+0x4744 US_ALU_RGB_ADDR_33
+0x4748 US_ALU_RGB_ADDR_34
+0x474C US_ALU_RGB_ADDR_35
+0x4750 US_ALU_RGB_ADDR_36
+0x4754 US_ALU_RGB_ADDR_37
+0x4758 US_ALU_RGB_ADDR_38
+0x475C US_ALU_RGB_ADDR_39
+0x4760 US_ALU_RGB_ADDR_40
+0x4764 US_ALU_RGB_ADDR_41
+0x4768 US_ALU_RGB_ADDR_42
+0x476C US_ALU_RGB_ADDR_43
+0x4770 US_ALU_RGB_ADDR_44
+0x4774 US_ALU_RGB_ADDR_45
+0x4778 US_ALU_RGB_ADDR_46
+0x477C US_ALU_RGB_ADDR_47
+0x4780 US_ALU_RGB_ADDR_48
+0x4784 US_ALU_RGB_ADDR_49
+0x4788 US_ALU_RGB_ADDR_50
+0x478C US_ALU_RGB_ADDR_51
+0x4790 US_ALU_RGB_ADDR_52
+0x4794 US_ALU_RGB_ADDR_53
+0x4798 US_ALU_RGB_ADDR_54
+0x479C US_ALU_RGB_ADDR_55
+0x47A0 US_ALU_RGB_ADDR_56
+0x47A4 US_ALU_RGB_ADDR_57
+0x47A8 US_ALU_RGB_ADDR_58
+0x47AC US_ALU_RGB_ADDR_59
+0x47B0 US_ALU_RGB_ADDR_60
+0x47B4 US_ALU_RGB_ADDR_61
+0x47B8 US_ALU_RGB_ADDR_62
+0x47BC US_ALU_RGB_ADDR_63
+0x47C0 US_ALU_ALPHA_ADDR_0
+0x47C4 US_ALU_ALPHA_ADDR_1
+0x47C8 US_ALU_ALPHA_ADDR_2
+0x47CC US_ALU_ALPHA_ADDR_3
+0x47D0 US_ALU_ALPHA_ADDR_4
+0x47D4 US_ALU_ALPHA_ADDR_5
+0x47D8 US_ALU_ALPHA_ADDR_6
+0x47DC US_ALU_ALPHA_ADDR_7
+0x47E0 US_ALU_ALPHA_ADDR_8
+0x47E4 US_ALU_ALPHA_ADDR_9
+0x47E8 US_ALU_ALPHA_ADDR_10
+0x47EC US_ALU_ALPHA_ADDR_11
+0x47F0 US_ALU_ALPHA_ADDR_12
+0x47F4 US_ALU_ALPHA_ADDR_13
+0x47F8 US_ALU_ALPHA_ADDR_14
+0x47FC US_ALU_ALPHA_ADDR_15
+0x4800 US_ALU_ALPHA_ADDR_16
+0x4804 US_ALU_ALPHA_ADDR_17
+0x4808 US_ALU_ALPHA_ADDR_18
+0x480C US_ALU_ALPHA_ADDR_19
+0x4810 US_ALU_ALPHA_ADDR_20
+0x4814 US_ALU_ALPHA_ADDR_21
+0x4818 US_ALU_ALPHA_ADDR_22
+0x481C US_ALU_ALPHA_ADDR_23
+0x4820 US_ALU_ALPHA_ADDR_24
+0x4824 US_ALU_ALPHA_ADDR_25
+0x4828 US_ALU_ALPHA_ADDR_26
+0x482C US_ALU_ALPHA_ADDR_27
+0x4830 US_ALU_ALPHA_ADDR_28
+0x4834 US_ALU_ALPHA_ADDR_29
+0x4838 US_ALU_ALPHA_ADDR_30
+0x483C US_ALU_ALPHA_ADDR_31
+0x4840 US_ALU_ALPHA_ADDR_32
+0x4844 US_ALU_ALPHA_ADDR_33
+0x4848 US_ALU_ALPHA_ADDR_34
+0x484C US_ALU_ALPHA_ADDR_35
+0x4850 US_ALU_ALPHA_ADDR_36
+0x4854 US_ALU_ALPHA_ADDR_37
+0x4858 US_ALU_ALPHA_ADDR_38
+0x485C US_ALU_ALPHA_ADDR_39
+0x4860 US_ALU_ALPHA_ADDR_40
+0x4864 US_ALU_ALPHA_ADDR_41
+0x4868 US_ALU_ALPHA_ADDR_42
+0x486C US_ALU_ALPHA_ADDR_43
+0x4870 US_ALU_ALPHA_ADDR_44
+0x4874 US_ALU_ALPHA_ADDR_45
+0x4878 US_ALU_ALPHA_ADDR_46
+0x487C US_ALU_ALPHA_ADDR_47
+0x4880 US_ALU_ALPHA_ADDR_48
+0x4884 US_ALU_ALPHA_ADDR_49
+0x4888 US_ALU_ALPHA_ADDR_50
+0x488C US_ALU_ALPHA_ADDR_51
+0x4890 US_ALU_ALPHA_ADDR_52
+0x4894 US_ALU_ALPHA_ADDR_53
+0x4898 US_ALU_ALPHA_ADDR_54
+0x489C US_ALU_ALPHA_ADDR_55
+0x48A0 US_ALU_ALPHA_ADDR_56
+0x48A4 US_ALU_ALPHA_ADDR_57
+0x48A8 US_ALU_ALPHA_ADDR_58
+0x48AC US_ALU_ALPHA_ADDR_59
+0x48B0 US_ALU_ALPHA_ADDR_60
+0x48B4 US_ALU_ALPHA_ADDR_61
+0x48B8 US_ALU_ALPHA_ADDR_62
+0x48BC US_ALU_ALPHA_ADDR_63
+0x48C0 US_ALU_RGB_INST_0
+0x48C4 US_ALU_RGB_INST_1
+0x48C8 US_ALU_RGB_INST_2
+0x48CC US_ALU_RGB_INST_3
+0x48D0 US_ALU_RGB_INST_4
+0x48D4 US_ALU_RGB_INST_5
+0x48D8 US_ALU_RGB_INST_6
+0x48DC US_ALU_RGB_INST_7
+0x48E0 US_ALU_RGB_INST_8
+0x48E4 US_ALU_RGB_INST_9
+0x48E8 US_ALU_RGB_INST_10
+0x48EC US_ALU_RGB_INST_11
+0x48F0 US_ALU_RGB_INST_12
+0x48F4 US_ALU_RGB_INST_13
+0x48F8 US_ALU_RGB_INST_14
+0x48FC US_ALU_RGB_INST_15
+0x4900 US_ALU_RGB_INST_16
+0x4904 US_ALU_RGB_INST_17
+0x4908 US_ALU_RGB_INST_18
+0x490C US_ALU_RGB_INST_19
+0x4910 US_ALU_RGB_INST_20
+0x4914 US_ALU_RGB_INST_21
+0x4918 US_ALU_RGB_INST_22
+0x491C US_ALU_RGB_INST_23
+0x4920 US_ALU_RGB_INST_24
+0x4924 US_ALU_RGB_INST_25
+0x4928 US_ALU_RGB_INST_26
+0x492C US_ALU_RGB_INST_27
+0x4930 US_ALU_RGB_INST_28
+0x4934 US_ALU_RGB_INST_29
+0x4938 US_ALU_RGB_INST_30
+0x493C US_ALU_RGB_INST_31
+0x4940 US_ALU_RGB_INST_32
+0x4944 US_ALU_RGB_INST_33
+0x4948 US_ALU_RGB_INST_34
+0x494C US_ALU_RGB_INST_35
+0x4950 US_ALU_RGB_INST_36
+0x4954 US_ALU_RGB_INST_37
+0x4958 US_ALU_RGB_INST_38
+0x495C US_ALU_RGB_INST_39
+0x4960 US_ALU_RGB_INST_40
+0x4964 US_ALU_RGB_INST_41
+0x4968 US_ALU_RGB_INST_42
+0x496C US_ALU_RGB_INST_43
+0x4970 US_ALU_RGB_INST_44
+0x4974 US_ALU_RGB_INST_45
+0x4978 US_ALU_RGB_INST_46
+0x497C US_ALU_RGB_INST_47
+0x4980 US_ALU_RGB_INST_48
+0x4984 US_ALU_RGB_INST_49
+0x4988 US_ALU_RGB_INST_50
+0x498C US_ALU_RGB_INST_51
+0x4990 US_ALU_RGB_INST_52
+0x4994 US_ALU_RGB_INST_53
+0x4998 US_ALU_RGB_INST_54
+0x499C US_ALU_RGB_INST_55
+0x49A0 US_ALU_RGB_INST_56
+0x49A4 US_ALU_RGB_INST_57
+0x49A8 US_ALU_RGB_INST_58
+0x49AC US_ALU_RGB_INST_59
+0x49B0 US_ALU_RGB_INST_60
+0x49B4 US_ALU_RGB_INST_61
+0x49B8 US_ALU_RGB_INST_62
+0x49BC US_ALU_RGB_INST_63
+0x49C0 US_ALU_ALPHA_INST_0
+0x49C4 US_ALU_ALPHA_INST_1
+0x49C8 US_ALU_ALPHA_INST_2
+0x49CC US_ALU_ALPHA_INST_3
+0x49D0 US_ALU_ALPHA_INST_4
+0x49D4 US_ALU_ALPHA_INST_5
+0x49D8 US_ALU_ALPHA_INST_6
+0x49DC US_ALU_ALPHA_INST_7
+0x49E0 US_ALU_ALPHA_INST_8
+0x49E4 US_ALU_ALPHA_INST_9
+0x49E8 US_ALU_ALPHA_INST_10
+0x49EC US_ALU_ALPHA_INST_11
+0x49F0 US_ALU_ALPHA_INST_12
+0x49F4 US_ALU_ALPHA_INST_13
+0x49F8 US_ALU_ALPHA_INST_14
+0x49FC US_ALU_ALPHA_INST_15
+0x4A00 US_ALU_ALPHA_INST_16
+0x4A04 US_ALU_ALPHA_INST_17
+0x4A08 US_ALU_ALPHA_INST_18
+0x4A0C US_ALU_ALPHA_INST_19
+0x4A10 US_ALU_ALPHA_INST_20
+0x4A14 US_ALU_ALPHA_INST_21
+0x4A18 US_ALU_ALPHA_INST_22
+0x4A1C US_ALU_ALPHA_INST_23
+0x4A20 US_ALU_ALPHA_INST_24
+0x4A24 US_ALU_ALPHA_INST_25
+0x4A28 US_ALU_ALPHA_INST_26
+0x4A2C US_ALU_ALPHA_INST_27
+0x4A30 US_ALU_ALPHA_INST_28
+0x4A34 US_ALU_ALPHA_INST_29
+0x4A38 US_ALU_ALPHA_INST_30
+0x4A3C US_ALU_ALPHA_INST_31
+0x4A40 US_ALU_ALPHA_INST_32
+0x4A44 US_ALU_ALPHA_INST_33
+0x4A48 US_ALU_ALPHA_INST_34
+0x4A4C US_ALU_ALPHA_INST_35
+0x4A50 US_ALU_ALPHA_INST_36
+0x4A54 US_ALU_ALPHA_INST_37
+0x4A58 US_ALU_ALPHA_INST_38
+0x4A5C US_ALU_ALPHA_INST_39
+0x4A60 US_ALU_ALPHA_INST_40
+0x4A64 US_ALU_ALPHA_INST_41
+0x4A68 US_ALU_ALPHA_INST_42
+0x4A6C US_ALU_ALPHA_INST_43
+0x4A70 US_ALU_ALPHA_INST_44
+0x4A74 US_ALU_ALPHA_INST_45
+0x4A78 US_ALU_ALPHA_INST_46
+0x4A7C US_ALU_ALPHA_INST_47
+0x4A80 US_ALU_ALPHA_INST_48
+0x4A84 US_ALU_ALPHA_INST_49
+0x4A88 US_ALU_ALPHA_INST_50
+0x4A8C US_ALU_ALPHA_INST_51
+0x4A90 US_ALU_ALPHA_INST_52
+0x4A94 US_ALU_ALPHA_INST_53
+0x4A98 US_ALU_ALPHA_INST_54
+0x4A9C US_ALU_ALPHA_INST_55
+0x4AA0 US_ALU_ALPHA_INST_56
+0x4AA4 US_ALU_ALPHA_INST_57
+0x4AA8 US_ALU_ALPHA_INST_58
+0x4AAC US_ALU_ALPHA_INST_59
+0x4AB0 US_ALU_ALPHA_INST_60
+0x4AB4 US_ALU_ALPHA_INST_61
+0x4AB8 US_ALU_ALPHA_INST_62
+0x4ABC US_ALU_ALPHA_INST_63
+0x4AC0 US_ALU_EXT_ADDR_0
+0x4AC4 US_ALU_EXT_ADDR_1
+0x4AC8 US_ALU_EXT_ADDR_2
+0x4ACC US_ALU_EXT_ADDR_3
+0x4AD0 US_ALU_EXT_ADDR_4
+0x4AD4 US_ALU_EXT_ADDR_5
+0x4AD8 US_ALU_EXT_ADDR_6
+0x4ADC US_ALU_EXT_ADDR_7
+0x4AE0 US_ALU_EXT_ADDR_8
+0x4AE4 US_ALU_EXT_ADDR_9
+0x4AE8 US_ALU_EXT_ADDR_10
+0x4AEC US_ALU_EXT_ADDR_11
+0x4AF0 US_ALU_EXT_ADDR_12
+0x4AF4 US_ALU_EXT_ADDR_13
+0x4AF8 US_ALU_EXT_ADDR_14
+0x4AFC US_ALU_EXT_ADDR_15
+0x4B00 US_ALU_EXT_ADDR_16
+0x4B04 US_ALU_EXT_ADDR_17
+0x4B08 US_ALU_EXT_ADDR_18
+0x4B0C US_ALU_EXT_ADDR_19
+0x4B10 US_ALU_EXT_ADDR_20
+0x4B14 US_ALU_EXT_ADDR_21
+0x4B18 US_ALU_EXT_ADDR_22
+0x4B1C US_ALU_EXT_ADDR_23
+0x4B20 US_ALU_EXT_ADDR_24
+0x4B24 US_ALU_EXT_ADDR_25
+0x4B28 US_ALU_EXT_ADDR_26
+0x4B2C US_ALU_EXT_ADDR_27
+0x4B30 US_ALU_EXT_ADDR_28
+0x4B34 US_ALU_EXT_ADDR_29
+0x4B38 US_ALU_EXT_ADDR_30
+0x4B3C US_ALU_EXT_ADDR_31
+0x4B40 US_ALU_EXT_ADDR_32
+0x4B44 US_ALU_EXT_ADDR_33
+0x4B48 US_ALU_EXT_ADDR_34
+0x4B4C US_ALU_EXT_ADDR_35
+0x4B50 US_ALU_EXT_ADDR_36
+0x4B54 US_ALU_EXT_ADDR_37
+0x4B58 US_ALU_EXT_ADDR_38
+0x4B5C US_ALU_EXT_ADDR_39
+0x4B60 US_ALU_EXT_ADDR_40
+0x4B64 US_ALU_EXT_ADDR_41
+0x4B68 US_ALU_EXT_ADDR_42
+0x4B6C US_ALU_EXT_ADDR_43
+0x4B70 US_ALU_EXT_ADDR_44
+0x4B74 US_ALU_EXT_ADDR_45
+0x4B78 US_ALU_EXT_ADDR_46
+0x4B7C US_ALU_EXT_ADDR_47
+0x4B80 US_ALU_EXT_ADDR_48
+0x4B84 US_ALU_EXT_ADDR_49
+0x4B88 US_ALU_EXT_ADDR_50
+0x4B8C US_ALU_EXT_ADDR_51
+0x4B90 US_ALU_EXT_ADDR_52
+0x4B94 US_ALU_EXT_ADDR_53
+0x4B98 US_ALU_EXT_ADDR_54
+0x4B9C US_ALU_EXT_ADDR_55
+0x4BA0 US_ALU_EXT_ADDR_56
+0x4BA4 US_ALU_EXT_ADDR_57
+0x4BA8 US_ALU_EXT_ADDR_58
+0x4BAC US_ALU_EXT_ADDR_59
+0x4BB0 US_ALU_EXT_ADDR_60
+0x4BB4 US_ALU_EXT_ADDR_61
+0x4BB8 US_ALU_EXT_ADDR_62
+0x4BBC US_ALU_EXT_ADDR_63
+0x4BC0 FG_FOG_BLEND
+0x4BC4 FG_FOG_FACTOR
+0x4BC8 FG_FOG_COLOR_R
+0x4BCC FG_FOG_COLOR_G
+0x4BD0 FG_FOG_COLOR_B
+0x4BD4 FG_ALPHA_FUNC
+0x4BD8 FG_DEPTH_SRC
+0x4C00 US_ALU_CONST_R_0
+0x4C04 US_ALU_CONST_G_0
+0x4C08 US_ALU_CONST_B_0
+0x4C0C US_ALU_CONST_A_0
+0x4C10 US_ALU_CONST_R_1
+0x4C14 US_ALU_CONST_G_1
+0x4C18 US_ALU_CONST_B_1
+0x4C1C US_ALU_CONST_A_1
+0x4C20 US_ALU_CONST_R_2
+0x4C24 US_ALU_CONST_G_2
+0x4C28 US_ALU_CONST_B_2
+0x4C2C US_ALU_CONST_A_2
+0x4C30 US_ALU_CONST_R_3
+0x4C34 US_ALU_CONST_G_3
+0x4C38 US_ALU_CONST_B_3
+0x4C3C US_ALU_CONST_A_3
+0x4C40 US_ALU_CONST_R_4
+0x4C44 US_ALU_CONST_G_4
+0x4C48 US_ALU_CONST_B_4
+0x4C4C US_ALU_CONST_A_4
+0x4C50 US_ALU_CONST_R_5
+0x4C54 US_ALU_CONST_G_5
+0x4C58 US_ALU_CONST_B_5
+0x4C5C US_ALU_CONST_A_5
+0x4C60 US_ALU_CONST_R_6
+0x4C64 US_ALU_CONST_G_6
+0x4C68 US_ALU_CONST_B_6
+0x4C6C US_ALU_CONST_A_6
+0x4C70 US_ALU_CONST_R_7
+0x4C74 US_ALU_CONST_G_7
+0x4C78 US_ALU_CONST_B_7
+0x4C7C US_ALU_CONST_A_7
+0x4C80 US_ALU_CONST_R_8
+0x4C84 US_ALU_CONST_G_8
+0x4C88 US_ALU_CONST_B_8
+0x4C8C US_ALU_CONST_A_8
+0x4C90 US_ALU_CONST_R_9
+0x4C94 US_ALU_CONST_G_9
+0x4C98 US_ALU_CONST_B_9
+0x4C9C US_ALU_CONST_A_9
+0x4CA0 US_ALU_CONST_R_10
+0x4CA4 US_ALU_CONST_G_10
+0x4CA8 US_ALU_CONST_B_10
+0x4CAC US_ALU_CONST_A_10
+0x4CB0 US_ALU_CONST_R_11
+0x4CB4 US_ALU_CONST_G_11
+0x4CB8 US_ALU_CONST_B_11
+0x4CBC US_ALU_CONST_A_11
+0x4CC0 US_ALU_CONST_R_12
+0x4CC4 US_ALU_CONST_G_12
+0x4CC8 US_ALU_CONST_B_12
+0x4CCC US_ALU_CONST_A_12
+0x4CD0 US_ALU_CONST_R_13
+0x4CD4 US_ALU_CONST_G_13
+0x4CD8 US_ALU_CONST_B_13
+0x4CDC US_ALU_CONST_A_13
+0x4CE0 US_ALU_CONST_R_14
+0x4CE4 US_ALU_CONST_G_14
+0x4CE8 US_ALU_CONST_B_14
+0x4CEC US_ALU_CONST_A_14
+0x4CF0 US_ALU_CONST_R_15
+0x4CF4 US_ALU_CONST_G_15
+0x4CF8 US_ALU_CONST_B_15
+0x4CFC US_ALU_CONST_A_15
+0x4D00 US_ALU_CONST_R_16
+0x4D04 US_ALU_CONST_G_16
+0x4D08 US_ALU_CONST_B_16
+0x4D0C US_ALU_CONST_A_16
+0x4D10 US_ALU_CONST_R_17
+0x4D14 US_ALU_CONST_G_17
+0x4D18 US_ALU_CONST_B_17
+0x4D1C US_ALU_CONST_A_17
+0x4D20 US_ALU_CONST_R_18
+0x4D24 US_ALU_CONST_G_18
+0x4D28 US_ALU_CONST_B_18
+0x4D2C US_ALU_CONST_A_18
+0x4D30 US_ALU_CONST_R_19
+0x4D34 US_ALU_CONST_G_19
+0x4D38 US_ALU_CONST_B_19
+0x4D3C US_ALU_CONST_A_19
+0x4D40 US_ALU_CONST_R_20
+0x4D44 US_ALU_CONST_G_20
+0x4D48 US_ALU_CONST_B_20
+0x4D4C US_ALU_CONST_A_20
+0x4D50 US_ALU_CONST_R_21
+0x4D54 US_ALU_CONST_G_21
+0x4D58 US_ALU_CONST_B_21
+0x4D5C US_ALU_CONST_A_21
+0x4D60 US_ALU_CONST_R_22
+0x4D64 US_ALU_CONST_G_22
+0x4D68 US_ALU_CONST_B_22
+0x4D6C US_ALU_CONST_A_22
+0x4D70 US_ALU_CONST_R_23
+0x4D74 US_ALU_CONST_G_23
+0x4D78 US_ALU_CONST_B_23
+0x4D7C US_ALU_CONST_A_23
+0x4D80 US_ALU_CONST_R_24
+0x4D84 US_ALU_CONST_G_24
+0x4D88 US_ALU_CONST_B_24
+0x4D8C US_ALU_CONST_A_24
+0x4D90 US_ALU_CONST_R_25
+0x4D94 US_ALU_CONST_G_25
+0x4D98 US_ALU_CONST_B_25
+0x4D9C US_ALU_CONST_A_25
+0x4DA0 US_ALU_CONST_R_26
+0x4DA4 US_ALU_CONST_G_26
+0x4DA8 US_ALU_CONST_B_26
+0x4DAC US_ALU_CONST_A_26
+0x4DB0 US_ALU_CONST_R_27
+0x4DB4 US_ALU_CONST_G_27
+0x4DB8 US_ALU_CONST_B_27
+0x4DBC US_ALU_CONST_A_27
+0x4DC0 US_ALU_CONST_R_28
+0x4DC4 US_ALU_CONST_G_28
+0x4DC8 US_ALU_CONST_B_28
+0x4DCC US_ALU_CONST_A_28
+0x4DD0 US_ALU_CONST_R_29
+0x4DD4 US_ALU_CONST_G_29
+0x4DD8 US_ALU_CONST_B_29
+0x4DDC US_ALU_CONST_A_29
+0x4DE0 US_ALU_CONST_R_30
+0x4DE4 US_ALU_CONST_G_30
+0x4DE8 US_ALU_CONST_B_30
+0x4DEC US_ALU_CONST_A_30
+0x4DF0 US_ALU_CONST_R_31
+0x4DF4 US_ALU_CONST_G_31
+0x4DF8 US_ALU_CONST_B_31
+0x4DFC US_ALU_CONST_A_31
+0x4E04 RB3D_BLENDCNTL_R3
+0x4E08 RB3D_ABLENDCNTL_R3
+0x4E0C RB3D_COLOR_CHANNEL_MASK
+0x4E10 RB3D_CONSTANT_COLOR
+0x4E14 RB3D_COLOR_CLEAR_VALUE
+0x4E18 RB3D_ROPCNTL_R3
+0x4E1C RB3D_CLRCMP_FLIPE_R3
+0x4E20 RB3D_CLRCMP_CLR_R3
+0x4E24 RB3D_CLRCMP_MSK_R3
+0x4E48 RB3D_DEBUG_CTL
+0x4E4C RB3D_DSTCACHE_CTLSTAT_R3
+0x4E50 RB3D_DITHER_CTL
+0x4E54 RB3D_CMASK_OFFSET0
+0x4E58 RB3D_CMASK_OFFSET1
+0x4E5C RB3D_CMASK_OFFSET2
+0x4E60 RB3D_CMASK_OFFSET3
+0x4E64 RB3D_CMASK_PITCH0
+0x4E68 RB3D_CMASK_PITCH1
+0x4E6C RB3D_CMASK_PITCH2
+0x4E70 RB3D_CMASK_PITCH3
+0x4E74 RB3D_CMASK_WRINDEX
+0x4E78 RB3D_CMASK_DWORD
+0x4E7C RB3D_CMASK_RDINDEX
+0x4E80 RB3D_AARESOLVE_OFFSET
+0x4E84 RB3D_AARESOLVE_PITCH
+0x4E88 RB3D_AARESOLVE_CTL
+0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD
+0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD
+0x4F04 ZB_ZSTENCILCNTL
+0x4F08 ZB_STENCILREFMASK
+0x4F14 ZB_ZTOP
+0x4F18 ZB_ZCACHE_CTLSTAT
+0x4F1C ZB_BW_CNTL
+0x4F28 ZB_DEPTHCLEARVALUE
+0x4F30 ZB_ZMASK_OFFSET
+0x4F34 ZB_ZMASK_PITCH
+0x4F38 ZB_ZMASK_WRINDEX
+0x4F3C ZB_ZMASK_DWORD
+0x4F40 ZB_ZMASK_RDINDEX
+0x4F44 ZB_HIZ_OFFSET
+0x4F48 ZB_HIZ_WRINDEX
+0x4F4C ZB_HIZ_DWORD
+0x4F50 ZB_HIZ_RDINDEX
+0x4F54 ZB_HIZ_PITCH
+0x4F58 ZB_ZPASS_DATA
index 8e3c0b807add9f485afedde7a294357e51e4eddd..6801b865d1c4fca2cda34bc580dad3039acdb521 100644 (file)
@@ -153,7 +153,7 @@ rs600 0x6d40
 0x42A4 SU_POLY_OFFSET_FRONT_SCALE
 0x42A8 SU_POLY_OFFSET_FRONT_OFFSET
 0x42AC SU_POLY_OFFSET_BACK_SCALE
-0x42B0 SU_POLY_OFFSET_BACK_OFFSET 
+0x42B0 SU_POLY_OFFSET_BACK_OFFSET
 0x42B4 SU_POLY_OFFSET_ENABLE
 0x42B8 SU_CULL_MODE
 0x42C0 SU_DEPTH_SCALE
@@ -291,6 +291,8 @@ rs600 0x6d40
 0x46AC US_OUT_FMT_2
 0x46B0 US_OUT_FMT_3
 0x46B4 US_W_FMT
+0x46B8 US_CODE_BANK
+0x46BC US_CODE_EXT
 0x46C0 US_ALU_RGB_ADDR_0
 0x46C4 US_ALU_RGB_ADDR_1
 0x46C8 US_ALU_RGB_ADDR_2
@@ -547,6 +549,70 @@ rs600 0x6d40
 0x4AB4 US_ALU_ALPHA_INST_61
 0x4AB8 US_ALU_ALPHA_INST_62
 0x4ABC US_ALU_ALPHA_INST_63
+0x4AC0 US_ALU_EXT_ADDR_0
+0x4AC4 US_ALU_EXT_ADDR_1
+0x4AC8 US_ALU_EXT_ADDR_2
+0x4ACC US_ALU_EXT_ADDR_3
+0x4AD0 US_ALU_EXT_ADDR_4
+0x4AD4 US_ALU_EXT_ADDR_5
+0x4AD8 US_ALU_EXT_ADDR_6
+0x4ADC US_ALU_EXT_ADDR_7
+0x4AE0 US_ALU_EXT_ADDR_8
+0x4AE4 US_ALU_EXT_ADDR_9
+0x4AE8 US_ALU_EXT_ADDR_10
+0x4AEC US_ALU_EXT_ADDR_11
+0x4AF0 US_ALU_EXT_ADDR_12
+0x4AF4 US_ALU_EXT_ADDR_13
+0x4AF8 US_ALU_EXT_ADDR_14
+0x4AFC US_ALU_EXT_ADDR_15
+0x4B00 US_ALU_EXT_ADDR_16
+0x4B04 US_ALU_EXT_ADDR_17
+0x4B08 US_ALU_EXT_ADDR_18
+0x4B0C US_ALU_EXT_ADDR_19
+0x4B10 US_ALU_EXT_ADDR_20
+0x4B14 US_ALU_EXT_ADDR_21
+0x4B18 US_ALU_EXT_ADDR_22
+0x4B1C US_ALU_EXT_ADDR_23
+0x4B20 US_ALU_EXT_ADDR_24
+0x4B24 US_ALU_EXT_ADDR_25
+0x4B28 US_ALU_EXT_ADDR_26
+0x4B2C US_ALU_EXT_ADDR_27
+0x4B30 US_ALU_EXT_ADDR_28
+0x4B34 US_ALU_EXT_ADDR_29
+0x4B38 US_ALU_EXT_ADDR_30
+0x4B3C US_ALU_EXT_ADDR_31
+0x4B40 US_ALU_EXT_ADDR_32
+0x4B44 US_ALU_EXT_ADDR_33
+0x4B48 US_ALU_EXT_ADDR_34
+0x4B4C US_ALU_EXT_ADDR_35
+0x4B50 US_ALU_EXT_ADDR_36
+0x4B54 US_ALU_EXT_ADDR_37
+0x4B58 US_ALU_EXT_ADDR_38
+0x4B5C US_ALU_EXT_ADDR_39
+0x4B60 US_ALU_EXT_ADDR_40
+0x4B64 US_ALU_EXT_ADDR_41
+0x4B68 US_ALU_EXT_ADDR_42
+0x4B6C US_ALU_EXT_ADDR_43
+0x4B70 US_ALU_EXT_ADDR_44
+0x4B74 US_ALU_EXT_ADDR_45
+0x4B78 US_ALU_EXT_ADDR_46
+0x4B7C US_ALU_EXT_ADDR_47
+0x4B80 US_ALU_EXT_ADDR_48
+0x4B84 US_ALU_EXT_ADDR_49
+0x4B88 US_ALU_EXT_ADDR_50
+0x4B8C US_ALU_EXT_ADDR_51
+0x4B90 US_ALU_EXT_ADDR_52
+0x4B94 US_ALU_EXT_ADDR_53
+0x4B98 US_ALU_EXT_ADDR_54
+0x4B9C US_ALU_EXT_ADDR_55
+0x4BA0 US_ALU_EXT_ADDR_56
+0x4BA4 US_ALU_EXT_ADDR_57
+0x4BA8 US_ALU_EXT_ADDR_58
+0x4BAC US_ALU_EXT_ADDR_59
+0x4BB0 US_ALU_EXT_ADDR_60
+0x4BB4 US_ALU_EXT_ADDR_61
+0x4BB8 US_ALU_EXT_ADDR_62
+0x4BBC US_ALU_EXT_ADDR_63
 0x4BC0 FG_FOG_BLEND
 0x4BC4 FG_FOG_FACTOR
 0x4BC8 FG_FOG_COLOR_R
index 0102a0d5735ca9e232acfe4f225a1a40fdb8dcdc..38abf63bf2cd84a47025ce6130457c16ca258381 100644 (file)
@@ -161,7 +161,12 @@ rv515 0x6d40
 0x401C GB_SELECT
 0x4020 GB_AA_CONFIG
 0x4024 GB_FIFO_SIZE
+0x4028 GB_Z_PEQ_CONFIG
 0x4100 TX_INVALTAGS
+0x4114 SU_TEX_WRAP_PS3
+0x4118 PS3_ENABLE
+0x411c PS3_VTX_FMT
+0x4120 PS3_TEX_SOURCE
 0x4200 GA_POINT_S0
 0x4204 GA_POINT_T0
 0x4208 GA_POINT_S1
@@ -171,6 +176,7 @@ rv515 0x6d40
 0x4230 GA_POINT_MINMAX
 0x4234 GA_LINE_CNTL
 0x4238 GA_LINE_STIPPLE_CONFIG
+0x4258 GA_COLOR_CONTROL_PS3
 0x4260 GA_LINE_STIPPLE_VALUE
 0x4264 GA_LINE_S0
 0x4268 GA_LINE_S1
index 368415df5f3abe954494e58f239708c1c5a1557b..9f5418983e2a5f30af108287aaa18f19d6bc70b3 100644 (file)
@@ -356,6 +356,7 @@ static int rs400_mc_init(struct radeon_device *rdev)
        rdev->mc.vram_location = G_00015C_MC_FB_START(tmp) << 16;
        rdev->mc.gtt_location = 0xFFFFFFFFUL;
        r = radeon_mc_setup(rdev);
+       rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev);
        if (r)
                return r;
        return 0;
@@ -395,6 +396,7 @@ static int rs400_startup(struct radeon_device *rdev)
                return r;
        /* Enable IRQ */
        r100_irq_set(rdev);
+       rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
index 4f8ea4260572d83ad562b034d4550b8214c4cd01..d5255751e7b365b5c987561f9f3bebb74e87a441 100644 (file)
@@ -56,6 +56,7 @@ int rs600_mc_init(struct radeon_device *rdev)
        rdev->mc.vram_location = G_000004_MC_FB_START(tmp) << 16;
        rdev->mc.gtt_location = 0xffffffffUL;
        r = radeon_mc_setup(rdev);
+       rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
        if (r)
                return r;
        return 0;
@@ -134,7 +135,8 @@ void rs600_hpd_init(struct radeon_device *rdev)
                        break;
                }
        }
-       rs600_irq_set(rdev);
+       if (rdev->irq.installed)
+               rs600_irq_set(rdev);
 }
 
 void rs600_hpd_fini(struct radeon_device *rdev)
@@ -315,6 +317,11 @@ int rs600_irq_set(struct radeon_device *rdev)
        u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) &
                ~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1);
 
+       if (!rdev->irq.installed) {
+               WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n");
+               WREG32(R_000040_GEN_INT_CNTL, 0);
+               return -EINVAL;
+       }
        if (rdev->irq.sw_int) {
                tmp |= S_000040_SW_INT_EN(1);
        }
@@ -396,7 +403,7 @@ int rs600_irq_process(struct radeon_device *rdev)
        }
        while (status || r500_disp_int) {
                /* SW interrupt */
-               if (G_000040_SW_INT_EN(status))
+               if (G_000044_SW_INT(status))
                        radeon_fence_process(rdev);
                /* Vertical blank interrupts */
                if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int))
@@ -553,6 +560,7 @@ static int rs600_startup(struct radeon_device *rdev)
                return r;
        /* Enable IRQ */
        rs600_irq_set(rdev);
+       rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
index 1e22f52d6039ff67c369b3317a997d0881ac094d..cd31da913771d898c3d68946f0f8f3399becf382 100644 (file)
@@ -172,6 +172,7 @@ static int rs690_mc_init(struct radeon_device *rdev)
        rdev->mc.vram_location = G_000100_MC_FB_START(tmp) << 16;
        rdev->mc.gtt_location = 0xFFFFFFFFUL;
        r = radeon_mc_setup(rdev);
+       rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
        if (r)
                return r;
        return 0;
@@ -625,6 +626,7 @@ static int rs690_startup(struct radeon_device *rdev)
                return r;
        /* Enable IRQ */
        rs600_irq_set(rdev);
+       rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
index 59632a506b46cc53ad6f74e8ca8f527662f6758c..62756717b0449bdbc3be45ec40f4cd2bc99e1058 100644 (file)
@@ -479,6 +479,7 @@ static int rv515_startup(struct radeon_device *rdev)
        }
        /* Enable IRQ */
        rs600_irq_set(rdev);
+       rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
index 3bcb66e52786c3ef0018d8e2c43bf29d3825b154..59c71245fb91e66d0429dd31cb8da36ef57015b6 100644 (file)
@@ -1096,8 +1096,7 @@ void rv770_fini(struct radeon_device *rdev)
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_clocks_fini(rdev);
-       if (rdev->flags & RADEON_IS_AGP)
-               radeon_agp_fini(rdev);
+       radeon_agp_fini(rdev);
        radeon_bo_fini(rdev);
        radeon_atombios_fini(rdev);
        kfree(rdev->bios);
index 46c3c566307ea3feedc9a2e439dd741f49fa7167..68cf87749a42f9be49e6ac8be6bb4d1669612d9b 100644 (file)
@@ -392,7 +392,7 @@ config SENSORS_GL520SM
 
 config SENSORS_CORETEMP
        tristate "Intel Core/Core2/Atom temperature sensor"
-       depends on X86 && EXPERIMENTAL
+       depends on X86 && PCI && EXPERIMENTAL
        help
          If you say yes here you get support for the temperature
          sensor inside your CPU. Most of the family 6 CPUs
@@ -792,6 +792,16 @@ config SENSORS_ADS7828
          This driver can also be built as a module.  If so, the module
          will be called ads7828.
 
+config SENSORS_AMC6821
+       tristate "Texas Instruments AMC6821"
+       depends on I2C  && EXPERIMENTAL
+       help
+         If you say yes here you get support for the Texas Instruments
+         AMC6821 hardware monitoring chips.
+
+         This driver can also be build as a module.  If so, the module
+         will be called amc6821.
+
 config SENSORS_THMC50
        tristate "Texas Instruments THMC50 / Analog Devices ADM1022"
        depends on I2C && EXPERIMENTAL
index 450c8e89427794558fe34feed87004cc3c8605e0..4bc215c0953f08cf515c5bb8ca3d01c192c6346f 100644 (file)
@@ -86,6 +86,7 @@ obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
 obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
+obj-$(CONFIG_SENSORS_AMC6821)  += amc6821.o
 obj-$(CONFIG_SENSORS_THMC50)   += thmc50.o
 obj-$(CONFIG_SENSORS_TMP401)   += tmp401.o
 obj-$(CONFIG_SENSORS_TMP421)   += tmp421.o
index a1a7ef14b519f68f80ae5c91f4169c2b5ff110fc..a31e77c776aeee3d0f14409710e5439de44f605b 100644 (file)
@@ -94,7 +94,7 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
 #define                ADT7462_PIN24_SHIFT             6
 #define                ADT7462_PIN26_VOLT_INPUT        0x08
 #define                ADT7462_PIN25_VOLT_INPUT        0x20
-#define                ADT7462_PIN28_SHIFT             6       /* cfg3 */
+#define                ADT7462_PIN28_SHIFT             4       /* cfg3 */
 #define                ADT7462_PIN28_VOLT              0x5
 
 #define ADT7462_REG_ALARM1                     0xB8
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
new file mode 100644 (file)
index 0000000..1c89d92
--- /dev/null
@@ -0,0 +1,1116 @@
+/*
+       amc6821.c - Part of lm_sensors, Linux kernel modules for hardware
+       monitoring
+       Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si>
+
+       Based on max6650.c:
+       Copyright (C) 2007 Hans J. Koch <hjk@linutronix.de>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the Free Software
+       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include <linux/kernel.h>      /* Needed for KERN_INFO */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+
+/*
+ * Addresses to scan.
+ */
+
+static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e,
+       0x4c, 0x4d, 0x4e, I2C_CLIENT_END};
+
+
+
+/*
+ * Insmod parameters
+ */
+
+static int pwminv = 0; /*Inverted PWM output. */
+module_param(pwminv, int, S_IRUGO);
+
+static int init = 1; /*Power-on initialization.*/
+module_param(init, int, S_IRUGO);
+
+
+enum chips { amc6821 };
+
+#define AMC6821_REG_DEV_ID 0x3D
+#define AMC6821_REG_COMP_ID 0x3E
+#define AMC6821_REG_CONF1 0x00
+#define AMC6821_REG_CONF2 0x01
+#define AMC6821_REG_CONF3 0x3F
+#define AMC6821_REG_CONF4 0x04
+#define AMC6821_REG_STAT1 0x02
+#define AMC6821_REG_STAT2 0x03
+#define AMC6821_REG_TDATA_LOW 0x08
+#define AMC6821_REG_TDATA_HI 0x09
+#define AMC6821_REG_LTEMP_HI 0x0A
+#define AMC6821_REG_RTEMP_HI 0x0B
+#define AMC6821_REG_LTEMP_LIMIT_MIN 0x15
+#define AMC6821_REG_LTEMP_LIMIT_MAX 0x14
+#define AMC6821_REG_RTEMP_LIMIT_MIN 0x19
+#define AMC6821_REG_RTEMP_LIMIT_MAX 0x18
+#define AMC6821_REG_LTEMP_CRIT 0x1B
+#define AMC6821_REG_RTEMP_CRIT 0x1D
+#define AMC6821_REG_PSV_TEMP 0x1C
+#define AMC6821_REG_DCY 0x22
+#define AMC6821_REG_LTEMP_FAN_CTRL 0x24
+#define AMC6821_REG_RTEMP_FAN_CTRL 0x25
+#define AMC6821_REG_DCY_LOW_TEMP 0x21
+
+#define AMC6821_REG_TACH_LLIMITL 0x10
+#define AMC6821_REG_TACH_LLIMITH 0x11
+#define AMC6821_REG_TACH_HLIMITL 0x12
+#define AMC6821_REG_TACH_HLIMITH 0x13
+
+#define AMC6821_CONF1_START 0x01
+#define AMC6821_CONF1_FAN_INT_EN 0x02
+#define AMC6821_CONF1_FANIE 0x04
+#define AMC6821_CONF1_PWMINV 0x08
+#define AMC6821_CONF1_FAN_FAULT_EN 0x10
+#define AMC6821_CONF1_FDRC0 0x20
+#define AMC6821_CONF1_FDRC1 0x40
+#define AMC6821_CONF1_THERMOVIE 0x80
+
+#define AMC6821_CONF2_PWM_EN 0x01
+#define AMC6821_CONF2_TACH_MODE 0x02
+#define AMC6821_CONF2_TACH_EN 0x04
+#define AMC6821_CONF2_RTFIE 0x08
+#define AMC6821_CONF2_LTOIE 0x10
+#define AMC6821_CONF2_RTOIE 0x20
+#define AMC6821_CONF2_PSVIE 0x40
+#define AMC6821_CONF2_RST 0x80
+
+#define AMC6821_CONF3_THERM_FAN_EN 0x80
+#define AMC6821_CONF3_REV_MASK 0x0F
+
+#define AMC6821_CONF4_OVREN 0x10
+#define AMC6821_CONF4_TACH_FAST 0x20
+#define AMC6821_CONF4_PSPR 0x40
+#define AMC6821_CONF4_MODE 0x80
+
+#define AMC6821_STAT1_RPM_ALARM 0x01
+#define AMC6821_STAT1_FANS 0x02
+#define AMC6821_STAT1_RTH 0x04
+#define AMC6821_STAT1_RTL 0x08
+#define AMC6821_STAT1_R_THERM 0x10
+#define AMC6821_STAT1_RTF 0x20
+#define AMC6821_STAT1_LTH 0x40
+#define AMC6821_STAT1_LTL 0x80
+
+#define AMC6821_STAT2_RTC 0x08
+#define AMC6821_STAT2_LTC 0x10
+#define AMC6821_STAT2_LPSV 0x20
+#define AMC6821_STAT2_L_THERM 0x40
+#define AMC6821_STAT2_THERM_IN 0x80
+
+enum {IDX_TEMP1_INPUT = 0, IDX_TEMP1_MIN, IDX_TEMP1_MAX,
+       IDX_TEMP1_CRIT, IDX_TEMP2_INPUT, IDX_TEMP2_MIN,
+       IDX_TEMP2_MAX, IDX_TEMP2_CRIT,
+       TEMP_IDX_LEN, };
+
+static const u8 temp_reg[] = {AMC6821_REG_LTEMP_HI,
+                       AMC6821_REG_LTEMP_LIMIT_MIN,
+                       AMC6821_REG_LTEMP_LIMIT_MAX,
+                       AMC6821_REG_LTEMP_CRIT,
+                       AMC6821_REG_RTEMP_HI,
+                       AMC6821_REG_RTEMP_LIMIT_MIN,
+                       AMC6821_REG_RTEMP_LIMIT_MAX,
+                       AMC6821_REG_RTEMP_CRIT, };
+
+enum {IDX_FAN1_INPUT = 0, IDX_FAN1_MIN, IDX_FAN1_MAX,
+       FAN1_IDX_LEN, };
+
+static const u8 fan_reg_low[] = {AMC6821_REG_TDATA_LOW,
+                       AMC6821_REG_TACH_LLIMITL,
+                       AMC6821_REG_TACH_HLIMITL, };
+
+
+static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI,
+                       AMC6821_REG_TACH_LLIMITH,
+                       AMC6821_REG_TACH_HLIMITH, };
+
+static int amc6821_probe(
+               struct i2c_client *client,
+               const struct i2c_device_id *id);
+static int amc6821_detect(
+               struct i2c_client *client,
+               struct i2c_board_info *info);
+static int amc6821_init_client(struct i2c_client *client);
+static int amc6821_remove(struct i2c_client *client);
+static struct amc6821_data *amc6821_update_device(struct device *dev);
+
+/*
+ * Driver data (common to all clients)
+ */
+
+static const struct i2c_device_id amc6821_id[] = {
+       { "amc6821", amc6821 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, amc6821_id);
+
+static struct i2c_driver amc6821_driver = {
+       .class = I2C_CLASS_HWMON,
+       .driver = {
+               .name   = "amc6821",
+       },
+       .probe = amc6821_probe,
+       .remove = amc6821_remove,
+       .id_table = amc6821_id,
+       .detect = amc6821_detect,
+       .address_list = normal_i2c,
+};
+
+
+/*
+ * Client data (each client gets its own)
+  */
+
+struct amc6821_data {
+       struct device *hwmon_dev;
+       struct mutex update_lock;
+       char valid; /* zero until following fields are valid */
+       unsigned long last_updated; /* in jiffies */
+
+       /* register values */
+       int temp[TEMP_IDX_LEN];
+
+       u16 fan[FAN1_IDX_LEN];
+       u8 fan1_div;
+
+       u8 pwm1;
+       u8 temp1_auto_point_temp[3];
+       u8 temp2_auto_point_temp[3];
+       u8 pwm1_auto_point_pwm[3];
+       u8 pwm1_enable;
+       u8 pwm1_auto_channels_temp;
+
+       u8 stat1;
+       u8 stat2;
+};
+
+
+static ssize_t get_temp(
+               struct device *dev,
+               struct device_attribute *devattr,
+               char *buf)
+{
+       struct amc6821_data *data = amc6821_update_device(dev);
+       int ix = to_sensor_dev_attr(devattr)->index;
+
+       return sprintf(buf, "%d\n", data->temp[ix] * 1000);
+}
+
+
+
+static ssize_t set_temp(
+               struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct amc6821_data *data = i2c_get_clientdata(client);
+       int ix = to_sensor_dev_attr(attr)->index;
+       long val;
+
+       int ret = strict_strtol(buf, 10, &val);
+       if (ret)
+               return ret;
+       val = SENSORS_LIMIT(val / 1000, -128, 127);
+
+       mutex_lock(&data->update_lock);
+       data->temp[ix] = val;
+       if (i2c_smbus_write_byte_data(client, temp_reg[ix], data->temp[ix])) {
+               dev_err(&client->dev, "Register write error, aborting.\n");
+               count = -EIO;
+       }
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+
+
+
+static ssize_t get_temp_alarm(
+       struct device *dev,
+       struct device_attribute *devattr,
+       char *buf)
+{
+       struct amc6821_data *data = amc6821_update_device(dev);
+       int ix = to_sensor_dev_attr(devattr)->index;
+       u8 flag;
+
+       switch (ix) {
+       case IDX_TEMP1_MIN:
+               flag = data->stat1 & AMC6821_STAT1_LTL;
+               break;
+       case IDX_TEMP1_MAX:
+               flag = data->stat1 & AMC6821_STAT1_LTH;
+               break;
+       case IDX_TEMP1_CRIT:
+               flag = data->stat2 & AMC6821_STAT2_LTC;
+               break;
+       case IDX_TEMP2_MIN:
+               flag = data->stat1 & AMC6821_STAT1_RTL;
+               break;
+       case IDX_TEMP2_MAX:
+               flag = data->stat1 & AMC6821_STAT1_RTH;
+               break;
+       case IDX_TEMP2_CRIT:
+               flag = data->stat2 & AMC6821_STAT2_RTC;
+               break;
+       default:
+               dev_dbg(dev, "Unknown attr->index (%d).\n", ix);
+               return -EINVAL;
+       }
+       if (flag)
+               return sprintf(buf, "1");
+       else
+               return sprintf(buf, "0");
+}
+
+
+
+
+static ssize_t get_temp2_fault(
+               struct device *dev,
+               struct device_attribute *devattr,
+               char *buf)
+{
+       struct amc6821_data *data = amc6821_update_device(dev);
+       if (data->stat1 & AMC6821_STAT1_RTF)
+               return sprintf(buf, "1");
+       else
+               return sprintf(buf, "0");
+}
+
+static ssize_t get_pwm1(
+               struct device *dev,
+               struct device_attribute *devattr,
+               char *buf)
+{
+       struct amc6821_data *data = amc6821_update_device(dev);
+       return sprintf(buf, "%d\n", data->pwm1);
+}
+
+static ssize_t set_pwm1(
+               struct device *dev,
+               struct device_attribute *devattr,
+               const char *buf,
+               size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct amc6821_data *data = i2c_get_clientdata(client);
+       long val;
+       int ret = strict_strtol(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       mutex_lock(&data->update_lock);
+       data->pwm1 = SENSORS_LIMIT(val , 0, 255);
+       i2c_smbus_write_byte_data(client, AMC6821_REG_DCY, data->pwm1);
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+static ssize_t get_pwm1_enable(
+               struct device *dev,
+               struct device_attribute *devattr,
+               char *buf)
+{
+       struct amc6821_data *data = amc6821_update_device(dev);
+       return sprintf(buf, "%d\n", data->pwm1_enable);
+}
+
+static ssize_t set_pwm1_enable(
+               struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct amc6821_data *data = i2c_get_clientdata(client);
+       long val;
+       int config = strict_strtol(buf, 10, &val);
+       if (config)
+               return config;
+
+       config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
+       if (config < 0) {
+                       dev_err(&client->dev,
+                       "Error reading configuration register, aborting.\n");
+                       return -EIO;
+       }
+
+       switch (val) {
+       case 1:
+               config &= ~AMC6821_CONF1_FDRC0;
+               config &= ~AMC6821_CONF1_FDRC1;
+               break;
+       case 2:
+               config &= ~AMC6821_CONF1_FDRC0;
+               config |= AMC6821_CONF1_FDRC1;
+               break;
+       case 3:
+               config |= AMC6821_CONF1_FDRC0;
+               config |= AMC6821_CONF1_FDRC1;
+               break;
+       default:
+               return -EINVAL;
+       }
+       mutex_lock(&data->update_lock);
+       if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) {
+                       dev_err(&client->dev,
+                       "Configuration register write error, aborting.\n");
+                       count = -EIO;
+       }
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+
+static ssize_t get_pwm1_auto_channels_temp(
+               struct device *dev,
+               struct device_attribute *devattr,
+               char *buf)
+{
+       struct amc6821_data *data = amc6821_update_device(dev);
+       return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp);
+}
+
+
+static ssize_t get_temp_auto_point_temp(
+               struct device *dev,
+               struct device_attribute *devattr,
+               char *buf)
+{
+       int ix = to_sensor_dev_attr_2(devattr)->index;
+       int nr = to_sensor_dev_attr_2(devattr)->nr;
+       struct amc6821_data *data = amc6821_update_device(dev);
+       switch (nr) {
+       case 1:
+               return sprintf(buf, "%d\n",
+                       data->temp1_auto_point_temp[ix] * 1000);
+               break;
+       case 2:
+               return sprintf(buf, "%d\n",
+                       data->temp2_auto_point_temp[ix] * 1000);
+               break;
+       default:
+               dev_dbg(dev, "Unknown attr->nr (%d).\n", nr);
+               return -EINVAL;
+       }
+}
+
+
+static ssize_t get_pwm1_auto_point_pwm(
+               struct device *dev,
+               struct device_attribute *devattr,
+               char *buf)
+{
+       int ix = to_sensor_dev_attr(devattr)->index;
+       struct amc6821_data *data = amc6821_update_device(dev);
+       return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]);
+}
+
+
+static inline ssize_t set_slope_register(struct i2c_client *client,
+               u8 reg,
+               u8 dpwm,
+               u8 *ptemp)
+{
+       int dt;
+       u8 tmp;
+
+       dt = ptemp[2]-ptemp[1];
+       for (tmp = 4; tmp > 0; tmp--) {
+               if (dt * (0x20 >> tmp) >= dpwm)
+                       break;
+       }
+       tmp |= (ptemp[1] & 0x7C) << 1;
+       if (i2c_smbus_write_byte_data(client,
+                       reg, tmp)) {
+               dev_err(&client->dev, "Register write error, aborting.\n");
+               return -EIO;
+       }
+       return 0;
+}
+
+
+
+static ssize_t set_temp_auto_point_temp(
+               struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct amc6821_data *data = amc6821_update_device(dev);
+       int ix = to_sensor_dev_attr_2(attr)->index;
+       int nr = to_sensor_dev_attr_2(attr)->nr;
+       u8 *ptemp;
+       u8 reg;
+       int dpwm;
+       long val;
+       int ret = strict_strtol(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       switch (nr) {
+       case 1:
+               ptemp = data->temp1_auto_point_temp;
+               reg = AMC6821_REG_LTEMP_FAN_CTRL;
+               break;
+       case 2:
+               ptemp = data->temp2_auto_point_temp;
+               reg = AMC6821_REG_RTEMP_FAN_CTRL;
+               break;
+       default:
+               dev_dbg(dev, "Unknown attr->nr (%d).\n", nr);
+               return -EINVAL;
+       }
+
+       data->valid = 0;
+       mutex_lock(&data->update_lock);
+       switch (ix) {
+       case 0:
+               ptemp[0] = SENSORS_LIMIT(val / 1000, 0,
+                               data->temp1_auto_point_temp[1]);
+               ptemp[0] = SENSORS_LIMIT(ptemp[0], 0,
+                               data->temp2_auto_point_temp[1]);
+               ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, 63);
+               if (i2c_smbus_write_byte_data(
+                                       client,
+                                       AMC6821_REG_PSV_TEMP,
+                                       ptemp[0])) {
+                               dev_err(&client->dev,
+                                       "Register write error, aborting.\n");
+                               count = -EIO;
+               }
+               goto EXIT;
+               break;
+       case 1:
+               ptemp[1] = SENSORS_LIMIT(
+                                       val / 1000,
+                                       (ptemp[0] & 0x7C) + 4,
+                                       124);
+               ptemp[1] &= 0x7C;
+               ptemp[2] = SENSORS_LIMIT(
+                                       ptemp[2], ptemp[1] + 1,
+                                       255);
+               break;
+       case 2:
+               ptemp[2] = SENSORS_LIMIT(
+                                       val / 1000,
+                                       ptemp[1]+1,
+                                       255);
+               break;
+       default:
+               dev_dbg(dev, "Unknown attr->index (%d).\n", ix);
+               count = -EINVAL;
+               goto EXIT;
+       }
+       dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1];
+       if (set_slope_register(client, reg, dpwm, ptemp))
+               count = -EIO;
+
+EXIT:
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+
+
+static ssize_t set_pwm1_auto_point_pwm(
+               struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct amc6821_data *data = i2c_get_clientdata(client);
+       int dpwm;
+       long val;
+       int ret = strict_strtol(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       mutex_lock(&data->update_lock);
+       data->pwm1_auto_point_pwm[1] = SENSORS_LIMIT(val, 0, 254);
+       if (i2c_smbus_write_byte_data(client, AMC6821_REG_DCY_LOW_TEMP,
+                       data->pwm1_auto_point_pwm[1])) {
+               dev_err(&client->dev, "Register write error, aborting.\n");
+               count = -EIO;
+               goto EXIT;
+       }
+       dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1];
+       if (set_slope_register(client, AMC6821_REG_LTEMP_FAN_CTRL, dpwm,
+                       data->temp1_auto_point_temp)) {
+               count = -EIO;
+               goto EXIT;
+       }
+       if (set_slope_register(client, AMC6821_REG_RTEMP_FAN_CTRL, dpwm,
+                       data->temp2_auto_point_temp)) {
+               count = -EIO;
+               goto EXIT;
+       }
+
+EXIT:
+       data->valid = 0;
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+static ssize_t get_fan(
+               struct device *dev,
+               struct device_attribute *devattr,
+               char *buf)
+{
+       struct amc6821_data *data = amc6821_update_device(dev);
+       int ix = to_sensor_dev_attr(devattr)->index;
+       if (0 == data->fan[ix])
+               return sprintf(buf, "0");
+       return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix]));
+}
+
+
+
+static ssize_t get_fan1_fault(
+               struct device *dev,
+               struct device_attribute *devattr,
+               char *buf)
+{
+       struct amc6821_data *data = amc6821_update_device(dev);
+       if (data->stat1 & AMC6821_STAT1_FANS)
+               return sprintf(buf, "1");
+       else
+               return sprintf(buf, "0");
+}
+
+
+
+static ssize_t set_fan(
+               struct device *dev,
+               struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct amc6821_data *data = i2c_get_clientdata(client);
+       long val;
+       int ix = to_sensor_dev_attr(attr)->index;
+       int ret = strict_strtol(buf, 10, &val);
+       if (ret)
+               return ret;
+       val = 1 > val ? 0xFFFF : 6000000/val;
+
+       mutex_lock(&data->update_lock);
+       data->fan[ix] = (u16) SENSORS_LIMIT(val, 1, 0xFFFF);
+       if (i2c_smbus_write_byte_data(client, fan_reg_low[ix],
+                       data->fan[ix] & 0xFF)) {
+               dev_err(&client->dev, "Register write error, aborting.\n");
+               count = -EIO;
+               goto EXIT;
+       }
+       if (i2c_smbus_write_byte_data(client,
+                       fan_reg_hi[ix], data->fan[ix] >> 8)) {
+               dev_err(&client->dev, "Register write error, aborting.\n");
+               count = -EIO;
+       }
+EXIT:
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+
+
+static ssize_t get_fan1_div(
+               struct device *dev,
+               struct device_attribute *devattr,
+               char *buf)
+{
+       struct amc6821_data *data = amc6821_update_device(dev);
+       return sprintf(buf, "%d\n", data->fan1_div);
+}
+
+static ssize_t set_fan1_div(
+               struct device *dev,
+               struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct amc6821_data *data = i2c_get_clientdata(client);
+       long val;
+       int config = strict_strtol(buf, 10, &val);
+       if (config)
+               return config;
+
+       config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
+       if (config < 0) {
+               dev_err(&client->dev,
+                       "Error reading configuration register, aborting.\n");
+               return -EIO;
+       }
+       mutex_lock(&data->update_lock);
+       switch (val) {
+       case 2:
+               config &= ~AMC6821_CONF4_PSPR;
+               data->fan1_div = 2;
+               break;
+       case 4:
+               config |= AMC6821_CONF4_PSPR;
+               data->fan1_div = 4;
+               break;
+       default:
+               mutex_unlock(&data->update_lock);
+               count = -EINVAL;
+               goto EXIT;
+       }
+       if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, config)) {
+               dev_err(&client->dev,
+                       "Configuration register write error, aborting.\n");
+               count = -EIO;
+       }
+EXIT:
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
+       get_temp, NULL, IDX_TEMP1_INPUT);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp,
+       set_temp, IDX_TEMP1_MIN);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, get_temp,
+       set_temp, IDX_TEMP1_MAX);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, get_temp,
+       set_temp, IDX_TEMP1_CRIT);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
+       get_temp_alarm, NULL, IDX_TEMP1_MIN);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
+       get_temp_alarm, NULL, IDX_TEMP1_MAX);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO,
+       get_temp_alarm, NULL, IDX_TEMP1_CRIT);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO | S_IWUSR,
+       get_temp, NULL, IDX_TEMP2_INPUT);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, get_temp,
+       set_temp, IDX_TEMP2_MIN);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, get_temp,
+       set_temp, IDX_TEMP2_MAX);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR, get_temp,
+       set_temp, IDX_TEMP2_CRIT);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO,
+       get_temp2_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO,
+       get_temp_alarm, NULL, IDX_TEMP2_MIN);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO,
+       get_temp_alarm, NULL, IDX_TEMP2_MAX);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO,
+       get_temp_alarm, NULL, IDX_TEMP2_CRIT);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, IDX_FAN1_INPUT);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
+       get_fan, set_fan, IDX_FAN1_MIN);
+static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO | S_IWUSR,
+       get_fan, set_fan, IDX_FAN1_MAX);
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan1_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
+       get_fan1_div, set_fan1_div, 0);
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm1, set_pwm1, 0);
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
+       get_pwm1_enable, set_pwm1_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO,
+       get_pwm1_auto_point_pwm, NULL, 0);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
+       get_pwm1_auto_point_pwm, set_pwm1_auto_point_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO,
+       get_pwm1_auto_point_pwm, NULL, 2);
+static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO,
+       get_pwm1_auto_channels_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO,
+       get_temp_auto_point_temp, NULL, 1, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IWUSR | S_IRUGO,
+       get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 1);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_point3_temp, S_IWUSR | S_IRUGO,
+       get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 2);
+
+static SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IWUSR | S_IRUGO,
+       get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IWUSR | S_IRUGO,
+       get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO,
+       get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2);
+
+
+
+static struct attribute *amc6821_attrs[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_min.dev_attr.attr,
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit.dev_attr.attr,
+       &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_min.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit.dev_attr.attr,
+       &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_fault.dev_attr.attr,
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan1_min.dev_attr.attr,
+       &sensor_dev_attr_fan1_max.dev_attr.attr,
+       &sensor_dev_attr_fan1_fault.dev_attr.attr,
+       &sensor_dev_attr_fan1_div.dev_attr.attr,
+       &sensor_dev_attr_pwm1.dev_attr.attr,
+       &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
+       &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
+       &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
+       &sensor_dev_attr_temp1_auto_point3_temp.dev_attr.attr,
+       &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
+       &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
+       &sensor_dev_attr_temp2_auto_point3_temp.dev_attr.attr,
+       NULL
+};
+
+static struct attribute_group amc6821_attr_grp = {
+       .attrs = amc6821_attrs,
+};
+
+
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int amc6821_detect(
+               struct i2c_client *client,
+               struct i2c_board_info *info)
+{
+       struct i2c_adapter *adapter = client->adapter;
+       int address = client->addr;
+       int dev_id, comp_id;
+
+       dev_dbg(&adapter->dev, "amc6821_detect called.\n");
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_dbg(&adapter->dev,
+                       "amc6821: I2C bus doesn't support byte mode, "
+                       "skipping.\n");
+               return -ENODEV;
+       }
+
+       dev_id = i2c_smbus_read_byte_data(client, AMC6821_REG_DEV_ID);
+       comp_id = i2c_smbus_read_byte_data(client, AMC6821_REG_COMP_ID);
+       if (dev_id != 0x21 || comp_id != 0x49) {
+               dev_dbg(&adapter->dev,
+                       "amc6821: detection failed at 0x%02x.\n",
+                       address);
+               return -ENODEV;
+       }
+
+       /* Bit 7 of the address register is ignored, so we can check the
+          ID registers again */
+       dev_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_DEV_ID);
+       comp_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_COMP_ID);
+       if (dev_id != 0x21 || comp_id != 0x49) {
+               dev_dbg(&adapter->dev,
+                       "amc6821: detection failed at 0x%02x.\n",
+                       address);
+               return -ENODEV;
+       }
+
+       dev_info(&adapter->dev, "amc6821: chip found at 0x%02x.\n", address);
+       strlcpy(info->type, "amc6821", I2C_NAME_SIZE);
+
+       return 0;
+}
+
+static int amc6821_probe(
+       struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       struct amc6821_data *data;
+       int err;
+
+       data = kzalloc(sizeof(struct amc6821_data), GFP_KERNEL);
+       if (!data) {
+               dev_err(&client->dev, "out of memory.\n");
+               return -ENOMEM;
+       }
+
+
+       i2c_set_clientdata(client, data);
+       mutex_init(&data->update_lock);
+
+       /*
+        * Initialize the amc6821 chip
+        */
+       err = amc6821_init_client(client);
+       if (err)
+               goto err_free;
+
+       err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp);
+       if (err)
+               goto err_free;
+
+       data->hwmon_dev = hwmon_device_register(&client->dev);
+       if (!IS_ERR(data->hwmon_dev))
+               return 0;
+
+       err = PTR_ERR(data->hwmon_dev);
+       dev_err(&client->dev, "error registering hwmon device.\n");
+       sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp);
+err_free:
+       kfree(data);
+       return err;
+}
+
+static int amc6821_remove(struct i2c_client *client)
+{
+       struct amc6821_data *data = i2c_get_clientdata(client);
+
+       hwmon_device_unregister(data->hwmon_dev);
+       sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp);
+
+       kfree(data);
+
+       return 0;
+}
+
+
+static int amc6821_init_client(struct i2c_client *client)
+{
+       int config;
+       int err = -EIO;
+
+       if (init) {
+               config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
+
+               if (config < 0) {
+                               dev_err(&client->dev,
+                       "Error reading configuration register, aborting.\n");
+                               return err;
+               }
+
+               config |= AMC6821_CONF4_MODE;
+
+               if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4,
+                               config)) {
+                       dev_err(&client->dev,
+                       "Configuration register write error, aborting.\n");
+                       return err;
+               }
+
+               config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF3);
+
+               if (config < 0) {
+                       dev_err(&client->dev,
+                       "Error reading configuration register, aborting.\n");
+                       return err;
+               }
+
+               dev_info(&client->dev, "Revision %d\n", config & 0x0f);
+
+               config &= ~AMC6821_CONF3_THERM_FAN_EN;
+
+               if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF3,
+                               config)) {
+                       dev_err(&client->dev,
+                       "Configuration register write error, aborting.\n");
+                       return err;
+               }
+
+               config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF2);
+
+               if (config < 0) {
+                       dev_err(&client->dev,
+                       "Error reading configuration register, aborting.\n");
+                       return err;
+               }
+
+               config &= ~AMC6821_CONF2_RTFIE;
+               config &= ~AMC6821_CONF2_LTOIE;
+               config &= ~AMC6821_CONF2_RTOIE;
+               if (i2c_smbus_write_byte_data(client,
+                               AMC6821_REG_CONF2, config)) {
+                       dev_err(&client->dev,
+                       "Configuration register write error, aborting.\n");
+                       return err;
+               }
+
+               config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
+
+               if (config < 0) {
+                       dev_err(&client->dev,
+                       "Error reading configuration register, aborting.\n");
+                       return err;
+               }
+
+               config &= ~AMC6821_CONF1_THERMOVIE;
+               config &= ~AMC6821_CONF1_FANIE;
+               config |= AMC6821_CONF1_START;
+               if (pwminv)
+                       config |= AMC6821_CONF1_PWMINV;
+               else
+                       config &= ~AMC6821_CONF1_PWMINV;
+
+               if (i2c_smbus_write_byte_data(
+                               client, AMC6821_REG_CONF1, config)) {
+                       dev_err(&client->dev,
+                       "Configuration register write error, aborting.\n");
+                       return err;
+               }
+       }
+       return 0;
+}
+
+
+static struct amc6821_data *amc6821_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct amc6821_data *data = i2c_get_clientdata(client);
+       int timeout = HZ;
+       u8 reg;
+       int i;
+
+       mutex_lock(&data->update_lock);
+
+       if (time_after(jiffies, data->last_updated + timeout) ||
+                       !data->valid) {
+
+               for (i = 0; i < TEMP_IDX_LEN; i++)
+                       data->temp[i] = i2c_smbus_read_byte_data(client,
+                               temp_reg[i]);
+
+               data->stat1 = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_STAT1);
+               data->stat2 = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_STAT2);
+
+               data->pwm1 = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_DCY);
+               for (i = 0; i < FAN1_IDX_LEN; i++) {
+                       data->fan[i] = i2c_smbus_read_byte_data(
+                                       client,
+                                       fan_reg_low[i]);
+                       data->fan[i] += i2c_smbus_read_byte_data(
+                                       client,
+                                       fan_reg_hi[i]) << 8;
+               }
+               data->fan1_div = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_CONF4);
+               data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2;
+
+               data->pwm1_auto_point_pwm[0] = 0;
+               data->pwm1_auto_point_pwm[2] = 255;
+               data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_DCY_LOW_TEMP);
+
+               data->temp1_auto_point_temp[0] =
+                       i2c_smbus_read_byte_data(client,
+                                       AMC6821_REG_PSV_TEMP);
+               data->temp2_auto_point_temp[0] =
+                               data->temp1_auto_point_temp[0];
+               reg = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_LTEMP_FAN_CTRL);
+               data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1;
+               reg &= 0x07;
+               reg = 0x20 >> reg;
+               if (reg > 0)
+                       data->temp1_auto_point_temp[2] =
+                               data->temp1_auto_point_temp[1] +
+                               (data->pwm1_auto_point_pwm[2] -
+                               data->pwm1_auto_point_pwm[1]) / reg;
+               else
+                       data->temp1_auto_point_temp[2] = 255;
+
+               reg = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_RTEMP_FAN_CTRL);
+               data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1;
+               reg &= 0x07;
+               reg = 0x20 >> reg;
+               if (reg > 0)
+                       data->temp2_auto_point_temp[2] =
+                               data->temp2_auto_point_temp[1] +
+                               (data->pwm1_auto_point_pwm[2] -
+                               data->pwm1_auto_point_pwm[1]) / reg;
+               else
+                       data->temp2_auto_point_temp[2] = 255;
+
+               reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
+               reg = (reg >> 5) & 0x3;
+               switch (reg) {
+               case 0: /*open loop: software sets pwm1*/
+                       data->pwm1_auto_channels_temp = 0;
+                       data->pwm1_enable = 1;
+                       break;
+               case 2: /*closed loop: remote T (temp2)*/
+                       data->pwm1_auto_channels_temp = 2;
+                       data->pwm1_enable = 2;
+                       break;
+               case 3: /*closed loop: local and remote T (temp2)*/
+                       data->pwm1_auto_channels_temp = 3;
+                       data->pwm1_enable = 3;
+                       break;
+               case 1: /*semi-open loop: software sets rpm, chip controls pwm1,
+                         *currently not implemented
+                         */
+                       data->pwm1_auto_channels_temp = 0;
+                       data->pwm1_enable = 0;
+                       break;
+               }
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+       mutex_unlock(&data->update_lock);
+       return data;
+}
+
+
+static int __init amc6821_init(void)
+{
+       return i2c_add_driver(&amc6821_driver);
+}
+
+static void __exit amc6821_exit(void)
+{
+       i2c_del_driver(&amc6821_driver);
+}
+
+module_init(amc6821_init);
+module_exit(amc6821_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("T. Mertelj <tomaz.mertelj@guest.arnes.si>");
+MODULE_DESCRIPTION("Texas Instruments amc6821 hwmon driver");
index 5a3ee00c0e7d2b65baafde7fefdb62a9fe935262..6811346c1c622672a3fa51ff6bec71b602a84b3c 100644 (file)
@@ -5,6 +5,7 @@
  * See COPYING in the top level directory of the kernel tree.
  */
 
+#include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/hwmon.h>
 #include <linux/list.h>
@@ -101,6 +102,11 @@ struct atk_data {
        int temperature_count;
        int fan_count;
        struct list_head sensor_list;
+
+       struct {
+               struct dentry *root;
+               u32 id;
+       } debugfs;
 };
 
 
@@ -624,6 +630,187 @@ static int atk_read_value(struct atk_sensor_data *sensor, u64 *value)
        return err;
 }
 
+#ifdef CONFIG_DEBUG_FS
+static int atk_debugfs_gitm_get(void *p, u64 *val)
+{
+       struct atk_data *data = p;
+       union acpi_object *ret;
+       struct atk_acpi_ret_buffer *buf;
+       int err = 0;
+
+       if (!data->read_handle)
+               return -ENODEV;
+
+       if (!data->debugfs.id)
+               return -EINVAL;
+
+       ret = atk_gitm(data, data->debugfs.id);
+       if (IS_ERR(ret))
+               return PTR_ERR(ret);
+
+       buf = (struct atk_acpi_ret_buffer *)ret->buffer.pointer;
+       if (buf->flags)
+               *val = buf->value;
+       else
+               err = -EIO;
+
+       return err;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(atk_debugfs_gitm,
+                       atk_debugfs_gitm_get,
+                       NULL,
+                       "0x%08llx\n")
+
+static int atk_acpi_print(char *buf, size_t sz, union acpi_object *obj)
+{
+       int ret = 0;
+
+       switch (obj->type) {
+       case ACPI_TYPE_INTEGER:
+               ret = snprintf(buf, sz, "0x%08llx\n", obj->integer.value);
+               break;
+       case ACPI_TYPE_STRING:
+               ret = snprintf(buf, sz, "%s\n", obj->string.pointer);
+               break;
+       }
+
+       return ret;
+}
+
+static void atk_pack_print(char *buf, size_t sz, union acpi_object *pack)
+{
+       int ret;
+       int i;
+
+       for (i = 0; i < pack->package.count; i++) {
+               union acpi_object *obj = &pack->package.elements[i];
+
+               ret = atk_acpi_print(buf, sz, obj);
+               if (ret >= sz)
+                       break;
+               buf += ret;
+               sz -= ret;
+       }
+}
+
+static int atk_debugfs_ggrp_open(struct inode *inode, struct file *file)
+{
+       struct atk_data *data = inode->i_private;
+       char *buf = NULL;
+       union acpi_object *ret;
+       u8 cls;
+       int i;
+
+       if (!data->enumerate_handle)
+               return -ENODEV;
+       if (!data->debugfs.id)
+               return -EINVAL;
+
+       cls = (data->debugfs.id & 0xff000000) >> 24;
+       ret = atk_ggrp(data, cls);
+       if (IS_ERR(ret))
+               return PTR_ERR(ret);
+
+       for (i = 0; i < ret->package.count; i++) {
+               union acpi_object *pack = &ret->package.elements[i];
+               union acpi_object *id;
+
+               if (pack->type != ACPI_TYPE_PACKAGE)
+                       continue;
+               if (!pack->package.count)
+                       continue;
+               id = &pack->package.elements[0];
+               if (id->integer.value == data->debugfs.id) {
+                       /* Print the package */
+                       buf = kzalloc(512, GFP_KERNEL);
+                       if (!buf) {
+                               ACPI_FREE(ret);
+                               return -ENOMEM;
+                       }
+                       atk_pack_print(buf, 512, pack);
+                       break;
+               }
+       }
+       ACPI_FREE(ret);
+
+       if (!buf)
+               return -EINVAL;
+
+       file->private_data = buf;
+
+       return nonseekable_open(inode, file);
+}
+
+static ssize_t atk_debugfs_ggrp_read(struct file *file, char __user *buf,
+               size_t count, loff_t *pos)
+{
+       char *str = file->private_data;
+       size_t len = strlen(str);
+
+       return simple_read_from_buffer(buf, count, pos, str, len);
+}
+
+static int atk_debugfs_ggrp_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       return 0;
+}
+
+static const struct file_operations atk_debugfs_ggrp_fops = {
+       .read           = atk_debugfs_ggrp_read,
+       .open           = atk_debugfs_ggrp_open,
+       .release        = atk_debugfs_ggrp_release,
+};
+
+static void atk_debugfs_init(struct atk_data *data)
+{
+       struct dentry *d;
+       struct dentry *f;
+
+       data->debugfs.id = 0;
+
+       d = debugfs_create_dir("asus_atk0110", NULL);
+       if (!d || IS_ERR(d))
+               return;
+
+       f = debugfs_create_x32("id", S_IRUSR | S_IWUSR, d, &data->debugfs.id);
+       if (!f || IS_ERR(f))
+               goto cleanup;
+
+       f = debugfs_create_file("gitm", S_IRUSR, d, data,
+                       &atk_debugfs_gitm);
+       if (!f || IS_ERR(f))
+               goto cleanup;
+
+       f = debugfs_create_file("ggrp", S_IRUSR, d, data,
+                       &atk_debugfs_ggrp_fops);
+       if (!f || IS_ERR(f))
+               goto cleanup;
+
+       data->debugfs.root = d;
+
+       return;
+cleanup:
+       debugfs_remove_recursive(d);
+}
+
+static void atk_debugfs_cleanup(struct atk_data *data)
+{
+       debugfs_remove_recursive(data->debugfs.root);
+}
+
+#else /* CONFIG_DEBUG_FS */
+
+static void atk_debugfs_init(struct atk_data *data)
+{
+}
+
+static void atk_debugfs_cleanup(struct atk_data *data)
+{
+}
+#endif
+
 static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
 {
        struct device *dev = &data->acpi_dev->dev;
@@ -1047,76 +1234,75 @@ remove:
        return err;
 }
 
-static int atk_check_old_if(struct atk_data *data)
+static int atk_probe_if(struct atk_data *data)
 {
        struct device *dev = &data->acpi_dev->dev;
        acpi_handle ret;
        acpi_status status;
+       int err = 0;
 
        /* RTMP: read temperature */
        status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_TMP, &ret);
-       if (status != AE_OK) {
+       if (ACPI_SUCCESS(status))
+               data->rtmp_handle = ret;
+       else
                dev_dbg(dev, "method " METHOD_OLD_READ_TMP " not found: %s\n",
                                acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->rtmp_handle = ret;
 
        /* RVLT: read voltage */
        status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_VLT, &ret);
-       if (status != AE_OK) {
+       if (ACPI_SUCCESS(status))
+               data->rvlt_handle = ret;
+       else
                dev_dbg(dev, "method " METHOD_OLD_READ_VLT " not found: %s\n",
                                acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->rvlt_handle = ret;
 
        /* RFAN: read fan status */
        status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_FAN, &ret);
-       if (status != AE_OK) {
+       if (ACPI_SUCCESS(status))
+               data->rfan_handle = ret;
+       else
                dev_dbg(dev, "method " METHOD_OLD_READ_FAN " not found: %s\n",
                                acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->rfan_handle = ret;
-
-       return 0;
-}
-
-static int atk_check_new_if(struct atk_data *data)
-{
-       struct device *dev = &data->acpi_dev->dev;
-       acpi_handle ret;
-       acpi_status status;
 
        /* Enumeration */
        status = acpi_get_handle(data->atk_handle, METHOD_ENUMERATE, &ret);
-       if (status != AE_OK) {
+       if (ACPI_SUCCESS(status))
+               data->enumerate_handle = ret;
+       else
                dev_dbg(dev, "method " METHOD_ENUMERATE " not found: %s\n",
                                acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->enumerate_handle = ret;
 
        /* De-multiplexer (read) */
        status = acpi_get_handle(data->atk_handle, METHOD_READ, &ret);
-       if (status != AE_OK) {
+       if (ACPI_SUCCESS(status))
+               data->read_handle = ret;
+       else
                dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
                                acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->read_handle = ret;
 
        /* De-multiplexer (write) */
        status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret);
-       if (status != AE_OK) {
-               dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
+       if (ACPI_SUCCESS(status))
+               data->write_handle = ret;
+       else
+               dev_dbg(dev, "method " METHOD_WRITE " not found: %s\n",
                                 acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->write_handle = ret;
 
-       return 0;
+       /* Check for hwmon methods: first check "old" style methods; note that
+        * both may be present: in this case we stick to the old interface;
+        * analysis of multiple DSDTs indicates that when both interfaces
+        * are present the new one (GGRP/GITM) is not functional.
+        */
+       if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle)
+               data->old_interface = true;
+       else if (data->enumerate_handle && data->read_handle &&
+                       data->write_handle)
+               data->old_interface = false;
+       else
+               err = -ENODEV;
+
+       return err;
 }
 
 static int atk_add(struct acpi_device *device)
@@ -1155,28 +1341,19 @@ static int atk_add(struct acpi_device *device)
        }
        ACPI_FREE(buf.pointer);
 
-       /* Check for hwmon methods: first check "old" style methods; note that
-        * both may be present: in this case we stick to the old interface;
-        * analysis of multiple DSDTs indicates that when both interfaces
-        * are present the new one (GGRP/GITM) is not functional.
-        */
-       err = atk_check_old_if(data);
-       if (!err) {
-               dev_dbg(&device->dev, "Using old hwmon interface\n");
-               data->old_interface = true;
-       } else {
-               err = atk_check_new_if(data);
-               if (err)
-                       goto out;
-
-               dev_dbg(&device->dev, "Using new hwmon interface\n");
-               data->old_interface = false;
+       err = atk_probe_if(data);
+       if (err) {
+               dev_err(&device->dev, "No usable hwmon interface detected\n");
+               goto out;
        }
 
-       if (data->old_interface)
+       if (data->old_interface) {
+               dev_dbg(&device->dev, "Using old hwmon interface\n");
                err = atk_enumerate_old_hwmon(data);
-       else
+       } else {
+               dev_dbg(&device->dev, "Using new hwmon interface\n");
                err = atk_enumerate_new_hwmon(data);
+       }
        if (err < 0)
                goto out;
        if (err == 0) {
@@ -1190,6 +1367,8 @@ static int atk_add(struct acpi_device *device)
        if (err)
                goto cleanup;
 
+       atk_debugfs_init(data);
+
        device->driver_data = data;
        return 0;
 cleanup:
@@ -1208,6 +1387,8 @@ static int atk_remove(struct acpi_device *device, int type)
 
        device->driver_data = NULL;
 
+       atk_debugfs_cleanup(data);
+
        atk_remove_files(data);
        atk_free_sensors(data);
        hwmon_device_unregister(data->hwmon_dev);
index caef39cda8c8e8d504eb1777d6aa409ff6bf7424..2d7bceeed0bc3daf10a8ae2d58d106d575107eb2 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
+#include <linux/pci.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
 
@@ -161,6 +162,7 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *
        int usemsr_ee = 1;
        int err;
        u32 eax, edx;
+       struct pci_dev *host_bridge;
 
        /* Early chips have no MSR for TjMax */
 
@@ -168,11 +170,21 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *
                usemsr_ee = 0;
        }
 
-       /* Atoms seems to have TjMax at 90C */
+       /* Atom CPUs */
 
        if (c->x86_model == 0x1c) {
                usemsr_ee = 0;
-               tjmax = 90000;
+
+               host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
+
+               if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL
+                   && (host_bridge->device == 0xa000   /* NM10 based nettop */
+                   || host_bridge->device == 0xa010))  /* NM10 based netbook */
+                       tjmax = 100000;
+               else
+                       tjmax = 90000;
+
+               pci_dev_put(host_bridge);
        }
 
        if ((c->x86_model > 0xe) && (usemsr_ee)) {
index d8a26d16d9489dcf26c8c2cf456de76fa9cc622f..099a2138cdf6ff739eda8826996a691b9f6ec0c0 100644 (file)
@@ -33,6 +33,16 @@ static bool force;
 module_param(force, bool, 0444);
 MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
 
+/* CPUID function 0x80000001, ebx */
+#define CPUID_PKGTYPE_MASK     0xf0000000
+#define CPUID_PKGTYPE_F                0x00000000
+#define CPUID_PKGTYPE_AM2R2_AM3        0x10000000
+
+/* DRAM controller (PCI function 2) */
+#define REG_DCT0_CONFIG_HIGH           0x094
+#define  DDR3_MODE                     0x00000100
+
+/* miscellaneous (PCI function 3) */
 #define REG_HARDWARE_THERMAL_CONTROL   0x64
 #define  HTC_ENABLE                    0x00000001
 
@@ -85,13 +95,28 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static bool __devinit has_erratum_319(void)
+static bool __devinit has_erratum_319(struct pci_dev *pdev)
 {
+       u32 pkg_type, reg_dram_cfg;
+
+       if (boot_cpu_data.x86 != 0x10)
+               return false;
+
        /*
-        * Erratum 319: The thermal sensor of older Family 10h processors
-        *              (B steppings) may be unreliable.
+        * Erratum 319: The thermal sensor of Socket F/AM2+ processors
+        *              may be unreliable.
         */
-       return boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model <= 2;
+       pkg_type = cpuid_ebx(0x80000001) & CPUID_PKGTYPE_MASK;
+       if (pkg_type == CPUID_PKGTYPE_F)
+               return true;
+       if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3)
+               return false;
+
+       /* Differentiate between AM2+ (bad) and AM3 (good) */
+       pci_bus_read_config_dword(pdev->bus,
+                                 PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),
+                                 REG_DCT0_CONFIG_HIGH, &reg_dram_cfg);
+       return !(reg_dram_cfg & DDR3_MODE);
 }
 
 static int __devinit k10temp_probe(struct pci_dev *pdev,
@@ -99,9 +124,10 @@ static int __devinit k10temp_probe(struct pci_dev *pdev,
 {
        struct device *hwmon_dev;
        u32 reg_caps, reg_htc;
+       int unreliable = has_erratum_319(pdev);
        int err;
 
-       if (has_erratum_319() && !force) {
+       if (unreliable && !force) {
                dev_err(&pdev->dev,
                        "unreliable CPU thermal sensor; monitoring disabled\n");
                err = -ENODEV;
@@ -139,7 +165,7 @@ static int __devinit k10temp_probe(struct pci_dev *pdev,
        }
        dev_set_drvdata(&pdev->dev, hwmon_dev);
 
-       if (has_erratum_319() && force)
+       if (unreliable && force)
                dev_warn(&pdev->dev,
                         "unreliable CPU thermal sensor; check erratum 319\n");
        return 0;
@@ -169,7 +195,7 @@ static void __devexit k10temp_remove(struct pci_dev *pdev)
        dev_set_drvdata(&pdev->dev, NULL);
 }
 
-static struct pci_device_id k10temp_id_table[] = {
+static const struct pci_device_id k10temp_id_table[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
        {}
index 1fe99511184111a68a38e151e96e03c9491f59ad..0ceb6d6200a313b5e1ea5ef488f221ac929cdf80 100644 (file)
@@ -136,7 +136,7 @@ static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0);
 static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static struct pci_device_id k8temp_ids[] = {
+static const struct pci_device_id k8temp_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
        { 0 },
 };
index 12f2e708656059e3dc357c438ee5d0c405f2fd0f..79c2931e30085632b594bf67bd5ff8db37bb10a1 100644 (file)
@@ -697,7 +697,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev)
        return data;
 }
 
-static struct pci_device_id sis5595_pci_ids[] = {
+static const struct pci_device_id sis5595_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
        { 0, }
 };
index 39e82a492f263114382e5c123bfc46b6ad5a1e6c..f397ce7ad5984d2347372d90053c6612cabfd345 100644 (file)
@@ -767,7 +767,7 @@ static struct via686a_data *via686a_update_device(struct device *dev)
        return data;
 }
 
-static struct pci_device_id via686a_pci_ids[] = {
+static const struct pci_device_id via686a_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
        { 0, }
 };
index 470a1226ba2b38bdd29721ee943ac373c093789a..d47b4c9949c2f7da720e2c69986193e2f76c96e6 100644 (file)
@@ -697,7 +697,7 @@ static struct platform_driver vt8231_driver = {
        .remove = __devexit_p(vt8231_remove),
 };
 
-static struct pci_device_id vt8231_pci_ids[] = {
+static const struct pci_device_id vt8231_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
        { 0, }
 };
index f102fcc7e52a73c83df1bec8eab19dc4ebd9f559..e02096cf7d95bfa383bddb703bbfbff6b782e688 100644 (file)
@@ -1,8 +1,3 @@
-menu "IEEE 1394 (FireWire) support"
-       depends on PCI || BROKEN
-
-source "drivers/firewire/Kconfig"
-
 config IEEE1394
        tristate "Legacy alternative FireWire driver stack"
        depends on PCI || BROKEN
@@ -16,8 +11,13 @@ config IEEE1394
          is the core support only, you will also need to select a driver for
          your IEEE 1394 adapter.
 
-         To compile this driver as a module, say M here: the
-         module will be called ieee1394.
+         To compile this driver as a module, say M here: the module will be
+         called ieee1394.
+
+         NOTE:
+         ieee1394 is superseded by the newer firewire-core driver.  See
+         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
+         further information on how to switch to the new FireWire drivers.
 
 config IEEE1394_OHCI1394
        tristate "OHCI-1394 controllers"
@@ -29,19 +29,23 @@ config IEEE1394_OHCI1394
          use one of these chipsets.  It should work with any OHCI-1394
          compliant card, however.
 
-         To compile this driver as a module, say M here: the
-         module will be called ohci1394.
+         To compile this driver as a module, say M here: the module will be
+         called ohci1394.
 
          NOTE:
+         ohci1394 is superseded by the newer firewire-ohci driver.  See
+         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
+         further information on how to switch to the new FireWire drivers.
+
          If you want to install firewire-ohci and ohci1394 together, you
          should configure them only as modules and blacklist the driver(s)
          which you don't want to have auto-loaded.  Add either
 
-             blacklist firewire-ohci
-         or
              blacklist ohci1394
              blacklist video1394
              blacklist dv1394
+         or
+             blacklist firewire-ohci
 
          to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf
          depending on your distribution.
@@ -58,8 +62,8 @@ config IEEE1394_PCILYNX
          Instruments PCILynx chip.  Note: this driver is written for revision
          2 of this chip and may not work with revision 0.
 
-         To compile this driver as a module, say M here: the
-         module will be called pcilynx.
+         To compile this driver as a module, say M here: the module will be
+         called pcilynx.
 
          Only some old and now very rare PCI and CardBus cards and
          PowerMacs G3 B&W contain the PCILynx controller.  Therefore
@@ -79,6 +83,14 @@ config IEEE1394_SBP2
          You should also enable support for disks, CD-ROMs, etc. in the SCSI
          configuration section.
 
+         To compile this driver as a module, say M here: the module will be
+         called sbp2.
+
+         NOTE:
+         sbp2 is superseded by the newer firewire-sbp2 driver. See
+         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
+         further information on how to switch to the new FireWire drivers.
+
 config IEEE1394_SBP2_PHYS_DMA
        bool "Enable replacement for physical DMA in SBP2"
        depends on IEEE1394_SBP2 && VIRT_TO_BUS && EXPERIMENTAL
@@ -111,6 +123,11 @@ config IEEE1394_ETH1394
 
          The module is called eth1394 although it does not emulate Ethernet.
 
+         NOTE:
+         eth1394 is superseded by the newer firewire-net driver. See
+         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
+         further information on how to switch to the new FireWire drivers.
+
 config IEEE1394_RAWIO
        tristate "raw1394 userspace interface"
        depends on IEEE1394
@@ -123,6 +140,11 @@ config IEEE1394_RAWIO
          To compile this driver as a module, say M here: the module will be
          called raw1394.
 
+         NOTE:
+         raw1394 is superseded by the newer firewire-core driver. See
+         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
+         further information on how to switch to the new FireWire drivers.
+
 config IEEE1394_VIDEO1394
        tristate "video1394 userspace interface"
        depends on IEEE1394 && IEEE1394_OHCI1394
@@ -136,13 +158,18 @@ config IEEE1394_VIDEO1394
          To compile this driver as a module, say M here: the module will be
          called video1394.
 
+         NOTE:
+         video1394 is superseded by the newer firewire-core driver. See
+         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
+         further information on how to switch to the new FireWire drivers.
+
 config IEEE1394_DV1394
        tristate "dv1394 userspace interface (deprecated)"
        depends on IEEE1394 && IEEE1394_OHCI1394
        help
          The dv1394 driver is unsupported and may be removed from Linux in a
-         future release.  Its functionality is now provided by raw1394 together
-         with libraries such as libiec61883.
+         future release.  Its functionality is now provided by either
+         raw1394 or firewire-core together with libraries such as libiec61883.
 
 config IEEE1394_VERBOSEDEBUG
        bool "Excessive debugging output"
@@ -153,5 +180,3 @@ config IEEE1394_VERBOSEDEBUG
          will quickly result in large amounts of data sent to the system log.
 
          Say Y if you really need the debugging output.  Everyone else says N.
-
-endmenu
index fbdd73106000b69143fc2a7f8f8a43df4fae53b6..cc9b5940fa97c69214dd1922091fc8de52fa1403 100644 (file)
@@ -2083,7 +2083,7 @@ static int cma_get_port(struct rdma_id_private *id_priv)
 static int cma_check_linklocal(struct rdma_dev_addr *dev_addr,
                               struct sockaddr *addr)
 {
-#if defined(CONFIG_IPv6) || defined(CONFIG_IPV6_MODULE)
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        struct sockaddr_in6 *sin6;
 
        if (addr->sa_family != AF_INET6)
index 989555cee8834dcf670e7d2d83c820d3cf3ef070..2a97c964b9ef6c425eeb2072980be58b7a782c40 100644 (file)
@@ -1752,7 +1752,7 @@ int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
        ind = qp->rq.head & (qp->rq.wqe_cnt - 1);
 
        for (nreq = 0; wr; ++nreq, wr = wr->next) {
-               if (mlx4_wq_overflow(&qp->rq, nreq, qp->ibqp.send_cq)) {
+               if (mlx4_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
                        err = -ENOMEM;
                        *bad_wr = wr;
                        goto out;
index d42565258fb7f0c2e0dc8053e62855a1887b87e4..cf8085bcbd6d294927f2c2cc44c048bf5c41da40 100644 (file)
@@ -74,6 +74,7 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
        struct mlx4_ib_dev *dev = to_mdev(pd->device);
        struct mlx4_ib_srq *srq;
        struct mlx4_wqe_srq_next_seg *next;
+       struct mlx4_wqe_data_seg *scatter;
        int desc_size;
        int buf_size;
        int err;
@@ -149,6 +150,11 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
                        next = get_wqe(srq, i);
                        next->next_wqe_index =
                                cpu_to_be16((i + 1) & (srq->msrq.max - 1));
+
+                       for (scatter = (void *) (next + 1);
+                            (void *) scatter < (void *) next + desc_size;
+                            ++scatter)
+                               scatter->lkey = cpu_to_be32(MLX4_INVALID_LKEY);
                }
 
                err = mlx4_mtt_init(dev->dev, srq->buf.npages, srq->buf.page_shift,
index b483b2995fa9918ad9cec432b37f0248517c45af..f967008f332e3a79fda20adb4d967957ab29f3e5 100644 (file)
@@ -220,12 +220,28 @@ static int get_compatible_type(struct ff_device *ff, int effect_type)
        return 0;
 }
 
+/*
+ * Only left/right direction should be used (under/over 0x8000) for
+ * forward/reverse motor direction (to keep calculation fast & simple).
+ */
+static u16 ml_calculate_direction(u16 direction, u16 force,
+                                 u16 new_direction, u16 new_force)
+{
+       if (!force)
+               return new_direction;
+       if (!new_force)
+               return direction;
+       return (((u32)(direction >> 1) * force +
+                (new_direction >> 1) * new_force) /
+               (force + new_force)) << 1;
+}
+
 /*
  * Combine two effects and apply gain.
  */
 static void ml_combine_effects(struct ff_effect *effect,
                               struct ml_effect_state *state,
-                              unsigned int gain)
+                              int gain)
 {
        struct ff_effect *new = state->effect;
        unsigned int strong, weak, i;
@@ -252,8 +268,21 @@ static void ml_combine_effects(struct ff_effect *effect,
                break;
 
        case FF_RUMBLE:
-               strong = new->u.rumble.strong_magnitude * gain / 0xffff;
-               weak = new->u.rumble.weak_magnitude * gain / 0xffff;
+               strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff;
+               weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff;
+
+               if (effect->u.rumble.strong_magnitude + strong)
+                       effect->direction = ml_calculate_direction(
+                               effect->direction,
+                               effect->u.rumble.strong_magnitude,
+                               new->direction, strong);
+               else if (effect->u.rumble.weak_magnitude + weak)
+                       effect->direction = ml_calculate_direction(
+                               effect->direction,
+                               effect->u.rumble.weak_magnitude,
+                               new->direction, weak);
+               else
+                       effect->direction = 0;
                effect->u.rumble.strong_magnitude =
                        min(strong + effect->u.rumble.strong_magnitude,
                            0xffffU);
@@ -268,6 +297,13 @@ static void ml_combine_effects(struct ff_effect *effect,
                /* here we also scale it 0x7fff => 0xffff */
                i = i * gain / 0x7fff;
 
+               if (effect->u.rumble.strong_magnitude + i)
+                       effect->direction = ml_calculate_direction(
+                               effect->direction,
+                               effect->u.rumble.strong_magnitude,
+                               new->direction, i);
+               else
+                       effect->direction = 0;
                effect->u.rumble.strong_magnitude =
                        min(i + effect->u.rumble.strong_magnitude, 0xffffU);
                effect->u.rumble.weak_magnitude =
@@ -411,8 +447,6 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
                                 msecs_to_jiffies(state->effect->replay.length);
                state->adj_at = state->play_at;
 
-               ml_schedule_timer(ml);
-
        } else {
                debug("initiated stop");
 
@@ -420,10 +454,10 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
                        __set_bit(FF_EFFECT_ABORTING, &state->flags);
                else
                        __clear_bit(FF_EFFECT_STARTED, &state->flags);
-
-               ml_play_effects(ml);
        }
 
+       ml_play_effects(ml);
+
        return 0;
 }
 
index f6c688cae33430e877cf88e39f2bfda4553ef145..b1edd778639c6f1fb2985e782e7a731e42bca2cb 100644 (file)
@@ -210,7 +210,7 @@ static int iforce_open(struct input_dev *dev)
        return 0;
 }
 
-static void iforce_release(struct input_dev *dev)
+static void iforce_close(struct input_dev *dev)
 {
        struct iforce *iforce = input_get_drvdata(dev);
        int i;
@@ -228,30 +228,17 @@ static void iforce_release(struct input_dev *dev)
 
                /* Disable force feedback playback */
                iforce_send_packet(iforce, FF_CMD_ENABLE, "\001");
+               /* Wait for the command to complete */
+               wait_event_interruptible(iforce->wait,
+                       !test_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags));
        }
 
-       switch (iforce->bus) {
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
-               case IFORCE_USB:
-                       usb_kill_urb(iforce->irq);
-
-                       /* The device was unplugged before the file
-                        * was released */
-                       if (iforce->usbdev == NULL) {
-                               iforce_delete_device(iforce);
-                               kfree(iforce);
-                       }
-               break;
-#endif
-       }
-}
-
-void iforce_delete_device(struct iforce *iforce)
-{
        switch (iforce->bus) {
 #ifdef CONFIG_JOYSTICK_IFORCE_USB
        case IFORCE_USB:
-               iforce_usb_delete(iforce);
+               usb_kill_urb(iforce->irq);
+               usb_kill_urb(iforce->out);
+               usb_kill_urb(iforce->ctrl);
                break;
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
@@ -303,7 +290,7 @@ int iforce_init_device(struct iforce *iforce)
 
        input_dev->name = "Unknown I-Force device";
        input_dev->open = iforce_open;
-       input_dev->close = iforce_release;
+       input_dev->close = iforce_close;
 
 /*
  * On-device memory allocation.
index 9f289d8f52c6e70dc0b6c28c0583291e46cdadaa..b41303d3ec54c339428e60cc4684b727050e4af8 100644 (file)
@@ -109,6 +109,7 @@ static void iforce_usb_out(struct urb *urb)
        struct iforce *iforce = urb->context;
 
        if (urb->status) {
+               clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
                dbg("urb->status %d, exiting", urb->status);
                return;
        }
@@ -186,33 +187,19 @@ fail:
        return err;
 }
 
-/* Called by iforce_delete() */
-void iforce_usb_delete(struct iforce* iforce)
-{
-       usb_kill_urb(iforce->irq);
-       usb_kill_urb(iforce->out);
-       usb_kill_urb(iforce->ctrl);
-
-       usb_free_urb(iforce->irq);
-       usb_free_urb(iforce->out);
-       usb_free_urb(iforce->ctrl);
-}
-
 static void iforce_usb_disconnect(struct usb_interface *intf)
 {
        struct iforce *iforce = usb_get_intfdata(intf);
-       int open = 0; /* FIXME! iforce->dev.handle->open; */
 
        usb_set_intfdata(intf, NULL);
-       if (iforce) {
-               iforce->usbdev = NULL;
-               input_unregister_device(iforce->dev);
 
-               if (!open) {
-                       iforce_delete_device(iforce);
-                       kfree(iforce);
-               }
-       }
+       input_unregister_device(iforce->dev);
+
+       usb_free_urb(iforce->irq);
+       usb_free_urb(iforce->out);
+       usb_free_urb(iforce->ctrl);
+
+       kfree(iforce);
 }
 
 static struct usb_device_id iforce_usb_ids [] = {
index f2d91f4028cace50888876ef28685c3eff2cb44d..9f494b75848abc7514c53417a73e627454ba44ad 100644 (file)
@@ -150,11 +150,9 @@ void iforce_serial_xmit(struct iforce *iforce);
 
 /* iforce-usb.c */
 void iforce_usb_xmit(struct iforce *iforce);
-void iforce_usb_delete(struct iforce *iforce);
 
 /* iforce-main.c */
 int iforce_init_device(struct iforce *iforce);
-void iforce_delete_device(struct iforce *iforce);
 
 /* iforce-packets.c */
 int iforce_control_playback(struct iforce*, u16 id, unsigned int);
index a3573570c52fbb3ec712c9d977c16d1e512f2bae..1f5e2ce327d6403e2042cc9179b9fc754e37c089 100644 (file)
@@ -134,7 +134,8 @@ static const unsigned short atkbd_unxlate_table[128] = {
 #define ATKBD_CMD_GETID                0x02f2
 #define ATKBD_CMD_SETREP       0x10f3
 #define ATKBD_CMD_ENABLE       0x00f4
-#define ATKBD_CMD_RESET_DIS    0x00f5
+#define ATKBD_CMD_RESET_DIS    0x00f5  /* Reset to defaults and disable */
+#define ATKBD_CMD_RESET_DEF    0x00f6  /* Reset to defaults */
 #define ATKBD_CMD_SETALL_MBR   0x00fa
 #define ATKBD_CMD_RESET_BAT    0x02ff
 #define ATKBD_CMD_RESEND       0x00fe
@@ -836,7 +837,7 @@ static void atkbd_cleanup(struct serio *serio)
        struct atkbd *atkbd = serio_get_drvdata(serio);
 
        atkbd_disable(atkbd);
-       ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT);
+       ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF);
 }
 
 
index 34f4a29d497313f84dbfffd6d107deff1f2b79cc..d3c8b61a941d46aa677e8f13dff3aba9edcb6f56 100644 (file)
@@ -29,11 +29,13 @@ struct matrix_keypad {
        unsigned short *keycodes;
        unsigned int row_shift;
 
+       DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS);
+
        uint32_t last_key_state[MATRIX_MAX_COLS];
        struct delayed_work work;
+       spinlock_t lock;
        bool scan_pending;
        bool stopped;
-       spinlock_t lock;
 };
 
 /*
@@ -222,9 +224,16 @@ static int matrix_keypad_suspend(struct device *dev)
 
        matrix_keypad_stop(keypad->input_dev);
 
-       if (device_may_wakeup(&pdev->dev))
-               for (i = 0; i < pdata->num_row_gpios; i++)
-                       enable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
+       if (device_may_wakeup(&pdev->dev)) {
+               for (i = 0; i < pdata->num_row_gpios; i++) {
+                       if (!test_bit(i, keypad->disabled_gpios)) {
+                               unsigned int gpio = pdata->row_gpios[i];
+
+                               if (enable_irq_wake(gpio_to_irq(gpio)) == 0)
+                                       __set_bit(i, keypad->disabled_gpios);
+                       }
+               }
+       }
 
        return 0;
 }
@@ -236,9 +245,15 @@ static int matrix_keypad_resume(struct device *dev)
        const struct matrix_keypad_platform_data *pdata = keypad->pdata;
        int i;
 
-       if (device_may_wakeup(&pdev->dev))
-               for (i = 0; i < pdata->num_row_gpios; i++)
-                       disable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
+       if (device_may_wakeup(&pdev->dev)) {
+               for (i = 0; i < pdata->num_row_gpios; i++) {
+                       if (test_and_clear_bit(i, keypad->disabled_gpios)) {
+                               unsigned int gpio = pdata->row_gpios[i];
+
+                               disable_irq_wake(gpio_to_irq(gpio));
+                       }
+               }
+       }
 
        matrix_keypad_start(keypad->input_dev);
 
index eeaa7acb9cfcfcc4ebf847a7035874a60c169d72..21d6184efa96059ed773b6f63a09e3d37025686f 100644 (file)
@@ -253,14 +253,6 @@ static irqreturn_t do_kp_irq(int irq, void *_kp)
        u8 reg;
        int ret;
 
-#ifdef CONFIG_LOCKDEP
-       /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
-        * we don't want and can't tolerate.  Although it might be
-        * friendlier not to borrow this thread context...
-        */
-       local_irq_enable();
-#endif
-
        /* Read & Clear TWL4030 pending interrupt */
        ret = twl4030_kpread(kp, &reg, KEYP_ISR1, 1);
 
@@ -403,7 +395,8 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev)
         *
         * NOTE:  we assume this host is wired to TWL4040 INT1, not INT2 ...
         */
-       error = request_irq(kp->irq, do_kp_irq, 0, pdev->name, kp);
+       error = request_threaded_irq(kp->irq, NULL, do_kp_irq,
+                       0, pdev->name, kp);
        if (error) {
                dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n",
                        kp->irq);
index bdde5c8890358aa9ea7025008c93501f098b370d..e9069b87fde235f10ee810a9cdfb3eb79ed89df5 100644 (file)
@@ -39,18 +39,8 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr)
        int err;
        u8 value;
 
-#ifdef CONFIG_LOCKDEP
-       /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
-        * we don't want and can't tolerate since this is a threaded
-        * IRQ and can sleep due to the i2c reads it has to issue.
-        * Although it might be friendlier not to borrow this thread
-        * context...
-        */
-       local_irq_enable();
-#endif
-
        err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value,
-                                 STS_HW_CONDITIONS);
+                               STS_HW_CONDITIONS);
        if (!err)  {
                input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ);
                input_sync(pwr);
@@ -80,7 +70,7 @@ static int __devinit twl4030_pwrbutton_probe(struct platform_device *pdev)
        pwr->phys = "twl4030_pwrbutton/input0";
        pwr->dev.parent = &pdev->dev;
 
-       err = request_irq(irq, powerbutton_irq,
+       err = request_threaded_irq(irq, NULL, powerbutton_irq,
                        IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
                        "twl4030_pwrbutton", pwr);
        if (err < 0) {
index 38da6ab043846a8b8874e51bdca70ec95885f5d6..c0afb71a3a6d7a34919a8a32f98731a3b28e8001 100644 (file)
@@ -1328,7 +1328,7 @@ static struct platform_driver wistron_driver = {
        .driver         = {
                .name   = "wistron-bios",
                .owner  = THIS_MODULE,
-#if CONFIG_PM
+#ifdef CONFIG_PM
                .pm     = &wistron_pm_ops,
 #endif
        },
index 3feeb3af8abd798f0fd544ecc12f888f1068c688..c714ca2407f8a190d247f3f8eb21d96edb577ac3 100644 (file)
@@ -70,7 +70,7 @@ config MOUSE_PS2_SYNAPTICS
 config MOUSE_PS2_LIFEBOOK
        bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED
        default y
-       depends on MOUSE_PS2 && X86
+       depends on MOUSE_PS2 && X86 && DMI
        help
          Say Y here if you have a Fujitsu B-series Lifebook PS/2
          TouchScreen connected to your system.
index b146237266d82610cf7a6a130e3e524a72f61ee2..90be30e9355606cbc0e50971fc4381c5b429952e 100644 (file)
@@ -427,7 +427,6 @@ static void hgpk_recalib_work(struct work_struct *work)
 
 static int hgpk_register(struct psmouse *psmouse)
 {
-       struct input_dev *dev = psmouse->dev;
        int err;
 
        /* register handlers */
index 2e6bdfea01651ad2764e3b0d053ccd53556535de..6d7aa10d10f002ae66388b0bf4ec23e58afecc90 100644 (file)
@@ -44,7 +44,6 @@ static int lifebook_set_6byte_proto(const struct dmi_system_id *d)
 }
 
 static const struct dmi_system_id __initconst lifebook_dmi_table[] = {
-#if defined(CONFIG_DMI) && defined(CONFIG_X86)
        {
                /* FLORA-ie 55mi */
                .matches = {
@@ -118,7 +117,6 @@ static const struct dmi_system_id __initconst lifebook_dmi_table[] = {
                },
        },
        { }
-#endif
 };
 
 void __init lifebook_module_init(void)
index fd0bc094616acbf2a3b027649840541516b647a1..401ac6b6edd43cca18b73b1663f731856f4f909b 100644 (file)
@@ -1137,7 +1137,10 @@ static void psmouse_cleanup(struct serio *serio)
        if (psmouse->cleanup)
                psmouse->cleanup(psmouse);
 
-       psmouse_reset(psmouse);
+/*
+ * Reset the mouse to defaults (bare PS/2 protocol).
+ */
+       ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
 
 /*
  * Some boxes, such as HP nx7400, get terribly confused if mouse
index 0236f0d5fd9156319f01abf3dd4f7d7cf6d2972f..e0f30186d513d4633649beeb9a7f73e361c7d972 100644 (file)
@@ -284,13 +284,7 @@ static void serio_handle_event(void)
 
        mutex_lock(&serio_mutex);
 
-       /*
-        * Note that we handle only one event here to give swsusp
-        * a chance to freeze kseriod thread. Serio events should
-        * be pretty rare so we are not concerned about taking
-        * performance hit.
-        */
-       if ((event = serio_get_event())) {
+       while ((event = serio_get_event())) {
 
                switch (event->type) {
                        case SERIO_REGISTER_PORT:
@@ -380,10 +374,9 @@ static struct serio *serio_get_pending_child(struct serio *parent)
 
 static int serio_thread(void *nothing)
 {
-       set_freezable();
        do {
                serio_handle_event();
-               wait_event_freezable(serio_wait,
+               wait_event_interruptible(serio_wait,
                        kthread_should_stop() || !list_empty(&serio_event_list));
        } while (!kthread_should_stop());
 
index 951c57b0a7e075a9d927193d3c54d46ccb682545..ede46581351a04d9a635aee91bec38d69c67c76f 100644 (file)
@@ -179,8 +179,10 @@ void load_guest_gdt_entry(struct lg_cpu *cpu, u32 num, u32 lo, u32 hi)
         * We assume the Guest has the same number of GDT entries as the
         * Host, otherwise we'd have to dynamically allocate the Guest GDT.
         */
-       if (num >= ARRAY_SIZE(cpu->arch.gdt))
+       if (num >= ARRAY_SIZE(cpu->arch.gdt)) {
                kill_guest(cpu, "too many gdt entries %i", num);
+               return;
+       }
 
        /* Set it up, then fix it. */
        cpu->arch.gdt[num].a = lo;
index f4f5f82f9f533109fff1898e14d7e30824c62d53..dd3dfe42d5a9d081c590018f1ac6325cfecdaf12 100644 (file)
@@ -386,7 +386,9 @@ static void mddev_put(mddev_t *mddev)
        if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock))
                return;
        if (!mddev->raid_disks && list_empty(&mddev->disks) &&
-           !mddev->hold_active) {
+           mddev->ctime == 0 && !mddev->hold_active) {
+               /* Array is not configured at all, and not held active,
+                * so destroy it */
                list_del(&mddev->all_mddevs);
                if (mddev->gendisk) {
                        /* we did a probe so need to clean up.
@@ -4355,7 +4357,7 @@ static int do_md_run(mddev_t * mddev)
        mddev->barriers_work = 1;
        mddev->ok_start_degraded = start_dirty_degraded;
 
-       if (start_readonly)
+       if (start_readonly && mddev->ro == 0)
                mddev->ro = 2; /* read-only, but switch on first write */
 
        err = mddev->pers->run(mddev);
@@ -4419,33 +4421,6 @@ static int do_md_run(mddev_t * mddev)
 
        set_capacity(disk, mddev->array_sectors);
 
-       /* If there is a partially-recovered drive we need to
-        * start recovery here.  If we leave it to md_check_recovery,
-        * it will remove the drives and not do the right thing
-        */
-       if (mddev->degraded && !mddev->sync_thread) {
-               int spares = 0;
-               list_for_each_entry(rdev, &mddev->disks, same_set)
-                       if (rdev->raid_disk >= 0 &&
-                           !test_bit(In_sync, &rdev->flags) &&
-                           !test_bit(Faulty, &rdev->flags))
-                               /* complete an interrupted recovery */
-                               spares++;
-               if (spares && mddev->pers->sync_request) {
-                       mddev->recovery = 0;
-                       set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
-                       mddev->sync_thread = md_register_thread(md_do_sync,
-                                                               mddev,
-                                                               "resync");
-                       if (!mddev->sync_thread) {
-                               printk(KERN_ERR "%s: could not start resync"
-                                      " thread...\n",
-                                      mdname(mddev));
-                               /* leave the spares where they are, it shouldn't hurt */
-                               mddev->recovery = 0;
-                       }
-               }
-       }
        md_wakeup_thread(mddev->thread);
        md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
 
@@ -5262,6 +5237,10 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
                mddev->minor_version = info->minor_version;
                mddev->patch_version = info->patch_version;
                mddev->persistent = !info->not_persistent;
+               /* ensure mddev_put doesn't delete this now that there
+                * is some minimal configuration.
+                */
+               mddev->ctime         = get_seconds();
                return 0;
        }
        mddev->major_version = MD_MAJOR_VERSION;
@@ -6494,10 +6473,11 @@ void md_do_sync(mddev_t *mddev)
                mddev->curr_resync = 2;
 
        try_again:
-               if (kthread_should_stop()) {
+               if (kthread_should_stop())
                        set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+
+               if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
                        goto skip;
-               }
                for_each_mddev(mddev2, tmp) {
                        if (mddev2 == mddev)
                                continue;
index fe44789ab03793fed09a9740e8622b9b798ceadc..6223bf01efe96893db6662bd5e308a8a59af6333 100644 (file)
@@ -202,14 +202,8 @@ static void handle_fcp(struct fw_card *card, struct fw_request *request,
        unsigned long flags;
        int su;
 
-       if ((tcode != TCODE_WRITE_QUADLET_REQUEST &&
-            tcode != TCODE_WRITE_BLOCK_REQUEST) ||
-           offset != CSR_REGISTER_BASE + CSR_FCP_RESPONSE ||
-           length == 0 ||
-           (((u8 *)payload)[0] & 0xf0) != 0) {
-               fw_send_response(card, request, RCODE_TYPE_ERROR);
+       if (length < 2 || (((u8 *)payload)[0] & 0xf0) != 0)
                return;
-       }
 
        su = ((u8 *)payload)[1] & 0x7;
 
@@ -230,10 +224,8 @@ static void handle_fcp(struct fw_card *card, struct fw_request *request,
        }
        spin_unlock_irqrestore(&node_list_lock, flags);
 
-       if (fdtv) {
+       if (fdtv)
                avc_recv(fdtv, payload, length);
-               fw_send_response(card, request, RCODE_COMPLETE);
-       }
 }
 
 static struct fw_address_handler fcp_handler = {
index efba7021948ab8f92c34c80e29c255a72e1fc70e..3d5f40cd69df2e70d5d1ffee42b91e31d36473e4 100644 (file)
@@ -40,8 +40,7 @@
 
 #define SG_TABLESIZE           30
 
-static int i2o_cfg_ioctl(struct inode *, struct file *, unsigned int,
-                        unsigned long);
+static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long);
 
 static spinlock_t i2o_config_lock;
 
@@ -751,7 +750,7 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
        lock_kernel();
        switch (cmd) {
        case I2OGETIOPS:
-               ret = i2o_cfg_ioctl(NULL, file, cmd, arg);
+               ret = i2o_cfg_ioctl(file, cmd, arg);
                break;
        case I2OPASSTHRU32:
                ret = i2o_cfg_passthru32(file, cmd, arg);
@@ -984,11 +983,11 @@ out:
 /*
  * IOCTL Handler
  */
-static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
-                        unsigned long arg)
+static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 {
        int ret;
 
+       lock_kernel();
        switch (cmd) {
        case I2OGETIOPS:
                ret = i2o_cfg_getiops(arg);
@@ -1044,7 +1043,7 @@ static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
                osm_debug("unknown ioctl called!\n");
                ret = -EINVAL;
        }
-
+       unlock_kernel();
        return ret;
 }
 
@@ -1118,7 +1117,7 @@ static int cfg_release(struct inode *inode, struct file *file)
 static const struct file_operations config_fops = {
        .owner = THIS_MODULE,
        .llseek = no_llseek,
-       .ioctl = i2o_cfg_ioctl,
+       .unlocked_ioctl = i2o_cfg_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl = i2o_cfg_compat_ioctl,
 #endif
index 20d29bafc9f5bc79477fcca4da0e567f17a58563..9df9a5ad38f9142ebc0c53e58d51541a0a0c133f 100644 (file)
@@ -568,12 +568,12 @@ static void twl4030_sih_do_edge(struct work_struct *work)
 
                bytes[byte] &= ~(0x03 << off);
 
-               spin_lock_irq(&d->lock);
+               raw_spin_lock_irq(&d->lock);
                if (d->status & IRQ_TYPE_EDGE_RISING)
                        bytes[byte] |= BIT(off + 1);
                if (d->status & IRQ_TYPE_EDGE_FALLING)
                        bytes[byte] |= BIT(off + 0);
-               spin_unlock_irq(&d->lock);
+               raw_spin_unlock_irq(&d->lock);
 
                edge_change &= ~BIT(i);
        }
index 85f0e8cd875bac4f153788ff0012fc0b27e05dd5..1f552c6e7579b5a42a665e89a69b5e7f798d161c 100644 (file)
@@ -85,7 +85,14 @@ static void mmc_blk_put(struct mmc_blk_data *md)
        mutex_lock(&open_lock);
        md->usage--;
        if (md->usage == 0) {
+               int devmaj = MAJOR(disk_devt(md->disk));
                int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT;
+
+               if (!devmaj)
+                       devidx = md->disk->first_minor >> MMC_SHIFT;
+
+               blk_cleanup_queue(md->queue.queue);
+
                __clear_bit(devidx, dev_use);
 
                put_disk(md->disk);
@@ -613,6 +620,7 @@ static int mmc_blk_probe(struct mmc_card *card)
        return 0;
 
  out:
+       mmc_cleanup_queue(&md->queue);
        mmc_blk_put(md);
 
        return err;
index 49e582356c65ab34bc17b1db1bbae002bc5faaff..c5a7a855f4b1c5f0a8ad7472a8f7896127d03ea8 100644 (file)
@@ -90,9 +90,10 @@ static void mmc_request(struct request_queue *q)
        struct request *req;
 
        if (!mq) {
-               printk(KERN_ERR "MMC: killing requests for dead queue\n");
-               while ((req = blk_fetch_request(q)) != NULL)
+               while ((req = blk_fetch_request(q)) != NULL) {
+                       req->cmd_flags |= REQ_QUIET;
                        __blk_end_request_all(req, -EIO);
+               }
                return;
        }
 
@@ -223,17 +224,18 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
        struct request_queue *q = mq->queue;
        unsigned long flags;
 
-       /* Mark that we should start throwing out stragglers */
-       spin_lock_irqsave(q->queue_lock, flags);
-       q->queuedata = NULL;
-       spin_unlock_irqrestore(q->queue_lock, flags);
-
        /* Make sure the queue isn't suspended, as that will deadlock */
        mmc_queue_resume(mq);
 
        /* Then terminate our worker thread */
        kthread_stop(mq->thread);
 
+       /* Empty the queue */
+       spin_lock_irqsave(q->queue_lock, flags);
+       q->queuedata = NULL;
+       blk_start_queue(q);
+       spin_unlock_irqrestore(q->queue_lock, flags);
+
        if (mq->bounce_sg)
                kfree(mq->bounce_sg);
        mq->bounce_sg = NULL;
@@ -245,8 +247,6 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
                kfree(mq->bounce_buf);
        mq->bounce_buf = NULL;
 
-       blk_cleanup_queue(mq->queue);
-
        mq->card = NULL;
 }
 EXPORT_SYMBOL(mmc_cleanup_queue);
index c11189446a1f70cd93bcf778e89a41ca06eeac52..0eac6c81490462fb640d768edbbdec54659510fa 100644 (file)
@@ -207,7 +207,7 @@ static int mmc_read_ext_csd(struct mmc_card *card)
        }
 
        card->ext_csd.rev = ext_csd[EXT_CSD_REV];
-       if (card->ext_csd.rev > 3) {
+       if (card->ext_csd.rev > 5) {
                printk(KERN_ERR "%s: unrecognised EXT_CSD structure "
                        "version %d\n", mmc_hostname(card->host),
                        card->ext_csd.rev);
index fbc231153e555f41b8c341670db078c8d7b21520..77cf0901a441146b99292755353d25bfd50222ae 100644 (file)
@@ -56,6 +56,7 @@ static const char version[] =
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/if_ether.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -734,8 +735,7 @@ static void init_82586_mem(struct net_device *dev)
        memcpy_toio(lp->base, init_words + 5, sizeof(init_words) - 10);
 
        /* Fill in the station address. */
-       memcpy_toio(lp->base+SA_OFFSET, dev->dev_addr,
-                  sizeof(dev->dev_addr));
+       memcpy_toio(lp->base+SA_OFFSET, dev->dev_addr, ETH_ALEN);
 
        /* The Tx-block list is written as needed.  We just set up the values. */
        lp->tx_cmd_link = IDLELOOP + 4;
index e58a65391ad2b581bb6aae3bba3ebf464655252c..dd9a09c72dfff2b080f09499a4afe8d6b2ad68ad 100644 (file)
@@ -2346,6 +2346,7 @@ config GELIC_NET
 
 config GELIC_WIRELESS
        bool "PS3 Wireless support"
+       depends on WLAN
        depends on GELIC_NET
        select WIRELESS_EXT
        help
@@ -2358,6 +2359,7 @@ config GELIC_WIRELESS
 config GELIC_WIRELESS_OLD_PSK_INTERFACE
        bool "PS3 Wireless private PSK interface (OBSOLETE)"
        depends on GELIC_WIRELESS
+       select WEXT_PRIV
        help
           This option retains the obsolete private interface to pass
           the PSK from user space programs to the driver.  The PSK
index c37ee9e6b67b93c989de07689c0c47bad7150d50..39e1c0d39476f8adca7f9dc772fe69db83804376 100644 (file)
@@ -68,6 +68,7 @@ config W90P910_ETH
        tristate "Nuvoton w90p910 Ethernet support"
        depends on ARM && ARCH_W90X900
        select PHYLIB
+       select MII
        help
          Say Y here if you want to use built-in Ethernet ports
          on w90p910 processor.
index 9e56014d27edad57c88bb19f36eb05559f28c344..9fd8e5ecd5d75dcd81cf30827fd2257ba50d1284 100644 (file)
@@ -275,6 +275,7 @@ struct be_adapter {
        u32 tx_fc;              /* Tx flow control */
        int link_speed;
        u8 port_type;
+       u8 transceiver;
 };
 
 extern const struct ethtool_ops be_ethtool_ops;
index 1b68bd98dc0c1955dfc6c33b5bb00875835a6b06..102ade13416526066e3639519beaf4f497bc8830 100644 (file)
@@ -1479,6 +1479,41 @@ err:
        return status;
 }
 
+int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
+                       u8 loopback_type, u8 enable)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_set_lmode *req;
+       int status;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = embedded_payload(wrb);
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+                               OPCODE_LOWLEVEL_SET_LOOPBACK_MODE);
+
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
+                       OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
+                       sizeof(*req));
+
+       req->src_port = port_num;
+       req->dest_port = port_num;
+       req->loopback_type = loopback_type;
+       req->loopback_state = enable;
+
+       status = be_mcc_notify_wait(adapter);
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
 int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
                u32 loopback_type, u32 pkt_size, u32 num_pkts, u64 pattern)
 {
@@ -1501,6 +1536,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
                        OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req));
+       req->hdr.timeout = 4;
 
        req->pattern = cpu_to_le64(pattern);
        req->src_port = cpu_to_le32(port_num);
index 92b87ef156ed912f8ff998cb3c7db7135aa8b6af..c002b8391b4dc18c24e0a6e4b48a8e39ff9549b1 100644 (file)
@@ -155,6 +155,7 @@ struct be_mcc_mailbox {
 
 #define OPCODE_LOWLEVEL_HOST_DDR_DMA                    17
 #define OPCODE_LOWLEVEL_LOOPBACK_TEST                   18
+#define OPCODE_LOWLEVEL_SET_LOOPBACK_MODE              19
 
 struct be_cmd_req_hdr {
        u8 opcode;              /* dword 0 */
@@ -821,6 +822,19 @@ struct be_cmd_resp_loopback_test {
        u32    ticks_compl;
 };
 
+struct be_cmd_req_set_lmode {
+       struct be_cmd_req_hdr hdr;
+       u8 src_port;
+       u8 dest_port;
+       u8 loopback_type;
+       u8 loopback_state;
+};
+
+struct be_cmd_resp_set_lmode {
+       struct be_cmd_resp_hdr resp_hdr;
+       u8 rsvd0[4];
+};
+
 /********************** DDR DMA test *********************/
 struct be_cmd_req_ddrdma_test {
        struct be_cmd_req_hdr hdr;
@@ -912,3 +926,5 @@ extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
                                u32 num_pkts, u64 pattern);
 extern int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
                        u32 byte_cnt, struct be_dma_mem *cmd);
+extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
+                               u8 loopback_type, u8 enable);
index 298b92cbd68948e3d54893a7e8f11885bda7c01c..5d001c4deac1d3b8684c91261cb0c15769c96cfa 100644 (file)
@@ -118,6 +118,7 @@ static const char et_self_tests[][ETH_GSTRING_LEN] = {
 #define BE_MAC_LOOPBACK 0x0
 #define BE_PHY_LOOPBACK 0x1
 #define BE_ONE_PORT_EXT_LOOPBACK 0x2
+#define BE_NO_LOOPBACK 0xff
 
 static void
 be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
@@ -339,28 +340,50 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 
                status = be_cmd_read_port_type(adapter, adapter->port_num,
                                                &connector);
-               switch (connector) {
-               case 7:
-                       ecmd->port = PORT_FIBRE;
-                       break;
-               default:
-                       ecmd->port = PORT_TP;
-                       break;
+               if (!status) {
+                       switch (connector) {
+                       case 7:
+                               ecmd->port = PORT_FIBRE;
+                               ecmd->transceiver = XCVR_EXTERNAL;
+                               break;
+                       case 0:
+                               ecmd->port = PORT_TP;
+                               ecmd->transceiver = XCVR_EXTERNAL;
+                               break;
+                       default:
+                               ecmd->port = PORT_TP;
+                               ecmd->transceiver = XCVR_INTERNAL;
+                               break;
+                       }
+               } else {
+                       ecmd->port = PORT_AUI;
+                       ecmd->transceiver = XCVR_INTERNAL;
                }
 
                /* Save for future use */
                adapter->link_speed = ecmd->speed;
                adapter->port_type = ecmd->port;
+               adapter->transceiver = ecmd->transceiver;
        } else {
                ecmd->speed = adapter->link_speed;
                ecmd->port = adapter->port_type;
+               ecmd->transceiver = adapter->transceiver;
        }
 
        ecmd->duplex = DUPLEX_FULL;
        ecmd->autoneg = AUTONEG_DISABLE;
-       ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP);
        ecmd->phy_address = adapter->port_num;
-       ecmd->transceiver = XCVR_INTERNAL;
+       switch (ecmd->port) {
+       case PORT_FIBRE:
+               ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+               break;
+       case PORT_TP:
+               ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP);
+               break;
+       case PORT_AUI:
+               ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_AUI);
+               break;
+       }
 
        return 0;
 }
@@ -489,6 +512,19 @@ err:
        return ret;
 }
 
+static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type,
+                               u64 *status)
+{
+       be_cmd_set_loopback(adapter, adapter->port_num,
+                               loopback_type, 1);
+       *status = be_cmd_loopback_test(adapter, adapter->port_num,
+                               loopback_type, 1500,
+                               2, 0xabc);
+       be_cmd_set_loopback(adapter, adapter->port_num,
+                               BE_NO_LOOPBACK, 1);
+       return *status;
+}
+
 static void
 be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
 {
@@ -497,23 +533,18 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
        memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM);
 
        if (test->flags & ETH_TEST_FL_OFFLINE) {
-               data[0] = be_cmd_loopback_test(adapter, adapter->port_num,
-                                               BE_MAC_LOOPBACK, 1500,
-                                               2, 0xabc);
-               if (data[0] != 0)
+               if (be_loopback_test(adapter, BE_MAC_LOOPBACK,
+                                               &data[0]) != 0) {
                        test->flags |= ETH_TEST_FL_FAILED;
-
-               data[1] = be_cmd_loopback_test(adapter, adapter->port_num,
-                                               BE_PHY_LOOPBACK, 1500,
-                                               2, 0xabc);
-               if (data[1] != 0)
+               }
+               if (be_loopback_test(adapter, BE_PHY_LOOPBACK,
+                                               &data[1]) != 0) {
                        test->flags |= ETH_TEST_FL_FAILED;
-
-               data[2] = be_cmd_loopback_test(adapter, adapter->port_num,
-                                               BE_ONE_PORT_EXT_LOOPBACK,
-                                               1500, 2, 0xabc);
-               if (data[2] != 0)
+               }
+               if (be_loopback_test(adapter, BE_ONE_PORT_EXT_LOOPBACK,
+                                               &data[2]) != 0) {
                        test->flags |= ETH_TEST_FL_FAILED;
+               }
 
                data[3] = be_test_ddr_dma(adapter);
                if (data[3] != 0)
index 77ba13520d87ae539854da167551892655b3ec3d..306c2b8165e242c8400d6b416de9cc201540484a 100644 (file)
@@ -7593,6 +7593,8 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) {
                        bnx2x_set_iscsi_eth_mac_addr(bp, 1);
                        bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET;
+                       bnx2x_init_sb(bp, bp->cnic_sb, bp->cnic_sb_mapping,
+                                     CNIC_SB_ID(bp));
                }
                mutex_unlock(&bp->cnic_mutex);
 #endif
index 0fb7a4964e7560c93d2a44fbd85d925646690099..822f586d72afa67d8abd5c606f38b11f60f0147d 100644 (file)
@@ -1580,7 +1580,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
                // check if any partner replys
                if (best->is_individual) {
                        pr_warning("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
-                                  best->slave->dev->master->name);
+                                  best->slave ? best->slave->dev->master->name : "NULL");
                }
 
                best->is_active = 1;
index e0620d0846440ca9c38b26e7370d85851eb05bcc..8bd3c9f17532529e6f3c445024f9e5e4c8d6ac96 100644 (file)
@@ -143,7 +143,6 @@ void gfar_start(struct net_device *dev);
 static void gfar_clear_exact_match(struct net_device *dev);
 static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
 static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-u16 gfar_select_queue(struct net_device *dev, struct sk_buff *skb);
 
 MODULE_AUTHOR("Freescale Semiconductor, Inc");
 MODULE_DESCRIPTION("Gianfar Ethernet Driver");
@@ -455,7 +454,6 @@ static const struct net_device_ops gfar_netdev_ops = {
        .ndo_set_multicast_list = gfar_set_multi,
        .ndo_tx_timeout = gfar_timeout,
        .ndo_do_ioctl = gfar_ioctl,
-       .ndo_select_queue = gfar_select_queue,
        .ndo_get_stats = gfar_get_stats,
        .ndo_vlan_rx_register = gfar_vlan_rx_register,
        .ndo_set_mac_address = eth_mac_addr,
@@ -506,10 +504,6 @@ static inline int gfar_uses_fcb(struct gfar_private *priv)
        return priv->vlgrp || priv->rx_csum_enable;
 }
 
-u16 gfar_select_queue(struct net_device *dev, struct sk_buff *skb)
-{
-       return skb_get_queue_mapping(skb);
-}
 static void free_tx_pointers(struct gfar_private *priv)
 {
        int i = 0;
@@ -2470,10 +2464,11 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
        fcb = (struct rxfcb *)skb->data;
 
        /* Remove the FCB from the skb */
-       skb_set_queue_mapping(skb, fcb->rq);
        /* Remove the padded bytes, if there are any */
-       if (amount_pull)
+       if (amount_pull) {
+               skb_record_rx_queue(skb, fcb->rq);
                skb_pull(skb, amount_pull);
+       }
 
        if (priv->rx_csum_enable)
                gfar_rx_checksum(skb, fcb);
@@ -2554,7 +2549,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
                                /* Remove the FCS from the packet length */
                                skb_put(skb, pkt_len);
                                rx_queue->stats.rx_bytes += pkt_len;
-
+                               skb_record_rx_queue(skb, rx_queue->qindex);
                                gfar_process_frame(dev, skb, amount_pull);
 
                        } else {
index 090a6d3af11212caefdb8abe794aa063d12b0823..052c74091d91065c6c419149361a92cfad6cb844 100644 (file)
@@ -87,6 +87,7 @@ History:
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/if_ether.h>
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
 
@@ -988,7 +989,7 @@ static int __devinit ibmlana_init_one(struct device *kdev)
 
        /* copy out MAC address */
 
-       for (z = 0; z < sizeof(dev->dev_addr); z++)
+       for (z = 0; z < ETH_ALEN; z++)
                dev->dev_addr[z] = inb(dev->base_addr + MACADDRPROM + z);
 
        /* print config */
index e8e9e9194a8825c29cb9008e49c566b8e873be12..c505b50d1fa32930164a250f82cd9d749bdaec98 100644 (file)
@@ -1096,9 +1096,7 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
                hw_dbg("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
        } else {
                /* Set PCS register for forced link */
-               reg |= E1000_PCS_LCTL_FSD |        /* Force Speed */
-                      E1000_PCS_LCTL_FORCE_LINK | /* Force Link */
-                      E1000_PCS_LCTL_FLV_LINK_UP; /* Force link value up */
+               reg |= E1000_PCS_LCTL_FSD;        /* Force Speed */
 
                hw_dbg("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
        }
index 5c9d73e9bb8d8733fe926bf6c9d7c9073fe5c35a..3670a66401b87923d5ff3dc82cc67f1701cc4986 100644 (file)
@@ -457,15 +457,6 @@ s32 igb_copper_link_setup_82580(struct e1000_hw *hw)
        phy_data |= I82580_CFG_ENABLE_DOWNSHIFT;
 
        ret_val = phy->ops.write_reg(hw, I82580_CFG_REG, phy_data);
-       if (ret_val)
-               goto out;
-
-       /* Set number of link attempts before downshift */
-       ret_val = phy->ops.read_reg(hw, I82580_CTRL_REG, &phy_data);
-       if (ret_val)
-               goto out;
-       phy_data &= ~I82580_CTRL_DOWNSHIFT_MASK;
-       ret_val = phy->ops.write_reg(hw, I82580_CTRL_REG, phy_data);
 
 out:
        return ret_val;
index ac9d5272650dbee362ded07308ea8cac651bab32..f771a6c08777c8438db7f25e37e388089464ccae 100644 (file)
@@ -1795,7 +1795,7 @@ static int igb_wol_exclusion(struct igb_adapter *adapter,
                /* dual port cards only support WoL on port A from now on
                 * unless it was enabled in the eeprom for port B
                 * so exclude FUNC_1 ports from having WoL enabled */
-               if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1 &&
+               if ((rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) &&
                    !adapter->eeprom_wol) {
                        wol->supported = 0;
                        break;
index 78963a0e128dcf4171c9d8a8d1ac579c0b529d15..933c64ff24657d362a2d3e34cb1c525c04826bb6 100644 (file)
@@ -1306,13 +1306,8 @@ void igb_reset(struct igb_adapter *adapter)
        hwm = min(((pba << 10) * 9 / 10),
                        ((pba << 10) - 2 * adapter->max_frame_size));
 
-       if (mac->type < e1000_82576) {
-               fc->high_water = hwm & 0xFFF8;  /* 8-byte granularity */
-               fc->low_water = fc->high_water - 8;
-       } else {
-               fc->high_water = hwm & 0xFFF0;  /* 16-byte granularity */
-               fc->low_water = fc->high_water - 16;
-       }
+       fc->high_water = hwm & 0xFFF0;  /* 16-byte granularity */
+       fc->low_water = fc->high_water - 16;
        fc->pause_time = 0xFFFF;
        fc->send_xon = 1;
        fc->current_mode = fc->requested_mode;
index e9dd95f136aa8432d1542fc344a19cd0acdf3abb..0dbd0320023acf47ff36f2b97fe434b567cfc414 100644 (file)
@@ -2763,7 +2763,8 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
        err = hw->mac.ops.reset_hw(hw);
        if (err) {
                dev_info(&pdev->dev,
-                        "PF still in reset state, assigning new address\n");
+                        "PF still in reset state, assigning new address."
+                        " Is the PF interface up?\n");
                random_ether_addr(hw->mac.addr);
        } else {
                err = hw->mac.ops.read_mac_addr(hw);
index bd64387563f040311ae5bafb207bf7f51f094cfe..1a2ea621e3716d35fa4ed28853b5af66ac2ebdea 100644 (file)
@@ -4373,6 +4373,11 @@ static int ixgbe_resume(struct pci_dev *pdev)
 
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
+       /*
+        * pci_restore_state clears dev->state_saved so call
+        * pci_save_state to restore it.
+        */
+       pci_save_state(pdev);
 
        err = pci_enable_device_mem(pdev);
        if (err) {
index 291a505fd4fcaac388d86597fc0ff8540bd9feea..3cf56d90d85924551c86252ac1343226173a3630 100644 (file)
@@ -1174,7 +1174,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return 0;
 
 err_port:
-       for (port = 1; port <= dev->caps.num_ports; port++)
+       for (--port; port >= 1; --port)
                mlx4_cleanup_port_info(&priv->port[port]);
 
        mlx4_cleanup_mcg_table(dev);
index dcc67a35e8f24f2a6c54eb3d65aedce23b55b3e0..e154677ff706834285ce6f4a7bd6f00d83118818 100644 (file)
@@ -45,6 +45,7 @@ static const char *const version =
 #include <linux/crc32.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/if_ether.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/moduleparam.h>
@@ -1765,7 +1766,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 
        /* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
        if (!is_valid_ether_addr(dev->perm_addr))
-               memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
+               memset(dev->dev_addr, 0, ETH_ALEN);
 
        if (pcnet32_debug & NETIF_MSG_PROBE) {
                printk(" %pM", dev->dev_addr);
index f983e3b507cc8951fd1837a946ab87b6acb2991f..103e8b0e2a0d67e6682cb827e010a7e8f260e025 100644 (file)
@@ -741,14 +741,14 @@ static int efx_probe_port(struct efx_nic *efx)
 
        EFX_LOG(efx, "create port\n");
 
+       if (phy_flash_cfg)
+               efx->phy_mode = PHY_MODE_SPECIAL;
+
        /* Connect up MAC/PHY operations table */
        rc = efx->type->probe_port(efx);
        if (rc)
                goto err;
 
-       if (phy_flash_cfg)
-               efx->phy_mode = PHY_MODE_SPECIAL;
-
        /* Sanity check MAC address */
        if (is_valid_ether_addr(efx->mac_address)) {
                memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
index 17afcd26e870c09058e8a3df8545d76566ccdb75..9d009c46e962c343befff8c1395e3651133e5ccb 100644 (file)
@@ -925,6 +925,7 @@ static int falcon_probe_port(struct efx_nic *efx)
 
 static void falcon_remove_port(struct efx_nic *efx)
 {
+       efx->phy_op->remove(efx);
        efx_nic_free_buffer(efx, &efx->stats_buffer);
 }
 
index 3da933f8f0797bc577027d489d4717ea8ec79dd3..8ccab2c67a2094680ef743df277cd7e20a8d16c2 100644 (file)
@@ -111,16 +111,12 @@ static void falcon_mask_status_intr(struct efx_nic *efx, bool enable)
        efx_writeo(efx, &reg, FR_AB_XM_MGT_INT_MASK);
 }
 
-/* Get status of XAUI link */
-static bool falcon_xaui_link_ok(struct efx_nic *efx)
+static bool falcon_xgxs_link_ok(struct efx_nic *efx)
 {
        efx_oword_t reg;
        bool align_done, link_ok = false;
        int sync_status;
 
-       if (LOOPBACK_INTERNAL(efx))
-               return true;
-
        /* Read link status */
        efx_reado(efx, &reg, FR_AB_XX_CORE_STAT);
 
@@ -135,14 +131,24 @@ static bool falcon_xaui_link_ok(struct efx_nic *efx)
        EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_DISPERR, FFE_AB_XX_STAT_ALL_LANES);
        efx_writeo(efx, &reg, FR_AB_XX_CORE_STAT);
 
-       /* If the link is up, then check the phy side of the xaui link */
-       if (efx->link_state.up && link_ok)
-               if (efx->mdio.mmds & (1 << MDIO_MMD_PHYXS))
-                       link_ok = efx_mdio_phyxgxs_lane_sync(efx);
-
        return link_ok;
 }
 
+static bool falcon_xmac_link_ok(struct efx_nic *efx)
+{
+       /*
+        * Check MAC's XGXS link status except when using XGMII loopback
+        * which bypasses the XGXS block.
+        * If possible, check PHY's XGXS link status except when using
+        * MAC loopback.
+        */
+       return (efx->loopback_mode == LOOPBACK_XGMII ||
+               falcon_xgxs_link_ok(efx)) &&
+               (!(efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) ||
+                LOOPBACK_INTERNAL(efx) || 
+                efx_mdio_phyxgxs_lane_sync(efx));
+}
+
 void falcon_reconfigure_xmac_core(struct efx_nic *efx)
 {
        unsigned int max_frame_len;
@@ -245,9 +251,9 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
 
 
 /* Try to bring up the Falcon side of the Falcon-Phy XAUI link */
-static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
+static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries)
 {
-       bool mac_up = falcon_xaui_link_ok(efx);
+       bool mac_up = falcon_xmac_link_ok(efx);
 
        if (LOOPBACK_MASK(efx) & LOOPBACKS_EXTERNAL(efx) & LOOPBACKS_WS ||
            efx_phy_mode_disabled(efx->phy_mode))
@@ -261,7 +267,7 @@ static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
                falcon_reset_xaui(efx);
                udelay(200);
 
-               mac_up = falcon_xaui_link_ok(efx);
+               mac_up = falcon_xmac_link_ok(efx);
                --tries;
        }
 
@@ -272,7 +278,7 @@ static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
 
 static bool falcon_xmac_check_fault(struct efx_nic *efx)
 {
-       return !falcon_check_xaui_link_up(efx, 5);
+       return !falcon_xmac_link_ok_retry(efx, 5);
 }
 
 static int falcon_reconfigure_xmac(struct efx_nic *efx)
@@ -284,7 +290,7 @@ static int falcon_reconfigure_xmac(struct efx_nic *efx)
 
        falcon_reconfigure_mac_wrapper(efx);
 
-       efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 5);
+       efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5);
        falcon_mask_status_intr(efx, true);
 
        return 0;
@@ -357,7 +363,7 @@ void falcon_poll_xmac(struct efx_nic *efx)
                return;
 
        falcon_mask_status_intr(efx, false);
-       efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 1);
+       efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1);
        falcon_mask_status_intr(efx, true);
 }
 
index 0e1bcc5a0d52c5e4ee637c529f0b062a3f22eb65..eb694af7a473503b176a23fb37cddce97e70b6cc 100644 (file)
@@ -304,31 +304,47 @@ static u32 mcdi_to_ethtool_media(u32 media)
 
 static int efx_mcdi_phy_probe(struct efx_nic *efx)
 {
-       struct efx_mcdi_phy_cfg *phy_cfg;
+       struct efx_mcdi_phy_cfg *phy_data;
+       u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
+       u32 caps;
        int rc;
 
-       /* TODO: Move phy_data initialisation to
-        * phy_op->probe/remove, rather than init/fini */
-       phy_cfg = kzalloc(sizeof(*phy_cfg), GFP_KERNEL);
-       if (phy_cfg == NULL) {
-               rc = -ENOMEM;
-               goto fail_alloc;
-       }
-       rc = efx_mcdi_get_phy_cfg(efx, phy_cfg);
+       /* Initialise and populate phy_data */
+       phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
+       if (phy_data == NULL)
+               return -ENOMEM;
+
+       rc = efx_mcdi_get_phy_cfg(efx, phy_data);
        if (rc != 0)
                goto fail;
 
-       efx->phy_type = phy_cfg->type;
+       /* Read initial link advertisement */
+       BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
+       rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
+                         outbuf, sizeof(outbuf), NULL);
+       if (rc)
+               goto fail;
+
+       /* Fill out nic state */
+       efx->phy_data = phy_data;
+       efx->phy_type = phy_data->type;
 
-       efx->mdio_bus = phy_cfg->channel;
-       efx->mdio.prtad = phy_cfg->port;
-       efx->mdio.mmds = phy_cfg->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22);
+       efx->mdio_bus = phy_data->channel;
+       efx->mdio.prtad = phy_data->port;
+       efx->mdio.mmds = phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22);
        efx->mdio.mode_support = 0;
-       if (phy_cfg->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22))
+       if (phy_data->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22))
                efx->mdio.mode_support |= MDIO_SUPPORTS_C22;
-       if (phy_cfg->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22))
+       if (phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22))
                efx->mdio.mode_support |= MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
 
+       caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP);
+       if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN))
+               efx->link_advertising =
+                       mcdi_to_ethtool_cap(phy_data->media, caps);
+       else
+               phy_data->forced_cap = caps;
+
        /* Assert that we can map efx -> mcdi loopback modes */
        BUILD_BUG_ON(LOOPBACK_NONE != MC_CMD_LOOPBACK_NONE);
        BUILD_BUG_ON(LOOPBACK_DATA != MC_CMD_LOOPBACK_DATA);
@@ -365,46 +381,6 @@ static int efx_mcdi_phy_probe(struct efx_nic *efx)
         * but by convention we don't */
        efx->loopback_modes &= ~(1 << LOOPBACK_NONE);
 
-       kfree(phy_cfg);
-
-       return 0;
-
-fail:
-       kfree(phy_cfg);
-fail_alloc:
-       return rc;
-}
-
-static int efx_mcdi_phy_init(struct efx_nic *efx)
-{
-       struct efx_mcdi_phy_cfg *phy_data;
-       u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
-       u32 caps;
-       int rc;
-
-       phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
-       if (phy_data == NULL)
-               return -ENOMEM;
-
-       rc = efx_mcdi_get_phy_cfg(efx, phy_data);
-       if (rc != 0)
-               goto fail;
-
-       efx->phy_data = phy_data;
-
-       BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
-       rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
-                         outbuf, sizeof(outbuf), NULL);
-       if (rc)
-               goto fail;
-
-       caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP);
-       if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN))
-               efx->link_advertising =
-                       mcdi_to_ethtool_cap(phy_data->media, caps);
-       else
-               phy_data->forced_cap = caps;
-
        return 0;
 
 fail:
@@ -504,7 +480,7 @@ static bool efx_mcdi_phy_poll(struct efx_nic *efx)
        return !efx_link_state_equal(&efx->link_state, &old_state);
 }
 
-static void efx_mcdi_phy_fini(struct efx_nic *efx)
+static void efx_mcdi_phy_remove(struct efx_nic *efx)
 {
        struct efx_mcdi_phy_data *phy_data = efx->phy_data;
 
@@ -586,10 +562,11 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec
 
 struct efx_phy_operations efx_mcdi_phy_ops = {
        .probe          = efx_mcdi_phy_probe,
-       .init           = efx_mcdi_phy_init,
+       .init           = efx_port_dummy_op_int,
        .reconfigure    = efx_mcdi_phy_reconfigure,
        .poll           = efx_mcdi_phy_poll,
-       .fini           = efx_mcdi_phy_fini,
+       .fini           = efx_port_dummy_op_void,
+       .remove         = efx_mcdi_phy_remove,
        .get_settings   = efx_mcdi_phy_get_settings,
        .set_settings   = efx_mcdi_phy_set_settings,
        .run_tests      = NULL,
index 34c381f009b77b13aa90e67be90b25b45375552f..d5aab5b3fa066e27666c44b01dd35c241a0b86f7 100644 (file)
@@ -524,6 +524,7 @@ struct efx_phy_operations {
        int (*probe) (struct efx_nic *efx);
        int (*init) (struct efx_nic *efx);
        void (*fini) (struct efx_nic *efx);
+       void (*remove) (struct efx_nic *efx);
        int (*reconfigure) (struct efx_nic *efx);
        bool (*poll) (struct efx_nic *efx);
        void (*get_settings) (struct efx_nic *efx,
index a577be2278621cd7281ae50b668abe5c860f1cfa..db44224ed2cad53789f7d5410db1a7988f34bca1 100644 (file)
@@ -1576,6 +1576,8 @@ void efx_nic_init_common(struct efx_nic *efx)
        EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_SOFT_EVT_EN, 1);
        /* Prefetch threshold 2 => fetch when descriptor cache half empty */
        EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_THRESHOLD, 2);
+       /* Disable hardware watchdog which can misfire */
+       EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
        /* Squash TX of packets of 16 bytes or less */
        if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
                EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
index 3800fc791b2f788f69a2c19241f7cc54ebc392f6..ff8f0a417fa3effb8b508cb7ac2681447da7247a 100644 (file)
@@ -33,6 +33,9 @@
 #define PCS_FW_HEARTBEAT_REG   0xd7ee
 #define PCS_FW_HEARTB_LBN      0
 #define PCS_FW_HEARTB_WIDTH    8
+#define PCS_FW_PRODUCT_CODE_1  0xd7f0
+#define PCS_FW_VERSION_1       0xd7f3
+#define PCS_FW_BUILD_1         0xd7f6
 #define PCS_UC8051_STATUS_REG  0xd7fd
 #define PCS_UC_STATUS_LBN      0
 #define PCS_UC_STATUS_WIDTH    8
@@ -52,14 +55,24 @@ void falcon_qt202x_set_led(struct efx_nic *p, int led, int mode)
 
 struct qt202x_phy_data {
        enum efx_phy_mode phy_mode;
+       bool bug17190_in_bad_state;
+       unsigned long bug17190_timer;
+       u32 firmware_ver;
 };
 
 #define QT2022C2_MAX_RESET_TIME 500
 #define QT2022C2_RESET_WAIT 10
 
-static int qt2025c_wait_reset(struct efx_nic *efx)
+#define QT2025C_MAX_HEARTB_TIME (5 * HZ)
+#define QT2025C_HEARTB_WAIT 100
+#define QT2025C_MAX_FWSTART_TIME (25 * HZ / 10)
+#define QT2025C_FWSTART_WAIT 100
+
+#define BUG17190_INTERVAL (2 * HZ)
+
+static int qt2025c_wait_heartbeat(struct efx_nic *efx)
 {
-       unsigned long timeout = jiffies + 10 * HZ;
+       unsigned long timeout = jiffies + QT2025C_MAX_HEARTB_TIME;
        int reg, old_counter = 0;
 
        /* Wait for firmware heartbeat to start */
@@ -74,11 +87,25 @@ static int qt2025c_wait_reset(struct efx_nic *efx)
                        old_counter = counter;
                else if (counter != old_counter)
                        break;
-               if (time_after(jiffies, timeout))
+               if (time_after(jiffies, timeout)) {
+                       /* Some cables have EEPROMs that conflict with the
+                        * PHY's on-board EEPROM so it cannot load firmware */
+                       EFX_ERR(efx, "If an SFP+ direct attach cable is"
+                               " connected, please check that it complies"
+                               " with the SFP+ specification\n");
                        return -ETIMEDOUT;
-               msleep(10);
+               }
+               msleep(QT2025C_HEARTB_WAIT);
        }
 
+       return 0;
+}
+
+static int qt2025c_wait_fw_status_good(struct efx_nic *efx)
+{
+       unsigned long timeout = jiffies + QT2025C_MAX_FWSTART_TIME;
+       int reg;
+
        /* Wait for firmware status to look good */
        for (;;) {
                reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG);
@@ -90,7 +117,178 @@ static int qt2025c_wait_reset(struct efx_nic *efx)
                        break;
                if (time_after(jiffies, timeout))
                        return -ETIMEDOUT;
+               msleep(QT2025C_FWSTART_WAIT);
+       }
+
+       return 0;
+}
+
+static void qt2025c_restart_firmware(struct efx_nic *efx)
+{
+       /* Restart microcontroller execution of firmware from RAM */
+       efx_mdio_write(efx, 3, 0xe854, 0x00c0);
+       efx_mdio_write(efx, 3, 0xe854, 0x0040);
+       msleep(50);
+}
+
+static int qt2025c_wait_reset(struct efx_nic *efx)
+{
+       int rc;
+
+       rc = qt2025c_wait_heartbeat(efx);
+       if (rc != 0)
+               return rc;
+
+       rc = qt2025c_wait_fw_status_good(efx);
+       if (rc == -ETIMEDOUT) {
+               /* Bug 17689: occasionally heartbeat starts but firmware status
+                * code never progresses beyond 0x00.  Try again, once, after
+                * restarting execution of the firmware image. */
+               EFX_LOG(efx, "bashing QT2025C microcontroller\n");
+               qt2025c_restart_firmware(efx);
+               rc = qt2025c_wait_heartbeat(efx);
+               if (rc != 0)
+                       return rc;
+               rc = qt2025c_wait_fw_status_good(efx);
+       }
+
+       return rc;
+}
+
+static void qt2025c_firmware_id(struct efx_nic *efx)
+{
+       struct qt202x_phy_data *phy_data = efx->phy_data;
+       u8 firmware_id[9];
+       size_t i;
+
+       for (i = 0; i < sizeof(firmware_id); i++)
+               firmware_id[i] = efx_mdio_read(efx, MDIO_MMD_PCS,
+                                              PCS_FW_PRODUCT_CODE_1 + i);
+       EFX_INFO(efx, "QT2025C firmware %xr%d v%d.%d.%d.%d [20%02d-%02d-%02d]\n",
+                (firmware_id[0] << 8) | firmware_id[1], firmware_id[2],
+                firmware_id[3] >> 4, firmware_id[3] & 0xf,
+                firmware_id[4], firmware_id[5],
+                firmware_id[6], firmware_id[7], firmware_id[8]);
+       phy_data->firmware_ver = ((firmware_id[3] & 0xf0) << 20) |
+                                ((firmware_id[3] & 0x0f) << 16) |
+                                (firmware_id[4] << 8) | firmware_id[5];
+}
+
+static void qt2025c_bug17190_workaround(struct efx_nic *efx)
+{
+       struct qt202x_phy_data *phy_data = efx->phy_data;
+
+       /* The PHY can get stuck in a state where it reports PHY_XS and PMA/PMD
+        * layers up, but PCS down (no block_lock).  If we notice this state
+        * persisting for a couple of seconds, we switch PMA/PMD loopback
+        * briefly on and then off again, which is normally sufficient to
+        * recover it.
+        */
+       if (efx->link_state.up ||
+           !efx_mdio_links_ok(efx, MDIO_DEVS_PMAPMD | MDIO_DEVS_PHYXS)) {
+               phy_data->bug17190_in_bad_state = false;
+               return;
+       }
+
+       if (!phy_data->bug17190_in_bad_state) {
+               phy_data->bug17190_in_bad_state = true;
+               phy_data->bug17190_timer = jiffies + BUG17190_INTERVAL;
+               return;
+       }
+
+       if (time_after_eq(jiffies, phy_data->bug17190_timer)) {
+               EFX_LOG(efx, "bashing QT2025C PMA/PMD\n");
+               efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1,
+                                 MDIO_PMA_CTRL1_LOOPBACK, true);
                msleep(100);
+               efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1,
+                                 MDIO_PMA_CTRL1_LOOPBACK, false);
+               phy_data->bug17190_timer = jiffies + BUG17190_INTERVAL;
+       }
+}
+
+static int qt2025c_select_phy_mode(struct efx_nic *efx)
+{
+       struct qt202x_phy_data *phy_data = efx->phy_data;
+       struct falcon_board *board = falcon_board(efx);
+       int reg, rc, i;
+       uint16_t phy_op_mode;
+
+       /* Only 2.0.1.0+ PHY firmware supports the more optimal SFP+
+        * Self-Configure mode.  Don't attempt any switching if we encounter
+        * older firmware. */
+       if (phy_data->firmware_ver < 0x02000100)
+               return 0;
+
+       /* In general we will get optimal behaviour in "SFP+ Self-Configure"
+        * mode; however, that powers down most of the PHY when no module is
+        * present, so we must use a different mode (any fixed mode will do)
+        * to be sure that loopbacks will work. */
+       phy_op_mode = (efx->loopback_mode == LOOPBACK_NONE) ? 0x0038 : 0x0020;
+
+       /* Only change mode if really necessary */
+       reg = efx_mdio_read(efx, 1, 0xc319);
+       if ((reg & 0x0038) == phy_op_mode)
+               return 0;
+       EFX_LOG(efx, "Switching PHY to mode 0x%04x\n", phy_op_mode);
+
+       /* This sequence replicates the register writes configured in the boot
+        * EEPROM (including the differences between board revisions), except
+        * that the operating mode is changed, and the PHY is prevented from
+        * unnecessarily reloading the main firmware image again. */
+       efx_mdio_write(efx, 1, 0xc300, 0x0000);
+       /* (Note: this portion of the boot EEPROM sequence, which bit-bashes 9
+        * STOPs onto the firmware/module I2C bus to reset it, varies across
+        * board revisions, as the bus is connected to different GPIO/LED
+        * outputs on the PHY.) */
+       if (board->major == 0 && board->minor < 2) {
+               efx_mdio_write(efx, 1, 0xc303, 0x4498);
+               for (i = 0; i < 9; i++) {
+                       efx_mdio_write(efx, 1, 0xc303, 0x4488);
+                       efx_mdio_write(efx, 1, 0xc303, 0x4480);
+                       efx_mdio_write(efx, 1, 0xc303, 0x4490);
+                       efx_mdio_write(efx, 1, 0xc303, 0x4498);
+               }
+       } else {
+               efx_mdio_write(efx, 1, 0xc303, 0x0920);
+               efx_mdio_write(efx, 1, 0xd008, 0x0004);
+               for (i = 0; i < 9; i++) {
+                       efx_mdio_write(efx, 1, 0xc303, 0x0900);
+                       efx_mdio_write(efx, 1, 0xd008, 0x0005);
+                       efx_mdio_write(efx, 1, 0xc303, 0x0920);
+                       efx_mdio_write(efx, 1, 0xd008, 0x0004);
+               }
+               efx_mdio_write(efx, 1, 0xc303, 0x4900);
+       }
+       efx_mdio_write(efx, 1, 0xc303, 0x4900);
+       efx_mdio_write(efx, 1, 0xc302, 0x0004);
+       efx_mdio_write(efx, 1, 0xc316, 0x0013);
+       efx_mdio_write(efx, 1, 0xc318, 0x0054);
+       efx_mdio_write(efx, 1, 0xc319, phy_op_mode);
+       efx_mdio_write(efx, 1, 0xc31a, 0x0098);
+       efx_mdio_write(efx, 3, 0x0026, 0x0e00);
+       efx_mdio_write(efx, 3, 0x0027, 0x0013);
+       efx_mdio_write(efx, 3, 0x0028, 0xa528);
+       efx_mdio_write(efx, 1, 0xd006, 0x000a);
+       efx_mdio_write(efx, 1, 0xd007, 0x0009);
+       efx_mdio_write(efx, 1, 0xd008, 0x0004);
+       /* This additional write is not present in the boot EEPROM.  It
+        * prevents the PHY's internal boot ROM doing another pointless (and
+        * slow) reload of the firmware image (the microcontroller's code
+        * memory is not affected by the microcontroller reset). */
+       efx_mdio_write(efx, 1, 0xc317, 0x00ff);
+       efx_mdio_write(efx, 1, 0xc300, 0x0002);
+       msleep(20);
+
+       /* Restart microcontroller execution of firmware from RAM */
+       qt2025c_restart_firmware(efx);
+
+       /* Wait for the microcontroller to be ready again */
+       rc = qt2025c_wait_reset(efx);
+       if (rc < 0) {
+               EFX_ERR(efx, "PHY microcontroller reset during mode switch "
+                               "timed out\n");
+               return rc;
        }
 
        return 0;
@@ -137,6 +335,16 @@ static int qt202x_reset_phy(struct efx_nic *efx)
 
 static int qt202x_phy_probe(struct efx_nic *efx)
 {
+       struct qt202x_phy_data *phy_data;
+
+       phy_data = kzalloc(sizeof(struct qt202x_phy_data), GFP_KERNEL);
+       if (!phy_data)
+               return -ENOMEM;
+       efx->phy_data = phy_data;
+       phy_data->phy_mode = efx->phy_mode;
+       phy_data->bug17190_in_bad_state = false;
+       phy_data->bug17190_timer = 0;
+
        efx->mdio.mmds = QT202X_REQUIRED_DEVS;
        efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
        efx->loopback_modes = QT202X_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
@@ -145,7 +353,6 @@ static int qt202x_phy_probe(struct efx_nic *efx)
 
 static int qt202x_phy_init(struct efx_nic *efx)
 {
-       struct qt202x_phy_data *phy_data;
        u32 devid;
        int rc;
 
@@ -155,17 +362,14 @@ static int qt202x_phy_init(struct efx_nic *efx)
                return rc;
        }
 
-       phy_data = kzalloc(sizeof(struct qt202x_phy_data), GFP_KERNEL);
-       if (!phy_data)
-               return -ENOMEM;
-       efx->phy_data = phy_data;
-
        devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS);
        EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n",
                 devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid),
                 efx_mdio_id_rev(devid));
 
-       phy_data->phy_mode = efx->phy_mode;
+       if (efx->phy_type == PHY_TYPE_QT2025C)
+               qt2025c_firmware_id(efx);
+
        return 0;
 }
 
@@ -183,6 +387,9 @@ static bool qt202x_phy_poll(struct efx_nic *efx)
        efx->link_state.fd = true;
        efx->link_state.fc = efx->wanted_fc;
 
+       if (efx->phy_type == PHY_TYPE_QT2025C)
+               qt2025c_bug17190_workaround(efx);
+
        return efx->link_state.up != was_up;
 }
 
@@ -191,6 +398,10 @@ static int qt202x_phy_reconfigure(struct efx_nic *efx)
        struct qt202x_phy_data *phy_data = efx->phy_data;
 
        if (efx->phy_type == PHY_TYPE_QT2025C) {
+               int rc = qt2025c_select_phy_mode(efx);
+               if (rc)
+                       return rc;
+
                /* There are several different register bits which can
                 * disable TX (and save power) on direct-attach cables
                 * or optical transceivers, varying somewhat between
@@ -224,7 +435,7 @@ static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecm
        mdio45_ethtool_gset(&efx->mdio, ecmd);
 }
 
-static void qt202x_phy_fini(struct efx_nic *efx)
+static void qt202x_phy_remove(struct efx_nic *efx)
 {
        /* Free the context block */
        kfree(efx->phy_data);
@@ -236,7 +447,8 @@ struct efx_phy_operations falcon_qt202x_phy_ops = {
        .init            = qt202x_phy_init,
        .reconfigure     = qt202x_phy_reconfigure,
        .poll            = qt202x_phy_poll,
-       .fini            = qt202x_phy_fini,
+       .fini            = efx_port_dummy_op_void,
+       .remove          = qt202x_phy_remove,
        .get_settings    = qt202x_phy_get_settings,
        .set_settings    = efx_mdio_set_settings,
 };
index de07a4f031b2f0c34cc47d08f829187c0b1aa57a..f8c6771e66d861488bd12fc69d51346a0fedebb6 100644 (file)
@@ -133,6 +133,7 @@ static int siena_probe_port(struct efx_nic *efx)
 
 void siena_remove_port(struct efx_nic *efx)
 {
+       efx->phy_op->remove(efx);
        efx_nic_free_buffer(efx, &efx->stats_buffer);
 }
 
index ca11572a49a93cab33554bdf49d422155c194f46..3009c297c135a647e945b26fc3acfe38fc24237b 100644 (file)
@@ -202,10 +202,14 @@ static ssize_t set_phy_short_reach(struct device *dev,
        int rc;
 
        rtnl_lock();
-       efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR,
-                         MDIO_PMA_10GBT_TXPWR_SHORT,
-                         count != 0 && *buf != '0');
-       rc = efx_reconfigure_port(efx);
+       if (efx->state != STATE_RUNNING) {
+               rc = -EBUSY;
+       } else {
+               efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR,
+                                 MDIO_PMA_10GBT_TXPWR_SHORT,
+                                 count != 0 && *buf != '0');
+               rc = efx_reconfigure_port(efx);
+       }
        rtnl_unlock();
 
        return rc < 0 ? rc : (ssize_t)count;
@@ -298,36 +302,62 @@ static int tenxpress_init(struct efx_nic *efx)
        return 0;
 }
 
-static int sfx7101_phy_probe(struct efx_nic *efx)
+static int tenxpress_phy_probe(struct efx_nic *efx)
 {
-       efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
-       efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
-       efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
-       return 0;
-}
+       struct tenxpress_phy_data *phy_data;
+       int rc;
+
+       /* Allocate phy private storage */
+       phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
+       if (!phy_data)
+               return -ENOMEM;
+       efx->phy_data = phy_data;
+       phy_data->phy_mode = efx->phy_mode;
+
+       /* Create any special files */
+       if (efx->phy_type == PHY_TYPE_SFT9001B) {
+               rc = device_create_file(&efx->pci_dev->dev,
+                                       &dev_attr_phy_short_reach);
+               if (rc)
+                       goto fail;
+       }
+
+       if (efx->phy_type == PHY_TYPE_SFX7101) {
+               efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
+               efx->mdio.mode_support = MDIO_SUPPORTS_C45;
+
+               efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
+
+               efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
+                                        ADVERTISED_10000baseT_Full);
+       } else {
+               efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
+               efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+
+               efx->loopback_modes = (SFT9001_LOOPBACKS |
+                                      FALCON_XMAC_LOOPBACKS | 
+                                      FALCON_GMAC_LOOPBACKS);
+
+               efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
+                                        ADVERTISED_10000baseT_Full |
+                                        ADVERTISED_1000baseT_Full |
+                                        ADVERTISED_100baseT_Full);
+       }
 
-static int sft9001_phy_probe(struct efx_nic *efx)
-{
-       efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
-       efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
-       efx->loopback_modes = (SFT9001_LOOPBACKS | FALCON_XMAC_LOOPBACKS |
-                              FALCON_GMAC_LOOPBACKS);
        return 0;
+
+fail:
+       kfree(efx->phy_data);
+       efx->phy_data = NULL;
+       return rc;
 }
 
 static int tenxpress_phy_init(struct efx_nic *efx)
 {
-       struct tenxpress_phy_data *phy_data;
-       int rc = 0;
+       int rc;
 
        falcon_board(efx)->type->init_phy(efx);
 
-       phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
-       if (!phy_data)
-               return -ENOMEM;
-       efx->phy_data = phy_data;
-       phy_data->phy_mode = efx->phy_mode;
-
        if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
                if (efx->phy_type == PHY_TYPE_SFT9001A) {
                        int reg;
@@ -341,44 +371,27 @@ static int tenxpress_phy_init(struct efx_nic *efx)
 
                rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
                if (rc < 0)
-                       goto fail;
+                       return rc;
 
                rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
                if (rc < 0)
-                       goto fail;
+                       return rc;
        }
 
        rc = tenxpress_init(efx);
        if (rc < 0)
-               goto fail;
+               return rc;
 
-       /* Initialise advertising flags */
-       efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
-                                 ADVERTISED_10000baseT_Full);
-       if (efx->phy_type != PHY_TYPE_SFX7101)
-               efx->link_advertising |= (ADVERTISED_1000baseT_Full |
-                                          ADVERTISED_100baseT_Full);
+       /* Reinitialise flow control settings */
        efx_link_set_wanted_fc(efx, efx->wanted_fc);
        efx_mdio_an_reconfigure(efx);
 
-       if (efx->phy_type == PHY_TYPE_SFT9001B) {
-               rc = device_create_file(&efx->pci_dev->dev,
-                                       &dev_attr_phy_short_reach);
-               if (rc)
-                       goto fail;
-       }
-
        schedule_timeout_uninterruptible(HZ / 5); /* 200ms */
 
        /* Let XGXS and SerDes out of reset */
        falcon_reset_xaui(efx);
 
        return 0;
-
- fail:
-       kfree(efx->phy_data);
-       efx->phy_data = NULL;
-       return rc;
 }
 
 /* Perform a "special software reset" on the PHY. The caller is
@@ -589,25 +602,26 @@ static bool tenxpress_phy_poll(struct efx_nic *efx)
        return !efx_link_state_equal(&efx->link_state, &old_state);
 }
 
-static void tenxpress_phy_fini(struct efx_nic *efx)
+static void sfx7101_phy_fini(struct efx_nic *efx)
 {
        int reg;
 
+       /* Power down the LNPGA */
+       reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
+       efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
+
+       /* Waiting here ensures that the board fini, which can turn
+        * off the power to the PHY, won't get run until the LNPGA
+        * powerdown has been given long enough to complete. */
+       schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */
+}
+
+static void tenxpress_phy_remove(struct efx_nic *efx)
+{
        if (efx->phy_type == PHY_TYPE_SFT9001B)
                device_remove_file(&efx->pci_dev->dev,
                                   &dev_attr_phy_short_reach);
 
-       if (efx->phy_type == PHY_TYPE_SFX7101) {
-               /* Power down the LNPGA */
-               reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
-               efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
-
-               /* Waiting here ensures that the board fini, which can turn
-                * off the power to the PHY, won't get run until the LNPGA
-                * powerdown has been given long enough to complete. */
-               schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */
-       }
-
        kfree(efx->phy_data);
        efx->phy_data = NULL;
 }
@@ -819,11 +833,12 @@ static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
 }
 
 struct efx_phy_operations falcon_sfx7101_phy_ops = {
-       .probe            = sfx7101_phy_probe,
+       .probe            = tenxpress_phy_probe,
        .init             = tenxpress_phy_init,
        .reconfigure      = tenxpress_phy_reconfigure,
        .poll             = tenxpress_phy_poll,
-       .fini             = tenxpress_phy_fini,
+       .fini             = sfx7101_phy_fini,
+       .remove           = tenxpress_phy_remove,
        .get_settings     = tenxpress_get_settings,
        .set_settings     = tenxpress_set_settings,
        .set_npage_adv    = sfx7101_set_npage_adv,
@@ -832,11 +847,12 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
 };
 
 struct efx_phy_operations falcon_sft9001_phy_ops = {
-       .probe            = sft9001_phy_probe,
+       .probe            = tenxpress_phy_probe,
        .init             = tenxpress_phy_init,
        .reconfigure      = tenxpress_phy_reconfigure,
        .poll             = tenxpress_phy_poll,
-       .fini             = tenxpress_phy_fini,
+       .fini             = efx_port_dummy_op_void,
+       .remove           = tenxpress_phy_remove,
        .get_settings     = tenxpress_get_settings,
        .set_settings     = tenxpress_set_settings,
        .set_npage_adv    = sft9001_set_npage_adv,
index e669f94e821bde87e23d842fe25005e9568a93a8..a8b70ef6d817ea51a867c217f25fa78871cf5624 100644 (file)
@@ -821,8 +821,6 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
                                           EFX_TXQ_MASK];
                efx_tsoh_free(tx_queue, buffer);
                EFX_BUG_ON_PARANOID(buffer->skb);
-               buffer->len = 0;
-               buffer->continuation = true;
                if (buffer->unmap_len) {
                        unmap_addr = (buffer->dma_addr + buffer->len -
                                      buffer->unmap_len);
@@ -836,6 +834,8 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
                                               PCI_DMA_TODEVICE);
                        buffer->unmap_len = 0;
                }
+               buffer->len = 0;
+               buffer->continuation = true;
        }
 }
 
index 1c01b96c9611220554a10385e447f579ad36e133..2d28d58200d08f2f709ed5f25e2e09f0c38f92a1 100644 (file)
@@ -4684,6 +4684,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        INIT_WORK(&hw->restart_work, sky2_restart);
 
        pci_set_drvdata(pdev, hw);
+       pdev->d3_delay = 150;
 
        return 0;
 
index 01e99f22210e0710b8e1bfe77565b051aa849b54..2834a01bae24a9d3e410f342a291b160b43cee02 100644 (file)
@@ -849,13 +849,13 @@ static void tun_sock_write_space(struct sock *sk)
        if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
                wake_up_interruptible_sync(sk->sk_sleep);
 
-       tun = container_of(sk, struct tun_sock, sk)->tun;
+       tun = tun_sk(sk)->tun;
        kill_fasync(&tun->fasync, SIGIO, POLL_OUT);
 }
 
 static void tun_sock_destruct(struct sock *sk)
 {
-       free_netdev(container_of(sk, struct tun_sock, sk)->tun->dev);
+       free_netdev(tun_sk(sk)->tun->dev);
 }
 
 static struct proto tun_proto = {
@@ -990,7 +990,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                sk->sk_write_space = tun_sock_write_space;
                sk->sk_sndbuf = INT_MAX;
 
-               container_of(sk, struct tun_sock, sk)->tun = tun;
+               tun_sk(sk)->tun = tun;
 
                security_tun_dev_post_create(sk);
 
index afaf088b72eaab23d1a6847f0e91abcae49ee2d6..41ad2f3697c710dd8be1e46985100e14242e218c 100644 (file)
@@ -1563,7 +1563,10 @@ static int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode)
 
 static void ugeth_quiesce(struct ucc_geth_private *ugeth)
 {
-       /* Wait for and prevent any further xmits. */
+       /* Prevent any further xmits, plus detach the device. */
+       netif_device_detach(ugeth->ndev);
+
+       /* Wait for any current xmits to finish. */
        netif_tx_disable(ugeth->ndev);
 
        /* Disable the interrupt to avoid NAPI rescheduling. */
@@ -1577,7 +1580,7 @@ static void ugeth_activate(struct ucc_geth_private *ugeth)
 {
        napi_enable(&ugeth->napi);
        enable_irq(ugeth->ug_info->uf_info.irq);
-       netif_tx_wake_all_queues(ugeth->ndev);
+       netif_device_attach(ugeth->ndev);
 }
 
 /* Called every time the controller might need to be made
@@ -1648,25 +1651,28 @@ static void adjust_link(struct net_device *dev)
                        ugeth->oldspeed = phydev->speed;
                }
 
-               /*
-                * To change the MAC configuration we need to disable the
-                * controller. To do so, we have to either grab ugeth->lock,
-                * which is a bad idea since 'graceful stop' commands might
-                * take quite a while, or we can quiesce driver's activity.
-                */
-               ugeth_quiesce(ugeth);
-               ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
-
-               out_be32(&ug_regs->maccfg2, tempval);
-               out_be32(&uf_regs->upsmr, upsmr);
-
-               ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
-               ugeth_activate(ugeth);
-
                if (!ugeth->oldlink) {
                        new_state = 1;
                        ugeth->oldlink = 1;
                }
+
+               if (new_state) {
+                       /*
+                        * To change the MAC configuration we need to disable
+                        * the controller. To do so, we have to either grab
+                        * ugeth->lock, which is a bad idea since 'graceful
+                        * stop' commands might take quite a while, or we can
+                        * quiesce driver's activity.
+                        */
+                       ugeth_quiesce(ugeth);
+                       ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+
+                       out_be32(&ug_regs->maccfg2, tempval);
+                       out_be32(&uf_regs->upsmr, upsmr);
+
+                       ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+                       ugeth_activate(ugeth);
+               }
        } else if (ugeth->oldlink) {
                        new_state = 1;
                        ugeth->oldlink = 0;
@@ -3273,7 +3279,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
                /* Handle the transmitted buffer and release */
                /* the BD to be used with the current frame  */
 
-               if ((bd == ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
+               if (bd == ugeth->txBd[txQ]) /* queue empty? */
                        break;
 
                dev->stats.tx_packets++;
index 593e01f64e9bbc6c62e518e68fa198dd0a245155..611b80435955343eb53e25fc2ef868e76440d9a5 100644 (file)
@@ -102,6 +102,7 @@ static const int multicast_filter_limit = 32;
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <linux/bitops.h>
+#include <linux/workqueue.h>
 #include <asm/processor.h>     /* Processor type for cache alignment. */
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -389,6 +390,7 @@ struct rhine_private {
        struct net_device *dev;
        struct napi_struct napi;
        spinlock_t lock;
+       struct work_struct reset_task;
 
        /* Frequently used values: keep some adjacent for cache effect. */
        u32 quirks;
@@ -407,6 +409,7 @@ struct rhine_private {
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int  rhine_open(struct net_device *dev);
+static void rhine_reset_task(struct work_struct *work);
 static void rhine_tx_timeout(struct net_device *dev);
 static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
                                  struct net_device *dev);
@@ -775,6 +778,8 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        dev->irq = pdev->irq;
 
        spin_lock_init(&rp->lock);
+       INIT_WORK(&rp->reset_task, rhine_reset_task);
+
        rp->mii_if.dev = dev;
        rp->mii_if.mdio_read = mdio_read;
        rp->mii_if.mdio_write = mdio_write;
@@ -1179,22 +1184,18 @@ static int rhine_open(struct net_device *dev)
        return 0;
 }
 
-static void rhine_tx_timeout(struct net_device *dev)
+static void rhine_reset_task(struct work_struct *work)
 {
-       struct rhine_private *rp = netdev_priv(dev);
-       void __iomem *ioaddr = rp->base;
-
-       printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
-              "%4.4x, resetting...\n",
-              dev->name, ioread16(ioaddr + IntrStatus),
-              mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
+       struct rhine_private *rp = container_of(work, struct rhine_private,
+                                               reset_task);
+       struct net_device *dev = rp->dev;
 
        /* protect against concurrent rx interrupts */
        disable_irq(rp->pdev->irq);
 
        napi_disable(&rp->napi);
 
-       spin_lock(&rp->lock);
+       spin_lock_bh(&rp->lock);
 
        /* clear all descriptors */
        free_tbufs(dev);
@@ -1206,7 +1207,7 @@ static void rhine_tx_timeout(struct net_device *dev)
        rhine_chip_reset(dev);
        init_registers(dev);
 
-       spin_unlock(&rp->lock);
+       spin_unlock_bh(&rp->lock);
        enable_irq(rp->pdev->irq);
 
        dev->trans_start = jiffies;
@@ -1214,6 +1215,19 @@ static void rhine_tx_timeout(struct net_device *dev)
        netif_wake_queue(dev);
 }
 
+static void rhine_tx_timeout(struct net_device *dev)
+{
+       struct rhine_private *rp = netdev_priv(dev);
+       void __iomem *ioaddr = rp->base;
+
+       printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
+              "%4.4x, resetting...\n",
+              dev->name, ioread16(ioaddr + IntrStatus),
+              mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
+
+       schedule_work(&rp->reset_task);
+}
+
 static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
                                  struct net_device *dev)
 {
@@ -1830,10 +1844,11 @@ static int rhine_close(struct net_device *dev)
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
 
-       spin_lock_irq(&rp->lock);
-
-       netif_stop_queue(dev);
        napi_disable(&rp->napi);
+       cancel_work_sync(&rp->reset_task);
+       netif_stop_queue(dev);
+
+       spin_lock_irq(&rp->lock);
 
        if (debug > 1)
                printk(KERN_DEBUG "%s: Shutting down ethercard, "
index f1c4b2a1e8678ea43085c55f522a1ea12d599979..0fdfd58a35a1bc9572c27b164b4ed8e81a0060e1 100644 (file)
@@ -4087,21 +4087,21 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
                goto _exit0;
        }
 
-       if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
+       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
                vxge_debug_ll_config(VXGE_TRACE,
                        "%s : using 64bit DMA", __func__);
 
                high_dma = 1;
 
                if (pci_set_consistent_dma_mask(pdev,
-                                               0xffffffffffffffffULL)) {
+                                               DMA_BIT_MASK(64))) {
                        vxge_debug_init(VXGE_ERR,
                                "%s : unable to obtain 64bit DMA for "
                                "consistent allocations", __func__);
                        ret = -ENOMEM;
                        goto _exit1;
                }
-       } else if (!pci_set_dma_mask(pdev, 0xffffffffUL)) {
+       } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
                vxge_debug_ll_config(VXGE_TRACE,
                        "%s : using 32bit DMA", __func__);
        } else {
index a4c086f069b168aad8e9a434104e3a809e40bff1..e63b7c40d0eeb5ce0b8fcca0df66beece476e209 100644 (file)
@@ -1903,17 +1903,6 @@ accept:
                rxs->noise = sc->ah->ah_noise_floor;
                rxs->signal = rxs->noise + rs.rs_rssi;
 
-               /* An rssi of 35 indicates you should be able use
-                * 54 Mbps reliably. A more elaborate scheme can be used
-                * here but it requires a map of SNR/throughput for each
-                * possible mode used */
-               rxs->qual = rs.rs_rssi * 100 / 35;
-
-               /* rssi can be more than 35 though, anything above that
-                * should be considered at 100% */
-               if (rxs->qual > 100)
-                       rxs->qual = 100;
-
                rxs->antenna = rs.rs_antenna;
                rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
                rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
@@ -2381,6 +2370,9 @@ ath5k_init(struct ath5k_softc *sc)
         */
        ath5k_stop_locked(sc);
 
+       /* Set PHY calibration interval */
+       ah->ah_cal_intval = ath5k_calinterval;
+
        /*
         * The basic interface to setting the hardware in a good
         * state is ``reset''.  On return the hardware is known to
@@ -2408,10 +2400,6 @@ ath5k_init(struct ath5k_softc *sc)
 
        /* Set ack to be sent at low bit-rates */
        ath5k_hw_set_ack_bitrate_high(ah, false);
-
-       /* Set PHY calibration inteval */
-       ah->ah_cal_intval = ath5k_calinterval;
-
        ret = 0;
 done:
        mmiowb();
index 71b84d91dcffbb2d6edd2e66ede4b9d73f1d9fab..efc420cd42bf91322f23cf711e638b3f7e8906c2 100644 (file)
@@ -186,7 +186,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
                wait = wait_time;
                while (ath9k_hw_numtxpending(ah, q)) {
                        if ((--wait) == 0) {
-                               ath_print(common, ATH_DBG_QUEUE,
+                               ath_print(common, ATH_DBG_FATAL,
                                          "Failed to stop TX DMA in 100 "
                                          "msec after killing last frame\n");
                                break;
index 0c87771383f08902a0610b873ce04bc6f238b3f6..e185479e295e9407e771b654ee7cfcfecf436ad1 100644 (file)
@@ -77,6 +77,9 @@
 #define ATH9K_TXERR_XTXOP          0x08
 #define ATH9K_TXERR_TIMER_EXPIRED  0x10
 #define ATH9K_TX_ACKED            0x20
+#define ATH9K_TXERR_MASK                                               \
+       (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO |     \
+        ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED)
 
 #define ATH9K_TX_BA                0x01
 #define ATH9K_TX_PWRMGMT           0x02
index c48743452515c16c5fdae713ceeda416156fccab..996eb90263ccba96363b17076504bdccfe8863db 100644 (file)
@@ -1973,6 +1973,9 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
        struct ieee80211_hw *hw = sc->hw;
        int r;
 
+       /* Stop ANI */
+       del_timer_sync(&common->ani.timer);
+
        ath9k_hw_set_interrupts(ah, 0);
        ath_drain_all_txq(sc, retry_tx);
        ath_stoprecv(sc);
@@ -2014,6 +2017,9 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
                }
        }
 
+       /* Start ANI */
+       ath_start_ani(common);
+
        return r;
 }
 
@@ -2508,6 +2514,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
                return; /* another wiphy still in use */
        }
 
+       /* Ensure HW is awake when we try to shut it down. */
+       ath9k_ps_wakeup(sc);
+
        if (ah->btcoex_hw.enabled) {
                ath9k_hw_btcoex_disable(ah);
                if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
@@ -2528,6 +2537,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
        /* disable HAL and put h/w to sleep */
        ath9k_hw_disable(ah);
        ath9k_hw_configpcipowersave(ah, 1, 1);
+       ath9k_ps_restore(sc);
+
+       /* Finally, put the chip in FULL SLEEP mode */
        ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
 
        sc->sc_flags |= SC_OP_INVALID;
@@ -2641,8 +2653,10 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
            (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
            (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
+               ath9k_ps_wakeup(sc);
                ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
                ath_beacon_return(sc, avp);
+               ath9k_ps_restore(sc);
        }
 
        sc->sc_flags &= ~SC_OP_BEACONS;
@@ -3091,15 +3105,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
        case IEEE80211_AMPDU_RX_STOP:
                break;
        case IEEE80211_AMPDU_TX_START:
+               ath9k_ps_wakeup(sc);
                ath_tx_aggr_start(sc, sta, tid, ssn);
                ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               ath9k_ps_restore(sc);
                break;
        case IEEE80211_AMPDU_TX_STOP:
+               ath9k_ps_wakeup(sc);
                ath_tx_aggr_stop(sc, sta, tid);
                ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               ath9k_ps_restore(sc);
                break;
        case IEEE80211_AMPDU_TX_OPERATIONAL:
+               ath9k_ps_wakeup(sc);
                ath_tx_aggr_resume(sc, sta, tid);
+               ath9k_ps_restore(sc);
                break;
        default:
                ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
index 5321f735e5a01592a59869343c2dae16de127210..f7af5ea54753725b45325d719c8e3b0ad22f97c8 100644 (file)
@@ -96,7 +96,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common)
        pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm);
 }
 
-const static struct ath_bus_ops ath_pci_bus_ops = {
+static const struct ath_bus_ops ath_pci_bus_ops = {
        .read_cachesize = ath_pci_read_cachesize,
        .cleanup = ath_pci_cleanup,
        .eeprom_read = ath_pci_eeprom_read,
index 2a11cc57ceeae891b2ef7a0f8c1bbf105e9a7f17..fa12b9060b0bbc1f0d5ae375501abdb9c2d31a0b 100644 (file)
@@ -1108,11 +1108,11 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
        if (npend) {
                int r;
 
-               ath_print(common, ATH_DBG_XMIT,
+               ath_print(common, ATH_DBG_FATAL,
                          "Unable to stop TxDMA. Reset HAL!\n");
 
                spin_lock_bh(&sc->sc_resetlock);
-               r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true);
+               r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false);
                if (r)
                        ath_print(common, ATH_DBG_FATAL,
                                  "Unable to reset hardware; reset status %d\n",
@@ -1414,17 +1414,9 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb,
         * For HT capable stations, we save tidno for later use.
         * We also override seqno set by upper layer with the one
         * in tx aggregation state.
-        *
-        * If fragmentation is on, the sequence number is
-        * not overridden, since it has been
-        * incremented by the fragmentation routine.
-        *
-        * FIXME: check if the fragmentation threshold exceeds
-        * IEEE80211 max.
         */
        tid = ATH_AN_2_TID(an, bf->bf_tidno);
-       hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
-                       IEEE80211_SEQ_SEQ_SHIFT);
+       hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
        bf->bf_seqno = tid->seq_next;
        INCR(tid->seq_next, IEEE80211_SEQ_MAX);
 }
@@ -1636,7 +1628,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
                bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
        }
 
-       if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR))
+       if (ieee80211_is_data_qos(fc) && bf_isht(bf) &&
+           (sc->sc_flags & SC_OP_TXAGGR))
                assign_aggr_tid_seqno(skb, bf);
 
        bf->bf_mpdu = skb;
@@ -1780,7 +1773,8 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
        struct ath_wiphy *aphy = hw->priv;
        struct ath_softc *sc = aphy->sc;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       int hdrlen, padsize;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       int padpos, padsize;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ath_tx_control txctl;
 
@@ -1792,7 +1786,6 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
         * BSSes.
         */
        if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-               struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
                if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
                        sc->tx.seq_no += 0x10;
                hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
@@ -1800,9 +1793,9 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
        }
 
        /* Add the padding after the header if this is not already done */
-       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-       if (hdrlen & 3) {
-               padsize = hdrlen % 4;
+       padpos = ath9k_cmn_padpos(hdr->frame_control);
+       padsize = padpos & 3;
+       if (padsize && skb->len>padpos) {
                if (skb_headroom(skb) < padsize) {
                        ath_print(common, ATH_DBG_XMIT,
                                  "TX CABQ padding failed\n");
@@ -1810,7 +1803,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
                        return;
                }
                skb_push(skb, padsize);
-               memmove(skb->data, skb->data + padsize, hdrlen);
+               memmove(skb->data, skb->data + padsize, padpos);
        }
 
        txctl.txq = sc->beacon.cabq;
@@ -1838,7 +1831,8 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
        struct ieee80211_hw *hw = sc->hw;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       int hdrlen, padsize;
+       struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
+       int padpos, padsize;
 
        ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
 
@@ -1853,14 +1847,14 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
                tx_info->flags |= IEEE80211_TX_STAT_ACK;
        }
 
-       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-       padsize = hdrlen & 3;
-       if (padsize && hdrlen >= 24) {
+       padpos = ath9k_cmn_padpos(hdr->frame_control);
+       padsize = padpos & 3;
+       if (padsize && skb->len>padpos+padsize) {
                /*
                 * Remove MAC header padding before giving the frame back to
                 * mac80211.
                 */
-               memmove(skb->data + padsize, skb->data, hdrlen);
+               memmove(skb->data + padsize, skb->data, padpos);
                skb_pull(skb, padsize);
        }
 
@@ -2078,7 +2072,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
                                &txq->axq_q, lastbf->list.prev);
 
                txq->axq_depth--;
-               txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_FILT);
+               txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK);
                txq->axq_tx_inprogress = false;
                spin_unlock_bh(&txq->axq_lock);
 
index 027be275e0351ee401e28d4b7f5993bbe3c0def5..88d1fd02d40ae50fd01b645e921e83e8c48fbced 100644 (file)
@@ -383,160 +383,44 @@ static inline
        }
 }
 
-/* Check if a DMA region fits the device constraints.
- * Returns true, if the region is OK for usage with this device. */
-static inline bool b43_dma_address_ok(struct b43_dmaring *ring,
-                                     dma_addr_t addr, size_t size)
-{
-       switch (ring->type) {
-       case B43_DMA_30BIT:
-               if ((u64)addr + size > (1ULL << 30))
-                       return 0;
-               break;
-       case B43_DMA_32BIT:
-               if ((u64)addr + size > (1ULL << 32))
-                       return 0;
-               break;
-       case B43_DMA_64BIT:
-               /* Currently we can't have addresses beyond
-                * 64bit in the kernel. */
-               break;
-       }
-       return 1;
-}
-
-#define is_4k_aligned(addr)    (((u64)(addr) & 0x0FFFull) == 0)
-#define is_8k_aligned(addr)    (((u64)(addr) & 0x1FFFull) == 0)
-
-static void b43_unmap_and_free_ringmem(struct b43_dmaring *ring, void *base,
-                                      dma_addr_t dmaaddr, size_t size)
-{
-       ssb_dma_unmap_single(ring->dev->dev, dmaaddr, size, DMA_TO_DEVICE);
-       free_pages((unsigned long)base, get_order(size));
-}
-
-static void * __b43_get_and_map_ringmem(struct b43_dmaring *ring,
-                                       dma_addr_t *dmaaddr, size_t size,
-                                       gfp_t gfp_flags)
-{
-       void *base;
-
-       base = (void *)__get_free_pages(gfp_flags, get_order(size));
-       if (!base)
-               return NULL;
-       memset(base, 0, size);
-       *dmaaddr = ssb_dma_map_single(ring->dev->dev, base, size,
-                                     DMA_TO_DEVICE);
-       if (ssb_dma_mapping_error(ring->dev->dev, *dmaaddr)) {
-               free_pages((unsigned long)base, get_order(size));
-               return NULL;
-       }
-
-       return base;
-}
-
-static void * b43_get_and_map_ringmem(struct b43_dmaring *ring,
-                                     dma_addr_t *dmaaddr, size_t size)
-{
-       void *base;
-
-       base = __b43_get_and_map_ringmem(ring, dmaaddr, size,
-                                        GFP_KERNEL);
-       if (!base) {
-               b43err(ring->dev->wl, "Failed to allocate or map pages "
-                      "for DMA ringmemory\n");
-               return NULL;
-       }
-       if (!b43_dma_address_ok(ring, *dmaaddr, size)) {
-               /* The memory does not fit our device constraints.
-                * Retry with GFP_DMA set to get lower memory. */
-               b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size);
-               base = __b43_get_and_map_ringmem(ring, dmaaddr, size,
-                                                GFP_KERNEL | GFP_DMA);
-               if (!base) {
-                       b43err(ring->dev->wl, "Failed to allocate or map pages "
-                              "in the GFP_DMA region for DMA ringmemory\n");
-                       return NULL;
-               }
-               if (!b43_dma_address_ok(ring, *dmaaddr, size)) {
-                       b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size);
-                       b43err(ring->dev->wl, "Failed to allocate DMA "
-                              "ringmemory that fits device constraints\n");
-                       return NULL;
-               }
-       }
-       /* We expect the memory to be 4k aligned, at least. */
-       if (B43_WARN_ON(!is_4k_aligned(*dmaaddr))) {
-               b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size);
-               return NULL;
-       }
-
-       return base;
-}
-
 static int alloc_ringmemory(struct b43_dmaring *ring)
 {
-       unsigned int required;
-       void *base;
-       dma_addr_t dmaaddr;
-
-       /* There are several requirements to the descriptor ring memory:
-        * - The memory region needs to fit the address constraints for the
-        *   device (same as for frame buffers).
-        * - For 30/32bit DMA devices, the descriptor ring must be 4k aligned.
-        * - For 64bit DMA devices, the descriptor ring must be 8k aligned.
+       gfp_t flags = GFP_KERNEL;
+
+       /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
+        * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing
+        * has shown that 4K is sufficient for the latter as long as the buffer
+        * does not cross an 8K boundary.
+        *
+        * For unknown reasons - possibly a hardware error - the BCM4311 rev
+        * 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
+        * which accounts for the GFP_DMA flag below.
+        *
+        * The flags here must match the flags in free_ringmemory below!
         */
-
        if (ring->type == B43_DMA_64BIT)
-               required = ring->nr_slots * sizeof(struct b43_dmadesc64);
-       else
-               required = ring->nr_slots * sizeof(struct b43_dmadesc32);
-       if (B43_WARN_ON(required > 0x1000))
+               flags |= GFP_DMA;
+       ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev,
+                                                 B43_DMA_RINGMEMSIZE,
+                                                 &(ring->dmabase), flags);
+       if (!ring->descbase) {
+               b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
                return -ENOMEM;
-
-       ring->alloc_descsize = 0x1000;
-       base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize);
-       if (!base)
-               return -ENOMEM;
-       ring->alloc_descbase = base;
-       ring->alloc_dmabase = dmaaddr;
-
-       if ((ring->type != B43_DMA_64BIT) || is_8k_aligned(dmaaddr)) {
-               /* We're on <=32bit DMA, or we already got 8k aligned memory.
-                * That's all we need, so we're fine. */
-               ring->descbase = base;
-               ring->dmabase = dmaaddr;
-               return 0;
-       }
-       b43_unmap_and_free_ringmem(ring, base, dmaaddr, ring->alloc_descsize);
-
-       /* Ok, we failed at the 8k alignment requirement.
-        * Try to force-align the memory region now. */
-       ring->alloc_descsize = 0x2000;
-       base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize);
-       if (!base)
-               return -ENOMEM;
-       ring->alloc_descbase = base;
-       ring->alloc_dmabase = dmaaddr;
-
-       if (is_8k_aligned(dmaaddr)) {
-               /* We're already 8k aligned. That Ok, too. */
-               ring->descbase = base;
-               ring->dmabase = dmaaddr;
-               return 0;
        }
-       /* Force-align it to 8k */
-       ring->descbase = (void *)((u8 *)base + 0x1000);
-       ring->dmabase = dmaaddr + 0x1000;
-       B43_WARN_ON(!is_8k_aligned(ring->dmabase));
+       memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE);
 
        return 0;
 }
 
 static void free_ringmemory(struct b43_dmaring *ring)
 {
-       b43_unmap_and_free_ringmem(ring, ring->alloc_descbase,
-                                  ring->alloc_dmabase, ring->alloc_descsize);
+       gfp_t flags = GFP_KERNEL;
+
+       if (ring->type == B43_DMA_64BIT)
+               flags |= GFP_DMA;
+
+       ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE,
+                               ring->descbase, ring->dmabase, flags);
 }
 
 /* Reset the RX DMA channel */
@@ -646,14 +530,29 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
        if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr)))
                return 1;
 
-       if (!b43_dma_address_ok(ring, addr, buffersize)) {
-               /* We can't support this address. Unmap it again. */
-               unmap_descbuffer(ring, addr, buffersize, dma_to_device);
-               return 1;
+       switch (ring->type) {
+       case B43_DMA_30BIT:
+               if ((u64)addr + buffersize > (1ULL << 30))
+                       goto address_error;
+               break;
+       case B43_DMA_32BIT:
+               if ((u64)addr + buffersize > (1ULL << 32))
+                       goto address_error;
+               break;
+       case B43_DMA_64BIT:
+               /* Currently we can't have addresses beyond
+                * 64bit in the kernel. */
+               break;
        }
 
        /* The address is OK. */
        return 0;
+
+address_error:
+       /* We can't support this address. Unmap it again. */
+       unmap_descbuffer(ring, addr, buffersize, dma_to_device);
+
+       return 1;
 }
 
 static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb)
@@ -715,9 +614,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
        meta->dmaaddr = dmaaddr;
        ring->ops->fill_descriptor(ring, desc, dmaaddr,
                                   ring->rx_buffersize, 0, 0, 0);
-       ssb_dma_sync_single_for_device(ring->dev->dev,
-                                      ring->alloc_dmabase,
-                                      ring->alloc_descsize, DMA_TO_DEVICE);
 
        return 0;
 }
@@ -1354,9 +1250,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
        }
        /* Now transfer the whole frame. */
        wmb();
-       ssb_dma_sync_single_for_device(ring->dev->dev,
-                                      ring->alloc_dmabase,
-                                      ring->alloc_descsize, DMA_TO_DEVICE);
        ops->poke_tx(ring, next_slot(ring, slot));
        return 0;
 
index e607b392314c9449a49431dcb92ebf47f8da1dfd..f7ab37c4cdbc8dfa88301c5384c91650e1046f63 100644 (file)
@@ -157,6 +157,7 @@ struct b43_dmadesc_generic {
 } __attribute__ ((__packed__));
 
 /* Misc DMA constants */
+#define B43_DMA_RINGMEMSIZE            PAGE_SIZE
 #define B43_DMA0_RX_FRAMEOFFSET                30
 
 /* DMA engine tuning knobs */
@@ -246,12 +247,6 @@ struct b43_dmaring {
        /* The QOS priority assigned to this ring. Only used for TX rings.
         * This is the mac80211 "queue" value. */
        u8 queue_prio;
-       /* Pointers and size of the originally allocated and mapped memory
-        * region for the descriptor ring. */
-       void *alloc_descbase;
-       dma_addr_t alloc_dmabase;
-       unsigned int alloc_descsize;
-       /* Pointer to our wireless device. */
        struct b43_wldev *dev;
 #ifdef CONFIG_B43_DEBUG
        /* Maximum number of used slots. */
index 7da1dab933d985b2777ce51412b5650e91e7c62c..234891d8cc1080b5358b624cf992fbc6d43510a6 100644 (file)
@@ -681,19 +681,13 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
                snr = rx_stats_sig_avg / rx_stats_noise_diff;
                rx_status.noise = rx_status.signal -
                                        iwl3945_calc_db_from_ratio(snr);
-               rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal,
-                                                        rx_status.noise);
-
-       /* If noise info not available, calculate signal quality indicator (%)
-        *   using just the dBm signal level. */
        } else {
                rx_status.noise = priv->last_rx_noise;
-               rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0);
        }
 
 
-       IWL_DEBUG_STATS(priv, "Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n",
-                       rx_status.signal, rx_status.noise, rx_status.qual,
+       IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n",
+                       rx_status.signal, rx_status.noise,
                        rx_stats_sig_avg, rx_stats_noise_diff);
 
        header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
@@ -1835,8 +1829,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
                rc = -EIO;
        }
 
-       priv->alloc_rxb_page--;
-       free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
+       iwl_free_pages(priv, cmd.reply_page);
 
        return rc;
 }
@@ -2836,6 +2829,7 @@ static struct iwl_cfg iwl3945_bg_cfg = {
        .use_isr_legacy = true,
        .ht_greenfield_support = false,
        .led_compensation = 64,
+       .broken_powersave = true,
 };
 
 static struct iwl_cfg iwl3945_abg_cfg = {
@@ -2852,6 +2846,7 @@ static struct iwl_cfg iwl3945_abg_cfg = {
        .use_isr_legacy = true,
        .ht_greenfield_support = false,
        .led_compensation = 64,
+       .broken_powersave = true,
 };
 
 struct pci_device_id iwl3945_hw_card_ids[] = {
index ecc23ec1f6a42981040112aca718afc5d6d15ea7..531fa125f5a60744b4c20f33bc61db4713394420 100644 (file)
@@ -222,7 +222,6 @@ struct iwl3945_ibss_seq {
  *
  *****************************************************************************/
 extern int iwl3945_calc_db_from_ratio(int sig_ratio);
-extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm);
 extern void iwl3945_rx_replenish(void *data);
 extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
 extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
index 386513b601f5caff86e22c73d90e106015cdc8be..484c5fdf7c2a511143ed569ec11833f7d45d7424 100644 (file)
@@ -1204,7 +1204,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
        iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info);
 
        /* calculate tx gain adjustment based on power supply voltage */
-       voltage = priv->calib_info->voltage;
+       voltage = le16_to_cpu(priv->calib_info->voltage);
        init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage);
        voltage_compensation =
            iwl4965_get_voltage_compensation(voltage, init_voltage);
index 4ef6804a455af2e31259db3a048fe4360f20dfe1..bc056e9ab85f0e38f73f60614462f8d36236fa73 100644 (file)
 
 static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
 {
-       u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv,
-                                                      EEPROM_5000_TEMPERATURE);
-       /* offset =  temperature -  voltage / coef */
-       s32 offset = (s32)(temp_calib[0] - temp_calib[1] / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF);
-       return offset;
+       u16 temperature, voltage;
+       __le16 *temp_calib =
+               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
+
+       temperature = le16_to_cpu(temp_calib[0]);
+       voltage = le16_to_cpu(temp_calib[1]);
+
+       /* offset = temp - volt / coeff */
+       return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF);
 }
 
 /* Fixed (non-configurable) rx data from phy */
index e2f8615c8c9b77bf81004bc7e415133fc5b2eb74..33a5866538e7dbbbc0c7b0a13085075a59939fba 100644 (file)
@@ -333,14 +333,15 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
 static int iwl5000_set_Xtal_calib(struct iwl_priv *priv)
 {
        struct iwl_calib_xtal_freq_cmd cmd;
-       u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);
+       __le16 *xtal_calib =
+               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);
 
        cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
        cmd.hdr.first_group = 0;
        cmd.hdr.groups_num = 1;
        cmd.hdr.data_valid = 1;
-       cmd.cap_pin1 = (u8)xtal_calib[0];
-       cmd.cap_pin2 = (u8)xtal_calib[1];
+       cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
+       cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
        return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL],
                             (u8 *)&cmd, sizeof(cmd));
 }
index fe511cbf012e009daaecb22e1be14d4be2b0d466..b93e49158196b47cc7f01c5f69c7a1b7badfbd96 100644 (file)
@@ -150,7 +150,7 @@ static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = {
 };
 
 /* mbps, mcs */
-const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
+static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
        {  "1", "BPSK DSSS"},
        {  "2", "QPSK DSSS"},
        {"5.5", "BPSK CCK"},
index b8377efb3ba71f873b646ae5020669d1b6c8fb16..1c9866daf81565007beb6ee596063702e4bf387f 100644 (file)
@@ -1842,7 +1842,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
        }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-       if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS))
+       if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
                size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
                        ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
 #else
@@ -3173,7 +3173,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
 
        priv->ibss_beacon = NULL;
 
-       spin_lock_init(&priv->lock);
        spin_lock_init(&priv->sta_lock);
        spin_lock_init(&priv->hcmd_lock);
 
@@ -3361,10 +3360,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                (unsigned long long) pci_resource_len(pdev, 0));
        IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
 
-       /* this spin lock will be used in apm_ops.init and EEPROM access
+       /* these spin locks will be used in apm_ops.init and EEPROM access
         * we should init now
         */
        spin_lock_init(&priv->reg_lock);
+       spin_lock_init(&priv->lock);
        iwl_hw_detect(priv);
        IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n",
                priv->cfg->name, priv->hw_rev);
index a7bfae01f19b017e674ca15eee0a50aff8c2411f..1ec8cb4d5eae4f541ec2bc158a963f72c9a456f8 100644 (file)
@@ -77,8 +77,7 @@
  * The MAC (uCode processor, etc.) does not need to be powered up for accessing
  * the CSR registers.
  *
- * NOTE:  Newer devices using one-time-programmable (OTP) memory
- *        require device to be awake in order to read this memory
+ * NOTE:  Device does need to be awake in order to read this memory
  *        via CSR_EEPROM and CSR_OTP registers
  */
 #define CSR_BASE    (0x000)
 /*
  * EEPROM and OTP (one-time-programmable) memory reads
  *
- * NOTE:  For (newer) devices using OTP, device must be awake, initialized via
- *        apm_ops.init() in order to read.  Older devices (3945/4965/5000)
- *        use EEPROM and do not require this.
+ * NOTE:  Device must be awake, initialized via apm_ops.init(),
+ *        in order to read.
  */
 #define CSR_EEPROM_REG          (CSR_BASE+0x02c)
 #define CSR_EEPROM_GP           (CSR_BASE+0x030)
index 2673e9a4db92c4992a52bb34a0bbfd0a99cb1f0d..165d1f6e2dd9304046895b437fd65e0d2f88e580 100644 (file)
@@ -1168,7 +1168,7 @@ struct iwl_priv {
        u32 last_beacon_time;
        u64 last_tsf;
 
-       /* eeprom */
+       /* eeprom -- this is in the card's little endian byte order */
        u8 *eeprom;
        int    nvm_device_type;
        struct iwl_eeprom_calib_info *calib_info;
@@ -1353,4 +1353,15 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch)
        return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
 }
 
+static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page)
+{
+       __free_pages(page, priv->hw_params.rx_page_order);
+       priv->alloc_rxb_page--;
+}
+
+static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page)
+{
+       free_pages(page, priv->hw_params.rx_page_order);
+       priv->alloc_rxb_page--;
+}
 #endif                         /* __iwl_dev_h__ */
index 3946e5c03f818e75651c7387d807edce2ab26078..4a30969689ff5eb777e76f4d8609f84f66570bd4 100644 (file)
@@ -370,7 +370,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
        return ret;
 }
 
-static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
+static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_data)
 {
        int ret = 0;
        u32 r;
@@ -404,7 +404,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
                                CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
                IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
        }
-       *eeprom_data = le16_to_cpu((__force __le16)(r >> 16));
+       *eeprom_data = cpu_to_le16(r >> 16);
        return 0;
 }
 
@@ -413,7 +413,8 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
  */
 static bool iwl_is_otp_empty(struct iwl_priv *priv)
 {
-       u16 next_link_addr = 0, link_value;
+       u16 next_link_addr = 0;
+       __le16 link_value;
        bool is_empty = false;
 
        /* locate the beginning of OTP link list */
@@ -443,7 +444,8 @@ static bool iwl_is_otp_empty(struct iwl_priv *priv)
 static int iwl_find_otp_image(struct iwl_priv *priv,
                                        u16 *validblockaddr)
 {
-       u16 next_link_addr = 0, link_value = 0, valid_addr;
+       u16 next_link_addr = 0, valid_addr;
+       __le16 link_value = 0;
        int usedblocks = 0;
 
        /* set addressing mode to absolute to traverse the link list */
@@ -463,7 +465,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
                 * check for more block on the link list
                 */
                valid_addr = next_link_addr;
-               next_link_addr = link_value * sizeof(u16);
+               next_link_addr = le16_to_cpu(link_value) * sizeof(u16);
                IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
                               usedblocks, next_link_addr);
                if (iwl_read_otp_word(priv, next_link_addr, &link_value))
@@ -497,7 +499,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
  */
 int iwl_eeprom_init(struct iwl_priv *priv)
 {
-       u16 *e;
+       __le16 *e;
        u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
        int sz;
        int ret;
@@ -516,12 +518,9 @@ int iwl_eeprom_init(struct iwl_priv *priv)
                ret = -ENOMEM;
                goto alloc_err;
        }
-       e = (u16 *)priv->eeprom;
+       e = (__le16 *)priv->eeprom;
 
-       if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
-               /* OTP reads require powered-up chip */
-               priv->cfg->ops->lib->apm_ops.init(priv);
-       }
+       priv->cfg->ops->lib->apm_ops.init(priv);
 
        ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
        if (ret < 0) {
@@ -562,7 +561,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
                }
                for (addr = validblockaddr; addr < validblockaddr + sz;
                     addr += sizeof(u16)) {
-                       u16 eeprom_data;
+                       __le16 eeprom_data;
 
                        ret = iwl_read_otp_word(priv, addr, &eeprom_data);
                        if (ret)
@@ -570,13 +569,6 @@ int iwl_eeprom_init(struct iwl_priv *priv)
                        e[cache_addr / 2] = eeprom_data;
                        cache_addr += sizeof(u16);
                }
-
-               /*
-                * Now that OTP reads are complete, reset chip to save
-                *   power until we load uCode during "up".
-                */
-               priv->cfg->ops->lib->apm_ops.stop(priv);
-
        } else {
                /* eeprom is an array of 16bit values */
                for (addr = 0; addr < sz; addr += sizeof(u16)) {
@@ -594,7 +586,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
                                goto done;
                        }
                        r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
-                       e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
+                       e[addr / 2] = cpu_to_le16(r >> 16);
                }
        }
        ret = 0;
@@ -603,6 +595,8 @@ done:
 err:
        if (ret)
                iwl_eeprom_free(priv);
+       /* Reset chip to save power until we load uCode during "up". */
+       priv->cfg->ops->lib->apm_ops.stop(priv);
 alloc_err:
        return ret;
 }
@@ -755,7 +749,8 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
        ch_info->ht40_eeprom = *eeprom_ch;
        ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
        ch_info->ht40_flags = eeprom_ch->flags;
-       ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel;
+       if (eeprom_ch->flags & EEPROM_CHANNEL_VALID)
+               ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel;
 
        return 0;
 }
index 5cd2b66bbe45235525c990f609021807704089ad..0cd9c02ee0441be719117a81037c2db9cd5993da 100644 (file)
@@ -137,7 +137,7 @@ struct iwl_eeprom_channel {
  *
  */
 struct iwl_eeprom_enhanced_txpwr {
-       u16 common;
+       __le16 common;
        s8 chain_a_max;
        s8 chain_b_max;
        s8 chain_c_max;
@@ -360,7 +360,7 @@ struct iwl_eeprom_calib_subband_info {
 struct iwl_eeprom_calib_info {
        u8 saturation_power24;  /* half-dBm (e.g. "34" = 17 dBm) */
        u8 saturation_power52;  /* half-dBm */
-       s16 voltage;            /* signed */
+       __le16 voltage;         /* signed */
        struct iwl_eeprom_calib_subband_info
                band_info[EEPROM_TX_POWER_BANDS];
 } __attribute__ ((packed));
index a23165948202054c4ec59a78f42a6ddb580efb10..30e9ea6d54ecd8dc18f2fa4416cd581bfdaa67e8 100644 (file)
@@ -234,7 +234,7 @@ cancel:
        }
 fail:
        if (cmd->reply_page) {
-               free_pages(cmd->reply_page, priv->hw_params.rx_page_order);
+               iwl_free_pages(priv, cmd->reply_page);
                cmd->reply_page = 0;
        }
 out:
index 6090bc15a6d536ab18c0219740c4a44740974835..6f36b6e79f5e3db56d72fdcbcab1da493ae41e8a 100644 (file)
@@ -345,10 +345,8 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
                        pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
                                PAGE_SIZE << priv->hw_params.rx_page_order,
                                PCI_DMA_FROMDEVICE);
-                       __free_pages(rxq->pool[i].page,
-                                    priv->hw_params.rx_page_order);
+                       __iwl_free_pages(priv, rxq->pool[i].page);
                        rxq->pool[i].page = NULL;
-                       priv->alloc_rxb_page--;
                }
        }
 
@@ -416,9 +414,7 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
                        pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
                                PAGE_SIZE << priv->hw_params.rx_page_order,
                                PCI_DMA_FROMDEVICE);
-                       priv->alloc_rxb_page--;
-                       __free_pages(rxq->pool[i].page,
-                                    priv->hw_params.rx_page_order);
+                       __iwl_free_pages(priv, rxq->pool[i].page);
                        rxq->pool[i].page = NULL;
                }
                list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
@@ -654,47 +650,6 @@ void iwl_reply_statistics(struct iwl_priv *priv,
 }
 EXPORT_SYMBOL(iwl_reply_statistics);
 
-#define PERFECT_RSSI (-20) /* dBm */
-#define WORST_RSSI (-95)   /* dBm */
-#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
-
-/* Calculate an indication of rx signal quality (a percentage, not dBm!).
- * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
- *   about formulas used below. */
-static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
-{
-       int sig_qual;
-       int degradation = PERFECT_RSSI - rssi_dbm;
-
-       /* If we get a noise measurement, use signal-to-noise ratio (SNR)
-        * as indicator; formula is (signal dbm - noise dbm).
-        * SNR at or above 40 is a great signal (100%).
-        * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
-        * Weakest usable signal is usually 10 - 15 dB SNR. */
-       if (noise_dbm) {
-               if (rssi_dbm - noise_dbm >= 40)
-                       return 100;
-               else if (rssi_dbm < noise_dbm)
-                       return 0;
-               sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
-
-       /* Else use just the signal level.
-        * This formula is a least squares fit of data points collected and
-        *   compared with a reference system that had a percentage (%) display
-        *   for signal quality. */
-       } else
-               sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
-                           (15 * RSSI_RANGE + 62 * degradation)) /
-                          (RSSI_RANGE * RSSI_RANGE);
-
-       if (sig_qual > 100)
-               sig_qual = 100;
-       else if (sig_qual < 1)
-               sig_qual = 0;
-
-       return sig_qual;
-}
-
 /* Calc max signal level (dBm) among 3 possible receivers */
 static inline int iwl_calc_rssi(struct iwl_priv *priv,
                                struct iwl_rx_phy_res *rx_resp)
@@ -1105,11 +1060,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
        if (iwl_is_associated(priv) &&
            !test_bit(STATUS_SCANNING, &priv->status)) {
                rx_status.noise = priv->last_rx_noise;
-               rx_status.qual = iwl_calc_sig_qual(rx_status.signal,
-                                                        rx_status.noise);
        } else {
                rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-               rx_status.qual = iwl_calc_sig_qual(rx_status.signal, 0);
        }
 
        /* Reset beacon noise level if not associated. */
@@ -1122,8 +1074,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
                iwl_dbg_report_frame(priv, phy_res, len, header, 1);
 #endif
        iwl_dbg_log_rx_data_frame(priv, len, header);
-       IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n",
-               rx_status.signal, rx_status.noise, rx_status.qual,
+       IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n",
+               rx_status.signal, rx_status.noise,
                (unsigned long long)rx_status.mactime);
 
        /*
index a2b2b8315ff9efa2509c47dbfafe123644423d7f..fa1c89ba6459645632d3425511b0a016edd97a08 100644 (file)
@@ -144,8 +144,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
                clear_bit(STATUS_SCAN_HW, &priv->status);
        }
 
-       priv->alloc_rxb_page--;
-       free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
+       iwl_free_pages(priv, cmd.reply_page);
 
        return ret;
 }
index cd6a6901216ec63892617f167591b32ddbfb2984..cde09a890b73f281fc65bf62e14a9dde8ab7bb61 100644 (file)
@@ -164,9 +164,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
                        break;
                }
        }
-
-       priv->alloc_rxb_page--;
-       free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
+       iwl_free_pages(priv, cmd.reply_page);
 
        return ret;
 }
@@ -391,9 +389,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
                        break;
                }
        }
-
-       priv->alloc_rxb_page--;
-       free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
+       iwl_free_pages(priv, cmd.reply_page);
 
        return ret;
 }
index 00da5e152d46330de2bc701f6969434c8853f092..87ce2bd292c7810630cd382239a15283f82add76 100644 (file)
@@ -407,13 +407,14 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
        int txq_id;
 
        /* Tx queues */
-       if (priv->txq)
+       if (priv->txq) {
                for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
                     txq_id++)
                        if (txq_id == IWL_CMD_QUEUE_NUM)
                                iwl_cmd_queue_free(priv);
                        else
                                iwl_tx_queue_free(priv, txq_id);
+       }
        iwl_free_dma_ptr(priv, &priv->kw);
 
        iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
index 2a28a1f8b1fe170eea264ed4a96bdb472ded3240..f8e4e4b18d02bee66f711e29080c4cc2b8a6366a 100644 (file)
@@ -548,6 +548,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        txq = &priv->txq[txq_id];
        q = &txq->q;
 
+       if ((iwl_queue_space(q) < q->high_mark))
+               goto drop;
+
        spin_lock_irqsave(&priv->lock, flags);
 
        idx = get_cmd_index(q, q->write_ptr, 0);
@@ -812,7 +815,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
                break;
        }
 
-       free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
+       iwl_free_pages(priv, cmd.reply_page);
 
        return rc;
 }
@@ -1198,9 +1201,7 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
                        pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
                                PAGE_SIZE << priv->hw_params.rx_page_order,
                                PCI_DMA_FROMDEVICE);
-                       priv->alloc_rxb_page--;
-                       __free_pages(rxq->pool[i].page,
-                                    priv->hw_params.rx_page_order);
+                       __iwl_free_pages(priv, rxq->pool[i].page);
                        rxq->pool[i].page = NULL;
                }
                list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
@@ -1247,10 +1248,8 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx
                        pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
                                PAGE_SIZE << priv->hw_params.rx_page_order,
                                PCI_DMA_FROMDEVICE);
-                       __free_pages(rxq->pool[i].page,
-                                    priv->hw_params.rx_page_order);
+                       __iwl_free_pages(priv, rxq->pool[i].page);
                        rxq->pool[i].page = NULL;
-                       priv->alloc_rxb_page--;
                }
        }
 
@@ -1300,47 +1299,6 @@ int iwl3945_calc_db_from_ratio(int sig_ratio)
        return (int)ratio2dB[sig_ratio];
 }
 
-#define PERFECT_RSSI (-20) /* dBm */
-#define WORST_RSSI (-95)   /* dBm */
-#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
-
-/* Calculate an indication of rx signal quality (a percentage, not dBm!).
- * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
- *   about formulas used below. */
-int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm)
-{
-       int sig_qual;
-       int degradation = PERFECT_RSSI - rssi_dbm;
-
-       /* If we get a noise measurement, use signal-to-noise ratio (SNR)
-        * as indicator; formula is (signal dbm - noise dbm).
-        * SNR at or above 40 is a great signal (100%).
-        * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
-        * Weakest usable signal is usually 10 - 15 dB SNR. */
-       if (noise_dbm) {
-               if (rssi_dbm - noise_dbm >= 40)
-                       return 100;
-               else if (rssi_dbm < noise_dbm)
-                       return 0;
-               sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
-
-       /* Else use just the signal level.
-        * This formula is a least squares fit of data points collected and
-        *   compared with a reference system that had a percentage (%) display
-        *   for signal quality. */
-       } else
-               sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
-                           (15 * RSSI_RANGE + 62 * degradation)) /
-                          (RSSI_RANGE * RSSI_RANGE);
-
-       if (sig_qual > 100)
-               sig_qual = 100;
-       else if (sig_qual < 1)
-               sig_qual = 0;
-
-       return sig_qual;
-}
-
 /**
  * iwl3945_rx_handle - Main entry function for receiving responses from uCode
  *
@@ -1688,7 +1646,7 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
        }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-       if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS))
+       if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
                size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
                        ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
 #else
@@ -3867,7 +3825,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
        priv->retry_rate = 1;
        priv->ibss_beacon = NULL;
 
-       spin_lock_init(&priv->lock);
        spin_lock_init(&priv->sta_lock);
        spin_lock_init(&priv->hcmd_lock);
 
@@ -3936,9 +3893,11 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
        /* Tell mac80211 our characteristics */
        hw->flags = IEEE80211_HW_SIGNAL_DBM |
                    IEEE80211_HW_NOISE_DBM |
-                   IEEE80211_HW_SPECTRUM_MGMT |
-                   IEEE80211_HW_SUPPORTS_PS |
-                   IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
+                   IEEE80211_HW_SPECTRUM_MGMT;
+
+       if (!priv->cfg->broken_powersave)
+               hw->flags |= IEEE80211_HW_SUPPORTS_PS |
+                            IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_STATION) |
@@ -4057,10 +4016,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
         * PCI Tx retries from interfering with C3 CPU state */
        pci_write_config_byte(pdev, 0x41, 0x00);
 
-       /* this spin lock will be used in apm_ops.init and EEPROM access
+       /* these spin locks will be used in apm_ops.init and EEPROM access
         * we should init now
         */
        spin_lock_init(&priv->reg_lock);
+       spin_lock_init(&priv->lock);
 
        /***********************
         * 4. Read EEPROM
index 5a26bb05a33ae8867f77179c5329053d9f258a11..842811142bef0c951eea272e93ac674fe21c76ae 100644 (file)
@@ -268,7 +268,7 @@ struct iwm_priv {
 
        struct sk_buff_head rx_list;
        struct list_head rx_tickets;
-       struct list_head rx_packets[IWM_RX_ID_HASH];
+       struct list_head rx_packets[IWM_RX_ID_HASH + 1];
        struct workqueue_struct *rx_wq;
        struct work_struct rx_worker;
 
@@ -349,7 +349,7 @@ int iwm_up(struct iwm_priv *iwm);
 int iwm_down(struct iwm_priv *iwm);
 
 /* TX API */
-u16 iwm_tid_to_queue(u16 tid);
+int iwm_tid_to_queue(u16 tid);
 void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages);
 void iwm_tx_worker(struct work_struct *work);
 int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
index e4f0f8705f65c29b3935d81e5dc481b1f0b0055d..c4c0d23c63ecbcefc6a8b7896849bbd779ece0dc 100644 (file)
@@ -76,7 +76,7 @@ static int iwm_stop(struct net_device *ndev)
  */
 static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
 
-u16 iwm_tid_to_queue(u16 tid)
+int iwm_tid_to_queue(u16 tid)
 {
        if (tid > IWM_UMAC_TID_NR - 2)
                return -EINVAL;
index 1c57c1f72cba46c9f6cc2545208d67ef9677857e..6d6ed7485175a6f2d8f8d05793767e08c6f91c69 100644 (file)
@@ -1126,7 +1126,7 @@ static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf,
 
                if (!stop) {
                        struct iwm_tx_queue *txq;
-                       u16 queue = iwm_tid_to_queue(bit);
+                       int queue = iwm_tid_to_queue(bit);
 
                        if (queue < 0)
                                continue;
index 2f91c9b808af0b2b9434b771381b88c95b548dc8..92b7a357a5e491d538477140d3f4f9855da99394 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
+#include <linux/if_ether.h>
 #include <linux/if_arp.h>
 #include <linux/kthread.h>
 #include <linux/kfifo.h>
@@ -351,8 +352,7 @@ int lbs_add_mesh(struct lbs_private *priv)
 
        mesh_dev->netdev_ops = &mesh_netdev_ops;
        mesh_dev->ethtool_ops = &lbs_ethtool_ops;
-       memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
-                       sizeof(priv->dev->dev_addr));
+       memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN);
 
        SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
 
index c6a6c042b82f66acddc00fe02e9f4e523d11b600..b0b1c7841500281eb7031554131aa8e713cdc3b4 100644 (file)
@@ -567,11 +567,8 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan)
        chan_count = lbs_scan_create_channel_list(priv, chan_list);
 
        netif_stop_queue(priv->dev);
-       netif_carrier_off(priv->dev);
-       if (priv->mesh_dev) {
+       if (priv->mesh_dev)
                netif_stop_queue(priv->mesh_dev);
-               netif_carrier_off(priv->mesh_dev);
-       }
 
        /* Prepare to continue an interrupted scan */
        lbs_deb_scan("chan_count %d, scan_channel %d\n",
@@ -635,16 +632,13 @@ out2:
        priv->scan_channel = 0;
 
 out:
-       if (priv->connect_status == LBS_CONNECTED) {
-               netif_carrier_on(priv->dev);
-               if (!priv->tx_pending_len)
-                       netif_wake_queue(priv->dev);
-       }
-       if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) {
-               netif_carrier_on(priv->mesh_dev);
-               if (!priv->tx_pending_len)
-                       netif_wake_queue(priv->mesh_dev);
-       }
+       if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len)
+               netif_wake_queue(priv->dev);
+
+       if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED) &&
+           !priv->tx_pending_len)
+               netif_wake_queue(priv->mesh_dev);
+
        kfree(chan_list);
 
        lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
index a8eb9e1fcf36ac7cca8cd3c4965af40f1454f310..4b1aab593a84ea93fbfd7721d58004e65113fd26 100644 (file)
@@ -2025,10 +2025,8 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
        if (priv->connect_status == LBS_CONNECTED) {
                memcpy(extra, priv->curbssparams.ssid,
                       priv->curbssparams.ssid_len);
-               extra[priv->curbssparams.ssid_len] = '\0';
        } else {
                memset(extra, 0, 32);
-               extra[priv->curbssparams.ssid_len] = '\0';
        }
        /*
         * If none, we may want to get the one that was set
index 019431d2f8a900ebe1f981aff8fd40b309e419b1..26a1abd5bb031c9b9c63565eaf1b9e298373d136 100644 (file)
@@ -495,7 +495,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
        stats.band = IEEE80211_BAND_2GHZ;
        stats.signal = prxpd->snr;
        stats.noise = prxpd->nf;
-       stats.qual = prxpd->snr - prxpd->nf;
        /* Marvell rate index has a hole at value 4 */
        if (prxpd->rx_rate > 4)
                --prxpd->rx_rate;
index 7698fdd6a3a23e721550a73215e05d15d1ef04a5..31ca241f775351a7129ff3007c1eea0f6e621b0d 100644 (file)
@@ -23,7 +23,7 @@
 #define MAX_RID_LEN 1024
 
 /* Helper routine to record keys
- * Do not call from interrupt context */
+ * It is called under orinoco_lock so it may not sleep */
 static int orinoco_set_key(struct orinoco_private *priv, int index,
                           enum orinoco_alg alg, const u8 *key, int key_len,
                           const u8 *seq, int seq_len)
@@ -32,14 +32,14 @@ static int orinoco_set_key(struct orinoco_private *priv, int index,
        kzfree(priv->keys[index].seq);
 
        if (key_len) {
-               priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
+               priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC);
                if (!priv->keys[index].key)
                        goto nomem;
        } else
                priv->keys[index].key = NULL;
 
        if (seq_len) {
-               priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
+               priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC);
                if (!priv->keys[index].seq)
                        goto free_key;
        } else
index c5fe867665e6f4feb11c5dbfbb32dba621b81c70..1a7eae357fef937efbc7e65429f763bf6fb83b32 100644 (file)
 #define PAIRWISE_KEY_ENTRY(__idx) \
        ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
 #define MAC_IVEIV_ENTRY(__idx) \
-       ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) )
+       ( MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)) )
 #define MAC_WCID_ATTR_ENTRY(__idx) \
        ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) )
 #define SHARED_KEY_ENTRY(__idx) \
index eb1e1d00bec31455c95a85068c9d959e7abbf45d..27bf887f1453ccc175e253c237abdc5516120965 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/module.h>
 
 #include "rt2x00.h"
-#ifdef CONFIG_RT2800USB
+#if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE)
 #include "rt2x00usb.h"
 #endif
 #include "rt2800lib.h"
@@ -1121,7 +1121,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 
        if (rt2x00_intf_is_usb(rt2x00dev)) {
                rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
-#ifdef CONFIG_RT2800USB
+#if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE)
                rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
                                            USB_MODE_RESET, REGISTER_TIMEOUT);
 #endif
@@ -2021,6 +2021,12 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        unsigned int i;
        u16 eeprom;
 
+       /*
+        * Disable powersaving as default on PCI devices.
+        */
+       if (rt2x00_intf_is_pci(rt2x00dev))
+               rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
        /*
         * Initialize all hw fields.
         */
@@ -2074,8 +2080,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
            IEEE80211_HT_CAP_SGI_20 |
            IEEE80211_HT_CAP_SGI_40 |
            IEEE80211_HT_CAP_TX_STBC |
-           IEEE80211_HT_CAP_RX_STBC |
-           IEEE80211_HT_CAP_PSMP_SUPPORT;
+           IEEE80211_HT_CAP_RX_STBC;
        spec->ht.ampdu_factor = 3;
        spec->ht.ampdu_density = 4;
        spec->ht.mcs.tx_params =
@@ -2140,8 +2145,8 @@ static void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx,
        rt2800_register_multiread(rt2x00dev, offset,
                                      &iveiv_entry, sizeof(iveiv_entry));
 
-       memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16));
-       memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32));
+       memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16));
+       memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32));
 }
 
 static int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
index af85d18cdbe7d96170b686413c4b732f00ab99b1..ab95346cf6a369102043018b2ee917910c44840d 100644 (file)
@@ -922,6 +922,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Logitec */
        { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) },
index 687e17dc2e9f2d7d06a30c6ebfe7b58925764ab8..0ca589306d7172eec437fb5dfcfd088ee0351ff0 100644 (file)
@@ -2538,6 +2538,11 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        char *tx_power;
        unsigned int i;
 
+       /*
+        * Disable powersaving as default.
+        */
+       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
        /*
         * Initialize all hw fields.
         */
index a1a3dd15c66419d63f6e11a5869067585f55575e..8a40a14399842c46b4dc9b845db79ce1141f1718 100644 (file)
@@ -132,7 +132,6 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
 
                        rx_status.antenna = (flags2 >> 15) & 1;
                        /* TODO: improve signal/rssi reporting */
-                       rx_status.qual = flags2 & 0xFF;
                        rx_status.signal = (flags2 >> 8) & 0x7F;
                        /* XXX: is this correct? */
                        rx_status.rate_idx = (flags >> 20) & 0xF;
index 2e733e7bdfd41453f77f3a607e0e7cc2da3bee4c..28a808674080952b73e1615fefcba75d784ef406 100644 (file)
@@ -256,7 +256,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
                }
        }
 
-       if (loop >= INIT_LOOP) {
+       if (loop > INIT_LOOP) {
                wl1251_error("timeout waiting for the hardware to "
                             "complete initialization");
                return -EIO;
index 886a9bc39cc1ddb87bd24d1a4a173c7b798af4f7..c3385b3d246cf988d3efb5d882a5d1c0e877ffd5 100644 (file)
@@ -777,7 +777,7 @@ out:
        return ret;
 }
 
-static int wl1271_build_basic_rates(char *rates, u8 band)
+static int wl1271_build_basic_rates(u8 *rates, u8 band)
 {
        u8 index = 0;
 
@@ -804,7 +804,7 @@ static int wl1271_build_basic_rates(char *rates, u8 band)
        return index;
 }
 
-static int wl1271_build_extended_rates(char *rates, u8 band)
+static int wl1271_build_extended_rates(u8 *rates, u8 band)
 {
        u8 index = 0;
 
index dfa1b9bc22c8f796908c12ef2041501798111d82..7ca95c414fa83d9e6b19e7fccb1b4ee43c7965a6 100644 (file)
@@ -1325,151 +1325,11 @@ int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
        return r;
 }
 
-static int ofdm_qual_db(u8 status_quality, u8 zd_rate, unsigned int size)
-{
-       static const u16 constants[] = {
-               715, 655, 585, 540, 470, 410, 360, 315,
-               270, 235, 205, 175, 150, 125, 105,  85,
-                65,  50,  40,  25,  15
-       };
-
-       int i;
-       u32 x;
-
-       /* It seems that their quality parameter is somehow per signal
-        * and is now transferred per bit.
-        */
-       switch (zd_rate) {
-       case ZD_OFDM_RATE_6M:
-       case ZD_OFDM_RATE_12M:
-       case ZD_OFDM_RATE_24M:
-               size *= 2;
-               break;
-       case ZD_OFDM_RATE_9M:
-       case ZD_OFDM_RATE_18M:
-       case ZD_OFDM_RATE_36M:
-       case ZD_OFDM_RATE_54M:
-               size *= 4;
-               size /= 3;
-               break;
-       case ZD_OFDM_RATE_48M:
-               size *= 3;
-               size /= 2;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       x = (10000 * status_quality)/size;
-       for (i = 0; i < ARRAY_SIZE(constants); i++) {
-               if (x > constants[i])
-                       break;
-       }
-
-       switch (zd_rate) {
-       case ZD_OFDM_RATE_6M:
-       case ZD_OFDM_RATE_9M:
-               i += 3;
-               break;
-       case ZD_OFDM_RATE_12M:
-       case ZD_OFDM_RATE_18M:
-               i += 5;
-               break;
-       case ZD_OFDM_RATE_24M:
-       case ZD_OFDM_RATE_36M:
-               i += 9;
-               break;
-       case ZD_OFDM_RATE_48M:
-       case ZD_OFDM_RATE_54M:
-               i += 15;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return i;
-}
-
-static int ofdm_qual_percent(u8 status_quality, u8 zd_rate, unsigned int size)
-{
-       int r;
-
-       r = ofdm_qual_db(status_quality, zd_rate, size);
-       ZD_ASSERT(r >= 0);
-       if (r < 0)
-               r = 0;
-
-       r = (r * 100)/29;
-       return r <= 100 ? r : 100;
-}
-
-static unsigned int log10times100(unsigned int x)
-{
-       static const u8 log10[] = {
-                 0,
-                 0,   30,   47,   60,   69,   77,   84,   90,   95,  100,
-               104,  107,  111,  114,  117,  120,  123,  125,  127,  130,
-               132,  134,  136,  138,  139,  141,  143,  144,  146,  147,
-               149,  150,  151,  153,  154,  155,  156,  157,  159,  160,
-               161,  162,  163,  164,  165,  166,  167,  168,  169,  169,
-               170,  171,  172,  173,  174,  174,  175,  176,  177,  177,
-               178,  179,  179,  180,  181,  181,  182,  183,  183,  184,
-               185,  185,  186,  186,  187,  188,  188,  189,  189,  190,
-               190,  191,  191,  192,  192,  193,  193,  194,  194,  195,
-               195,  196,  196,  197,  197,  198,  198,  199,  199,  200,
-               200,  200,  201,  201,  202,  202,  202,  203,  203,  204,
-               204,  204,  205,  205,  206,  206,  206,  207,  207,  207,
-               208,  208,  208,  209,  209,  210,  210,  210,  211,  211,
-               211,  212,  212,  212,  213,  213,  213,  213,  214,  214,
-               214,  215,  215,  215,  216,  216,  216,  217,  217,  217,
-               217,  218,  218,  218,  219,  219,  219,  219,  220,  220,
-               220,  220,  221,  221,  221,  222,  222,  222,  222,  223,
-               223,  223,  223,  224,  224,  224,  224,
-       };
-
-       return x < ARRAY_SIZE(log10) ? log10[x] : 225;
-}
-
-enum {
-       MAX_CCK_EVM_DB = 45,
-};
-
-static int cck_evm_db(u8 status_quality)
-{
-       return (20 * log10times100(status_quality)) / 100;
-}
-
-static int cck_snr_db(u8 status_quality)
-{
-       int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality);
-       ZD_ASSERT(r >= 0);
-       return r;
-}
-
-static int cck_qual_percent(u8 status_quality)
-{
-       int r;
-
-       r = cck_snr_db(status_quality);
-       r = (100*r)/17;
-       return r <= 100 ? r : 100;
-}
-
 static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame)
 {
        return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame);
 }
 
-u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
-                     const struct rx_status *status)
-{
-       return (status->frame_status&ZD_RX_OFDM) ?
-               ofdm_qual_percent(status->signal_quality_ofdm,
-                                 zd_rate_from_ofdm_plcp_header(rx_frame),
-                                 size) :
-               cck_qual_percent(status->signal_quality_cck);
-}
-
 /**
  * zd_rx_rate - report zd-rate
  * @rx_frame - received frame
index 9fd8f3508d661a7d1c46027983d6423e4a5c2ae2..f8bbf7d302ae6758b3d98ea69acf3dbeb4ad41e2 100644 (file)
@@ -929,9 +929,6 @@ static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
 
 struct rx_status;
 
-u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
-                      const struct rx_status *status);
-
 u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
 
 struct zd_mc_hash {
index cf51e8f8174bd92dbdd04b70cdc0807bb187e544..8ebf5c33955d791551dd20ac107fca41f75c2b97 100644 (file)
@@ -828,9 +828,6 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
        stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
        stats.band = IEEE80211_BAND_2GHZ;
        stats.signal = status->signal_strength;
-       stats.qual = zd_rx_qual_percent(buffer,
-                                         length - sizeof(struct rx_status),
-                                         status);
 
        rate = zd_rx_rate(buffer, status);
 
index bd588eb8e9225206ec39a7b707aceaaffda879d1..8e210cd76e55c34c617ccabd4c6b752acbd45401 100644 (file)
@@ -121,7 +121,7 @@ struct controller {
 #define PCI_DEVICE_ID_AMD_GOLAM_7450   0x7450
 #define PCI_DEVICE_ID_AMD_POGO_7458    0x7458
 
-/* AMD PCIX bridge registers */
+/* AMD PCI-X bridge registers */
 #define PCIX_MEM_BASE_LIMIT_OFFSET     0x1C
 #define PCIX_MISCII_OFFSET             0x48
 #define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80
index e56f9bed6f2b29d74c1e8e0a910644bc31d5a688..417312528ddff29ab4ead4fd5bc7d89e9a718121 100644 (file)
@@ -305,7 +305,7 @@ struct device_domain_info {
        int segment;            /* PCI domain */
        u8 bus;                 /* PCI bus number */
        u8 devfn;               /* PCI devfn number */
-       struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
+       struct pci_dev *dev; /* it's NULL for PCIe-to-PCI bridge */
        struct intel_iommu *iommu; /* IOMMU used by this device */
        struct dmar_domain *domain; /* pointer to domain */
 };
@@ -1604,7 +1604,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
                        return ret;
                parent = parent->bus->self;
        }
-       if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */
+       if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
                return domain_context_mapping_one(domain,
                                        pci_domain_nr(tmp->subordinate),
                                        tmp->subordinate->number, 0,
@@ -3325,7 +3325,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
                                         parent->devfn);
                        parent = parent->bus->self;
                }
-               if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */
+               if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
                        iommu_detach_dev(iommu,
                                tmp->subordinate->number, 0);
                else /* this is a legacy PCI bridge */
index 8b65a489581b07aa88349a1f37285f03efec6b2b..95b849130ad41189ea2540272ffc84f5407a5bc6 100644 (file)
@@ -528,7 +528,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
 
        bridge = pci_find_upstream_pcie_bridge(dev);
        if (bridge) {
-               if (pci_is_pcie(bridge))/* this is a PCIE-to-PCI/PCIX bridge */
+               if (pci_is_pcie(bridge))/* this is a PCIe-to-PCI/PCIX bridge */
                        set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
                                (bridge->bus->number << 8) | dev->bus->number);
                else /* this is a legacy PCI bridge */
index cc617ddd33d03ce8c16717249ad7413fdd0a0e3e..7e2829538a4cfc5bf03131971930d4463ded11cf 100644 (file)
@@ -112,11 +112,7 @@ static bool acpi_pci_can_wakeup(struct pci_dev *dev)
 static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable)
 {
        while (bus->parent) {
-               struct pci_dev *bridge = bus->self;
-               int ret;
-
-               ret = acpi_pm_device_sleep_wake(&bridge->dev, enable);
-               if (!ret || pci_is_pcie(bridge))
+               if (!acpi_pm_device_sleep_wake(&bus->self->dev, enable))
                        return;
                bus = bus->parent;
        }
@@ -131,9 +127,7 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable)
        if (acpi_pci_can_wakeup(dev))
                return acpi_pm_device_sleep_wake(&dev->dev, enable);
 
-       if (!pci_is_pcie(dev))
-               acpi_pci_propagate_wakeup_enable(dev->bus, enable);
-
+       acpi_pci_propagate_wakeup_enable(dev->bus, enable);
        return 0;
 }
 
index c5df94e866787bb63bf344197edd14a08d7a1398..807224ec8351f819250f6b9c1a3caff97c3275e6 100644 (file)
@@ -75,7 +75,8 @@ static ssize_t local_cpus_show(struct device *dev,
        int len;
 
 #ifdef CONFIG_NUMA
-       mask = cpumask_of_node(dev_to_node(dev));
+       mask = (dev_to_node(dev) == -1) ? cpu_online_mask :
+                                         cpumask_of_node(dev_to_node(dev));
 #else
        mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
 #endif
@@ -93,7 +94,8 @@ static ssize_t local_cpulist_show(struct device *dev,
        int len;
 
 #ifdef CONFIG_NUMA
-       mask = cpumask_of_node(dev_to_node(dev));
+       mask = (dev_to_node(dev) == -1) ? cpu_online_mask :
+                                         cpumask_of_node(dev_to_node(dev));
 #else
        mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
 #endif
index 0bc27e0590196484b7733c1e0dbb049e4571cda5..315fea47e7843956772514a25a64afae736cd38e 100644 (file)
@@ -29,7 +29,17 @@ const char *pci_power_names[] = {
 };
 EXPORT_SYMBOL_GPL(pci_power_names);
 
-unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT;
+unsigned int pci_pm_d3_delay;
+
+static void pci_dev_d3_sleep(struct pci_dev *dev)
+{
+       unsigned int delay = dev->d3_delay;
+
+       if (delay < pci_pm_d3_delay)
+               delay = pci_pm_d3_delay;
+
+       msleep(delay);
+}
 
 #ifdef CONFIG_PCI_DOMAINS
 int pci_domains_supported = 1;
@@ -522,7 +532,7 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
        /* Mandatory power management transition delays */
        /* see PCI PM 1.1 5.6.1 table 18 */
        if (state == PCI_D3hot || dev->current_state == PCI_D3hot)
-               msleep(pci_pm_d3_delay);
+               pci_dev_d3_sleep(dev);
        else if (state == PCI_D2 || dev->current_state == PCI_D2)
                udelay(PCI_PM_D2_DELAY);
 
@@ -1153,11 +1163,11 @@ pci_disable_device(struct pci_dev *dev)
 
 /**
  * pcibios_set_pcie_reset_state - set reset state for device dev
- * @dev: the PCI-E device reset
+ * @dev: the PCIe device reset
  * @state: Reset state to enter into
  *
  *
- * Sets the PCI-E reset state for the device. This is the default
+ * Sets the PCIe reset state for the device. This is the default
  * implementation. Architecture implementations can override this.
  */
 int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev,
@@ -1168,7 +1178,7 @@ int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev,
 
 /**
  * pci_set_pcie_reset_state - set reset state for device dev
- * @dev: the PCI-E device reset
+ * @dev: the PCIe device reset
  * @state: Reset state to enter into
  *
  *
@@ -1409,6 +1419,7 @@ void pci_pm_init(struct pci_dev *dev)
        }
 
        dev->pm_cap = pm;
+       dev->d3_delay = PCI_PM_D3_WAIT;
 
        dev->d1_support = false;
        dev->d2_support = false;
@@ -2247,12 +2258,12 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
        csr &= ~PCI_PM_CTRL_STATE_MASK;
        csr |= PCI_D3hot;
        pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr);
-       msleep(pci_pm_d3_delay);
+       pci_dev_d3_sleep(dev);
 
        csr &= ~PCI_PM_CTRL_STATE_MASK;
        csr |= PCI_D0;
        pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr);
-       msleep(pci_pm_d3_delay);
+       pci_dev_d3_sleep(dev);
 
        return 0;
 }
@@ -2296,6 +2307,10 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
                down(&dev->dev.sem);
        }
 
+       rc = pci_dev_specific_reset(dev, probe);
+       if (rc != -ENOTTY)
+               goto done;
+
        rc = pcie_flr(dev, probe);
        if (rc != -ENOTTY)
                goto done;
@@ -2779,6 +2794,11 @@ int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev)
        return 1;
 }
 
+void __weak pci_fixup_cardbus(struct pci_bus *bus)
+{
+}
+EXPORT_SYMBOL(pci_fixup_cardbus);
+
 static int __init pci_setup(char *str)
 {
        while (str) {
index 33ed8e0aba1ea25b54c928691e1a03c78b1391f8..fbd0e3adbca3cf58c9995a5f46cf41a51f4d4df5 100644 (file)
@@ -313,4 +313,12 @@ static inline int pci_resource_alignment(struct pci_dev *dev,
 
 extern void pci_enable_acs(struct pci_dev *dev);
 
+struct pci_dev_reset_methods {
+       u16 vendor;
+       u16 device;
+       int (*reset)(struct pci_dev *dev, int probe);
+};
+
+extern int pci_dev_specific_reset(struct pci_dev *dev, int probe);
+
 #endif /* DRIVERS_PCI_H */
index b8c925c1f6aa8ad97331d640e2f95bfcc929e13f..9142949734f541630a7cb7a4512be15f6986f0fc 100644 (file)
@@ -3,14 +3,14 @@
 #
 
 config PCIEAER_INJECT
-       tristate "PCIE AER error injector support"
+       tristate "PCIe AER error injector support"
        depends on PCIEAER
        default n
        help
          This enables PCI Express Root Port Advanced Error Reporting
          (AER) software error injector.
 
-         Debuging PCIE AER code is quite difficult because it is hard
+         Debugging PCIe AER code is quite difficult because it is hard
          to trigger various real hardware errors. Software based
          error injection can fake almost all kinds of errors with the
          help of a user space helper tool aer-inject, which can be
index 7fcd5331b14c37fdbbe4662e80afdf393191dcb8..8c30a9544d61f07176fbf69a59b84c2afabf9e8a 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * PCIE AER software error injection support.
+ * PCIe AER software error injection support.
  *
- * Debuging PCIE AER code is quite difficult because it is hard to
+ * Debuging PCIe AER code is quite difficult because it is hard to
  * trigger various real hardware errors. Software based error
  * injection can fake almost all kinds of errors with the help of a
  * user space helper tool aer-inject, which can be gotten from:
@@ -321,7 +321,7 @@ static int aer_inject(struct aer_error_inj *einj)
        unsigned long flags;
        unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn);
        int pos_cap_err, rp_pos_cap_err;
-       u32 sever;
+       u32 sever, mask;
        int ret = 0;
 
        dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
@@ -374,6 +374,24 @@ static int aer_inject(struct aer_error_inj *einj)
        err->header_log2 = einj->header_log2;
        err->header_log3 = einj->header_log3;
 
+       pci_read_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK, &mask);
+       if (einj->cor_status && !(einj->cor_status & ~mask)) {
+               ret = -EINVAL;
+               printk(KERN_WARNING "The correctable error(s) is masked "
+                               "by device\n");
+               spin_unlock_irqrestore(&inject_lock, flags);
+               goto out_put;
+       }
+
+       pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK, &mask);
+       if (einj->uncor_status && !(einj->uncor_status & ~mask)) {
+               ret = -EINVAL;
+               printk(KERN_WARNING "The uncorrectable error(s) is masked "
+                               "by device\n");
+               spin_unlock_irqrestore(&inject_lock, flags);
+               goto out_put;
+       }
+
        rperr = __find_aer_error_by_dev(rpdev);
        if (!rperr) {
                rperr = rperr_alloc;
@@ -413,8 +431,14 @@ static int aer_inject(struct aer_error_inj *einj)
        if (ret)
                goto out_put;
 
-       if (find_aer_device(rpdev, &edev))
+       if (find_aer_device(rpdev, &edev)) {
+               if (!get_service_data(edev)) {
+                       printk(KERN_WARNING "AER service is not initialized\n");
+                       ret = -EINVAL;
+                       goto out_put;
+               }
                aer_irq(-1, edev);
+       }
        else
                ret = -EINVAL;
 out_put:
@@ -484,5 +508,5 @@ static void __exit aer_inject_exit(void)
 module_init(aer_inject_init);
 module_exit(aer_inject_exit);
 
-MODULE_DESCRIPTION("PCIE AER software error injector");
+MODULE_DESCRIPTION("PCIe AER software error injector");
 MODULE_LICENSE("GPL");
index 97a345927b55644e1798095d385ff6104abb3499..21f215f4daa30cc090424ee25f4b24bb90d27115 100644 (file)
@@ -155,7 +155,7 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
        mutex_init(&rpc->rpc_mutex);
        init_waitqueue_head(&rpc->wait_release);
 
-       /* Use PCIE bus function to store rpc into PCIE device */
+       /* Use PCIe bus function to store rpc into PCIe device */
        set_service_data(dev, rpc);
 
        return rpc;
index 8edb2f300e8f85cc91c31ad8f6c208b6363cb118..04814087658d32a27ed6cd5dc8571b2ee077e59f 100644 (file)
@@ -24,7 +24,7 @@
  *
  * @return: Zero on success. Nonzero otherwise.
  *
- * Invoked when PCIE bus loads AER service driver. To avoid conflict with
+ * Invoked when PCIe bus loads AER service driver. To avoid conflict with
  * BIOS AER support requires BIOS to yield AER control to OS native driver.
  **/
 int aer_osc_setup(struct pcie_device *pciedev)
index ae672ca803331f6c70ad12422110b5079a2090c2..c843a799814d28fde6e8a4832edf986ccde977f0 100644 (file)
@@ -587,7 +587,7 @@ static void handle_error_source(struct pcie_device *aerdev,
  * aer_enable_rootport - enable Root Port's interrupts when receiving messages
  * @rpc: pointer to a Root Port data structure
  *
- * Invoked when PCIE bus loads AER service driver.
+ * Invoked when PCIe bus loads AER service driver.
  */
 void aer_enable_rootport(struct aer_rpc *rpc)
 {
@@ -597,7 +597,7 @@ void aer_enable_rootport(struct aer_rpc *rpc)
        u32 reg32;
 
        pos = pci_pcie_cap(pdev);
-       /* Clear PCIE Capability's Device Status */
+       /* Clear PCIe Capability's Device Status */
        pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16);
        pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16);
 
@@ -631,7 +631,7 @@ void aer_enable_rootport(struct aer_rpc *rpc)
  * disable_root_aer - disable Root Port's interrupts when receiving messages
  * @rpc: pointer to a Root Port data structure
  *
- * Invoked when PCIE bus unloads AER service driver.
+ * Invoked when PCIe bus unloads AER service driver.
  */
 static void disable_root_aer(struct aer_rpc *rpc)
 {
index 44acde72294f80210136f808135efeed76a128fe..9d3e4c8d0184202ce58177d88b2d6ac9454c20d2 100644 (file)
@@ -184,7 +184,7 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
 
        if (info->status == 0) {
                AER_PR(info, dev,
-                       "PCIE Bus Error: severity=%s, type=Unaccessible, "
+                       "PCIe Bus Error: severity=%s, type=Unaccessible, "
                        "id=%04x(Unregistered Agent ID)\n",
                        aer_error_severity_string[info->severity], id);
        } else {
@@ -194,7 +194,7 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
                agent = AER_GET_AGENT(info->severity, info->status);
 
                AER_PR(info, dev,
-                       "PCIE Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
+                       "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
                        aer_error_severity_string[info->severity],
                        aer_error_layer[layer], id, aer_agent_string[agent]);
 
index 5a01fc7fbf056371e6a1e90c874060cec486c221..be53d98fa38466992e762ca029d7c32007998d88 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * File:       drivers/pci/pcie/aspm.c
- * Enabling PCIE link L0s/L1 state and Clock Power Management
+ * Enabling PCIe link L0s/L1 state and Clock Power Management
  *
  * Copyright (C) 2007 Intel
  * Copyright (C) Zhang Yanmin (yanmin.zhang@intel.com)
@@ -499,7 +499,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
        int pos;
        u32 reg32;
        /*
-        * Some functions in a slot might not all be PCIE functions,
+        * Some functions in a slot might not all be PCIe functions,
         * very strange. Disable ASPM for the whole slot
         */
        list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
index 413262eb95b7607be682ac374bbcd7f9e00fc682..b174188ac1212e4f128190c9a8ee78c3b1ef9962 100644 (file)
@@ -27,7 +27,7 @@
  */
 static void release_pcie_device(struct device *dev)
 {
-       kfree(to_pcie_device(dev));                     
+       kfree(to_pcie_device(dev));
 }
 
 /**
@@ -346,12 +346,11 @@ static int suspend_iter(struct device *dev, void *data)
 {
        struct pcie_port_service_driver *service_driver;
 
-       if ((dev->bus == &pcie_port_bus_type) &&
-           (dev->driver)) {
-               service_driver = to_service_driver(dev->driver);
-               if (service_driver->suspend)
-                       service_driver->suspend(to_pcie_device(dev));
-       }
+       if ((dev->bus == &pcie_port_bus_type) && dev->driver) {
+               service_driver = to_service_driver(dev->driver);
+               if (service_driver->suspend)
+                       service_driver->suspend(to_pcie_device(dev));
+       }
        return 0;
 }
 
@@ -494,6 +493,7 @@ int pcie_port_service_register(struct pcie_port_service_driver *new)
 
        return driver_register(&new->driver);
 }
+EXPORT_SYMBOL(pcie_port_service_register);
 
 /**
  * pcie_port_service_unregister - unregister PCI Express port service driver
@@ -503,6 +503,4 @@ void pcie_port_service_unregister(struct pcie_port_service_driver *drv)
 {
        driver_unregister(&drv->driver);
 }
-
-EXPORT_SYMBOL(pcie_port_service_register);
 EXPORT_SYMBOL(pcie_port_service_unregister);
index a49452e2aed9e932d82cd51a9570aaaf3f61c903..13c8972886e6e788cf47916507376e5138c1c195 100644 (file)
@@ -24,7 +24,7 @@
  */
 #define DRIVER_VERSION "v1.0"
 #define DRIVER_AUTHOR "tom.l.nguyen@intel.com"
-#define DRIVER_DESC "PCIE Port Bus Driver"
+#define DRIVER_DESC "PCIe Port Bus Driver"
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
@@ -63,7 +63,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
  * pcie_portdrv_probe - Probe PCI-Express port devices
  * @dev: PCI-Express port device being probed
  *
- * If detected invokes the pcie_port_device_register() method for 
+ * If detected invokes the pcie_port_device_register() method for
  * this port device.
  *
  */
@@ -78,7 +78,7 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
             (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
                return -ENODEV;
 
-        if (!dev->irq && dev->pin) {
+       if (!dev->irq && dev->pin) {
                dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
                         "check vendor BIOS\n", dev->vendor, dev->device);
        }
@@ -91,7 +91,7 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
        return 0;
 }
 
-static void pcie_portdrv_remove (struct pci_dev *dev)
+static void pcie_portdrv_remove(struct pci_dev *dev)
 {
        pcie_port_device_remove(dev);
        pci_disable_device(dev);
@@ -129,14 +129,13 @@ static int error_detected_iter(struct device *device, void *data)
 static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
                                        enum pci_channel_state error)
 {
-       struct aer_broadcast_data result_data =
-                       {error, PCI_ERS_RESULT_CAN_RECOVER};
-       int retval;
+       struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER};
+       int ret;
 
        /* can not fail */
-       retval = device_for_each_child(&dev->dev, &result_data, error_detected_iter);
+       ret = device_for_each_child(&dev->dev, &data, error_detected_iter);
 
-       return result_data.result;
+       return data.result;
 }
 
 static int mmio_enabled_iter(struct device *device, void *data)
@@ -290,7 +289,7 @@ static int __init pcie_portdrv_init(void)
        return retval;
 }
 
-static void __exit pcie_portdrv_exit(void) 
+static void __exit pcie_portdrv_exit(void)
 {
        pci_unregister_driver(&pcie_portdriver);
        pcie_port_bus_unregister();
index 7cfa7c38d31869bd482138fa2fc3fcba06d561e7..c74694345b6ea6321fe643c2720c86812220f363 100644 (file)
@@ -2629,14 +2629,86 @@ static int __init pci_apply_final_quirks(void)
        if (!pci_cache_line_size) {
                printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n",
                       cls << 2, pci_dfl_cache_line_size << 2);
-               pci_cache_line_size = cls;
+               pci_cache_line_size = cls ? cls : pci_dfl_cache_line_size;
        }
 
        return 0;
 }
 
 fs_initcall_sync(pci_apply_final_quirks);
+
+/*
+ * Followings are device-specific reset methods which can be used to
+ * reset a single function if other methods (e.g. FLR, PM D0->D3) are
+ * not available.
+ */
+static int reset_intel_generic_dev(struct pci_dev *dev, int probe)
+{
+       int pos;
+
+       /* only implement PCI_CLASS_SERIAL_USB at present */
+       if (dev->class == PCI_CLASS_SERIAL_USB) {
+               pos = pci_find_capability(dev, PCI_CAP_ID_VNDR);
+               if (!pos)
+                       return -ENOTTY;
+
+               if (probe)
+                       return 0;
+
+               pci_write_config_byte(dev, pos + 0x4, 1);
+               msleep(100);
+
+               return 0;
+       } else {
+               return -ENOTTY;
+       }
+}
+
+static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
+{
+       int pos;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!pos)
+               return -ENOTTY;
+
+       if (probe)
+               return 0;
+
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
+                               PCI_EXP_DEVCTL_BCR_FLR);
+       msleep(100);
+
+       return 0;
+}
+
+#define PCI_DEVICE_ID_INTEL_82599_SFP_VF   0x10ed
+
+static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
+                reset_intel_82599_sfp_virtfn },
+       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
+               reset_intel_generic_dev },
+       { 0 }
+};
+
+int pci_dev_specific_reset(struct pci_dev *dev, int probe)
+{
+       const struct pci_dev_reset_methods *i;
+
+       for (i = pci_dev_reset_methods; i->reset; i++) {
+               if ((i->vendor == dev->vendor ||
+                    i->vendor == (u16)PCI_ANY_ID) &&
+                   (i->device == dev->device ||
+                    i->device == (u16)PCI_ANY_ID))
+                       return i->reset(dev, probe);
+       }
+
+       return -ENOTTY;
+}
+
 #else
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {}
+int pci_dev_specific_reset(struct pci_dev *dev, int probe) { return -ENOTTY; }
 #endif
 EXPORT_SYMBOL(pci_fixup_device);
index 6dae871432588e29f93b86e7a2565856cc36ab99..4a471dc4f4b9c6167a11de5d8041df65aa371fc1 100644 (file)
@@ -15,9 +15,9 @@
 
 DECLARE_RWSEM(pci_bus_sem);
 /*
- * find the upstream PCIE-to-PCI bridge of a PCI device
+ * find the upstream PCIe-to-PCI bridge of a PCI device
  * if the device is PCIE, return NULL
- * if the device isn't connected to a PCIE bridge (that is its parent is a
+ * if the device isn't connected to a PCIe bridge (that is its parent is a
  * legacy PCI bridge and the bridge is directly connected to bus 0), return its
  * parent
  */
@@ -37,7 +37,7 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
                        tmp = pdev;
                        continue;
                }
-               /* PCI device should connect to a PCIE bridge */
+               /* PCI device should connect to a PCIe bridge */
                if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) {
                        /* Busted hardware? */
                        WARN_ON_ONCE(1);
index cdf50f3bc2df389af234ed8976017ba5c717e218..d99f846451a3ecbba1d2608c6bd828696c9c15a7 100644 (file)
@@ -222,7 +222,7 @@ int __ref cb_alloc(struct pcmcia_socket *s)
        unsigned int max, pass;
 
        s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
-/*     pcibios_fixup_bus(bus); */
+       pci_fixup_cardbus(bus); 
 
        max = bus->secondary;
        for (pass = 0; pass < 2; pass++)
index ec4faffe6b0587da92c620e7f5d291c373d02fdf..db32c25e360591c7dd232e6463ca00d3001e00ae 100644 (file)
@@ -231,8 +231,36 @@ config THINKPAD_ACPI
 
          This driver was formerly known as ibm-acpi.
 
+         Extra functionality will be available if the rfkill (CONFIG_RFKILL)
+         and/or ALSA (CONFIG_SND) subsystems are available in the kernel.
+         Note that if you want ThinkPad-ACPI to be built-in instead of
+         modular, ALSA and rfkill will also have to be built-in.
+
          If you have an IBM or Lenovo ThinkPad laptop, say Y or M here.
 
+config THINKPAD_ACPI_ALSA_SUPPORT
+       bool "Console audio control ALSA interface"
+       depends on THINKPAD_ACPI
+       depends on SND
+       depends on SND = y || THINKPAD_ACPI = SND
+       default y
+       ---help---
+         Enables monitoring of the built-in console audio output control
+         (headphone and speakers), which is operated by the mute and (in
+         some ThinkPad models) volume hotkeys.
+
+         If this option is enabled, ThinkPad-ACPI will export an ALSA card
+         with a single read-only mixer control, which should be used for
+         on-screen-display feedback purposes by the Desktop Environment.
+
+         Optionally, the driver will also allow software control (the
+         ALSA mixer will be made read-write).  Please refer to the driver
+         documentation for details.
+
+         All IBM models have both volume and mute control.  Newer Lenovo
+         models only have mute control (the volume hotkeys are just normal
+         keys and volume control is done through the main HDA mixer).
+
 config THINKPAD_ACPI_DEBUGFACILITIES
        bool "Maintainer debug facilities"
        depends on THINKPAD_ACPI
index 916ccb2b316c5b87c92d576a5bb6906f49891082..1b1dddbd5744e85d0a1123ac27d0a7379190eb13 100644 (file)
@@ -202,8 +202,13 @@ static void dell_wmi_notify(u32 value, void *context)
        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
        static struct key_entry *key;
        union acpi_object *obj;
+       acpi_status status;
 
-       wmi_get_event_data(value, &response);
+       status = wmi_get_event_data(value, &response);
+       if (status != AE_OK) {
+               printk(KERN_INFO "dell-wmi: bad event status 0x%x\n", status);
+               return;
+       }
 
        obj = (union acpi_object *)response.pointer;
 
@@ -323,8 +328,9 @@ static int __init dell_wmi_input_setup(void)
 static int __init dell_wmi_init(void)
 {
        int err;
+       acpi_status status;
 
-       if (wmi_has_guid(DELL_EVENT_GUID)) {
+       if (!wmi_has_guid(DELL_EVENT_GUID)) {
                printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n");
                return -ENODEV;
        }
@@ -336,14 +342,14 @@ static int __init dell_wmi_init(void)
        if (err)
                return err;
 
-       err = wmi_install_notify_handler(DELL_EVENT_GUID,
+       status = wmi_install_notify_handler(DELL_EVENT_GUID,
                                         dell_wmi_notify, NULL);
-       if (err) {
+       if (ACPI_FAILURE(status)) {
                input_unregister_device(dell_wmi_input_dev);
                printk(KERN_ERR
                        "dell-wmi: Unable to register notify handler - %d\n",
-                       err);
-               return err;
+                       status);
+               return -ENODEV;
        }
 
        return 0;
index 8781d8fa7a579b609bd2d4999c9eadb94c79e405..ad4c414dbfbcd1e056fa26c7010fb03d975edf87 100644 (file)
@@ -338,8 +338,13 @@ static void hp_wmi_notify(u32 value, void *context)
        static struct key_entry *key;
        union acpi_object *obj;
        int eventcode;
+       acpi_status status;
 
-       wmi_get_event_data(value, &response);
+       status = wmi_get_event_data(value, &response);
+       if (status != AE_OK) {
+               printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status);
+               return;
+       }
 
        obj = (union acpi_object *)response.pointer;
 
@@ -388,8 +393,6 @@ static void hp_wmi_notify(u32 value, void *context)
        } else
                printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
                        eventcode);
-
-       kfree(obj);
 }
 
 static int __init hp_wmi_input_setup(void)
@@ -581,7 +584,7 @@ static int __init hp_wmi_init(void)
        if (wmi_has_guid(HPWMI_EVENT_GUID)) {
                err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
                                                 hp_wmi_notify, NULL);
-               if (!err)
+               if (ACPI_SUCCESS(err))
                        hp_wmi_input_setup();
        }
 
index 7f77f908bb01c95d104342848dad3872f5a2fdcb..f5f70d4c6913bf373af4a052e6618c3077bee85d 100644 (file)
@@ -149,8 +149,13 @@ static void msi_wmi_notify(u32 value, void *context)
        static struct key_entry *key;
        union acpi_object *obj;
        ktime_t cur;
+       acpi_status status;
 
-       wmi_get_event_data(value, &response);
+       status = wmi_get_event_data(value, &response);
+       if (status != AE_OK) {
+               printk(KERN_INFO DRV_PFX "bad event status 0x%x\n", status);
+               return;
+       }
 
        obj = (union acpi_object *)response.pointer;
 
@@ -236,7 +241,7 @@ static int __init msi_wmi_init(void)
        }
        err = wmi_install_notify_handler(MSIWMI_EVENT_GUID,
                        msi_wmi_notify, NULL);
-       if (err)
+       if (ACPI_FAILURE(err))
                return -EINVAL;
 
        err = msi_wmi_input_setup();
index 448c8aeb166b1e25561be66b98649c6de4042637..e67e4feb35cb814f85ad2df10bc1836c00cc79b6 100644 (file)
@@ -6384,11 +6384,13 @@ static struct ibm_struct brightness_driver_data = {
  * and we leave them unchanged.
  */
 
+#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT
+
 #define TPACPI_ALSA_DRVNAME  "ThinkPad EC"
 #define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control"
 #define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME
 
-static int alsa_index = SNDRV_DEFAULT_IDX1;
+static int alsa_index = ~((1 << (SNDRV_CARDS - 3)) - 1); /* last three slots */
 static char *alsa_id = "ThinkPadEC";
 static int alsa_enable = SNDRV_DEFAULT_ENABLE1;
 
@@ -6705,10 +6707,11 @@ static int __init volume_create_alsa_mixer(void)
 
        rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE,
                            sizeof(struct tpacpi_alsa_data), &card);
-       if (rc < 0)
-               return rc;
-       if (!card)
-               return -ENOMEM;
+       if (rc < 0 || !card) {
+               printk(TPACPI_ERR
+                       "Failed to create ALSA card structures: %d\n", rc);
+               return 1;
+       }
 
        BUG_ON(!card->private_data);
        data = card->private_data;
@@ -6741,8 +6744,9 @@ static int __init volume_create_alsa_mixer(void)
                rc = snd_ctl_add(card, ctl_vol);
                if (rc < 0) {
                        printk(TPACPI_ERR
-                               "Failed to create ALSA volume control\n");
-                       goto err_out;
+                               "Failed to create ALSA volume control: %d\n",
+                               rc);
+                       goto err_exit;
                }
                data->ctl_vol_id = &ctl_vol->id;
        }
@@ -6750,22 +6754,25 @@ static int __init volume_create_alsa_mixer(void)
        ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL);
        rc = snd_ctl_add(card, ctl_mute);
        if (rc < 0) {
-               printk(TPACPI_ERR "Failed to create ALSA mute control\n");
-               goto err_out;
+               printk(TPACPI_ERR "Failed to create ALSA mute control: %d\n",
+                       rc);
+               goto err_exit;
        }
        data->ctl_mute_id = &ctl_mute->id;
 
        snd_card_set_dev(card, &tpacpi_pdev->dev);
        rc = snd_card_register(card);
-
-err_out:
        if (rc < 0) {
-               snd_card_free(card);
-               card = NULL;
+               printk(TPACPI_ERR "Failed to register ALSA card: %d\n", rc);
+               goto err_exit;
        }
 
        alsa_card = card;
-       return rc;
+       return 0;
+
+err_exit:
+       snd_card_free(card);
+       return 1;
 }
 
 #define TPACPI_VOL_Q_MUTEONLY  0x0001  /* Mute-only control available */
@@ -7016,6 +7023,28 @@ static struct ibm_struct volume_driver_data = {
        .shutdown = volume_shutdown,
 };
 
+#else /* !CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */
+
+#define alsa_card NULL
+
+static void inline volume_alsa_notify_change(void)
+{
+}
+
+static int __init volume_init(struct ibm_init_struct *iibm)
+{
+       printk(TPACPI_INFO
+               "volume: disabled as there is no ALSA support in this kernel\n");
+
+       return 1;
+}
+
+static struct ibm_struct volume_driver_data = {
+       .name = "volume",
+};
+
+#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */
+
 /*************************************************************************
  * Fan subdriver
  */
@@ -8738,6 +8767,7 @@ MODULE_PARM_DESC(hotkey_report_mode,
                 "used for backwards compatibility with userspace, "
                 "see documentation");
 
+#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT
 module_param_named(volume_mode, volume_mode, uint, 0444);
 MODULE_PARM_DESC(volume_mode,
                 "Selects volume control strategy: "
@@ -8760,6 +8790,7 @@ module_param_named(id, alsa_id, charp, 0444);
 MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer");
 module_param_named(enable, alsa_enable, bool, 0444);
 MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer");
+#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */
 
 #define TPACPI_PARAM(feature) \
        module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
index 9f93d6c0f510d88a9e662caa917e92df4a4ed39f..b104302fea0a1e9dbc4a91f82290a185ad244e00 100644 (file)
@@ -492,8 +492,7 @@ wmi_notify_handler handler, void *data)
        if (!guid || !handler)
                return AE_BAD_PARAMETER;
 
-       find_guid(guid, &block);
-       if (!block)
+       if (!find_guid(guid, &block))
                return AE_NOT_EXIST;
 
        if (block->handler)
@@ -521,8 +520,7 @@ acpi_status wmi_remove_notify_handler(const char *guid)
        if (!guid)
                return AE_BAD_PARAMETER;
 
-       find_guid(guid, &block);
-       if (!block)
+       if (!find_guid(guid, &block))
                return AE_NOT_EXIST;
 
        if (!block->handler)
@@ -716,6 +714,22 @@ static int wmi_class_init(void)
        return ret;
 }
 
+static bool guid_already_parsed(const char *guid_string)
+{
+       struct guid_block *gblock;
+       struct wmi_block *wblock;
+       struct list_head *p;
+
+       list_for_each(p, &wmi_blocks.list) {
+               wblock = list_entry(p, struct wmi_block, list);
+               gblock = &wblock->gblock;
+
+               if (strncmp(gblock->guid, guid_string, 16) == 0)
+                       return true;
+       }
+       return false;
+}
+
 /*
  * Parse the _WDG method for the GUID data blocks
  */
@@ -725,6 +739,7 @@ static __init acpi_status parse_wdg(acpi_handle handle)
        union acpi_object *obj;
        struct guid_block *gblock;
        struct wmi_block *wblock;
+       char guid_string[37];
        acpi_status status;
        u32 i, total;
 
@@ -747,6 +762,19 @@ static __init acpi_status parse_wdg(acpi_handle handle)
        memcpy(gblock, obj->buffer.pointer, obj->buffer.length);
 
        for (i = 0; i < total; i++) {
+               /*
+                 Some WMI devices, like those for nVidia hooks, have a
+                 duplicate GUID. It's not clear what we should do in this
+                 case yet, so for now, we'll just ignore the duplicate.
+                 Anyone who wants to add support for that device can come
+                 up with a better workaround for the mess then.
+               */
+               if (guid_already_parsed(gblock[i].guid) == true) {
+                       wmi_gtoa(gblock[i].guid, guid_string);
+                       printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n",
+                               guid_string);
+                       continue;
+               }
                wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
                if (!wblock)
                        return AE_NO_MEMORY;
index c8c12325e69b9feef3e7a5918fd59ef99fea8192..e9aa814ddd23909cfa78c3769b8b5ab2a785f2ea 100644 (file)
@@ -1096,9 +1096,9 @@ static int cmos_pnp_resume(struct pnp_dev *pnp)
 #define        cmos_pnp_resume         NULL
 #endif
 
-static void cmos_pnp_shutdown(struct device *pdev)
+static void cmos_pnp_shutdown(struct pnp_dev *pnp)
 {
-       if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev))
+       if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev))
                return;
 
        cmos_do_shutdown();
@@ -1117,15 +1117,12 @@ static struct pnp_driver cmos_pnp_driver = {
        .id_table       = rtc_ids,
        .probe          = cmos_pnp_probe,
        .remove         = __exit_p(cmos_pnp_remove),
+       .shutdown       = cmos_pnp_shutdown,
 
        /* flag ensures resume() gets called, and stops syslog spam */
        .flags          = PNP_DRIVER_RES_DO_NOT_CHANGE,
        .suspend        = cmos_pnp_suspend,
        .resume         = cmos_pnp_resume,
-       .driver         = {
-               .name     = (char *)driver_name,
-               .shutdown = cmos_pnp_shutdown,
-       }
 };
 
 #endif /* CONFIG_PNP */
index d033414f75997e53f22343c1d47e426e5c23fd1d..e1b700a19648c87ffefa5cb455541503295d9788 100644 (file)
@@ -10,5 +10,5 @@ obj-y += ccw_device.o cmf.o
 obj-$(CONFIG_CHSC_SCH) += chsc_sch.o
 obj-$(CONFIG_CCWGROUP) += ccwgroup.o
 
-qdio-objs := qdio_main.o qdio_thinint.o qdio_debug.o qdio_perf.o qdio_setup.o
+qdio-objs := qdio_main.o qdio_thinint.o qdio_debug.o qdio_setup.o
 obj-$(CONFIG_QDIO) += qdio.o
index ff7748a9199d7a91f49330e2ea8f893638df9252..44f2f6a97f33afeee0326a1e502c934313253209 100644 (file)
@@ -182,6 +182,34 @@ struct scssc_area {
        u32:32;
 } __attribute__ ((packed));
 
+struct qdio_dev_perf_stat {
+       unsigned int adapter_int;
+       unsigned int qdio_int;
+       unsigned int pci_request_int;
+
+       unsigned int tasklet_inbound;
+       unsigned int tasklet_inbound_resched;
+       unsigned int tasklet_inbound_resched2;
+       unsigned int tasklet_outbound;
+
+       unsigned int siga_read;
+       unsigned int siga_write;
+       unsigned int siga_sync;
+
+       unsigned int inbound_call;
+       unsigned int inbound_handler;
+       unsigned int stop_polling;
+       unsigned int inbound_queue_full;
+       unsigned int outbound_call;
+       unsigned int outbound_handler;
+       unsigned int fast_requeue;
+       unsigned int target_full;
+       unsigned int eqbs;
+       unsigned int eqbs_partial;
+       unsigned int sqbs;
+       unsigned int sqbs_partial;
+};
+
 struct qdio_input_q {
        /* input buffer acknowledgement flag */
        int polling;
@@ -269,6 +297,7 @@ struct qdio_irq {
        u32 *dsci;              /* address of device state change indicator */
        struct ccw_device *cdev;
        struct dentry *debugfs_dev;
+       struct dentry *debugfs_perf;
 
        unsigned long int_parm;
        struct subchannel_id schid;
@@ -286,9 +315,10 @@ struct qdio_irq {
        struct ciw aqueue;
 
        struct qdio_ssqd_desc ssqd_desc;
-
        void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
 
+       struct qdio_dev_perf_stat perf_stat;
+       int perf_stat_enabled;
        /*
         * Warning: Leave these members together at the end so they won't be
         * cleared in qdio_setup_irq.
@@ -311,6 +341,10 @@ struct qdio_irq {
        (irq->qib.qfmt == QDIO_IQDIO_QFMT || \
         css_general_characteristics.aif_osa)
 
+#define qperf(qdev,attr)       qdev->perf_stat.attr
+#define qperf_inc(q,attr)      if (q->irq_ptr->perf_stat_enabled) \
+                                       q->irq_ptr->perf_stat.attr++
+
 /* the highest iqdio queue is used for multicast */
 static inline int multicast_outbound(struct qdio_q *q)
 {
index 76769978285f0cd28a15eb2004b633bce16a6418..f49761ff9a00a648b5f70e5500c7efb70cac6277 100644 (file)
@@ -55,13 +55,11 @@ static int qstat_show(struct seq_file *m, void *v)
        if (!q)
                return 0;
 
-       seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci);
-       seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used));
-       seq_printf(m, "ftc: %d\n", q->first_to_check);
-       seq_printf(m, "last_move: %d\n", q->last_move);
-       seq_printf(m, "polling: %d\n", q->u.in.polling);
-       seq_printf(m, "ack start: %d\n", q->u.in.ack_start);
-       seq_printf(m, "ack count: %d\n", q->u.in.ack_count);
+       seq_printf(m, "DSCI: %d   nr_used: %d\n",
+                  *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
+       seq_printf(m, "ftc: %d  last_move: %d\n", q->first_to_check, q->last_move);
+       seq_printf(m, "polling: %d  ack start: %d  ack count: %d\n",
+                  q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count);
        seq_printf(m, "slsb buffer states:\n");
        seq_printf(m, "|0      |8      |16     |24     |32     |40     |48     |56  63|\n");
 
@@ -110,7 +108,6 @@ static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
 
        if (!q)
                return 0;
-
        if (q->is_input_q)
                xchg(q->irq_ptr->dsci, 1);
        local_bh_disable();
@@ -134,6 +131,98 @@ static const struct file_operations debugfs_fops = {
        .release = single_release,
 };
 
+static char *qperf_names[] = {
+       "Assumed adapter interrupts",
+       "QDIO interrupts",
+       "Requested PCIs",
+       "Inbound tasklet runs",
+       "Inbound tasklet resched",
+       "Inbound tasklet resched2",
+       "Outbound tasklet runs",
+       "SIGA read",
+       "SIGA write",
+       "SIGA sync",
+       "Inbound calls",
+       "Inbound handler",
+       "Inbound stop_polling",
+       "Inbound queue full",
+       "Outbound calls",
+       "Outbound handler",
+       "Outbound fast_requeue",
+       "Outbound target_full",
+       "QEBSM eqbs",
+       "QEBSM eqbs partial",
+       "QEBSM sqbs",
+       "QEBSM sqbs partial"
+};
+
+static int qperf_show(struct seq_file *m, void *v)
+{
+       struct qdio_irq *irq_ptr = m->private;
+       unsigned int *stat;
+       int i;
+
+       if (!irq_ptr)
+               return 0;
+       if (!irq_ptr->perf_stat_enabled) {
+               seq_printf(m, "disabled\n");
+               return 0;
+       }
+       stat = (unsigned int *)&irq_ptr->perf_stat;
+
+       for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
+               seq_printf(m, "%26s:\t%u\n",
+                          qperf_names[i], *(stat + i));
+       return 0;
+}
+
+static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
+                              size_t count, loff_t *off)
+{
+       struct seq_file *seq = file->private_data;
+       struct qdio_irq *irq_ptr = seq->private;
+       unsigned long val;
+       char buf[8];
+       int ret;
+
+       if (!irq_ptr)
+               return 0;
+       if (count >= sizeof(buf))
+               return -EINVAL;
+       if (copy_from_user(&buf, ubuf, count))
+               return -EFAULT;
+       buf[count] = 0;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret < 0)
+               return ret;
+
+       switch (val) {
+       case 0:
+               irq_ptr->perf_stat_enabled = 0;
+               memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
+               break;
+       case 1:
+               irq_ptr->perf_stat_enabled = 1;
+               break;
+       }
+       return count;
+}
+
+static int qperf_seq_open(struct inode *inode, struct file *filp)
+{
+       return single_open(filp, qperf_show,
+                          filp->f_path.dentry->d_inode->i_private);
+}
+
+static struct file_operations debugfs_perf_fops = {
+       .owner   = THIS_MODULE,
+       .open    = qperf_seq_open,
+       .read    = seq_read,
+       .write   = qperf_seq_write,
+       .llseek  = seq_lseek,
+       .release = single_release,
+};
 static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
 {
        char name[QDIO_DEBUGFS_NAME_LEN];
@@ -156,6 +245,14 @@ void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
                                                  debugfs_root);
        if (IS_ERR(irq_ptr->debugfs_dev))
                irq_ptr->debugfs_dev = NULL;
+
+       irq_ptr->debugfs_perf = debugfs_create_file("statistics",
+                               S_IFREG | S_IRUGO | S_IWUSR,
+                               irq_ptr->debugfs_dev, irq_ptr,
+                               &debugfs_perf_fops);
+       if (IS_ERR(irq_ptr->debugfs_perf))
+               irq_ptr->debugfs_perf = NULL;
+
        for_each_input_queue(irq_ptr, q, i)
                setup_debugfs_entry(q, cdev);
        for_each_output_queue(irq_ptr, q, i)
@@ -171,6 +268,7 @@ void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cd
                debugfs_remove(q->debugfs_q);
        for_each_output_queue(irq_ptr, q, i)
                debugfs_remove(q->debugfs_q);
+       debugfs_remove(irq_ptr->debugfs_perf);
        debugfs_remove(irq_ptr->debugfs_dev);
 }
 
index b2275c5000e7c458b1afaf9c2542c25a3e7dc976..999fe80c40516983d68a6435b5718c5433af1737 100644 (file)
@@ -22,7 +22,6 @@
 #include "device.h"
 #include "qdio.h"
 #include "qdio_debug.h"
-#include "qdio_perf.h"
 
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>,"\
        "Jan Glauber <jang@linux.vnet.ibm.com>");
@@ -126,7 +125,7 @@ static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
        int rc;
 
        BUG_ON(!q->irq_ptr->sch_token);
-       qdio_perf_stat_inc(&perf_stats.debug_eqbs_all);
+       qperf_inc(q, eqbs);
 
        if (!q->is_input_q)
                nr += q->irq_ptr->nr_input_qs;
@@ -139,7 +138,7 @@ again:
         * buffers later.
         */
        if ((ccq == 96) && (count != tmp_count)) {
-               qdio_perf_stat_inc(&perf_stats.debug_eqbs_incomplete);
+               qperf_inc(q, eqbs_partial);
                return (count - tmp_count);
        }
 
@@ -182,7 +181,7 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start,
                return 0;
 
        BUG_ON(!q->irq_ptr->sch_token);
-       qdio_perf_stat_inc(&perf_stats.debug_sqbs_all);
+       qperf_inc(q, sqbs);
 
        if (!q->is_input_q)
                nr += q->irq_ptr->nr_input_qs;
@@ -191,7 +190,7 @@ again:
        rc = qdio_check_ccq(q, ccq);
        if (rc == 1) {
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq);
-               qdio_perf_stat_inc(&perf_stats.debug_sqbs_incomplete);
+               qperf_inc(q, sqbs_partial);
                goto again;
        }
        if (rc < 0) {
@@ -285,7 +284,7 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output,
                return 0;
 
        DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr);
-       qdio_perf_stat_inc(&perf_stats.siga_sync);
+       qperf_inc(q, siga_sync);
 
        cc = do_siga_sync(q->irq_ptr->schid, output, input);
        if (cc)
@@ -350,7 +349,7 @@ static inline int qdio_siga_input(struct qdio_q *q)
        int cc;
 
        DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-r:%1d", q->nr);
-       qdio_perf_stat_inc(&perf_stats.siga_in);
+       qperf_inc(q, siga_read);
 
        cc = do_siga_input(q->irq_ptr->schid, q->mask);
        if (cc)
@@ -382,7 +381,7 @@ static inline void qdio_stop_polling(struct qdio_q *q)
                return;
 
        q->u.in.polling = 0;
-       qdio_perf_stat_inc(&perf_stats.debug_stop_polling);
+       qperf_inc(q, stop_polling);
 
        /* show the card that we are not polling anymore */
        if (is_qebsm(q)) {
@@ -400,7 +399,7 @@ static void announce_buffer_error(struct qdio_q *q, int count)
        /* special handling for no target buffer empty */
        if ((!q->is_input_q &&
            (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) {
-               qdio_perf_stat_inc(&perf_stats.outbound_target_full);
+               qperf_inc(q, target_full);
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x",
                              q->first_to_check);
                return;
@@ -487,7 +486,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
                inbound_primed(q, count);
                q->first_to_check = add_buf(q->first_to_check, count);
                if (atomic_sub(count, &q->nr_buf_used) == 0)
-                       qdio_perf_stat_inc(&perf_stats.inbound_queue_full);
+                       qperf_inc(q, inbound_queue_full);
                break;
        case SLSB_P_INPUT_ERROR:
                announce_buffer_error(q, count);
@@ -567,9 +566,10 @@ static void qdio_kick_handler(struct qdio_q *q)
        count = sub_buf(end, start);
 
        if (q->is_input_q) {
-               qdio_perf_stat_inc(&perf_stats.inbound_handler);
+               qperf_inc(q, inbound_handler);
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count);
        } else
+               qperf_inc(q, outbound_handler);
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x",
                              start, count);
 
@@ -583,24 +583,28 @@ static void qdio_kick_handler(struct qdio_q *q)
 
 static void __qdio_inbound_processing(struct qdio_q *q)
 {
-       qdio_perf_stat_inc(&perf_stats.tasklet_inbound);
+       qperf_inc(q, tasklet_inbound);
 again:
        if (!qdio_inbound_q_moved(q))
                return;
 
        qdio_kick_handler(q);
 
-       if (!qdio_inbound_q_done(q))
+       if (!qdio_inbound_q_done(q)) {
                /* means poll time is not yet over */
+               qperf_inc(q, tasklet_inbound_resched);
                goto again;
+       }
 
        qdio_stop_polling(q);
        /*
         * We need to check again to not lose initiative after
         * resetting the ACK state.
         */
-       if (!qdio_inbound_q_done(q))
+       if (!qdio_inbound_q_done(q)) {
+               qperf_inc(q, tasklet_inbound_resched2);
                goto again;
+       }
 }
 
 void qdio_inbound_processing(unsigned long data)
@@ -688,7 +692,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q)
                return 0;
 
        DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr);
-       qdio_perf_stat_inc(&perf_stats.siga_out);
+       qperf_inc(q, siga_write);
 
        cc = qdio_siga_output(q, &busy_bit);
        switch (cc) {
@@ -711,7 +715,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q)
 
 static void __qdio_outbound_processing(struct qdio_q *q)
 {
-       qdio_perf_stat_inc(&perf_stats.tasklet_outbound);
+       qperf_inc(q, tasklet_outbound);
        BUG_ON(atomic_read(&q->nr_buf_used) < 0);
 
        if (qdio_outbound_q_moved(q))
@@ -739,12 +743,9 @@ static void __qdio_outbound_processing(struct qdio_q *q)
         */
        if (qdio_outbound_q_done(q))
                del_timer(&q->u.out.timer);
-       else {
-               if (!timer_pending(&q->u.out.timer)) {
+       else
+               if (!timer_pending(&q->u.out.timer))
                        mod_timer(&q->u.out.timer, jiffies + 10 * HZ);
-                       qdio_perf_stat_inc(&perf_stats.debug_tl_out_timer);
-               }
-       }
        return;
 
 sched:
@@ -784,7 +785,7 @@ static inline void qdio_check_outbound_after_thinint(struct qdio_q *q)
 
 static void __tiqdio_inbound_processing(struct qdio_q *q)
 {
-       qdio_perf_stat_inc(&perf_stats.thinint_inbound);
+       qperf_inc(q, tasklet_inbound);
        qdio_sync_after_thinint(q);
 
        /*
@@ -799,7 +800,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q)
        qdio_kick_handler(q);
 
        if (!qdio_inbound_q_done(q)) {
-               qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop);
+               qperf_inc(q, tasklet_inbound_resched);
                if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) {
                        tasklet_schedule(&q->tasklet);
                        return;
@@ -812,7 +813,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q)
         * resetting the ACK state.
         */
        if (!qdio_inbound_q_done(q)) {
-               qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop2);
+               qperf_inc(q, tasklet_inbound_resched2);
                if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED))
                        tasklet_schedule(&q->tasklet);
        }
@@ -851,8 +852,6 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
        if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
                return;
 
-       qdio_perf_stat_inc(&perf_stats.pci_int);
-
        for_each_input_queue(irq_ptr, q, i)
                tasklet_schedule(&q->tasklet);
 
@@ -923,8 +922,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
        struct qdio_irq *irq_ptr = cdev->private->qdio_data;
        int cstat, dstat;
 
-       qdio_perf_stat_inc(&perf_stats.qdio_int);
-
        if (!intparm || !irq_ptr) {
                DBF_ERROR("qint:%4x", cdev->private->schid.sch_no);
                return;
@@ -1383,6 +1380,8 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
 {
        int used, diff;
 
+       qperf_inc(q, inbound_call);
+
        if (!q->u.in.polling)
                goto set;
 
@@ -1438,14 +1437,16 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
        unsigned char state;
        int used, rc = 0;
 
-       qdio_perf_stat_inc(&perf_stats.outbound_handler);
+       qperf_inc(q, outbound_call);
 
        count = set_buf_states(q, bufnr, SLSB_CU_OUTPUT_PRIMED, count);
        used = atomic_add_return(count, &q->nr_buf_used);
        BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q);
 
-       if (callflags & QDIO_FLAG_PCI_OUT)
+       if (callflags & QDIO_FLAG_PCI_OUT) {
                q->u.out.pci_out_enabled = 1;
+               qperf_inc(q, pci_request_int);
+       }
        else
                q->u.out.pci_out_enabled = 0;
 
@@ -1484,7 +1485,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
        if (state != SLSB_CU_OUTPUT_PRIMED)
                rc = qdio_kick_outbound_q(q);
        else
-               qdio_perf_stat_inc(&perf_stats.fast_requeue);
+               qperf_inc(q, fast_requeue);
 
 out:
        tasklet_schedule(&q->tasklet);
@@ -1540,16 +1541,11 @@ static int __init init_QDIO(void)
        rc = qdio_debug_init();
        if (rc)
                goto out_ti;
-       rc = qdio_setup_perf_stats();
-       if (rc)
-               goto out_debug;
        rc = tiqdio_register_thinints();
        if (rc)
-               goto out_perf;
+               goto out_debug;
        return 0;
 
-out_perf:
-       qdio_remove_perf_stats();
 out_debug:
        qdio_debug_exit();
 out_ti:
@@ -1563,7 +1559,6 @@ static void __exit exit_QDIO(void)
 {
        tiqdio_unregister_thinints();
        tiqdio_free_memory();
-       qdio_remove_perf_stats();
        qdio_debug_exit();
        qdio_setup_exit();
 }
diff --git a/drivers/s390/cio/qdio_perf.c b/drivers/s390/cio/qdio_perf.c
deleted file mode 100644 (file)
index 54f7c32..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *  drivers/s390/cio/qdio_perf.c
- *
- *  Copyright IBM Corp. 2008
- *
- *  Author: Jan Glauber (jang@linux.vnet.ibm.com)
- */
-#include <linux/kernel.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <asm/ccwdev.h>
-
-#include "cio.h"
-#include "css.h"
-#include "device.h"
-#include "ioasm.h"
-#include "chsc.h"
-#include "qdio_debug.h"
-#include "qdio_perf.h"
-
-int qdio_performance_stats;
-struct qdio_perf_stats perf_stats;
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *qdio_perf_pde;
-#endif
-
-/*
- * procfs functions
- */
-static int qdio_perf_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "Number of qdio interrupts\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.qdio_int));
-       seq_printf(m, "Number of PCI interrupts\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.pci_int));
-       seq_printf(m, "Number of adapter interrupts\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.thin_int));
-       seq_printf(m, "\n");
-       seq_printf(m, "Inbound tasklet runs\t\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.tasklet_inbound));
-       seq_printf(m, "Outbound tasklet runs\t\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.tasklet_outbound));
-       seq_printf(m, "Adapter interrupt tasklet runs/loops\t\t: %li/%li\n",
-                  (long)atomic_long_read(&perf_stats.tasklet_thinint),
-                  (long)atomic_long_read(&perf_stats.tasklet_thinint_loop));
-       seq_printf(m, "Adapter interrupt inbound tasklet runs/loops\t: %li/%li\n",
-                  (long)atomic_long_read(&perf_stats.thinint_inbound),
-                  (long)atomic_long_read(&perf_stats.thinint_inbound_loop));
-       seq_printf(m, "\n");
-       seq_printf(m, "Number of SIGA In issued\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.siga_in));
-       seq_printf(m, "Number of SIGA Out issued\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.siga_out));
-       seq_printf(m, "Number of SIGA Sync issued\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.siga_sync));
-       seq_printf(m, "\n");
-       seq_printf(m, "Number of inbound transfers\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.inbound_handler));
-       seq_printf(m, "Number of outbound transfers\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.outbound_handler));
-       seq_printf(m, "\n");
-       seq_printf(m, "Number of fast requeues (outg. SBAL w/o SIGA)\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.fast_requeue));
-       seq_printf(m, "Number of outbound target full condition\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.outbound_target_full));
-       seq_printf(m, "Number of inbound queue full condition\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.inbound_queue_full));
-       seq_printf(m, "Number of outbound tasklet mod_timer calls\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.debug_tl_out_timer));
-       seq_printf(m, "Number of stop polling calls\t\t\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.debug_stop_polling));
-       seq_printf(m, "AI inbound tasklet loops after stop polling\t: %li\n",
-                  (long)atomic_long_read(&perf_stats.thinint_inbound_loop2));
-       seq_printf(m, "QEBSM EQBS total/incomplete\t\t\t: %li/%li\n",
-                  (long)atomic_long_read(&perf_stats.debug_eqbs_all),
-                  (long)atomic_long_read(&perf_stats.debug_eqbs_incomplete));
-       seq_printf(m, "QEBSM SQBS total/incomplete\t\t\t: %li/%li\n",
-                  (long)atomic_long_read(&perf_stats.debug_sqbs_all),
-                  (long)atomic_long_read(&perf_stats.debug_sqbs_incomplete));
-       seq_printf(m, "\n");
-       return 0;
-}
-static int qdio_perf_seq_open(struct inode *inode, struct file *filp)
-{
-       return single_open(filp, qdio_perf_proc_show, NULL);
-}
-
-static const struct file_operations qdio_perf_proc_fops = {
-       .owner   = THIS_MODULE,
-       .open    = qdio_perf_seq_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .release = single_release,
-};
-
-/*
- * sysfs functions
- */
-static ssize_t qdio_perf_stats_show(struct bus_type *bus, char *buf)
-{
-       return sprintf(buf, "%i\n", qdio_performance_stats ? 1 : 0);
-}
-
-static ssize_t qdio_perf_stats_store(struct bus_type *bus,
-                             const char *buf, size_t count)
-{
-       unsigned long i;
-
-       if (strict_strtoul(buf, 16, &i) != 0)
-               return -EINVAL;
-       if ((i != 0) && (i != 1))
-               return -EINVAL;
-       if (i == qdio_performance_stats)
-               return count;
-
-       qdio_performance_stats = i;
-       /* reset performance statistics */
-       if (i == 0)
-               memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
-       return count;
-}
-
-static BUS_ATTR(qdio_performance_stats, 0644, qdio_perf_stats_show,
-               qdio_perf_stats_store);
-
-int __init qdio_setup_perf_stats(void)
-{
-       int rc;
-
-       rc = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
-       if (rc)
-               return rc;
-
-#ifdef CONFIG_PROC_FS
-       memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
-       qdio_perf_pde = proc_create("qdio_perf", S_IFREG | S_IRUGO,
-                                   NULL, &qdio_perf_proc_fops);
-#endif
-       return 0;
-}
-
-void qdio_remove_perf_stats(void)
-{
-#ifdef CONFIG_PROC_FS
-       remove_proc_entry("qdio_perf", NULL);
-#endif
-       bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
-}
diff --git a/drivers/s390/cio/qdio_perf.h b/drivers/s390/cio/qdio_perf.h
deleted file mode 100644 (file)
index 1245423..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  drivers/s390/cio/qdio_perf.h
- *
- *  Copyright IBM Corp. 2008
- *
- *  Author: Jan Glauber (jang@linux.vnet.ibm.com)
- */
-#ifndef QDIO_PERF_H
-#define QDIO_PERF_H
-
-#include <linux/types.h>
-#include <asm/atomic.h>
-
-struct qdio_perf_stats {
-       /* interrupt handler calls */
-       atomic_long_t qdio_int;
-       atomic_long_t pci_int;
-       atomic_long_t thin_int;
-
-       /* tasklet runs */
-       atomic_long_t tasklet_inbound;
-       atomic_long_t tasklet_outbound;
-       atomic_long_t tasklet_thinint;
-       atomic_long_t tasklet_thinint_loop;
-       atomic_long_t thinint_inbound;
-       atomic_long_t thinint_inbound_loop;
-       atomic_long_t thinint_inbound_loop2;
-
-       /* signal adapter calls */
-       atomic_long_t siga_out;
-       atomic_long_t siga_in;
-       atomic_long_t siga_sync;
-
-       /* misc */
-       atomic_long_t inbound_handler;
-       atomic_long_t outbound_handler;
-       atomic_long_t fast_requeue;
-       atomic_long_t outbound_target_full;
-       atomic_long_t inbound_queue_full;
-
-       /* for debugging */
-       atomic_long_t debug_tl_out_timer;
-       atomic_long_t debug_stop_polling;
-       atomic_long_t debug_eqbs_all;
-       atomic_long_t debug_eqbs_incomplete;
-       atomic_long_t debug_sqbs_all;
-       atomic_long_t debug_sqbs_incomplete;
-};
-
-extern struct qdio_perf_stats perf_stats;
-extern int qdio_performance_stats;
-
-static inline void qdio_perf_stat_inc(atomic_long_t *count)
-{
-       if (qdio_performance_stats)
-               atomic_long_inc(count);
-}
-
-int qdio_setup_perf_stats(void);
-void qdio_remove_perf_stats(void);
-
-#endif
index 981a77ea7ee24871c3f4d72db130c014238ebbde..091d904d3182a566fc059e11fd193adb5d574cbb 100644 (file)
@@ -1,9 +1,7 @@
 /*
  * linux/drivers/s390/cio/thinint_qdio.c
  *
- * thin interrupt support for qdio
- *
- * Copyright 2000-2008 IBM Corp.
+ * Copyright 2000,2009 IBM Corp.
  * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
  *           Cornelia Huck <cornelia.huck@de.ibm.com>
  *           Jan Glauber <jang@linux.vnet.ibm.com>
@@ -19,7 +17,6 @@
 #include "ioasm.h"
 #include "qdio.h"
 #include "qdio_debug.h"
-#include "qdio_perf.h"
 
 /*
  * Restriction: only 63 iqdio subchannels would have its own indicator,
@@ -132,8 +129,6 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data)
 {
        struct qdio_q *q;
 
-       qdio_perf_stat_inc(&perf_stats.thin_int);
-
        /*
         * SVS only when needed: issue SVS to benefit from iqdio interrupt
         * avoidance (SVS clears adapter interrupt suppression overwrite)
@@ -154,6 +149,7 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data)
        list_for_each_entry_rcu(q, &tiq_list, entry)
                /* only process queues from changed sets */
                if (*q->irq_ptr->dsci) {
+                       qperf_inc(q, adapter_int);
 
                        /* only clear it if the indicator is non-shared */
                        if (!shared_ind(q->irq_ptr))
index 7c815d3327f754e095212dfc608a64f514547429..28d86f9df83c64717d3d173283cc5c5679c8a539 100644 (file)
@@ -522,6 +522,40 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op,
        set_fan_speeds(fp);
 }
 
+static void destroy_one_temp(struct bbc_cpu_temperature *tp)
+{
+       bbc_i2c_detach(tp->client);
+       kfree(tp);
+}
+
+static void destroy_all_temps(struct bbc_i2c_bus *bp)
+{
+       struct bbc_cpu_temperature *tp, *tpos;
+
+       list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
+               list_del(&tp->bp_list);
+               list_del(&tp->glob_list);
+               destroy_one_temp(tp);
+       }
+}
+
+static void destroy_one_fan(struct bbc_fan_control *fp)
+{
+       bbc_i2c_detach(fp->client);
+       kfree(fp);
+}
+
+static void destroy_all_fans(struct bbc_i2c_bus *bp)
+{
+       struct bbc_fan_control *fp, *fpos;
+
+       list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
+               list_del(&fp->bp_list);
+               list_del(&fp->glob_list);
+               destroy_one_fan(fp);
+       }
+}
+
 int bbc_envctrl_init(struct bbc_i2c_bus *bp)
 {
        struct of_device *op;
@@ -541,6 +575,8 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
                        int err = PTR_ERR(kenvctrld_task);
 
                        kenvctrld_task = NULL;
+                       destroy_all_temps(bp);
+                       destroy_all_fans(bp);
                        return err;
                }
        }
@@ -548,35 +584,11 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
        return 0;
 }
 
-static void destroy_one_temp(struct bbc_cpu_temperature *tp)
-{
-       bbc_i2c_detach(tp->client);
-       kfree(tp);
-}
-
-static void destroy_one_fan(struct bbc_fan_control *fp)
-{
-       bbc_i2c_detach(fp->client);
-       kfree(fp);
-}
-
 void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp)
 {
-       struct bbc_cpu_temperature *tp, *tpos;
-       struct bbc_fan_control *fp, *fpos;
-
        if (kenvctrld_task)
                kthread_stop(kenvctrld_task);
 
-       list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
-               list_del(&tp->bp_list);
-               list_del(&tp->glob_list);
-               destroy_one_temp(tp);
-       }
-
-       list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
-               list_del(&fp->bp_list);
-               list_del(&fp->glob_list);
-               destroy_one_fan(fp);
-       }
+       destroy_all_temps(bp);
+       destroy_all_fans(bp);
 }
index 26ffdcd5a43701db2792a3187f23ac1ab845c601..15a00e8b71225d535b64dc3e02c4c703cb48062d 100644 (file)
@@ -1440,6 +1440,10 @@ void cxgb3i_c3cn_release(struct s3_conn *c3cn)
 static int is_cxgb3_dev(struct net_device *dev)
 {
        struct cxgb3i_sdev_data *cdata;
+       struct net_device *ndev = dev;
+
+       if (dev->priv_flags & IFF_802_1Q_VLAN)
+               ndev = vlan_dev_real_dev(dev);
 
        write_lock(&cdata_rwlock);
        list_for_each_entry(cdata, &cdata_list, list) {
@@ -1447,7 +1451,7 @@ static int is_cxgb3_dev(struct net_device *dev)
                int i;
 
                for (i = 0; i < ports->nports; i++)
-                       if (dev == ports->lldevs[i]) {
+                       if (ndev == ports->lldevs[i]) {
                                write_unlock(&cdata_rwlock);
                                return 1;
                        }
@@ -1566,6 +1570,26 @@ out_err:
        return -EINVAL;
 }
 
+/**
+ * cxgb3i_find_dev - find the interface associated with the given address
+ * @ipaddr: ip address
+ */
+static struct net_device *
+cxgb3i_find_dev(struct net_device *dev, __be32 ipaddr)
+{
+       struct flowi fl;
+       int err;
+       struct rtable *rt;
+
+       memset(&fl, 0, sizeof(fl));
+       fl.nl_u.ip4_u.daddr = ipaddr;
+
+       err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl);
+       if (!err)
+               return (&rt->u.dst)->dev;
+
+       return NULL;
+}
 
 /**
  * cxgb3i_c3cn_connect - initiates an iscsi tcp connection to a given address
@@ -1581,6 +1605,7 @@ int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn,
        struct cxgb3i_sdev_data *cdata;
        struct t3cdev *cdev;
        __be32 sipv4;
+       struct net_device *dstdev;
        int err;
 
        c3cn_conn_debug("c3cn 0x%p, dev 0x%p.\n", c3cn, dev);
@@ -1591,6 +1616,13 @@ int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn,
        c3cn->daddr.sin_port = usin->sin_port;
        c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr;
 
+       dstdev = cxgb3i_find_dev(dev, usin->sin_addr.s_addr);
+       if (!dstdev || !is_cxgb3_dev(dstdev))
+               return -ENETUNREACH;
+
+       if (dstdev->priv_flags & IFF_802_1Q_VLAN)
+               dev = dstdev;
+
        rt = find_route(dev, c3cn->saddr.sin_addr.s_addr,
                        c3cn->daddr.sin_addr.s_addr,
                        c3cn->saddr.sin_port,
index ce522702a6c13b951e1790a846b7758fa9c71e97..2cc39684ce97622f4db92d617a9d0c40cf3a7ff8 100644 (file)
@@ -4142,8 +4142,8 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        spin_lock_irq(shost->host_lock);
        if (vport->fc_rscn_flush) {
                /* Another thread is walking fc_rscn_id_list on this vport */
-               spin_unlock_irq(shost->host_lock);
                vport->fc_flag |= FC_RSCN_DISCOVERY;
+               spin_unlock_irq(shost->host_lock);
                /* Send back ACC */
                lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
                return 0;
@@ -5948,8 +5948,8 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                                lpfc_initial_fdisc(vport);
                        break;
                }
-
        } else {
+               vport->vpi_state |= LPFC_VPI_REGISTERED;
                if (vport == phba->pport)
                        if (phba->sli_rev < LPFC_SLI_REV4)
                                lpfc_issue_fabric_reglogin(vport);
index 3b9424427652a630f60bf197b1cd1146d4953d43..2445e399fd60fd3e76bfbcd3a644519e11206893 100755 (executable)
@@ -747,6 +747,10 @@ lpfc_linkdown(struct lpfc_hba *phba)
 
        if (phba->link_state == LPFC_LINK_DOWN)
                return 0;
+
+       /* Block all SCSI stack I/Os */
+       lpfc_scsi_dev_block(phba);
+
        spin_lock_irq(&phba->hbalock);
        phba->fcf.fcf_flag &= ~(FCF_AVAILABLE | FCF_DISCOVERED);
        if (phba->link_state > LPFC_LINK_DOWN) {
@@ -1555,10 +1559,16 @@ lpfc_mbx_cmpl_read_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
         * to book keeping the FCFIs can be used.
         */
        if (shdr_status || shdr_add_status) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "2521 READ_FCF_RECORD mailbox failed "
-                               "with status x%x add_status x%x, mbx\n",
-                               shdr_status, shdr_add_status);
+               if (shdr_status == STATUS_FCF_TABLE_EMPTY) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "2726 READ_FCF_RECORD Indicates empty "
+                                       "FCF table.\n");
+               } else {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "2521 READ_FCF_RECORD mailbox failed "
+                                       "with status x%x add_status x%x, mbx\n",
+                                       shdr_status, shdr_add_status);
+               }
                goto out;
        }
        /* Interpreting the returned information of FCF records */
@@ -1698,7 +1708,9 @@ lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
                return;
        }
+       spin_lock_irq(&phba->hbalock);
        vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI;
+       spin_unlock_irq(&phba->hbalock);
 
        if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
                lpfc_initial_fdisc(vport);
@@ -2259,7 +2271,10 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                                 mb->mbxStatus);
                break;
        }
+       spin_lock_irq(&phba->hbalock);
        vport->vpi_state &= ~LPFC_VPI_REGISTERED;
+       vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+       spin_unlock_irq(&phba->hbalock);
        vport->unreg_vpi_cmpl = VPORT_OK;
        mempool_free(pmb, phba->mbox_mem_pool);
        /*
@@ -4475,8 +4490,10 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba)
                (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED))
                for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
                        lpfc_mbx_unreg_vpi(vports[i]);
+                       spin_lock_irq(&phba->hbalock);
                        vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
                        vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED;
+                       spin_unlock_irq(&phba->hbalock);
                }
        lpfc_destroy_vport_work_array(phba, vports);
 
old mode 100644 (file)
new mode 100755 (executable)
index 1585148..8a2a1c5
@@ -1013,7 +1013,7 @@ struct lpfc_mbx_wq_destroy {
 };
 
 #define LPFC_HDR_BUF_SIZE 128
-#define LPFC_DATA_BUF_SIZE 4096
+#define LPFC_DATA_BUF_SIZE 2048
 struct rq_context {
        uint32_t word0;
 #define lpfc_rq_context_rq_size_SHIFT  16
@@ -1371,6 +1371,7 @@ struct lpfc_mbx_query_fw_cfg {
 #define STATUS_ERROR_ACITMAIN                          0x2a
 #define STATUS_REBOOT_REQUIRED                         0x2c
 #define STATUS_FCF_IN_USE                              0x3a
+#define STATUS_FCF_TABLE_EMPTY                         0x43
 
 struct lpfc_mbx_sli4_config {
        struct mbox_header header;
index d4da6bdd0e73fd5d4442b2487e185920f59ef7de..b8eb1b6e5e77ea2522dfe93b76841454ceebfc5a 100644 (file)
@@ -3006,6 +3006,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
        struct lpfc_vport *vport;
        struct lpfc_nodelist *ndlp;
        struct Scsi_Host  *shost;
+       uint32_t link_state;
 
        phba->fc_eventTag = acqe_fcoe->event_tag;
        phba->fcoe_eventtag = acqe_fcoe->event_tag;
@@ -3052,9 +3053,12 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
                        break;
                /*
                 * Currently, driver support only one FCF - so treat this as
-                * a link down.
+                * a link down, but save the link state because we don't want
+                * it to be changed to Link Down unless it is already down.
                 */
+               link_state = phba->link_state;
                lpfc_linkdown(phba);
+               phba->link_state = link_state;
                /* Unregister FCF if no devices connected to it */
                lpfc_unregister_unused_fcf(phba);
                break;
@@ -7226,8 +7230,6 @@ lpfc_prep_dev_for_perm_failure(struct lpfc_hba *phba)
 {
        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                        "2711 PCI channel permanent disable for failure\n");
-       /* Block all SCSI devices' I/Os on the host */
-       lpfc_scsi_dev_block(phba);
        /* Clean up all driver's outstanding SCSI I/Os */
        lpfc_sli_flush_fcp_rings(phba);
 }
@@ -7256,6 +7258,9 @@ lpfc_io_error_detected_s3(struct pci_dev *pdev, pci_channel_state_t state)
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
 
+       /* Block all SCSI devices' I/Os on the host */
+       lpfc_scsi_dev_block(phba);
+
        switch (state) {
        case pci_channel_io_normal:
                /* Non-fatal error, prepare for recovery */
@@ -7507,6 +7512,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                        error = -ENODEV;
                        goto out_free_sysfs_attr;
                }
+               /* Default to single FCP EQ for non-MSI-X */
+               if (phba->intr_type != MSIX)
+                       phba->cfg_fcp_eq_count = 1;
                /* Set up SLI-4 HBA */
                if (lpfc_sli4_hba_setup(phba)) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
index 7935667b81a5b8a8f46fe64b7d1cfd441b24cc6d..589549b2bf0e2da65b38078c8ee005f0afcee822 100644 (file)
@@ -1383,7 +1383,7 @@ lpfc_sli_hbq_to_firmware_s4(struct lpfc_hba *phba, uint32_t hbqno,
 /* HBQ for ELS and CT traffic. */
 static struct lpfc_hbq_init lpfc_els_hbq = {
        .rn = 1,
-       .entry_count = 200,
+       .entry_count = 256,
        .mask_count = 0,
        .profile = 0,
        .ring_mask = (1 << LPFC_ELS_RING),
@@ -1482,8 +1482,11 @@ err:
 int
 lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
 {
-       return(lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
-                                        lpfc_hbq_defs[qno]->add_count));
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               return 0;
+       else
+               return lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
+                                        lpfc_hbq_defs[qno]->add_count);
 }
 
 /**
@@ -1498,8 +1501,12 @@ lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
 static int
 lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
 {
-       return(lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
-                                        lpfc_hbq_defs[qno]->init_count));
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               return lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
+                                        lpfc_hbq_defs[qno]->entry_count);
+       else
+               return lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
+                                        lpfc_hbq_defs[qno]->init_count);
 }
 
 /**
@@ -4110,6 +4117,7 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
        if (rc) {
                dma_free_coherent(&phba->pcidev->dev, dma_size,
                                  dmabuf->virt, dmabuf->phys);
+               kfree(dmabuf);
                return -EIO;
        }
 
@@ -5848,7 +5856,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                                        iocbq->iocb.un.ulpWord[3]);
                wqe->generic.word3 = 0;
                bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext);
-               bf_set(wqe_xc, &wqe->generic, 1);
                /* The entire sequence is transmitted for this IOCB */
                xmit_len = total_len;
                cmnd = CMD_XMIT_SEQUENCE64_CR;
@@ -10944,7 +10951,8 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
                return dmabuf;
        }
        temp_hdr = seq_dmabuf->hbuf.virt;
-       if (new_hdr->fh_seq_cnt < temp_hdr->fh_seq_cnt) {
+       if (be16_to_cpu(new_hdr->fh_seq_cnt) <
+               be16_to_cpu(temp_hdr->fh_seq_cnt)) {
                list_del_init(&seq_dmabuf->hbuf.list);
                list_add_tail(&dmabuf->hbuf.list, &vport->rcv_buffer_list);
                list_add_tail(&dmabuf->dbuf.list, &seq_dmabuf->dbuf.list);
@@ -10955,6 +10963,11 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
        list_move_tail(&seq_dmabuf->hbuf.list, &vport->rcv_buffer_list);
        seq_dmabuf->time_stamp = jiffies;
        lpfc_update_rcv_time_stamp(vport);
+       if (list_empty(&seq_dmabuf->dbuf.list)) {
+               temp_hdr = dmabuf->hbuf.virt;
+               list_add_tail(&dmabuf->dbuf.list, &seq_dmabuf->dbuf.list);
+               return seq_dmabuf;
+       }
        /* find the correct place in the sequence to insert this frame */
        list_for_each_entry_reverse(d_buf, &seq_dmabuf->dbuf.list, list) {
                temp_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
@@ -10963,7 +10976,8 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
                 * If the frame's sequence count is greater than the frame on
                 * the list then insert the frame right after this frame
                 */
-               if (new_hdr->fh_seq_cnt > temp_hdr->fh_seq_cnt) {
+               if (be16_to_cpu(new_hdr->fh_seq_cnt) >
+                       be16_to_cpu(temp_hdr->fh_seq_cnt)) {
                        list_add(&dmabuf->dbuf.list, &temp_dmabuf->dbuf.list);
                        return seq_dmabuf;
                }
@@ -11210,7 +11224,7 @@ lpfc_seq_complete(struct hbq_dmabuf *dmabuf)
                seq_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
                hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
                /* If there is a hole in the sequence count then fail. */
-               if (++seq_count != hdr->fh_seq_cnt)
+               if (++seq_count != be16_to_cpu(hdr->fh_seq_cnt))
                        return 0;
                fctl = (hdr->fh_f_ctl[0] << 16 |
                        hdr->fh_f_ctl[1] << 8 |
@@ -11242,6 +11256,7 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
        struct lpfc_iocbq *first_iocbq, *iocbq;
        struct fc_frame_header *fc_hdr;
        uint32_t sid;
+       struct ulp_bde64 *pbde;
 
        fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
        /* remove from receive buffer list */
@@ -11283,8 +11298,9 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
                if (!iocbq->context3) {
                        iocbq->context3 = d_buf;
                        iocbq->iocb.ulpBdeCount++;
-                       iocbq->iocb.unsli3.rcvsli3.bde2.tus.f.bdeSize =
-                                                       LPFC_DATA_BUF_SIZE;
+                       pbde = (struct ulp_bde64 *)
+                                       &iocbq->iocb.unsli3.sli3Words[4];
+                       pbde->tus.f.bdeSize = LPFC_DATA_BUF_SIZE;
                        first_iocbq->iocb.unsli3.rcvsli3.acc_len +=
                                bf_get(lpfc_rcqe_length,
                                       &seq_dmabuf->cq_event.cqe.rcqe_cmpl);
@@ -11401,15 +11417,9 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
                return;
        }
        /* If not last frame in sequence continue processing frames. */
-       if (!lpfc_seq_complete(seq_dmabuf)) {
-               /*
-                * When saving off frames post a new one and mark this
-                * frame to be freed when it is finished.
-                **/
-               lpfc_sli_hbqbuf_fill_hbqs(phba, LPFC_ELS_HBQ, 1);
-               dmabuf->tag = -1;
+       if (!lpfc_seq_complete(seq_dmabuf))
                return;
-       }
+
        /* Send the complete sequence to the upper layer protocol */
        lpfc_sli4_send_seq_to_ulp(vport, seq_dmabuf);
 }
index 25d66d070cf8ff9e992b7bc164eaffd65bc336ec..44e5f574236bf25322eb9d30ebebc3faa8ae9442 100644 (file)
@@ -28,7 +28,7 @@
 /* Multi-queue arrangement for fast-path FCP work queues */
 #define LPFC_FN_EQN_MAX       8
 #define LPFC_SP_EQN_DEF       1
-#define LPFC_FP_EQN_DEF       1
+#define LPFC_FP_EQN_DEF       4
 #define LPFC_FP_EQN_MIN       1
 #define LPFC_FP_EQN_MAX       (LPFC_FN_EQN_MAX - LPFC_SP_EQN_DEF)
 
index c7f3aed2aab839c1f4d460820ebf65a3fd242bb6..792f72263f1ae39a921db273897b11bd689e48d2 100644 (file)
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.6"
+#define LPFC_DRIVER_VERSION "8.3.7"
 #define LPFC_DRIVER_NAME               "lpfc"
 #define LPFC_SP_DRIVER_HANDLER_NAME    "lpfc:sp"
 #define LPFC_FP_DRIVER_HANDLER_NAME    "lpfc:fp"
index 7d6dd83d35926d039efde743a819c3bbf835d65e..e3c7fa642306db2e64a12b27880442cc61316e89 100644 (file)
@@ -512,8 +512,10 @@ enable_vport(struct fc_vport *fc_vport)
                return VPORT_OK;
        }
 
+       spin_lock_irq(&phba->hbalock);
        vport->load_flag |= FC_LOADING;
        vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+       spin_unlock_irq(&phba->hbalock);
 
        /* Use the Physical nodes Fabric NDLP to determine if the link is
         * up and ready to FDISC.
@@ -700,7 +702,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
                        }
                        spin_unlock_irq(&phba->ndlp_lock);
                }
-               if (vport->vpi_state != LPFC_VPI_REGISTERED)
+               if (!(vport->vpi_state & LPFC_VPI_REGISTERED))
                        goto skip_logo;
                vport->unreg_vpi_cmpl = VPORT_INVAL;
                timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
index e7d2688fbeba9f6cd2ca37d27f5c4229347bd4ae..b6f1ef954af1b469a75ca7ab96c1112b8034146c 100644 (file)
@@ -2483,14 +2483,12 @@ static int pmcraid_error_handler(struct pmcraid_cmd *cmd)
                        sense_copied = 1;
                }
 
-               if (RES_IS_GSCSI(res->cfg_entry)) {
+               if (RES_IS_GSCSI(res->cfg_entry))
                        pmcraid_cancel_all(cmd, sense_copied);
-               } else if (sense_copied) {
+               else if (sense_copied)
                        pmcraid_erp_done(cmd);
-                       return 0;
-               } else  {
+               else
                        pmcraid_request_sense(cmd);
-               }
 
                return 1;
 
index 21e2bc4d74013caa1446385a72f53c17eaa58391..3a9f5b288aee40f6553b3dc2362efab9f0632c47 100644 (file)
@@ -232,6 +232,9 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
        if (off)
                return 0;
 
+       if (unlikely(pci_channel_offline(ha->pdev)))
+               return 0;
+
        if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1)
                return -EINVAL;
        if (start > ha->optrom_size)
@@ -379,6 +382,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj,
            struct device, kobj)));
        struct qla_hw_data *ha = vha->hw;
 
+       if (unlikely(pci_channel_offline(ha->pdev)))
+               return 0;
+
        if (!capable(CAP_SYS_ADMIN))
                return 0;
 
@@ -398,6 +404,9 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj,
        struct qla_hw_data *ha = vha->hw;
        uint8_t *tmp_data;
 
+       if (unlikely(pci_channel_offline(ha->pdev)))
+               return 0;
+
        if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size ||
            !ha->isp_ops->write_nvram)
                return 0;
@@ -1238,10 +1247,11 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
     char *buf)
 {
        scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
-       int rval;
+       int rval = QLA_FUNCTION_FAILED;
        uint16_t state[5];
 
-       rval = qla2x00_get_firmware_state(vha, state);
+       if (!vha->hw->flags.eeh_busy)
+               rval = qla2x00_get_firmware_state(vha, state);
        if (rval != QLA_SUCCESS)
                memset(state, -1, sizeof(state));
 
@@ -1452,10 +1462,13 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
        if (!fcport)
                return;
 
-       if (unlikely(pci_channel_offline(fcport->vha->hw->pdev)))
+       if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
+               return;
+
+       if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
                qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
-       else
-               qla2x00_abort_fcport_cmds(fcport);
+               return;
+       }
 
        /*
         * Transport has effectively 'deleted' the rport, clear
@@ -1475,6 +1488,9 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
        if (!fcport)
                return;
 
+       if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
+               return;
+
        if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
                qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
                return;
@@ -1515,6 +1531,12 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
        pfc_host_stat = &ha->fc_host_stat;
        memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
 
+       if (test_bit(UNLOADING, &vha->dpc_flags))
+               goto done;
+
+       if (unlikely(pci_channel_offline(ha->pdev)))
+               goto done;
+
        stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
        if (stats == NULL) {
                DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
index f660dd70b72e460671a00cc7342224197d8a4cc3..d6d9c86cb05826b8ddaf54cd465c160ad6d0d2c0 100644 (file)
@@ -26,7 +26,7 @@
 /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */
 /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
 /* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
-/* #define QL_DEBUG_LEVEL_17 */ /* Output MULTI-Q trace messages */
+/* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */
 
 /*
 * Macros use for debugging the driver.
 #else
 #define DEBUG16(x)     do {} while (0)
 #endif
+
+#if defined(QL_DEBUG_LEVEL_17)
+#define DEBUG17(x)     do {x;} while (0)
+#else
+#define DEBUG17(x)     do {} while (0)
+#endif
+
 /*
  * Firmware Dump structure definition
  */
index 384afda7dbe942f2ade0f189be0da5e4e7d71685..608e675f68c8569b79ccfc2fb79a2965824de347 100644 (file)
@@ -2256,11 +2256,13 @@ struct qla_hw_data {
                uint32_t        disable_serdes          :1;
                uint32_t        gpsc_supported          :1;
                uint32_t        npiv_supported          :1;
+               uint32_t        pci_channel_io_perm_failure     :1;
                uint32_t        fce_enabled             :1;
                uint32_t        fac_supported           :1;
                uint32_t        chip_reset_done         :1;
                uint32_t        port0                   :1;
                uint32_t        running_gold_fw         :1;
+               uint32_t        eeh_busy                :1;
                uint32_t        cpu_affinity_enabled    :1;
                uint32_t        disable_msix_handshake  :1;
        } flags;
index 0b6801fc6389dcce0a07720db60b423275e2a1ee..f61fb8d01330948f1f8328523cf5eb9de7944dae 100644 (file)
@@ -324,6 +324,7 @@ qla2x00_read_ram_word(scsi_qla_host_t *, uint32_t, uint32_t *);
 extern int
 qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
 
+extern int qla2x00_get_data_rate(scsi_qla_host_t *);
 /*
  * Global Function Prototypes in qla_isr.c source file.
  */
index 73a793539d4512ba0ac7a5921a6cd0783ffd4308..b4a0eac8f96d845f34043da8e9eb7e65cd5e2b98 100644 (file)
@@ -269,6 +269,8 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
        vha->flags.online = 0;
        ha->flags.chip_reset_done = 0;
        vha->flags.reset_active = 0;
+       ha->flags.pci_channel_io_perm_failure = 0;
+       ha->flags.eeh_busy = 0;
        atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
        atomic_set(&vha->loop_state, LOOP_DOWN);
        vha->device_flags = DFLG_NO_CABLE;
@@ -581,6 +583,9 @@ qla2x00_reset_chip(scsi_qla_host_t *vha)
        uint32_t        cnt;
        uint16_t        cmd;
 
+       if (unlikely(pci_channel_offline(ha->pdev)))
+               return;
+
        ha->isp_ops->disable_intrs(ha);
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -786,6 +791,12 @@ void
 qla24xx_reset_chip(scsi_qla_host_t *vha)
 {
        struct qla_hw_data *ha = vha->hw;
+
+       if (pci_channel_offline(ha->pdev) &&
+           ha->flags.pci_channel_io_perm_failure) {
+               return;
+       }
+
        ha->isp_ops->disable_intrs(ha);
 
        /* Perform RISC reset. */
@@ -2266,6 +2277,8 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
        clear_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
        clear_bit(RSCN_UPDATE, &vha->dpc_flags);
 
+       qla2x00_get_data_rate(vha);
+
        /* Determine what we need to do */
        if (ha->current_topology == ISP_CFG_FL &&
            (test_bit(LOCAL_LOOP_UPDATE, &flags))) {
@@ -3560,6 +3573,13 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
                /* Requeue all commands in outstanding command list. */
                qla2x00_abort_all_cmds(vha, DID_RESET << 16);
 
+               if (unlikely(pci_channel_offline(ha->pdev) &&
+                   ha->flags.pci_channel_io_perm_failure)) {
+                       clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
+                       status = 0;
+                       return status;
+               }
+
                ha->isp_ops->get_flash_version(vha, req->ring);
 
                ha->isp_ops->nvram_config(vha);
@@ -4458,6 +4478,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
        int ret, retries;
        struct qla_hw_data *ha = vha->hw;
 
+       if (ha->flags.pci_channel_io_perm_failure)
+               return;
        if (!IS_FWI2_CAPABLE(ha))
                return;
        if (!ha->fw_major_version)
index 1692a883f4de837b7cd386bd6ea02e4de4c278ef..ffd0efdff40e5f04504e2d148349e0909172364f 100644 (file)
@@ -152,7 +152,7 @@ qla2300_intr_handler(int irq, void *dev_id)
        for (iter = 50; iter--; ) {
                stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
                if (stat & HSR_RISC_PAUSED) {
-                       if (pci_channel_offline(ha->pdev))
+                       if (unlikely(pci_channel_offline(ha->pdev)))
                                break;
 
                        hccr = RD_REG_WORD(&reg->hccr);
@@ -1846,12 +1846,15 @@ qla24xx_intr_handler(int irq, void *dev_id)
        reg = &ha->iobase->isp24;
        status = 0;
 
+       if (unlikely(pci_channel_offline(ha->pdev)))
+               return IRQ_HANDLED;
+
        spin_lock_irqsave(&ha->hardware_lock, flags);
        vha = pci_get_drvdata(ha->pdev);
        for (iter = 50; iter--; ) {
                stat = RD_REG_DWORD(&reg->host_status);
                if (stat & HSRX_RISC_PAUSED) {
-                       if (pci_channel_offline(ha->pdev))
+                       if (unlikely(pci_channel_offline(ha->pdev)))
                                break;
 
                        hccr = RD_REG_DWORD(&reg->hccr);
@@ -1992,7 +1995,7 @@ qla24xx_msix_default(int irq, void *dev_id)
        do {
                stat = RD_REG_DWORD(&reg->host_status);
                if (stat & HSRX_RISC_PAUSED) {
-                       if (pci_channel_offline(ha->pdev))
+                       if (unlikely(pci_channel_offline(ha->pdev)))
                                break;
 
                        hccr = RD_REG_DWORD(&reg->hccr);
index 05d595d9a7ef3ed82bd1f97ce0800c686e221897..056e4d4505f369852788409a8b56ba913086d546 100644 (file)
@@ -56,6 +56,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, base_vha->host_no));
 
+       if (ha->flags.pci_channel_io_perm_failure) {
+               DEBUG(printk("%s(%ld): Perm failure on EEH, timeout MBX "
+                            "Exiting.\n", __func__, vha->host_no));
+               return QLA_FUNCTION_TIMEOUT;
+       }
+
        /*
         * Wait for active mailbox commands to finish by waiting at most tov
         * seconds. This is to serialize actual issuing of mailbox cmds during
@@ -154,10 +160,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                        /* Check for pending interrupts. */
                        qla2x00_poll(ha->rsp_q_map[0]);
 
-                       if (command != MBC_LOAD_RISC_RAM_EXTENDED &&
-                           !ha->flags.mbox_int)
+                       if (!ha->flags.mbox_int &&
+                           !(IS_QLA2200(ha) &&
+                           command == MBC_LOAD_RISC_RAM_EXTENDED))
                                msleep(10);
                } /* while */
+               DEBUG17(qla_printk(KERN_WARNING, ha,
+                       "Waited %d sec\n",
+                       (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ)));
        }
 
        /* Check whether we timed out */
@@ -227,7 +237,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 
        if (rval == QLA_FUNCTION_TIMEOUT &&
            mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) {
-               if (!io_lock_on || (mcp->flags & IOCTL_CMD)) {
+               if (!io_lock_on || (mcp->flags & IOCTL_CMD) ||
+                   ha->flags.eeh_busy) {
                        /* not in dpc. schedule it for dpc to take over. */
                        DEBUG(printk("%s(%ld): timeout schedule "
                        "isp_abort_needed.\n", __func__,
@@ -237,7 +248,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                        base_vha->host_no));
                        qla_printk(KERN_WARNING, ha,
                            "Mailbox command timeout occurred. Scheduling ISP "
-                           "abort.\n");
+                           "abort. eeh_busy: 0x%x\n", ha->flags.eeh_busy);
                        set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
                        qla2xxx_wake_dpc(vha);
                } else if (!abort_active) {
@@ -2530,6 +2541,9 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma,
        if (!IS_FWI2_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
+       if (unlikely(pci_channel_offline(vha->hw->pdev)))
+               return QLA_FUNCTION_FAILED;
+
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
 
        mcp->mb[0] = MBC_TRACE_CONTROL;
@@ -2565,6 +2579,9 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha)
        if (!IS_FWI2_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
+       if (unlikely(pci_channel_offline(vha->hw->pdev)))
+               return QLA_FUNCTION_FAILED;
+
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
 
        mcp->mb[0] = MBC_TRACE_CONTROL;
@@ -2595,6 +2612,9 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma,
        if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
+       if (unlikely(pci_channel_offline(vha->hw->pdev)))
+               return QLA_FUNCTION_FAILED;
+
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
 
        mcp->mb[0] = MBC_TRACE_CONTROL;
@@ -2639,6 +2659,9 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd)
        if (!IS_FWI2_CAPABLE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
+       if (unlikely(pci_channel_offline(vha->hw->pdev)))
+               return QLA_FUNCTION_FAILED;
+
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
 
        mcp->mb[0] = MBC_TRACE_CONTROL;
@@ -3643,3 +3666,36 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
 
        return rval;
 }
+
+int
+qla2x00_get_data_rate(scsi_qla_host_t *vha)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+       struct qla_hw_data *ha = vha->hw;
+
+       if (!IS_FWI2_CAPABLE(ha))
+               return QLA_FUNCTION_FAILED;
+
+       DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, vha->host_no));
+
+       mcp->mb[0] = MBC_DATA_RATE;
+       mcp->mb[1] = 0;
+       mcp->out_mb = MBX_1|MBX_0;
+       mcp->in_mb = MBX_2|MBX_1|MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(vha, mcp);
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n",
+                   __func__, vha->host_no, rval, mcp->mb[0]));
+       } else {
+               DEBUG11(printk(KERN_INFO
+                   "%s(%ld): done.\n", __func__, vha->host_no));
+               if (mcp->mb[1] != 0x7)
+                       ha->link_data_rate = mcp->mb[1];
+       }
+
+       return rval;
+}
index 2a4c7f4e7b69b0a4fcaf13cf044044c60639a3f6..b901aa267e7d35e5fb1530056ceedab8d2c75b25 100644 (file)
@@ -639,8 +639,10 @@ static void qla_do_work(struct work_struct *work)
        struct rsp_que *rsp = container_of(work, struct rsp_que, q_work);
        struct scsi_qla_host *vha;
 
+       spin_lock_irq(&rsp->hw->hardware_lock);
        vha = qla25xx_get_host(rsp);
        qla24xx_process_response_queue(vha, rsp);
+       spin_unlock_irq(&rsp->hw->hardware_lock);
 }
 
 /* create response queue */
index 2f873d23732584e334be93a64e6ae6e2ba204744..209f50e788a1e893549e2caa365e23b03d897437 100644 (file)
@@ -475,11 +475,11 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
        srb_t *sp;
        int rval;
 
-       if (unlikely(pci_channel_offline(ha->pdev))) {
-               if (ha->pdev->error_state == pci_channel_io_frozen)
-                       cmd->result = DID_REQUEUE << 16;
-               else
+       if (ha->flags.eeh_busy) {
+               if (ha->flags.pci_channel_io_perm_failure)
                        cmd->result = DID_NO_CONNECT << 16;
+               else
+                       cmd->result = DID_REQUEUE << 16;
                goto qc24_fail_command;
        }
 
@@ -552,8 +552,15 @@ qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
 #define ABORT_POLLING_PERIOD   1000
 #define ABORT_WAIT_ITER                ((10 * 1000) / (ABORT_POLLING_PERIOD))
        unsigned long wait_iter = ABORT_WAIT_ITER;
+       scsi_qla_host_t *vha = shost_priv(cmd->device->host);
+       struct qla_hw_data *ha = vha->hw;
        int ret = QLA_SUCCESS;
 
+       if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) {
+               DEBUG17(qla_printk(KERN_WARNING, ha, "return:eh_wait\n"));
+               return ret;
+       }
+
        while (CMD_SP(cmd) && wait_iter--) {
                msleep(ABORT_POLLING_PERIOD);
        }
@@ -1810,6 +1817,13 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* Set ISP-type information. */
        qla2x00_set_isp_flags(ha);
+
+       /* Set EEH reset type to fundamental if required by hba */
+       if ( IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha)) {
+               pdev->needs_freset = 1;
+               pci_save_state(pdev);
+       }
+
        /* Configure PCI I/O space */
        ret = qla2x00_iospace_config(ha);
        if (ret)
@@ -2174,6 +2188,24 @@ qla2x00_free_device(scsi_qla_host_t *vha)
 {
        struct qla_hw_data *ha = vha->hw;
 
+       qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
+
+       /* Disable timer */
+       if (vha->timer_active)
+               qla2x00_stop_timer(vha);
+
+       /* Kill the kernel thread for this host */
+       if (ha->dpc_thread) {
+               struct task_struct *t = ha->dpc_thread;
+
+               /*
+                * qla2xxx_wake_dpc checks for ->dpc_thread
+                * so we need to zero it out.
+                */
+               ha->dpc_thread = NULL;
+               kthread_stop(t);
+       }
+
        qla25xx_delete_queues(vha);
 
        if (ha->flags.fce_enabled)
@@ -2185,6 +2217,8 @@ qla2x00_free_device(scsi_qla_host_t *vha)
        /* Stop currently executing firmware. */
        qla2x00_try_to_stop_firmware(vha);
 
+       vha->flags.online = 0;
+
        /* turn-off interrupts on the card */
        if (ha->interrupts_on)
                ha->isp_ops->disable_intrs(ha);
@@ -2859,6 +2893,13 @@ qla2x00_do_dpc(void *data)
                if (!base_vha->flags.init_done)
                        continue;
 
+               if (ha->flags.eeh_busy) {
+                       DEBUG17(qla_printk(KERN_WARNING, ha,
+                           "qla2x00_do_dpc: dpc_flags: %lx\n",
+                           base_vha->dpc_flags));
+                       continue;
+               }
+
                DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no));
 
                ha->dpc_active = 1;
@@ -3049,8 +3090,13 @@ qla2x00_timer(scsi_qla_host_t *vha)
        int             index;
        srb_t           *sp;
        int             t;
+       uint16_t        w;
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req;
+
+       /* Hardware read to raise pending EEH errors during mailbox waits. */
+       if (!pci_channel_offline(ha->pdev))
+               pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
        /*
         * Ports - Port down timer.
         *
@@ -3252,16 +3298,23 @@ qla2x00_release_firmware(void)
 static pci_ers_result_t
 qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 {
-       scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
+       scsi_qla_host_t *vha = pci_get_drvdata(pdev);
+       struct qla_hw_data *ha = vha->hw;
+
+       DEBUG2(qla_printk(KERN_WARNING, ha, "error_detected:state %x\n",
+           state));
 
        switch (state) {
        case pci_channel_io_normal:
+               ha->flags.eeh_busy = 0;
                return PCI_ERS_RESULT_CAN_RECOVER;
        case pci_channel_io_frozen:
+               ha->flags.eeh_busy = 1;
                pci_disable_device(pdev);
                return PCI_ERS_RESULT_NEED_RESET;
        case pci_channel_io_perm_failure:
-               qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
+               ha->flags.pci_channel_io_perm_failure = 1;
+               qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
                return PCI_ERS_RESULT_DISCONNECT;
        }
        return PCI_ERS_RESULT_NEED_RESET;
@@ -3312,6 +3365,8 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
        struct qla_hw_data *ha = base_vha->hw;
        int rc;
 
+       DEBUG17(qla_printk(KERN_WARNING, ha, "slot_reset\n"));
+
        if (ha->mem_only)
                rc = pci_enable_device_mem(pdev);
        else
@@ -3320,19 +3375,33 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
        if (rc) {
                qla_printk(KERN_WARNING, ha,
                    "Can't re-enable PCI device after reset.\n");
-
                return ret;
        }
-       pci_set_master(pdev);
 
        if (ha->isp_ops->pci_config(base_vha))
                return ret;
 
+#ifdef QL_DEBUG_LEVEL_17
+       {
+               uint8_t b;
+               uint32_t i;
+
+               printk("slot_reset_1: ");
+               for (i = 0; i < 256; i++) {
+                       pci_read_config_byte(ha->pdev, i, &b);
+                       printk("%s%02x", (i%16) ? " " : "\n", b);
+               }
+               printk("\n");
+       }
+#endif
        set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
        if (qla2x00_abort_isp(base_vha) == QLA_SUCCESS)
                ret =  PCI_ERS_RESULT_RECOVERED;
        clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
 
+       DEBUG17(qla_printk(KERN_WARNING, ha,
+           "slot_reset-return:ret=%x\n", ret));
+
        return ret;
 }
 
@@ -3343,12 +3412,17 @@ qla2xxx_pci_resume(struct pci_dev *pdev)
        struct qla_hw_data *ha = base_vha->hw;
        int ret;
 
+       DEBUG17(qla_printk(KERN_WARNING, ha, "pci_resume\n"));
+
        ret = qla2x00_wait_for_hba_online(base_vha);
        if (ret != QLA_SUCCESS) {
                qla_printk(KERN_ERR, ha,
                    "the device failed to resume I/O "
                    "from slot/link_reset");
        }
+
+       ha->flags.eeh_busy = 0;
+
        pci_cleanup_aer_uncorrect_error_status(pdev);
 }
 
index c482220f7eed4fc0530ef41c4ea9c524597b4059..a65dd95507c6f6a012189a5a5447c6f54fbfdca1 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.01-k8"
+#define QLA2XXX_VERSION      "8.03.01-k9"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   3
index 3058bb1aff9599b15a165a20e9be8dab77e78d88..fd7b15be7640fa8d5b89c616f76a849606704445 100644 (file)
@@ -623,6 +623,11 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
                }
                break;
        case INQUIRY:
+               if (lun >= host->max_lun) {
+                       cmd->result = DID_NO_CONNECT << 16;
+                       done(cmd);
+                       return 0;
+               }
                if (id != host->max_id - 1)
                        break;
                if (!lun && !cmd->device->channel &&
index 409ca9643528b6d52a0906afdd97b3cbcf158a9b..a3a7f893817516aacbfa0da8e4aecf727c671932 100644 (file)
@@ -139,8 +139,6 @@ static int omapbl_probe(struct platform_device *pdev)
        if (!pdata)
                return -ENXIO;
 
-       omapbl_ops.check_fb = pdata->check_fb;
-
        bl = kzalloc(sizeof(struct omap_backlight), GFP_KERNEL);
        if (unlikely(!bl))
                return -ENOMEM;
index 415858b421b3591df40f1336e7080fba7e47bbe0..825b665245bbd8cbc6aa9f6a5575982d734e9f2d 100644 (file)
@@ -1221,9 +1221,9 @@ static void setup_smart_timing(struct pxafb_info *fbi,
 static int pxafb_smart_thread(void *arg)
 {
        struct pxafb_info *fbi = arg;
-       struct pxafb_mach_info *inf;
+       struct pxafb_mach_info *inf = fbi->dev->platform_data;
 
-       if (!fbi || !fbi->dev->platform_data->smart_update) {
+       if (!inf->smart_update) {
                pr_err("%s: not properly initialized, thread terminated\n",
                                __func__);
                return -EINVAL;
index 7dc85997e96c36c51eb8a3319a706224031b3ebd..c57d9ce5ff7ef85605786fc26200b3fe76df93df 100644 (file)
@@ -170,6 +170,9 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
        unsigned long stack_size, entryaddr;
 #ifdef ELF_FDPIC_PLAT_INIT
        unsigned long dynaddr;
+#endif
+#ifndef CONFIG_MMU
+       unsigned long stack_prot;
 #endif
        struct file *interpreter = NULL; /* to shut gcc up */
        char *interpreter_name = NULL;
@@ -316,6 +319,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
         * defunct, deceased, etc. after this point we have to exit via
         * error_kill */
        set_personality(PER_LINUX_FDPIC);
+       if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
+               current->personality |= READ_IMPLIES_EXEC;
        set_binfmt(&elf_fdpic_format);
 
        current->mm->start_code = 0;
@@ -377,9 +382,13 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
        if (stack_size < PAGE_SIZE * 2)
                stack_size = PAGE_SIZE * 2;
 
+       stack_prot = PROT_READ | PROT_WRITE;
+       if (executable_stack == EXSTACK_ENABLE_X ||
+           (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
+               stack_prot |= PROT_EXEC;
+
        down_write(&current->mm->mmap_sem);
-       current->mm->start_brk = do_mmap(NULL, 0, stack_size,
-                                        PROT_READ | PROT_WRITE | PROT_EXEC,
+       current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot,
                                         MAP_PRIVATE | MAP_ANONYMOUS |
                                         MAP_UNINITIALIZED | MAP_GROWSDOWN,
                                         0);
index 094ea65afc85354f029a2c3be38d01b684441156..7b2600b380d7c74f4aa398378012cf1e8bccfed7 100644 (file)
@@ -5,7 +5,9 @@ have duplicated data). Fix oops in cifs_lookup. Workaround problem
 mounting to OS/400 Netserve. Fix oops in cifs_get_tcp_session.
 Disable use of server inode numbers when server only
 partially supports them (e.g. for one server querying inode numbers on
-FindFirst fails but QPathInfo queries works).
+FindFirst fails but QPathInfo queries works). Fix oops with dfs in 
+cifs_put_smb_ses. Fix mmap to work on directio mounts (needed
+for OpenOffice when on forcedirectio mount e.g.)
 
 Version 1.60
 -------------
index 29f1da761bbf10fc948f16e0c77a0d75dea22125..8c6a03627176bbce7dd94641455111a736b78458 100644 (file)
@@ -758,7 +758,7 @@ const struct file_operations cifs_file_ops = {
 };
 
 const struct file_operations cifs_file_direct_ops = {
-       /* no mmap, no aio, no readv -
+       /* no aio, no readv -
           BB reevaluate whether they can be done with directio, no cache */
        .read = cifs_user_read,
        .write = cifs_user_write,
@@ -767,6 +767,7 @@ const struct file_operations cifs_file_direct_ops = {
        .lock = cifs_lock,
        .fsync = cifs_fsync,
        .flush = cifs_flush,
+       .mmap = cifs_file_mmap,
        .splice_read = generic_file_splice_read,
 #ifdef CONFIG_CIFS_POSIX
        .unlocked_ioctl  = cifs_ioctl,
index 63ea83ff687f7664b7205038cebdcb6184b831e8..3bbcaa716b3c7afb18ee5826261ed11e5cb32aed 100644 (file)
@@ -2287,12 +2287,12 @@ int
 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                char *mount_data_global, const char *devname)
 {
-       int rc = 0;
+       int rc;
        int xid;
        struct smb_vol *volume_info;
-       struct cifsSesInfo *pSesInfo = NULL;
-       struct cifsTconInfo *tcon = NULL;
-       struct TCP_Server_Info *srvTcp = NULL;
+       struct cifsSesInfo *pSesInfo;
+       struct cifsTconInfo *tcon;
+       struct TCP_Server_Info *srvTcp;
        char   *full_path;
        char *mount_data = mount_data_global;
 #ifdef CONFIG_CIFS_DFS_UPCALL
@@ -2301,6 +2301,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
        int referral_walks_count = 0;
 try_mount_again:
 #endif
+       rc = 0;
+       tcon = NULL;
+       pSesInfo = NULL;
+       srvTcp = NULL;
        full_path = NULL;
 
        xid = GetXid();
@@ -2597,6 +2601,7 @@ remote_path_check:
 
                        cleanup_volume_info(&volume_info);
                        referral_walks_count++;
+                       FreeXid(xid);
                        goto try_mount_again;
                }
 #else /* No DFS support, return error on mount */
index 698a8636d39c5895e76e8ce4c15d9305d899ae00..2afbcebeda718efa2e468d0ff03ee96cd5e10267 100644 (file)
@@ -738,13 +738,28 @@ static int exofs_write_begin_export(struct file *file,
                                        fsdata);
 }
 
+static int exofs_write_end(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned copied,
+                       struct page *page, void *fsdata)
+{
+       struct inode *inode = mapping->host;
+       /* According to comment in simple_write_end i_mutex is held */
+       loff_t i_size = inode->i_size;
+       int ret;
+
+       ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata);
+       if (i_size != inode->i_size)
+               mark_inode_dirty(inode);
+       return ret;
+}
+
 const struct address_space_operations exofs_aops = {
        .readpage       = exofs_readpage,
        .readpages      = exofs_readpages,
        .writepage      = exofs_writepage,
        .writepages     = exofs_writepages,
        .write_begin    = exofs_write_begin_export,
-       .write_end      = simple_write_end,
+       .write_end      = exofs_write_end,
 };
 
 /******************************************************************************
index 423033addd1fef0deb5fd7eb04339ecabc19ee2b..c52e9888b8ab4cea10499512f65a60ed94c5d0e7 100644 (file)
 #ifndef __EXOFS_PNFS_H__
 #define __EXOFS_PNFS_H__
 
-#if defined(CONFIG_PNFS)
-
-
-/* FIXME: move this file to: linux/exportfs/pnfs_osd_xdr.h */
-#include "../nfs/objlayout/pnfs_osd_xdr.h"
-
-#else /* defined(CONFIG_PNFS) */
+#if ! defined(__PNFS_OSD_XDR_H__)
 
 enum pnfs_iomode {
        IOMODE_READ = 1,
@@ -46,6 +40,6 @@ struct pnfs_osd_data_map {
        u32     odm_raid_algorithm;
 };
 
-#endif /* else defined(CONFIG_PNFS) */
+#endif /* ! defined(__PNFS_OSD_XDR_H__) */
 
 #endif /* __EXOFS_PNFS_H__ */
index 9acf7e808139d3df688da7d66ffb33b5cf081d8e..9ed1bb1f319f381b700a6386a4d8d068d04e0fdf 100644 (file)
@@ -28,6 +28,7 @@ config EXT4_FS
 
 config EXT4_USE_FOR_EXT23
        bool "Use ext4 for ext2/ext3 file systems"
+       depends on EXT4_FS
        depends on EXT3_FS=n || EXT2_FS=n
        default y
        help
index 4df8621ec31cff1f5c8eef0211942750b92fd009..a60ab9aad57d4f5807adb72b702042056132e08a 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/swap.h>
 #include <linux/pagemap.h>
-#include <linux/version.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
 #include "ext4.h"
index 56f9271ee8cce5bed485e539f6f7b4e7cdaeb8c4..af7b62699ea94d3aa1ca358869dc32e2b3ba1eb7 100644 (file)
@@ -699,6 +699,8 @@ struct ext4_inode_info {
        unsigned int i_reserved_meta_blocks;
        unsigned int i_allocated_meta_blocks;
        unsigned short i_delalloc_reserved_flag;
+       sector_t i_da_metadata_calc_last_lblock;
+       int i_da_metadata_calc_len;
 
        /* on-disk additional length */
        __u16 i_extra_isize;
index 2ca686454e875c976ff969d5ecf7e437d0dadd40..bdb6ce7e2eb48d08c1bf006e28fdc7b27a8651dd 100644 (file)
@@ -225,7 +225,8 @@ static inline void ext4_ext_mark_initialized(struct ext4_extent *ext)
        ext->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ext));
 }
 
-extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks);
+extern int ext4_ext_calc_metadata_amount(struct inode *inode,
+                                        sector_t lblocks);
 extern ext4_fsblk_t ext_pblock(struct ext4_extent *ex);
 extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
 extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
index 3a7928f825e45f8fb244587cbe7c8921f6a3269b..7d7b74e9468757a241959fd9903d7e5951ab5843 100644 (file)
@@ -296,29 +296,44 @@ static inline int ext4_ext_space_root_idx(struct inode *inode, int check)
  * to allocate @blocks
  * Worse case is one block per extent
  */
-int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks)
+int ext4_ext_calc_metadata_amount(struct inode *inode, sector_t lblock)
 {
-       int lcap, icap, rcap, leafs, idxs, num;
-       int newextents = blocks;
-
-       rcap = ext4_ext_space_root_idx(inode, 0);
-       lcap = ext4_ext_space_block(inode, 0);
-       icap = ext4_ext_space_block_idx(inode, 0);
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       int idxs, num = 0;
 
-       /* number of new leaf blocks needed */
-       num = leafs = (newextents + lcap - 1) / lcap;
+       idxs = ((inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
+               / sizeof(struct ext4_extent_idx));
 
        /*
-        * Worse case, we need separate index block(s)
-        * to link all new leaf blocks
+        * If the new delayed allocation block is contiguous with the
+        * previous da block, it can share index blocks with the
+        * previous block, so we only need to allocate a new index
+        * block every idxs leaf blocks.  At ldxs**2 blocks, we need
+        * an additional index block, and at ldxs**3 blocks, yet
+        * another index blocks.
         */
-       idxs = (leafs + icap - 1) / icap;
-       do {
-               num += idxs;
-               idxs = (idxs + icap - 1) / icap;
-       } while (idxs > rcap);
+       if (ei->i_da_metadata_calc_len &&
+           ei->i_da_metadata_calc_last_lblock+1 == lblock) {
+               if ((ei->i_da_metadata_calc_len % idxs) == 0)
+                       num++;
+               if ((ei->i_da_metadata_calc_len % (idxs*idxs)) == 0)
+                       num++;
+               if ((ei->i_da_metadata_calc_len % (idxs*idxs*idxs)) == 0) {
+                       num++;
+                       ei->i_da_metadata_calc_len = 0;
+               } else
+                       ei->i_da_metadata_calc_len++;
+               ei->i_da_metadata_calc_last_lblock++;
+               return num;
+       }
 
-       return num;
+       /*
+        * In the worst case we need a new set of index blocks at
+        * every level of the inode's extent tree.
+        */
+       ei->i_da_metadata_calc_len = 1;
+       ei->i_da_metadata_calc_last_lblock = lblock;
+       return ext_depth(inode) + 1;
 }
 
 static int
@@ -3023,6 +3038,14 @@ out:
        return err;
 }
 
+static void unmap_underlying_metadata_blocks(struct block_device *bdev,
+                       sector_t block, int count)
+{
+       int i;
+       for (i = 0; i < count; i++)
+                unmap_underlying_metadata(bdev, block + i);
+}
+
 static int
 ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
                        ext4_lblk_t iblock, unsigned int max_blocks,
@@ -3098,6 +3121,18 @@ out:
        } else
                allocated = ret;
        set_buffer_new(bh_result);
+       /*
+        * if we allocated more blocks than requested
+        * we need to make sure we unmap the extra block
+        * allocated. The actual needed block will get
+        * unmapped later when we find the buffer_head marked
+        * new.
+        */
+       if (allocated > max_blocks) {
+               unmap_underlying_metadata_blocks(inode->i_sb->s_bdev,
+                                       newblock + max_blocks,
+                                       allocated - max_blocks);
+       }
 map_out:
        set_buffer_mapped(bh_result);
 out1:
@@ -3190,7 +3225,13 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
         * this situation is possible, though, _during_ tree modification;
         * this is why assert can't be put in ext4_ext_find_extent()
         */
-       BUG_ON(path[depth].p_ext == NULL && depth != 0);
+       if (path[depth].p_ext == NULL && depth != 0) {
+               ext4_error(inode->i_sb, __func__, "bad extent address "
+                          "inode: %lu, iblock: %d, depth: %d",
+                          inode->i_ino, iblock, depth);
+               err = -EIO;
+               goto out2;
+       }
        eh = path[depth].p_hdr;
 
        ex = path[depth].p_ext;
index 0b22497d92e1b079e2eb10c22eb7a6ce6f546153..98bd140aad01148b07a85d2ca7ee59b97c1ac8c4 100644 (file)
@@ -88,9 +88,21 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
                return ext4_force_commit(inode->i_sb);
 
        commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
-       if (jbd2_log_start_commit(journal, commit_tid))
+       if (jbd2_log_start_commit(journal, commit_tid)) {
+               /*
+                * When the journal is on a different device than the
+                * fs data disk, we need to issue the barrier in
+                * writeback mode.  (In ordered mode, the jbd2 layer
+                * will take care of issuing the barrier.  In
+                * data=journal, all of the data blocks are written to
+                * the journal device.)
+                */
+               if (ext4_should_writeback_data(inode) &&
+                   (journal->j_fs_dev != journal->j_dev) &&
+                   (journal->j_flags & JBD2_BARRIER))
+                       blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
                jbd2_log_wait_commit(journal, commit_tid);
-       else if (journal->j_flags & JBD2_BARRIER)
+       else if (journal->j_flags & JBD2_BARRIER)
                blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
        return ret;
 }
index ab807963a61494f2aca5bae2f01ec364fec20a7a..c818972c830231fe6ae3ec47b09f6c23b35481b9 100644 (file)
@@ -1009,77 +1009,88 @@ qsize_t *ext4_get_reserved_space(struct inode *inode)
        return &EXT4_I(inode)->i_reserved_quota;
 }
 #endif
+
 /*
  * Calculate the number of metadata blocks need to reserve
- * to allocate @blocks for non extent file based file
+ * to allocate a new block at @lblocks for non extent file based file
  */
-static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks)
+static int ext4_indirect_calc_metadata_amount(struct inode *inode,
+                                             sector_t lblock)
 {
-       int icap = EXT4_ADDR_PER_BLOCK(inode->i_sb);
-       int ind_blks, dind_blks, tind_blks;
-
-       /* number of new indirect blocks needed */
-       ind_blks = (blocks + icap - 1) / icap;
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       int dind_mask = EXT4_ADDR_PER_BLOCK(inode->i_sb) - 1;
+       int blk_bits;
 
-       dind_blks = (ind_blks + icap - 1) / icap;
+       if (lblock < EXT4_NDIR_BLOCKS)
+               return 0;
 
-       tind_blks = 1;
+       lblock -= EXT4_NDIR_BLOCKS;
 
-       return ind_blks + dind_blks + tind_blks;
+       if (ei->i_da_metadata_calc_len &&
+           (lblock & dind_mask) == ei->i_da_metadata_calc_last_lblock) {
+               ei->i_da_metadata_calc_len++;
+               return 0;
+       }
+       ei->i_da_metadata_calc_last_lblock = lblock & dind_mask;
+       ei->i_da_metadata_calc_len = 1;
+       blk_bits = roundup_pow_of_two(lblock + 1);
+       return (blk_bits / EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb)) + 1;
 }
 
 /*
  * Calculate the number of metadata blocks need to reserve
- * to allocate given number of blocks
+ * to allocate a block located at @lblock
  */
-static int ext4_calc_metadata_amount(struct inode *inode, int blocks)
+static int ext4_calc_metadata_amount(struct inode *inode, sector_t lblock)
 {
-       if (!blocks)
-               return 0;
-
        if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
-               return ext4_ext_calc_metadata_amount(inode, blocks);
+               return ext4_ext_calc_metadata_amount(inode, lblock);
 
-       return ext4_indirect_calc_metadata_amount(inode, blocks);
+       return ext4_indirect_calc_metadata_amount(inode, lblock);
 }
 
+/*
+ * Called with i_data_sem down, which is important since we can call
+ * ext4_discard_preallocations() from here.
+ */
 static void ext4_da_update_reserve_space(struct inode *inode, int used)
 {
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-       int total, mdb, mdb_free, mdb_claim = 0;
-
-       spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
-       /* recalculate the number of metablocks still need to be reserved */
-       total = EXT4_I(inode)->i_reserved_data_blocks - used;
-       mdb = ext4_calc_metadata_amount(inode, total);
-
-       /* figure out how many metablocks to release */
-       BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
-       mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb;
-
-       if (mdb_free) {
-               /* Account for allocated meta_blocks */
-               mdb_claim = EXT4_I(inode)->i_allocated_meta_blocks;
-               BUG_ON(mdb_free < mdb_claim);
-               mdb_free -= mdb_claim;
-
-               /* update fs dirty blocks counter */
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       int mdb_free = 0;
+
+       spin_lock(&ei->i_block_reservation_lock);
+       if (unlikely(used > ei->i_reserved_data_blocks)) {
+               ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, used %d "
+                        "with only %d reserved data blocks\n",
+                        __func__, inode->i_ino, used,
+                        ei->i_reserved_data_blocks);
+               WARN_ON(1);
+               used = ei->i_reserved_data_blocks;
+       }
+
+       /* Update per-inode reservations */
+       ei->i_reserved_data_blocks -= used;
+       used += ei->i_allocated_meta_blocks;
+       ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks;
+       ei->i_allocated_meta_blocks = 0;
+       percpu_counter_sub(&sbi->s_dirtyblocks_counter, used);
+
+       if (ei->i_reserved_data_blocks == 0) {
+               /*
+                * We can release all of the reserved metadata blocks
+                * only when we have written all of the delayed
+                * allocation blocks.
+                */
+               mdb_free = ei->i_reserved_meta_blocks;
+               ei->i_reserved_meta_blocks = 0;
+               ei->i_da_metadata_calc_len = 0;
                percpu_counter_sub(&sbi->s_dirtyblocks_counter, mdb_free);
-               EXT4_I(inode)->i_allocated_meta_blocks = 0;
-               EXT4_I(inode)->i_reserved_meta_blocks = mdb;
        }
-
-       /* update per-inode reservations */
-       BUG_ON(used  > EXT4_I(inode)->i_reserved_data_blocks);
-       EXT4_I(inode)->i_reserved_data_blocks -= used;
-       percpu_counter_sub(&sbi->s_dirtyblocks_counter, used + mdb_claim);
        spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 
-       vfs_dq_claim_block(inode, used + mdb_claim);
-
-       /*
-        * free those over-booking quota for metadata blocks
-        */
+       /* Update quota subsystem */
+       vfs_dq_claim_block(inode, used);
        if (mdb_free)
                vfs_dq_release_reservation_block(inode, mdb_free);
 
@@ -1088,7 +1099,8 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
         * there aren't any writers on the inode, we can discard the
         * inode's preallocations.
         */
-       if (!total && (atomic_read(&inode->i_writecount) == 0))
+       if ((ei->i_reserved_data_blocks == 0) &&
+           (atomic_read(&inode->i_writecount) == 0))
                ext4_discard_preallocations(inode);
 }
 
@@ -1797,11 +1809,15 @@ static int ext4_journalled_write_end(struct file *file,
        return ret ? ret : copied;
 }
 
-static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
+/*
+ * Reserve a single block located at lblock
+ */
+static int ext4_da_reserve_space(struct inode *inode, sector_t lblock)
 {
        int retries = 0;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-       unsigned long md_needed, mdblocks, total = 0;
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       unsigned long md_needed, md_reserved;
 
        /*
         * recalculate the amount of metadata blocks to reserve
@@ -1809,35 +1825,43 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
         * worse case is one extent per block
         */
 repeat:
-       spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
-       total = EXT4_I(inode)->i_reserved_data_blocks + nrblocks;
-       mdblocks = ext4_calc_metadata_amount(inode, total);
-       BUG_ON(mdblocks < EXT4_I(inode)->i_reserved_meta_blocks);
-
-       md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks;
-       total = md_needed + nrblocks;
-       spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+       spin_lock(&ei->i_block_reservation_lock);
+       md_reserved = ei->i_reserved_meta_blocks;
+       md_needed = ext4_calc_metadata_amount(inode, lblock);
+       spin_unlock(&ei->i_block_reservation_lock);
 
        /*
         * Make quota reservation here to prevent quota overflow
         * later. Real quota accounting is done at pages writeout
         * time.
         */
-       if (vfs_dq_reserve_block(inode, total))
+       if (vfs_dq_reserve_block(inode, md_needed + 1)) {
+               /* 
+                * We tend to badly over-estimate the amount of
+                * metadata blocks which are needed, so if we have
+                * reserved any metadata blocks, try to force out the
+                * inode and see if we have any better luck.
+                */
+               if (md_reserved && retries++ <= 3)
+                       goto retry;
                return -EDQUOT;
+       }
 
-       if (ext4_claim_free_blocks(sbi, total)) {
-               vfs_dq_release_reservation_block(inode, total);
+       if (ext4_claim_free_blocks(sbi, md_needed + 1)) {
+               vfs_dq_release_reservation_block(inode, md_needed + 1);
                if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
+               retry:
+                       if (md_reserved)
+                               write_inode_now(inode, (retries == 3));
                        yield();
                        goto repeat;
                }
                return -ENOSPC;
        }
-       spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
-       EXT4_I(inode)->i_reserved_data_blocks += nrblocks;
-       EXT4_I(inode)->i_reserved_meta_blocks += md_needed;
-       spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+       spin_lock(&ei->i_block_reservation_lock);
+       ei->i_reserved_data_blocks++;
+       ei->i_reserved_meta_blocks += md_needed;
+       spin_unlock(&ei->i_block_reservation_lock);
 
        return 0;       /* success */
 }
@@ -1845,49 +1869,46 @@ repeat:
 static void ext4_da_release_space(struct inode *inode, int to_free)
 {
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-       int total, mdb, mdb_free, release;
+       struct ext4_inode_info *ei = EXT4_I(inode);
 
        if (!to_free)
                return;         /* Nothing to release, exit */
 
        spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
 
-       if (!EXT4_I(inode)->i_reserved_data_blocks) {
+       if (unlikely(to_free > ei->i_reserved_data_blocks)) {
                /*
-                * if there is no reserved blocks, but we try to free some
-                * then the counter is messed up somewhere.
-                * but since this function is called from invalidate
-                * page, it's harmless to return without any action
+                * if there aren't enough reserved blocks, then the
+                * counter is messed up somewhere.  Since this
+                * function is called from invalidate page, it's
+                * harmless to return without any action.
                 */
-               printk(KERN_INFO "ext4 delalloc try to release %d reserved "
-                           "blocks for inode %lu, but there is no reserved "
-                           "data blocks\n", to_free, inode->i_ino);
-               spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
-               return;
+               ext4_msg(inode->i_sb, KERN_NOTICE, "ext4_da_release_space: "
+                        "ino %lu, to_free %d with only %d reserved "
+                        "data blocks\n", inode->i_ino, to_free,
+                        ei->i_reserved_data_blocks);
+               WARN_ON(1);
+               to_free = ei->i_reserved_data_blocks;
        }
+       ei->i_reserved_data_blocks -= to_free;
 
-       /* recalculate the number of metablocks still need to be reserved */
-       total = EXT4_I(inode)->i_reserved_data_blocks - to_free;
-       mdb = ext4_calc_metadata_amount(inode, total);
-
-       /* figure out how many metablocks to release */
-       BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
-       mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb;
-
-       release = to_free + mdb_free;
-
-       /* update fs dirty blocks counter for truncate case */
-       percpu_counter_sub(&sbi->s_dirtyblocks_counter, release);
+       if (ei->i_reserved_data_blocks == 0) {
+               /*
+                * We can release all of the reserved metadata blocks
+                * only when we have written all of the delayed
+                * allocation blocks.
+                */
+               to_free += ei->i_reserved_meta_blocks;
+               ei->i_reserved_meta_blocks = 0;
+               ei->i_da_metadata_calc_len = 0;
+       }
 
-       /* update per-inode reservations */
-       BUG_ON(to_free > EXT4_I(inode)->i_reserved_data_blocks);
-       EXT4_I(inode)->i_reserved_data_blocks -= to_free;
+       /* update fs dirty blocks counter */
+       percpu_counter_sub(&sbi->s_dirtyblocks_counter, to_free);
 
-       BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
-       EXT4_I(inode)->i_reserved_meta_blocks = mdb;
        spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 
-       vfs_dq_release_reservation_block(inode, release);
+       vfs_dq_release_reservation_block(inode, to_free);
 }
 
 static void ext4_da_page_release_reservation(struct page *page,
@@ -2493,7 +2514,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
                 * XXX: __block_prepare_write() unmaps passed block,
                 * is it OK?
                 */
-               ret = ext4_da_reserve_space(inode, 1);
+               ret = ext4_da_reserve_space(inode, iblock);
                if (ret)
                        /* not enough space to reserve */
                        return ret;
@@ -2967,8 +2988,7 @@ retry:
 out_writepages:
        if (!no_nrwrite_index_update)
                wbc->no_nrwrite_index_update = 0;
-       if (wbc->nr_to_write > nr_to_writebump)
-               wbc->nr_to_write -= nr_to_writebump;
+       wbc->nr_to_write -= nr_to_writebump;
        wbc->range_start = range_start;
        trace_ext4_da_writepages_result(inode, wbc, ret, pages_written);
        return ret;
@@ -2993,11 +3013,18 @@ static int ext4_nonda_switch(struct super_block *sb)
        if (2 * free_blocks < 3 * dirty_blocks ||
                free_blocks < (dirty_blocks + EXT4_FREEBLOCKS_WATERMARK)) {
                /*
-                * free block count is less that 150% of dirty blocks
-                * or free blocks is less that watermark
+                * free block count is less than 150% of dirty blocks
+                * or free blocks is less than watermark
                 */
                return 1;
        }
+       /*
+        * Even if we don't switch but are nearing capacity,
+        * start pushing delalloc when 1/2 of free blocks are dirty.
+        */
+       if (free_blocks < 2 * dirty_blocks)
+               writeback_inodes_sb_if_idle(sb);
+
        return 0;
 }
 
index 0ca811061bc72eca18b46ca025b660f32ce87138..436521cae45662629d02871d5ff8429aee92065b 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/proc_fs.h>
 #include <linux/pagemap.h>
 #include <linux/seq_file.h>
-#include <linux/version.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
 #include "ext4_jbd2.h"
index 6ed9aa91f27d1d51609b797717ff17882c4ab579..735c20d5fd56565dcb53adbf2726acb9cc79fe8c 100644 (file)
@@ -702,6 +702,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        ei->i_reserved_data_blocks = 0;
        ei->i_reserved_meta_blocks = 0;
        ei->i_allocated_meta_blocks = 0;
+       ei->i_da_metadata_calc_len = 0;
        ei->i_delalloc_reserved_flag = 0;
        spin_lock_init(&(ei->i_block_reservation_lock));
 #ifdef CONFIG_QUOTA
@@ -2174,9 +2175,9 @@ static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a,
        struct super_block *sb = sbi->s_buddy_cache->i_sb;
 
        return snprintf(buf, PAGE_SIZE, "%llu\n",
-                       sbi->s_kbytes_written + 
+                       (unsigned long long)(sbi->s_kbytes_written +
                        ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
-                         EXT4_SB(sb)->s_sectors_written_start) >> 1));
+                         EXT4_SB(sb)->s_sectors_written_start) >> 1)));
 }
 
 static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
@@ -4005,6 +4006,7 @@ static inline void unregister_as_ext2(void)
 {
        unregister_filesystem(&ext2_fs_type);
 }
+MODULE_ALIAS("ext2");
 #else
 static inline void register_as_ext2(void) { }
 static inline void unregister_as_ext2(void) { }
@@ -4031,6 +4033,7 @@ static inline void unregister_as_ext3(void)
 {
        unregister_filesystem(&ext3_fs_type);
 }
+MODULE_ALIAS("ext3");
 #else
 static inline void register_as_ext3(void) { }
 static inline void unregister_as_ext3(void) { }
index 83218bebbc7cf8bc0d6251b57fbf33ecd33f7800..f3a2f7ed45aabc13e3ea4a28fc9baa098131cbb4 100644 (file)
@@ -1332,6 +1332,8 @@ retry:
                        goto cleanup;
                kfree(b_entry_name);
                kfree(buffer);
+               b_entry_name = NULL;
+               buffer = NULL;
                brelse(is->iloc.bh);
                kfree(is);
                kfree(bs);
index 49bc1b8e8f1945f1a282f162cd00037a5cefcbb9..1a7c42c64ff47ee7e55c378d0e067892d789e2d7 100644 (file)
@@ -242,6 +242,7 @@ static void bdi_sync_writeback(struct backing_dev_info *bdi,
 /**
  * bdi_start_writeback - start writeback
  * @bdi: the backing device to write from
+ * @sb: write inodes from this super_block
  * @nr_pages: the number of pages to write
  *
  * Description:
@@ -1186,6 +1187,23 @@ void writeback_inodes_sb(struct super_block *sb)
 }
 EXPORT_SYMBOL(writeback_inodes_sb);
 
+/**
+ * writeback_inodes_sb_if_idle -       start writeback if none underway
+ * @sb: the superblock
+ *
+ * Invoke writeback_inodes_sb if no writeback is currently underway.
+ * Returns 1 if writeback was started, 0 if not.
+ */
+int writeback_inodes_sb_if_idle(struct super_block *sb)
+{
+       if (!writeback_in_progress(sb->s_bdi)) {
+               writeback_inodes_sb(sb);
+               return 1;
+       } else
+               return 0;
+}
+EXPORT_SYMBOL(writeback_inodes_sb_if_idle);
+
 /**
  * sync_inodes_sb      -       sync sb inode pages
  * @sb: the superblock
index 4eb308aa32342f0f51eb00cafefda3ecbb6ada17..a6abbae8a278cefb0ae39fe4553341a5ce85ebef 100644 (file)
@@ -569,6 +569,40 @@ static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync)
        return ret;
 }
 
+/**
+ * gfs2_file_aio_write - Perform a write to a file
+ * @iocb: The io context
+ * @iov: The data to write
+ * @nr_segs: Number of @iov segments
+ * @pos: The file position
+ *
+ * We have to do a lock/unlock here to refresh the inode size for
+ * O_APPEND writes, otherwise we can land up writing at the wrong
+ * offset. There is still a race, but provided the app is using its
+ * own file locking, this will make O_APPEND work as expected.
+ *
+ */
+
+static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                                  unsigned long nr_segs, loff_t pos)
+{
+       struct file *file = iocb->ki_filp;
+
+       if (file->f_flags & O_APPEND) {
+               struct dentry *dentry = file->f_dentry;
+               struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
+               struct gfs2_holder gh;
+               int ret;
+
+               ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
+               if (ret)
+                       return ret;
+               gfs2_glock_dq_uninit(&gh);
+       }
+
+       return generic_file_aio_write(iocb, iov, nr_segs, pos);
+}
+
 #ifdef CONFIG_GFS2_FS_LOCKING_DLM
 
 /**
@@ -711,7 +745,7 @@ const struct file_operations gfs2_file_fops = {
        .read           = do_sync_read,
        .aio_read       = generic_file_aio_read,
        .write          = do_sync_write,
-       .aio_write      = generic_file_aio_write,
+       .aio_write      = gfs2_file_aio_write,
        .unlocked_ioctl = gfs2_ioctl,
        .mmap           = gfs2_mmap,
        .open           = gfs2_open,
@@ -741,7 +775,7 @@ const struct file_operations gfs2_file_fops_nolock = {
        .read           = do_sync_read,
        .aio_read       = generic_file_aio_read,
        .write          = do_sync_write,
-       .aio_write      = generic_file_aio_write,
+       .aio_write      = gfs2_file_aio_write,
        .unlocked_ioctl = gfs2_ioctl,
        .mmap           = gfs2_mmap,
        .open           = gfs2_open,
index cb8d7a93d5ec257204c93aac033c95146fdd1a07..6f68a5f18eb8ccdb0c2b85744def9f9476c77af0 100644 (file)
@@ -121,7 +121,7 @@ struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp)
        if (aspace) {
                mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS);
                aspace->i_mapping->a_ops = &aspace_aops;
-               aspace->i_size = ~0ULL;
+               aspace->i_size = MAX_LFS_FILESIZE;
                ip = GFS2_I(aspace);
                clear_bit(GIF_USER, &ip->i_flags);
                insert_inode_hash(aspace);
index 247436c10deb853a35f4daf7db90cf18de96099a..78f73ca1ef3e8ac9ce5af97b43eccec7e8f7be68 100644 (file)
@@ -748,7 +748,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
        struct gfs2_rgrpd *nrgd;
        unsigned int num_gh;
        int dir_rename = 0;
-       int alloc_required;
+       int alloc_required = 0;
        unsigned int x;
        int error;
 
@@ -867,7 +867,9 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                        goto out_gunlock;
        }
 
-       alloc_required = error = gfs2_diradd_alloc_required(ndir, &ndentry->d_name);
+       if (nip == NULL)
+               alloc_required = gfs2_diradd_alloc_required(ndir, &ndentry->d_name);
+       error = alloc_required;
        if (error < 0)
                goto out_gunlock;
        error = 0;
index 8a04108e0c22fff076b8dbae79ad87dab98f8eff..c2ebdf2c01d4fb2d4018e76fe8506d8ce04bd155 100644 (file)
@@ -1296,6 +1296,7 @@ fail:
 
 int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
 {
+       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_ea_location el;
        struct buffer_head *dibh;
        int error;
@@ -1305,16 +1306,17 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
                return error;
 
        if (GFS2_EA_IS_STUFFED(el.el_ea)) {
-               error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0);
-               if (error)
-                       return error;
-
-               gfs2_trans_add_bh(ip->i_gl, el.el_bh, 1);
-               memcpy(GFS2_EA2DATA(el.el_ea), data,
-                      GFS2_EA_DATA_LEN(el.el_ea));
-       } else
+               error = gfs2_trans_begin(sdp, RES_DINODE + RES_EATTR, 0);
+               if (error == 0) {
+                       gfs2_trans_add_bh(ip->i_gl, el.el_bh, 1);
+                       memcpy(GFS2_EA2DATA(el.el_ea), data,
+                              GFS2_EA_DATA_LEN(el.el_ea));
+               }
+       } else {
                error = ea_acl_chmod_unstuffed(ip, el.el_ea, data);
+       }
 
+       brelse(el.el_bh);
        if (error)
                return error;
 
@@ -1327,8 +1329,7 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
                brelse(dibh);
        }
 
-       gfs2_trans_end(GFS2_SB(&ip->i_inode));
-
+       gfs2_trans_end(sdp);
        return error;
 }
 
index ca0f5eb62b20e450b38ef84b52c64bc2a214bc17..886849370950f462627f0a9d2df692ec4d117d97 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/jbd2.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/blkdev.h>
 #include <trace/events/jbd2.h>
 
 /*
@@ -515,6 +516,20 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
        journal->j_tail_sequence = first_tid;
        journal->j_tail = blocknr;
        spin_unlock(&journal->j_state_lock);
+
+       /*
+        * If there is an external journal, we need to make sure that
+        * any data blocks that were recently written out --- perhaps
+        * by jbd2_log_do_checkpoint() --- are flushed out before we
+        * drop the transactions from the external journal.  It's
+        * unlikely this will be necessary, especially with a
+        * appropriately sized journal, but we need this to guarantee
+        * correctness.  Fortunately jbd2_cleanup_journal_tail()
+        * doesn't get called all that often.
+        */
+       if ((journal->j_fs_dev != journal->j_dev) &&
+           (journal->j_flags & JBD2_BARRIER))
+               blkdev_issue_flush(journal->j_fs_dev, NULL);
        if (!(journal->j_flags & JBD2_ABORT))
                jbd2_journal_update_superblock(journal, 1);
        return 0;
index 6a10238d2c63d3f7c7945d1d6cbe6a4adcb57d04..1bc74b6f26d2cbb9d159f9f49aef102fa7dda30e 100644 (file)
@@ -259,6 +259,7 @@ static int journal_submit_data_buffers(journal_t *journal,
                        ret = err;
                spin_lock(&journal->j_list_lock);
                J_ASSERT(jinode->i_transaction == commit_transaction);
+               commit_transaction->t_flushed_data_blocks = 1;
                jinode->i_flags &= ~JI_COMMIT_RUNNING;
                wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING);
        }
@@ -708,8 +709,17 @@ start_journal_io:
                }
        }
 
-       /* Done it all: now write the commit record asynchronously. */
+       /* 
+        * If the journal is not located on the file system device,
+        * then we must flush the file system device before we issue
+        * the commit record
+        */
+       if (commit_transaction->t_flushed_data_blocks &&
+           (journal->j_fs_dev != journal->j_dev) &&
+           (journal->j_flags & JBD2_BARRIER))
+               blkdev_issue_flush(journal->j_fs_dev, NULL);
 
+       /* Done it all: now write the commit record asynchronously. */
        if (JBD2_HAS_INCOMPAT_FEATURE(journal,
                                      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
                err = journal_submit_commit_record(journal, commit_transaction,
@@ -720,13 +730,6 @@ start_journal_io:
                        blkdev_issue_flush(journal->j_dev, NULL);
        }
 
-       /*
-        * This is the right place to wait for data buffers both for ASYNC
-        * and !ASYNC commit. If commit is ASYNC, we need to wait only after
-        * the commit block went to disk (which happens above). If commit is
-        * SYNC, we need to wait for data buffers before we start writing
-        * commit block, which happens below in such setting.
-        */
        err = journal_finish_inode_data_buffers(journal, commit_transaction);
        if (err) {
                printk(KERN_WARNING
index 17af879e6e9ec157528f3bcab4ad7c01436abc68..ac0d027595d00bf28e55f00b040d26e295023602 100644 (file)
@@ -814,7 +814,7 @@ static journal_t * journal_init_common (void)
        journal_t *journal;
        int err;
 
-       journal = kzalloc(sizeof(*journal), GFP_KERNEL|__GFP_NOFAIL);
+       journal = kzalloc(sizeof(*journal), GFP_KERNEL);
        if (!journal)
                goto fail;
 
index 68921d9b53020d16e12021ede6188e5e642830a7..b55440baf7ab832e9d05ae8fdddc2337da57b5ed 100644 (file)
@@ -232,6 +232,7 @@ int generic_permission(struct inode *inode, int mask,
        /*
         * Searching includes executable on directories, else just read.
         */
+       mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
        if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
                if (capable(CAP_DAC_READ_SEARCH))
                        return 0;
index 2c5ace4f00a7ffecfcf41c21e512833ef70d426b..3c7f03b669fb62a7a9158b8d699a24249e51c66d 100644 (file)
@@ -1615,6 +1615,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                                goto out;
 
                        new_dentry = dentry;
+                       rehash = NULL;
                        new_inode = NULL;
                }
        }
index 7c2e337d05af58fb2d733a6b688580f40d1221b5..c194793b642b8f5e35175ac52fed9c104606d274 100644 (file)
@@ -780,12 +780,9 @@ static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
        int (*fsync) (struct file *, struct dentry *, int);
        int err;
 
-       err = filemap_fdatawrite(inode->i_mapping);
+       err = filemap_write_and_wait(inode->i_mapping);
        if (err == 0 && fop && (fsync = fop->fsync))
                err = fsync(filp, dp, 0);
-       if (err == 0)
-               err = filemap_fdatawait(inode->i_mapping);
-
        return err;
 }
 
index f4a14ea2ed9c3d17f269260affcb82947109ed46..effdbdbe6c117208624c0f03c069d3212fb61e2c 100644 (file)
@@ -417,8 +417,8 @@ __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
 
        key = page_index(bh->b_page) << (PAGE_CACHE_SHIFT -
                                         bmap->b_inode->i_blkbits);
-       for (pbh = page_buffers(bh->b_page); pbh != bh;
-            pbh = pbh->b_this_page, key++);
+       for (pbh = page_buffers(bh->b_page); pbh != bh; pbh = pbh->b_this_page)
+               key++;
 
        return key;
 }
index d5ad54e204a59f45c181990857d6977cc9b5a73b..18737818db63c63875db8a414e7f415a0217f014 100644 (file)
@@ -328,19 +328,24 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile,
                        tnicps += nicps;
                        nilfs_mdt_mark_buffer_dirty(cp_bh);
                        nilfs_mdt_mark_dirty(cpfile);
-                       if (!nilfs_cpfile_is_in_first(cpfile, cno) &&
-                           (count = nilfs_cpfile_block_sub_valid_checkpoints(
-                                   cpfile, cp_bh, kaddr, nicps)) == 0) {
-                               /* make hole */
-                               kunmap_atomic(kaddr, KM_USER0);
-                               brelse(cp_bh);
-                               ret = nilfs_cpfile_delete_checkpoint_block(
-                                       cpfile, cno);
-                               if (ret == 0)
-                                       continue;
-                               printk(KERN_ERR "%s: cannot delete block\n",
-                                      __func__);
-                               break;
+                       if (!nilfs_cpfile_is_in_first(cpfile, cno)) {
+                               count =
+                                 nilfs_cpfile_block_sub_valid_checkpoints(
+                                               cpfile, cp_bh, kaddr, nicps);
+                               if (count == 0) {
+                                       /* make hole */
+                                       kunmap_atomic(kaddr, KM_USER0);
+                                       brelse(cp_bh);
+                                       ret =
+                                         nilfs_cpfile_delete_checkpoint_block(
+                                                                  cpfile, cno);
+                                       if (ret == 0)
+                                               continue;
+                                       printk(KERN_ERR
+                                              "%s: cannot delete block\n",
+                                              __func__);
+                                       break;
+                               }
                        }
                }
 
index d369ac7182772b359bc148bd5dc7d7a30d3285d9..236753df5cdf9db2362494aa44d8b20105cfc5fb 100644 (file)
@@ -51,11 +51,11 @@ static int nilfs_direct_lookup(const struct nilfs_bmap *bmap,
        struct nilfs_direct *direct;
        __u64 ptr;
 
-       direct = (struct nilfs_direct *)bmap;
-       if ((key > NILFS_DIRECT_KEY_MAX) ||
-           (level != 1) ||     /* XXX: use macro for level 1 */
-           ((ptr = nilfs_direct_get_ptr(direct, key)) ==
-            NILFS_BMAP_INVALID_PTR))
+       direct = (struct nilfs_direct *)bmap;  /* XXX: use macro for level 1 */
+       if (key > NILFS_DIRECT_KEY_MAX || level != 1)
+               return -ENOENT;
+       ptr = nilfs_direct_get_ptr(direct, key);
+       if (ptr == NILFS_BMAP_INVALID_PTR)
                return -ENOENT;
 
        if (ptrp != NULL)
@@ -73,9 +73,10 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *bmap,
        sector_t blocknr;
        int ret, cnt;
 
-       if (key > NILFS_DIRECT_KEY_MAX ||
-           (ptr = nilfs_direct_get_ptr(direct, key)) ==
-           NILFS_BMAP_INVALID_PTR)
+       if (key > NILFS_DIRECT_KEY_MAX)
+               return -ENOENT;
+       ptr = nilfs_direct_get_ptr(direct, key);
+       if (ptr == NILFS_BMAP_INVALID_PTR)
                return -ENOENT;
 
        if (NILFS_BMAP_USE_VBN(bmap)) {
index f6af76042d80fe8f7278bb2fa791fdc7b2551a21..d6b2b83de3633a7401a8f8720de0e6ec5b4568c7 100644 (file)
@@ -480,7 +480,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
                                      unsigned int cmd, void __user *argp)
 {
        struct nilfs_argv argv[5];
-       const static size_t argsz[5] = {
+       static const size_t argsz[5] = {
                sizeof(struct nilfs_vdesc),
                sizeof(struct nilfs_period),
                sizeof(__u64),
index 3d30a1c974a89dbb4429d91d453a1c46d185bb55..06ccf6a86d35ca01a8f80e5a997a30ea8820f30a 100644 (file)
@@ -1772,7 +1772,8 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
                                         loff_t *ppos,
                                         size_t count,
                                         int appending,
-                                        int *direct_io)
+                                        int *direct_io,
+                                        int *has_refcount)
 {
        int ret = 0, meta_level = 0;
        struct inode *inode = dentry->d_inode;
@@ -1833,6 +1834,8 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
                                                               saved_pos,
                                                               count,
                                                               &meta_level);
+                       if (has_refcount)
+                               *has_refcount = 1;
                }
 
                if (ret < 0) {
@@ -1856,6 +1859,10 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
                        break;
                }
 
+               if (has_refcount && *has_refcount == 1) {
+                       *direct_io = 0;
+                       break;
+               }
                /*
                 * Allowing concurrent direct writes means
                 * i_size changes wouldn't be synchronized, so
@@ -1899,7 +1906,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
                                    loff_t pos)
 {
        int ret, direct_io, appending, rw_level, have_alloc_sem  = 0;
-       int can_do_direct;
+       int can_do_direct, has_refcount = 0;
        ssize_t written = 0;
        size_t ocount;          /* original count */
        size_t count;           /* after file limit checks */
@@ -1942,7 +1949,7 @@ relock:
        can_do_direct = direct_io;
        ret = ocfs2_prepare_inode_for_write(file->f_path.dentry, ppos,
                                            iocb->ki_left, appending,
-                                           &can_do_direct);
+                                           &can_do_direct, &has_refcount);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
@@ -2006,14 +2013,16 @@ out_dio:
        /* buffered aio wouldn't have proper lock coverage today */
        BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
 
-       if ((file->f_flags & O_DSYNC && !direct_io) || IS_SYNC(inode)) {
+       if ((file->f_flags & O_DSYNC && !direct_io) || IS_SYNC(inode) ||
+           (file->f_flags & O_DIRECT && has_refcount)) {
                ret = filemap_fdatawrite_range(file->f_mapping, pos,
                                               pos + count - 1);
                if (ret < 0)
                        written = ret;
 
                if (!ret && (old_size != i_size_read(inode) ||
-                   old_clusters != OCFS2_I(inode)->ip_clusters)) {
+                   old_clusters != OCFS2_I(inode)->ip_clusters ||
+                   has_refcount)) {
                        ret = jbd2_journal_force_commit(osb->journal->j_journal);
                        if (ret < 0)
                                written = ret;
@@ -2062,7 +2071,7 @@ static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
        int ret;
 
        ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, &sd->pos,
-                                           sd->total_len, 0, NULL);
+                                           sd->total_len, 0, NULL, NULL);
        if (ret < 0) {
                mlog_errno(ret);
                return ret;
index f560325c444f0c10e6258ce7c5d9836c58d703b9..13b5d07081751e1cb42aca4ce491c9a52b70ab4f 100644 (file)
@@ -327,94 +327,6 @@ static inline void task_context_switch_counts(struct seq_file *m,
                        p->nivcsw);
 }
 
-#ifdef CONFIG_MMU
-
-struct stack_stats {
-       struct vm_area_struct *vma;
-       unsigned long   startpage;
-       unsigned long   usage;
-};
-
-static int stack_usage_pte_range(pmd_t *pmd, unsigned long addr,
-                               unsigned long end, struct mm_walk *walk)
-{
-       struct stack_stats *ss = walk->private;
-       struct vm_area_struct *vma = ss->vma;
-       pte_t *pte, ptent;
-       spinlock_t *ptl;
-       int ret = 0;
-
-       pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-       for (; addr != end; pte++, addr += PAGE_SIZE) {
-               ptent = *pte;
-
-#ifdef CONFIG_STACK_GROWSUP
-               if (pte_present(ptent) || is_swap_pte(ptent))
-                       ss->usage = addr - ss->startpage + PAGE_SIZE;
-#else
-               if (pte_present(ptent) || is_swap_pte(ptent)) {
-                       ss->usage = ss->startpage - addr + PAGE_SIZE;
-                       pte++;
-                       ret = 1;
-                       break;
-               }
-#endif
-       }
-       pte_unmap_unlock(pte - 1, ptl);
-       cond_resched();
-       return ret;
-}
-
-static inline unsigned long get_stack_usage_in_bytes(struct vm_area_struct *vma,
-                               struct task_struct *task)
-{
-       struct stack_stats ss;
-       struct mm_walk stack_walk = {
-               .pmd_entry = stack_usage_pte_range,
-               .mm = vma->vm_mm,
-               .private = &ss,
-       };
-
-       if (!vma->vm_mm || is_vm_hugetlb_page(vma))
-               return 0;
-
-       ss.vma = vma;
-       ss.startpage = task->stack_start & PAGE_MASK;
-       ss.usage = 0;
-
-#ifdef CONFIG_STACK_GROWSUP
-       walk_page_range(KSTK_ESP(task) & PAGE_MASK, vma->vm_end,
-               &stack_walk);
-#else
-       walk_page_range(vma->vm_start, (KSTK_ESP(task) & PAGE_MASK) + PAGE_SIZE,
-               &stack_walk);
-#endif
-       return ss.usage;
-}
-
-static inline void task_show_stack_usage(struct seq_file *m,
-                                               struct task_struct *task)
-{
-       struct vm_area_struct   *vma;
-       struct mm_struct        *mm = get_task_mm(task);
-
-       if (mm) {
-               down_read(&mm->mmap_sem);
-               vma = find_vma(mm, task->stack_start);
-               if (vma)
-                       seq_printf(m, "Stack usage:\t%lu kB\n",
-                               get_stack_usage_in_bytes(vma, task) >> 10);
-
-               up_read(&mm->mmap_sem);
-               mmput(mm);
-       }
-}
-#else
-static void task_show_stack_usage(struct seq_file *m, struct task_struct *task)
-{
-}
-#endif         /* CONFIG_MMU */
-
 static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
 {
        seq_printf(m, "Cpus_allowed:\t");
@@ -445,7 +357,6 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
        task_show_regs(m, task);
 #endif
        task_context_switch_counts(m, task);
-       task_show_stack_usage(m, task);
        return 0;
 }
 
index 47c03f4336b843ed1ba9a7f28b3f4824e1c663d1..f277c4a111cb7217d6002cceb8a488cce26c468f 100644 (file)
@@ -361,12 +361,11 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                if (!pte_present(ptent))
                        continue;
 
-               mss->resident += PAGE_SIZE;
-
                page = vm_normal_page(vma, addr, ptent);
                if (!page)
                        continue;
 
+               mss->resident += PAGE_SIZE;
                /* Accumulate the size in pages that have been accessed. */
                if (pte_young(ptent) || PageReferenced(page))
                        mss->referenced += PAGE_SIZE;
index dea86abdf2e7fe8ca6589dc0ba22210357a28d01..3fc62b097bedac541f2ada3309932b0953f8bbda 100644 (file)
@@ -1377,6 +1377,9 @@ static void inode_sub_rsv_space(struct inode *inode, qsize_t number)
 static qsize_t inode_get_rsv_space(struct inode *inode)
 {
        qsize_t ret;
+
+       if (!inode->i_sb->dq_op->get_reserved_space)
+               return 0;
        spin_lock(&inode->i_lock);
        ret = *inode_reserved_space(inode);
        spin_unlock(&inode->i_lock);
index 685495707181c7f168ec280e69b72ba3a1bcc230..65c872761177e10d5b074d97800e5245208c9fe1 100644 (file)
@@ -1277,7 +1277,10 @@ int reiserfs_init_bitmap_cache(struct super_block *sb)
        struct reiserfs_bitmap_info *bitmap;
        unsigned int bmap_nr = reiserfs_bmap_count(sb);
 
+       /* Avoid lock recursion in fault case */
+       reiserfs_write_unlock(sb);
        bitmap = vmalloc(sizeof(*bitmap) * bmap_nr);
+       reiserfs_write_lock(sb);
        if (bitmap == NULL)
                return -ENOMEM;
 
index 290ae38fca8ae915c749c287ce3e4a19307d3d89..9087b10209e634c4f694aceaad2e14bde7e01ba2 100644 (file)
@@ -31,11 +31,12 @@ void reiserfs_delete_inode(struct inode *inode)
            JOURNAL_PER_BALANCE_CNT * 2 +
            2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
        struct reiserfs_transaction_handle th;
+       int depth;
        int err;
 
        truncate_inode_pages(&inode->i_data, 0);
 
-       reiserfs_write_lock(inode->i_sb);
+       depth = reiserfs_write_lock_once(inode->i_sb);
 
        /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
        if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) {  /* also handles bad_inode case */
@@ -74,7 +75,7 @@ void reiserfs_delete_inode(struct inode *inode)
       out:
        clear_inode(inode);     /* note this must go after the journal_end to prevent deadlock */
        inode->i_blocks = 0;
-       reiserfs_write_unlock(inode->i_sb);
+       reiserfs_write_unlock_once(inode->i_sb, depth);
 }
 
 static void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid,
@@ -3061,13 +3062,14 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb,
 int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
-       int error;
        unsigned int ia_valid;
+       int depth;
+       int error;
 
        /* must be turned off for recursive notify_change calls */
        ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
 
-       reiserfs_write_lock(inode->i_sb);
+       depth = reiserfs_write_lock_once(inode->i_sb);
        if (attr->ia_valid & ATTR_SIZE) {
                /* version 2 items will be caught by the s_maxbytes check
                 ** done for us in vmtruncate
@@ -3148,8 +3150,17 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                                    journal_end(&th, inode->i_sb, jbegin_count);
                        }
                }
-               if (!error)
+               if (!error) {
+                       /*
+                        * Relax the lock here, as it might truncate the
+                        * inode pages and wait for inode pages locks.
+                        * To release such page lock, the owner needs the
+                        * reiserfs lock
+                        */
+                       reiserfs_write_unlock_once(inode->i_sb, depth);
                        error = inode_setattr(inode, attr);
+                       depth = reiserfs_write_lock_once(inode->i_sb);
+               }
        }
 
        if (!error && reiserfs_posixacl(inode->i_sb)) {
@@ -3158,7 +3169,8 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
       out:
-       reiserfs_write_unlock(inode->i_sb);
+       reiserfs_write_unlock_once(inode->i_sb, depth);
+
        return error;
 }
 
index ace77451ceb16d3280a94e4bebc1044e0c6920f3..f53505de071217399e39bf2013304ba46bd0c7f5 100644 (file)
@@ -104,9 +104,10 @@ setflags_out:
                err = put_user(inode->i_generation, (int __user *)arg);
                break;
        case REISERFS_IOC_SETVERSION:
-               if (!is_owner_or_cap(inode))
+               if (!is_owner_or_cap(inode)) {
                        err = -EPERM;
                        break;
+               }
                err = mnt_want_write(filp->f_path.mnt);
                if (err)
                        break;
index 2f8a7e7b8dabf04b8641e7b4426b02b3bba8e570..83ac4d3b3cb0f019f128b30c81f6e2e94e8b5a98 100644 (file)
@@ -2009,10 +2009,11 @@ static int do_journal_release(struct reiserfs_transaction_handle *th,
                destroy_workqueue(commit_wq);
                commit_wq = NULL;
        }
-       reiserfs_write_lock(sb);
 
        free_journal_ram(sb);
 
+       reiserfs_write_lock(sb);
+
        return 0;
 }
 
@@ -2758,11 +2759,18 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
        struct reiserfs_journal *journal;
        struct reiserfs_journal_list *jl;
        char b[BDEVNAME_SIZE];
+       int ret;
 
+       /*
+        * Unlock here to avoid various RECLAIM-FS-ON <-> IN-RECLAIM-FS
+        * dependency inversion warnings.
+        */
+       reiserfs_write_unlock(sb);
        journal = SB_JOURNAL(sb) = vmalloc(sizeof(struct reiserfs_journal));
        if (!journal) {
                reiserfs_warning(sb, "journal-1256",
                                 "unable to get memory for journal structure");
+               reiserfs_write_lock(sb);
                return 1;
        }
        memset(journal, 0, sizeof(struct reiserfs_journal));
@@ -2771,10 +2779,12 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
        INIT_LIST_HEAD(&journal->j_working_list);
        INIT_LIST_HEAD(&journal->j_journal_list);
        journal->j_persistent_trans = 0;
-       if (reiserfs_allocate_list_bitmaps(sb,
-                                          journal->j_list_bitmap,
-                                          reiserfs_bmap_count(sb)))
+       ret = reiserfs_allocate_list_bitmaps(sb, journal->j_list_bitmap,
+                                          reiserfs_bmap_count(sb));
+       reiserfs_write_lock(sb);
+       if (ret)
                goto free_and_return;
+
        allocate_bitmap_nodes(sb);
 
        /* reserved for journal area support */
index ee2cfc0fd8a77411f3b581ee759792b3579046ae..b87aa2c1afc14fc9165c6f3a4a42c1c06063c0fa 100644 (file)
@@ -86,3 +86,12 @@ void reiserfs_check_lock_depth(struct super_block *sb, char *caller)
                reiserfs_panic(sb, "%s called without kernel lock held %d",
                               caller);
 }
+
+#ifdef CONFIG_REISERFS_CHECK
+void reiserfs_lock_check_recursive(struct super_block *sb)
+{
+       struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
+
+       WARN_ONCE((sb_i->lock_depth > 0), "Unwanted recursive reiserfs lock!\n");
+}
+#endif
index e296ff72a6ccb2bc2e99cfbb97472c7da39f3253..9d4dcf0b07cbdcd65353915de08e9a27e9f99848 100644 (file)
@@ -921,6 +921,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
        struct reiserfs_transaction_handle th;
        int jbegin_count;
        unsigned long savelink;
+       int depth;
 
        inode = dentry->d_inode;
 
@@ -932,7 +933,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
            JOURNAL_PER_BALANCE_CNT * 2 + 2 +
            4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
 
-       reiserfs_write_lock(dir->i_sb);
+       depth = reiserfs_write_lock_once(dir->i_sb);
        retval = journal_begin(&th, dir->i_sb, jbegin_count);
        if (retval)
                goto out_unlink;
@@ -993,7 +994,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
 
        retval = journal_end(&th, dir->i_sb, jbegin_count);
        reiserfs_check_path(&path);
-       reiserfs_write_unlock(dir->i_sb);
+       reiserfs_write_unlock_once(dir->i_sb, depth);
        return retval;
 
       end_unlink:
@@ -1003,7 +1004,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
        if (err)
                retval = err;
       out_unlink:
-       reiserfs_write_unlock(dir->i_sb);
+       reiserfs_write_unlock_once(dir->i_sb, depth);
        return retval;
 }
 
index 8c7033a8b67e43bed5d0acef901875fc2a22aa14..81f09fab8ae476ccbdb9547d226e397e1b8cb6d1 100644 (file)
@@ -83,7 +83,8 @@ static int xattr_unlink(struct inode *dir, struct dentry *dentry)
        BUG_ON(!mutex_is_locked(&dir->i_mutex));
        vfs_dq_init(dir);
 
-       mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
+       reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex,
+                                       I_MUTEX_CHILD, dir->i_sb);
        error = dir->i_op->unlink(dir, dentry);
        mutex_unlock(&dentry->d_inode->i_mutex);
 
@@ -98,7 +99,8 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
        BUG_ON(!mutex_is_locked(&dir->i_mutex));
        vfs_dq_init(dir);
 
-       mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
+       reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex,
+                                       I_MUTEX_CHILD, dir->i_sb);
        dentry_unhash(dentry);
        error = dir->i_op->rmdir(dir, dentry);
        if (!error)
@@ -235,16 +237,22 @@ static int reiserfs_for_each_xattr(struct inode *inode,
        if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1)
                return 0;
 
+       reiserfs_write_unlock(inode->i_sb);
        dir = open_xa_dir(inode, XATTR_REPLACE);
        if (IS_ERR(dir)) {
                err = PTR_ERR(dir);
+               reiserfs_write_lock(inode->i_sb);
                goto out;
        } else if (!dir->d_inode) {
                err = 0;
+               reiserfs_write_lock(inode->i_sb);
                goto out_dir;
        }
 
        mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
+
+       reiserfs_write_lock(inode->i_sb);
+
        buf.xadir = dir;
        err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos);
        while ((err == 0 || err == -ENOSPC) && buf.count) {
@@ -283,8 +291,9 @@ static int reiserfs_for_each_xattr(struct inode *inode,
                err = journal_begin(&th, inode->i_sb, blocks);
                if (!err) {
                        int jerror;
-                       mutex_lock_nested(&dir->d_parent->d_inode->i_mutex,
-                                         I_MUTEX_XATTR);
+                       reiserfs_mutex_lock_nested_safe(
+                                         &dir->d_parent->d_inode->i_mutex,
+                                         I_MUTEX_XATTR, inode->i_sb);
                        err = action(dir, data);
                        jerror = journal_end(&th, inode->i_sb, blocks);
                        mutex_unlock(&dir->d_parent->d_inode->i_mutex);
@@ -443,7 +452,9 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name)
        }
 
        if (dentry->d_inode) {
+               reiserfs_write_lock(inode->i_sb);
                err = xattr_unlink(xadir->d_inode, dentry);
+               reiserfs_write_unlock(inode->i_sb);
                update_ctime(inode);
        }
 
@@ -477,15 +488,24 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
        if (get_inode_sd_version(inode) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
-       if (!buffer)
-               return lookup_and_delete_xattr(inode, name);
+       reiserfs_write_unlock(inode->i_sb);
+
+       if (!buffer) {
+               err = lookup_and_delete_xattr(inode, name);
+               reiserfs_write_lock(inode->i_sb);
+               return err;
+       }
 
        dentry = xattr_lookup(inode, name, flags);
-       if (IS_ERR(dentry))
+       if (IS_ERR(dentry)) {
+               reiserfs_write_lock(inode->i_sb);
                return PTR_ERR(dentry);
+       }
 
        down_write(&REISERFS_I(inode)->i_xattr_sem);
 
+       reiserfs_write_lock(inode->i_sb);
+
        xahash = xattr_hash(buffer, buffer_size);
        while (buffer_pos < buffer_size || buffer_pos == 0) {
                size_t chunk;
@@ -540,8 +560,12 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
                        .ia_size = buffer_size,
                        .ia_valid = ATTR_SIZE | ATTR_CTIME,
                };
+
+               reiserfs_write_unlock(inode->i_sb);
                mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
                down_write(&dentry->d_inode->i_alloc_sem);
+               reiserfs_write_lock(inode->i_sb);
+
                err = reiserfs_setattr(dentry, &newattrs);
                up_write(&dentry->d_inode->i_alloc_sem);
                mutex_unlock(&dentry->d_inode->i_mutex);
index cc32e6ada67b3330aa0a9e3fc3bacfd0ca7c7c61..dd20a7883f0f3a2606d3b4d8bf9ca2a65f274fbb 100644 (file)
@@ -455,7 +455,9 @@ int reiserfs_acl_chmod(struct inode *inode)
                return 0;
        }
 
+       reiserfs_write_unlock(inode->i_sb);
        acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
+       reiserfs_write_lock(inode->i_sb);
        if (!acl)
                return 0;
        if (IS_ERR(acl))
index f05f2303a8b8c60c80fb81a6059c0ebd39471b2f..699f371b9f12f0f9831f712101e63df948f66350 100644 (file)
@@ -106,8 +106,10 @@ static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
                        return NULL;
 
                t = atomic_cmpxchg(&sd->s_active, v, v + 1);
-               if (likely(t == v))
+               if (likely(t == v)) {
+                       rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
                        return sd;
+               }
                if (t < 0)
                        return NULL;
 
@@ -130,6 +132,7 @@ static void sysfs_put_active(struct sysfs_dirent *sd)
        if (unlikely(!sd))
                return;
 
+       rwsem_release(&sd->dep_map, 1, _RET_IP_);
        v = atomic_dec_return(&sd->s_active);
        if (likely(v != SD_DEACTIVATED_BIAS))
                return;
@@ -194,15 +197,21 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
        BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
        sd->s_sibling = (void *)&wait;
 
+       rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_);
        /* atomic_add_return() is a mb(), put_active() will always see
         * the updated sd->s_sibling.
         */
        v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);
 
-       if (v != SD_DEACTIVATED_BIAS)
+       if (v != SD_DEACTIVATED_BIAS) {
+               lock_contended(&sd->dep_map, _RET_IP_);
                wait_for_completion(&wait);
+       }
 
        sd->s_sibling = NULL;
+
+       lock_acquired(&sd->dep_map, _RET_IP_);
+       rwsem_release(&sd->dep_map, 1, _RET_IP_);
 }
 
 static int sysfs_alloc_ino(ino_t *pino)
@@ -345,6 +354,7 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
 
        atomic_set(&sd->s_count, 1);
        atomic_set(&sd->s_active, 0);
+       sysfs_dirent_init_lockdep(sd);
 
        sd->s_name = name;
        sd->s_mode = mode;
index ca52e7b9d8f86029085cd85c6ea1a9db12cc2838..cdd9377a6e06a9d3d5fafc18e295bb8b5565b662 100644 (file)
@@ -8,6 +8,7 @@
  * This file is released under the GPLv2.
  */
 
+#include <linux/lockdep.h>
 #include <linux/fs.h>
 
 struct sysfs_open_dirent;
@@ -50,6 +51,9 @@ struct sysfs_inode_attrs {
 struct sysfs_dirent {
        atomic_t                s_count;
        atomic_t                s_active;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       struct lockdep_map      dep_map;
+#endif
        struct sysfs_dirent     *s_parent;
        struct sysfs_dirent     *s_sibling;
        const char              *s_name;
@@ -84,6 +88,17 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
        return sd->s_flags & SYSFS_TYPE_MASK;
 }
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#define sysfs_dirent_init_lockdep(sd)                          \
+do {                                                           \
+       static struct lock_class_key __key;                     \
+                                                               \
+       lockdep_init_map(&sd->dep_map, "s_active", &__key, 0);  \
+} while(0)
+#else
+#define sysfs_dirent_init_lockdep(sd) do {} while(0)
+#endif
+
 /*
  * Context structure to be used while adding/removing nodes.
  */
index 2512125dfa7c9eadba5e440afea5250124fcbe28..883ca5ab8af572f4daa961e3e0fb1a6777bd3a3c 100644 (file)
@@ -251,8 +251,9 @@ xfs_set_mode(struct inode *inode, mode_t mode)
        if (mode != inode->i_mode) {
                struct iattr iattr;
 
-               iattr.ia_valid = ATTR_MODE;
+               iattr.ia_valid = ATTR_MODE | ATTR_CTIME;
                iattr.ia_mode = mode;
+               iattr.ia_ctime = current_fs_time(inode->i_sb);
 
                error = -xfs_setattr(XFS_I(inode), &iattr, XFS_ATTR_NOACL);
        }
index c40834bdee58a28c5a49ab5d27b1bc678e0d2dc3..c22a608321a34e19466e6f5453bf860a518610e2 100644 (file)
@@ -33,51 +33,55 @@ struct xfs_dquot;
 struct xlog_ticket;
 struct log;
 
+DECLARE_EVENT_CLASS(xfs_attr_list_class,
+       TP_PROTO(struct xfs_attr_list_context *ctx),
+       TP_ARGS(ctx),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(u32, hashval)
+               __field(u32, blkno)
+               __field(u32, offset)
+               __field(void *, alist)
+               __field(int, bufsize)
+               __field(int, count)
+               __field(int, firstu)
+               __field(int, dupcnt)
+               __field(int, flags)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ctx->dp)->i_sb->s_dev;
+               __entry->ino = ctx->dp->i_ino;
+               __entry->hashval = ctx->cursor->hashval;
+               __entry->blkno = ctx->cursor->blkno;
+               __entry->offset = ctx->cursor->offset;
+               __entry->alist = ctx->alist;
+               __entry->bufsize = ctx->bufsize;
+               __entry->count = ctx->count;
+               __entry->firstu = ctx->firstu;
+               __entry->flags = ctx->flags;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx cursor h/b/o 0x%x/0x%x/%u dupcnt %u "
+                 "alist 0x%p size %u count %u firstu %u flags %d %s",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                  __entry->ino,
+                  __entry->hashval,
+                  __entry->blkno,
+                  __entry->offset,
+                  __entry->dupcnt,
+                  __entry->alist,
+                  __entry->bufsize,
+                  __entry->count,
+                  __entry->firstu,
+                  __entry->flags,
+                  __print_flags(__entry->flags, "|", XFS_ATTR_FLAGS)
+       )
+)
+
 #define DEFINE_ATTR_LIST_EVENT(name) \
-TRACE_EVENT(name, \
+DEFINE_EVENT(xfs_attr_list_class, name, \
        TP_PROTO(struct xfs_attr_list_context *ctx), \
-       TP_ARGS(ctx), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __field(u32, hashval) \
-               __field(u32, blkno) \
-               __field(u32, offset) \
-               __field(void *, alist) \
-               __field(int, bufsize) \
-               __field(int, count) \
-               __field(int, firstu) \
-               __field(int, dupcnt) \
-               __field(int, flags) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = VFS_I(ctx->dp)->i_sb->s_dev; \
-               __entry->ino = ctx->dp->i_ino; \
-               __entry->hashval = ctx->cursor->hashval; \
-               __entry->blkno = ctx->cursor->blkno; \
-               __entry->offset = ctx->cursor->offset; \
-               __entry->alist = ctx->alist; \
-               __entry->bufsize = ctx->bufsize; \
-               __entry->count = ctx->count; \
-               __entry->firstu = ctx->firstu; \
-               __entry->flags = ctx->flags; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx cursor h/b/o 0x%x/0x%x/%u dupcnt %u " \
-                 "alist 0x%p size %u count %u firstu %u flags %d %s", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                  __entry->ino, \
-                  __entry->hashval, \
-                  __entry->blkno, \
-                  __entry->offset, \
-                  __entry->dupcnt, \
-                  __entry->alist, \
-                  __entry->bufsize, \
-                  __entry->count, \
-                  __entry->firstu, \
-                  __entry->flags, \
-                  __print_flags(__entry->flags, "|", XFS_ATTR_FLAGS) \
-       ) \
-)
+       TP_ARGS(ctx))
 DEFINE_ATTR_LIST_EVENT(xfs_attr_list_sf);
 DEFINE_ATTR_LIST_EVENT(xfs_attr_list_sf_all);
 DEFINE_ATTR_LIST_EVENT(xfs_attr_list_leaf);
@@ -178,91 +182,99 @@ TRACE_EVENT(xfs_iext_insert,
                  (char *)__entry->caller_ip)
 );
 
+DECLARE_EVENT_CLASS(xfs_bmap_class,
+       TP_PROTO(struct xfs_inode *ip, xfs_extnum_t idx, int state,
+                unsigned long caller_ip),
+       TP_ARGS(ip, idx, state, caller_ip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(xfs_extnum_t, idx)
+               __field(xfs_fileoff_t, startoff)
+               __field(xfs_fsblock_t, startblock)
+               __field(xfs_filblks_t, blockcount)
+               __field(xfs_exntst_t, state)
+               __field(int, bmap_state)
+               __field(unsigned long, caller_ip)
+       ),
+       TP_fast_assign(
+               struct xfs_ifork        *ifp = (state & BMAP_ATTRFORK) ?
+                                               ip->i_afp : &ip->i_df;
+               struct xfs_bmbt_irec    r;
+
+               xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &r);
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->idx = idx;
+               __entry->startoff = r.br_startoff;
+               __entry->startblock = r.br_startblock;
+               __entry->blockcount = r.br_blockcount;
+               __entry->state = r.br_state;
+               __entry->bmap_state = state;
+               __entry->caller_ip = caller_ip;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx state %s idx %ld "
+                 "offset %lld block %s count %lld flag %d caller %pf",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __print_flags(__entry->bmap_state, "|", XFS_BMAP_EXT_FLAGS),
+                 (long)__entry->idx,
+                 __entry->startoff,
+                 xfs_fmtfsblock(__entry->startblock),
+                 __entry->blockcount,
+                 __entry->state,
+                 (char *)__entry->caller_ip)
+)
+
 #define DEFINE_BMAP_EVENT(name) \
-TRACE_EVENT(name, \
+DEFINE_EVENT(xfs_bmap_class, name, \
        TP_PROTO(struct xfs_inode *ip, xfs_extnum_t idx, int state, \
                 unsigned long caller_ip), \
-       TP_ARGS(ip, idx, state, caller_ip), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __field(xfs_extnum_t, idx) \
-               __field(xfs_fileoff_t, startoff) \
-               __field(xfs_fsblock_t, startblock) \
-               __field(xfs_filblks_t, blockcount) \
-               __field(xfs_exntst_t, state) \
-               __field(int, bmap_state) \
-               __field(unsigned long, caller_ip) \
-       ), \
-       TP_fast_assign( \
-               struct xfs_ifork        *ifp = (state & BMAP_ATTRFORK) ? \
-                                               ip->i_afp : &ip->i_df; \
-               struct xfs_bmbt_irec    r; \
-       \
-               xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &r); \
-               __entry->dev = VFS_I(ip)->i_sb->s_dev; \
-               __entry->ino = ip->i_ino; \
-               __entry->idx = idx; \
-               __entry->startoff = r.br_startoff; \
-               __entry->startblock = r.br_startblock; \
-               __entry->blockcount = r.br_blockcount; \
-               __entry->state = r.br_state; \
-               __entry->bmap_state = state; \
-               __entry->caller_ip = caller_ip; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx state %s idx %ld " \
-                 "offset %lld block %s count %lld flag %d caller %pf", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino, \
-                 __print_flags(__entry->bmap_state, "|", XFS_BMAP_EXT_FLAGS), \
-                 (long)__entry->idx, \
-                 __entry->startoff, \
-                 xfs_fmtfsblock(__entry->startblock), \
-                 __entry->blockcount, \
-                 __entry->state, \
-                 (char *)__entry->caller_ip) \
-)
-
+       TP_ARGS(ip, idx, state, caller_ip))
 DEFINE_BMAP_EVENT(xfs_iext_remove);
 DEFINE_BMAP_EVENT(xfs_bmap_pre_update);
 DEFINE_BMAP_EVENT(xfs_bmap_post_update);
 DEFINE_BMAP_EVENT(xfs_extlist);
 
-#define DEFINE_BUF_EVENT(tname) \
-TRACE_EVENT(tname, \
-       TP_PROTO(struct xfs_buf *bp, unsigned long caller_ip), \
-       TP_ARGS(bp, caller_ip), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_daddr_t, bno) \
-               __field(size_t, buffer_length) \
-               __field(int, hold) \
-               __field(int, pincount) \
-               __field(unsigned, lockval) \
-               __field(unsigned, flags) \
-               __field(unsigned long, caller_ip) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = bp->b_target->bt_dev; \
-               __entry->bno = bp->b_bn; \
-               __entry->buffer_length = bp->b_buffer_length; \
-               __entry->hold = atomic_read(&bp->b_hold); \
-               __entry->pincount = atomic_read(&bp->b_pin_count); \
-               __entry->lockval = xfs_buf_lock_value(bp); \
-               __entry->flags = bp->b_flags; \
-               __entry->caller_ip = caller_ip; \
-       ), \
-       TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d " \
-                 "lock %d flags %s caller %pf", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 (unsigned long long)__entry->bno, \
-                 __entry->buffer_length, \
-                 __entry->hold, \
-                 __entry->pincount, \
-                 __entry->lockval, \
-                 __print_flags(__entry->flags, "|", XFS_BUF_FLAGS), \
-                 (void *)__entry->caller_ip) \
+DECLARE_EVENT_CLASS(xfs_buf_class,
+       TP_PROTO(struct xfs_buf *bp, unsigned long caller_ip),
+       TP_ARGS(bp, caller_ip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_daddr_t, bno)
+               __field(size_t, buffer_length)
+               __field(int, hold)
+               __field(int, pincount)
+               __field(unsigned, lockval)
+               __field(unsigned, flags)
+               __field(unsigned long, caller_ip)
+       ),
+       TP_fast_assign(
+               __entry->dev = bp->b_target->bt_dev;
+               __entry->bno = bp->b_bn;
+               __entry->buffer_length = bp->b_buffer_length;
+               __entry->hold = atomic_read(&bp->b_hold);
+               __entry->pincount = atomic_read(&bp->b_pin_count);
+               __entry->lockval = xfs_buf_lock_value(bp);
+               __entry->flags = bp->b_flags;
+               __entry->caller_ip = caller_ip;
+       ),
+       TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d "
+                 "lock %d flags %s caller %pf",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long long)__entry->bno,
+                 __entry->buffer_length,
+                 __entry->hold,
+                 __entry->pincount,
+                 __entry->lockval,
+                 __print_flags(__entry->flags, "|", XFS_BUF_FLAGS),
+                 (void *)__entry->caller_ip)
 )
+
+#define DEFINE_BUF_EVENT(name) \
+DEFINE_EVENT(xfs_buf_class, name, \
+       TP_PROTO(struct xfs_buf *bp, unsigned long caller_ip), \
+       TP_ARGS(bp, caller_ip))
 DEFINE_BUF_EVENT(xfs_buf_init);
 DEFINE_BUF_EVENT(xfs_buf_free);
 DEFINE_BUF_EVENT(xfs_buf_hold);
@@ -299,41 +311,45 @@ DEFINE_BUF_EVENT(xfs_reset_dqcounts);
 DEFINE_BUF_EVENT(xfs_inode_item_push);
 
 /* pass flags explicitly */
-#define DEFINE_BUF_FLAGS_EVENT(tname) \
-TRACE_EVENT(tname, \
-       TP_PROTO(struct xfs_buf *bp, unsigned flags, unsigned long caller_ip), \
-       TP_ARGS(bp, flags, caller_ip), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_daddr_t, bno) \
-               __field(size_t, buffer_length) \
-               __field(int, hold) \
-               __field(int, pincount) \
-               __field(unsigned, lockval) \
-               __field(unsigned, flags) \
-               __field(unsigned long, caller_ip) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = bp->b_target->bt_dev; \
-               __entry->bno = bp->b_bn; \
-               __entry->buffer_length = bp->b_buffer_length; \
-               __entry->flags = flags; \
-               __entry->hold = atomic_read(&bp->b_hold); \
-               __entry->pincount = atomic_read(&bp->b_pin_count); \
-               __entry->lockval = xfs_buf_lock_value(bp); \
-               __entry->caller_ip = caller_ip; \
-       ), \
-       TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d " \
-                 "lock %d flags %s caller %pf", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 (unsigned long long)__entry->bno, \
-                 __entry->buffer_length, \
-                 __entry->hold, \
-                 __entry->pincount, \
-                 __entry->lockval, \
-                 __print_flags(__entry->flags, "|", XFS_BUF_FLAGS), \
-                 (void *)__entry->caller_ip) \
+DECLARE_EVENT_CLASS(xfs_buf_flags_class,
+       TP_PROTO(struct xfs_buf *bp, unsigned flags, unsigned long caller_ip),
+       TP_ARGS(bp, flags, caller_ip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_daddr_t, bno)
+               __field(size_t, buffer_length)
+               __field(int, hold)
+               __field(int, pincount)
+               __field(unsigned, lockval)
+               __field(unsigned, flags)
+               __field(unsigned long, caller_ip)
+       ),
+       TP_fast_assign(
+               __entry->dev = bp->b_target->bt_dev;
+               __entry->bno = bp->b_bn;
+               __entry->buffer_length = bp->b_buffer_length;
+               __entry->flags = flags;
+               __entry->hold = atomic_read(&bp->b_hold);
+               __entry->pincount = atomic_read(&bp->b_pin_count);
+               __entry->lockval = xfs_buf_lock_value(bp);
+               __entry->caller_ip = caller_ip;
+       ),
+       TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d "
+                 "lock %d flags %s caller %pf",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long long)__entry->bno,
+                 __entry->buffer_length,
+                 __entry->hold,
+                 __entry->pincount,
+                 __entry->lockval,
+                 __print_flags(__entry->flags, "|", XFS_BUF_FLAGS),
+                 (void *)__entry->caller_ip)
 )
+
+#define DEFINE_BUF_FLAGS_EVENT(name) \
+DEFINE_EVENT(xfs_buf_flags_class, name, \
+       TP_PROTO(struct xfs_buf *bp, unsigned flags, unsigned long caller_ip), \
+       TP_ARGS(bp, flags, caller_ip))
 DEFINE_BUF_FLAGS_EVENT(xfs_buf_find);
 DEFINE_BUF_FLAGS_EVENT(xfs_buf_get);
 DEFINE_BUF_FLAGS_EVENT(xfs_buf_read);
@@ -376,55 +392,58 @@ TRACE_EVENT(xfs_buf_ioerror,
                  (void *)__entry->caller_ip)
 );
 
-#define DEFINE_BUF_ITEM_EVENT(tname) \
-TRACE_EVENT(tname, \
-       TP_PROTO(struct xfs_buf_log_item *bip), \
-       TP_ARGS(bip), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_daddr_t, buf_bno) \
-               __field(size_t, buf_len) \
-               __field(int, buf_hold) \
-               __field(int, buf_pincount) \
-               __field(int, buf_lockval) \
-               __field(unsigned, buf_flags) \
-               __field(unsigned, bli_recur) \
-               __field(int, bli_refcount) \
-               __field(unsigned, bli_flags) \
-               __field(void *, li_desc) \
-               __field(unsigned, li_flags) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = bip->bli_buf->b_target->bt_dev; \
-               __entry->bli_flags = bip->bli_flags; \
-               __entry->bli_recur = bip->bli_recur; \
-               __entry->bli_refcount = atomic_read(&bip->bli_refcount); \
-               __entry->buf_bno = bip->bli_buf->b_bn; \
-               __entry->buf_len = bip->bli_buf->b_buffer_length; \
-               __entry->buf_flags = bip->bli_buf->b_flags; \
-               __entry->buf_hold = atomic_read(&bip->bli_buf->b_hold); \
-               __entry->buf_pincount = \
-                       atomic_read(&bip->bli_buf->b_pin_count); \
-               __entry->buf_lockval = xfs_buf_lock_value(bip->bli_buf); \
-               __entry->li_desc = bip->bli_item.li_desc; \
-               __entry->li_flags = bip->bli_item.li_flags; \
-       ), \
-       TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d " \
-                 "lock %d flags %s recur %d refcount %d bliflags %s " \
-                 "lidesc 0x%p liflags %s", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 (unsigned long long)__entry->buf_bno, \
-                 __entry->buf_len, \
-                 __entry->buf_hold, \
-                 __entry->buf_pincount, \
-                 __entry->buf_lockval, \
-                 __print_flags(__entry->buf_flags, "|", XFS_BUF_FLAGS), \
-                 __entry->bli_recur, \
-                 __entry->bli_refcount, \
-                 __print_flags(__entry->bli_flags, "|", XFS_BLI_FLAGS), \
-                 __entry->li_desc, \
-                 __print_flags(__entry->li_flags, "|", XFS_LI_FLAGS)) \
+DECLARE_EVENT_CLASS(xfs_buf_item_class,
+       TP_PROTO(struct xfs_buf_log_item *bip),
+       TP_ARGS(bip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_daddr_t, buf_bno)
+               __field(size_t, buf_len)
+               __field(int, buf_hold)
+               __field(int, buf_pincount)
+               __field(int, buf_lockval)
+               __field(unsigned, buf_flags)
+               __field(unsigned, bli_recur)
+               __field(int, bli_refcount)
+               __field(unsigned, bli_flags)
+               __field(void *, li_desc)
+               __field(unsigned, li_flags)
+       ),
+       TP_fast_assign(
+               __entry->dev = bip->bli_buf->b_target->bt_dev;
+               __entry->bli_flags = bip->bli_flags;
+               __entry->bli_recur = bip->bli_recur;
+               __entry->bli_refcount = atomic_read(&bip->bli_refcount);
+               __entry->buf_bno = bip->bli_buf->b_bn;
+               __entry->buf_len = bip->bli_buf->b_buffer_length;
+               __entry->buf_flags = bip->bli_buf->b_flags;
+               __entry->buf_hold = atomic_read(&bip->bli_buf->b_hold);
+               __entry->buf_pincount = atomic_read(&bip->bli_buf->b_pin_count);
+               __entry->buf_lockval = xfs_buf_lock_value(bip->bli_buf);
+               __entry->li_desc = bip->bli_item.li_desc;
+               __entry->li_flags = bip->bli_item.li_flags;
+       ),
+       TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d "
+                 "lock %d flags %s recur %d refcount %d bliflags %s "
+                 "lidesc 0x%p liflags %s",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 (unsigned long long)__entry->buf_bno,
+                 __entry->buf_len,
+                 __entry->buf_hold,
+                 __entry->buf_pincount,
+                 __entry->buf_lockval,
+                 __print_flags(__entry->buf_flags, "|", XFS_BUF_FLAGS),
+                 __entry->bli_recur,
+                 __entry->bli_refcount,
+                 __print_flags(__entry->bli_flags, "|", XFS_BLI_FLAGS),
+                 __entry->li_desc,
+                 __print_flags(__entry->li_flags, "|", XFS_LI_FLAGS))
 )
+
+#define DEFINE_BUF_ITEM_EVENT(name) \
+DEFINE_EVENT(xfs_buf_item_class, name, \
+       TP_PROTO(struct xfs_buf_log_item *bip), \
+       TP_ARGS(bip))
 DEFINE_BUF_ITEM_EVENT(xfs_buf_item_size);
 DEFINE_BUF_ITEM_EVENT(xfs_buf_item_size_stale);
 DEFINE_BUF_ITEM_EVENT(xfs_buf_item_format);
@@ -450,78 +469,90 @@ DEFINE_BUF_ITEM_EVENT(xfs_trans_bhold);
 DEFINE_BUF_ITEM_EVENT(xfs_trans_bhold_release);
 DEFINE_BUF_ITEM_EVENT(xfs_trans_binval);
 
+DECLARE_EVENT_CLASS(xfs_lock_class,
+       TP_PROTO(struct xfs_inode *ip, unsigned lock_flags,
+                unsigned long caller_ip),
+       TP_ARGS(ip,  lock_flags, caller_ip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(int, lock_flags)
+               __field(unsigned long, caller_ip)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->lock_flags = lock_flags;
+               __entry->caller_ip = caller_ip;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx flags %s caller %pf",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __print_flags(__entry->lock_flags, "|", XFS_LOCK_FLAGS),
+                 (void *)__entry->caller_ip)
+)
+
 #define DEFINE_LOCK_EVENT(name) \
-TRACE_EVENT(name, \
+DEFINE_EVENT(xfs_lock_class, name, \
        TP_PROTO(struct xfs_inode *ip, unsigned lock_flags, \
                 unsigned long caller_ip), \
-       TP_ARGS(ip,  lock_flags, caller_ip), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __field(int, lock_flags) \
-               __field(unsigned long, caller_ip) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = VFS_I(ip)->i_sb->s_dev; \
-               __entry->ino = ip->i_ino; \
-               __entry->lock_flags = lock_flags; \
-               __entry->caller_ip = caller_ip; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx flags %s caller %pf", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino, \
-                 __print_flags(__entry->lock_flags, "|", XFS_LOCK_FLAGS), \
-                 (void *)__entry->caller_ip) \
-)
-
+       TP_ARGS(ip,  lock_flags, caller_ip))
 DEFINE_LOCK_EVENT(xfs_ilock);
 DEFINE_LOCK_EVENT(xfs_ilock_nowait);
 DEFINE_LOCK_EVENT(xfs_ilock_demote);
 DEFINE_LOCK_EVENT(xfs_iunlock);
 
+DECLARE_EVENT_CLASS(xfs_iget_class,
+       TP_PROTO(struct xfs_inode *ip),
+       TP_ARGS(ip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino)
+)
+
 #define DEFINE_IGET_EVENT(name) \
-TRACE_EVENT(name, \
+DEFINE_EVENT(xfs_iget_class, name, \
        TP_PROTO(struct xfs_inode *ip), \
-       TP_ARGS(ip), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = VFS_I(ip)->i_sb->s_dev; \
-               __entry->ino = ip->i_ino; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino) \
-)
+       TP_ARGS(ip))
 DEFINE_IGET_EVENT(xfs_iget_skip);
 DEFINE_IGET_EVENT(xfs_iget_reclaim);
 DEFINE_IGET_EVENT(xfs_iget_found);
 DEFINE_IGET_EVENT(xfs_iget_alloc);
 
+DECLARE_EVENT_CLASS(xfs_inode_class,
+       TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip),
+       TP_ARGS(ip, caller_ip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(int, count)
+               __field(unsigned long, caller_ip)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->count = atomic_read(&VFS_I(ip)->i_count);
+               __entry->caller_ip = caller_ip;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx count %d caller %pf",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->count,
+                 (char *)__entry->caller_ip)
+)
+
 #define DEFINE_INODE_EVENT(name) \
-TRACE_EVENT(name, \
+DEFINE_EVENT(xfs_inode_class, name, \
        TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), \
-       TP_ARGS(ip, caller_ip), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __field(int, count) \
-               __field(unsigned long, caller_ip) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = VFS_I(ip)->i_sb->s_dev; \
-               __entry->ino = ip->i_ino; \
-               __entry->count = atomic_read(&VFS_I(ip)->i_count); \
-               __entry->caller_ip = caller_ip; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx count %d caller %pf", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino, \
-                 __entry->count, \
-                 (char *)__entry->caller_ip) \
-)
+       TP_ARGS(ip, caller_ip))
 DEFINE_INODE_EVENT(xfs_ihold);
 DEFINE_INODE_EVENT(xfs_irele);
 /* the old xfs_itrace_entry tracer - to be replaced by s.th. in the VFS */
@@ -529,55 +560,59 @@ DEFINE_INODE_EVENT(xfs_inode);
 #define xfs_itrace_entry(ip)    \
        trace_xfs_inode(ip, _THIS_IP_)
 
-#define DEFINE_DQUOT_EVENT(tname) \
-TRACE_EVENT(tname, \
-       TP_PROTO(struct xfs_dquot *dqp), \
-       TP_ARGS(dqp), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(__be32, id) \
-               __field(unsigned, flags) \
-               __field(unsigned, nrefs) \
-               __field(unsigned long long, res_bcount) \
-               __field(unsigned long long, bcount) \
-               __field(unsigned long long, icount) \
-               __field(unsigned long long, blk_hardlimit) \
-               __field(unsigned long long, blk_softlimit) \
-               __field(unsigned long long, ino_hardlimit) \
-               __field(unsigned long long, ino_softlimit) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = dqp->q_mount->m_super->s_dev; \
-               __entry->id = dqp->q_core.d_id; \
-               __entry->flags = dqp->dq_flags; \
-               __entry->nrefs = dqp->q_nrefs; \
-               __entry->res_bcount = dqp->q_res_bcount; \
-               __entry->bcount = be64_to_cpu(dqp->q_core.d_bcount); \
-               __entry->icount = be64_to_cpu(dqp->q_core.d_icount); \
-               __entry->blk_hardlimit = \
-                       be64_to_cpu(dqp->q_core.d_blk_hardlimit); \
-               __entry->blk_softlimit = \
-                       be64_to_cpu(dqp->q_core.d_blk_softlimit); \
-               __entry->ino_hardlimit = \
-                       be64_to_cpu(dqp->q_core.d_ino_hardlimit); \
-               __entry->ino_softlimit = \
-                       be64_to_cpu(dqp->q_core.d_ino_softlimit); \
+DECLARE_EVENT_CLASS(xfs_dquot_class,
+       TP_PROTO(struct xfs_dquot *dqp),
+       TP_ARGS(dqp),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(__be32, id)
+               __field(unsigned, flags)
+               __field(unsigned, nrefs)
+               __field(unsigned long long, res_bcount)
+               __field(unsigned long long, bcount)
+               __field(unsigned long long, icount)
+               __field(unsigned long long, blk_hardlimit)
+               __field(unsigned long long, blk_softlimit)
+               __field(unsigned long long, ino_hardlimit)
+               __field(unsigned long long, ino_softlimit)
        ), \
-       TP_printk("dev %d:%d id 0x%x flags %s nrefs %u res_bc 0x%llx " \
-                 "bcnt 0x%llx [hard 0x%llx | soft 0x%llx] " \
-                 "icnt 0x%llx [hard 0x%llx | soft 0x%llx]", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 be32_to_cpu(__entry->id), \
-                 __print_flags(__entry->flags, "|", XFS_DQ_FLAGS), \
-                 __entry->nrefs, \
-                 __entry->res_bcount, \
-                 __entry->bcount, \
-                 __entry->blk_hardlimit, \
-                 __entry->blk_softlimit, \
-                 __entry->icount, \
-                 __entry->ino_hardlimit, \
-                 __entry->ino_softlimit) \
+       TP_fast_assign(
+               __entry->dev = dqp->q_mount->m_super->s_dev;
+               __entry->id = dqp->q_core.d_id;
+               __entry->flags = dqp->dq_flags;
+               __entry->nrefs = dqp->q_nrefs;
+               __entry->res_bcount = dqp->q_res_bcount;
+               __entry->bcount = be64_to_cpu(dqp->q_core.d_bcount);
+               __entry->icount = be64_to_cpu(dqp->q_core.d_icount);
+               __entry->blk_hardlimit =
+                       be64_to_cpu(dqp->q_core.d_blk_hardlimit);
+               __entry->blk_softlimit =
+                       be64_to_cpu(dqp->q_core.d_blk_softlimit);
+               __entry->ino_hardlimit =
+                       be64_to_cpu(dqp->q_core.d_ino_hardlimit);
+               __entry->ino_softlimit =
+                       be64_to_cpu(dqp->q_core.d_ino_softlimit);
+       ),
+       TP_printk("dev %d:%d id 0x%x flags %s nrefs %u res_bc 0x%llx "
+                 "bcnt 0x%llx [hard 0x%llx | soft 0x%llx] "
+                 "icnt 0x%llx [hard 0x%llx | soft 0x%llx]",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 be32_to_cpu(__entry->id),
+                 __print_flags(__entry->flags, "|", XFS_DQ_FLAGS),
+                 __entry->nrefs,
+                 __entry->res_bcount,
+                 __entry->bcount,
+                 __entry->blk_hardlimit,
+                 __entry->blk_softlimit,
+                 __entry->icount,
+                 __entry->ino_hardlimit,
+                 __entry->ino_softlimit)
 )
+
+#define DEFINE_DQUOT_EVENT(name) \
+DEFINE_EVENT(xfs_dquot_class, name, \
+       TP_PROTO(struct xfs_dquot *dqp), \
+       TP_ARGS(dqp))
 DEFINE_DQUOT_EVENT(xfs_dqadjust);
 DEFINE_DQUOT_EVENT(xfs_dqshake_dirty);
 DEFINE_DQUOT_EVENT(xfs_dqshake_unlink);
@@ -610,72 +645,75 @@ DEFINE_DQUOT_EVENT(xfs_dqflush_done);
 DEFINE_IGET_EVENT(xfs_dquot_dqalloc);
 DEFINE_IGET_EVENT(xfs_dquot_dqdetach);
 
+DECLARE_EVENT_CLASS(xfs_loggrant_class,
+       TP_PROTO(struct log *log, struct xlog_ticket *tic),
+       TP_ARGS(log, tic),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(unsigned, trans_type)
+               __field(char, ocnt)
+               __field(char, cnt)
+               __field(int, curr_res)
+               __field(int, unit_res)
+               __field(unsigned int, flags)
+               __field(void *, reserve_headq)
+               __field(void *, write_headq)
+               __field(int, grant_reserve_cycle)
+               __field(int, grant_reserve_bytes)
+               __field(int, grant_write_cycle)
+               __field(int, grant_write_bytes)
+               __field(int, curr_cycle)
+               __field(int, curr_block)
+               __field(xfs_lsn_t, tail_lsn)
+       ),
+       TP_fast_assign(
+               __entry->dev = log->l_mp->m_super->s_dev;
+               __entry->trans_type = tic->t_trans_type;
+               __entry->ocnt = tic->t_ocnt;
+               __entry->cnt = tic->t_cnt;
+               __entry->curr_res = tic->t_curr_res;
+               __entry->unit_res = tic->t_unit_res;
+               __entry->flags = tic->t_flags;
+               __entry->reserve_headq = log->l_reserve_headq;
+               __entry->write_headq = log->l_write_headq;
+               __entry->grant_reserve_cycle = log->l_grant_reserve_cycle;
+               __entry->grant_reserve_bytes = log->l_grant_reserve_bytes;
+               __entry->grant_write_cycle = log->l_grant_write_cycle;
+               __entry->grant_write_bytes = log->l_grant_write_bytes;
+               __entry->curr_cycle = log->l_curr_cycle;
+               __entry->curr_block = log->l_curr_block;
+               __entry->tail_lsn = log->l_tail_lsn;
+       ),
+       TP_printk("dev %d:%d type %s t_ocnt %u t_cnt %u t_curr_res %u "
+                 "t_unit_res %u t_flags %s reserve_headq 0x%p "
+                 "write_headq 0x%p grant_reserve_cycle %d "
+                 "grant_reserve_bytes %d grant_write_cycle %d "
+                 "grant_write_bytes %d curr_cycle %d curr_block %d "
+                 "tail_cycle %d tail_block %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __print_symbolic(__entry->trans_type, XFS_TRANS_TYPES),
+                 __entry->ocnt,
+                 __entry->cnt,
+                 __entry->curr_res,
+                 __entry->unit_res,
+                 __print_flags(__entry->flags, "|", XLOG_TIC_FLAGS),
+                 __entry->reserve_headq,
+                 __entry->write_headq,
+                 __entry->grant_reserve_cycle,
+                 __entry->grant_reserve_bytes,
+                 __entry->grant_write_cycle,
+                 __entry->grant_write_bytes,
+                 __entry->curr_cycle,
+                 __entry->curr_block,
+                 CYCLE_LSN(__entry->tail_lsn),
+                 BLOCK_LSN(__entry->tail_lsn)
+       )
+)
 
-#define DEFINE_LOGGRANT_EVENT(tname) \
-TRACE_EVENT(tname, \
+#define DEFINE_LOGGRANT_EVENT(name) \
+DEFINE_EVENT(xfs_loggrant_class, name, \
        TP_PROTO(struct log *log, struct xlog_ticket *tic), \
-       TP_ARGS(log, tic), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(unsigned, trans_type) \
-               __field(char, ocnt) \
-               __field(char, cnt) \
-               __field(int, curr_res) \
-               __field(int, unit_res) \
-               __field(unsigned int, flags) \
-               __field(void *, reserve_headq) \
-               __field(void *, write_headq) \
-               __field(int, grant_reserve_cycle) \
-               __field(int, grant_reserve_bytes) \
-               __field(int, grant_write_cycle) \
-               __field(int, grant_write_bytes) \
-               __field(int, curr_cycle) \
-               __field(int, curr_block) \
-               __field(xfs_lsn_t, tail_lsn) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = log->l_mp->m_super->s_dev; \
-               __entry->trans_type = tic->t_trans_type; \
-               __entry->ocnt = tic->t_ocnt; \
-               __entry->cnt = tic->t_cnt; \
-               __entry->curr_res = tic->t_curr_res; \
-               __entry->unit_res = tic->t_unit_res; \
-               __entry->flags = tic->t_flags; \
-               __entry->reserve_headq = log->l_reserve_headq; \
-               __entry->write_headq = log->l_write_headq; \
-               __entry->grant_reserve_cycle = log->l_grant_reserve_cycle; \
-               __entry->grant_reserve_bytes = log->l_grant_reserve_bytes; \
-               __entry->grant_write_cycle = log->l_grant_write_cycle; \
-               __entry->grant_write_bytes = log->l_grant_write_bytes; \
-               __entry->curr_cycle = log->l_curr_cycle; \
-               __entry->curr_block = log->l_curr_block; \
-               __entry->tail_lsn = log->l_tail_lsn; \
-       ), \
-       TP_printk("dev %d:%d type %s t_ocnt %u t_cnt %u t_curr_res %u " \
-                 "t_unit_res %u t_flags %s reserve_headq 0x%p " \
-                 "write_headq 0x%p grant_reserve_cycle %d " \
-                 "grant_reserve_bytes %d grant_write_cycle %d " \
-                 "grant_write_bytes %d curr_cycle %d curr_block %d " \
-                 "tail_cycle %d tail_block %d", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __print_symbolic(__entry->trans_type, XFS_TRANS_TYPES), \
-                 __entry->ocnt, \
-                 __entry->cnt, \
-                 __entry->curr_res, \
-                 __entry->unit_res, \
-                 __print_flags(__entry->flags, "|", XLOG_TIC_FLAGS), \
-                 __entry->reserve_headq, \
-                 __entry->write_headq, \
-                 __entry->grant_reserve_cycle, \
-                 __entry->grant_reserve_bytes, \
-                 __entry->grant_write_cycle, \
-                 __entry->grant_write_bytes, \
-                 __entry->curr_cycle, \
-                 __entry->curr_block, \
-                 CYCLE_LSN(__entry->tail_lsn), \
-                 BLOCK_LSN(__entry->tail_lsn) \
-       ) \
-)
+       TP_ARGS(log, tic))
 DEFINE_LOGGRANT_EVENT(xfs_log_done_nonperm);
 DEFINE_LOGGRANT_EVENT(xfs_log_done_perm);
 DEFINE_LOGGRANT_EVENT(xfs_log_reserve);
@@ -815,7 +853,7 @@ TRACE_EVENT(name, \
        ), \
        TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
                  "offset 0x%llx count %zd flags %s " \
-                 "startoff 0x%llx startblock 0x%llx blockcount 0x%llx", \
+                 "startoff 0x%llx startblock %s blockcount 0x%llx", \
                  MAJOR(__entry->dev), MINOR(__entry->dev), \
                  __entry->ino, \
                  __entry->size, \
@@ -824,7 +862,7 @@ TRACE_EVENT(name, \
                  __entry->count, \
                  __print_flags(__entry->flags, "|", BMAPI_FLAGS), \
                  __entry->startoff, \
-                 __entry->startblock, \
+                 xfs_fmtfsblock(__entry->startblock), \
                  __entry->blockcount) \
 )
 DEFINE_IOMAP_EVENT(xfs_iomap_enter);
@@ -897,28 +935,32 @@ TRACE_EVENT(xfs_itruncate_start,
                  __entry->toss_finish)
 );
 
+DECLARE_EVENT_CLASS(xfs_itrunc_class,
+       TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size),
+       TP_ARGS(ip, new_size),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(xfs_fsize_t, size)
+               __field(xfs_fsize_t, new_size)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->size = ip->i_d.di_size;
+               __entry->new_size = new_size;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->size,
+                 __entry->new_size)
+)
+
 #define DEFINE_ITRUNC_EVENT(name) \
-TRACE_EVENT(name, \
+DEFINE_EVENT(xfs_itrunc_class, name, \
        TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size), \
-       TP_ARGS(ip, new_size), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __field(xfs_fsize_t, size) \
-               __field(xfs_fsize_t, new_size) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = VFS_I(ip)->i_sb->s_dev; \
-               __entry->ino = ip->i_ino; \
-               __entry->size = ip->i_d.di_size; \
-               __entry->new_size = new_size; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino, \
-                 __entry->size, \
-                 __entry->new_size) \
-)
+       TP_ARGS(ip, new_size))
 DEFINE_ITRUNC_EVENT(xfs_itruncate_finish_start);
 DEFINE_ITRUNC_EVENT(xfs_itruncate_finish_end);
 
@@ -1037,28 +1079,28 @@ TRACE_EVENT(xfs_alloc_unbusy,
 
 TRACE_EVENT(xfs_alloc_busysearch,
        TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno,
-                xfs_extlen_t len, int found),
-       TP_ARGS(mp, agno, agbno, len, found),
+                xfs_extlen_t len, xfs_lsn_t lsn),
+       TP_ARGS(mp, agno, agbno, len, lsn),
        TP_STRUCT__entry(
                __field(dev_t, dev)
                __field(xfs_agnumber_t, agno)
                __field(xfs_agblock_t, agbno)
                __field(xfs_extlen_t, len)
-               __field(int, found)
+               __field(xfs_lsn_t, lsn)
        ),
        TP_fast_assign(
                __entry->dev = mp->m_super->s_dev;
                __entry->agno = agno;
                __entry->agbno = agbno;
                __entry->len = len;
-               __entry->found = found;
+               __entry->lsn = lsn;
        ),
-       TP_printk("dev %d:%d agno %u agbno %u len %u %s",
+       TP_printk("dev %d:%d agno %u agbno %u len %u force lsn 0x%llx",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->agno,
                  __entry->agbno,
                  __entry->len,
-                 __print_symbolic(__entry->found, XFS_BUSY_STATES))
+                 __entry->lsn)
 );
 
 TRACE_EVENT(xfs_agf,
@@ -1152,77 +1194,80 @@ TRACE_EVENT(xfs_free_extent,
 
 );
 
-#define DEFINE_ALLOC_EVENT(name) \
-TRACE_EVENT(name, \
-       TP_PROTO(struct xfs_alloc_arg *args), \
-       TP_ARGS(args), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_agnumber_t, agno) \
-               __field(xfs_agblock_t, agbno) \
-               __field(xfs_extlen_t, minlen) \
-               __field(xfs_extlen_t, maxlen) \
-               __field(xfs_extlen_t, mod) \
-               __field(xfs_extlen_t, prod) \
-               __field(xfs_extlen_t, minleft) \
-               __field(xfs_extlen_t, total) \
-               __field(xfs_extlen_t, alignment) \
-               __field(xfs_extlen_t, minalignslop) \
-               __field(xfs_extlen_t, len) \
-               __field(short, type) \
-               __field(short, otype) \
-               __field(char, wasdel) \
-               __field(char, wasfromfl) \
-               __field(char, isfl) \
-               __field(char, userdata) \
-               __field(xfs_fsblock_t, firstblock) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = args->mp->m_super->s_dev; \
-               __entry->agno = args->agno; \
-               __entry->agbno = args->agbno; \
-               __entry->minlen = args->minlen; \
-               __entry->maxlen = args->maxlen; \
-               __entry->mod = args->mod; \
-               __entry->prod = args->prod; \
-               __entry->minleft = args->minleft; \
-               __entry->total = args->total; \
-               __entry->alignment = args->alignment; \
-               __entry->minalignslop = args->minalignslop; \
-               __entry->len = args->len; \
-               __entry->type = args->type; \
-               __entry->otype = args->otype; \
-               __entry->wasdel = args->wasdel; \
-               __entry->wasfromfl = args->wasfromfl; \
-               __entry->isfl = args->isfl; \
-               __entry->userdata = args->userdata; \
-               __entry->firstblock = args->firstblock; \
-       ), \
-       TP_printk("dev %d:%d agno %u agbno %u minlen %u maxlen %u mod %u " \
-                 "prod %u minleft %u total %u alignment %u minalignslop %u " \
-                 "len %u type %s otype %s wasdel %d wasfromfl %d isfl %d " \
-                 "userdata %d firstblock 0x%llx", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->agno, \
-                 __entry->agbno, \
-                 __entry->minlen, \
-                 __entry->maxlen, \
-                 __entry->mod, \
-                 __entry->prod, \
-                 __entry->minleft, \
-                 __entry->total, \
-                 __entry->alignment, \
-                 __entry->minalignslop, \
-                 __entry->len, \
-                 __print_symbolic(__entry->type, XFS_ALLOC_TYPES), \
-                 __print_symbolic(__entry->otype, XFS_ALLOC_TYPES), \
-                 __entry->wasdel, \
-                 __entry->wasfromfl, \
-                 __entry->isfl, \
-                 __entry->userdata, \
-                 __entry->firstblock) \
+DECLARE_EVENT_CLASS(xfs_alloc_class,
+       TP_PROTO(struct xfs_alloc_arg *args),
+       TP_ARGS(args),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(xfs_agblock_t, agbno)
+               __field(xfs_extlen_t, minlen)
+               __field(xfs_extlen_t, maxlen)
+               __field(xfs_extlen_t, mod)
+               __field(xfs_extlen_t, prod)
+               __field(xfs_extlen_t, minleft)
+               __field(xfs_extlen_t, total)
+               __field(xfs_extlen_t, alignment)
+               __field(xfs_extlen_t, minalignslop)
+               __field(xfs_extlen_t, len)
+               __field(short, type)
+               __field(short, otype)
+               __field(char, wasdel)
+               __field(char, wasfromfl)
+               __field(char, isfl)
+               __field(char, userdata)
+               __field(xfs_fsblock_t, firstblock)
+       ),
+       TP_fast_assign(
+               __entry->dev = args->mp->m_super->s_dev;
+               __entry->agno = args->agno;
+               __entry->agbno = args->agbno;
+               __entry->minlen = args->minlen;
+               __entry->maxlen = args->maxlen;
+               __entry->mod = args->mod;
+               __entry->prod = args->prod;
+               __entry->minleft = args->minleft;
+               __entry->total = args->total;
+               __entry->alignment = args->alignment;
+               __entry->minalignslop = args->minalignslop;
+               __entry->len = args->len;
+               __entry->type = args->type;
+               __entry->otype = args->otype;
+               __entry->wasdel = args->wasdel;
+               __entry->wasfromfl = args->wasfromfl;
+               __entry->isfl = args->isfl;
+               __entry->userdata = args->userdata;
+               __entry->firstblock = args->firstblock;
+       ),
+       TP_printk("dev %d:%d agno %u agbno %u minlen %u maxlen %u mod %u "
+                 "prod %u minleft %u total %u alignment %u minalignslop %u "
+                 "len %u type %s otype %s wasdel %d wasfromfl %d isfl %d "
+                 "userdata %d firstblock 0x%llx",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->agno,
+                 __entry->agbno,
+                 __entry->minlen,
+                 __entry->maxlen,
+                 __entry->mod,
+                 __entry->prod,
+                 __entry->minleft,
+                 __entry->total,
+                 __entry->alignment,
+                 __entry->minalignslop,
+                 __entry->len,
+                 __print_symbolic(__entry->type, XFS_ALLOC_TYPES),
+                 __print_symbolic(__entry->otype, XFS_ALLOC_TYPES),
+                 __entry->wasdel,
+                 __entry->wasfromfl,
+                 __entry->isfl,
+                 __entry->userdata,
+                 __entry->firstblock)
 )
 
+#define DEFINE_ALLOC_EVENT(name) \
+DEFINE_EVENT(xfs_alloc_class, name, \
+       TP_PROTO(struct xfs_alloc_arg *args), \
+       TP_ARGS(args))
 DEFINE_ALLOC_EVENT(xfs_alloc_exact_done);
 DEFINE_ALLOC_EVENT(xfs_alloc_exact_error);
 DEFINE_ALLOC_EVENT(xfs_alloc_near_nominleft);
@@ -1245,92 +1290,100 @@ DEFINE_ALLOC_EVENT(xfs_alloc_vextent_noagbp);
 DEFINE_ALLOC_EVENT(xfs_alloc_vextent_loopfailed);
 DEFINE_ALLOC_EVENT(xfs_alloc_vextent_allfailed);
 
-#define DEFINE_DIR2_TRACE(tname) \
-TRACE_EVENT(tname, \
+DECLARE_EVENT_CLASS(xfs_dir2_class,
+       TP_PROTO(struct xfs_da_args *args),
+       TP_ARGS(args),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __dynamic_array(char, name, args->namelen)
+               __field(int, namelen)
+               __field(xfs_dahash_t, hashval)
+               __field(xfs_ino_t, inumber)
+               __field(int, op_flags)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(args->dp)->i_sb->s_dev;
+               __entry->ino = args->dp->i_ino;
+               if (args->namelen)
+                       memcpy(__get_str(name), args->name, args->namelen);
+               __entry->namelen = args->namelen;
+               __entry->hashval = args->hashval;
+               __entry->inumber = args->inumber;
+               __entry->op_flags = args->op_flags;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx name %.*s namelen %d hashval 0x%x "
+                 "inumber 0x%llx op_flags %s",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->namelen,
+                 __entry->namelen ? __get_str(name) : NULL,
+                 __entry->namelen,
+                 __entry->hashval,
+                 __entry->inumber,
+                 __print_flags(__entry->op_flags, "|", XFS_DA_OP_FLAGS))
+)
+
+#define DEFINE_DIR2_EVENT(name) \
+DEFINE_EVENT(xfs_dir2_class, name, \
        TP_PROTO(struct xfs_da_args *args), \
-       TP_ARGS(args), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __dynamic_array(char, name, args->namelen) \
-               __field(int, namelen) \
-               __field(xfs_dahash_t, hashval) \
-               __field(xfs_ino_t, inumber) \
-               __field(int, op_flags) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = VFS_I(args->dp)->i_sb->s_dev; \
-               __entry->ino = args->dp->i_ino; \
-               if (args->namelen) \
-                       memcpy(__get_str(name), args->name, args->namelen); \
-               __entry->namelen = args->namelen; \
-               __entry->hashval = args->hashval; \
-               __entry->inumber = args->inumber; \
-               __entry->op_flags = args->op_flags; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx name %.*s namelen %d hashval 0x%x " \
-                 "inumber 0x%llx op_flags %s", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino, \
-                 __entry->namelen, \
-                 __entry->namelen ? __get_str(name) : NULL, \
-                 __entry->namelen, \
-                 __entry->hashval, \
-                 __entry->inumber, \
-                 __print_flags(__entry->op_flags, "|", XFS_DA_OP_FLAGS)) \
+       TP_ARGS(args))
+DEFINE_DIR2_EVENT(xfs_dir2_sf_addname);
+DEFINE_DIR2_EVENT(xfs_dir2_sf_create);
+DEFINE_DIR2_EVENT(xfs_dir2_sf_lookup);
+DEFINE_DIR2_EVENT(xfs_dir2_sf_replace);
+DEFINE_DIR2_EVENT(xfs_dir2_sf_removename);
+DEFINE_DIR2_EVENT(xfs_dir2_sf_toino4);
+DEFINE_DIR2_EVENT(xfs_dir2_sf_toino8);
+DEFINE_DIR2_EVENT(xfs_dir2_sf_to_block);
+DEFINE_DIR2_EVENT(xfs_dir2_block_addname);
+DEFINE_DIR2_EVENT(xfs_dir2_block_lookup);
+DEFINE_DIR2_EVENT(xfs_dir2_block_replace);
+DEFINE_DIR2_EVENT(xfs_dir2_block_removename);
+DEFINE_DIR2_EVENT(xfs_dir2_block_to_sf);
+DEFINE_DIR2_EVENT(xfs_dir2_block_to_leaf);
+DEFINE_DIR2_EVENT(xfs_dir2_leaf_addname);
+DEFINE_DIR2_EVENT(xfs_dir2_leaf_lookup);
+DEFINE_DIR2_EVENT(xfs_dir2_leaf_replace);
+DEFINE_DIR2_EVENT(xfs_dir2_leaf_removename);
+DEFINE_DIR2_EVENT(xfs_dir2_leaf_to_block);
+DEFINE_DIR2_EVENT(xfs_dir2_leaf_to_node);
+DEFINE_DIR2_EVENT(xfs_dir2_node_addname);
+DEFINE_DIR2_EVENT(xfs_dir2_node_lookup);
+DEFINE_DIR2_EVENT(xfs_dir2_node_replace);
+DEFINE_DIR2_EVENT(xfs_dir2_node_removename);
+DEFINE_DIR2_EVENT(xfs_dir2_node_to_leaf);
+
+DECLARE_EVENT_CLASS(xfs_dir2_space_class,
+       TP_PROTO(struct xfs_da_args *args, int idx),
+       TP_ARGS(args, idx),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(int, op_flags)
+               __field(int, idx)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(args->dp)->i_sb->s_dev;
+               __entry->ino = args->dp->i_ino;
+               __entry->op_flags = args->op_flags;
+               __entry->idx = idx;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx op_flags %s index %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __print_flags(__entry->op_flags, "|", XFS_DA_OP_FLAGS),
+                 __entry->idx)
 )
-DEFINE_DIR2_TRACE(xfs_dir2_sf_addname);
-DEFINE_DIR2_TRACE(xfs_dir2_sf_create);
-DEFINE_DIR2_TRACE(xfs_dir2_sf_lookup);
-DEFINE_DIR2_TRACE(xfs_dir2_sf_replace);
-DEFINE_DIR2_TRACE(xfs_dir2_sf_removename);
-DEFINE_DIR2_TRACE(xfs_dir2_sf_toino4);
-DEFINE_DIR2_TRACE(xfs_dir2_sf_toino8);
-DEFINE_DIR2_TRACE(xfs_dir2_sf_to_block);
-DEFINE_DIR2_TRACE(xfs_dir2_block_addname);
-DEFINE_DIR2_TRACE(xfs_dir2_block_lookup);
-DEFINE_DIR2_TRACE(xfs_dir2_block_replace);
-DEFINE_DIR2_TRACE(xfs_dir2_block_removename);
-DEFINE_DIR2_TRACE(xfs_dir2_block_to_sf);
-DEFINE_DIR2_TRACE(xfs_dir2_block_to_leaf);
-DEFINE_DIR2_TRACE(xfs_dir2_leaf_addname);
-DEFINE_DIR2_TRACE(xfs_dir2_leaf_lookup);
-DEFINE_DIR2_TRACE(xfs_dir2_leaf_replace);
-DEFINE_DIR2_TRACE(xfs_dir2_leaf_removename);
-DEFINE_DIR2_TRACE(xfs_dir2_leaf_to_block);
-DEFINE_DIR2_TRACE(xfs_dir2_leaf_to_node);
-DEFINE_DIR2_TRACE(xfs_dir2_node_addname);
-DEFINE_DIR2_TRACE(xfs_dir2_node_lookup);
-DEFINE_DIR2_TRACE(xfs_dir2_node_replace);
-DEFINE_DIR2_TRACE(xfs_dir2_node_removename);
-DEFINE_DIR2_TRACE(xfs_dir2_node_to_leaf);
 
-#define DEFINE_DIR2_SPACE_TRACE(tname) \
-TRACE_EVENT(tname, \
+#define DEFINE_DIR2_SPACE_EVENT(name) \
+DEFINE_EVENT(xfs_dir2_space_class, name, \
        TP_PROTO(struct xfs_da_args *args, int idx), \
-       TP_ARGS(args, idx), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __field(int, op_flags) \
-               __field(int, idx) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = VFS_I(args->dp)->i_sb->s_dev; \
-               __entry->ino = args->dp->i_ino; \
-               __entry->op_flags = args->op_flags; \
-               __entry->idx = idx; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx op_flags %s index %d", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino, \
-                 __print_flags(__entry->op_flags, "|", XFS_DA_OP_FLAGS), \
-                 __entry->idx) \
-)
-DEFINE_DIR2_SPACE_TRACE(xfs_dir2_leafn_add);
-DEFINE_DIR2_SPACE_TRACE(xfs_dir2_leafn_remove);
-DEFINE_DIR2_SPACE_TRACE(xfs_dir2_grow_inode);
-DEFINE_DIR2_SPACE_TRACE(xfs_dir2_shrink_inode);
+       TP_ARGS(args, idx))
+DEFINE_DIR2_SPACE_EVENT(xfs_dir2_leafn_add);
+DEFINE_DIR2_SPACE_EVENT(xfs_dir2_leafn_remove);
+DEFINE_DIR2_SPACE_EVENT(xfs_dir2_grow_inode);
+DEFINE_DIR2_SPACE_EVENT(xfs_dir2_shrink_inode);
 
 TRACE_EVENT(xfs_dir2_leafn_moveents,
        TP_PROTO(struct xfs_da_args *args, int src_idx, int dst_idx, int count),
index a1c65fc6d9c4dfc382da05ddbc0f66d1cac6e8cb..275b1f4f9430d5c214fba1703b3724b0de631f8a 100644 (file)
@@ -2563,43 +2563,41 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
        xfs_mount_t             *mp;
        xfs_perag_busy_t        *bsy;
        xfs_agblock_t           uend, bend;
-       xfs_lsn_t               lsn;
+       xfs_lsn_t               lsn = 0;
        int                     cnt;
 
        mp = tp->t_mountp;
 
        spin_lock(&mp->m_perag[agno].pagb_lock);
-       cnt = mp->m_perag[agno].pagb_count;
 
        uend = bno + len - 1;
 
-       /* search pagb_list for this slot, skipping open slots */
-       for (bsy = mp->m_perag[agno].pagb_list; cnt; bsy++) {
+       /*
+        * search pagb_list for this slot, skipping open slots. We have to
+        * search the entire array as there may be multiple overlaps and
+        * we have to get the most recent LSN for the log force to push out
+        * all the transactions that span the range.
+        */
+       for (cnt = 0; cnt < mp->m_perag[agno].pagb_count; cnt++) {
+               bsy = &mp->m_perag[agno].pagb_list[cnt];
+               if (!bsy->busy_tp)
+                       continue;
 
-               /*
-                * (start1,length1) within (start2, length2)
-                */
-               if (bsy->busy_tp != NULL) {
-                       bend = bsy->busy_start + bsy->busy_length - 1;
-                       if ((bno > bend) || (uend < bsy->busy_start)) {
-                               cnt--;
-                       } else {
-                               break;
-                       }
-               }
-       }
+               bend = bsy->busy_start + bsy->busy_length - 1;
+               if (bno > bend || uend < bsy->busy_start)
+                       continue;
 
-       trace_xfs_alloc_busysearch(mp, agno, bno, len, !!cnt);
+               /* (start1,length1) within (start2, length2) */
+               if (XFS_LSN_CMP(bsy->busy_tp->t_commit_lsn, lsn) > 0)
+                       lsn = bsy->busy_tp->t_commit_lsn;
+       }
+       spin_unlock(&mp->m_perag[agno].pagb_lock);
+       trace_xfs_alloc_busysearch(tp->t_mountp, agno, bno, len, lsn);
 
        /*
         * If a block was found, force the log through the LSN of the
         * transaction that freed the block
         */
-       if (cnt) {
-               lsn = bsy->busy_tp->t_commit_lsn;
-               spin_unlock(&mp->m_perag[agno].pagb_lock);
+       if (lsn)
                xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
-       } else {
-               spin_unlock(&mp->m_perag[agno].pagb_lock);
-       }
 }
index ce278b3ae7fcb607ff1f6d5e9e13b621744e95bb..391d36b0e68c2a33b769dd66540148e94e7da3f2 100644 (file)
@@ -2841,10 +2841,14 @@ xfs_iflush(
        mp = ip->i_mount;
 
        /*
-        * If the inode isn't dirty, then just release the inode
-        * flush lock and do nothing.
+        * If the inode isn't dirty, then just release the inode flush lock and
+        * do nothing. Treat stale inodes the same; we cannot rely on the
+        * backing buffer remaining stale in cache for the remaining life of
+        * the stale inode and so xfs_itobp() below may give us a buffer that
+        * no longer contains inodes below. Doing this stale check here also
+        * avoids forcing the log on pinned, stale inodes.
         */
-       if (xfs_inode_clean(ip)) {
+       if (xfs_inode_clean(ip) || xfs_iflags_test(ip, XFS_ISTALE)) {
                xfs_ifunlock(ip);
                return 0;
        }
index 6558ffd8d140683bdb1eaebb0e201dcdba3b04e7..6f268756bf3632e376035e3b7402e29fb0319920 100644 (file)
@@ -70,7 +70,6 @@ xfs_setattr(
        uint                    commit_flags=0;
        uid_t                   uid=0, iuid=0;
        gid_t                   gid=0, igid=0;
-       int                     timeflags = 0;
        struct xfs_dquot        *udqp, *gdqp, *olddquot1, *olddquot2;
        int                     need_iolock = 1;
 
@@ -135,16 +134,13 @@ xfs_setattr(
        if (flags & XFS_ATTR_NOLOCK)
                need_iolock = 0;
        if (!(mask & ATTR_SIZE)) {
-               if ((mask != (ATTR_CTIME|ATTR_ATIME|ATTR_MTIME)) ||
-                   (mp->m_flags & XFS_MOUNT_WSYNC)) {
-                       tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
-                       commit_flags = 0;
-                       if ((code = xfs_trans_reserve(tp, 0,
-                                                    XFS_ICHANGE_LOG_RES(mp), 0,
-                                                    0, 0))) {
-                               lock_flags = 0;
-                               goto error_return;
-                       }
+               tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
+               commit_flags = 0;
+               code = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp),
+                                        0, 0, 0);
+               if (code) {
+                       lock_flags = 0;
+                       goto error_return;
                }
        } else {
                if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) &&
@@ -295,15 +291,23 @@ xfs_setattr(
                 * or we are explicitly asked to change it. This handles
                 * the semantic difference between truncate() and ftruncate()
                 * as implemented in the VFS.
+                *
+                * The regular truncate() case without ATTR_CTIME and ATTR_MTIME
+                * is a special case where we need to update the times despite
+                * not having these flags set.  For all other operations the
+                * VFS set these flags explicitly if it wants a timestamp
+                * update.
                 */
-               if (iattr->ia_size != ip->i_size || (mask & ATTR_CTIME))
-                       timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
+               if (iattr->ia_size != ip->i_size &&
+                   (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
+                       iattr->ia_ctime = iattr->ia_mtime =
+                               current_fs_time(inode->i_sb);
+                       mask |= ATTR_CTIME | ATTR_MTIME;
+               }
 
                if (iattr->ia_size > ip->i_size) {
                        ip->i_d.di_size = iattr->ia_size;
                        ip->i_size = iattr->ia_size;
-                       if (!(flags & XFS_ATTR_DMI))
-                               xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
                        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
                } else if (iattr->ia_size <= ip->i_size ||
                           (iattr->ia_size == 0 && ip->i_d.di_nextents)) {
@@ -374,9 +378,6 @@ xfs_setattr(
                        ip->i_d.di_gid = gid;
                        inode->i_gid = gid;
                }
-
-               xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
-               timeflags |= XFS_ICHGTIME_CHG;
        }
 
        /*
@@ -393,51 +394,37 @@ xfs_setattr(
 
                inode->i_mode &= S_IFMT;
                inode->i_mode |= mode & ~S_IFMT;
-
-               xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-               timeflags |= XFS_ICHGTIME_CHG;
        }
 
        /*
         * Change file access or modified times.
         */
-       if (mask & (ATTR_ATIME|ATTR_MTIME)) {
-               if (mask & ATTR_ATIME) {
-                       inode->i_atime = iattr->ia_atime;
-                       ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
-                       ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
-                       ip->i_update_core = 1;
-               }
-               if (mask & ATTR_MTIME) {
-                       inode->i_mtime = iattr->ia_mtime;
-                       ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
-                       ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
-                       timeflags &= ~XFS_ICHGTIME_MOD;
-                       timeflags |= XFS_ICHGTIME_CHG;
-               }
-               if (tp && (mask & (ATTR_MTIME_SET|ATTR_ATIME_SET)))
-                       xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
+       if (mask & ATTR_ATIME) {
+               inode->i_atime = iattr->ia_atime;
+               ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
+               ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
+               ip->i_update_core = 1;
        }
-
-       /*
-        * Change file inode change time only if ATTR_CTIME set
-        * AND we have been called by a DMI function.
-        */
-
-       if ((flags & XFS_ATTR_DMI) && (mask & ATTR_CTIME)) {
+       if (mask & ATTR_CTIME) {
                inode->i_ctime = iattr->ia_ctime;
                ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
                ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
                ip->i_update_core = 1;
-               timeflags &= ~XFS_ICHGTIME_CHG;
+       }
+       if (mask & ATTR_MTIME) {
+               inode->i_mtime = iattr->ia_mtime;
+               ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
+               ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
+               ip->i_update_core = 1;
        }
 
        /*
-        * Send out timestamp changes that need to be set to the
-        * current time.  Not done when called by a DMI function.
+        * And finally, log the inode core if any attribute in it
+        * has been changed.
         */
-       if (timeflags && !(flags & XFS_ATTR_DMI))
-               xfs_ichgtime(ip, timeflags);
+       if (mask & (ATTR_UID|ATTR_GID|ATTR_MODE|
+                   ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
+               xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
        XFS_STATS_INC(xs_ig_attrchg);
 
@@ -452,12 +439,10 @@ xfs_setattr(
         * mix so this probably isn't worth the trouble to optimize.
         */
        code = 0;
-       if (tp) {
-               if (mp->m_flags & XFS_MOUNT_WSYNC)
-                       xfs_trans_set_sync(tp);
+       if (mp->m_flags & XFS_MOUNT_WSYNC)
+               xfs_trans_set_sync(tp);
 
-               code = xfs_trans_commit(tp, commit_flags);
-       }
+       code = xfs_trans_commit(tp, commit_flags);
 
        xfs_iunlock(ip, lock_flags);
 
index 71dafb69cfeb2fc5baf60d639f6c3210a826cc2d..ffac157fb5b2958aa33df80184a535a5fb5b9af6 100644 (file)
@@ -1408,7 +1408,7 @@ extern int drm_ati_pcigart_cleanup(struct drm_device *dev,
                                   struct drm_ati_pcigart_info * gart_info);
 
 extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
-                                      size_t align, dma_addr_t maxaddr);
+                                      size_t align);
 extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
 extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
 
index 43009bc2e7574ff4dda9f451f25e47abb10d0c06..bc4fdf27bd2ec36ea884c2b0537eee1418117f1b 100644 (file)
@@ -160,6 +160,7 @@ struct drm_mode_get_encoder {
 #define DRM_MODE_CONNECTOR_HDMIA       11
 #define DRM_MODE_CONNECTOR_HDMIB       12
 #define DRM_MODE_CONNECTOR_TV          13
+#define DRM_MODE_CONNECTOR_eDP         14
 
 struct drm_mode_get_connector {
 
index ec3f5e80a5df7f6e0148adf67001108864c788ce..b64a8d7cdf6d291205f8b89edf3a78d4a6a4d9c6 100644 (file)
@@ -188,6 +188,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_MADVISE   0x26
 #define DRM_I915_OVERLAY_PUT_IMAGE     0x27
 #define DRM_I915_OVERLAY_ATTRS 0x28
+#define DRM_I915_GEM_EXECBUFFER2       0x29
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -207,6 +208,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_VBLANK_SWAP     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
 #define DRM_IOCTL_I915_GEM_INIT                DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
 #define DRM_IOCTL_I915_GEM_EXECBUFFER  DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
+#define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
 #define DRM_IOCTL_I915_GEM_PIN         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
 #define DRM_IOCTL_I915_GEM_UNPIN       DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
 #define DRM_IOCTL_I915_GEM_BUSY                DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
@@ -272,6 +274,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_NUM_FENCES_AVAIL      6
 #define I915_PARAM_HAS_OVERLAY           7
 #define I915_PARAM_HAS_PAGEFLIPPING     8
+#define I915_PARAM_HAS_EXECBUF2          9
 
 typedef struct drm_i915_getparam {
        int param;
@@ -567,6 +570,57 @@ struct drm_i915_gem_execbuffer {
        __u64 cliprects_ptr;
 };
 
+struct drm_i915_gem_exec_object2 {
+       /**
+        * User's handle for a buffer to be bound into the GTT for this
+        * operation.
+        */
+       __u32 handle;
+
+       /** Number of relocations to be performed on this buffer */
+       __u32 relocation_count;
+       /**
+        * Pointer to array of struct drm_i915_gem_relocation_entry containing
+        * the relocations to be performed in this buffer.
+        */
+       __u64 relocs_ptr;
+
+       /** Required alignment in graphics aperture */
+       __u64 alignment;
+
+       /**
+        * Returned value of the updated offset of the object, for future
+        * presumed_offset writes.
+        */
+       __u64 offset;
+
+#define EXEC_OBJECT_NEEDS_FENCE (1<<0)
+       __u64 flags;
+       __u64 rsvd1;
+       __u64 rsvd2;
+};
+
+struct drm_i915_gem_execbuffer2 {
+       /**
+        * List of gem_exec_object2 structs
+        */
+       __u64 buffers_ptr;
+       __u32 buffer_count;
+
+       /** Offset in the batchbuffer to start execution from. */
+       __u32 batch_start_offset;
+       /** Bytes used in batchbuffer from batch_start_offset */
+       __u32 batch_len;
+       __u32 DR1;
+       __u32 DR4;
+       __u32 num_cliprects;
+       /** This is a struct drm_clip_rect *cliprects */
+       __u64 cliprects_ptr;
+       __u64 flags; /* currently unused */
+       __u64 rsvd1;
+       __u64 rsvd2;
+};
+
 struct drm_i915_gem_pin {
        /** Handle of the buffer to be pinned. */
        __u32 handle;
index ce945d4845fcc158c3e493a7d64c986cad7e1072..36924255c0d541ad97dc0d8525c3481a7d60478f 100644 (file)
@@ -251,6 +251,7 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
 void __init acpi_no_s4_hw_signature(void);
 void __init acpi_old_suspend_ordering(void);
 void __init acpi_s4_no_nvs(void);
+void __init acpi_set_sci_en_on_resume(void);
 #endif /* CONFIG_PM_SLEEP */
 
 struct acpi_osc_context {
index 784a919aa0d0e05bf978f56f97a2f6eb4e6451e1..9b98173a81845bc4dc61b0bb30a516e738c4ec5d 100644 (file)
@@ -845,7 +845,6 @@ static inline struct request_queue *bdev_get_queue(struct block_device *bdev)
  * blk_rq_err_bytes()          : bytes left till the next error boundary
  * blk_rq_sectors()            : sectors left in the entire request
  * blk_rq_cur_sectors()                : sectors left in the current segment
- * blk_rq_err_sectors()                : sectors left till the next error boundary
  */
 static inline sector_t blk_rq_pos(const struct request *rq)
 {
@@ -874,11 +873,6 @@ static inline unsigned int blk_rq_cur_sectors(const struct request *rq)
        return blk_rq_cur_bytes(rq) >> 9;
 }
 
-static inline unsigned int blk_rq_err_sectors(const struct request *rq)
-{
-       return blk_rq_err_bytes(rq) >> 9;
-}
-
 /*
  * Request issue related functions.
  */
@@ -1116,11 +1110,18 @@ static inline int queue_alignment_offset(struct request_queue *q)
        return q->limits.alignment_offset;
 }
 
+static inline int queue_limit_alignment_offset(struct queue_limits *lim, sector_t offset)
+{
+       unsigned int granularity = max(lim->physical_block_size, lim->io_min);
+
+       offset &= granularity - 1;
+       return (granularity + lim->alignment_offset - offset) & (granularity - 1);
+}
+
 static inline int queue_sector_alignment_offset(struct request_queue *q,
                                                sector_t sector)
 {
-       return ((sector << 9) - q->limits.alignment_offset)
-               & (q->limits.io_min - 1);
+       return queue_limit_alignment_offset(&q->limits, sector << 9);
 }
 
 static inline int bdev_alignment_offset(struct block_device *bdev)
diff --git a/include/linux/decompress/unlzo.h b/include/linux/decompress/unlzo.h
new file mode 100644 (file)
index 0000000..9872297
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef DECOMPRESS_UNLZO_H
+#define DECOMPRESS_UNLZO_H
+
+int unlzo(unsigned char *inbuf, int len,
+       int(*fill)(void*, unsigned int),
+       int(*flush)(void*, unsigned int),
+       unsigned char *output,
+       int *pos,
+       void(*error)(char *x));
+#endif
index c6b3ca3af6df6ce93614d3f6df59986b15fc4fd8..1f716d9f714b05b00d949891fd0b550e48fbee36 100644 (file)
@@ -340,6 +340,9 @@ struct fw_cdev_send_response {
  * The @closure field is passed back to userspace in the response event.
  * The @handle field is an out parameter, returning a handle to the allocated
  * range to be used for later deallocation of the range.
+ *
+ * The address range is allocated on all local nodes.  The address allocation
+ * is exclusive except for the FCP command and response registers.
  */
 struct fw_cdev_allocate {
        __u64 offset;
index 9416a461b69654b78bf51532cbecff7654f83c8e..a0e67150a729cadbc6782ab70821b2d5981a09ab 100644 (file)
@@ -248,8 +248,8 @@ typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode,
                                          void *data, size_t length,
                                          void *callback_data);
 /*
- * Important note:  The callback must guarantee that either fw_send_response()
- * or kfree() is called on the @request.
+ * Important note:  Except for the FCP registers, the callback must guarantee
+ * that either fw_send_response() or kfree() is called on the @request.
  */
 typedef void (*fw_address_callback_t)(struct fw_card *card,
                                      struct fw_request *request,
index 211ff4497269e8228951524c8bf2b01a7d1dbeb3..ab2cc20e21a5c381a1912a5bfe54aa7bdb293c50 100644 (file)
@@ -46,7 +46,7 @@ void kmap_flush_unused(void);
 
 static inline unsigned int nr_free_highpages(void) { return 0; }
 
-#define totalhigh_pages 0
+#define totalhigh_pages 0UL
 
 #ifndef ARCH_HAS_KMAP
 static inline void *kmap(struct page *page)
index fc5db826b48e610f75c951958198773205d36072..02c9af374741835efb1feaa1cd0c4f7bcc7e80dd 100644 (file)
@@ -89,4 +89,16 @@ struct adp5588_kpad_platform_data {
        unsigned short unlock_key2;     /* Unlock Key 2 */
 };
 
+struct adp5588_gpio_platform_data {
+       unsigned gpio_start;            /* GPIO Chip base # */
+       unsigned pullup_dis_mask;       /* Pull-Up Disable Mask */
+       int     (*setup)(struct i2c_client *client,
+                               int gpio, unsigned ngpio,
+                               void *context);
+       int     (*teardown)(struct i2c_client *client,
+                               int gpio, unsigned ngpio,
+                               void *context);
+       void    *context;
+};
+
 #endif
index d9724a28c0c295db1ceeeb7427d1a7873ae45e00..163c840437d604ca9993b3fc70e3349a3fabd199 100644 (file)
@@ -832,7 +832,7 @@ struct ieee80211_ht_cap {
 #define IEEE80211_HT_CAP_DELAY_BA              0x0400
 #define IEEE80211_HT_CAP_MAX_AMSDU             0x0800
 #define IEEE80211_HT_CAP_DSSSCCK40             0x1000
-#define IEEE80211_HT_CAP_PSMP_SUPPORT          0x2000
+#define IEEE80211_HT_CAP_RESERVED              0x2000
 #define IEEE80211_HT_CAP_40MHZ_INTOLERANT      0x4000
 #define IEEE80211_HT_CAP_LSIG_TXOP_PROT                0x8000
 
index 699e85c01a4d78efcf0df4ac0fb61f01e736ee5c..b2304929434e27591a750ff7b8dbb066fa2b5759 100644 (file)
@@ -81,6 +81,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
 #define IN_DEV_FORWARD(in_dev)         IN_DEV_CONF_GET((in_dev), FORWARDING)
 #define IN_DEV_MFORWARD(in_dev)                IN_DEV_ANDCONF((in_dev), MC_FORWARDING)
 #define IN_DEV_RPFILTER(in_dev)                IN_DEV_MAXCONF((in_dev), RP_FILTER)
+#define IN_DEV_SRC_VMARK(in_dev)       IN_DEV_ORCONF((in_dev), SRC_VMARK)
 #define IN_DEV_SOURCE_ROUTE(in_dev)    IN_DEV_ANDCONF((in_dev), \
                                                       ACCEPT_SOURCE_ROUTE)
 #define IN_DEV_ACCEPT_LOCAL(in_dev)    IN_DEV_ORCONF((in_dev), ACCEPT_LOCAL)
index f1011f7f3d4142bf5771007661cec4cd8a6c3315..638ce4554c76e903d632720b3d25dea3350c745b 100644 (file)
@@ -653,6 +653,7 @@ struct transaction_s
         * waiting for it to finish.
         */
        unsigned int t_synchronous_commit:1;
+       unsigned int t_flushed_data_blocks:1;
 
        /*
         * For use by the filesystem to store fs-specific data
index 3d44e9c65a8e3afa5621b8f771f7e0b54dc40515..7c6b32a1421c000b33f1fa924f3f7ec43b32c551 100644 (file)
@@ -81,7 +81,7 @@ union { \
 }
 
 /**
- * INIT_KFIFO - Initialize a kfifo declared by DECLARED_KFIFO
+ * INIT_KFIFO - Initialize a kfifo declared by DECLARE_KFIFO
  * @name: name of the declared kfifo datatype
  */
 #define INIT_KFIFO(name) \
index 6adcc297e35408f45990ce5263f006827a08b062..19ec41a183f58f0e82c2a5a9fa840c2a11b2b6fb 100644 (file)
@@ -29,8 +29,7 @@ struct pt_regs;
  *
  *     On some architectures it is required to skip a breakpoint
  *     exception when it occurs after a breakpoint has been removed.
- *     This can be implemented in the architecture specific portion of
- *     for kgdb.
+ *     This can be implemented in the architecture specific portion of kgdb.
  */
 extern int kgdb_skipexception(int exception, struct pt_regs *regs);
 
@@ -65,7 +64,7 @@ struct uart_port;
 /**
  *     kgdb_breakpoint - compiled in breakpoint
  *
- *     This will be impelmented a static inline per architecture.  This
+ *     This will be implemented as a static inline per architecture.  This
  *     function is called by the kgdb core to execute an architecture
  *     specific trap to cause kgdb to enter the exception processing.
  *
@@ -190,7 +189,7 @@ kgdb_arch_handle_exception(int vector, int signo, int err_code,
  *     @flags: Current IRQ state
  *
  *     On SMP systems, we need to get the attention of the other CPUs
- *     and get them be in a known state.  This should do what is needed
+ *     and get them into a known state.  This should do what is needed
  *     to get the other CPUs to call kgdb_wait(). Note that on some arches,
  *     the NMI approach is not used for rounding up all the CPUs. For example,
  *     in case of MIPS, smp_call_function() is used to roundup CPUs. In
index e880d4cf9e223d1e4ca4b8e4ebe655f599a52b16..08d7dc4ddf40b57047d1f1304be6b02dac2f2063 100644 (file)
@@ -36,6 +36,56 @@ int kmemcheck_hide_addr(unsigned long address);
 
 bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size);
 
+/*
+ * Bitfield annotations
+ *
+ * How to use: If you have a struct using bitfields, for example
+ *
+ *     struct a {
+ *             int x:8, y:8;
+ *     };
+ *
+ * then this should be rewritten as
+ *
+ *     struct a {
+ *             kmemcheck_bitfield_begin(flags);
+ *             int x:8, y:8;
+ *             kmemcheck_bitfield_end(flags);
+ *     };
+ *
+ * Now the "flags_begin" and "flags_end" members may be used to refer to the
+ * beginning and end, respectively, of the bitfield (and things like
+ * &x.flags_begin is allowed). As soon as the struct is allocated, the bit-
+ * fields should be annotated:
+ *
+ *     struct a *a = kmalloc(sizeof(struct a), GFP_KERNEL);
+ *     kmemcheck_annotate_bitfield(a, flags);
+ */
+#define kmemcheck_bitfield_begin(name) \
+       int name##_begin[0];
+
+#define kmemcheck_bitfield_end(name)   \
+       int name##_end[0];
+
+#define kmemcheck_annotate_bitfield(ptr, name)                         \
+       do {                                                            \
+               int _n;                                                 \
+                                                                       \
+               if (!ptr)                                               \
+                       break;                                          \
+                                                                       \
+               _n = (long) &((ptr)->name##_end)                        \
+                       - (long) &((ptr)->name##_begin);                \
+               MAYBE_BUILD_BUG_ON(_n < 0);                             \
+                                                                       \
+               kmemcheck_mark_initialized(&((ptr)->name##_begin), _n); \
+       } while (0)
+
+#define kmemcheck_annotate_variable(var)                               \
+       do {                                                            \
+               kmemcheck_mark_initialized(&(var), sizeof(var));        \
+       } while (0)                                                     \
+
 #else
 #define kmemcheck_enabled 0
 
@@ -106,60 +156,16 @@ static inline bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size)
        return true;
 }
 
-#endif /* CONFIG_KMEMCHECK */
-
-/*
- * Bitfield annotations
- *
- * How to use: If you have a struct using bitfields, for example
- *
- *     struct a {
- *             int x:8, y:8;
- *     };
- *
- * then this should be rewritten as
- *
- *     struct a {
- *             kmemcheck_bitfield_begin(flags);
- *             int x:8, y:8;
- *             kmemcheck_bitfield_end(flags);
- *     };
- *
- * Now the "flags_begin" and "flags_end" members may be used to refer to the
- * beginning and end, respectively, of the bitfield (and things like
- * &x.flags_begin is allowed). As soon as the struct is allocated, the bit-
- * fields should be annotated:
- *
- *     struct a *a = kmalloc(sizeof(struct a), GFP_KERNEL);
- *     kmemcheck_annotate_bitfield(a, flags);
- *
- * Note: We provide the same definitions for both kmemcheck and non-
- * kmemcheck kernels. This makes it harder to introduce accidental errors. It
- * is also allowed to pass NULL pointers to kmemcheck_annotate_bitfield().
- */
-#define kmemcheck_bitfield_begin(name) \
-       int name##_begin[0];
-
-#define kmemcheck_bitfield_end(name)   \
-       int name##_end[0];
+#define kmemcheck_bitfield_begin(name)
+#define kmemcheck_bitfield_end(name)
+#define kmemcheck_annotate_bitfield(ptr, name) \
+       do {                                    \
+       } while (0)
 
-#define kmemcheck_annotate_bitfield(ptr, name)                         \
-       do {                                                            \
-               int _n;                                                 \
-                                                                       \
-               if (!ptr)                                               \
-                       break;                                          \
-                                                                       \
-               _n = (long) &((ptr)->name##_end)                        \
-                       - (long) &((ptr)->name##_begin);                \
-               MAYBE_BUILD_BUG_ON(_n < 0);                             \
-                                                                       \
-               kmemcheck_mark_initialized(&((ptr)->name##_begin), _n); \
+#define kmemcheck_annotate_variable(var)       \
+       do {                                    \
        } while (0)
 
-#define kmemcheck_annotate_variable(var)                               \
-       do {                                                            \
-               kmemcheck_mark_initialized(&(var), sizeof(var));        \
-       } while (0)                                                     \
+#endif /* CONFIG_KMEMCHECK */
 
 #endif /* LINUX_KMEMCHECK_H */
index 84a524afb3dcdffdd60c7ef1eaf2672acd7731ca..84d020bed0830eecb4ffd3e678d2c64f7ff4ddc1 100644 (file)
@@ -123,6 +123,8 @@ struct vm_region {
        struct file     *vm_file;       /* the backing file or NULL */
 
        atomic_t        vm_usage;       /* region usage count */
+       bool            vm_icache_flushed : 1; /* true if the icache has been flushed for
+                                               * this region */
 };
 
 /*
index bf1e6708084909b786f19a6fdb095b1573b53df4..174e5392e51ed29975ed0439facc0d6e77af600c 100644 (file)
@@ -243,6 +243,7 @@ struct pci_dev {
        unsigned int    d2_support:1;   /* Low power state D2 is supported */
        unsigned int    no_d1d2:1;      /* Only allow D0 and D3 */
        unsigned int    wakeup_prepared:1;
+       unsigned int    d3_delay;       /* D3->D0 transition time in ms */
 
 #ifdef CONFIG_PCIEASPM
        struct pcie_link_state  *link_state;    /* ASPM link state. */
@@ -566,6 +567,9 @@ void pcibios_align_resource(void *, struct resource *, resource_size_t,
                                resource_size_t);
 void pcibios_update_irq(struct pci_dev *, int irq);
 
+/* Weak but can be overriden by arch */
+void pci_fixup_cardbus(struct pci_bus *);
+
 /* Generic PCI functions used internally */
 
 extern struct pci_bus *pci_find_bus(int domain, int busnr);
index 7fc194aef8c23cc8bfe1ac4a98be55486a8b9d64..2110a81c5e2afaab47ec5cb107cf17503d731317 100644 (file)
@@ -2,13 +2,25 @@
 #define _LINUX_POISON_H
 
 /********** include/linux/list.h **********/
+
+/*
+ * Architectures might want to move the poison pointer offset
+ * into some well-recognized area such as 0xdead000000000000,
+ * that is also not mappable by user-space exploits:
+ */
+#ifdef CONFIG_ILLEGAL_POINTER_VALUE
+# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
+#else
+# define POISON_POINTER_DELTA 0
+#endif
+
 /*
  * These are non-NULL pointers that will result in page faults
  * under normal circumstances, used to verify that nobody uses
  * non-initialized list entries.
  */
-#define LIST_POISON1  ((void *) 0x00100100)
-#define LIST_POISON2  ((void *) 0x00200200)
+#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
+#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)
 
 /********** include/linux/timer.h **********/
 /*
index c96c1858fe2c404673810c33560ce0c56701d566..1ba3cf6edfbb4d80f17f76411c19360a0ac978c6 100644 (file)
@@ -62,6 +62,12 @@ void reiserfs_write_unlock(struct super_block *s);
 int reiserfs_write_lock_once(struct super_block *s);
 void reiserfs_write_unlock_once(struct super_block *s, int lock_depth);
 
+#ifdef CONFIG_REISERFS_CHECK
+void reiserfs_lock_check_recursive(struct super_block *s);
+#else
+static inline void reiserfs_lock_check_recursive(struct super_block *s) { }
+#endif
+
 /*
  * Several mutexes depend on the write lock.
  * However sometimes we want to relax the write lock while we hold
@@ -92,11 +98,31 @@ void reiserfs_write_unlock_once(struct super_block *s, int lock_depth);
 static inline void reiserfs_mutex_lock_safe(struct mutex *m,
                               struct super_block *s)
 {
+       reiserfs_lock_check_recursive(s);
        reiserfs_write_unlock(s);
        mutex_lock(m);
        reiserfs_write_lock(s);
 }
 
+static inline void
+reiserfs_mutex_lock_nested_safe(struct mutex *m, unsigned int subclass,
+                              struct super_block *s)
+{
+       reiserfs_lock_check_recursive(s);
+       reiserfs_write_unlock(s);
+       mutex_lock_nested(m, subclass);
+       reiserfs_write_lock(s);
+}
+
+static inline void
+reiserfs_down_read_safe(struct rw_semaphore *sem, struct super_block *s)
+{
+       reiserfs_lock_check_recursive(s);
+       reiserfs_write_unlock(s);
+       down_read(sem);
+       reiserfs_write_lock(s);
+}
+
 /*
  * When we schedule, we usually want to also release the write lock,
  * according to the previous bkl based locking scheme of reiserfs.
index 40fc7e62608220e9a64dd70493c3b091fa49a0b7..f1e914eefeab89fc246a2e266a22b7e66111717b 100644 (file)
@@ -3,8 +3,6 @@
 
 #include <linux/time.h>
 
-struct task_struct;
-
 /*
  * Resource control/accounting header file for linux
  */
@@ -70,6 +68,12 @@ struct rlimit {
  */
 #include <asm/resource.h>
 
+#ifdef __KERNEL__
+
+struct task_struct;
+
 int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
 
+#endif /* __KERNEL__ */
+
 #endif
index f2f842db03cea4e1d082f6d45596ba3c3c52e1a1..8d4991be9d53800a8c3cfd4a67cf0879d9ea62e7 100644 (file)
@@ -2601,6 +2601,28 @@ static inline void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
 }
 #endif /* CONFIG_MM_OWNER */
 
+static inline unsigned long task_rlimit(const struct task_struct *tsk,
+               unsigned int limit)
+{
+       return ACCESS_ONCE(tsk->signal->rlim[limit].rlim_cur);
+}
+
+static inline unsigned long task_rlimit_max(const struct task_struct *tsk,
+               unsigned int limit)
+{
+       return ACCESS_ONCE(tsk->signal->rlim[limit].rlim_max);
+}
+
+static inline unsigned long rlimit(unsigned int limit)
+{
+       return task_rlimit(current, limit);
+}
+
+static inline unsigned long rlimit_max(unsigned int limit)
+{
+       return task_rlimit_max(current, limit);
+}
+
 #endif /* __KERNEL__ */
 
 #endif
index 65793e90d6f64f1865230412638a8b52679d1431..207466a49f3d59b9d0927670c379d8be091a4d37 100644 (file)
@@ -195,7 +195,7 @@ struct perf_event_attr;
        static const struct syscall_metadata __used             \
          __attribute__((__aligned__(4)))                       \
          __attribute__((section("__syscalls_metadata")))       \
-         __syscall_meta_##sname = {                            \
+         __syscall_meta__##sname = {                           \
                .name           = "sys_"#sname,                 \
                .nb_args        = 0,                            \
                .enter_event    = &event_enter__##sname,        \
index 877ba039e6a4b04a2adec72db41c429fc38c2a37..bd27fbc9db621eb6e96f365ed610d9a736cfcb3e 100644 (file)
@@ -482,6 +482,7 @@ enum
        NET_IPV4_CONF_ARP_ACCEPT=21,
        NET_IPV4_CONF_ARP_NOTIFY=22,
        NET_IPV4_CONF_ACCEPT_LOCAL=23,
+       NET_IPV4_CONF_SRC_VMARK=24,
        __NET_IPV4_CONF_MAX
 };
 
index 6b58367d145e8735eaebbf16bfec0733406389fb..d512d98dfb7dbae07b1669132e40af457da3e879 100644 (file)
@@ -94,6 +94,7 @@ static inline unsigned long __copy_from_user_nocache(void *to,
  * happens, handle that and return -EFAULT.
  */
 extern long probe_kernel_read(void *dst, void *src, size_t size);
+extern long __probe_kernel_read(void *dst, void *src, size_t size);
 
 /*
  * probe_kernel_write(): safely attempt to write to a location
@@ -104,6 +105,7 @@ extern long probe_kernel_read(void *dst, void *src, size_t size);
  * Safely write to address @dst from the buffer at @src.  If a kernel fault
  * happens, handle that and return -EFAULT.
  */
-extern long probe_kernel_write(void *dst, void *src, size_t size);
+extern long notrace probe_kernel_write(void *dst, void *src, size_t size);
+extern long notrace __probe_kernel_write(void *dst, void *src, size_t size);
 
 #endif         /* __LINUX_UACCESS_H__ */
index c18c008f4bbfffb3a59df701c2e366d35325e2df..76e8903cd204d4b2a21a8577a00150532c3dc24f 100644 (file)
@@ -70,6 +70,7 @@ struct writeback_control {
 struct bdi_writeback;
 int inode_wait(void *);
 void writeback_inodes_sb(struct super_block *);
+int writeback_inodes_sb_if_idle(struct super_block *);
 void sync_inodes_sb(struct super_block *);
 void writeback_inodes_wbc(struct writeback_control *wbc);
 long wb_do_writeback(struct bdi_writeback *wb, int force_wait);
index 2aff4906b2aeec8011b9de98e744d0b396a8232e..0bf369752274f39658ded037e961900895431058 100644 (file)
@@ -547,7 +547,6 @@ enum mac80211_rx_flags {
  *     unspecified depending on the hardware capabilities flags
  *     @IEEE80211_HW_SIGNAL_*
  * @noise: noise when receiving this frame, in dBm.
- * @qual: overall signal quality indication, in percent (0-100).
  * @antenna: antenna used
  * @rate_idx: index of data rate into band's supported rates or MCS index if
  *     HT rates are use (RX_FLAG_HT)
@@ -559,7 +558,6 @@ struct ieee80211_rx_status {
        int freq;
        int signal;
        int noise;
-       int __deprecated qual;
        int antenna;
        int rate_idx;
        int flag;
@@ -1737,6 +1735,12 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw,
        local_bh_enable();
 }
 
+/*
+ * The TX headroom reserved by mac80211 for its own tx_status functions.
+ * This is enough for the radiotap header.
+ */
+#define IEEE80211_TX_STATUS_HEADROOM   13
+
 /**
  * ieee80211_tx_status - transmit status callback
  *
index 07e3adde21d99ceff8c958e6c380ec32eb6b90a9..f4105c91af532d05de69b80cf513f52392b1a4a6 100644 (file)
@@ -2,6 +2,7 @@
 #define __LIBSRP_H__
 
 #include <linux/list.h>
+#include <linux/kfifo.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
 #include <scsi/srp.h>
index 73523151a731f61598702d7ccd2ab51fefb39aa7..c6fe03e902ca2c4502c984b79645d1d3648f2640 100644 (file)
@@ -414,7 +414,8 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags)    \
        BUILD_BUG_ON(len > MAX_FILTER_STR_VAL);                         \
        ret = trace_define_field(event_call, #type "[" #len "]", #item, \
                                 offsetof(typeof(field), item),         \
-                                sizeof(field.item), 0, FILTER_OTHER);  \
+                                sizeof(field.item),                    \
+                                is_signed_type(type), FILTER_OTHER);   \
        if (ret)                                                        \
                return ret;
 
@@ -422,8 +423,8 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags)    \
 #define __dynamic_array(type, item, len)                                      \
        ret = trace_define_field(event_call, "__data_loc " #type "[]", #item,  \
                                 offsetof(typeof(field), __data_loc_##item),   \
-                                sizeof(field.__data_loc_##item), 0,           \
-                                FILTER_OTHER);
+                                sizeof(field.__data_loc_##item),              \
+                                is_signed_type(type), FILTER_OTHER);
 
 #undef __string
 #define __string(item, src) __dynamic_array(char, item, -1)
index a23da9f0180341dd0cb8809f6108a2911336897a..d95ca7cd5d45f092fe33e175a577e0a94675c549 100644 (file)
@@ -115,10 +115,13 @@ config HAVE_KERNEL_BZIP2
 config HAVE_KERNEL_LZMA
        bool
 
+config HAVE_KERNEL_LZO
+       bool
+
 choice
        prompt "Kernel compression mode"
        default KERNEL_GZIP
-       depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA
+       depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_LZO
        help
          The linux kernel is a kind of self-extracting executable.
          Several compression algorithms are available, which differ
@@ -141,9 +144,8 @@ config KERNEL_GZIP
        bool "Gzip"
        depends on HAVE_KERNEL_GZIP
        help
-         The old and tried gzip compression. Its compression ratio is
-         the poorest among the 3 choices; however its speed (both
-         compression and decompression) is the fastest.
+         The old and tried gzip compression. It provides a good balance
+         between compression ratio and decompression speed.
 
 config KERNEL_BZIP2
        bool "Bzip2"
@@ -164,6 +166,14 @@ config KERNEL_LZMA
          two. Compression is slowest.  The kernel size is about 33%
          smaller with LZMA in comparison to gzip.
 
+config KERNEL_LZO
+       bool "LZO"
+       depends on HAVE_KERNEL_LZO
+       help
+         Its compression ratio is the poorest among the 4. The kernel
+         size is about about 10% bigger than gzip; however its speed
+         (both compression and decompression) is the fastest.
+
 endchoice
 
 config SWAP
index 0249f4be9b5cf8fefe9885b6093911746d7a9cdd..1fbcc748044a7f3dc367381838289ecce3992652 100644 (file)
@@ -2468,7 +2468,6 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp,
                        /* make sure l doesn't vanish out from under us */
                        down_write(&l->mutex);
                        mutex_unlock(&cgrp->pidlist_mutex);
-                       l->use_count++;
                        return l;
                }
        }
index dbcbf6a33a08d4f3a0d9b50469fa15162d81787b..50dbd599958838cdfeaf1512fcfd36135b97ebf2 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/percpu.h>
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/cpu.h>
 #include <linux/smp.h>
 
 #include <linux/hw_breakpoint.h>
@@ -388,7 +389,8 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr,
        if (!cpu_events)
                return ERR_PTR(-ENOMEM);
 
-       for_each_possible_cpu(cpu) {
+       get_online_cpus();
+       for_each_online_cpu(cpu) {
                pevent = per_cpu_ptr(cpu_events, cpu);
                bp = perf_event_create_kernel_counter(attr, cpu, -1, triggered);
 
@@ -399,18 +401,20 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr,
                        goto fail;
                }
        }
+       put_online_cpus();
 
        return cpu_events;
 
 fail:
-       for_each_possible_cpu(cpu) {
+       for_each_online_cpu(cpu) {
                pevent = per_cpu_ptr(cpu_events, cpu);
                if (IS_ERR(*pevent))
                        break;
                unregister_hw_breakpoint(*pevent);
        }
+       put_online_cpus();
+
        free_percpu(cpu_events);
-       /* return the error if any */
        return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);
index 25b1031903642654eb43043ee016d78eebbb26dd..bf0e231d970236278380019513b19188132bb62a 100644 (file)
@@ -520,13 +520,15 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
                return -ENOMEM;
 
        ret = call_usermodehelper_stdinpipe(sub_info, filp);
-       if (ret < 0)
-               goto out;
+       if (ret < 0) {
+               call_usermodehelper_freeinfo(sub_info);
+               return ret;
+       }
 
-       return call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
+       ret = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
+       if (ret < 0)    /* Failed to execute helper, close pipe */
+               filp_close(*filp, NULL);
 
-  out:
-       call_usermodehelper_freeinfo(sub_info);
        return ret;
 }
 EXPORT_SYMBOL(call_usermodehelper_pipe);
index e5342a344c43bee9140d9127f1fe907b21149e8d..b7df302a02046e2b9404d8267a66a6300ffd831a 100644 (file)
@@ -1035,7 +1035,7 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
        /* Pre-allocate memory for max kretprobe instances */
        if (rp->maxactive <= 0) {
 #ifdef CONFIG_PREEMPT
-               rp->maxactive = max(10, 2 * num_possible_cpus());
+               rp->maxactive = max_t(unsigned int, 10, 2*num_possible_cpus());
 #else
                rp->maxactive = num_possible_cpus();
 #endif
index e96b8ed1cb6aff09033114dd219157b84e8b23a3..f82386bd9ee9cf01b6399ee750fc481269c63c89 100644 (file)
@@ -1010,6 +1010,12 @@ static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs,
  * J. Corbet <corbet@lwn.net>
  */
 #if defined(CONFIG_KALLSYMS) && defined(CONFIG_SYSFS)
+
+static inline bool sect_empty(const Elf_Shdr *sect)
+{
+       return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0;
+}
+
 struct module_sect_attr
 {
        struct module_attribute mattr;
@@ -1051,8 +1057,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
 
        /* Count loaded sections and allocate structures */
        for (i = 0; i < nsect; i++)
-               if (sechdrs[i].sh_flags & SHF_ALLOC
-                   && sechdrs[i].sh_size)
+               if (!sect_empty(&sechdrs[i]))
                        nloaded++;
        size[0] = ALIGN(sizeof(*sect_attrs)
                        + nloaded * sizeof(sect_attrs->attrs[0]),
@@ -1070,9 +1075,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
        sattr = &sect_attrs->attrs[0];
        gattr = &sect_attrs->grp.attrs[0];
        for (i = 0; i < nsect; i++) {
-               if (! (sechdrs[i].sh_flags & SHF_ALLOC))
-                       continue;
-               if (!sechdrs[i].sh_size)
+               if (sect_empty(&sechdrs[i]))
                        continue;
                sattr->address = sechdrs[i].sh_addr;
                sattr->name = kstrdup(secstrings + sechdrs[i].sh_name,
@@ -1156,7 +1159,7 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect,
        /* Count notes sections and allocate structures.  */
        notes = 0;
        for (i = 0; i < nsect; i++)
-               if ((sechdrs[i].sh_flags & SHF_ALLOC) &&
+               if (!sect_empty(&sechdrs[i]) &&
                    (sechdrs[i].sh_type == SHT_NOTE))
                        ++notes;
 
@@ -1172,7 +1175,7 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect,
        notes_attrs->notes = notes;
        nattr = &notes_attrs->attrs[0];
        for (loaded = i = 0; i < nsect; ++i) {
-               if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+               if (sect_empty(&sechdrs[i]))
                        continue;
                if (sechdrs[i].sh_type == SHT_NOTE) {
                        nattr->attr.name = mod->sect_attrs->attrs[loaded].name;
index 1f38270f08c7d62613665ac6cbb07fccef1c51b6..603c0d8b5df17a93c8b9679be42dd8905b5eaf97 100644 (file)
@@ -5148,7 +5148,7 @@ int perf_event_init_task(struct task_struct *child)
                                            GFP_KERNEL);
                        if (!child_ctx) {
                                ret = -ENOMEM;
-                               goto exit;
+                               break;
                        }
 
                        __perf_event_init_context(child_ctx, child);
@@ -5164,7 +5164,7 @@ int perf_event_init_task(struct task_struct *child)
                }
        }
 
-       if (inherited_all) {
+       if (child_ctx && inherited_all) {
                /*
                 * Mark the child context as a clone of the parent
                 * context, or of whatever the parent is a clone of.
@@ -5184,7 +5184,6 @@ int perf_event_init_task(struct task_struct *child)
                get_ctx(child_ctx->parent_ctx);
        }
 
-exit:
        mutex_unlock(&parent_ctx->mutex);
 
        perf_unpin_context(parent_ctx);
index d09692b4037614cf8a596ec229002018ebee9aac..934ae5e687b960ddf78c939db4b0e55936799243 100644 (file)
@@ -979,7 +979,8 @@ static void print_fatal_signal(struct pt_regs *regs, int signr)
                for (i = 0; i < 16; i++) {
                        unsigned char insn;
 
-                       __get_user(insn, (unsigned char *)(regs->ip + i));
+                       if (get_user(insn, (unsigned char *)(regs->ip + i)))
+                               break;
                        printk("%02x ", insn);
                }
        }
index d006554888dc68752a8813e5f6063379c2d98f47..6c22d8a2f289e81de4af3ccff97996f752a06583 100644 (file)
@@ -12,17 +12,17 @@ config NOP_TRACER
 config HAVE_FTRACE_NMI_ENTER
        bool
        help
-         See Documentation/trace/ftrace-implementation.txt
+         See Documentation/trace/ftrace-design.txt
 
 config HAVE_FUNCTION_TRACER
        bool
        help
-         See Documentation/trace/ftrace-implementation.txt
+         See Documentation/trace/ftrace-design.txt
 
 config HAVE_FUNCTION_GRAPH_TRACER
        bool
        help
-         See Documentation/trace/ftrace-implementation.txt
+         See Documentation/trace/ftrace-design.txt
 
 config HAVE_FUNCTION_GRAPH_FP_TEST
        bool
@@ -34,17 +34,17 @@ config HAVE_FUNCTION_GRAPH_FP_TEST
 config HAVE_FUNCTION_TRACE_MCOUNT_TEST
        bool
        help
-         See Documentation/trace/ftrace-implementation.txt
+         See Documentation/trace/ftrace-design.txt
 
 config HAVE_DYNAMIC_FTRACE
        bool
        help
-         See Documentation/trace/ftrace-implementation.txt
+         See Documentation/trace/ftrace-design.txt
 
 config HAVE_FTRACE_MCOUNT_RECORD
        bool
        help
-         See Documentation/trace/ftrace-implementation.txt
+         See Documentation/trace/ftrace-design.txt
 
 config HAVE_HW_BRANCH_TRACER
        bool
@@ -52,7 +52,7 @@ config HAVE_HW_BRANCH_TRACER
 config HAVE_SYSCALL_TRACEPOINTS
        bool
        help
-         See Documentation/trace/ftrace-implementation.txt
+         See Documentation/trace/ftrace-design.txt
 
 config TRACER_MAX_TRACE
        bool
@@ -83,7 +83,7 @@ config RING_BUFFER_ALLOW_SWAP
 # This allows those options to appear when no other tracer is selected. But the
 # options do not appear when something else selects it. We need the two options
 # GENERIC_TRACER and TRACING to avoid circular dependencies to accomplish the
-# hidding of the automatic options.
+# hiding of the automatic options.
 
 config TRACING
        bool
@@ -119,7 +119,7 @@ menuconfig FTRACE
        bool "Tracers"
        default y if DEBUG_KERNEL
        help
-        Enable the kernel tracing infrastructure.
+         Enable the kernel tracing infrastructure.
 
 if FTRACE
 
@@ -133,7 +133,7 @@ config FUNCTION_TRACER
        help
          Enable the kernel to trace every kernel function. This is done
          by using a compiler feature to insert a small, 5-byte No-Operation
-         instruction to the beginning of every kernel function, which NOP
+         instruction at the beginning of every kernel function, which NOP
          sequence is then dynamically patched into a tracer call when
          tracing is enabled by the administrator. If it's runtime disabled
          (the bootup default), then the overhead of the instructions is very
@@ -150,7 +150,7 @@ config FUNCTION_GRAPH_TRACER
          and its entry.
          Its first purpose is to trace the duration of functions and
          draw a call graph for each thread with some information like
-         the return value. This is done by setting the current return 
+         the return value. This is done by setting the current return
          address on the current task structure into a stack of calls.
 
 
@@ -173,7 +173,7 @@ config IRQSOFF_TRACER
 
              echo 0 > /sys/kernel/debug/tracing/tracing_max_latency
 
-         (Note that kernel size and overhead increases with this option
+         (Note that kernel size and overhead increase with this option
          enabled. This option and the preempt-off timing option can be
          used together or separately.)
 
@@ -186,7 +186,7 @@ config PREEMPT_TRACER
        select TRACER_MAX_TRACE
        select RING_BUFFER_ALLOW_SWAP
        help
-         This option measures the time spent in preemption off critical
+         This option measures the time spent in preemption-off critical
          sections, with microsecond accuracy.
 
          The default measurement method is a maximum search, which is
@@ -195,7 +195,7 @@ config PREEMPT_TRACER
 
              echo 0 > /sys/kernel/debug/tracing/tracing_max_latency
 
-         (Note that kernel size and overhead increases with this option
+         (Note that kernel size and overhead increase with this option
          enabled. This option and the irqs-off timing option can be
          used together or separately.)
 
@@ -222,7 +222,7 @@ config ENABLE_DEFAULT_TRACERS
        depends on !GENERIC_TRACER
        select TRACING
        help
-         This tracer hooks to various trace points in the kernel
+         This tracer hooks to various trace points in the kernel,
          allowing the user to pick and choose which trace point they
          want to trace. It also includes the sched_switch tracer plugin.
 
@@ -265,19 +265,19 @@ choice
         The likely/unlikely profiler only looks at the conditions that
         are annotated with a likely or unlikely macro.
 
-        The "all branch" profiler will profile every if statement in the
+        The "all branch" profiler will profile every if-statement in the
         kernel. This profiler will also enable the likely/unlikely
-        profiler as well.
+        profiler.
 
-        Either of the above profilers add a bit of overhead to the system.
-        If unsure choose "No branch profiling".
+        Either of the above profilers adds a bit of overhead to the system.
+        If unsure, choose "No branch profiling".
 
 config BRANCH_PROFILE_NONE
        bool "No branch profiling"
        help
-        No branch profiling. Branch profiling adds a bit of overhead.
-        Only enable it if you want to analyse the branching behavior.
-        Otherwise keep it disabled.
+         No branch profiling. Branch profiling adds a bit of overhead.
+         Only enable it if you want to analyse the branching behavior.
+         Otherwise keep it disabled.
 
 config PROFILE_ANNOTATED_BRANCHES
        bool "Trace likely/unlikely profiler"
@@ -288,7 +288,7 @@ config PROFILE_ANNOTATED_BRANCHES
 
          /sys/kernel/debug/tracing/profile_annotated_branch
 
-         Note: this will add a significant overhead, only turn this
+         Note: this will add a significant overhead; only turn this
          on if you need to profile the system's use of these macros.
 
 config PROFILE_ALL_BRANCHES
@@ -305,7 +305,7 @@ config PROFILE_ALL_BRANCHES
 
          This configuration, when enabled, will impose a great overhead
          on the system. This should only be enabled when the system
-         is to be analyzed
+         is to be analyzed in much detail.
 endchoice
 
 config TRACING_BRANCHES
@@ -335,7 +335,7 @@ config POWER_TRACER
        depends on X86
        select GENERIC_TRACER
        help
-         This tracer helps developers to analyze and optimize the kernels
+         This tracer helps developers to analyze and optimize the kernel's
          power management decisions, specifically the C-state and P-state
          behavior.
 
@@ -391,14 +391,14 @@ config HW_BRANCH_TRACER
        select GENERIC_TRACER
        help
          This tracer records all branches on the system in a circular
-         buffer giving access to the last N branches for each cpu.
+         buffer, giving access to the last N branches for each cpu.
 
 config KMEMTRACE
        bool "Trace SLAB allocations"
        select GENERIC_TRACER
        help
          kmemtrace provides tracing for slab allocator functions, such as
-         kmalloc, kfree, kmem_cache_alloc, kmem_cache_free etc.. Collected
+         kmalloc, kfree, kmem_cache_alloc, kmem_cache_free, etc. Collected
          data is then fed to the userspace application in order to analyse
          allocation hotspots, internal fragmentation and so on, making it
          possible to see how well an allocator performs, as well as debug
@@ -417,15 +417,15 @@ config WORKQUEUE_TRACER
        bool "Trace workqueues"
        select GENERIC_TRACER
        help
-         The workqueue tracer provides some statistical informations
+         The workqueue tracer provides some statistical information
           about each cpu workqueue thread such as the number of the
           works inserted and executed since their creation. It can help
-          to evaluate the amount of work each of them have to perform.
+          to evaluate the amount of work each of them has to perform.
           For example it can help a developer to decide whether he should
-          choose a per cpu workqueue instead of a singlethreaded one.
+          choose a per-cpu workqueue instead of a singlethreaded one.
 
 config BLK_DEV_IO_TRACE
-       bool "Support for tracing block io actions"
+       bool "Support for tracing block IO actions"
        depends on SYSFS
        depends on BLOCK
        select RELAY
@@ -456,15 +456,15 @@ config KPROBE_EVENT
        select TRACING
        default y
        help
-         This allows the user to add tracing events (similar to tracepoints) on the fly
-         via the ftrace interface. See Documentation/trace/kprobetrace.txt
-         for more details.
+         This allows the user to add tracing events (similar to tracepoints)
+         on the fly via the ftrace interface. See
+         Documentation/trace/kprobetrace.txt for more details.
 
          Those events can be inserted wherever kprobes can probe, and record
          various register and memory values.
 
-         This option is also required by perf-probe subcommand of perf tools. If
-         you want to use perf tools, this option is strongly recommended.
+         This option is also required by perf-probe subcommand of perf tools.
+         If you want to use perf tools, this option is strongly recommended.
 
 config DYNAMIC_FTRACE
        bool "enable/disable ftrace tracepoints dynamically"
@@ -472,32 +472,32 @@ config DYNAMIC_FTRACE
        depends on HAVE_DYNAMIC_FTRACE
        default y
        help
-         This option will modify all the calls to ftrace dynamically
-        (will patch them out of the binary image and replaces them
-        with a No-Op instruction) as they are called. A table is
-        created to dynamically enable them again.
+          This option will modify all the calls to ftrace dynamically
+         (will patch them out of the binary image and replace them
+         with a No-Op instruction) as they are called. A table is
+         created to dynamically enable them again.
 
-        This way a CONFIG_FUNCTION_TRACER kernel is slightly larger, but otherwise
-        has native performance as long as no tracing is active.
+         This way a CONFIG_FUNCTION_TRACER kernel is slightly larger, but
+         otherwise has native performance as long as no tracing is active.
 
-        The changes to the code are done by a kernel thread that
-        wakes up once a second and checks to see if any ftrace calls
-        were made. If so, it runs stop_machine (stops all CPUS)
-        and modifies the code to jump over the call to ftrace.
+         The changes to the code are done by a kernel thread that
+         wakes up once a second and checks to see if any ftrace calls
+         were made. If so, it runs stop_machine (stops all CPUS)
+         and modifies the code to jump over the call to ftrace.
 
 config FUNCTION_PROFILER
        bool "Kernel function profiler"
        depends on FUNCTION_TRACER
        default n
        help
-        This option enables the kernel function profiler. A file is created
-        in debugfs called function_profile_enabled which defaults to zero.
-        When a 1 is echoed into this file profiling begins, and when a
-        zero is entered, profiling stops. A file in the trace_stats
-        directory called functions, that show the list of functions that
-        have been hit and their counters.
+         This option enables the kernel function profiler. A file is created
+         in debugfs called function_profile_enabled which defaults to zero.
+         When a 1 is echoed into this file profiling begins, and when a
+         zero is entered, profiling stops. A "functions" file is created in
+         the trace_stats directory; this file shows the list of functions that
+         have been hit and their counters.
 
-        If in doubt, say N
+         If in doubt, say N.
 
 config FTRACE_MCOUNT_RECORD
        def_bool y
@@ -556,8 +556,8 @@ config RING_BUFFER_BENCHMARK
        tristate "Ring buffer benchmark stress tester"
        depends on RING_BUFFER
        help
-         This option creates a test to stress the ring buffer and bench mark it.
-         It creates its own ring buffer such that it will not interfer with
+         This option creates a test to stress the ring buffer and benchmark it.
+         It creates its own ring buffer such that it will not interfere with
          any other users of the ring buffer (such as ftrace). It then creates
          a producer and consumer that will run for 10 seconds and sleep for
          10 seconds. Each interval it will print out the number of events
@@ -566,7 +566,7 @@ config RING_BUFFER_BENCHMARK
          It does not disable interrupts or raise its priority, so it may be
          affected by processes that are running.
 
-         If unsure, say N
+         If unsure, say N.
 
 endif # FTRACE
 
index 8b9f20ab8eed9acc1b3d2529e377668951125723..0df1b0f2cb9e0717f2a21f6923389c1978a1fa04 100644 (file)
@@ -3949,7 +3949,7 @@ trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,
        if (!!(topt->flags->val & topt->opt->bit) != val) {
                mutex_lock(&trace_types_lock);
                ret = __set_tracer_option(current_trace, topt->flags,
-                                         topt->opt, val);
+                                         topt->opt, !val);
                mutex_unlock(&trace_types_lock);
                if (ret)
                        return ret;
index 458e5bfe26d0f700a9a913b204d53d761ae69b7f..d4fa5dc1ee4e0763a54224654129ded7c9ec48f1 100644 (file)
@@ -158,7 +158,8 @@ ftrace_format_##name(struct ftrace_event_call *unused,                      \
        BUILD_BUG_ON(len > MAX_FILTER_STR_VAL);                         \
        ret = trace_define_field(event_call, #type "[" #len "]", #item, \
                                 offsetof(typeof(field), item),         \
-                                sizeof(field.item), 0, FILTER_OTHER);  \
+                                sizeof(field.item),                    \
+                                is_signed_type(type), FILTER_OTHER);   \
        if (ret)                                                        \
                return ret;
 
@@ -168,8 +169,8 @@ ftrace_format_##name(struct ftrace_event_call *unused,                      \
        ret = trace_define_field(event_call, #type "[" #len "]", #item, \
                                 offsetof(typeof(field),                \
                                          container.item),              \
-                                sizeof(field.container.item), 0,       \
-                                FILTER_OTHER);                         \
+                                sizeof(field.container.item),          \
+                                is_signed_type(type), FILTER_OTHER);   \
        if (ret)                                                        \
                return ret;
 
index 375f81a568dc267cfc847009418c056cfb24469f..6ea90c0e2c96a89835216314f3b9f792161c49de 100644 (file)
@@ -1201,10 +1201,11 @@ static int __probe_event_show_format(struct trace_seq *s,
 #undef SHOW_FIELD
 #define SHOW_FIELD(type, item, name)                                   \
        do {                                                            \
-               ret = trace_seq_printf(s, "\tfield: " #type " %s;\t"    \
-                               "offset:%u;\tsize:%u;\n", name,         \
+               ret = trace_seq_printf(s, "\tfield:" #type " %s;\t"     \
+                               "offset:%u;\tsize:%u;\tsigned:%d;\n", name,\
                                (unsigned int)offsetof(typeof(field), item),\
-                               (unsigned int)sizeof(type));            \
+                               (unsigned int)sizeof(type),             \
+                               is_signed_type(type));                  \
                if (!ret)                                               \
                        return 0;                                       \
        } while (0)
index faf37fa4408c3b7d87a357a64dfc6532a9545c76..94103cdcf9d86aa5f48c1f50c46c4b4366aaf770 100644 (file)
 #include <linux/fs.h>
 
 #include "trace_output.h"
-#include "trace_stat.h"
 #include "trace.h"
 
 #include <linux/hw_breakpoint.h>
 #include <asm/hw_breakpoint.h>
 
+#include <asm/atomic.h>
+
 /*
  * For now, let us restrict the no. of symbols traced simultaneously to number
  * of available hardware breakpoint registers.
@@ -44,7 +45,7 @@ struct trace_ksym {
        struct perf_event       **ksym_hbp;
        struct perf_event_attr  attr;
 #ifdef CONFIG_PROFILE_KSYM_TRACER
-       unsigned long           counter;
+       atomic64_t              counter;
 #endif
        struct hlist_node       ksym_hlist;
 };
@@ -69,9 +70,8 @@ void ksym_collect_stats(unsigned long hbp_hit_addr)
 
        rcu_read_lock();
        hlist_for_each_entry_rcu(entry, node, &ksym_filter_head, ksym_hlist) {
-               if ((entry->attr.bp_addr == hbp_hit_addr) &&
-                   (entry->counter <= MAX_UL_INT)) {
-                       entry->counter++;
+               if (entry->attr.bp_addr == hbp_hit_addr) {
+                       atomic64_inc(&entry->counter);
                        break;
                }
        }
@@ -197,7 +197,6 @@ int process_new_ksym_entry(char *ksymname, int op, unsigned long addr)
        entry->attr.bp_addr = addr;
        entry->attr.bp_len = HW_BREAKPOINT_LEN_4;
 
-       ret = -EAGAIN;
        entry->ksym_hbp = register_wide_hw_breakpoint(&entry->attr,
                                        ksym_hbp_handler);
 
@@ -300,8 +299,8 @@ static ssize_t ksym_trace_filter_write(struct file *file,
         * 2: echo 0 > ksym_trace_filter
         * 3: echo "*:---" > ksym_trace_filter
         */
-       if (!buf[0] || !strcmp(buf, "0") ||
-           !strcmp(buf, "*:---")) {
+       if (!input_string[0] || !strcmp(input_string, "0") ||
+           !strcmp(input_string, "*:---")) {
                __ksym_trace_reset();
                ret = 0;
                goto out;
@@ -444,102 +443,77 @@ struct tracer ksym_tracer __read_mostly =
        .print_line     = ksym_trace_output
 };
 
-__init static int init_ksym_trace(void)
-{
-       struct dentry *d_tracer;
-       struct dentry *entry;
-
-       d_tracer = tracing_init_dentry();
-       ksym_filter_entry_count = 0;
-
-       entry = debugfs_create_file("ksym_trace_filter", 0644, d_tracer,
-                                   NULL, &ksym_tracing_fops);
-       if (!entry)
-               pr_warning("Could not create debugfs "
-                          "'ksym_trace_filter' file\n");
-
-       return register_tracer(&ksym_tracer);
-}
-device_initcall(init_ksym_trace);
-
-
 #ifdef CONFIG_PROFILE_KSYM_TRACER
-static int ksym_tracer_stat_headers(struct seq_file *m)
+static int ksym_profile_show(struct seq_file *m, void *v)
 {
+       struct hlist_node *node;
+       struct trace_ksym *entry;
+       int access_type = 0;
+       char fn_name[KSYM_NAME_LEN];
+
        seq_puts(m, "  Access Type ");
        seq_puts(m, "  Symbol                                       Counter\n");
        seq_puts(m, "  ----------- ");
        seq_puts(m, "  ------                                       -------\n");
-       return 0;
-}
 
-static int ksym_tracer_stat_show(struct seq_file *m, void *v)
-{
-       struct hlist_node *stat = v;
-       struct trace_ksym *entry;
-       int access_type = 0;
-       char fn_name[KSYM_NAME_LEN];
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(entry, node, &ksym_filter_head, ksym_hlist) {
 
-       entry = hlist_entry(stat, struct trace_ksym, ksym_hlist);
+               access_type = entry->attr.bp_type;
 
-       access_type = entry->attr.bp_type;
+               switch (access_type) {
+               case HW_BREAKPOINT_R:
+                       seq_puts(m, "  R           ");
+                       break;
+               case HW_BREAKPOINT_W:
+                       seq_puts(m, "  W           ");
+                       break;
+               case HW_BREAKPOINT_R | HW_BREAKPOINT_W:
+                       seq_puts(m, "  RW          ");
+                       break;
+               default:
+                       seq_puts(m, "  NA          ");
+               }
 
-       switch (access_type) {
-       case HW_BREAKPOINT_R:
-               seq_puts(m, "  R           ");
-               break;
-       case HW_BREAKPOINT_W:
-               seq_puts(m, "  W           ");
-               break;
-       case HW_BREAKPOINT_R | HW_BREAKPOINT_W:
-               seq_puts(m, "  RW          ");
-               break;
-       default:
-               seq_puts(m, "  NA          ");
+               if (lookup_symbol_name(entry->attr.bp_addr, fn_name) >= 0)
+                       seq_printf(m, "  %-36s", fn_name);
+               else
+                       seq_printf(m, "  %-36s", "<NA>");
+               seq_printf(m, " %15llu\n",
+                          (unsigned long long)atomic64_read(&entry->counter));
        }
-
-       if (lookup_symbol_name(entry->attr.bp_addr, fn_name) >= 0)
-               seq_printf(m, "  %-36s", fn_name);
-       else
-               seq_printf(m, "  %-36s", "<NA>");
-       seq_printf(m, " %15lu\n", entry->counter);
+       rcu_read_unlock();
 
        return 0;
 }
 
-static void *ksym_tracer_stat_start(struct tracer_stat *trace)
+static int ksym_profile_open(struct inode *node, struct file *file)
 {
-       return ksym_filter_head.first;
-}
-
-static void *
-ksym_tracer_stat_next(void *v, int idx)
-{
-       struct hlist_node *stat = v;
-
-       return stat->next;
+       return single_open(file, ksym_profile_show, NULL);
 }
 
-static struct tracer_stat ksym_tracer_stats = {
-       .name = "ksym_tracer",
-       .stat_start = ksym_tracer_stat_start,
-       .stat_next = ksym_tracer_stat_next,
-       .stat_headers = ksym_tracer_stat_headers,
-       .stat_show = ksym_tracer_stat_show
+static const struct file_operations ksym_profile_fops = {
+       .open           = ksym_profile_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
 };
+#endif /* CONFIG_PROFILE_KSYM_TRACER */
 
-__init static int ksym_tracer_stat_init(void)
+__init static int init_ksym_trace(void)
 {
-       int ret;
+       struct dentry *d_tracer;
 
-       ret = register_stat_tracer(&ksym_tracer_stats);
-       if (ret) {
-               printk(KERN_WARNING "Warning: could not register "
-                                   "ksym tracer stats\n");
-               return 1;
-       }
+       d_tracer = tracing_init_dentry();
 
-       return 0;
+       trace_create_file("ksym_trace_filter", 0644, d_tracer,
+                         NULL, &ksym_tracing_fops);
+
+#ifdef CONFIG_PROFILE_KSYM_TRACER
+       trace_create_file("ksym_profile", 0444, d_tracer,
+                         NULL, &ksym_profile_fops);
+#endif
+
+       return register_tracer(&ksym_tracer);
 }
-fs_initcall(ksym_tracer_stat_init);
-#endif /* CONFIG_PROFILE_KSYM_TRACER */
+device_initcall(init_ksym_trace);
index 1cfe51628e1bd590bc2cfae81729d1b326e8ef82..97b136ff117e364b3d1153c1ae5a0780064ab3de 100644 (file)
@@ -117,6 +117,10 @@ config DECOMPRESS_BZIP2
 config DECOMPRESS_LZMA
        tristate
 
+config DECOMPRESS_LZO
+       select LZO_DECOMPRESS
+       tristate
+
 #
 # Generic allocator support is selected if needed
 #
index 347ad8db29d3aa14d340dc659ab10c01dbaa2d05..911b25aed1e7875a101f26ccffc3ef1d6699a1c4 100644 (file)
@@ -69,6 +69,7 @@ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
 lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
 lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
 lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o
+lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o
 
 obj-$(CONFIG_TEXTSEARCH) += textsearch.o
 obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
index d2842f57167446e0221352035a2276b87318ea4b..a7606815541f4631d675707950a11de0609aff89 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/decompress/bunzip2.h>
 #include <linux/decompress/unlzma.h>
 #include <linux/decompress/inflate.h>
+#include <linux/decompress/unlzo.h>
 
 #include <linux/types.h>
 #include <linux/string.h>
@@ -22,6 +23,9 @@
 #ifndef CONFIG_DECOMPRESS_LZMA
 # define unlzma NULL
 #endif
+#ifndef CONFIG_DECOMPRESS_LZO
+# define unlzo NULL
+#endif
 
 static const struct compress_format {
        unsigned char magic[2];
@@ -32,6 +36,7 @@ static const struct compress_format {
        { {037, 0236}, "gzip", gunzip },
        { {0x42, 0x5a}, "bzip2", bunzip2 },
        { {0x5d, 0x00}, "lzma", unlzma },
+       { {0x89, 0x4c}, "lzo", unlzo },
        { {0, 0}, NULL, NULL }
 };
 
diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c
new file mode 100644 (file)
index 0000000..db521f4
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * LZO decompressor for the Linux kernel. Code borrowed from the lzo
+ * implementation by Markus Franz Xaver Johannes Oberhumer.
+ *
+ * Linux kernel adaptation:
+ * Copyright (C) 2009
+ * Albin Tonnerre, Free Electrons <albin.tonnerre@free-electrons.com>
+ *
+ * Original code:
+ * Copyright (C) 1996-2005 Markus Franz Xaver Johannes Oberhumer
+ * All Rights Reserved.
+ *
+ * lzop and the LZO library are free software; you can redistribute them
+ * and/or modify them 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; see the file COPYING.
+ * If not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Markus F.X.J. Oberhumer
+ * <markus@oberhumer.com>
+ * http://www.oberhumer.com/opensource/lzop/
+ */
+
+#ifdef STATIC
+#include "lzo/lzo1x_decompress.c"
+#else
+#include <linux/slab.h>
+#include <linux/decompress/unlzo.h>
+#endif
+
+#include <linux/types.h>
+#include <linux/lzo.h>
+#include <linux/decompress/mm.h>
+
+#include <linux/compiler.h>
+#include <asm/unaligned.h>
+
+static const unsigned char lzop_magic[] = {
+       0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a };
+
+#define LZO_BLOCK_SIZE        (256*1024l)
+#define HEADER_HAS_FILTER      0x00000800L
+
+STATIC inline int INIT parse_header(u8 *input, u8 *skip)
+{
+       int l;
+       u8 *parse = input;
+       u8 level = 0;
+       u16 version;
+
+       /* read magic: 9 first bits */
+       for (l = 0; l < 9; l++) {
+               if (*parse++ != lzop_magic[l])
+                       return 0;
+       }
+       /* get version (2bytes), skip library version (2),
+        * 'need to be extracted' version (2) and
+        * method (1) */
+       version = get_unaligned_be16(parse);
+       parse += 7;
+       if (version >= 0x0940)
+               level = *parse++;
+       if (get_unaligned_be32(parse) & HEADER_HAS_FILTER)
+               parse += 8; /* flags + filter info */
+       else
+               parse += 4; /* flags */
+
+       /* skip mode and mtime_low */
+       parse += 8;
+       if (version >= 0x0940)
+               parse += 4;     /* skip mtime_high */
+
+       l = *parse++;
+       /* don't care about the file name, and skip checksum */
+       parse += l + 4;
+
+       *skip = parse - input;
+       return 1;
+}
+
+STATIC inline int INIT unlzo(u8 *input, int in_len,
+                               int (*fill) (void *, unsigned int),
+                               int (*flush) (void *, unsigned int),
+                               u8 *output, int *posp,
+                               void (*error_fn) (char *x))
+{
+       u8 skip = 0, r = 0;
+       u32 src_len, dst_len;
+       size_t tmp;
+       u8 *in_buf, *in_buf_save, *out_buf;
+       int obytes_processed = 0;
+
+       set_error_fn(error_fn);
+
+       if (output) {
+               out_buf = output;
+       } else if (!flush) {
+               error("NULL output pointer and no flush function provided");
+               goto exit;
+       } else {
+               out_buf = malloc(LZO_BLOCK_SIZE);
+               if (!out_buf) {
+                       error("Could not allocate output buffer");
+                       goto exit;
+               }
+       }
+
+       if (input && fill) {
+               error("Both input pointer and fill function provided, don't know what to do");
+               goto exit_1;
+       } else if (input) {
+               in_buf = input;
+       } else if (!fill || !posp) {
+               error("NULL input pointer and missing position pointer or fill function");
+               goto exit_1;
+       } else {
+               in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE));
+               if (!in_buf) {
+                       error("Could not allocate input buffer");
+                       goto exit_1;
+               }
+       }
+       in_buf_save = in_buf;
+
+       if (posp)
+               *posp = 0;
+
+       if (fill)
+               fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
+
+       if (!parse_header(input, &skip)) {
+               error("invalid header");
+               goto exit_2;
+       }
+       in_buf += skip;
+
+       if (posp)
+               *posp = skip;
+
+       for (;;) {
+               /* read uncompressed block size */
+               dst_len = get_unaligned_be32(in_buf);
+               in_buf += 4;
+
+               /* exit if last block */
+               if (dst_len == 0) {
+                       if (posp)
+                               *posp += 4;
+                       break;
+               }
+
+               if (dst_len > LZO_BLOCK_SIZE) {
+                       error("dest len longer than block size");
+                       goto exit_2;
+               }
+
+               /* read compressed block size, and skip block checksum info */
+               src_len = get_unaligned_be32(in_buf);
+               in_buf += 8;
+
+               if (src_len <= 0 || src_len > dst_len) {
+                       error("file corrupted");
+                       goto exit_2;
+               }
+
+               /* decompress */
+               tmp = dst_len;
+               r = lzo1x_decompress_safe((u8 *) in_buf, src_len,
+                                               out_buf, &tmp);
+
+               if (r != LZO_E_OK || dst_len != tmp) {
+                       error("Compressed data violation");
+                       goto exit_2;
+               }
+
+               obytes_processed += dst_len;
+               if (flush)
+                       flush(out_buf, dst_len);
+               if (output)
+                       out_buf += dst_len;
+               if (posp)
+                       *posp += src_len + 12;
+               if (fill) {
+                       in_buf = in_buf_save;
+                       fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
+               } else
+                       in_buf += src_len;
+       }
+
+exit_2:
+       if (!input)
+               free(in_buf);
+exit_1:
+       if (!output)
+               free(out_buf);
+exit:
+       return obytes_processed;
+}
+
+#define decompress unlzo
index d9b08e0f7f55fb82758f0c393db6c86fb3d74900..7d2f0b33e5a82937d2fb615fe5bbbb0de3884777 100644 (file)
@@ -670,12 +670,13 @@ static int device_dma_allocations(struct device *dev)
        return count;
 }
 
-static int dma_debug_device_change(struct notifier_block *nb,
-                                   unsigned long action, void *data)
+static int dma_debug_device_change(struct notifier_block *nb, unsigned long action, void *data)
 {
        struct device *dev = data;
        int count;
 
+       if (global_disable)
+               return 0;
 
        switch (action) {
        case BUS_NOTIFY_UNBOUND_DRIVER:
@@ -697,6 +698,9 @@ void dma_debug_add_bus(struct bus_type *bus)
 {
        struct notifier_block *nb;
 
+       if (global_disable)
+               return;
+
        nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
        if (nb == NULL) {
                pr_err("dma_debug_add_bus: out of memory\n");
@@ -909,6 +913,9 @@ static void check_sync(struct device *dev,
                                ref->size);
        }
 
+       if (entry->direction == DMA_BIDIRECTIONAL)
+               goto out;
+
        if (ref->direction != entry->direction) {
                err_printk(dev, entry, "DMA-API: device driver syncs "
                                "DMA memory with different direction "
@@ -919,9 +926,6 @@ static void check_sync(struct device *dev,
                                dir2name[ref->direction]);
        }
 
-       if (entry->direction == DMA_BIDIRECTIONAL)
-               goto out;
-
        if (to_cpu && !(entry->direction == DMA_FROM_DEVICE) &&
                      !(ref->direction == DMA_TO_DEVICE))
                err_printk(dev, entry, "DMA-API: device driver syncs "
@@ -944,7 +948,6 @@ static void check_sync(struct device *dev,
 
 out:
        put_hash_bucket(bucket, &flags);
-
 }
 
 void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
index 5dc6b29c1575f80903a3a9facc55642facbd0462..f2fd09850223b319965ef1f593e9a5507e3dc3f8 100644 (file)
  *  Richard Purdie <rpurdie@openedhand.com>
  */
 
+#ifndef STATIC
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/lzo.h>
-#include <asm/byteorder.h>
+#endif
+
 #include <asm/unaligned.h>
+#include <linux/lzo.h>
 #include "lzodefs.h"
 
 #define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
@@ -244,9 +246,10 @@ lookbehind_overrun:
        *out_len = op - out;
        return LZO_E_LOOKBEHIND_OVERRUN;
 }
-
+#ifndef STATIC
 EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("LZO1X Decompressor");
 
+#endif
index b3c099b5478e36615f69b47884ad2d15bd71abf4..3ed247b80662cd07c5f871d914285159d01b5274 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/rational.h>
+#include <linux/module.h>
 
 /*
  * calculate best rational approximation for a given fraction
index d4996cf46eb6ac0b2227a28ff26c734568b86f99..3b8aeec4e32762c3066f8ec633ec0baed99e746e 100644 (file)
@@ -903,7 +903,7 @@ static char *uuid_string(char *buf, char *end, const u8 *addr,
  *       IPv6 omits the colons (01020304...0f)
  *       IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
  * - 'I6c' for IPv6 addresses printed as specified by
- *       http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+ *       http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
  * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
  *       "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  *       Options for %pU are:
@@ -1188,7 +1188,7 @@ qualifier:
  * %pI6 print an IPv6 address with colons
  * %pi6 print an IPv6 address without colons
  * %pI6c print an IPv6 address as specified by
- *   http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+ *   http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
  * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
  *   case.
  * %n is ignored
index 8550b0c05d00191d97521356ed7d6ed2e1a84f3f..05e1559fa156f3b2cc81e2f6af32b11b0ee061f3 100644 (file)
@@ -4,6 +4,8 @@
  */
 
 #include <linux/zutil.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
 #include "inftrees.h"
 #include "inflate.h"
 #include "inffast.h"
 #ifdef POSTINC
 #  define OFF 0
 #  define PUP(a) *(a)++
+#  define UP_UNALIGNED(a) get_unaligned((a)++)
 #else
 #  define OFF 1
 #  define PUP(a) *++(a)
+#  define UP_UNALIGNED(a) get_unaligned(++(a))
 #endif
 
 /*
@@ -239,18 +243,47 @@ void inflate_fast(z_streamp strm, unsigned start)
                     }
                 }
                 else {
+                   unsigned short *sout;
+                   unsigned long loops;
+
                     from = out - dist;          /* copy direct from output */
-                    do {                        /* minimum length is three */
-                        PUP(out) = PUP(from);
-                        PUP(out) = PUP(from);
-                        PUP(out) = PUP(from);
-                        len -= 3;
-                    } while (len > 2);
-                    if (len) {
-                        PUP(out) = PUP(from);
-                        if (len > 1)
-                            PUP(out) = PUP(from);
-                    }
+                   /* minimum length is three */
+                   /* Align out addr */
+                   if (!((long)(out - 1 + OFF) & 1)) {
+                       PUP(out) = PUP(from);
+                       len--;
+                   }
+                   sout = (unsigned short *)(out - OFF);
+                   if (dist > 2) {
+                       unsigned short *sfrom;
+
+                       sfrom = (unsigned short *)(from - OFF);
+                       loops = len >> 1;
+                       do
+                           PUP(sout) = UP_UNALIGNED(sfrom);
+                       while (--loops);
+                       out = (unsigned char *)sout + OFF;
+                       from = (unsigned char *)sfrom + OFF;
+                   } else { /* dist == 1 or dist == 2 */
+                       unsigned short pat16;
+
+                       pat16 = *(sout-2+2*OFF);
+                       if (dist == 1)
+#if defined(__BIG_ENDIAN)
+                           pat16 = (pat16 & 0xff) | ((pat16 & 0xff) << 8);
+#elif defined(__LITTLE_ENDIAN)
+                           pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00) >> 8);
+#else
+#error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined
+#endif
+                       loops = len >> 1;
+                       do
+                           PUP(sout) = pat16;
+                       while (--loops);
+                       out = (unsigned char *)sout + OFF;
+                   }
+                   if (len & 1)
+                       PUP(out) = PUP(from);
                 }
             }
             else if ((op & 64) == 0) {          /* 2nd level distance code */
index 65f38c218207231e0bf5b612ccacc5858be1b4e0..e91b81b636700befc4ce10c5286e9a0e6512df7e 100644 (file)
@@ -402,7 +402,7 @@ static void clear_huge_page(struct page *page,
 {
        int i;
 
-       if (unlikely(sz > MAX_ORDER_NR_PAGES)) {
+       if (unlikely(sz/PAGE_SIZE > MAX_ORDER_NR_PAGES)) {
                clear_gigantic_page(page, addr, sz);
                return;
        }
index 9073695ff25f3db8da8df878e6ade3952542229a..4e348dbaecd75a297e59101aa9cb5b9ffc872968 100644 (file)
  * Safely read from address @src to the buffer at @dst.  If a kernel fault
  * happens, handle that and return -EFAULT.
  */
-long probe_kernel_read(void *dst, void *src, size_t size)
+
+long __weak probe_kernel_read(void *dst, void *src, size_t size)
+    __attribute__((alias("__probe_kernel_read")));
+
+long __probe_kernel_read(void *dst, void *src, size_t size)
 {
        long ret;
        mm_segment_t old_fs = get_fs();
@@ -39,7 +43,10 @@ EXPORT_SYMBOL_GPL(probe_kernel_read);
  * Safely write to address @dst from the buffer at @src.  If a kernel fault
  * happens, handle that and return -EFAULT.
  */
-long notrace __weak probe_kernel_write(void *dst, void *src, size_t size)
+long __weak probe_kernel_write(void *dst, void *src, size_t size)
+    __attribute__((alias("__probe_kernel_write")));
+
+long __probe_kernel_write(void *dst, void *src, size_t size)
 {
        long ret;
        mm_segment_t old_fs = get_fs();
index d9c77b2dbe9d6489cdf5e40e5f5ae0dfc2be2a5a..ee2298936fe677870ad4979b98bd8d6ada7c3439 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1043,6 +1043,46 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 }
 EXPORT_SYMBOL(do_mmap_pgoff);
 
+SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
+               unsigned long, prot, unsigned long, flags,
+               unsigned long, fd, unsigned long, pgoff)
+{
+       struct file *file = NULL;
+       unsigned long retval = -EBADF;
+
+       if (!(flags & MAP_ANONYMOUS)) {
+               if (unlikely(flags & MAP_HUGETLB))
+                       return -EINVAL;
+               file = fget(fd);
+               if (!file)
+                       goto out;
+       } else if (flags & MAP_HUGETLB) {
+               struct user_struct *user = NULL;
+               /*
+                * VM_NORESERVE is used because the reservations will be
+                * taken when vm_ops->mmap() is called
+                * A dummy user value is used because we are not locking
+                * memory so no accounting is necessary
+                */
+               len = ALIGN(len, huge_page_size(&default_hstate));
+               file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE,
+                                               &user, HUGETLB_ANONHUGE_INODE);
+               if (IS_ERR(file))
+                       return PTR_ERR(file);
+       }
+
+       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+       down_write(&current->mm->mmap_sem);
+       retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+       up_write(&current->mm->mmap_sem);
+
+       if (file)
+               fput(file);
+out:
+       return retval;
+}
+
 /*
  * Some shared mappigns will want the pages marked read-only
  * to track write events. If so, we'll downgrade vm_page_prot
index 8687973462bbea8becddfe0941eb94fab60ce304..17773862619b5334832b76a062411c830e90135b 100644 (file)
@@ -432,6 +432,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
        /*
         * Ok, looks good - let it rip.
         */
+       flush_icache_range(mm->brk, brk);
        return mm->brk = brk;
 }
 
@@ -1353,10 +1354,14 @@ unsigned long do_mmap_pgoff(struct file *file,
 share:
        add_vma_to_mm(current->mm, vma);
 
-       up_write(&nommu_region_sem);
+       /* we flush the region from the icache only when the first executable
+        * mapping of it is made  */
+       if (vma->vm_flags & VM_EXEC && !region->vm_icache_flushed) {
+               flush_icache_range(region->vm_start, region->vm_end);
+               region->vm_icache_flushed = true;
+       }
 
-       if (prot & PROT_EXEC)
-               flush_icache_range(result, result + len);
+       up_write(&nommu_region_sem);
 
        kleave(" = %lx", result);
        return result;
@@ -1398,6 +1403,31 @@ error_getting_region:
 }
 EXPORT_SYMBOL(do_mmap_pgoff);
 
+SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
+               unsigned long, prot, unsigned long, flags,
+               unsigned long, fd, unsigned long, pgoff)
+{
+       struct file *file = NULL;
+       unsigned long retval = -EBADF;
+
+       if (!(flags & MAP_ANONYMOUS)) {
+               file = fget(fd);
+               if (!file)
+                       goto out;
+       }
+
+       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+       down_write(&current->mm->mmap_sem);
+       retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+       up_write(&current->mm->mmap_sem);
+
+       if (file)
+               fput(file);
+out:
+       return retval;
+}
+
 /*
  * split a vma into two pieces at address 'addr', a new vma is allocated either
  * for the first part or the tail.
@@ -1891,9 +1921,11 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
 
                /* only read or write mappings where it is permitted */
                if (write && vma->vm_flags & VM_MAYWRITE)
-                       len -= copy_to_user((void *) addr, buf, len);
+                       copy_to_user_page(vma, NULL, addr,
+                                        (void *) addr, buf, len);
                else if (!write && vma->vm_flags & VM_MAYREAD)
-                       len -= copy_from_user(buf, (void *) addr, len);
+                       copy_from_user_page(vma, NULL, addr,
+                                           buf, (void *) addr, len);
                else
                        len = 0;
        } else {
index 442010cc91c6c82eb8489e64d21500baa52b5911..083e7c91e5f62b10ec0b85eaa2f307a1bb2921df 100644 (file)
@@ -1271,7 +1271,7 @@ static void pcpu_reclaim(struct work_struct *work)
  */
 void free_percpu(void *ptr)
 {
-       void *addr = __pcpu_ptr_to_addr(ptr);
+       void *addr;
        struct pcpu_chunk *chunk;
        unsigned long flags;
        int off;
@@ -1279,6 +1279,8 @@ void free_percpu(void *ptr)
        if (!ptr)
                return;
 
+       addr = __pcpu_ptr_to_addr(ptr);
+
        spin_lock_irqsave(&pcpu_lock, flags);
 
        chunk = pcpu_chunk_addr_search(addr);
index 7d41f15b48d37ad45d9184441b5daf3640afd6bb..7451bdacaf18875044ea97ed3d49da8c401d8249 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -654,7 +654,7 @@ static void init_node_lock_keys(int q)
 
                l3 = s->cs_cachep->nodelists[q];
                if (!l3 || OFF_SLAB(s->cs_cachep))
-                       return;
+                       continue;
                lockdep_set_class(&l3->list_lock, &on_slab_l3_key);
                alc = l3->alien;
                /*
@@ -665,7 +665,7 @@ static void init_node_lock_keys(int q)
                 * for alloc_alien_cache,
                 */
                if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC)
-                       return;
+                       continue;
                for_each_node(r) {
                        if (alc[r])
                                lockdep_set_class(&alc[r]->lock,
index b377ce43080312411a8910ea21a5f2867a7c7007..7c35ad95f92756d1473bbc2ae658f5bb27de2ca9 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -4,10 +4,6 @@
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/sched.h>
-#include <linux/hugetlb.h>
-#include <linux/syscalls.h>
-#include <linux/mman.h>
-#include <linux/file.h>
 #include <asm/uaccess.h>
 
 #define CREATE_TRACE_POINTS
@@ -272,46 +268,6 @@ int __attribute__((weak)) get_user_pages_fast(unsigned long start,
 }
 EXPORT_SYMBOL_GPL(get_user_pages_fast);
 
-SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
-               unsigned long, prot, unsigned long, flags,
-               unsigned long, fd, unsigned long, pgoff)
-{
-       struct file * file = NULL;
-       unsigned long retval = -EBADF;
-
-       if (!(flags & MAP_ANONYMOUS)) {
-               if (unlikely(flags & MAP_HUGETLB))
-                       return -EINVAL;
-               file = fget(fd);
-               if (!file)
-                       goto out;
-       } else if (flags & MAP_HUGETLB) {
-               struct user_struct *user = NULL;
-               /*
-                * VM_NORESERVE is used because the reservations will be
-                * taken when vm_ops->mmap() is called
-                * A dummy user value is used because we are not locking
-                * memory so no accounting is necessary
-                */
-               len = ALIGN(len, huge_page_size(&default_hstate));
-               file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE,
-                                               &user, HUGETLB_ANONHUGE_INODE);
-               if (IS_ERR(file))
-                       return PTR_ERR(file);
-       }
-
-       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-       down_write(&current->mm->mmap_sem);
-       retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-       up_write(&current->mm->mmap_sem);
-
-       if (file)
-               fput(file);
-out:
-       return retval;
-}
-
 /* Tracepoints definitions. */
 EXPORT_TRACEPOINT_SYMBOL(kmalloc);
 EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
index a23b45f08ec9ce6644cfc350cb3bc393c167ab92..de0c2c726420e2044c55fd6235e15e915de16a51 100644 (file)
@@ -250,8 +250,7 @@ struct pktgen_dev {
        __u64 count;            /* Default No packets to send */
        __u64 sofar;            /* How many pkts we've sent so far */
        __u64 tx_bytes;         /* How many bytes we've transmitted */
-       __u64 errors;           /* Errors when trying to transmit,
-                                  pkts will be re-sent */
+       __u64 errors;           /* Errors when trying to transmit, */
 
        /* runtime counters relating to clone_skb */
 
@@ -3465,6 +3464,12 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
                pkt_dev->seq_num++;
                pkt_dev->tx_bytes += pkt_dev->last_pkt_size;
                break;
+       case NET_XMIT_DROP:
+       case NET_XMIT_CN:
+       case NET_XMIT_POLICED:
+               /* skb has been consumed */
+               pkt_dev->errors++;
+               break;
        default: /* Drivers are not supposed to return other values! */
                if (net_ratelimit())
                        pr_info("pktgen: %s xmit error: %d\n",
index 5cdbc102a4187a274106c9ec6a8ad830c11d2bd6..040c4f05b65321b6b2c6023bb0eba66eecb7c26a 100644 (file)
@@ -1397,6 +1397,7 @@ static struct devinet_sysctl_table {
                DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
                                        "accept_source_route"),
                DEVINET_SYSCTL_RW_ENTRY(ACCEPT_LOCAL, "accept_local"),
+               DEVINET_SYSCTL_RW_ENTRY(SRC_VMARK, "src_valid_mark"),
                DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
                DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
                DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
index 3323168ee52d8774c6cb0258acbd807e7646a203..82dbf711d6d0ef2a704e6a636131242f379011c8 100644 (file)
@@ -252,6 +252,8 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
                no_addr = in_dev->ifa_list == NULL;
                rpf = IN_DEV_RPFILTER(in_dev);
                accept_local = IN_DEV_ACCEPT_LOCAL(in_dev);
+               if (mark && !IN_DEV_SRC_VMARK(in_dev))
+                       fl.mark = 0;
        }
        rcu_read_unlock();
 
index 3787455fb69637b9f60a84e0afe09b7b5bba40ac..d7dcee68072820764d0910c79e740db052512073 100644 (file)
@@ -34,9 +34,28 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
 
        ht_cap->ht_supported = true;
 
-       ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info) & sband->ht_cap.cap;
-       ht_cap->cap &= ~IEEE80211_HT_CAP_SM_PS;
-       ht_cap->cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS;
+       /*
+        * The bits listed in this expression should be
+        * the same for the peer and us, if the station
+        * advertises more then we can't use those thus
+        * we mask them out.
+        */
+       ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info) &
+               (sband->ht_cap.cap |
+                ~(IEEE80211_HT_CAP_LDPC_CODING |
+                  IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+                  IEEE80211_HT_CAP_GRN_FLD |
+                  IEEE80211_HT_CAP_SGI_20 |
+                  IEEE80211_HT_CAP_SGI_40 |
+                  IEEE80211_HT_CAP_DSSSCCK40));
+       /*
+        * The STBC bits are asymmetric -- if we don't have
+        * TX then mask out the peer's RX and vice versa.
+        */
+       if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))
+               ht_cap->cap &= ~IEEE80211_HT_CAP_RX_STBC;
+       if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC))
+               ht_cap->cap &= ~IEEE80211_HT_CAP_TX_STBC;
 
        ampdu_info = ht_cap_ie->ampdu_params_info;
        ht_cap->ampdu_factor =
index 10d13856f86c5f338c2923e887e34ecf090f35d8..1f2db647bb5ccd3526d8fc40ef3e6aeb3cb68da6 100644 (file)
@@ -382,6 +382,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
                                        u8 *bssid,u8 *addr, u32 supp_rates)
 {
+       struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
        int band = local->hw.conf.channel->band;
@@ -397,6 +398,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
                return NULL;
        }
 
+       if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH)
+               return NULL;
+
        if (compare_ether_addr(bssid, sdata->u.ibss.bssid))
                return NULL;
 
index 8116d1a96a4afc2f2d3e0bf19afb4b2232b5d815..0d2d94881f1f14fd3d42b692c144fea3b66909e3 100644 (file)
@@ -515,6 +515,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
         * and we need some headroom for passing the frame to monitor
         * interfaces, but never both at the same time.
         */
+       BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM !=
+                       sizeof(struct ieee80211_tx_status_rtap_hdr));
        local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
                                   sizeof(struct ieee80211_tx_status_rtap_hdr));
 
index d8d50fb5e823e395b5d160a6cf560f1678574847..c79e59f82fd9933bd98024d4d9b8551244c1f4a6 100644 (file)
@@ -915,6 +915,14 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
        sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
                                IEEE80211_STA_BEACON_POLL);
 
+       /*
+        * Always handle WMM once after association regardless
+        * of the first value the AP uses. Setting -1 here has
+        * that effect because the AP values is an unsigned
+        * 4-bit value.
+        */
+       sdata->u.mgd.wmm_last_param_set = -1;
+
        ieee80211_led_assoc(local, 1);
 
        sdata->vif.bss_conf.assoc = 1;
index 8834cc93c71691d993339ee99d285e392f7806ba..27ceaefd7bc8d3cb71a49bf51626192e8aacd3bd 100644 (file)
@@ -1419,6 +1419,10 @@ static bool need_dynamic_ps(struct ieee80211_local *local)
        if (!local->ps_sdata)
                return false;
 
+       /* No point if we're going to suspend */
+       if (local->quiescing)
+               return false;
+
        return true;
 }
 
index 78a6e924c7e13d11ae31b2acb42e4a2c2c1671af..dc76267e436ece4f322187d0170593ad5d9598d1 100644 (file)
@@ -1039,7 +1039,19 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 
        /* restart hardware */
        if (local->open_count) {
+               /*
+                * Upon resume hardware can sometimes be goofy due to
+                * various platform / driver / bus issues, so restarting
+                * the device may at times not work immediately. Propagate
+                * the error.
+                */
                res = drv_start(local);
+               if (res) {
+                       WARN(local->suspended, "Harware became unavailable "
+                            "upon resume. This is could be a software issue"
+                            "prior to suspend or a harware issue\n");
+                       return res;
+               }
 
                ieee80211_led_radio(local, true);
        }
index 3c3c50f38a1c4a773113db4f5388b27bc85453f8..f7a7f8380e385565034cb70f7f9a3dfdcf37bef2 100644 (file)
@@ -644,7 +644,22 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        p = gss_fill_context(p, end, ctx, gss_msg->auth->mech);
        if (IS_ERR(p)) {
                err = PTR_ERR(p);
-               gss_msg->msg.errno = (err == -EAGAIN) ? -EAGAIN : -EACCES;
+               switch (err) {
+               case -EACCES:
+                       gss_msg->msg.errno = err;
+                       err = mlen;
+                       break;
+               case -EFAULT:
+               case -ENOMEM:
+               case -EINVAL:
+               case -ENOSYS:
+                       gss_msg->msg.errno = -EAGAIN;
+                       break;
+               default:
+                       printk(KERN_CRIT "%s: bad return from "
+                               "gss_fill_context: %zd\n", __func__, err);
+                       BUG();
+               }
                goto err_release_msg;
        }
        gss_msg->ctx = gss_get_ctx(ctx);
index ef45eba22485cf355c8fdd17382943d7ff7ec602..2deb0ed72ff4ed7823a1fc22118c3ea46f0d7232 100644 (file)
@@ -131,8 +131,10 @@ gss_import_sec_context_kerberos(const void *p,
        struct  krb5_ctx *ctx;
        int tmp;
 
-       if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS)))
+       if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS))) {
+               p = ERR_PTR(-ENOMEM);
                goto out_err;
+       }
 
        p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
        if (IS_ERR(p))
index 6efbb0cd3c7cd03d18b610fa3ee7a42a5ba97a5e..76e4c6f4ac3c1ad8f58f1f7a92bf7781d05b18a3 100644 (file)
@@ -252,7 +252,7 @@ gss_import_sec_context(const void *input_token, size_t bufsize,
                       struct gss_ctx           **ctx_id)
 {
        if (!(*ctx_id = kzalloc(sizeof(**ctx_id), GFP_KERNEL)))
-               return GSS_S_FAILURE;
+               return -ENOMEM;
        (*ctx_id)->mech_type = gss_mech_get(mech);
 
        return mech->gm_ops
index 1c924ee0a1ef804105ec092d99badd880ca38b43..7d1f9e928f69b23ff640643c06c0b8b86f95b80b 100644 (file)
@@ -699,7 +699,8 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
        spin_unlock_bh(&pool->sp_lock);
 
        len = 0;
-       if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
+       if (test_bit(XPT_LISTENER, &xprt->xpt_flags) &&
+           !test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
                struct svc_xprt *newxpt;
                newxpt = xprt->xpt_ops->xpo_accept(xprt);
                if (newxpt) {
index 1001db4912f723bada113e61d9211c1ce9a35998..82e6002c8d678654f2cdfd7c88baa4ee53586a0b 100644 (file)
@@ -93,7 +93,18 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
                        }
                }
 
-               WARN_ON(!bss);
+               /*
+                * We might be coming here because the driver reported
+                * a successful association at the same time as the
+                * user requested a deauth. In that case, we will have
+                * removed the BSS from the auth_bsses list due to the
+                * deauth request when the assoc response makes it. If
+                * the two code paths acquire the lock the other way
+                * around, that's just the standard situation of a
+                * deauth being requested while connected.
+                */
+               if (!bss)
+                       goto out;
        } else if (wdev->conn) {
                cfg80211_sme_failed_assoc(wdev);
                /*
index 12dfa62aad18da8d74b6652dcef2c85c120fc896..0c2cbbebca95572d3897a30285aa03f9032f814e 100644 (file)
@@ -601,7 +601,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
        struct cfg80211_registered_device *rdev;
        struct wiphy *wiphy;
        struct iw_scan_req *wreq = NULL;
-       struct cfg80211_scan_request *creq;
+       struct cfg80211_scan_request *creq = NULL;
        int i, err, n_channels = 0;
        enum ieee80211_band band;
 
@@ -694,8 +694,10 @@ int cfg80211_wext_siwscan(struct net_device *dev,
        /* translate "Scan for SSID" request */
        if (wreq) {
                if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
-                       if (wreq->essid_len > IEEE80211_MAX_SSID_LEN)
-                               return -EINVAL;
+                       if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) {
+                               err = -EINVAL;
+                               goto out;
+                       }
                        memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
                        creq->ssids[0].ssid_len = wreq->essid_len;
                }
@@ -707,12 +709,15 @@ int cfg80211_wext_siwscan(struct net_device *dev,
        err = rdev->ops->scan(wiphy, dev, creq);
        if (err) {
                rdev->scan_req = NULL;
-               kfree(creq);
+               /* creq will be freed below */
        } else {
                nl80211_send_scan_start(rdev, dev);
+               /* creq now owned by driver */
+               creq = NULL;
                dev_hold(dev);
        }
  out:
+       kfree(creq);
        cfg80211_unlock_rdev(rdev);
        return err;
 }
index cb81ca35b0d6eae85ecac2f7967d556971519afb..4725a549ad4d52bc1c791425413b21bfe9af9929 100644 (file)
@@ -1445,7 +1445,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
        if (!dev)
                goto free_dst;
 
-       /* Copy neighbout for reachability confirmation */
+       /* Copy neighbour for reachability confirmation */
        dst0->neighbour = neigh_clone(dst->neighbour);
 
        xfrm_init_path((struct xfrm_dst *)dst0, dst, nfheader_len);
index cd815ac2a50b41da74f32d950b7e759e60f28605..0fe48cd91ffad42d80d8890c04fbd3f90f8869cd 100644 (file)
@@ -235,3 +235,8 @@ quiet_cmd_lzma = LZMA    $@
 cmd_lzma = (cat $(filter-out FORCE,$^) | \
        lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
        (rm -f $@ ; false)
+
+quiet_cmd_lzo = LZO    $@
+cmd_lzo = (cat $(filter-out FORCE,$^) | \
+       lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+       (rm -f $@ ; false)
index 445e8845f0a4c06ee5109e63471bab7769d2f3d5..090f2483970038e074d7be9593d635a6f1303e6a 100755 (executable)
@@ -296,46 +296,56 @@ my @status = ();
 
 foreach my $file (@files) {
 
-#Do not match excluded file patterns
-
-    my $exclude = 0;
-    foreach my $line (@typevalue) {
-       if ($line =~ m/^(\C):\s*(.*)/) {
-           my $type = $1;
-           my $value = $2;
-           if ($type eq 'X') {
-               if (file_match_pattern($file, $value)) {
-                   $exclude = 1;
-                   last;
-               }
-           }
-       }
-    }
+    my %hash;
+    my $tvi = find_first_section();
+    while ($tvi < @typevalue) {
+       my $start = find_starting_index($tvi);
+       my $end = find_ending_index($tvi);
+       my $exclude = 0;
+       my $i;
+
+       #Do not match excluded file patterns
 
-    if (!$exclude) {
-       my $tvi = 0;
-       my %hash;
-       foreach my $line (@typevalue) {
+       for ($i = $start; $i < $end; $i++) {
+           my $line = $typevalue[$i];
            if ($line =~ m/^(\C):\s*(.*)/) {
                my $type = $1;
                my $value = $2;
-               if ($type eq 'F') {
+               if ($type eq 'X') {
                    if (file_match_pattern($file, $value)) {
-                       my $value_pd = ($value =~ tr@/@@);
-                       my $file_pd = ($file  =~ tr@/@@);
-                       $value_pd++ if (substr($value,-1,1) ne "/");
-                       if ($pattern_depth == 0 ||
-                           (($file_pd - $value_pd) < $pattern_depth)) {
-                           $hash{$tvi} = $value_pd;
-                       }
+                       $exclude = 1;
                    }
                }
            }
-           $tvi++;
        }
-       foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
-           add_categories($line);
+
+       if (!$exclude) {
+           for ($i = $start; $i < $end; $i++) {
+               my $line = $typevalue[$i];
+               if ($line =~ m/^(\C):\s*(.*)/) {
+                   my $type = $1;
+                   my $value = $2;
+                   if ($type eq 'F') {
+                       if (file_match_pattern($file, $value)) {
+                           my $value_pd = ($value =~ tr@/@@);
+                           my $file_pd = ($file  =~ tr@/@@);
+                           $value_pd++ if (substr($value,-1,1) ne "/");
+                           if ($pattern_depth == 0 ||
+                               (($file_pd - $value_pd) < $pattern_depth)) {
+                               $hash{$tvi} = $value_pd;
+                           }
+                       }
+                   }
+               }
+           }
        }
+
+       $tvi += ($end - $start);
+
+    }
+
+    foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
+       add_categories($line);
     }
 
     if ($email && $email_git) {
@@ -570,6 +580,20 @@ sub format_email {
     return $formatted_email;
 }
 
+sub find_first_section {
+    my $index = 0;
+
+    while ($index < @typevalue) {
+       my $tv = $typevalue[$index];
+       if (($tv =~ m/^(\C):\s*(.*)/)) {
+           last;
+       }
+       $index++;
+    }
+
+    return $index;
+}
+
 sub find_starting_index {
     my ($index) = @_;
 
index 7a374c2eb043b1f611069bd1c67d64f7f64c7f13..9a2ee845e9d4c4b40bc29a9f33c67d591f2e8c30 100644 (file)
@@ -2365,7 +2365,7 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
                        initrlim = init_task.signal->rlim + i;
                        rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
                }
-               update_rlimit_cpu(rlim->rlim_cur);
+               update_rlimit_cpu(current->signal->rlim[RLIMIT_CPU].rlim_cur);
        }
 }
 
index c5699863643b4241538b563299a6cc275de57c27..656e474dca47f1a20d0ed473ebdfc1e8eb0c1a7f 100644 (file)
@@ -441,6 +441,7 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
                              struct snd_pcm_hw_params *params)
 {
        int err;
+       struct aaci *aaci = substream->private_data;
 
        aaci_pcm_hw_free(substream);
        if (aacirun->pcm_open) {
@@ -560,7 +561,6 @@ static int aaci_pcm_open(struct snd_pcm_substream *substream)
 static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
                                       struct snd_pcm_hw_params *params)
 {
-       struct aaci *aaci = substream->private_data;
        struct aaci_runtime *aacirun = substream->runtime->private_data;
        unsigned int channels = params_channels(params);
        int ret;
@@ -659,7 +659,6 @@ static struct snd_pcm_ops aaci_playback_ops = {
 static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream,
                                      struct snd_pcm_hw_params *params)
 {
-       struct aaci *aaci = substream->private_data;
        struct aaci_runtime *aacirun = substream->runtime->private_data;
        int ret;
 
index 29ab46a12e11cda66ff86a2865c74b9286274761..25b0641e6b8c28b7afefb3e54648990f6618e80c 100644 (file)
@@ -1918,13 +1918,13 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
 
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
                                           hw->rate_min, hw->rate_max);
-        if (err < 0)
-                return err;
+       if (err < 0)
+               return err;
 
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
                                           hw->period_bytes_min, hw->period_bytes_max);
-        if (err < 0)
-                return err;
+       if (err < 0)
+               return err;
 
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
                                           hw->periods_min, hw->periods_max);
index 5fe34a8d8c816ae6df99d80753a97a8afed1cd3e..e4581a42ace56e62ba0e530f5a6cbd360f43b2d3 100644 (file)
@@ -42,7 +42,7 @@ static void snd_hda_generate_beep(struct work_struct *work)
                return;
 
        /* generate tone */
-       snd_hda_codec_write_cache(codec, beep->nid, 0,
+       snd_hda_codec_write(codec, beep->nid, 0,
                        AC_VERB_SET_BEEP_CONTROL, beep->tone);
 }
 
@@ -119,7 +119,7 @@ static void snd_hda_do_detach(struct hda_beep *beep)
        beep->dev = NULL;
        cancel_work_sync(&beep->beep_work);
        /* turn off beep for sure */
-       snd_hda_codec_write_cache(beep->codec, beep->nid, 0,
+       snd_hda_codec_write(beep->codec, beep->nid, 0,
                                  AC_VERB_SET_BEEP_CONTROL, 0);
 }
 
@@ -192,7 +192,7 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
                beep->enabled = enable;
                if (!enable) {
                        /* turn off beep */
-                       snd_hda_codec_write_cache(beep->codec, beep->nid, 0,
+                       snd_hda_codec_write(beep->codec, beep->nid, 0,
                                                  AC_VERB_SET_BEEP_CONTROL, 0);
                }
                if (beep->mode == HDA_BEEP_MODE_SWREG) {
@@ -239,8 +239,12 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
        mutex_init(&beep->mutex);
 
        if (beep->mode == HDA_BEEP_MODE_ON) {
-               beep->enabled = 1;
-               snd_hda_do_register(&beep->register_work);
+               int err = snd_hda_do_attach(beep);
+               if (err < 0) {
+                       kfree(beep);
+                       codec->beep = NULL;
+                       return err;
+               }
        }
 
        return 0;
@@ -253,7 +257,7 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
        if (beep) {
                cancel_work_sync(&beep->register_work);
                cancel_delayed_work(&beep->unregister_work);
-               if (beep->enabled)
+               if (beep->dev)
                        snd_hda_do_detach(beep);
                codec->beep = NULL;
                kfree(beep);
index 950ee5cfcacf06611d9d818832b8367944314086..f98b47cd6cfb38fc97335c3788a8f7f5cc3afca1 100644 (file)
@@ -1327,11 +1327,13 @@ EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
  */
 u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
 {
-       u32 pincap = snd_hda_query_pin_caps(codec, nid);
-
-       if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
-               snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
+       u32 pincap;
 
+       if (!codec->no_trigger_sense) {
+               pincap = snd_hda_query_pin_caps(codec, nid);
+               if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
+                       snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
+       }
        return snd_hda_codec_read(codec, nid, 0,
                                  AC_VERB_GET_PIN_SENSE, 0);
 }
index 1d541b7f5547cde1e3871d45e44e7cae4931a435..0a770a28e71f8b66a6c225bf08133dcec5d99390 100644 (file)
@@ -817,6 +817,7 @@ struct hda_codec {
        unsigned int pin_amp_workaround:1; /* pin out-amp takes index
                                            * (e.g. Conexant codecs)
                                            */
+       unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        unsigned int power_on :1;       /* current (global) power-state */
        unsigned int power_transition :1; /* power-state in transition */
index ff8ad46cc50e09dc726775322314d9ec5bb8d15f..ec9c348336cc383d5bb2902bc1e525bdda1afd96 100644 (file)
@@ -356,6 +356,7 @@ struct azx_dev {
                                         */
        unsigned char stream_tag;       /* assigned stream */
        unsigned char index;            /* stream index */
+       int device;                     /* last device number assigned to */
 
        unsigned int opened :1;
        unsigned int running :1;
@@ -1441,10 +1442,13 @@ static int __devinit azx_codec_configure(struct azx *chip)
  */
 
 /* assign a stream for the PCM */
-static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream)
+static inline struct azx_dev *
+azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
 {
        int dev, i, nums;
-       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+       struct azx_dev *res = NULL;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                dev = chip->playback_index_offset;
                nums = chip->playback_streams;
        } else {
@@ -1453,10 +1457,15 @@ static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream)
        }
        for (i = 0; i < nums; i++, dev++)
                if (!chip->azx_dev[dev].opened) {
-                       chip->azx_dev[dev].opened = 1;
-                       return &chip->azx_dev[dev];
+                       res = &chip->azx_dev[dev];
+                       if (res->device == substream->pcm->device)
+                               break;
                }
-       return NULL;
+       if (res) {
+               res->opened = 1;
+               res->device = substream->pcm->device;
+       }
+       return res;
 }
 
 /* release the assigned stream */
@@ -1505,7 +1514,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        int err;
 
        mutex_lock(&chip->open_mutex);
-       azx_dev = azx_assign_device(chip, substream->stream);
+       azx_dev = azx_assign_device(chip, substream);
        if (azx_dev == NULL) {
                mutex_unlock(&chip->open_mutex);
                return -EBUSY;
index 1a36137e13eca5f3d488402da0084500fa4489bc..69a941c7b1588b7db4a9acd0fe79da65824c8944 100644 (file)
@@ -1186,6 +1186,8 @@ static int patch_ad1986a(struct hda_codec *codec)
         */
        spec->multiout.no_share_stream = 1;
 
+       codec->no_trigger_sense = 1;
+
        return 0;
 }
 
@@ -1371,6 +1373,8 @@ static int patch_ad1983(struct hda_codec *codec)
 
        codec->patch_ops = ad198x_patch_ops;
 
+       codec->no_trigger_sense = 1;
+
        return 0;
 }
 
@@ -1813,6 +1817,9 @@ static int patch_ad1981(struct hda_codec *codec)
                codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
                break;
        }
+
+       codec->no_trigger_sense = 1;
+
        return 0;
 }
 
@@ -3118,6 +3125,8 @@ static int patch_ad1988(struct hda_codec *codec)
 #endif
        spec->vmaster_nid = 0x04;
 
+       codec->no_trigger_sense = 1;
+
        return 0;
 }
 
@@ -3330,6 +3339,8 @@ static int patch_ad1884(struct hda_codec *codec)
 
        codec->patch_ops = ad198x_patch_ops;
 
+       codec->no_trigger_sense = 1;
+
        return 0;
 }
 
@@ -4287,6 +4298,8 @@ static int patch_ad1884a(struct hda_codec *codec)
                break;
        }
 
+       codec->no_trigger_sense = 1;
+
        return 0;
 }
 
@@ -4623,6 +4636,9 @@ static int patch_ad1882(struct hda_codec *codec)
                spec->mixers[2] = ad1882_6stack_mixers;
                break;
        }
+
+       codec->no_trigger_sense = 1;
+
        return 0;
 }
 
index eeda7beeb57a2300fe38ed2e83b7b1d22dcfeea0..2291a839681795606ee9333920627966c577069d 100644 (file)
@@ -4453,14 +4453,7 @@ static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
 {
        if (!nid)
                return 0;
-       /* NOTE: we can't use snd_hda_jack_detect() here because STAC/IDT
-        * codecs behave wrongly when SET_PIN_SENSE is triggered, although
-        * the pincap gives TRIG_REQ bit.
-        */
-       if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0) &
-           AC_PINSENSE_PRESENCE)
-               return 1;
-       return 0;
+       return snd_hda_jack_detect(codec, nid);
 }
 
 static void stac92xx_line_out_detect(struct hda_codec *codec,
@@ -4962,6 +4955,7 @@ static int patch_stac9200(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
        spec->pin_nids = stac9200_pin_nids;
@@ -5024,6 +5018,7 @@ static int patch_stac925x(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
        spec->pin_nids = stac925x_pin_nids;
@@ -5108,6 +5103,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        codec->slave_dig_outs = stac92hd73xx_slave_dig_outs;
        spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids);
@@ -5255,6 +5251,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
        spec->digbeep_nid = 0x21;
@@ -5418,6 +5415,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        codec->patch_ops = stac92xx_patch_ops;
        spec->num_pins = STAC92HD71BXX_NUM_PINS;
@@ -5661,6 +5659,7 @@ static int patch_stac922x(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac922x_pin_nids);
        spec->pin_nids = stac922x_pin_nids;
@@ -5764,6 +5763,7 @@ static int patch_stac927x(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        codec->slave_dig_outs = stac927x_slave_dig_outs;
        spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
@@ -5898,6 +5898,7 @@ static int patch_stac9205(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac9205_pin_nids);
        spec->pin_nids = stac9205_pin_nids;
@@ -6053,6 +6054,7 @@ static int patch_stac9872(struct hda_codec *codec)
        spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
                return -ENOMEM;
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
        spec->pin_nids = stac9872_pin_nids;
index 69bd0acc81c8c45a26adc0cc99d2c32f2289e21a..a1bbe16b7f9613e3129ebdb8819125c2b7c7463a 100644 (file)
@@ -102,6 +102,12 @@ static int ac97_soc_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&codec->dapm_widgets);
        INIT_LIST_HEAD(&codec->dapm_paths);
 
+       ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
+       if (ret < 0) {
+               printk(KERN_ERR "ASoC: failed to init gen ac97 glue\n");
+               goto err;
+       }
+
        /* register pcms */
        ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
        if (ret < 0)
index 265e68c75df8e2908bcf4bcba8724c8c12599013..af8cb6995a1f5d053ffda2e348c6cf489270d5f2 100644 (file)
@@ -424,23 +424,23 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
 
        /* filter coefficient */
        switch (params_rate(params)) {
-       case SNDRV_PCM_RATE_8000:
+       case 8000:
                adn |= 0x5 << 1;
                break;
-       case SNDRV_PCM_RATE_11025:
+       case 11025:
                adn |= 0x4 << 1;
                break;
-       case SNDRV_PCM_RATE_16000:
+       case 16000:
                adn |= 0x3 << 1;
                break;
-       case SNDRV_PCM_RATE_22050:
+       case 22050:
                adn |= 0x2 << 1;
                break;
-       case SNDRV_PCM_RATE_32000:
+       case 32000:
                adn |= 0x1 << 1;
                break;
-       case SNDRV_PCM_RATE_44100:
-       case SNDRV_PCM_RATE_48000:
+       case 44100:
+       case 48000:
                break;
        }
 
index 3d850b97037a69fed4961ea6eea3591e53617587..31e39ffd1d8e84f27ae1f0daf5ca17e22c14331a 100644 (file)
@@ -378,23 +378,23 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
                iface |= (1 << 9);
 
        switch (params_rate(params)) {
-       case SNDRV_PCM_RATE_8000:
+       case 8000:
                addcntrl |= (0x5 << 1);
                break;
-       case SNDRV_PCM_RATE_11025:
+       case 11025:
                addcntrl |= (0x4 << 1);
                break;
-       case SNDRV_PCM_RATE_16000:
+       case 16000:
                addcntrl |= (0x3 << 1);
                break;
-       case SNDRV_PCM_RATE_22050:
+       case 22050:
                addcntrl |= (0x2 << 1);
                break;
-       case SNDRV_PCM_RATE_32000:
+       case 32000:
                addcntrl |= (0x1 << 1);
                break;
-       case SNDRV_PCM_RATE_44100:
-       case SNDRV_PCM_RATE_48000:
+       case 44100:
+       case 48000:
                break;
        }
        ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl);
index a808675388fc99d6e9a03cca06e0ce2f5114d829..8812751da8c9838c484ffe66ae1d0e0eb8858546 100644 (file)
@@ -482,23 +482,23 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream,
 
        /* filter coefficient */
        switch (params_rate(params)) {
-       case SNDRV_PCM_RATE_8000:
+       case 8000:
                adn |= 0x5 << 1;
                break;
-       case SNDRV_PCM_RATE_11025:
+       case 11025:
                adn |= 0x4 << 1;
                break;
-       case SNDRV_PCM_RATE_16000:
+       case 16000:
                adn |= 0x3 << 1;
                break;
-       case SNDRV_PCM_RATE_22050:
+       case 22050:
                adn |= 0x2 << 1;
                break;
-       case SNDRV_PCM_RATE_32000:
+       case 32000:
                adn |= 0x1 << 1;
                break;
-       case SNDRV_PCM_RATE_44100:
-       case SNDRV_PCM_RATE_48000:
+       case 44100:
+       case 48000:
                break;
        }
 
index c7af09729c6eb88205f38557e1135f035d813912..5263ab18f827ad92f01e6ed29f773a176b83b21a 100644 (file)
@@ -42,42 +42,12 @@ static struct snd_soc_device fsi_snd_devdata = {
        .codec_dev      = &soc_codec_dev_ak4642,
 };
 
-#define AK4642_BUS 0
-#define AK4642_ADR 0x12
-static int ak4642_add_i2c_device(void)
-{
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = AK4642_ADR;
-       strlcpy(info.type, "ak4642", I2C_NAME_SIZE);
-
-       adapter = i2c_get_adapter(AK4642_BUS);
-       if (!adapter) {
-               printk(KERN_DEBUG "can't get i2c adapter\n");
-               return -ENODEV;
-       }
-
-       client = i2c_new_device(adapter, &info);
-       i2c_put_adapter(adapter);
-       if (!client) {
-               printk(KERN_DEBUG "can't add i2c device\n");
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
 static struct platform_device *fsi_snd_device;
 
 static int __init fsi_ak4642_init(void)
 {
        int ret = -ENOMEM;
 
-       ak4642_add_i2c_device();
-
        fsi_snd_device = platform_device_alloc("soc-audio", -1);
        if (!fsi_snd_device)
                goto out;
index 4390d225686d63360cf9c5e8bbc87b9bebdec8af..652a470b5f749aeadc05e33f617bf18a588b3162 100644 (file)
@@ -343,13 +343,18 @@ LIB_H += util/include/linux/string.h
 LIB_H += util/include/linux/types.h
 LIB_H += util/include/asm/asm-offsets.h
 LIB_H += util/include/asm/bitops.h
+LIB_H += util/include/asm/bug.h
 LIB_H += util/include/asm/byteorder.h
 LIB_H += util/include/asm/swab.h
 LIB_H += util/include/asm/system.h
 LIB_H += util/include/asm/uaccess.h
 LIB_H += perf.h
+LIB_H += util/cache.h
+LIB_H += util/callchain.h
+LIB_H += util/debug.h
 LIB_H += util/debugfs.h
 LIB_H += util/event.h
+LIB_H += util/exec_cmd.h
 LIB_H += util/types.h
 LIB_H += util/levenshtein.h
 LIB_H += util/parse-options.h
@@ -362,6 +367,7 @@ LIB_H += util/session.h
 LIB_H += util/strbuf.h
 LIB_H += util/string.h
 LIB_H += util/strlist.h
+LIB_H += util/svghelper.h
 LIB_H += util/run-command.h
 LIB_H += util/sigchain.h
 LIB_H += util/symbol.h
@@ -370,6 +376,8 @@ LIB_H += util/values.h
 LIB_H += util/sort.h
 LIB_H += util/hist.h
 LIB_H += util/thread.h
+LIB_H += util/trace-event.h
+LIB_H += util/trace-event-perl.h
 LIB_H += util/probe-finder.h
 LIB_H += util/probe-event.h
 
index e693e6777af5a3418d3f0b542a4197b2383aa741..1e99ac806913679d963ae8043f6035f844ea2bc2 100644 (file)
@@ -17,7 +17,7 @@
 static char const *input_name = "perf.data";
 static int force;
 
-static const char *const buildid_list_usage[] = {
+static const char * const buildid_list_usage[] = {
        "perf buildid-list [<options>]",
        NULL
 };
index 4d33b55d55846c9c46fe8854824e4eb8da5c3873..bd71b8ceafb78d0c0e6f05e2daa266b2d4758d88 100644 (file)
@@ -189,8 +189,9 @@ out_delete:
        return ret;
 }
 
-static const char *const diff_usage[] = {
+static const char * const diff_usage[] = {
        "perf diff [<options>] [old_file] [new_file]",
+       NULL,
 };
 
 static const struct option options[] = {
index fc21ad79dd83e25a7520f00e6d3611587650ee79..7ceb7416c3169dadb71fbf44de7246a4e25c5f2a 100644 (file)
@@ -137,7 +137,7 @@ static void insert_alloc_stat(unsigned long call_site, unsigned long ptr,
        if (data && data->ptr == ptr) {
                data->hit++;
                data->bytes_req += bytes_req;
-               data->bytes_alloc += bytes_req;
+               data->bytes_alloc += bytes_alloc;
        } else {
                data = malloc(sizeof(*data));
                if (!data)
@@ -177,7 +177,7 @@ static void insert_caller_stat(unsigned long call_site,
        if (data && data->call_site == call_site) {
                data->hit++;
                data->bytes_req += bytes_req;
-               data->bytes_alloc += bytes_req;
+               data->bytes_alloc += bytes_alloc;
        } else {
                data = malloc(sizeof(*data));
                if (!data)
index 63136d0534d450ef18a6bf65ee1d78275f41333b..265425322734eecfc3087a7be42a60960c89f2b0 100644 (file)
@@ -402,7 +402,7 @@ static void atexit_header(void)
        perf_header__write(&session->header, output, true);
 }
 
-static int __cmd_record(int argc __used, const char **argv)
+static int __cmd_record(int argc, const char **argv)
 {
        int i, counter;
        struct stat st;
@@ -411,6 +411,7 @@ static int __cmd_record(int argc __used, const char **argv)
        int err;
        unsigned long waking = 0;
        int child_ready_pipe[2], go_pipe[2];
+       const bool forks = target_pid == -1 && argc > 0;
        char buf;
 
        page_size = sysconf(_SC_PAGE_SIZE);
@@ -422,7 +423,7 @@ static int __cmd_record(int argc __used, const char **argv)
        signal(SIGCHLD, sig_handler);
        signal(SIGINT, sig_handler);
 
-       if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) {
+       if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
                perror("failed to create pipes");
                exit(-1);
        }
@@ -483,7 +484,7 @@ static int __cmd_record(int argc __used, const char **argv)
 
        atexit(atexit_header);
 
-       if (target_pid == -1) {
+       if (forks) {
                pid = fork();
                if (pid < 0) {
                        perror("failed to fork");
@@ -550,7 +551,7 @@ static int __cmd_record(int argc __used, const char **argv)
                        return err;
        }
 
-       if (!system_wide)
+       if (!system_wide && profile_cpu == -1)
                event__synthesize_thread(pid, process_synthesized_event,
                                         session);
        else
@@ -569,7 +570,8 @@ static int __cmd_record(int argc __used, const char **argv)
        /*
         * Let the child rip
         */
-       close(go_pipe[1]);
+       if (forks)
+               close(go_pipe[1]);
 
        for (;;) {
                int hits = samples;
@@ -667,7 +669,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 
        argc = parse_options(argc, argv, options, record_usage,
                            PARSE_OPT_STOP_AT_NON_OPTION);
-       if (!argc && target_pid == -1 && (!system_wide || profile_cpu == -1))
+       if (!argc && target_pid == -1 && !system_wide && profile_cpu == -1)
                usage_with_options(record_usage, options);
 
        symbol__init();
index 5c2ab5357ec689b4047689fa6281a1d1a99f78fb..db10c0e8ecae7ee18f4ce352256bed5516fd4024 100644 (file)
@@ -294,8 +294,7 @@ setup:
        return 0;
 }
 
-//static const char * const report_usage[] = {
-const char * const report_usage[] = {
+static const char * const report_usage[] = {
        "perf report [<options>] <command>",
        NULL
 };
index e2285e28720fe2cb076240edc53fdd90913ee748..574a215e800b502abeb05fa9e874421db8e3f79a 100644 (file)
@@ -512,7 +512,7 @@ static char *get_script_path(const char *script_root, const char *suffix)
        return path;
 }
 
-static const char * const annotate_usage[] = {
+static const char * const trace_usage[] = {
        "perf trace [<options>] <command>",
        NULL
 };
@@ -581,7 +581,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
 
        setup_scripting();
 
-       argc = parse_options(argc, argv, options, annotate_usage,
+       argc = parse_options(argc, argv, options, trace_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
 
        if (symbol__init() < 0)
index f000c30877acf3eb153c8a499b61d51660fde917..8d0de5130db3a2d006e1e04497ba41fcf09e7247 100644 (file)
@@ -21,7 +21,7 @@ There's one file descriptor per virtual counter used.
 The special file descriptor is opened via the perf_event_open()
 system call:
 
-   int sys_perf_event_open(struct perf_event_hw_event *hw_event_uptr,
+   int sys_perf_event_open(struct perf_event_attr *hw_event_uptr,
                             pid_t pid, int cpu, int group_fd,
                             unsigned long flags);
 
@@ -32,9 +32,9 @@ can be used to set the blocking mode, etc.
 Multiple counters can be kept open at a time, and the counters
 can be poll()ed.
 
-When creating a new counter fd, 'perf_event_hw_event' is:
+When creating a new counter fd, 'perf_event_attr' is:
 
-struct perf_event_hw_event {
+struct perf_event_attr {
         /*
          * The MSB of the config word signifies if the rest contains cpu
          * specific (raw) counter configuration data, if unset, the next
@@ -399,7 +399,7 @@ Notification of new events is possible through poll()/select()/epoll() and
 fcntl() managing signals.
 
 Normally a notification is generated for every page filled, however one can
-additionally set perf_event_hw_event.wakeup_events to generate one every
+additionally set perf_event_attr.wakeup_events to generate one every
 so many counter overflow events.
 
 Future work will include a splice() interface to the ring-buffer.
index 1c3039f28909bc4f6e96ab4c654af563f7788582..e2721f5a350411fc7fb502b21ccd73e6620d9a50 100644 (file)
@@ -72,6 +72,15 @@ config RD_LZMA
          Support loading of a LZMA encoded initial ramdisk or cpio buffer
          If unsure, say N.
 
+config RD_LZO
+       bool "Support initial ramdisks compressed using LZO" if EMBEDDED
+       default !EMBEDDED
+       depends on BLK_DEV_INITRD
+       select DECOMPRESS_LZO
+       help
+         Support loading of a LZO encoded initial ramdisk or cpio buffer
+         If unsure, say N.
+
 choice
        prompt "Built-in initramfs compression mode" if INITRAMFS_SOURCE!=""
        help
@@ -108,16 +117,15 @@ config INITRAMFS_COMPRESSION_GZIP
        bool "Gzip"
        depends on RD_GZIP
        help
-         The old and tried gzip compression. Its compression ratio is
-         the poorest among the 3 choices; however its speed (both
-         compression and decompression) is the fastest.
+         The old and tried gzip compression. It provides a good balance
+         between compression ratio and decompression speed.
 
 config INITRAMFS_COMPRESSION_BZIP2
        bool "Bzip2"
        depends on RD_BZIP2
        help
          Its compression ratio and speed is intermediate.
-         Decompression speed is slowest among the three.  The initramfs
+         Decompression speed is slowest among the four.  The initramfs
          size is about 10% smaller with bzip2, in comparison to gzip.
          Bzip2 uses a large amount of memory. For modern kernels you
          will need at least 8MB RAM or more for booting.
@@ -128,7 +136,15 @@ config INITRAMFS_COMPRESSION_LZMA
        help
          The most recent compression algorithm.
          Its ratio is best, decompression speed is between the other
-         two. Compression is slowest.  The initramfs size is about 33%
+         three. Compression is slowest. The initramfs size is about 33%
          smaller with LZMA in comparison to gzip.
 
+config INITRAMFS_COMPRESSION_LZO
+       bool "LZO"
+       depends on RD_LZO
+       help
+         Its compression ratio is the poorest among the four. The kernel
+         size is about about 10% bigger than gzip; however its speed
+         (both compression and decompression) is the fastest.
+
 endchoice
index fd9c097b760ae909c0425dbfe6d2b8aa034fc24d..f73de631e3eef53d6a5c50b95b21f037969d2f95 100644 (file)
@@ -508,8 +508,8 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
        struct kvm_assigned_dev_kernel *match;
        struct pci_dev *dev;
 
-       down_read(&kvm->slots_lock);
        mutex_lock(&kvm->lock);
+       down_read(&kvm->slots_lock);
 
        match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
                                      assigned_dev->assigned_dev_id);
@@ -573,8 +573,8 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
        }
 
 out:
-       mutex_unlock(&kvm->lock);
        up_read(&kvm->slots_lock);
+       mutex_unlock(&kvm->lock);
        return r;
 out_list_del:
        list_del(&match->list);
@@ -585,8 +585,8 @@ out_put:
        pci_dev_put(dev);
 out_free:
        kfree(match);
-       mutex_unlock(&kvm->lock);
        up_read(&kvm->slots_lock);
+       mutex_unlock(&kvm->lock);
        return r;
 }
 
index b5af88167613ded2aba4ebcdca2cb702d47c84eb..a944be392d6e9420aa38d833cbc736bf9f07d22e 100644 (file)
@@ -64,7 +64,7 @@ MODULE_LICENSE("GPL");
 /*
  * Ordering of locks:
  *
- *             kvm->slots_lock --> kvm->lock --> kvm->irq_lock
+ *             kvm->lock --> kvm->slots_lock --> kvm->irq_lock
  */
 
 DEFINE_SPINLOCK(kvm_lock);
@@ -406,8 +406,11 @@ static struct kvm *kvm_create_vm(void)
 out:
        return kvm;
 
+#if defined(KVM_COALESCED_MMIO_PAGE_OFFSET) || \
+    (defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER))
 out_err:
        hardware_disable_all();
+#endif
 out_err_nodisable:
        kfree(kvm);
        return ERR_PTR(r);
This page took 0.669022 seconds and 5 git commands to generate.