Merge tag 'pinctrl-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Apr 2013 16:40:35 +0000 (09:40 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Apr 2013 16:40:35 +0000 (09:40 -0700)
Pull pinctrl update from Linus Walleij:
 "These are the pinctrl changes for v3.10:

   - Patrice Chotard contributed a new configuration debugfs interface
     and reintroduced fine-grained locking into the core: instead of
     having a "big pinctrl lock" we have a per-controller lock and
     specialized locks for the global controller and pinctrl handle
     lists.

   - Haoijan Zhuang deleted all the PXA and MMP2 pinctrl drivers and
     replaced them with pinctrl-single (which is also used by other
     SoCs) so we are gaining consolidation.  The platform particulars
     now come in through the device tree.

   - Haoijan also added support for generic pin config into the
     pinctrl-single driver which is another big consolidation win.

   - Finally also GPIO ranges are now supported by the pinctrl-single
     driver.

   - Tomasz Figa contributed a new Samsung S3C pinctrl driver, bringing
     more of the older Samsung platforms under the pinctrl umbrella and
     out of arch/arm.

   - Maxime Ripard contributed new Allwinner A10/A13 drivers.

   - Sachin Kamat, Wei Yongjun and Axel Lin did a lot of cleanups."

* tag 'pinctrl-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (66 commits)
  pinctrl: move subsystem mutex to pinctrl_dev struct
  pinctrl/pinconfig: fix misplaced goto
  pinctrl: s3c64xx: Fix build error caused by undefined chained_irq_enter
  pinctrl/pinconfig: add debug interface
  pinctrl: abx500: fix issue when no pdata
  pinctrl: pinctrl-single: add missing double quote
  pinctrl: sunxi: Rename wemac functions to emac
  pinctrl: exynos5440: add gpio interrupt support
  pinctrl: exynos5440: fix probe failure due to missing pin-list in config nodes
  pinctrl: ab8505: Staticize some symbols
  pinctrl: ab8540: Staticize some symbols
  pinctrl: ab9540: Staticize some symbols
  pinctrl: ab8500: Staticize some symbols
  pinctrl: abx500: Staticize some symbols
  pinctrl: Add pinctrl-s3c64xx driver
  pinctrl: samsung: Handle banks with two configuration registers
  pinctrl: samsung: Remove hardcoded register offsets
  pinctrl: samsung: Split pin bank description into two structures
  pinctrl: samsung: Include pinctrl-exynos driver data conditionally
  pinctrl: samsung: Protect bank registers with a spinlock
  ...

819 files changed:
Documentation/DocBook/device-drivers.tmpl
Documentation/devicetree/bindings/video/via,vt8500-fb.txt
Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
Documentation/ia64/err_inject.txt
Documentation/kdump/kdump.txt
Documentation/kernel-parameters.txt
Documentation/s390/s390dbf.txt
Documentation/scsi/LICENSE.qla2xxx
Documentation/sound/alsa/ALSA-Configuration.txt
MAINTAINERS
Makefile
arch/alpha/Makefile
arch/alpha/include/asm/floppy.h
arch/alpha/kernel/irq.c
arch/alpha/kernel/irq_alpha.c
arch/alpha/kernel/sys_nautilus.c
arch/alpha/kernel/sys_titan.c
arch/arc/include/asm/irqflags.h
arch/arm/Kconfig
arch/arm/boot/dts/armada-370-mirabox.dts
arch/arm/boot/dts/armada-370.dtsi
arch/arm/boot/dts/dbx5x0.dtsi
arch/arm/boot/dts/imx28-m28evk.dts
arch/arm/boot/dts/imx28-sps1.dts
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/kirkwood-goflexnet.dts
arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
arch/arm/boot/dts/orion5x.dtsi
arch/arm/boot/dts/vt8500-bv07.dts
arch/arm/boot/dts/vt8500.dtsi
arch/arm/boot/dts/wm8505-ref.dts
arch/arm/boot/dts/wm8505.dtsi
arch/arm/boot/dts/wm8650-mid.dts
arch/arm/boot/dts/wm8650.dtsi
arch/arm/boot/dts/wm8850-w70v2.dts
arch/arm/boot/dts/wm8850.dtsi
arch/arm/include/asm/delay.h
arch/arm/include/asm/glue-cache.h
arch/arm/include/asm/hardware/iop3xx.h
arch/arm/include/asm/highmem.h
arch/arm/include/asm/mmu_context.h
arch/arm/include/asm/pgtable-3level.h
arch/arm/include/asm/tlbflush.h
arch/arm/kernel/entry-common.S
arch/arm/kernel/head.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/sched_clock.c
arch/arm/kernel/setup.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_tlb.c
arch/arm/kernel/tcm.c
arch/arm/kernel/tcm.h [deleted file]
arch/arm/kvm/arm.c
arch/arm/kvm/coproc.c
arch/arm/kvm/vgic.c
arch/arm/lib/delay.c
arch/arm/mach-cns3xxx/core.c
arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
arch/arm/mach-ep93xx/include/mach/uncompress.h
arch/arm/mach-highbank/hotplug.c
arch/arm/mach-imx/clk-imx35.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/common.h
arch/arm/mach-imx/hotplug.c
arch/arm/mach-imx/src.c
arch/arm/mach-kirkwood/board-iomega_ix2_200.c
arch/arm/mach-kirkwood/guruplug-setup.c
arch/arm/mach-kirkwood/openrd-setup.c
arch/arm/mach-kirkwood/rd88f6281-setup.c
arch/arm/mach-msm/timer.c
arch/arm/mach-mvebu/irq-armada-370-xp.c
arch/arm/mach-omap1/clock_data.c
arch/arm/mach-omap2/cclock44xx_data.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod.h
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-s3c24xx/include/mach/irqs.h
arch/arm/mach-s3c24xx/irq.c
arch/arm/mach-ux500/board-mop500-sdi.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/board-mop500.h
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mm/Kconfig
arch/arm/mm/Makefile
arch/arm/mm/cache-feroceon-l2.c
arch/arm/mm/cache-l2x0.c
arch/arm/mm/cache-v3.S [deleted file]
arch/arm/mm/cache-v4.S
arch/arm/mm/context.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-arm740.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-mohawk.S
arch/arm/mm/proc-sa1100.S
arch/arm/mm/proc-syms.c
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-v7.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S
arch/arm/mm/tcm.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/fb.h
arch/avr32/include/asm/io.h
arch/c6x/include/asm/irqflags.h
arch/ia64/Kconfig
arch/ia64/include/asm/futex.h
arch/ia64/include/asm/mca.h
arch/ia64/include/asm/numa.h
arch/ia64/kernel/fsys.S
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/irq.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca_drv.c
arch/ia64/kernel/palinfo.c
arch/ia64/kvm/vtlb.c
arch/ia64/mm/ioremap.c
arch/ia64/mm/numa.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/tiocx.c
arch/m68k/include/asm/gpio.h
arch/mips/Kconfig
arch/mips/bcm63xx/boards/board_bcm963xx.c
arch/mips/bcm63xx/nvram.c
arch/mips/bcm63xx/setup.c
arch/mips/cavium-octeon/setup.c
arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/page.h
arch/mips/include/asm/signal.h
arch/mips/include/uapi/asm/signal.h
arch/mips/kernel/Makefile
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/linux32.c
arch/mips/kernel/mcount.S
arch/mips/kernel/proc.c
arch/mips/kernel/traps.c
arch/mips/lib/bitops.c
arch/mips/lib/csum_partial.S
arch/mips/mm/c-r4k.c
arch/mips/mm/sc-mips.c
arch/mips/pci/pci-alchemy.c
arch/mips/pci/pci.c
arch/parisc/Makefile
arch/parisc/include/asm/cacheflush.h
arch/parisc/include/asm/pgtable.h
arch/parisc/include/asm/uaccess.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/parisc_ksyms.c
arch/parisc/lib/Makefile
arch/parisc/lib/ucmpdi2.c [new file with mode: 0644]
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/tm.S
arch/powerpc/kvm/e500.h
arch/powerpc/kvm/e500_mmu_host.c
arch/powerpc/kvm/e500mc.c
arch/powerpc/platforms/pseries/lpar.c
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/hypfs/hypfs_dbfs.c
arch/s390/include/asm/bitops.h
arch/s390/include/asm/ccwdev.h
arch/s390/include/asm/cio.h
arch/s390/include/asm/compat.h
arch/s390/include/asm/elf.h
arch/s390/include/asm/io.h
arch/s390/include/asm/pci.h
arch/s390/include/asm/pci_debug.h
arch/s390/include/asm/pci_insn.h
arch/s390/include/asm/pci_io.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/ptrace.h
arch/s390/include/asm/syscall.h
arch/s390/include/asm/thread_info.h
arch/s390/include/uapi/asm/ptrace.h
arch/s390/include/uapi/asm/statfs.h
arch/s390/kernel/Makefile
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/dis.c
arch/s390/kernel/dumpstack.c [new file with mode: 0644]
arch/s390/kernel/entry.S
arch/s390/kernel/entry.h
arch/s390/kernel/entry64.S
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/suspend.c
arch/s390/kernel/swsusp_asm64.S
arch/s390/kernel/traps.c
arch/s390/kvm/trace.h
arch/s390/lib/uaccess_pt.c
arch/s390/mm/cmm.c
arch/s390/mm/fault.c
arch/s390/mm/init.c
arch/s390/mm/pageattr.c
arch/s390/mm/pgtable.c
arch/s390/net/bpf_jit_comp.c
arch/s390/pci/Makefile
arch/s390/pci/pci.c
arch/s390/pci/pci_clp.c
arch/s390/pci/pci_debug.c
arch/s390/pci/pci_dma.c
arch/s390/pci/pci_insn.c [new file with mode: 0644]
arch/s390/pci/pci_msi.c
arch/sparc/include/asm/Kbuild
arch/sparc/include/asm/cputime.h [deleted file]
arch/sparc/include/asm/emergency-restart.h [deleted file]
arch/sparc/include/asm/mutex.h [deleted file]
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/serial.h [deleted file]
arch/sparc/include/asm/smp_32.h
arch/sparc/include/asm/switch_to_64.h
arch/sparc/include/asm/tlbflush_64.h
arch/sparc/include/uapi/asm/Kbuild
arch/sparc/include/uapi/asm/types.h [deleted file]
arch/sparc/kernel/smp_64.c
arch/sparc/lib/bitext.c
arch/sparc/mm/iommu.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/tlb.c
arch/sparc/mm/tsb.c
arch/sparc/mm/ultra.S
arch/tile/include/asm/irqflags.h
arch/tile/kernel/setup.c
arch/x86/Kconfig
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/eboot.c
arch/x86/include/asm/efi.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/syscall.h
arch/x86/include/asm/tlb.h
arch/x86/include/uapi/asm/bootparam.h
arch/x86/kernel/cpu/mshyperv.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/microcode_core_early.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/setup.c
arch/x86/kvm/lapic.c
arch/x86/kvm/x86.c
arch/x86/lguest/boot.c
arch/x86/mm/fault.c
arch/x86/mm/pageattr-test.c
arch/x86/mm/pageattr.c
arch/x86/mm/pgtable.c
arch/x86/pci/common.c
arch/x86/pci/xen.c
arch/x86/platform/efi/efi.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/smp.c
arch/x86/xen/spinlock.c
arch/x86/xen/time.c
block/blk-core.c
block/blk-sysfs.c
block/partition-generic.c
crypto/algif_hash.c
crypto/algif_skcipher.c
crypto/gcm.c
drivers/acpi/Kconfig
drivers/acpi/acpi_i2c.c
drivers/acpi/pci_root.c
drivers/acpi/pci_slot.c
drivers/acpi/processor_idle.c
drivers/acpi/scan.c
drivers/ata/ahci.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/base/power/qos.c
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regmap.c
drivers/block/aoe/aoecmd.c
drivers/block/loop.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/rbd.c
drivers/char/hpet.c
drivers/char/hw_random/core.c
drivers/char/virtio_console.c
drivers/clk/tegra/clk-tegra20.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/intel_pstate.c
drivers/crypto/ux500/cryp/cryp_core.c
drivers/dma/Kconfig
drivers/dma/at_hdmac.c
drivers/dma/omap-dma.c
drivers/dma/pl330.c
drivers/eisa/eisa-bus.c
drivers/eisa/pci_eisa.c
drivers/firmware/Kconfig
drivers/firmware/efivars.c
drivers/gpio/gpio-ich.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpio-stmpe.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drm.h
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/tilcdc/Kconfig
drivers/gpu/drm/tilcdc/tilcdc_panel.c
drivers/gpu/drm/udl/udl_connector.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-magicmouse.c
drivers/hwspinlock/hwspinlock_core.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/idle/intel_idle.c
drivers/infiniband/hw/qib/qib_sd7220.c
drivers/input/tablet/wacom_wac.c
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_types.h
drivers/irqchip/irq-gic.c
drivers/md/dm-cache-target.c
drivers/md/dm.c
drivers/md/raid5.c
drivers/media/dvb-frontends/mb86a20s.c
drivers/media/pci/cx25821/cx25821-video.c
drivers/media/platform/Kconfig
drivers/media/radio/radio-ma901.c
drivers/misc/vmw_vmci/Kconfig
drivers/mtd/mtdchar.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/can/mcp251x.c
drivers/net/can/sja1000/Kconfig
drivers/net/can/sja1000/plx_pci.c
drivers/net/can/sja1000/sja1000.c
drivers/net/can/sja1000/sja1000.h
drivers/net/can/sja1000/sja1000_of_platform.c
drivers/net/ethernet/8390/ax88796.c
drivers/net/ethernet/atheros/atl1e/atl1e.h
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/calxeda/xgmac.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/davicom/dm9000.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec.c
drivers/net/ethernet/intel/e100.c
drivers/net/ethernet/intel/e1000/e1000_ethtool.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgb/ixgb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/marvell/Kconfig
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/marvell/sky2.h
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
drivers/net/ethernet/qlogic/qlge/qlge.h
drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/renesas/sh_eth.h
drivers/net/ethernet/stmicro/stmmac/mmc_core.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/tun.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/smsc75xx.c
drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/link.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/phy_n.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
drivers/net/wireless/iwlegacy/4965-rs.c
drivers/net/wireless/iwlwifi/dvm/lib.c
drivers/net/wireless/iwlwifi/dvm/rxon.c
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/dvm/ucode.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/pcie.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/rt2x00/Kconfig
drivers/net/wireless/rt2x00/Makefile
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2x00mmio.c [new file with mode: 0644]
drivers/net/wireless/rt2x00/rt2x00mmio.h [new file with mode: 0644]
drivers/net/wireless/rt2x00/rt2x00pci.c
drivers/net/wireless/rt2x00/rt2x00pci.h
drivers/net/wireless/rt2x00/rt61pci.c
drivers/nfc/microread/mei.c
drivers/pci/bus.c
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/cpci_hotplug.h
drivers/pci/hotplug/cpqphp.h
drivers/pci/hotplug/cpqphp_nvram.h
drivers/pci/hotplug/ibmphp.h
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_acpi.c
drivers/pci/hotplug/rpadlpar.h
drivers/pci/hotplug/rpaphp.h
drivers/pci/hotplug/s390_pci_hpc.c
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_sysfs.c
drivers/pci/msi.c
drivers/pci/msi.h [deleted file]
drivers/pci/pci-acpi.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/Kconfig
drivers/pci/pcie/aer/aer_inject.c
drivers/pci/pcie/aer/aerdrv.h
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/pme.c
drivers/pci/pcie/portdrv.h
drivers/pci/pcie/portdrv_acpi.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/rom.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/pci/slot.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/thinkpad_acpi.c
drivers/remoteproc/Kconfig
drivers/remoteproc/remoteproc_core.c
drivers/remoteproc/ste_modem_rproc.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-at91rm9200.h
drivers/s390/block/dasd.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/block/scm_blk.c
drivers/s390/block/scm_blk_cluster.c
drivers/s390/block/scm_drv.c
drivers/s390/char/con3215.c
drivers/s390/char/monreader.c
drivers/s390/char/raw3270.c
drivers/s390/char/sclp_cmd.c
drivers/s390/char/tty3270.c
drivers/s390/char/zcore.c
drivers/s390/cio/chp.c
drivers/s390/cio/chp.h
drivers/s390/cio/chsc.c
drivers/s390/cio/cio.c
drivers/s390/cio/cio.h
drivers/s390/cio/css.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/device_ops.c
drivers/s390/cio/idset.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/sbus/char/bbc_i2c.c
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fcoe/fcoe_ctlr.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ipr.c
drivers/scsi/libfc/fc_disc.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/mvsas/mv_init.c
drivers/scsi/mvumi.c
drivers/scsi/mvumi.h
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/st.c
drivers/spi/Kconfig
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-tegra20-slink.c
drivers/spi/spi.c
drivers/ssb/driver_chipcommon_pmu.c
drivers/target/target_core_alua.c
drivers/tty/mxser.c
drivers/tty/serial/8250/8250_pnp.c
drivers/tty/serial/omap-serial.c
drivers/tty/tty_io.c
drivers/usb/core/port.c
drivers/vfio/pci/vfio_pci.c
drivers/vhost/tcm_vhost.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/amifb.c
drivers/video/atmel_lcdfb.c
drivers/video/auo_k1900fb.c
drivers/video/auo_k1901fb.c
drivers/video/auo_k190x.c
drivers/video/controlfb.c
drivers/video/exynos/exynos_mipi_dsi.c
drivers/video/exynos/exynos_mipi_dsi_common.c
drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
drivers/video/fb-puv3.c
drivers/video/fbmem.c
drivers/video/fbmon.c
drivers/video/fsl-diu-fb.c
drivers/video/gbefb.c
drivers/video/mmp/core.c
drivers/video/of_display_timing.c
drivers/video/of_videomode.c
drivers/video/omap/Kconfig
drivers/video/omap2/omapfb/omapfb-main.c
drivers/video/omap2/vrfb.c
drivers/video/ps3fb.c
drivers/video/s3c-fb.c
drivers/video/sa1100fb.c
drivers/video/sgivwfb.c
drivers/video/sh_mipi_dsi.c
drivers/video/sh_mobile_hdmi.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/smscufx.c
drivers/video/udlfb.c
drivers/video/uvesafb.c
drivers/video/vermilion/vermilion.c
drivers/video/vfb.c
drivers/video/videomode.c
drivers/video/vt8500lcdfb.c
drivers/video/wm8505fb.c
drivers/video/wmt_ge_rops.h
drivers/watchdog/Kconfig
drivers/xen/events.c
drivers/xen/xen-acpi-processor.c
firmware/Makefile
firmware/intel/sd7220.fw.ihex [deleted file]
firmware/qlogic/sd7220.fw.ihex [new file with mode: 0644]
fs/aio.c
fs/binfmt_elf.c
fs/bio.c
fs/block_dev.c
fs/btrfs/tree-log.c
fs/cifs/connect.c
fs/ecryptfs/miscdev.c
fs/ext4/extents.c
fs/ext4/indirect.c
fs/gfs2/file.c
fs/gfs2/incore.h
fs/gfs2/lock_dlm.c
fs/gfs2/rgrp.c
fs/hfsplus/extents.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/namespace.c
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/proc/array.c
fs/proc/generic.c
fs/reiserfs/xattr.c
fs/ubifs/super.c
include/asm-generic/tlb.h
include/linux/acpi.h
include/linux/ata.h
include/linux/blktrace_api.h
include/linux/capability.h
include/linux/compat.h
include/linux/devfreq.h
include/linux/efi.h
include/linux/ftrace.h
include/linux/kexec.h
include/linux/kvm_host.h
include/linux/kvm_types.h
include/linux/libata.h
include/linux/mm.h
include/linux/msi.h
include/linux/mutex.h
include/linux/netdevice.h
include/linux/netfilter/ipset/ip_set_ahash.h
include/linux/pci-acpi.h
include/linux/pci-aspm.h
include/linux/pci-ats.h
include/linux/pci.h
include/linux/pci_hotplug.h
include/linux/pci_ids.h
include/linux/pcieport_if.h
include/linux/platform_data/video-vt8500lcdfb.h [deleted file]
include/linux/platform_data/video_s3c.h [new file with mode: 0644]
include/linux/preempt.h
include/linux/proc_fs.h
include/linux/sched.h
include/linux/security.h
include/linux/signal.h
include/linux/skbuff.h
include/linux/spinlock_up.h
include/linux/ssb/ssb_driver_chipcommon.h
include/linux/swiotlb.h
include/linux/ucs2_string.h [new file with mode: 0644]
include/net/addrconf.h
include/net/irda/irlmp.h
include/net/iucv/af_iucv.h
include/net/scm.h
include/scsi/libfc.h
include/sound/max98090.h [changed mode: 0755->0644]
include/sound/soc-dapm.h
include/trace/events/block.h
include/trace/events/sched.h
include/uapi/linux/fuse.h
include/uapi/linux/pci_regs.h
include/video/auo_k190xfb.h
include/video/display_timing.h
include/video/videomode.h
include/xen/events.h
ipc/msg.c
kernel/.gitignore
kernel/capability.c
kernel/events/core.c
kernel/events/internal.h
kernel/events/ring_buffer.c
kernel/hrtimer.c
kernel/kexec.c
kernel/kprobes.c
kernel/kthread.c
kernel/lockdep.c
kernel/mutex.c
kernel/rtmutex-tester.c
kernel/sched/clock.c
kernel/sched/core.c
kernel/sched/cputime.c
kernel/sched/features.h
kernel/signal.c
kernel/smpboot.c
kernel/sys.c
kernel/trace/blktrace.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace_stack.c
kernel/user_namespace.c
lib/Kconfig
lib/Makefile
lib/kobject.c
lib/swiotlb.c
lib/ucs2_string.c [new file with mode: 0644]
mm/hugetlb.c
mm/memory.c
mm/mmap.c
mm/nommu.c
mm/vmscan.c
net/802/mrp.c
net/atm/common.c
net/ax25/af_ax25.c
net/batman-adv/main.c
net/batman-adv/main.h
net/batman-adv/routing.c
net/batman-adv/translation-table.c
net/batman-adv/vis.c
net/bluetooth/af_bluetooth.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c
net/bridge/br_if.c
net/bridge/br_private.h
net/bridge/br_stp_if.c
net/caif/caif_socket.c
net/can/gw.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/flow.c
net/core/rtnetlink.c
net/ipv4/devinet.c
net/ipv4/esp4.c
net/ipv4/ip_fragment.c
net/ipv4/netfilter/ipt_rpfilter.c
net/ipv4/syncookies.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/addrconf_core.c
net/ipv6/ip6_input.c
net/ipv6/netfilter/ip6t_NPT.c
net/ipv6/netfilter/ip6t_rpfilter.c
net/ipv6/reassembly.c
net/ipv6/tcp_ipv6.c
net/irda/af_irda.c
net/irda/iriap.c
net/irda/irlmp.c
net/iucv/af_iucv.c
net/key/af_key.c
net/l2tp/l2tp_ip6.c
net/llc/af_llc.c
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/mesh.c
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_hash_ipportnet.c
net/netfilter/ipset/ip_set_hash_net.c
net/netfilter/ipset/ip_set_hash_netiface.c
net/netfilter/ipset/ip_set_hash_netport.c
net/netfilter/ipset/ip_set_list_set.c
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_nat_core.c
net/netfilter/nfnetlink_acct.c
net/netfilter/nfnetlink_queue_core.c
net/netrom/af_netrom.c
net/nfc/llcp/llcp.c
net/nfc/llcp/sock.c
net/openvswitch/datapath.c
net/openvswitch/flow.c
net/rose/af_rose.c
net/sched/cls_fw.c
net/sched/sch_cbq.c
net/sched/sch_fq_codel.c
net/sched/sch_generic.c
net/sunrpc/clnt.c
net/tipc/socket.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/vmci_transport.c
net/vmw_vsock/vsock_addr.c
net/vmw_vsock/vsock_addr.h
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/scan.c
net/wireless/sme.c
net/wireless/trace.h
net/wireless/wext-sme.c
net/xfrm/xfrm_replay.c
scripts/checkpatch.pl
security/capability.c
security/security.c
security/selinux/hooks.c
sound/core/pcm_native.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/max98090.c [changed mode: 0755->0644]
sound/soc/codecs/max98090.h [changed mode: 0755->0644]
sound/soc/codecs/si476x.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/imx-ssi.c
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/samsung/i2s.c
sound/soc/sh/dma-sh7760.c
sound/soc/soc-compress.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/spear/spear_pcm.c
sound/soc/tegra/tegra_pcm.c
sound/usb/clock.c
sound/usb/mixer_quirks.c
sound/usb/quirks.c
tools/power/x86/turbostat/turbostat.c
virt/kvm/kvm_main.c

index 7514dbf0a6796c4e216a175fa79db0ed3ff470d9..c36892c072dad4aaff9b2e34f3653ac88c915190 100644 (file)
@@ -227,7 +227,7 @@ X!Isound/sound_firmware.c
   <chapter id="uart16x50">
      <title>16x50 UART Driver</title>
 !Edrivers/tty/serial/serial_core.c
-!Edrivers/tty/serial/8250/8250.c
+!Edrivers/tty/serial/8250/8250_core.c
   </chapter>
 
   <chapter id="fbdev">
index c870b6478ec81861ada145526dc8c0644b1806aa..2871e218a0fb7662299997b848c859b00d150435 100644 (file)
@@ -5,58 +5,32 @@ Required properties:
 - compatible : "via,vt8500-fb"
 - reg : Should contain 1 register ranges(address and length)
 - interrupts : framebuffer controller interrupt
-- display: a phandle pointing to the display node
+- bits-per-pixel : bit depth of framebuffer (16 or 32)
 
-Required nodes:
-- display: a display node is required to initialize the lcd panel
-       This should be in the board dts.
-- default-mode: a videomode within the display with timing parameters
-       as specified below.
+Required subnodes:
+- display-timings: see display-timing.txt for information
 
 Example:
 
-       fb@d800e400 {
+       fb@d8050800 {
                compatible = "via,vt8500-fb";
                reg = <0xd800e400 0x400>;
                interrupts = <12>;
-               display = <&display>;
-               default-mode = <&mode0>;
-       };
-
-VIA VT8500 Display
------------------------------------------------------
-Required properties (as per of_videomode_helper):
-
- - hactive, vactive: Display resolution
- - hfront-porch, hback-porch, hsync-len: Horizontal Display timing parameters
-   in pixels
-   vfront-porch, vback-porch, vsync-len: Vertical display timing parameters in
-   lines
- - clock: displayclock in Hz
- - bpp: lcd panel bit-depth.
-       <16> for RGB565, <32> for RGB888
-
-Optional properties (as per of_videomode_helper):
- - width-mm, height-mm: Display dimensions in mm
- - hsync-active-high (bool): Hsync pulse is active high
- - vsync-active-high (bool): Vsync pulse is active high
- - interlaced (bool): This is an interlaced mode
- - doublescan (bool): This is a doublescan mode
+               bits-per-pixel = <16>;
 
-Example:
-       display: display@0 {
-               modes {
-                       mode0: mode@0 {
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: 800x480 {
+                               clock-frequency = <0>; /* unused but required */
                                hactive = <800>;
                                vactive = <480>;
-                               hback-porch = <88>;
                                hfront-porch = <40>;
+                               hback-porch = <88>;
                                hsync-len = <0>;
                                vback-porch = <32>;
                                vfront-porch = <11>;
                                vsync-len = <1>;
-                               clock = <0>;    /* unused but required */
-                               bpp = <16>;     /* non-standard but required */
                        };
                };
        };
+
index 3d325e1d11ee64fd80ebfc61a3ae45fbf390b1cc..0bcadb2840a5c9d17d3f81dd2ef3056ed4b25381 100644 (file)
@@ -4,20 +4,30 @@ Wondermedia WM8505 Framebuffer
 Required properties:
 - compatible : "wm,wm8505-fb"
 - reg : Should contain 1 register ranges(address and length)
-- via,display: a phandle pointing to the display node
+- bits-per-pixel : bit depth of framebuffer (16 or 32)
 
-Required nodes:
-- display: a display node is required to initialize the lcd panel
-       This should be in the board dts. See definition in
-       Documentation/devicetree/bindings/video/via,vt8500-fb.txt
-- default-mode: a videomode node as specified in
-       Documentation/devicetree/bindings/video/via,vt8500-fb.txt
+Required subnodes:
+- display-timings: see display-timing.txt for information
 
 Example:
 
-       fb@d8050800 {
+       fb@d8051700 {
                compatible = "wm,wm8505-fb";
-               reg = <0xd8050800 0x200>;
-               display = <&display>;
-               default-mode = <&mode0>;
+               reg = <0xd8051700 0x200>;
+               bits-per-pixel = <16>;
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: 800x480 {
+                               clock-frequency = <0>; /* unused but required */
+                               hactive = <800>;
+                               vactive = <480>;
+                               hfront-porch = <40>;
+                               hback-porch = <88>;
+                               hsync-len = <0>;
+                               vback-porch = <32>;
+                               vfront-porch = <11>;
+                               vsync-len = <1>;
+                       };
+               };
        };
index 223e4f0582d018254e692b8e83d809fe77dbc400..9f651c181429052b06d1e331f112141f947c6f71 100644 (file)
@@ -882,7 +882,7 @@ int err_inj()
                        cpu=parameters[i].cpu;
                        k = cpu%64;
                        j = cpu/64;
-                       mask[j]=1<<k;
+                       mask[j] = 1UL << k;
 
                        if (sched_setaffinity(0, MASK_SIZE*8, mask)==-1) {
                                perror("Error sched_setaffinity:");
index 13f1aa09b938c09c91421ad55dc168ef67cd8347..9c7fd988e299f0a9a5bcdec3d3db98efc837b2c0 100644 (file)
@@ -297,6 +297,7 @@ Boot into System Kernel
    On ia64, 256M@256M is a generous value that typically works.
    The region may be automatically placed on ia64, see the
    dump-capture kernel config option notes above.
+   If use sparse memory, the size should be rounded to GRANULE boundaries.
 
    On s390x, typically use "crashkernel=xxM". The value of xx is dependent
    on the memory consumption of the kdump system. In general this is not
index 4609e81dbc37fc2dbfa005ff607890df3a8bbc6b..8ccbf27aead4def123c94eaf0de40e39db40199f 100644 (file)
@@ -596,9 +596,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        is selected automatically. Check
                        Documentation/kdump/kdump.txt for further details.
 
-       crashkernel_low=size[KMG]
-                       [KNL, x86] parts under 4G.
-
        crashkernel=range1:size1[,range2:size2,...][@offset]
                        [KNL] Same as above, but depends on the memory
                        in the running system. The syntax of range is
@@ -606,6 +603,26 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        a memory unit (amount[KMG]). See also
                        Documentation/kdump/kdump.txt for an example.
 
+       crashkernel=size[KMG],high
+                       [KNL, x86_64] range could be above 4G. Allow kernel
+                       to allocate physical memory region from top, so could
+                       be above 4G if system have more than 4G ram installed.
+                       Otherwise memory region will be allocated below 4G, if
+                       available.
+                       It will be ignored if crashkernel=X is specified.
+       crashkernel=size[KMG],low
+                       [KNL, x86_64] range under 4G. When crashkernel=X,high
+                       is passed, kernel could allocate physical memory region
+                       above 4G, that cause second kernel crash on system
+                       that require some amount of low memory, e.g. swiotlb
+                       requires at least 64M+32K low memory.  Kernel would
+                       try to allocate 72M below 4G automatically.
+                       This one let user to specify own low range under 4G
+                       for second kernel instead.
+                       0: to disable low allocation.
+                       It will be ignored when crashkernel=X,high is not used
+                       or memory reserved is below 4G.
+
        cs89x0_dma=     [HW,NET]
                        Format: <dma>
 
@@ -788,6 +805,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        edd=            [EDD]
                        Format: {"off" | "on" | "skip[mbr]"}
 
+       efi_no_storage_paranoia [EFI; X86]
+                       Using this parameter you can use more than 50% of
+                       your efi variable storage. Use this parameter only if
+                       you are really sure that your UEFI does sane gc and
+                       fulfills the spec otherwise your board may brick.
+
        eisa_irq_edge=  [PARISC,HW]
                        See header of drivers/parisc/eisa.c.
 
index ae66f9b90a25d687565a7ea897b4e9aad978887a..fcaf0b4efba21cfe51ed1aa4a6d9303aa614dea5 100644 (file)
@@ -143,7 +143,8 @@ Parameter:     id:   handle for debug log
 
 Return Value:  none 
 
-Description:   frees memory for a debug log     
+Description:   frees memory for a debug log and removes all registered debug
+              views.
                Must not be called within an interrupt handler 
 
 ---------------------------------------------------------------------------
index 27a91cf43d6d66ce4137e9335988175b096423a4..5020b7b5a24410f5cac04c2a8cbc849b3546a8e8 100644 (file)
@@ -1,4 +1,4 @@
-Copyright (c) 2003-2012 QLogic Corporation
+Copyright (c) 2003-2013 QLogic Corporation
 QLogic Linux FC-FCoE Driver
 
 This program includes a device driver for Linux 3.x.
index 4499bd948860cebe52e7db8aae65b2a16fd1a897..95731a08f25787ff77a03a4f542dec5791f120e6 100644 (file)
@@ -890,9 +890,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     enable_msi - Enable Message Signaled Interrupt (MSI) (default = off)
     power_save - Automatic power-saving timeout (in second, 0 =
                disable)
-    power_save_controller - Support runtime D3 of HD-audio controller
-               (-1 = on for supported chip (default), false = off,
-                true = force to on even for unsupported hardware)
+    power_save_controller - Reset HD-audio controller in power-saving mode
+               (default = on)
     align_buffer_size - Force rounding of buffer/period sizes to multiples
                      of 128 bytes. This is more efficient in terms of memory
                      access but isn't required by the HDA spec and prevents
index 74e58a4d035b953fe2aa28f86b1cab87249a3223..8bdd7a7ef2f4687aa26ee66a70fe8ad428e14890 100644 (file)
@@ -4941,6 +4941,12 @@ W:       logfs.org
 S:     Maintained
 F:     fs/logfs/
 
+LPC32XX MACHINE SUPPORT
+M:     Roland Stigge <stigge@antcom.de>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-lpc32xx/
+
 LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
 M:     Nagalakshmi Nandigama <Nagalakshmi.Nandigama@lsi.com>
 M:     Sreekanth Reddy <Sreekanth.Reddy@lsi.com>
@@ -5065,9 +5071,8 @@ S:        Maintained
 F:     drivers/net/ethernet/marvell/sk*
 
 MARVELL LIBERTAS WIRELESS DRIVER
-M:     Dan Williams <dcbw@redhat.com>
 L:     libertas-dev@lists.infradead.org
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wireless/libertas/
 
 MARVELL MV643XX ETHERNET DRIVER
@@ -5569,6 +5574,7 @@ F:        include/uapi/linux/if_*
 F:     include/uapi/linux/netdevice.h
 
 NETXEN (1/10) GbE SUPPORT
+M:     Manish Chopra <manish.chopra@qlogic.com>
 M:     Sony Chacko <sony.chacko@qlogic.com>
 M:     Rajesh Borundia <rajesh.borundia@qlogic.com>
 L:     netdev@vger.kernel.org
@@ -6625,7 +6631,7 @@ S:        Supported
 F:     fs/reiserfs/
 
 REGISTER MAP ABSTRACTION
-M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
+M:     Mark Brown <broonie@kernel.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git
 S:     Supported
 F:     drivers/base/regmap/
@@ -6951,7 +6957,6 @@ F:        drivers/scsi/st*
 
 SCTP PROTOCOL
 M:     Vlad Yasevich <vyasevich@gmail.com>
-M:     Sridhar Samudrala <sri@us.ibm.com>
 M:     Neil Horman <nhorman@tuxdriver.com>
 L:     linux-sctp@vger.kernel.org
 W:     http://lksctp.sourceforge.net
@@ -7374,7 +7379,7 @@ F:        sound/
 
 SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
 M:     Liam Girdwood <lgirdwood@gmail.com>
-M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
+M:     Mark Brown <broonie@kernel.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 W:     http://alsa-project.org/main/index.php/ASoC
@@ -7463,7 +7468,7 @@ F:        drivers/clk/spear/
 
 SPI SUBSYSTEM
 M:     Grant Likely <grant.likely@secretlab.ca>
-M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
+M:     Mark Brown <broonie@kernel.org>
 L:     spi-devel-general@lists.sourceforge.net
 Q:     http://patchwork.kernel.org/project/spi-devel-general/list/
 T:     git git://git.secretlab.ca/git/linux-2.6.git
@@ -8708,7 +8713,7 @@ F:        drivers/scsi/vmw_pvscsi.h
 
 VOLTAGE AND CURRENT REGULATOR FRAMEWORK
 M:     Liam Girdwood <lrg@ti.com>
-M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
+M:     Mark Brown <broonie@kernel.org>
 W:     http://opensource.wolfsonmicro.com/node/15
 W:     http://www.slimlogic.co.uk/?p=48
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lrg/regulator.git
index 58a165b02af1e27acb6d2635f3c9ab0d58c5cb00..8fe69916e726f7a3ec90a897425e46bc94394a4e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 9
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION =
 NAME = Unicycling Gorilla
 
 # *DOCUMENTATION*
@@ -513,7 +513,8 @@ ifeq ($(KBUILD_EXTMOD),)
 # Carefully list dependencies so we do not try to build scripts twice
 # in parallel
 PHONY += scripts
-scripts: scripts_basic include/config/auto.conf include/config/tristate.conf
+scripts: scripts_basic include/config/auto.conf include/config/tristate.conf \
+        asm-generic
        $(Q)$(MAKE) $(build)=$(@)
 
 # Objects we will link into vmlinux / subdirs we need to visit
index 4759fe751aa1ba1b21ea99b99ae2c9487627e326..2cc3cc519c549a357052a2279b7f587ed8558c9d 100644 (file)
@@ -12,7 +12,7 @@ NM := $(NM) -B
 
 LDFLAGS_vmlinux        := -static -N #-relax
 CHECKFLAGS     += -D__alpha__ -m64
-cflags-y       := -pipe -mno-fp-regs -ffixed-8 -msmall-data
+cflags-y       := -pipe -mno-fp-regs -ffixed-8
 cflags-y       += $(call cc-option, -fno-jump-tables)
 
 cpuflags-$(CONFIG_ALPHA_EV4)           := -mcpu=ev4
index 46cefbd50e73453abc7d26c08e501c09ce8da5e9..bae97eb19d269dd8cf7b8008ddb9833aab68abfd 100644 (file)
@@ -26,7 +26,7 @@
 #define fd_disable_irq()        disable_irq(FLOPPY_IRQ)
 #define fd_cacheflush(addr,size) /* nothing */
 #define fd_request_irq()        request_irq(FLOPPY_IRQ, floppy_interrupt,\
-                                           IRQF_DISABLED, "floppy", NULL)
+                                           0, "floppy", NULL)
 #define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL)
 
 #ifdef CONFIG_PCI
index 2872accd22156b7ee134f70c84376a7dff48a4c8..7b2be251c30fb92981d4aef8cf4f8951bed24728 100644 (file)
@@ -117,13 +117,6 @@ handle_irq(int irq)
                return;
        }
 
-       /*
-        * From here we must proceed with IPL_MAX. Note that we do not
-        * explicitly enable interrupts afterwards - some MILO PALcode
-        * (namely LX164 one) seems to have severe problems with RTI
-        * at IPL 0.
-        */
-       local_irq_disable();
        irq_enter();
        generic_handle_irq_desc(irq, desc);
        irq_exit();
index 772ddfdb71a8e67af8f20e38ff7f8def9af3b943..f433fc11877a30ae096dd54d263b37b094132fac 100644 (file)
@@ -45,6 +45,14 @@ do_entInt(unsigned long type, unsigned long vector,
          unsigned long la_ptr, struct pt_regs *regs)
 {
        struct pt_regs *old_regs;
+
+       /*
+        * Disable interrupts during IRQ handling.
+        * Note that there is no matching local_irq_enable() due to
+        * severe problems with RTI at IPL0 and some MILO PALcode
+        * (namely LX164).
+        */
+       local_irq_disable();
        switch (type) {
        case 0:
 #ifdef CONFIG_SMP
@@ -62,7 +70,6 @@ do_entInt(unsigned long type, unsigned long vector,
          {
                long cpu;
 
-               local_irq_disable();
                smp_percpu_timer_interrupt(regs);
                cpu = smp_processor_id();
                if (cpu != boot_cpuid) {
@@ -222,7 +229,6 @@ process_mcheck_info(unsigned long vector, unsigned long la_ptr,
 
 struct irqaction timer_irqaction = {
        .handler        = timer_interrupt,
-       .flags          = IRQF_DISABLED,
        .name           = "timer",
 };
 
index 4d4c046f708d6f4691388b64fdd3bd014bb3b3c5..1383f8601a93b7595b290f7ad595f061917c180b 100644 (file)
@@ -188,6 +188,10 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr)
 extern void free_reserved_mem(void *, void *);
 extern void pcibios_claim_one_bus(struct pci_bus *);
 
+static struct resource irongate_io = {
+       .name   = "Irongate PCI IO",
+       .flags  = IORESOURCE_IO,
+};
 static struct resource irongate_mem = {
        .name   = "Irongate PCI MEM",
        .flags  = IORESOURCE_MEM,
@@ -209,6 +213,7 @@ nautilus_init_pci(void)
 
        irongate = pci_get_bus_and_slot(0, 0);
        bus->self = irongate;
+       bus->resource[0] = &irongate_io;
        bus->resource[1] = &irongate_mem;
 
        pci_bus_size_bridges(bus);
index 5cf4a481b8c57ea01e0709764f2e4c11ad26b863..a53cf03f49d503cee6e17f043e851d07b847c882 100644 (file)
@@ -280,15 +280,15 @@ titan_late_init(void)
         * all reported to the kernel as machine checks, so the handler
         * is a nop so it can be called to count the individual events.
         */
-       titan_request_irq(63+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(63+16, titan_intr_nop, 0,
                    "CChip Error", NULL);
-       titan_request_irq(62+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(62+16, titan_intr_nop, 0,
                    "PChip 0 H_Error", NULL);
-       titan_request_irq(61+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(61+16, titan_intr_nop, 0,
                    "PChip 1 H_Error", NULL);
-       titan_request_irq(60+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(60+16, titan_intr_nop, 0,
                    "PChip 0 C_Error", NULL);
-       titan_request_irq(59+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(59+16, titan_intr_nop, 0,
                    "PChip 1 C_Error", NULL);
 
        /* 
@@ -348,9 +348,9 @@ privateer_init_pci(void)
         * Hook a couple of extra err interrupts that the
         * common titan code won't.
         */
-       titan_request_irq(53+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(53+16, titan_intr_nop, 0,
                    "NMI", NULL);
-       titan_request_irq(50+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(50+16, titan_intr_nop, 0,
                    "Temperature Warning", NULL);
 
        /*
index ccd84806b62fe9635472e6bbc00e0dc5643683ff..eac071668201a143bf0e93367cd277441b520fb8 100644 (file)
@@ -39,7 +39,7 @@ static inline long arch_local_irq_save(void)
        "       flag.nz %0              \n"
        : "=r"(temp), "=r"(flags)
        : "n"((STATUS_E1_MASK | STATUS_E2_MASK))
-       : "cc");
+       : "memory", "cc");
 
        return flags;
 }
@@ -53,7 +53,8 @@ static inline void arch_local_irq_restore(unsigned long flags)
        __asm__ __volatile__(
        "       flag %0                 \n"
        :
-       : "r"(flags));
+       : "r"(flags)
+       : "memory");
 }
 
 /*
@@ -73,7 +74,8 @@ static inline void arch_local_irq_disable(void)
        "       and %0, %0, %1          \n"
        "       flag %0                 \n"
        : "=&r"(temp)
-       : "n"(~(STATUS_E1_MASK | STATUS_E2_MASK)));
+       : "n"(~(STATUS_E1_MASK | STATUS_E2_MASK))
+       : "memory");
 }
 
 /*
@@ -85,7 +87,9 @@ static inline long arch_local_save_flags(void)
 
        __asm__ __volatile__(
        "       lr  %0, [status32]      \n"
-       : "=&r"(temp));
+       : "=&r"(temp)
+       :
+       : "memory");
 
        return temp;
 }
index 13b739469c515cb93a8dff1cdf686583a3941c54..1cacda426a0ea6699528dd0eeedf83032825e09e 100644 (file)
@@ -1183,9 +1183,9 @@ config ARM_NR_BANKS
        default 8
 
 config IWMMXT
-       bool "Enable iWMMXt support"
+       bool "Enable iWMMXt support" if !CPU_PJ4
        depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
-       default y if PXA27x || PXA3xx || ARCH_MMP
+       default y if PXA27x || PXA3xx || ARCH_MMP || CPU_PJ4
        help
          Enable support for iWMMXt context switching at run time if
          running on a CPU that supports it.
@@ -1439,6 +1439,16 @@ config ARM_ERRATA_775420
         to deadlock. This workaround puts DSB before executing ISB if
         an abort may occur on cache maintenance.
 
+config ARM_ERRATA_798181
+       bool "ARM errata: TLBI/DSB failure on Cortex-A15"
+       depends on CPU_V7 && SMP
+       help
+         On Cortex-A15 (r0p0..r3p2) the TLBI*IS/DSB operations are not
+         adequately shooting down all use of the old entries. This
+         option enables the Linux kernel workaround for this erratum
+         which sends an IPI to the CPUs that are running the same ASID
+         as the one being invalidated.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
index dd0c57dd9f3096ae40b35e2b4e43fc3c983f3ea1..3234875824dcc35258bef8909d6bd0a283710765 100644 (file)
@@ -54,7 +54,7 @@
                };
 
                mvsdio@d00d4000 {
-                       pinctrl-0 = <&sdio_pins2>;
+                       pinctrl-0 = <&sdio_pins3>;
                        pinctrl-names = "default";
                        status = "okay";
                        /*
index 8188d138020edc57c88db0cb749b91bdf016a5cf..a195debb67d35297292b43c1a9e7fc45c4908a2c 100644 (file)
                                             "mpp50", "mpp51", "mpp52";
                              marvell,function = "sd0";
                        };
+
+                       sdio_pins3: sdio-pins3 {
+                             marvell,pins = "mpp48", "mpp49", "mpp50",
+                                            "mpp51", "mpp52", "mpp53";
+                             marvell,function = "sd0";
+                       };
                };
 
                gpio0: gpio@d0018100 {
index 9de93096601a2d1d526c37faf332a5510a4fc5d1..aaa63d0a80968b20abd4660492fb2af1ed463072 100644 (file)
 
                prcmu: prcmu@80157000 {
                        compatible = "stericsson,db8500-prcmu";
-                       reg = <0x80157000 0x1000>;
-                       reg-names = "prcmu";
+                       reg = <0x80157000 0x1000>, <0x801b0000 0x8000>, <0x801b8000 0x1000>;
+                       reg-names = "prcmu", "prcmu-tcpm", "prcmu-tcdm";
                        interrupts = <0 47 0x4>;
                        #address-cells = <1>;
                        #size-cells = <1>;
index 6ce3d17c3a29c19c80ef6a04484fd59ec5e8765a..fd36e1cca1042306476c54d4038603780af358a1 100644 (file)
                        i2c0: i2c@80058000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&i2c0_pins_a>;
-                               clock-frequency = <400000>;
                                status = "okay";
 
                                sgtl5000: codec@0a {
index e6cde8aa7ffff5c3a2b670e2584c7475a8419525..6c6a5442800ad78adfe13ada4cf44a2cfd3cfbc5 100644 (file)
@@ -70,7 +70,6 @@
                        i2c0: i2c@80058000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&i2c0_pins_a>;
-                               clock-frequency = <400000>;
                                status = "okay";
 
                                rtc: rtc@51 {
index 06ec460b4581c4163e4053953e84acfaad01a76b..281a223591ff83d5a9eef96c6775c77c99a356ad 100644 (file)
@@ -91,6 +91,7 @@
                        compatible = "arm,cortex-a9-twd-timer";
                        reg = <0x00a00600 0x20>;
                        interrupts = <1 13 0xf01>;
+                       clocks = <&clks 15>;
                };
 
                L2: l2-cache@00a02000 {
index bd83b8fc7c83f01304397ac17e75be5a6438128e..c3573be7b92c18d1bb0b577f200c8d0bcc170351 100644 (file)
@@ -77,6 +77,7 @@
                };
 
                nand@3000000 {
+                       chip-delay = <40>;
                        status = "okay";
 
                        partition@0 {
index 93c3afbef9eeecc4b0b3741c2bc2360717da81b9..3694e94f6e99dc93aaf91985f55c6245830a92af 100644 (file)
                                marvell,function = "gpio";
                        };
                        pmx_led_rebuild_brt_ctrl_1: pmx-led-rebuild-brt-ctrl-1 {
-                               marvell,pins = "mpp44";
+                               marvell,pins = "mpp46";
                                marvell,function = "gpio";
                        };
                        pmx_led_rebuild_brt_ctrl_2: pmx-led-rebuild-brt-ctrl-2 {
-                               marvell,pins = "mpp45";
+                               marvell,pins = "mpp47";
                                marvell,function = "gpio";
                        };
 
                        gpios = <&gpio0 16 0>;
                        linux,default-trigger = "default-on";
                };
-               health_led1 {
+               rebuild_led {
+                       label = "status:white:rebuild_led";
+                       gpios = <&gpio1 4 0>;
+               };
+               health_led {
                        label = "status:red:health_led";
                        gpios = <&gpio1 5 0>;
                };
-               health_led2 {
-                       label = "status:white:health_led";
-                       gpios = <&gpio1 4 0>;
-               };
                backup_led {
                        label = "status:blue:backup_led";
                        gpios = <&gpio0 15 0>;
index 8aad00f81ed9393118e64b38bfe96dc9aab56d28..f7bec3b1ba323538c7ef26d3f9b2aa5cd68b00cc 100644 (file)
@@ -13,6 +13,9 @@
        compatible = "marvell,orion5x";
        interrupt-parent = <&intc>;
 
+       aliases {
+               gpio0 = &gpio0;
+       };
        intc: interrupt-controller {
                compatible = "marvell,orion-intc", "marvell,intc";
                interrupt-controller;
@@ -32,7 +35,9 @@
                        #gpio-cells = <2>;
                        gpio-controller;
                        reg = <0x10100 0x40>;
-                       ngpio = <32>;
+                       ngpios = <32>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
                        interrupts = <6>, <7>, <8>, <9>;
                };
 
@@ -91,7 +96,7 @@
                        reg = <0x90000 0x10000>,
                              <0xf2200000 0x800>;
                        reg-names = "regs", "sram";
-                       interrupts = <22>;
+                       interrupts = <28>;
                        status = "okay";
                };
        };
index 567cf4e8ab84e49551667e8f68f986675b15a1a7..877b33afa7ed9182ca2b4f20597f66e26729dd3f 100644 (file)
 
 / {
        model = "Benign BV07 Netbook";
+};
 
-       /*
-        * Display node is based on Sascha Hauer's patch on dri-devel.
-        * Added a bpp property to calculate the size of the framebuffer
-        * until the binding is formalized.
-        */
-       display: display@0 {
-               modes {
-                       mode0: mode@0 {
-                               hactive = <800>;
-                               vactive = <480>;
-                               hback-porch = <88>;
-                               hfront-porch = <40>;
-                               hsync-len = <0>;
-                               vback-porch = <32>;
-                               vfront-porch = <11>;
-                               vsync-len = <1>;
-                               clock = <0>;    /* unused but required */
-                               bpp = <16>;     /* non-standard but required */
-                       };
+&fb {
+       bits-per-pixel = <16>;
+       display-timings {
+               native-mode = <&timing0>;
+               timing0: 800x480 {
+                       clock-frequency = <0>; /* unused but required */
+                       hactive = <800>;
+                       vactive = <480>;
+                       hfront-porch = <40>;
+                       hback-porch = <88>;
+                       hsync-len = <0>;
+                       vback-porch = <32>;
+                       vfront-porch = <11>;
+                       vsync-len = <1>;
                };
        };
 };
index cf31ced46602e1ef8c24bf8a1fed2634488e8845..68c8dc644383a248a502bb5da7a359010a6b4342 100644 (file)
                        interrupts = <43>;
                };
 
-               fb@d800e400 {
+               fb: fb@d8050800 {
                        compatible = "via,vt8500-fb";
                        reg = <0xd800e400 0x400>;
                        interrupts = <12>;
-                       display = <&display>;
-                       default-mode = <&mode0>;
                };
 
                ge_rops@d8050400 {
index fd4e248074c676a43d965338f210f1e3ea6fa673..edd2cec3d37f6b801335af4361560a2cecc1bb6b 100644 (file)
 
 / {
        model = "Wondermedia WM8505 Netbook";
+};
 
-       /*
-        * Display node is based on Sascha Hauer's patch on dri-devel.
-        * Added a bpp property to calculate the size of the framebuffer
-        * until the binding is formalized.
-        */
-       display: display@0 {
-               modes {
-                       mode0: mode@0 {
-                               hactive = <800>;
-                               vactive = <480>;
-                               hback-porch = <88>;
-                               hfront-porch = <40>;
-                               hsync-len = <0>;
-                               vback-porch = <32>;
-                               vfront-porch = <11>;
-                               vsync-len = <1>;
-                               clock = <0>;    /* unused but required */
-                               bpp = <32>;     /* non-standard but required */
-                       };
+&fb {
+       bits-per-pixel = <32>;
+       display-timings {
+               native-mode = <&timing0>;
+               timing0: 800x480 {
+                       clock-frequency = <0>; /* unused but required */
+                       hactive = <800>;
+                       vactive = <480>;
+                       hfront-porch = <40>;
+                       hback-porch = <88>;
+                       hsync-len = <0>;
+                       vback-porch = <32>;
+                       vfront-porch = <11>;
+                       vsync-len = <1>;
                };
        };
 };
index e74a1c0fb9a2998ef91dbf58019850644711465f..bcf668d31b28471602dc86c2b1555c9bcbb73be6 100644 (file)
                        interrupts = <0>;
                };
 
-               fb@d8050800 {
+               fb: fb@d8050800 {
                        compatible = "wm,wm8505-fb";
                        reg = <0xd8050800 0x200>;
-                       display = <&display>;
-                       default-mode = <&mode0>;
                };
 
                ge_rops@d8050400 {
index cefd938f842fe6192e90a2c244b05730c11383a5..61671a0d9edec507422bbf27fbf51bf5c908f2f6 100644 (file)
 
 / {
        model = "Wondermedia WM8650-MID Tablet";
+};
+
+&fb {
+       bits-per-pixel = <16>;
 
-       /*
-        * Display node is based on Sascha Hauer's patch on dri-devel.
-        * Added a bpp property to calculate the size of the framebuffer
-        * until the binding is formalized.
-        */
-       display: display@0 {
-               modes {
-                       mode0: mode@0 {
-                               hactive = <800>;
-                               vactive = <480>;
-                               hback-porch = <88>;
-                               hfront-porch = <40>;
-                               hsync-len = <0>;
-                               vback-porch = <32>;
-                               vfront-porch = <11>;
-                               vsync-len = <1>;
-                               clock = <0>;    /* unused but required */
-                               bpp = <16>;     /* non-standard but required */
-                       };
+       display-timings {
+               native-mode = <&timing0>;
+               timing0: 800x480 {
+                       clock-frequency = <0>; /* unused but required */
+                       hactive = <800>;
+                       vactive = <480>;
+                       hfront-porch = <40>;
+                       hback-porch = <88>;
+                       hsync-len = <0>;
+                       vback-porch = <32>;
+                       vfront-porch = <11>;
+                       vsync-len = <1>;
                };
        };
 };
+
index db3c0a12e052782641bd23731bf58aa4f4d4cc62..9313407bbc3044a8c3db5030a24eee24308dec83 100644 (file)
                        interrupts = <43>;
                };
 
-               fb@d8050800 {
+               fb: fb@d8050800 {
                        compatible = "wm,wm8505-fb";
                        reg = <0xd8050800 0x200>;
-                       display = <&display>;
-                       default-mode = <&mode0>;
                };
 
                ge_rops@d8050400 {
index fcc660c89540b9db811f68519d2c4c20c54c9a0c..32d22532cd6c1f2c4490c05d159358ce131651cc 100644 (file)
 / {
        model = "Wondermedia WM8850-W70v2 Tablet";
 
-       /*
-        * Display node is based on Sascha Hauer's patch on dri-devel.
-        * Added a bpp property to calculate the size of the framebuffer
-        * until the binding is formalized.
-        */
-       display: display@0 {
-               modes {
-                       mode0: mode@0 {
-                               hactive = <800>;
-                               vactive = <480>;
-                               hback-porch = <88>;
-                               hfront-porch = <40>;
-                               hsync-len = <0>;
-                               vback-porch = <32>;
-                               vfront-porch = <11>;
-                               vsync-len = <1>;
-                               clock = <0>;    /* unused but required */
-                               bpp = <16>;     /* non-standard but required */
-                       };
-               };
-       };
-
        backlight {
                compatible = "pwm-backlight";
                pwms = <&pwm 0 50000 1>;        /* duty inverted */
                default-brightness-level = <5>;
        };
 };
+
+&fb {
+       bits-per-pixel = <16>;
+       display-timings {
+               native-mode = <&timing0>;
+               timing0: 800x480 {
+                       clock-frequency = <0>; /* unused but required */
+                       hactive = <800>;
+                       vactive = <480>;
+                       hfront-porch = <40>;
+                       hback-porch = <88>;
+                       hsync-len = <0>;
+                       vback-porch = <32>;
+                       vfront-porch = <11>;
+                       vsync-len = <1>;
+               };
+       };
+};
index e8cbfdc87bba4bcfaa64089377727b02db13b0a3..7149cd13e3b97b1de6a01daddae27131f6f391f4 100644 (file)
                        };
                };
 
-               fb@d8051700 {
+               fb: fb@d8051700 {
                        compatible = "wm,wm8505-fb";
                        reg = <0xd8051700 0x200>;
-                       display = <&display>;
-                       default-mode = <&mode0>;
                };
 
                ge_rops@d8050400 {
index 720799fd3a81195f02563ed5540d649adea14e05..dff714d886d58dbdce93a468e6a098cf45db98f6 100644 (file)
@@ -24,7 +24,7 @@ extern struct arm_delay_ops {
        void (*delay)(unsigned long);
        void (*const_udelay)(unsigned long);
        void (*udelay)(unsigned long);
-       bool const_clock;
+       unsigned long ticks_per_jiffy;
 } arm_delay_ops;
 
 #define __delay(n)             arm_delay_ops.delay(n)
index cca9f15704ed82bb2726ce8898611be42d28b5ff..ea289e1435e742807f48550200582de5630bf817 100644 (file)
 #undef _CACHE
 #undef MULTI_CACHE
 
-#if defined(CONFIG_CPU_CACHE_V3)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE v3
-# endif
-#endif
-
 #if defined(CONFIG_CPU_CACHE_V4)
 # ifdef _CACHE
 #  define MULTI_CACHE 1
index 02fe2fbe2477078b4fa8da59c6f2a416fdb71913..ed94b1a366ae62d9535c66847ebe85abf4f4f0c0 100644 (file)
@@ -37,7 +37,7 @@ extern int iop3xx_get_init_atu(void);
  * IOP3XX processor registers
  */
 #define IOP3XX_PERIPHERAL_PHYS_BASE    0xffffe000
-#define IOP3XX_PERIPHERAL_VIRT_BASE    0xfeffe000
+#define IOP3XX_PERIPHERAL_VIRT_BASE    0xfedfe000
 #define IOP3XX_PERIPHERAL_SIZE         0x00002000
 #define IOP3XX_PERIPHERAL_UPPER_PA (IOP3XX_PERIPHERAL_PHYS_BASE +\
                                        IOP3XX_PERIPHERAL_SIZE - 1)
index 8c5e828f484dd7a039a2c5c9d060d6bba008c0ef..91b99abe7a95c114be0d3b628fb8b8d09f781c74 100644 (file)
@@ -41,6 +41,13 @@ extern void kunmap_high(struct page *page);
 #endif
 #endif
 
+/*
+ * Needed to be able to broadcast the TLB invalidation for kmap.
+ */
+#ifdef CONFIG_ARM_ERRATA_798181
+#undef ARCH_NEEDS_KMAP_HIGH_GET
+#endif
+
 #ifdef ARCH_NEEDS_KMAP_HIGH_GET
 extern void *kmap_high_get(struct page *page);
 #else
index 863a6611323c70077a9428b198a10d59758ff919..a7b85e0d0cc154a90a2efadca763cc60d95e82d8 100644 (file)
@@ -27,6 +27,8 @@ void __check_vmalloc_seq(struct mm_struct *mm);
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
 #define init_new_context(tsk,mm)       ({ atomic64_set(&mm->context.id, 0); 0; })
 
+DECLARE_PER_CPU(atomic64_t, active_asids);
+
 #else  /* !CONFIG_CPU_HAS_ASID */
 
 #ifdef CONFIG_MMU
index 6ef8afd1b64cbc3c27ea025d81d0e67d43f0400a..86b8fe398b9514d89a9032658f6bb3ad221b069e 100644 (file)
 #define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */
 #define L_PTE_S2_MT_WRITEBACK   (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */
 #define L_PTE_S2_RDONLY                 (_AT(pteval_t, 1) << 6)   /* HAP[1]   */
-#define L_PTE_S2_RDWR           (_AT(pteval_t, 2) << 6)   /* HAP[2:1] */
+#define L_PTE_S2_RDWR           (_AT(pteval_t, 3) << 6)   /* HAP[2:1] */
 
 /*
  * Hyp-mode PL2 PTE definitions for LPAE.
index 4db8c8820f0d1c832bf9efd5e81a69d32b4fc7d7..ab865e65a84c1d0aa735b512b0fbc528de699dad 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <asm/glue.h>
 
-#define TLB_V3_PAGE    (1 << 0)
 #define TLB_V4_U_PAGE  (1 << 1)
 #define TLB_V4_D_PAGE  (1 << 2)
 #define TLB_V4_I_PAGE  (1 << 3)
@@ -22,7 +21,6 @@
 #define TLB_V6_D_PAGE  (1 << 5)
 #define TLB_V6_I_PAGE  (1 << 6)
 
-#define TLB_V3_FULL    (1 << 8)
 #define TLB_V4_U_FULL  (1 << 9)
 #define TLB_V4_D_FULL  (1 << 10)
 #define TLB_V4_I_FULL  (1 << 11)
@@ -52,7 +50,6 @@
  *     =============
  *
  *     We have the following to choose from:
- *       v3    - ARMv3
  *       v4    - ARMv4 without write buffer
  *       v4wb  - ARMv4 with write buffer without I TLB flush entry instruction
  *       v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
@@ -330,7 +327,6 @@ static inline void local_flush_tlb_all(void)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       tlb_op(TLB_V3_FULL, "c6, c0, 0", zero);
        tlb_op(TLB_V4_U_FULL | TLB_V6_U_FULL, "c8, c7, 0", zero);
        tlb_op(TLB_V4_D_FULL | TLB_V6_D_FULL, "c8, c6, 0", zero);
        tlb_op(TLB_V4_I_FULL | TLB_V6_I_FULL, "c8, c5, 0", zero);
@@ -351,9 +347,8 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (possible_tlb_flags & (TLB_V3_FULL|TLB_V4_U_FULL|TLB_V4_D_FULL|TLB_V4_I_FULL)) {
+       if (possible_tlb_flags & (TLB_V4_U_FULL|TLB_V4_D_FULL|TLB_V4_I_FULL)) {
                if (cpumask_test_cpu(get_cpu(), mm_cpumask(mm))) {
-                       tlb_op(TLB_V3_FULL, "c6, c0, 0", zero);
                        tlb_op(TLB_V4_U_FULL, "c8, c7, 0", zero);
                        tlb_op(TLB_V4_D_FULL, "c8, c6, 0", zero);
                        tlb_op(TLB_V4_I_FULL, "c8, c5, 0", zero);
@@ -385,9 +380,8 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (possible_tlb_flags & (TLB_V3_PAGE|TLB_V4_U_PAGE|TLB_V4_D_PAGE|TLB_V4_I_PAGE|TLB_V4_I_FULL) &&
+       if (possible_tlb_flags & (TLB_V4_U_PAGE|TLB_V4_D_PAGE|TLB_V4_I_PAGE|TLB_V4_I_FULL) &&
            cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
-               tlb_op(TLB_V3_PAGE, "c6, c0, 0", uaddr);
                tlb_op(TLB_V4_U_PAGE, "c8, c7, 1", uaddr);
                tlb_op(TLB_V4_D_PAGE, "c8, c6, 1", uaddr);
                tlb_op(TLB_V4_I_PAGE, "c8, c5, 1", uaddr);
@@ -418,7 +412,6 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       tlb_op(TLB_V3_PAGE, "c6, c0, 0", kaddr);
        tlb_op(TLB_V4_U_PAGE, "c8, c7, 1", kaddr);
        tlb_op(TLB_V4_D_PAGE, "c8, c6, 1", kaddr);
        tlb_op(TLB_V4_I_PAGE, "c8, c5, 1", kaddr);
@@ -450,6 +443,21 @@ static inline void local_flush_bp_all(void)
                isb();
 }
 
+#ifdef CONFIG_ARM_ERRATA_798181
+static inline void dummy_flush_tlb_a15_erratum(void)
+{
+       /*
+        * Dummy TLBIMVAIS. Using the unmapped address 0 and ASID 0.
+        */
+       asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
+       dsb();
+}
+#else
+static inline void dummy_flush_tlb_a15_erratum(void)
+{
+}
+#endif
+
 /*
  *     flush_pmd_entry
  *
index 3248cde504ed9e3995d2f14357e9e1875b3f8129..fefd7f971437a084bedb5d4281fd6e78bac59d04 100644 (file)
@@ -276,7 +276,13 @@ ENDPROC(ftrace_graph_caller_old)
  */
 
 .macro mcount_enter
+/*
+ * This pad compensates for the push {lr} at the call site.  Note that we are
+ * unable to unwind through a function which does not otherwise save its lr.
+ */
+ UNWIND(.pad   #4)
        stmdb   sp!, {r0-r3, lr}
+ UNWIND(.save  {r0-r3, lr})
 .endm
 
 .macro mcount_get_lr reg
@@ -289,6 +295,7 @@ ENDPROC(ftrace_graph_caller_old)
 .endm
 
 ENTRY(__gnu_mcount_nc)
+UNWIND(.fnstart)
 #ifdef CONFIG_DYNAMIC_FTRACE
        mov     ip, lr
        ldmia   sp!, {lr}
@@ -296,17 +303,22 @@ ENTRY(__gnu_mcount_nc)
 #else
        __mcount
 #endif
+UNWIND(.fnend)
 ENDPROC(__gnu_mcount_nc)
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 ENTRY(ftrace_caller)
+UNWIND(.fnstart)
        __ftrace_caller
+UNWIND(.fnend)
 ENDPROC(ftrace_caller)
 #endif
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 ENTRY(ftrace_graph_caller)
+UNWIND(.fnstart)
        __ftrace_graph_caller
+UNWIND(.fnend)
 ENDPROC(ftrace_graph_caller)
 #endif
 
index e0eb9a1cae774fc714548c3e11ad5141cc82190e..8bac553fe213def562dec9e30cad88c827d6239c 100644 (file)
@@ -267,7 +267,7 @@ __create_page_tables:
        addne   r6, r6, #1 << SECTION_SHIFT
        strne   r6, [r3]
 
-#if defined(CONFIG_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8)
+#if defined(CONFIG_ARM_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8)
        sub     r4, r4, #4                      @ Fixup page table pointer
                                                @ for 64-bit descriptors
 #endif
index 96093b75ab90dc134d7232e3f6a1e3c5f41e7902..1fd749ee4a1bb96c1740f4a131fde1d3cd53bfb0 100644 (file)
@@ -966,7 +966,7 @@ static void reset_ctrl_regs(void *unused)
        }
 
        if (err) {
-               pr_warning("CPU %d debug is powered down!\n", cpu);
+               pr_warn_once("CPU %d debug is powered down!\n", cpu);
                cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
                return;
        }
@@ -987,7 +987,7 @@ clear_vcr:
        isb();
 
        if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
-               pr_warning("CPU %d failed to disable vector catch\n", cpu);
+               pr_warn_once("CPU %d failed to disable vector catch\n", cpu);
                return;
        }
 
@@ -1007,7 +1007,7 @@ clear_vcr:
        }
 
        if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
-               pr_warning("CPU %d failed to clear debug register pairs\n", cpu);
+               pr_warn_once("CPU %d failed to clear debug register pairs\n", cpu);
                return;
        }
 
@@ -1043,7 +1043,7 @@ static int dbg_cpu_pm_notify(struct notifier_block *self, unsigned long action,
        return NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata dbg_cpu_pm_nb = {
+static struct notifier_block dbg_cpu_pm_nb = {
        .notifier_call = dbg_cpu_pm_notify,
 };
 
index 146157dfe27c6c991b8507c2c3f248d810754cc0..8c3094d0f7b78426e367e2cf3ed538e54d686cbd 100644 (file)
@@ -253,7 +253,10 @@ validate_event(struct pmu_hw_events *hw_events,
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        struct pmu *leader_pmu = event->group_leader->pmu;
 
-       if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
+       if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF)
+               return 1;
+
+       if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec)
                return 1;
 
        return armpmu->get_event_idx(hw_events, event) >= 0;
index bd6f56b9ec2101534b7477c11c9f6ef0a3a6e68b..59d2adb764a995f9174a6494bd2bcc1974c10e73 100644 (file)
@@ -45,12 +45,12 @@ static u32 notrace jiffy_sched_clock_read(void)
 
 static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
 
-static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
+static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
 {
        return (cyc * mult) >> shift;
 }
 
-static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask)
+static unsigned long long notrace cyc_to_sched_clock(u32 cyc, u32 mask)
 {
        u64 epoch_ns;
        u32 epoch_cyc;
index 3f6cbb2e3edae392f2b73520b89b6ee3b19e8437..234e339196c0b8fbf0c10a920db0342f3411083f 100644 (file)
@@ -56,7 +56,6 @@
 #include <asm/virt.h>
 
 #include "atags.h"
-#include "tcm.h"
 
 
 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
@@ -353,6 +352,23 @@ void __init early_print(const char *str, ...)
        printk("%s", buf);
 }
 
+static void __init cpuid_init_hwcaps(void)
+{
+       unsigned int divide_instrs;
+
+       if (cpu_architecture() < CPU_ARCH_ARMv7)
+               return;
+
+       divide_instrs = (read_cpuid_ext(CPUID_EXT_ISAR0) & 0x0f000000) >> 24;
+
+       switch (divide_instrs) {
+       case 2:
+               elf_hwcap |= HWCAP_IDIVA;
+       case 1:
+               elf_hwcap |= HWCAP_IDIVT;
+       }
+}
+
 static void __init feat_v6_fixup(void)
 {
        int id = read_cpuid_id();
@@ -483,8 +499,11 @@ static void __init setup_processor(void)
        snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c",
                 list->elf_name, ENDIANNESS);
        elf_hwcap = list->elf_hwcap;
+
+       cpuid_init_hwcaps();
+
 #ifndef CONFIG_ARM_THUMB
-       elf_hwcap &= ~HWCAP_THUMB;
+       elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT);
 #endif
 
        feat_v6_fixup();
@@ -524,7 +543,7 @@ int __init arm_add_memory(phys_addr_t start, phys_addr_t size)
        size -= start & ~PAGE_MASK;
        bank->start = PAGE_ALIGN(start);
 
-#ifndef CONFIG_LPAE
+#ifndef CONFIG_ARM_LPAE
        if (bank->start + size < bank->start) {
                printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in "
                        "32-bit physical address space\n", (long long)start);
@@ -778,8 +797,6 @@ void __init setup_arch(char **cmdline_p)
 
        reserve_crashkernel();
 
-       tcm_init();
-
 #ifdef CONFIG_MULTI_IRQ_HANDLER
        handle_arch_irq = mdesc->handle_irq;
 #endif
index 79078edbb9bc12d38bb144a88754b83390429c95..1f2ccccaf009751a0ed830c6a91bfa4ea60278e3 100644 (file)
@@ -673,9 +673,6 @@ static int cpufreq_callback(struct notifier_block *nb,
        if (freq->flags & CPUFREQ_CONST_LOOPS)
                return NOTIFY_OK;
 
-       if (arm_delay_ops.const_clock)
-               return NOTIFY_OK;
-
        if (!per_cpu(l_p_j_ref, cpu)) {
                per_cpu(l_p_j_ref, cpu) =
                        per_cpu(cpu_data, cpu).loops_per_jiffy;
index bd0300531399e5eeb066a45f3c29b0d897c23b42..e82e1d24877227ba65ab716dc6c87e110617bd79 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <asm/smp_plat.h>
 #include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
 
 /**********************************************************************/
 
@@ -69,12 +70,72 @@ static inline void ipi_flush_bp_all(void *ignored)
        local_flush_bp_all();
 }
 
+#ifdef CONFIG_ARM_ERRATA_798181
+static int erratum_a15_798181(void)
+{
+       unsigned int midr = read_cpuid_id();
+
+       /* Cortex-A15 r0p0..r3p2 affected */
+       if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2)
+               return 0;
+       return 1;
+}
+#else
+static int erratum_a15_798181(void)
+{
+       return 0;
+}
+#endif
+
+static void ipi_flush_tlb_a15_erratum(void *arg)
+{
+       dmb();
+}
+
+static void broadcast_tlb_a15_erratum(void)
+{
+       if (!erratum_a15_798181())
+               return;
+
+       dummy_flush_tlb_a15_erratum();
+       smp_call_function_many(cpu_online_mask, ipi_flush_tlb_a15_erratum,
+                              NULL, 1);
+}
+
+static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm)
+{
+       int cpu;
+       cpumask_t mask = { CPU_BITS_NONE };
+
+       if (!erratum_a15_798181())
+               return;
+
+       dummy_flush_tlb_a15_erratum();
+       for_each_online_cpu(cpu) {
+               if (cpu == smp_processor_id())
+                       continue;
+               /*
+                * We only need to send an IPI if the other CPUs are running
+                * the same ASID as the one being invalidated. There is no
+                * need for locking around the active_asids check since the
+                * switch_mm() function has at least one dmb() (as required by
+                * this workaround) in case a context switch happens on
+                * another CPU after the condition below.
+                */
+               if (atomic64_read(&mm->context.id) ==
+                   atomic64_read(&per_cpu(active_asids, cpu)))
+                       cpumask_set_cpu(cpu, &mask);
+       }
+       smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1);
+}
+
 void flush_tlb_all(void)
 {
        if (tlb_ops_need_broadcast())
                on_each_cpu(ipi_flush_tlb_all, NULL, 1);
        else
                local_flush_tlb_all();
+       broadcast_tlb_a15_erratum();
 }
 
 void flush_tlb_mm(struct mm_struct *mm)
@@ -83,6 +144,7 @@ void flush_tlb_mm(struct mm_struct *mm)
                on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_mm, mm, 1);
        else
                local_flush_tlb_mm(mm);
+       broadcast_tlb_mm_a15_erratum(mm);
 }
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
@@ -95,6 +157,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
                                        &ta, 1);
        } else
                local_flush_tlb_page(vma, uaddr);
+       broadcast_tlb_mm_a15_erratum(vma->vm_mm);
 }
 
 void flush_tlb_kernel_page(unsigned long kaddr)
@@ -105,6 +168,7 @@ void flush_tlb_kernel_page(unsigned long kaddr)
                on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
        } else
                local_flush_tlb_kernel_page(kaddr);
+       broadcast_tlb_a15_erratum();
 }
 
 void flush_tlb_range(struct vm_area_struct *vma,
@@ -119,6 +183,7 @@ void flush_tlb_range(struct vm_area_struct *vma,
                                        &ta, 1);
        } else
                local_flush_tlb_range(vma, start, end);
+       broadcast_tlb_mm_a15_erratum(vma->vm_mm);
 }
 
 void flush_tlb_kernel_range(unsigned long start, unsigned long end)
@@ -130,6 +195,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
                on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
        } else
                local_flush_tlb_kernel_range(start, end);
+       broadcast_tlb_a15_erratum();
 }
 
 void flush_bp_all(void)
index 30ae6bb4a310c12723b7bc7ca26ea91ae25bb770..f50f19e5c138839bede270baf3531a41aa5af7c4 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/mach/map.h>
 #include <asm/memory.h>
 #include <asm/system_info.h>
-#include "tcm.h"
 
 static struct gen_pool *tcm_pool;
 static bool dtcm_present;
diff --git a/arch/arm/kernel/tcm.h b/arch/arm/kernel/tcm.h
deleted file mode 100644 (file)
index 8015ad4..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2008-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * TCM memory handling for ARM systems
- *
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- * Author: Rickard Andersson <rickard.andersson@stericsson.com>
- */
-
-#ifdef CONFIG_HAVE_TCM
-void __init tcm_init(void);
-#else
-/* No TCM support, just blank inlines to be optimized out */
-inline void tcm_init(void)
-{
-}
-#endif
index 5a936988eb24d1e62e5ae248ff6e4a3db59667b9..c1fe498983ac84c21334d87b1cd9cd6c8c3abc3f 100644 (file)
@@ -201,6 +201,7 @@ int kvm_dev_ioctl_check_extension(long ext)
                break;
        case KVM_CAP_ARM_SET_DEVICE_ADDR:
                r = 1;
+               break;
        case KVM_CAP_NR_VCPUS:
                r = num_online_cpus();
                break;
index 4ea9a982269c8f9c9c56808f92b464a025356533..7bed7556077a20002f0e1a6cea2c5a43b05b9102 100644 (file)
@@ -79,11 +79,11 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
        u32 val;
        int cpu;
 
-       cpu = get_cpu();
-
        if (!p->is_write)
                return read_from_write_only(vcpu, p);
 
+       cpu = get_cpu();
+
        cpumask_setall(&vcpu->arch.require_dcache_flush);
        cpumask_clear_cpu(cpu, &vcpu->arch.require_dcache_flush);
 
index c9a17316e9fe75f2a8dec4fe3893816d3d0730c9..0e4cfe123b385339629499ae5dacb4f6f5e08ff6 100644 (file)
@@ -883,8 +883,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
                          lr, irq, vgic_cpu->vgic_lr[lr]);
                BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
                vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT;
-
-               goto out;
+               return true;
        }
 
        /* Try to use another LR for this interrupt */
@@ -898,7 +897,6 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
        vgic_cpu->vgic_irq_lr_map[irq] = lr;
        set_bit(lr, vgic_cpu->lr_used);
 
-out:
        if (!vgic_irq_is_edge(vcpu, irq))
                vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI;
 
@@ -1018,21 +1016,6 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 
        kvm_debug("MISR = %08x\n", vgic_cpu->vgic_misr);
 
-       /*
-        * We do not need to take the distributor lock here, since the only
-        * action we perform is clearing the irq_active_bit for an EOIed
-        * level interrupt.  There is a potential race with
-        * the queuing of an interrupt in __kvm_vgic_flush_hwstate(), where we
-        * check if the interrupt is already active. Two possibilities:
-        *
-        * - The queuing is occurring on the same vcpu: cannot happen,
-        *   as we're already in the context of this vcpu, and
-        *   executing the handler
-        * - The interrupt has been migrated to another vcpu, and we
-        *   ignore this interrupt for this run. Big deal. It is still
-        *   pending though, and will get considered when this vcpu
-        *   exits.
-        */
        if (vgic_cpu->vgic_misr & GICH_MISR_EOI) {
                /*
                 * Some level interrupts have been EOIed. Clear their
@@ -1054,6 +1037,13 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
                        } else {
                                vgic_cpu_irq_clear(vcpu, irq);
                        }
+
+                       /*
+                        * Despite being EOIed, the LR may not have
+                        * been marked as empty.
+                        */
+                       set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr);
+                       vgic_cpu->vgic_lr[lr] &= ~GICH_LR_ACTIVE_BIT;
                }
        }
 
@@ -1064,9 +1054,8 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 }
 
 /*
- * Sync back the VGIC state after a guest run. We do not really touch
- * the distributor here (the irq_pending_on_cpu bit is safe to set),
- * so there is no need for taking its lock.
+ * Sync back the VGIC state after a guest run. The distributor lock is
+ * needed so we don't get preempted in the middle of the state processing.
  */
 static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 {
@@ -1112,10 +1101,14 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 {
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
        if (!irqchip_in_kernel(vcpu->kvm))
                return;
 
+       spin_lock(&dist->lock);
        __kvm_vgic_sync_hwstate(vcpu);
+       spin_unlock(&dist->lock);
 }
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
index 6b93f6a1a3c7413982d455e674c0a12ba5f70186..64dbfa57204ae9c3fde48c6efaec7f60e3c6af89 100644 (file)
@@ -58,7 +58,7 @@ static void __timer_delay(unsigned long cycles)
 static void __timer_const_udelay(unsigned long xloops)
 {
        unsigned long long loops = xloops;
-       loops *= loops_per_jiffy;
+       loops *= arm_delay_ops.ticks_per_jiffy;
        __timer_delay(loops >> UDELAY_SHIFT);
 }
 
@@ -73,11 +73,13 @@ void __init register_current_timer_delay(const struct delay_timer *timer)
                pr_info("Switching to timer-based delay loop\n");
                delay_timer                     = timer;
                lpj_fine                        = timer->freq / HZ;
-               loops_per_jiffy                 = lpj_fine;
+
+               /* cpufreq may scale loops_per_jiffy, so keep a private copy */
+               arm_delay_ops.ticks_per_jiffy   = lpj_fine;
                arm_delay_ops.delay             = __timer_delay;
                arm_delay_ops.const_udelay      = __timer_const_udelay;
                arm_delay_ops.udelay            = __timer_udelay;
-               arm_delay_ops.const_clock       = true;
+
                delay_calibrated                = true;
        } else {
                pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
index e698f26cc0cb5ed6bd3a62b7effb39b70d619376..52e4bb5cf12df3d58295c5120ee7fbb0c2e57fd9 100644 (file)
 
 static struct map_desc cns3xxx_io_desc[] __initdata = {
        {
-               .virtual        = CNS3XXX_TC11MP_TWD_BASE_VIRT,
-               .pfn            = __phys_to_pfn(CNS3XXX_TC11MP_TWD_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT,
-               .pfn            = __phys_to_pfn(CNS3XXX_TC11MP_GIC_CPU_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT,
-               .pfn            = __phys_to_pfn(CNS3XXX_TC11MP_GIC_DIST_BASE),
-               .length         = SZ_4K,
+               .virtual        = CNS3XXX_TC11MP_SCU_BASE_VIRT,
+               .pfn            = __phys_to_pfn(CNS3XXX_TC11MP_SCU_BASE),
+               .length         = SZ_8K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = CNS3XXX_TIMER1_2_3_BASE_VIRT,
index 191c8e57f2890f09c30610bce584194bc1c3d7f1..b1021aafa4810663a202dc2d1837fcae98c3c2de 100644 (file)
 #define RTC_INTR_STS_OFFSET                    0x34
 
 #define CNS3XXX_MISC_BASE                      0x76000000      /* Misc Control */
-#define CNS3XXX_MISC_BASE_VIRT                 0xFFF07000      /* Misc Control */
+#define CNS3XXX_MISC_BASE_VIRT                 0xFB000000      /* Misc Control */
 
 #define CNS3XXX_PM_BASE                                0x77000000      /* Power Management Control */
-#define CNS3XXX_PM_BASE_VIRT                   0xFFF08000
+#define CNS3XXX_PM_BASE_VIRT                   0xFB001000
 
 #define PM_CLK_GATE_OFFSET                     0x00
 #define PM_SOFT_RST_OFFSET                     0x04
 #define PM_PLL_HM_PD_OFFSET                    0x1C
 
 #define CNS3XXX_UART0_BASE                     0x78000000      /* UART 0 */
-#define CNS3XXX_UART0_BASE_VIRT                        0xFFF09000
+#define CNS3XXX_UART0_BASE_VIRT                        0xFB002000
 
 #define CNS3XXX_UART1_BASE                     0x78400000      /* UART 1 */
 #define CNS3XXX_UART1_BASE_VIRT                        0xFFF0A000
 #define CNS3XXX_I2S_BASE_VIRT                  0xFFF10000
 
 #define CNS3XXX_TIMER1_2_3_BASE                        0x7C800000      /* Timer */
-#define CNS3XXX_TIMER1_2_3_BASE_VIRT           0xFFF10800
+#define CNS3XXX_TIMER1_2_3_BASE_VIRT           0xFB003000
 
 #define TIMER1_COUNTER_OFFSET                  0x00
 #define TIMER1_AUTO_RELOAD_OFFSET              0x04
  * Testchip peripheral and fpga gic regions
  */
 #define CNS3XXX_TC11MP_SCU_BASE                        0x90000000      /* IRQ, Test chip */
-#define CNS3XXX_TC11MP_SCU_BASE_VIRT           0xFF000000
+#define CNS3XXX_TC11MP_SCU_BASE_VIRT           0xFB004000
 
 #define CNS3XXX_TC11MP_GIC_CPU_BASE            0x90000100      /* Test chip interrupt controller CPU interface */
-#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT       0xFF000100
+#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT       (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x100)
 
 #define CNS3XXX_TC11MP_TWD_BASE                        0x90000600
-#define CNS3XXX_TC11MP_TWD_BASE_VIRT           0xFF000600
+#define CNS3XXX_TC11MP_TWD_BASE_VIRT           (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x600)
 
 #define CNS3XXX_TC11MP_GIC_DIST_BASE           0x90001000      /* Test chip interrupt controller distributor */
-#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT      0xFF001000
+#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT      (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x1000)
 
 #define CNS3XXX_TC11MP_L220_BASE               0x92002000      /* L220 registers */
 #define CNS3XXX_TC11MP_L220_BASE_VIRT          0xFF002000
index d2afb4dd82aba7902049e24e72215e432eed6bd2..b5cc77d2380bd59c24c2da80a9995d45c2277f85 100644 (file)
@@ -47,9 +47,13 @@ static void __raw_writel(unsigned int value, unsigned int ptr)
 
 static inline void putc(int c)
 {
-       /* Transmit fifo not full?  */
-       while (__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF)
-               ;
+       int i;
+
+       for (i = 0; i < 10000; i++) {
+               /* Transmit fifo not full? */
+               if (!(__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF))
+                       break;
+       }
 
        __raw_writeb(c, PHYS_UART_DATA);
 }
index f30c528433967e43b1f1afa1050c13feefbbe914..890cae23c12aee40b3f0d675e54d590b13965a5c 100644 (file)
@@ -28,13 +28,11 @@ extern void secondary_startup(void);
  */
 void __ref highbank_cpu_die(unsigned int cpu)
 {
-       flush_cache_all();
-
        highbank_set_cpu_jump(cpu, phys_to_virt(0));
-       highbank_set_core_pwr();
 
-       cpu_do_idle();
+       flush_cache_louis();
+       highbank_set_core_pwr();
 
-       /* We should never return from idle */
-       panic("highbank: cpu %d unexpectedly exit from shutdown\n", cpu);
+       while (1)
+               cpu_do_idle();
 }
index e13a8fa5e62c5aa4f04b0aba66f4e77df0ac24ce..2193c834f55ccc68dcbd35cb3ebb1d68dc9f35d6 100644 (file)
@@ -257,6 +257,7 @@ int __init mx35_clocks_init(void)
        clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
        clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0");
        clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
+       clk_register_clkdev(clk[admux_gate], "audmux", NULL);
 
        clk_prepare_enable(clk[spba_gate]);
        clk_prepare_enable(clk[gpio1_gate]);
@@ -265,6 +266,7 @@ int __init mx35_clocks_init(void)
        clk_prepare_enable(clk[iim_gate]);
        clk_prepare_enable(clk[emi_gate]);
        clk_prepare_enable(clk[max_gate]);
+       clk_prepare_enable(clk[iomuxc_gate]);
 
        /*
         * SCC is needed to boot via mmc after a watchdog reset. The clock code
index 2f9ff93a4e6134773befacb68c4dd4ec5c14bb90..d38e54f5b6d7f1dbbbd245a91db8be9a2408b28f 100644 (file)
@@ -115,7 +115,7 @@ static const char *gpu2d_core_sels[]        = { "axi", "pll3_usb_otg", "pll2_pfd0_352m"
 static const char *gpu3d_core_sels[]   = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
 static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", };
 static const char *ipu_sels[]          = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
-static const char *ldb_di_sels[]       = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_pfd1_540m", };
+static const char *ldb_di_sels[]       = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", };
 static const char *ipu_di_pre_sels[]   = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
 static const char *ipu1_di0_sels[]     = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
 static const char *ipu1_di1_sels[]     = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
@@ -443,7 +443,6 @@ int __init mx6q_clocks_init(void)
 
        clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
        clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
-       clk_register_clkdev(clk[twd], NULL, "smp_twd");
        clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL);
        clk_register_clkdev(clk[ahb], "ahb", NULL);
        clk_register_clkdev(clk[cko1], "cko1", NULL);
index 5a800bfcec5b9e67bbf20b6b7001a70867c28482..5bf4a97ab2413c3a7234a092a74350423cba359b 100644 (file)
@@ -110,6 +110,8 @@ void tzic_handle_irq(struct pt_regs *);
 
 extern void imx_enable_cpu(int cpu, bool enable);
 extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+extern u32 imx_get_cpu_arg(int cpu);
+extern void imx_set_cpu_arg(int cpu, u32 arg);
 extern void v7_cpu_resume(void);
 extern u32 *pl310_get_save_ptr(void);
 #ifdef CONFIG_SMP
index 7bc5fe15dda2a3cbc5eb43bd1c93d69830c4af70..361a253e2b63c1abbce953df6745c1fdac8812d7 100644 (file)
@@ -46,11 +46,23 @@ static inline void cpu_enter_lowpower(void)
 void imx_cpu_die(unsigned int cpu)
 {
        cpu_enter_lowpower();
+       /*
+        * We use the cpu jumping argument register to sync with
+        * imx_cpu_kill() which is running on cpu0 and waiting for
+        * the register being cleared to kill the cpu.
+        */
+       imx_set_cpu_arg(cpu, ~0);
        cpu_do_idle();
 }
 
 int imx_cpu_kill(unsigned int cpu)
 {
+       unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+       while (imx_get_cpu_arg(cpu) == 0)
+               if (time_after(jiffies, timeout))
+                       return 0;
        imx_enable_cpu(cpu, false);
+       imx_set_cpu_arg(cpu, 0);
        return 1;
 }
index e15f1555c59b1ebd2712ba8b8c31772c340b06ef..09a742f8c7aba31be0155076699eb192f4aa251e 100644 (file)
@@ -43,6 +43,18 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)
                       src_base + SRC_GPR1 + cpu * 8);
 }
 
+u32 imx_get_cpu_arg(int cpu)
+{
+       cpu = cpu_logical_map(cpu);
+       return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
+}
+
+void imx_set_cpu_arg(int cpu, u32 arg)
+{
+       cpu = cpu_logical_map(cpu);
+       writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
+}
+
 void imx_src_prepare_restart(void)
 {
        u32 val;
index f655b2637b0e2b4822efc185c499095c44bc6b9e..e5f70415905a998e919b5b4aabe8d3121fa8a81e 100644 (file)
@@ -20,10 +20,15 @@ static struct mv643xx_eth_platform_data iomega_ix2_200_ge00_data = {
        .duplex         = DUPLEX_FULL,
 };
 
+static struct mv643xx_eth_platform_data iomega_ix2_200_ge01_data = {
+        .phy_addr       = MV643XX_ETH_PHY_ADDR(11),
+};
+
 void __init iomega_ix2_200_init(void)
 {
        /*
         * Basic setup. Needs to be called early.
         */
-       kirkwood_ge01_init(&iomega_ix2_200_ge00_data);
+       kirkwood_ge00_init(&iomega_ix2_200_ge00_data);
+       kirkwood_ge01_init(&iomega_ix2_200_ge01_data);
 }
index 1c6e736cbbf8b64e580f511c4a3f0e6f3a239d0a..08dd739aa70918fe9fdf1c06aeca7eda265ca07f 100644 (file)
@@ -53,6 +53,8 @@ static struct mv_sata_platform_data guruplug_sata_data = {
 
 static struct mvsdio_platform_data guruplug_mvsdio_data = {
        /* unfortunately the CD signal has not been connected */
+       .gpio_card_detect = -1,
+       .gpio_write_protect = -1,
 };
 
 static struct gpio_led guruplug_led_pins[] = {
index 8ddd69fdc9374ebe20c8ab7b1842593164410c05..6a6eb548307d10762b0f56307b81938842d180aa 100644 (file)
@@ -55,6 +55,7 @@ static struct mv_sata_platform_data openrd_sata_data = {
 
 static struct mvsdio_platform_data openrd_mvsdio_data = {
        .gpio_card_detect = 29, /* MPP29 used as SD card detect */
+       .gpio_write_protect = -1,
 };
 
 static unsigned int openrd_mpp_config[] __initdata = {
index c7d93b48926bbae7d7013190e00ae401e552549b..d24223166e06c60e5d9631d6f8818f44bfb0fc5b 100644 (file)
@@ -69,6 +69,7 @@ static struct mv_sata_platform_data rd88f6281_sata_data = {
 
 static struct mvsdio_platform_data rd88f6281_mvsdio_data = {
        .gpio_card_detect = 28,
+       .gpio_write_protect = -1,
 };
 
 static unsigned int rd88f6281_mpp_config[] __initdata = {
index 2969027f02fa57045ec7bb3d65d7a98927cfde3c..f9fd77e8f1f5a998af7b8f15e12af3afd5bcc299 100644 (file)
@@ -62,7 +62,10 @@ static int msm_timer_set_next_event(unsigned long cycles,
 {
        u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
 
-       writel_relaxed(0, event_base + TIMER_CLEAR);
+       ctrl &= ~TIMER_ENABLE_EN;
+       writel_relaxed(ctrl, event_base + TIMER_ENABLE);
+
+       writel_relaxed(ctrl, event_base + TIMER_CLEAR);
        writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
        writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE);
        return 0;
index 274ff58271de149f168a1a901ccc435ea131f690..d5970f5a1e8d5ea8010c8f243853ec3a28d6bb30 100644 (file)
@@ -44,6 +44,8 @@
 
 #define ARMADA_370_XP_MAX_PER_CPU_IRQS         (28)
 
+#define ARMADA_370_XP_TIMER0_PER_CPU_IRQ       (5)
+
 #define ACTIVE_DOORBELLS                       (8)
 
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
@@ -59,36 +61,26 @@ static struct irq_domain *armada_370_xp_mpic_domain;
  */
 static void armada_370_xp_irq_mask(struct irq_data *d)
 {
-#ifdef CONFIG_SMP
        irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-       if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS)
+       if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
                writel(hwirq, main_int_base +
                                ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS);
        else
                writel(hwirq, per_cpu_int_base +
                                ARMADA_370_XP_INT_SET_MASK_OFFS);
-#else
-       writel(irqd_to_hwirq(d),
-              per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS);
-#endif
 }
 
 static void armada_370_xp_irq_unmask(struct irq_data *d)
 {
-#ifdef CONFIG_SMP
        irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-       if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS)
+       if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
                writel(hwirq, main_int_base +
                                ARMADA_370_XP_INT_SET_ENABLE_OFFS);
        else
                writel(hwirq, per_cpu_int_base +
                                ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
-#else
-       writel(irqd_to_hwirq(d),
-              per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
-#endif
 }
 
 #ifdef CONFIG_SMP
@@ -144,10 +136,14 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
                                      unsigned int virq, irq_hw_number_t hw)
 {
        armada_370_xp_irq_mask(irq_get_irq_data(virq));
-       writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
+       if (hw != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
+               writel(hw, per_cpu_int_base +
+                       ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+       else
+               writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
        irq_set_status_flags(virq, IRQ_LEVEL);
 
-       if (hw < ARMADA_370_XP_MAX_PER_CPU_IRQS) {
+       if (hw == ARMADA_370_XP_TIMER0_PER_CPU_IRQ) {
                irq_set_percpu_devid(virq);
                irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
                                        handle_percpu_devid_irq);
index cb7c6ae2e3fc66f4a0744bf7930e7e1cd635ee87..6c4f766365a2e31d9b0364ef6460dca7e79c756c 100644 (file)
@@ -538,15 +538,6 @@ static struct clk usb_hhc_ck16xx = {
 };
 
 static struct clk usb_dc_ck = {
-       .name           = "usb_dc_ck",
-       .ops            = &clkops_generic,
-       /* Direct from ULPD, no parent */
-       .rate           = 48000000,
-       .enable_reg     = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
-       .enable_bit     = USB_REQ_EN_SHIFT,
-};
-
-static struct clk usb_dc_ck7xx = {
        .name           = "usb_dc_ck",
        .ops            = &clkops_generic,
        /* Direct from ULPD, no parent */
@@ -727,8 +718,7 @@ static struct omap_clk omap_clks[] = {
        CLK(NULL,       "usb_clko",     &usb_clko,      CK_16XX | CK_1510 | CK_310),
        CLK(NULL,       "usb_hhc_ck",   &usb_hhc_ck1510, CK_1510 | CK_310),
        CLK(NULL,       "usb_hhc_ck",   &usb_hhc_ck16xx, CK_16XX),
-       CLK(NULL,       "usb_dc_ck",    &usb_dc_ck,     CK_16XX),
-       CLK(NULL,       "usb_dc_ck",    &usb_dc_ck7xx,  CK_7XX),
+       CLK(NULL,       "usb_dc_ck",    &usb_dc_ck,     CK_16XX | CK_7XX),
        CLK(NULL,       "mclk",         &mclk_1510,     CK_1510 | CK_310),
        CLK(NULL,       "mclk",         &mclk_16xx,     CK_16XX),
        CLK(NULL,       "bclk",         &bclk_1510,     CK_1510 | CK_310),
index 3d58f335f173fe4c3a9542590d43a98dbebedefb..0c6834ae1fc43a8ab20409dccd1bb24d7eeb20fd 100644 (file)
  */
 #define OMAP4_DPLL_ABE_DEFFREQ                         98304000
 
+/*
+ * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section
+ * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred
+ * locked frequency for the USB DPLL is 960MHz.
+ */
+#define OMAP4_DPLL_USB_DEFFREQ                         960000000
+
 /* Root clocks */
 
 DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0);
@@ -1011,6 +1018,10 @@ DEFINE_CLK_OMAP_MUX(hsmmc2_fclk, "l3_init_clkdm", hsmmc1_fclk_sel,
                    OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK,
                    hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops);
 
+DEFINE_CLK_GATE(ocp2scp_usb_phy_phy_48m, "func_48m_fclk", &func_48m_fclk, 0x0,
+               OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+               OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, 0x0, NULL);
+
 DEFINE_CLK_GATE(sha2md5_fck, "l3_div_ck", &l3_div_ck, 0x0,
                OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
                OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
@@ -1538,6 +1549,7 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "per_mcbsp4_gfclk",                     &per_mcbsp4_gfclk,      CK_443X),
        CLK(NULL,       "hsmmc1_fclk",                  &hsmmc1_fclk,   CK_443X),
        CLK(NULL,       "hsmmc2_fclk",                  &hsmmc2_fclk,   CK_443X),
+       CLK(NULL,       "ocp2scp_usb_phy_phy_48m",      &ocp2scp_usb_phy_phy_48m,       CK_443X),
        CLK(NULL,       "sha2md5_fck",                  &sha2md5_fck,   CK_443X),
        CLK(NULL,       "slimbus1_fclk_1",              &slimbus1_fclk_1,       CK_443X),
        CLK(NULL,       "slimbus1_fclk_0",              &slimbus1_fclk_0,       CK_443X),
@@ -1705,5 +1717,13 @@ int __init omap4xxx_clk_init(void)
        if (rc)
                pr_err("%s: failed to configure ABE DPLL!\n", __func__);
 
+       /*
+        * Lock USB DPLL on OMAP4 devices so that the L3INIT power
+        * domain can transition to retention state when not in use.
+        */
+       rc = clk_set_rate(&dpll_usb_ck, OMAP4_DPLL_USB_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure USB DPLL!\n", __func__);
+
        return 0;
 }
index 40f4a03d728fc9a7278b722ce809bd57f47c64f4..d6ba13e1c540f6ecc186a164f441ca48b2540a1e 100644 (file)
@@ -293,5 +293,8 @@ extern void omap_reserve(void);
 struct omap_hwmod;
 extern int omap_dss_reset(struct omap_hwmod *);
 
+/* SoC specific clock initializer */
+extern int (*omap_clk_init)(void);
+
 #endif /* __ASSEMBLER__ */
 #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
index 2c3fdd65387b56c542d6d97cbc093fcf69a51b9a..5c445ca1e271ca9f14c9e4fd008035ee449ad9b4 100644 (file)
 #include "prm3xxx.h"
 #include "prm44xx.h"
 
+/*
+ * omap_clk_init: points to a function that does the SoC-specific
+ * clock initializations
+ */
+int (*omap_clk_init)(void);
+
 /*
  * The machine specific code may provide the extra mapping besides the
  * default mapping provided here.
@@ -397,7 +403,7 @@ void __init omap2420_init_early(void)
        omap242x_clockdomains_init();
        omap2420_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap2420_clk_init();
+       omap_clk_init = omap2420_clk_init;
 }
 
 void __init omap2420_init_late(void)
@@ -427,7 +433,7 @@ void __init omap2430_init_early(void)
        omap243x_clockdomains_init();
        omap2430_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap2430_clk_init();
+       omap_clk_init = omap2430_clk_init;
 }
 
 void __init omap2430_init_late(void)
@@ -462,7 +468,7 @@ void __init omap3_init_early(void)
        omap3xxx_clockdomains_init();
        omap3xxx_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap3xxx_clk_init();
+       omap_clk_init = omap3xxx_clk_init;
 }
 
 void __init omap3430_init_early(void)
@@ -500,7 +506,7 @@ void __init ti81xx_init_early(void)
        omap3xxx_clockdomains_init();
        omap3xxx_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap3xxx_clk_init();
+       omap_clk_init = omap3xxx_clk_init;
 }
 
 void __init omap3_init_late(void)
@@ -568,7 +574,7 @@ void __init am33xx_init_early(void)
        am33xx_clockdomains_init();
        am33xx_hwmod_init();
        omap_hwmod_init_postsetup();
-       am33xx_clk_init();
+       omap_clk_init = am33xx_clk_init;
 }
 #endif
 
@@ -593,7 +599,7 @@ void __init omap4430_init_early(void)
        omap44xx_clockdomains_init();
        omap44xx_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap4xxx_clk_init();
+       omap_clk_init = omap4xxx_clk_init;
 }
 
 void __init omap4430_init_late(void)
index c2c798c08c2b9f63a55bc11be5f654f80006431c..a202a47851045c8be6d947ce6407574d7a824f27 100644 (file)
@@ -1368,7 +1368,9 @@ static void _enable_sysc(struct omap_hwmod *oh)
        }
 
        if (sf & SYSC_HAS_MIDLEMODE) {
-               if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+               if (oh->flags & HWMOD_FORCE_MSTANDBY) {
+                       idlemode = HWMOD_IDLEMODE_FORCE;
+               } else if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
                        idlemode = HWMOD_IDLEMODE_NO;
                } else {
                        if (sf & SYSC_HAS_ENAWAKEUP)
@@ -1440,7 +1442,8 @@ static void _idle_sysc(struct omap_hwmod *oh)
        }
 
        if (sf & SYSC_HAS_MIDLEMODE) {
-               if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+               if ((oh->flags & HWMOD_SWSUP_MSTANDBY) ||
+                   (oh->flags & HWMOD_FORCE_MSTANDBY)) {
                        idlemode = HWMOD_IDLEMODE_FORCE;
                } else {
                        if (sf & SYSC_HAS_ENAWAKEUP)
index d43d9b608edab3c1b7e69c96e711ec1eefc2d7c8..d5dc935f6060446aee42a250eddbe6140e9aa42a 100644 (file)
@@ -427,8 +427,8 @@ struct omap_hwmod_omap4_prcm {
  *
  * HWMOD_SWSUP_SIDLE: omap_hwmod code should manually bring module in and out
  *     of idle, rather than relying on module smart-idle
- * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out
- *     of standby, rather than relying on module smart-standby
+ * HWMOD_SWSUP_MSTANDBY: omap_hwmod code should manually bring module in and
+ *     out of standby, rather than relying on module smart-standby
  * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for
  *     SDRAM controller, etc. XXX probably belongs outside the main hwmod file
  *     XXX Should be HWMOD_SETUP_NO_RESET
@@ -459,6 +459,10 @@ struct omap_hwmod_omap4_prcm {
  *     correctly, or this is being abused to deal with some PM latency
  *     issues -- but we're currently suffering from a shortage of
  *     folks who are able to track these issues down properly.
+ * HWMOD_FORCE_MSTANDBY: Always keep MIDLEMODE bits cleared so that device
+ *     is kept in force-standby mode. Failing to do so causes PM problems
+ *     with musb on OMAP3630 at least. Note that musb has a dedicated register
+ *     to control MSTANDBY signal when MIDLEMODE is set to force-standby.
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -471,6 +475,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_16BIT_REG                                (1 << 8)
 #define HWMOD_EXT_OPT_MAIN_CLK                 (1 << 9)
 #define HWMOD_BLOCK_WFI                                (1 << 10)
+#define HWMOD_FORCE_MSTANDBY                   (1 << 11)
 
 /*
  * omap_hwmod._int_flags definitions
index ac7e03ec952f22f7c856084c15e2de3e767e4273..5112d04e7b79bd928a3d332f2ec846352e0e5b1b 100644 (file)
@@ -1707,9 +1707,14 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
         * Erratum ID: i479  idle_req / idle_ack mechanism potentially
         * broken when autoidle is enabled
         * workaround is to disable the autoidle bit at module level.
+        *
+        * Enabling the device in any other MIDLEMODE setting but force-idle
+        * causes core_pwrdm not enter idle states at least on OMAP3630.
+        * Note that musb has OTG_FORCESTDBY register that controls MSTANDBY
+        * signal when MIDLEMODE is set to force-idle.
         */
        .flags          = HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
-                               | HWMOD_SWSUP_MSTANDBY,
+                               | HWMOD_FORCE_MSTANDBY,
 };
 
 /* usb_otg_hs */
index 0e47d2e1687c76004ea7449b8e496340617b09d1..eaba9dc91a0d9824a530cf185537a28a881b5a24 100644 (file)
@@ -2719,7 +2719,17 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
        .name           = "ocp2scp_usb_phy",
        .class          = &omap44xx_ocp2scp_hwmod_class,
        .clkdm_name     = "l3_init_clkdm",
-       .main_clk       = "func_48m_fclk",
+       /*
+        * ocp2scp_usb_phy_phy_48m is provided by the OMAP4 PRCM IP
+        * block as an "optional clock," and normally should never be
+        * specified as the main_clk for an OMAP IP block.  However it
+        * turns out that this clock is actually the main clock for
+        * the ocp2scp_usb_phy IP block:
+        * http://lists.infradead.org/pipermail/linux-arm-kernel/2012-September/119943.html
+        * So listing ocp2scp_usb_phy_phy_48m as a main_clk here seems
+        * to be the best workaround.
+        */
+       .main_clk       = "ocp2scp_usb_phy_phy_48m",
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET,
index 2bdd4cf17a8fd0e80b6c2c74feb66fcc9018ecca..f62b509ed08de75e6f4191bc8cf43dc130c7cb2d 100644 (file)
@@ -547,6 +547,8 @@ static inline void __init realtime_counter_init(void)
                               clksrc_nr, clksrc_src)                   \
 void __init omap##name##_gptimer_timer_init(void)                      \
 {                                                                      \
+       if (omap_clk_init)                                              \
+               omap_clk_init();                                        \
        omap_dmtimer_init();                                            \
        omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);    \
        omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src);        \
@@ -556,6 +558,8 @@ void __init omap##name##_gptimer_timer_init(void)                   \
                                clksrc_nr, clksrc_src)                  \
 void __init omap##name##_sync32k_timer_init(void)              \
 {                                                                      \
+       if (omap_clk_init)                                              \
+               omap_clk_init();                                        \
        omap_dmtimer_init();                                            \
        omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);    \
        /* Enable the use of clocksource="gp_timer" kernel parameter */ \
index b7a9f4d469e816bf6ca1f389f31d9280d06ecc46..1e73f5fa865983cd0a79fae37623af0f4a0ebbaf 100644 (file)
 
 #if defined(CONFIG_CPU_S3C2416)
 #define NR_IRQS (IRQ_S3C2416_I2S1 + 1)
-#elif defined(CONFIG_CPU_S3C2443)
-#define NR_IRQS (IRQ_S3C2443_AC97+1)
 #else
-#define NR_IRQS (IRQ_S3C2440_AC97+1)
+#define NR_IRQS (IRQ_S3C2443_AC97 + 1)
 #endif
 
 /* compatibility define. */
index cb9f5e011e73a1fb5f055dc6a3c6498aa095f7e0..d8ba9bee4c7e61434aa90852ce7f4e66ff4a5ebd 100644 (file)
@@ -500,7 +500,7 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
                base = (void *)0xfd000000;
 
                intc->reg_mask = base + 0xa4;
-               intc->reg_pending = base + 0x08;
+               intc->reg_pending = base + 0xa8;
                irq_num = 20;
                irq_start = S3C2410_IRQ(32);
                irq_offset = 4;
index 051b62c2710208537a3442a0ec03af57c11cc530..7f2cb6c5e2c10de3b6479e8a23ced9c523329b55 100644 (file)
@@ -81,7 +81,6 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
 #endif
 
 struct mmci_platform_data mop500_sdi0_data = {
-       .ios_handler    = mop500_sdi0_ios_handler,
        .ocr_mask       = MMC_VDD_29_30,
        .f_max          = 50000000,
        .capabilities   = MMC_CAP_4_BIT_DATA |
index b03457881c4b5aed70daee7ded2c182cc238d3b7..87d2d7b38ce90742a0a1b9d3ccda2e0271c1f5fb 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/platform_data/i2c-nomadik.h>
@@ -439,6 +440,15 @@ static void mop500_prox_deactivate(struct device *dev)
        regulator_put(prox_regulator);
 }
 
+void mop500_snowball_ethernet_clock_enable(void)
+{
+       struct clk *clk;
+
+       clk = clk_get_sys("fsmc", NULL);
+       if (!IS_ERR(clk))
+               clk_prepare_enable(clk);
+}
+
 static struct cryp_platform_data u8500_cryp1_platform_data = {
                .mem_to_engine = {
                                .dir = STEDMA40_MEM_TO_PERIPH,
@@ -683,6 +693,8 @@ static void __init snowball_init_machine(void)
        mop500_audio_init(parent);
        mop500_uart_init(parent);
 
+       mop500_snowball_ethernet_clock_enable();
+
        /* This board has full regulator constraints */
        regulator_has_full_constraints();
 }
index eaa605f5d90dc463ac62079e01d5db92e50473ca..d38951be70df01304745bcc1a62584b5c89522f3 100644 (file)
@@ -104,6 +104,7 @@ void __init mop500_pinmaps_init(void);
 void __init snowball_pinmaps_init(void);
 void __init hrefv60_pinmaps_init(void);
 void mop500_audio_init(struct device *parent);
+void mop500_snowball_ethernet_clock_enable(void);
 
 int __init mop500_uib_init(void);
 void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
index 19235cf7bbe3f33c4fe4d63eee73d779624dbb69..f1a581844372881e7e0d54aac4b3465495a5941d 100644 (file)
@@ -312,9 +312,10 @@ static void __init u8500_init_machine(void)
        /* Pinmaps must be in place before devices register */
        if (of_machine_is_compatible("st-ericsson,mop500"))
                mop500_pinmaps_init();
-       else if (of_machine_is_compatible("calaosystems,snowball-a9500"))
+       else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
                snowball_pinmaps_init();
-       else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
+               mop500_snowball_ethernet_clock_enable();
+       } else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
                hrefv60_pinmaps_init();
        else if (of_machine_is_compatible("st-ericsson,ccu9540")) {}
                /* TODO: Add pinmaps for ccu9540 board. */
index 025d173287307afdb5db4bc0b7a9679511629c11..4045c4931a300d3381848dc2ff3d39403096c2d9 100644 (file)
@@ -43,7 +43,7 @@ config CPU_ARM740T
        depends on !MMU
        select CPU_32v4T
        select CPU_ABRT_LV4T
-       select CPU_CACHE_V3     # although the core is v4t
+       select CPU_CACHE_V4
        select CPU_CP15_MPU
        select CPU_PABRT_LEGACY
        help
@@ -469,9 +469,6 @@ config CPU_PABRT_V7
        bool
 
 # The cache model
-config CPU_CACHE_V3
-       bool
-
 config CPU_CACHE_V4
        bool
 
index 4e333fa2756f4de16b4005ca65e1eb44cff0c579..9e51be96f635b5945b978bed2c6978fd3d2b61ba 100644 (file)
@@ -33,7 +33,6 @@ obj-$(CONFIG_CPU_PABRT_LEGACY)        += pabort-legacy.o
 obj-$(CONFIG_CPU_PABRT_V6)     += pabort-v6.o
 obj-$(CONFIG_CPU_PABRT_V7)     += pabort-v7.o
 
-obj-$(CONFIG_CPU_CACHE_V3)     += cache-v3.o
 obj-$(CONFIG_CPU_CACHE_V4)     += cache-v4.o
 obj-$(CONFIG_CPU_CACHE_V4WT)   += cache-v4wt.o
 obj-$(CONFIG_CPU_CACHE_V4WB)   += cache-v4wb.o
index dd3d59122cc374c80ad487ad57bc3f5fbc580325..48bc3c0a87ce321cc2e37c257bf217dc085307e6 100644 (file)
@@ -343,6 +343,7 @@ void __init feroceon_l2_init(int __l2_wt_override)
        outer_cache.inv_range = feroceon_l2_inv_range;
        outer_cache.clean_range = feroceon_l2_clean_range;
        outer_cache.flush_range = feroceon_l2_flush_range;
+       outer_cache.inv_all = l2_inv_all;
 
        enable_l2();
 
index c2f37390308a20b835d653dfbb0f64f28cc8ce40..c465faca51b06b05ed50c27962b8b169198ea909 100644 (file)
@@ -299,7 +299,7 @@ static void l2x0_unlock(u32 cache_id)
        int lockregs;
        int i;
 
-       switch (cache_id) {
+       switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
        case L2X0_CACHE_ID_PART_L310:
                lockregs = 8;
                break;
@@ -333,15 +333,14 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
        if (cache_id_part_number_from_dt)
                cache_id = cache_id_part_number_from_dt;
        else
-               cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID)
-                       & L2X0_CACHE_ID_PART_MASK;
+               cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
        aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
 
        aux &= aux_mask;
        aux |= aux_val;
 
        /* Determine the number of ways */
-       switch (cache_id) {
+       switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
        case L2X0_CACHE_ID_PART_L310:
                if (aux & (1 << 16))
                        ways = 16;
@@ -725,7 +724,6 @@ static const struct l2x0_of_data pl310_data = {
                .flush_all   = l2x0_flush_all,
                .inv_all     = l2x0_inv_all,
                .disable     = l2x0_disable,
-               .set_debug   = pl310_set_debug,
        },
 };
 
@@ -814,9 +812,8 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
                data->save();
 
        of_init = true;
-       l2x0_init(l2x0_base, aux_val, aux_mask);
-
        memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache));
+       l2x0_init(l2x0_base, aux_val, aux_mask);
 
        return 0;
 }
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
deleted file mode 100644 (file)
index 8a3fade..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- *  linux/arch/arm/mm/cache-v3.S
- *
- *  Copyright (C) 1997-2002 Russell king
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/page.h>
-#include "proc-macros.S"
-
-/*
- *     flush_icache_all()
- *
- *     Unconditionally clean and invalidate the entire icache.
- */
-ENTRY(v3_flush_icache_all)
-       mov     pc, lr
-ENDPROC(v3_flush_icache_all)
-
-/*
- *     flush_user_cache_all()
- *
- *     Invalidate all cache entries in a particular address
- *     space.
- *
- *     - mm    - mm_struct describing address space
- */
-ENTRY(v3_flush_user_cache_all)
-       /* FALLTHROUGH */
-/*
- *     flush_kern_cache_all()
- *
- *     Clean and invalidate the entire cache.
- */
-ENTRY(v3_flush_kern_cache_all)
-       /* FALLTHROUGH */
-
-/*
- *     flush_user_cache_range(start, end, flags)
- *
- *     Invalidate a range of cache entries in the specified
- *     address space.
- *
- *     - start - start address (may not be aligned)
- *     - end   - end address (exclusive, may not be aligned)
- *     - flags - vma_area_struct flags describing address space
- */
-ENTRY(v3_flush_user_cache_range)
-       mov     ip, #0
-       mcreq   p15, 0, ip, c7, c0, 0           @ flush ID cache
-       mov     pc, lr
-
-/*
- *     coherent_kern_range(start, end)
- *
- *     Ensure coherency between the Icache and the Dcache in the
- *     region described by start.  If you have non-snooping
- *     Harvard caches, you need to implement this function.
- *
- *     - start  - virtual start address
- *     - end    - virtual end address
- */
-ENTRY(v3_coherent_kern_range)
-       /* FALLTHROUGH */
-
-/*
- *     coherent_user_range(start, end)
- *
- *     Ensure coherency between the Icache and the Dcache in the
- *     region described by start.  If you have non-snooping
- *     Harvard caches, you need to implement this function.
- *
- *     - start  - virtual start address
- *     - end    - virtual end address
- */
-ENTRY(v3_coherent_user_range)
-       mov     r0, #0
-       mov     pc, lr
-
-/*
- *     flush_kern_dcache_area(void *page, size_t size)
- *
- *     Ensure no D cache aliasing occurs, either with itself or
- *     the I cache
- *
- *     - addr  - kernel address
- *     - size  - region size
- */
-ENTRY(v3_flush_kern_dcache_area)
-       /* FALLTHROUGH */
-
-/*
- *     dma_flush_range(start, end)
- *
- *     Clean and invalidate the specified virtual address range.
- *
- *     - start  - virtual start address
- *     - end    - virtual end address
- */
-ENTRY(v3_dma_flush_range)
-       mov     r0, #0
-       mcr     p15, 0, r0, c7, c0, 0           @ flush ID cache
-       mov     pc, lr
-
-/*
- *     dma_unmap_area(start, size, dir)
- *     - start - kernel virtual start address
- *     - size  - size of region
- *     - dir   - DMA direction
- */
-ENTRY(v3_dma_unmap_area)
-       teq     r2, #DMA_TO_DEVICE
-       bne     v3_dma_flush_range
-       /* FALLTHROUGH */
-
-/*
- *     dma_map_area(start, size, dir)
- *     - start - kernel virtual start address
- *     - size  - size of region
- *     - dir   - DMA direction
- */
-ENTRY(v3_dma_map_area)
-       mov     pc, lr
-ENDPROC(v3_dma_unmap_area)
-ENDPROC(v3_dma_map_area)
-
-       .globl  v3_flush_kern_cache_louis
-       .equ    v3_flush_kern_cache_louis, v3_flush_kern_cache_all
-
-       __INITDATA
-
-       @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
-       define_cache_functions v3
index 43e5d77be677a329f497f9829364f392b254fa75..a7ba68f59f0cd8564fa2a12b84e0e2b3f13b6860 100644 (file)
@@ -58,7 +58,7 @@ ENTRY(v4_flush_kern_cache_all)
 ENTRY(v4_flush_user_cache_range)
 #ifdef CONFIG_CPU_CP15
        mov     ip, #0
-       mcreq   p15, 0, ip, c7, c7, 0           @ flush ID cache
+       mcr     p15, 0, ip, c7, c7, 0           @ flush ID cache
        mov     pc, lr
 #else
        /* FALLTHROUGH */
index a5a4b2bc42ba353e7e0ae94461cf4d8691b2b68a..2ac37372ef52f4ba4db642d39bef349798f1785a 100644 (file)
@@ -48,7 +48,7 @@ static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
 static atomic64_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION);
 static DECLARE_BITMAP(asid_map, NUM_USER_ASIDS);
 
-static DEFINE_PER_CPU(atomic64_t, active_asids);
+DEFINE_PER_CPU(atomic64_t, active_asids);
 static DEFINE_PER_CPU(u64, reserved_asids);
 static cpumask_t tlb_flush_pending;
 
@@ -215,6 +215,7 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
        if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) {
                local_flush_bp_all();
                local_flush_tlb_all();
+               dummy_flush_tlb_a15_erratum();
        }
 
        atomic64_set(&per_cpu(active_asids, cpu), asid);
index e95a996ab78f6c7d995d859f6010ef5d8df471ed..a84ff763ac399b72778ed8e6f7a3571676ac5ffa 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/mach/pci.h>
 
 #include "mm.h"
+#include "tcm.h"
 
 /*
  * empty_zero_page is a special page that is used for
@@ -598,39 +599,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
        } while (pte++, addr += PAGE_SIZE, addr != end);
 }
 
-static void __init alloc_init_section(pud_t *pud, unsigned long addr,
-                                     unsigned long end, phys_addr_t phys,
-                                     const struct mem_type *type)
+static void __init map_init_section(pmd_t *pmd, unsigned long addr,
+                       unsigned long end, phys_addr_t phys,
+                       const struct mem_type *type)
 {
-       pmd_t *pmd = pmd_offset(pud, addr);
-
+#ifndef CONFIG_ARM_LPAE
        /*
-        * Try a section mapping - end, addr and phys must all be aligned
-        * to a section boundary.  Note that PMDs refer to the individual
-        * L1 entries, whereas PGDs refer to a group of L1 entries making
-        * up one logical pointer to an L2 table.
+        * In classic MMU format, puds and pmds are folded in to
+        * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
+        * group of L1 entries making up one logical pointer to
+        * an L2 table (2MB), where as PMDs refer to the individual
+        * L1 entries (1MB). Hence increment to get the correct
+        * offset for odd 1MB sections.
+        * (See arch/arm/include/asm/pgtable-2level.h)
         */
-       if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
-               pmd_t *p = pmd;
-
-#ifndef CONFIG_ARM_LPAE
-               if (addr & SECTION_SIZE)
-                       pmd++;
+       if (addr & SECTION_SIZE)
+               pmd++;
 #endif
+       do {
+               *pmd = __pmd(phys | type->prot_sect);
+               phys += SECTION_SIZE;
+       } while (pmd++, addr += SECTION_SIZE, addr != end);
 
-               do {
-                       *pmd = __pmd(phys | type->prot_sect);
-                       phys += SECTION_SIZE;
-               } while (pmd++, addr += SECTION_SIZE, addr != end);
+       flush_pmd_entry(pmd);
+}
 
-               flush_pmd_entry(p);
-       } else {
+static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
+                                     unsigned long end, phys_addr_t phys,
+                                     const struct mem_type *type)
+{
+       pmd_t *pmd = pmd_offset(pud, addr);
+       unsigned long next;
+
+       do {
                /*
-                * No need to loop; pte's aren't interested in the
-                * individual L1 entries.
+                * With LPAE, we must loop over to map
+                * all the pmds for the given range.
                 */
-               alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
-       }
+               next = pmd_addr_end(addr, end);
+
+               /*
+                * Try a section mapping - addr, next and phys must all be
+                * aligned to a section boundary.
+                */
+               if (type->prot_sect &&
+                               ((addr | next | phys) & ~SECTION_MASK) == 0) {
+                       map_init_section(pmd, addr, next, phys, type);
+               } else {
+                       alloc_init_pte(pmd, addr, next,
+                                               __phys_to_pfn(phys), type);
+               }
+
+               phys += next - addr;
+
+       } while (pmd++, addr = next, addr != end);
 }
 
 static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
@@ -641,7 +663,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
 
        do {
                next = pud_addr_end(addr, end);
-               alloc_init_section(pud, addr, next, phys, type);
+               alloc_init_pmd(pud, addr, next, phys, type);
                phys += next - addr;
        } while (pud++, addr = next, addr != end);
 }
@@ -1256,6 +1278,7 @@ void __init paging_init(struct machine_desc *mdesc)
        dma_contiguous_remap();
        devicemaps_init(mdesc);
        kmap_init();
+       tcm_init();
 
        top_pmd = pmd_off_k(0xffff0000);
 
index dc5de5d53f20c4865f6522d86fa96e7d9495071e..fde2d2a794cfbc0b43c31619fff9668172aebad3 100644 (file)
@@ -77,24 +77,27 @@ __arm740_setup:
        mcr     p15, 0, r0, c6, c0              @ set area 0, default
 
        ldr     r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
-       ldr     r1, =(CONFIG_DRAM_SIZE >> 12)   @ size of RAM (must be >= 4KB)
-       mov     r2, #10                         @ 11 is the minimum (4KB)
-1:     add     r2, r2, #1                      @ area size *= 2
-       mov     r1, r1, lsr #1
+       ldr     r3, =(CONFIG_DRAM_SIZE >> 12)   @ size of RAM (must be >= 4KB)
+       mov     r4, #10                         @ 11 is the minimum (4KB)
+1:     add     r4, r4, #1                      @ area size *= 2
+       movs    r3, r3, lsr #1
        bne     1b                              @ count not zero r-shift
-       orr     r0, r0, r2, lsl #1              @ the area register value
+       orr     r0, r0, r4, lsl #1              @ the area register value
        orr     r0, r0, #1                      @ set enable bit
        mcr     p15, 0, r0, c6, c1              @ set area 1, RAM
 
        ldr     r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
-       ldr     r1, =(CONFIG_FLASH_SIZE >> 12)  @ size of FLASH (must be >= 4KB)
-       mov     r2, #10                         @ 11 is the minimum (4KB)
-1:     add     r2, r2, #1                      @ area size *= 2
-       mov     r1, r1, lsr #1
+       ldr     r3, =(CONFIG_FLASH_SIZE >> 12)  @ size of FLASH (must be >= 4KB)
+       cmp     r3, #0
+       moveq   r0, #0
+       beq     2f
+       mov     r4, #10                         @ 11 is the minimum (4KB)
+1:     add     r4, r4, #1                      @ area size *= 2
+       movs    r3, r3, lsr #1
        bne     1b                              @ count not zero r-shift
-       orr     r0, r0, r2, lsl #1              @ the area register value
+       orr     r0, r0, r4, lsl #1              @ the area register value
        orr     r0, r0, #1                      @ set enable bit
-       mcr     p15, 0, r0, c6, c2              @ set area 2, ROM/FLASH
+2:     mcr     p15, 0, r0, c6, c2              @ set area 2, ROM/FLASH
 
        mov     r0, #0x06
        mcr     p15, 0, r0, c2, c0              @ Region 1&2 cacheable
@@ -137,13 +140,14 @@ __arm740_proc_info:
        .long   0x41807400
        .long   0xfffffff0
        .long   0
+       .long   0
        b       __arm740_setup
        .long   cpu_arch_name
        .long   cpu_elf_name
-       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_26BIT
        .long   cpu_arm740_name
        .long   arm740_processor_functions
        .long   0
        .long   0
-       .long   v3_cache_fns                    @ cache model
+       .long   v4_cache_fns                    @ cache model
        .size   __arm740_proc_info, . - __arm740_proc_info
index 2c3b9421ab5eca938dfe9289fc39472259ada3c1..2556cf1c2da1c8f40c09edbe7d43b7c0286f355f 100644 (file)
@@ -387,7 +387,7 @@ ENTRY(cpu_arm920_set_pte_ext)
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl cpu_arm920_suspend_size
 .equ   cpu_arm920_suspend_size, 4 * 3
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_arm920_do_suspend)
        stmfd   sp!, {r4 - r6, lr}
        mrc     p15, 0, r4, c13, c0, 0  @ PID
index f1803f7e29728460965675b6722a978d0cc33dcd..344c8a548cc0ef95aea9653d883b26c629f016dd 100644 (file)
@@ -402,7 +402,7 @@ ENTRY(cpu_arm926_set_pte_ext)
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl cpu_arm926_suspend_size
 .equ   cpu_arm926_suspend_size, 4 * 3
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_arm926_do_suspend)
        stmfd   sp!, {r4 - r6, lr}
        mrc     p15, 0, r4, c13, c0, 0  @ PID
index 82f9cdc751d6421d01bcb4eca3de51dd211f1868..0b60dd3d742a1d909e4ffdf8d5162cd052754098 100644 (file)
@@ -350,7 +350,7 @@ ENTRY(cpu_mohawk_set_pte_ext)
 
 .globl cpu_mohawk_suspend_size
 .equ   cpu_mohawk_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_mohawk_do_suspend)
        stmfd   sp!, {r4 - r9, lr}
        mrc     p14, 0, r4, c6, c0, 0   @ clock configuration, for turbo mode
index 3aa0da11fd8473376405d6fe57b76b777ca1cf93..d92dfd081429294200875ddedfbd6beb4fd98735 100644 (file)
@@ -172,7 +172,7 @@ ENTRY(cpu_sa1100_set_pte_ext)
 
 .globl cpu_sa1100_suspend_size
 .equ   cpu_sa1100_suspend_size, 4 * 3
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_sa1100_do_suspend)
        stmfd   sp!, {r4 - r6, lr}
        mrc     p15, 0, r4, c3, c0, 0           @ domain ID
index 3e6210b4d6d4cc713ba524ab3966760ad1d6f6f8..054b491ff7649ca067ff821770aec80a4da42102 100644 (file)
@@ -17,7 +17,9 @@
 
 #ifndef MULTI_CPU
 EXPORT_SYMBOL(cpu_dcache_clean_area);
+#ifdef CONFIG_MMU
 EXPORT_SYMBOL(cpu_set_pte_ext);
+#endif
 #else
 EXPORT_SYMBOL(processor);
 #endif
index bcaaa8de93250fb73dbab83b3b0d07a74ccd70fc..5c07ee4fe3eb5cd004d5a81780c5f255527150cb 100644 (file)
@@ -138,7 +138,7 @@ ENTRY(cpu_v6_set_pte_ext)
 /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
 .globl cpu_v6_suspend_size
 .equ   cpu_v6_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_v6_do_suspend)
        stmfd   sp!, {r4 - r9, lr}
        mrc     p15, 0, r4, c13, c0, 0  @ FCSE/PID
index 3a3c015f8d5c33cb99357995b6d35790037e7f94..f584d3f5b37c5855782a0259c327bc6347bba89a 100644 (file)
@@ -420,7 +420,7 @@ __v7_pj4b_proc_info:
 __v7_ca7mp_proc_info:
        .long   0x410fc070
        .long   0xff0ffff0
-       __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV
+       __v7_proc __v7_ca7mp_setup
        .size   __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
 
        /*
@@ -430,9 +430,24 @@ __v7_ca7mp_proc_info:
 __v7_ca15mp_proc_info:
        .long   0x410fc0f0
        .long   0xff0ffff0
-       __v7_proc __v7_ca15mp_setup, hwcaps = HWCAP_IDIV
+       __v7_proc __v7_ca15mp_setup
        .size   __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
 
+       /*
+        * Qualcomm Inc. Krait processors.
+        */
+       .type   __krait_proc_info, #object
+__krait_proc_info:
+       .long   0x510f0400              @ Required ID value
+       .long   0xff0ffc00              @ Mask for ID
+       /*
+        * Some Krait processors don't indicate support for SDIV and UDIV
+        * instructions in the ARM instruction set, even though they actually
+        * do support them.
+        */
+       __v7_proc __v7_setup, hwcaps = HWCAP_IDIV
+       .size   __krait_proc_info, . - __krait_proc_info
+
        /*
         * Match any ARMv7 processor core.
         */
index eb93d6487f3598fcb0cc6e92c0f3e23faa36fb11..e8efd83b6f252f00b85b29eb45d24bbd4919d4ae 100644 (file)
@@ -413,7 +413,7 @@ ENTRY(cpu_xsc3_set_pte_ext)
 
 .globl cpu_xsc3_suspend_size
 .equ   cpu_xsc3_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_xsc3_do_suspend)
        stmfd   sp!, {r4 - r9, lr}
        mrc     p14, 0, r4, c6, c0, 0   @ clock configuration, for turbo mode
index 25510361aa181e7200d6f69a64d41ff6b8f8a8a6..e766f889bfd6d1b4159c6724a975468dbba56892 100644 (file)
@@ -528,7 +528,7 @@ ENTRY(cpu_xscale_set_pte_ext)
 
 .globl cpu_xscale_suspend_size
 .equ   cpu_xscale_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_xscale_do_suspend)
        stmfd   sp!, {r4 - r9, lr}
        mrc     p14, 0, r4, c6, c0, 0   @ clock configuration, for turbo mode
diff --git a/arch/arm/mm/tcm.h b/arch/arm/mm/tcm.h
new file mode 100644 (file)
index 0000000..8015ad4
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2008-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * TCM memory handling for ARM systems
+ *
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Rickard Andersson <rickard.andersson@stericsson.com>
+ */
+
+#ifdef CONFIG_HAVE_TCM
+void __init tcm_init(void);
+#else
+/* No TCM support, just blank inlines to be optimized out */
+inline void tcm_init(void)
+{
+}
+#endif
index b885322717a14258a74675062d792705b0bd849e..9ae507270785ed0ce803844d724043a5d87b7407 100644 (file)
 #ifndef __PLAT_S3C_FB_H
 #define __PLAT_S3C_FB_H __FILE__
 
-/* S3C_FB_MAX_WIN
- * Set to the maximum number of windows that any of the supported hardware
- * can use. Since the platform data uses this for an array size, having it
- * set to the maximum of any version of the hardware can do is safe.
- */
-#define S3C_FB_MAX_WIN (5)
-
-/**
- * struct s3c_fb_pd_win - per window setup data
- * @xres     : The window X size.
- * @yres     : The window Y size.
- * @virtual_x: The virtual X size.
- * @virtual_y: The virtual Y size.
- */
-struct s3c_fb_pd_win {
-       unsigned short          default_bpp;
-       unsigned short          max_bpp;
-       unsigned short          xres;
-       unsigned short          yres;
-       unsigned short          virtual_x;
-       unsigned short          virtual_y;
-};
-
-/**
- * struct s3c_fb_platdata -  S3C driver platform specific information
- * @setup_gpio: Setup the external GPIO pins to the right state to transfer
- *             the data from the display system to the connected display
- *             device.
- * @vidcon0: The base vidcon0 values to control the panel data format.
- * @vidcon1: The base vidcon1 values to control the panel data output.
- * @vtiming: Video timing when connected to a RGB type panel.
- * @win: The setup data for each hardware window, or NULL for unused.
- * @display_mode: The LCD output display mode.
- *
- * The platform data supplies the video driver with all the information
- * it requires to work with the display(s) attached to the machine. It
- * controls the initial mode, the number of display windows (0 is always
- * the base framebuffer) that are initialised etc.
- *
- */
-struct s3c_fb_platdata {
-       void    (*setup_gpio)(void);
-
-       struct s3c_fb_pd_win    *win[S3C_FB_MAX_WIN];
-       struct fb_videomode     *vtiming;
-
-       u32                      vidcon0;
-       u32                      vidcon1;
-};
+#include <linux/platform_data/video_s3c.h>
 
 /**
  * s3c_fb_set_platdata() - Setup the FB device with platform data.
index cf60d0a9f1767ca8d8ba8e3e810526539022313f..fc6483f83ccca748a3dc4319bb1ee849f8435654 100644 (file)
@@ -165,6 +165,10 @@ BUILDIO_IOPORT(l, u32)
 #define readw_be                       __raw_readw
 #define readl_be                       __raw_readl
 
+#define writeb_relaxed                 writeb
+#define writew_relaxed                 writew
+#define writel_relaxed                 writel
+
 #define writeb_be                      __raw_writeb
 #define writew_be                      __raw_writew
 #define writel_be                      __raw_writel
index cf78e09e18c3613fe027cd3ac458ed4a4a15c01b..2c71d5634ec299e181d53a4a2ca430563d385b05 100644 (file)
@@ -27,7 +27,7 @@ static inline unsigned long arch_local_save_flags(void)
 /* set interrupt enabled status */
 static inline void arch_local_irq_restore(unsigned long flags)
 {
-       asm volatile (" mvc .s2 %0,CSR\n" : : "b"(flags));
+       asm volatile (" mvc .s2 %0,CSR\n" : : "b"(flags) : "memory");
 }
 
 /* unconditionally enable interrupts */
index 9a02f71c6b1f7cb5e8339e55f77bb82ad9b8d8d3..e7e55a00f94f6072bd57217e34a6fe6d8f201b10 100644 (file)
@@ -187,7 +187,7 @@ config IA64_DIG
 
 config IA64_DIG_VTD
        bool "DIG+Intel+IOMMU"
-       select DMAR
+       select INTEL_IOMMU
        select PCI_MSI
 
 config IA64_HP_ZX1
index d2bf1fd5e44f5970caf455acdddc671fc0dee192..76acbcd5c06090e25cd35e77b3afbd5c16f7c0ae 100644 (file)
@@ -106,16 +106,15 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                return -EFAULT;
 
        {
-               register unsigned long r8 __asm ("r8");
+               register unsigned long r8 __asm ("r8") = 0;
                unsigned long prev;
                __asm__ __volatile__(
                        "       mf;;                                    \n"
-                       "       mov %0=r0                               \n"
                        "       mov ar.ccv=%4;;                         \n"
                        "[1:]   cmpxchg4.acq %1=[%2],%3,ar.ccv          \n"
                        "       .xdata4 \"__ex_table\", 1b-., 2f-.      \n"
                        "[2:]"
-                       : "=r" (r8), "=r" (prev)
+                       : "+r" (r8), "=&r" (prev)
                        : "r" (uaddr), "r" (newval),
                          "rO" ((long) (unsigned) oldval)
                        : "memory");
index 43f96ab18fa0d2754ff5f79374c02e785ec24347..8c709616871626f175164a5f237bfa0cec1af2d9 100644 (file)
@@ -143,6 +143,7 @@ extern unsigned long __per_cpu_mca[NR_CPUS];
 extern int cpe_vector;
 extern int ia64_cpe_irq;
 extern void ia64_mca_init(void);
+extern void ia64_mca_irq_init(void);
 extern void ia64_mca_cpu_init(void *);
 extern void ia64_os_mca_dispatch(void);
 extern void ia64_os_mca_dispatch_end(void);
index 2e27ef17565295ccebd21c75cc2d700be4c9d891..2db0a6c6daa5f13840bed1ede72c224e6dd5cf6a 100644 (file)
@@ -67,14 +67,13 @@ extern int paddr_to_nid(unsigned long paddr);
 
 extern void map_cpu_to_node(int cpu, int nid);
 extern void unmap_cpu_from_node(int cpu, int nid);
-
+extern void numa_clear_node(int cpu);
 
 #else /* !CONFIG_NUMA */
 #define map_cpu_to_node(cpu, nid)      do{}while(0)
 #define unmap_cpu_from_node(cpu, nid)  do{}while(0)
-
 #define paddr_to_nid(addr)     0
-
+#define numa_clear_node(cpu)   do { } while (0)
 #endif /* CONFIG_NUMA */
 
 #endif /* _ASM_IA64_NUMA_H */
index c4cd45d97749bf610f55b8be24a04ba5b7cec107..abc6dee3799c989597d7d84cdc87e8110619affd 100644 (file)
@@ -90,53 +90,6 @@ ENTRY(fsys_getpid)
        FSYS_RETURN
 END(fsys_getpid)
 
-ENTRY(fsys_getppid)
-       .prologue
-       .altrp b6
-       .body
-       add r17=IA64_TASK_GROUP_LEADER_OFFSET,r16
-       ;;
-       ld8 r17=[r17]                           // r17 = current->group_leader
-       add r9=TI_FLAGS+IA64_TASK_SIZE,r16
-       ;;
-
-       ld4 r9=[r9]
-       add r17=IA64_TASK_REAL_PARENT_OFFSET,r17 // r17 = &current->group_leader->real_parent
-       ;;
-       and r9=TIF_ALLWORK_MASK,r9
-
-1:     ld8 r18=[r17]                           // r18 = current->group_leader->real_parent
-       ;;
-       cmp.ne p8,p0=0,r9
-       add r8=IA64_TASK_TGID_OFFSET,r18        // r8 = &current->group_leader->real_parent->tgid
-       ;;
-
-       /*
-        * The .acq is needed to ensure that the read of tgid has returned its data before
-        * we re-check "real_parent".
-        */
-       ld4.acq r8=[r8]                         // r8 = current->group_leader->real_parent->tgid
-#ifdef CONFIG_SMP
-       /*
-        * Re-read current->group_leader->real_parent.
-        */
-       ld8 r19=[r17]                           // r19 = current->group_leader->real_parent
-(p8)   br.spnt.many fsys_fallback_syscall
-       ;;
-       cmp.ne p6,p0=r18,r19                    // did real_parent change?
-       mov r19=0                       // i must not leak kernel bits...
-(p6)   br.cond.spnt.few 1b                     // yes -> redo the read of tgid and the check
-       ;;
-       mov r17=0                       // i must not leak kernel bits...
-       mov r18=0                       // i must not leak kernel bits...
-#else
-       mov r17=0                       // i must not leak kernel bits...
-       mov r18=0                       // i must not leak kernel bits...
-       mov r19=0                       // i must not leak kernel bits...
-#endif
-       FSYS_RETURN
-END(fsys_getppid)
-
 ENTRY(fsys_set_tid_address)
        .prologue
        .altrp b6
@@ -614,7 +567,7 @@ paravirt_fsyscall_table:
        data8 0                         // chown
        data8 0                         // lseek                // 1040
        data8 fsys_getpid               // getpid
-       data8 fsys_getppid              // getppid
+       data8 0                         // getppid
        data8 0                         // mount
        data8 0                         // umount
        data8 0                         // setuid               // 1045
index ee33c3aaa2fca383abd28f64021a0b6cb1c4c6ba..19f107be734e6e9db90c050b2389eb2a79cc1b71 100644 (file)
@@ -76,7 +76,7 @@
  *     PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ
  *
  * Note: The term "IRQ" is loosely used everywhere in Linux kernel to
- * describeinterrupts.  Now we use "IRQ" only for Linux IRQ's.  ISA IRQ
+ * describe interrupts.  Now we use "IRQ" only for Linux IRQ's.  ISA IRQ
  * (isa_irq) is the only exception in this source code.
  */
 
@@ -1010,6 +1010,26 @@ iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)
        return 0;
 }
 
+static int
+iosapic_delete_rte(unsigned int irq, unsigned int gsi)
+{
+       struct iosapic_rte_info *rte, *temp;
+
+       list_for_each_entry_safe(rte, temp, &iosapic_intr_info[irq].rtes,
+                                                               rte_list) {
+               if (rte->iosapic->gsi_base + rte->rte_index == gsi) {
+                       if (rte->refcnt)
+                               return -EBUSY;
+
+                       list_del(&rte->rte_list);
+                       kfree(rte);
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
 int iosapic_init(unsigned long phys_addr, unsigned int gsi_base)
 {
        int num_rte, err, index;
@@ -1069,7 +1089,7 @@ int iosapic_init(unsigned long phys_addr, unsigned int gsi_base)
 
 int iosapic_remove(unsigned int gsi_base)
 {
-       int index, err = 0;
+       int i, irq, index, err = 0;
        unsigned long flags;
 
        spin_lock_irqsave(&iosapic_lock, flags);
@@ -1087,6 +1107,16 @@ int iosapic_remove(unsigned int gsi_base)
                goto out;
        }
 
+       for (i = gsi_base; i < gsi_base + iosapic_lists[index].num_rte; i++) {
+               irq = __gsi_to_irq(i);
+               if (irq < 0)
+                       continue;
+
+               err = iosapic_delete_rte(irq, i);
+               if (err)
+                       goto out;
+       }
+
        iounmap(iosapic_lists[index].addr);
        iosapic_free(index);
  out:
index ad69606613eb6d336a6f73af5f6c45eb2c936eb1..f2c41828113050c19f0f09ce6d97beb733ebcd3e 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 
+#include <asm/mca.h>
+
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves.
@@ -83,6 +85,12 @@ bool is_affinity_mask_valid(const struct cpumask *cpumask)
 
 #endif /* CONFIG_SMP */
 
+int __init arch_early_irq_init(void)
+{
+       ia64_mca_irq_init();
+       return 0;
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 unsigned int vectors_in_migration[NR_IRQS];
 
index 65bf9cd390443c3574e8d4da5a175c566928b535..d7396dbb07bb40598c2a7de3b26ffc34bf5de8ca 100644 (file)
@@ -2074,22 +2074,16 @@ ia64_mca_init(void)
        printk(KERN_INFO "MCA related initialization done\n");
 }
 
+
 /*
- * ia64_mca_late_init
- *
- *     Opportunity to setup things that require initialization later
- *     than ia64_mca_init.  Setup a timer to poll for CPEs if the
- *     platform doesn't support an interrupt driven mechanism.
- *
- *  Inputs  :   None
- *  Outputs :   Status
+ * These pieces cannot be done in ia64_mca_init() because it is called before
+ * early_irq_init() which would wipe out our percpu irq registrations. But we
+ * cannot leave them until ia64_mca_late_init() because by then all the other
+ * processors have been brought online and have set their own CMC vectors to
+ * point at a non-existant action. Called from arch_early_irq_init().
  */
-static int __init
-ia64_mca_late_init(void)
+void __init ia64_mca_irq_init(void)
 {
-       if (!mca_init)
-               return 0;
-
        /*
         *  Configure the CMCI/P vector and handler. Interrupts for CMC are
         *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
@@ -2108,6 +2102,23 @@ ia64_mca_late_init(void)
        /* Setup the CPEI/P handler */
        register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
 #endif
+}
+
+/*
+ * ia64_mca_late_init
+ *
+ *     Opportunity to setup things that require initialization later
+ *     than ia64_mca_init.  Setup a timer to poll for CPEs if the
+ *     platform doesn't support an interrupt driven mechanism.
+ *
+ *  Inputs  :   None
+ *  Outputs :   Status
+ */
+static int __init
+ia64_mca_late_init(void)
+{
+       if (!mca_init)
+               return 0;
 
        register_hotcpu_notifier(&mca_cpu_notifier);
 
index 9392e021c93be2cd371d487ba2c56b72af0432a1..94f8bf777afa62d84e74cc3456959e2090d0f6f5 100644 (file)
@@ -349,7 +349,7 @@ init_record_index_pools(void)
 
        /* - 3 - */
        slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
-       slidx_pool.buffer = (slidx_list_t *)
+       slidx_pool.buffer =
                kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
 
        return slidx_pool.buffer ? 0 : -ENOMEM;
index 77597e5ea60aca9429f29c26ec7973bf89a19683..79521d5499f94e906c7a0fece9cfe206d7629c79 100644 (file)
@@ -849,17 +849,6 @@ static palinfo_entry_t palinfo_entries[]={
 
 #define NR_PALINFO_ENTRIES     (int) ARRAY_SIZE(palinfo_entries)
 
-/*
- * this array is used to keep track of the proc entries we create. This is
- * required in the module mode when we need to remove all entries. The procfs code
- * does not do recursion of deletion
- *
- * Notes:
- *     - +1 accounts for the cpuN directory entry in /proc/pal
- */
-#define NR_PALINFO_PROC_ENTRIES        (NR_CPUS*(NR_PALINFO_ENTRIES+1))
-
-static struct proc_dir_entry *palinfo_proc_entries[NR_PALINFO_PROC_ENTRIES];
 static struct proc_dir_entry *palinfo_dir;
 
 /*
@@ -971,60 +960,32 @@ palinfo_read_entry(char *page, char **start, off_t off, int count, int *eof, voi
 static void __cpuinit
 create_palinfo_proc_entries(unsigned int cpu)
 {
-#      define CPUSTR   "cpu%d"
-
        pal_func_cpu_u_t f;
-       struct proc_dir_entry **pdir;
        struct proc_dir_entry *cpu_dir;
        int j;
-       char cpustr[sizeof(CPUSTR)];
-
-
-       /*
-        * we keep track of created entries in a depth-first order for
-        * cleanup purposes. Each entry is stored into palinfo_proc_entries
-        */
-       sprintf(cpustr,CPUSTR, cpu);
+       char cpustr[3+4+1];     /* cpu numbers are up to 4095 on itanic */
+       sprintf(cpustr, "cpu%d", cpu);
 
        cpu_dir = proc_mkdir(cpustr, palinfo_dir);
+       if (!cpu_dir)
+               return;
 
        f.req_cpu = cpu;
 
-       /*
-        * Compute the location to store per cpu entries
-        * We dont store the top level entry in this list, but
-        * remove it finally after removing all cpu entries.
-        */
-       pdir = &palinfo_proc_entries[cpu*(NR_PALINFO_ENTRIES+1)];
-       *pdir++ = cpu_dir;
        for (j=0; j < NR_PALINFO_ENTRIES; j++) {
                f.func_id = j;
-               *pdir = create_proc_read_entry(
-                               palinfo_entries[j].name, 0, cpu_dir,
-                               palinfo_read_entry, (void *)f.value);
-               pdir++;
+               create_proc_read_entry(
+                       palinfo_entries[j].name, 0, cpu_dir,
+                       palinfo_read_entry, (void *)f.value);
        }
 }
 
 static void
 remove_palinfo_proc_entries(unsigned int hcpu)
 {
-       int j;
-       struct proc_dir_entry *cpu_dir, **pdir;
-
-       pdir = &palinfo_proc_entries[hcpu*(NR_PALINFO_ENTRIES+1)];
-       cpu_dir = *pdir;
-       *pdir++=NULL;
-       for (j=0; j < (NR_PALINFO_ENTRIES); j++) {
-               if ((*pdir)) {
-                       remove_proc_entry ((*pdir)->name, cpu_dir);
-                       *pdir ++= NULL;
-               }
-       }
-
-       if (cpu_dir) {
-               remove_proc_entry(cpu_dir->name, palinfo_dir);
-       }
+       char cpustr[3+4+1];     /* cpu numbers are up to 4095 on itanic */
+       sprintf(cpustr, "cpu%d", hcpu);
+       remove_proc_subtree(cpustr, palinfo_dir);
 }
 
 static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb,
@@ -1058,6 +1019,8 @@ palinfo_init(void)
 
        printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION);
        palinfo_dir = proc_mkdir("pal", NULL);
+       if (!palinfo_dir)
+               return -ENOMEM;
 
        /* Create palinfo dirs in /proc for all online cpus */
        for_each_online_cpu(i) {
@@ -1073,22 +1036,8 @@ palinfo_init(void)
 static void __exit
 palinfo_exit(void)
 {
-       int i = 0;
-
-       /* remove all nodes: depth first pass. Could optimize this  */
-       for_each_online_cpu(i) {
-               remove_palinfo_proc_entries(i);
-       }
-
-       /*
-        * Remove the top level entry finally
-        */
-       remove_proc_entry(palinfo_dir->name, NULL);
-
-       /*
-        * Unregister from cpu notifier callbacks
-        */
        unregister_hotcpu_notifier(&palinfo_cpu_notifier);
+       remove_proc_subtree("pal", NULL);
 }
 
 module_init(palinfo_init);
index 4332f7ee5203f27179db08b5a95d372c6509e681..a7869f8f49a6604cd550750766250aeb0d04756c 100644 (file)
@@ -256,7 +256,7 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte)
                        "srlz.d;;"
                        "ssm psr.i;;"
                        "srlz.d;;"
-                       : "=r"(ret) : "r"(iha), "r"(pte):"memory");
+                       : "=&r"(ret) : "r"(iha), "r"(pte) : "memory");
 
        return ret;
 }
index 3dccdd8eb275fd9c36c1e3105791a09f34e0a858..43964cde6214ae6b0fc3cb6cfec911b6a4df2fd2 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/meminit.h>
 
 static inline void __iomem *
-__ioremap (unsigned long phys_addr)
+__ioremap_uc(unsigned long phys_addr)
 {
        return (void __iomem *) (__IA64_UNCACHED_OFFSET | phys_addr);
 }
@@ -24,7 +24,11 @@ __ioremap (unsigned long phys_addr)
 void __iomem *
 early_ioremap (unsigned long phys_addr, unsigned long size)
 {
-       return __ioremap(phys_addr);
+       u64 attr;
+       attr = kern_mem_attribute(phys_addr, size);
+       if (attr & EFI_MEMORY_WB)
+               return (void __iomem *) phys_to_virt(phys_addr);
+       return __ioremap_uc(phys_addr);
 }
 
 void __iomem *
@@ -47,7 +51,7 @@ ioremap (unsigned long phys_addr, unsigned long size)
        if (attr & EFI_MEMORY_WB)
                return (void __iomem *) phys_to_virt(phys_addr);
        else if (attr & EFI_MEMORY_UC)
-               return __ioremap(phys_addr);
+               return __ioremap_uc(phys_addr);
 
        /*
         * Some chipsets don't support UC access to memory.  If
@@ -93,7 +97,7 @@ ioremap (unsigned long phys_addr, unsigned long size)
                return (void __iomem *) (offset + (char __iomem *)addr);
        }
 
-       return __ioremap(phys_addr);
+       return __ioremap_uc(phys_addr);
 }
 EXPORT_SYMBOL(ioremap);
 
@@ -103,7 +107,7 @@ ioremap_nocache (unsigned long phys_addr, unsigned long size)
        if (kern_mem_attribute(phys_addr, size) & EFI_MEMORY_WB)
                return NULL;
 
-       return __ioremap(phys_addr);
+       return __ioremap_uc(phys_addr);
 }
 EXPORT_SYMBOL(ioremap_nocache);
 
index 3efea7d0a351c5159d5e843406e744fe0948a33d..def782e31aac31a5401d5bb75d2c6b2a25f682f2 100644 (file)
@@ -73,6 +73,11 @@ int __meminit __early_pfn_to_nid(unsigned long pfn)
        return -1;
 }
 
+void __cpuinit numa_clear_node(int cpu)
+{
+       unmap_cpu_from_node(cpu, NUMA_NO_NODE);
+}
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
  *  SRAT information is stored in node_memblk[], then we can use SRAT
index 60532ab2734684eafc036e5a5bc88194b7bae142..de1474ff0bc59fb26d2822c6793da608bb3194fb 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/pci-acpi.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
@@ -458,6 +459,16 @@ void pcibios_fixup_bus(struct pci_bus *b)
        platform_pci_fixup_bus(b);
 }
 
+void pcibios_add_bus(struct pci_bus *bus)
+{
+       acpi_pci_add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+       acpi_pci_remove_bus(bus);
+}
+
 void pcibios_set_master (struct pci_dev *dev)
 {
        /* No special bus mastering setup handling */
index 14c1711238c0c0edf2c4a2e89250269376634d31..e35f6485c1fd1964cfb4f379dd89497e52dc4de8 100644 (file)
@@ -490,11 +490,14 @@ static int __init tiocx_init(void)
 {
        cnodeid_t cnodeid;
        int found_tiocx_device = 0;
+       int err;
 
        if (!ia64_platform_is("sn2"))
                return 0;
 
-       bus_register(&tiocx_bus_type);
+       err = bus_register(&tiocx_bus_type);
+       if (err)
+               return err;
 
        for (cnodeid = 0; cnodeid < num_cnodes; cnodeid++) {
                nasid_t nasid;
index 4395ffc51fdbc4739ae5f22257c42a6f76b06a41..8cc83431805b73eb44d777d8749e6fc3de66fbbe 100644 (file)
@@ -86,4 +86,24 @@ static inline int gpio_cansleep(unsigned gpio)
        return gpio < MCFGPIO_PIN_MAX ? 0 : __gpio_cansleep(gpio);
 }
 
+static inline int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
+{
+       int err;
+
+       err = gpio_request(gpio, label);
+       if (err)
+               return err;
+
+       if (flags & GPIOF_DIR_IN)
+               err = gpio_direction_input(gpio);
+       else
+               err = gpio_direction_output(gpio,
+                       (flags & GPIOF_INIT_HIGH) ? 1 : 0);
+
+       if (err)
+               gpio_free(gpio);
+
+       return err;
+}
+
 #endif
index cd2e21ff562af434803045c048dbbfbcd28a50cb..51244bf972718a54876e7ba2ab78ae1790c98e59 100644 (file)
@@ -18,7 +18,7 @@ config MIPS
        select HAVE_KRETPROBES
        select HAVE_DEBUG_KMEMLEAK
        select ARCH_BINFMT_ELF_RANDOMIZE_PIE
-       select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+       select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
        select RTC_LIB if !MACH_LOONGSON
        select GENERIC_ATOMIC64 if !64BIT
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
@@ -657,7 +657,7 @@ config SNI_RM
        bool "SNI RM200/300/400"
        select FW_ARC if CPU_LITTLE_ENDIAN
        select FW_ARC32 if CPU_LITTLE_ENDIAN
-       select SNIPROM if CPU_BIG_ENDIAN
+       select FW_SNIPROM if CPU_BIG_ENDIAN
        select ARCH_MAY_HAVE_PC_FDC
        select BOOT_ELF32
        select CEVT_R4K
@@ -1144,7 +1144,7 @@ config DEFAULT_SGI_PARTITION
 config FW_ARC32
        bool
 
-config SNIPROM
+config FW_SNIPROM
        bool
 
 config BOOT_ELF32
@@ -1493,7 +1493,6 @@ config CPU_XLP
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
-       select CPU_HAS_LLSC
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
        select CPU_HAS_PREFETCH
index ed1949c295087bf81ef951539c08400507e9d603..9aa7d44898ed11cff9c70112e0e142923e27f2f4 100644 (file)
@@ -745,10 +745,7 @@ void __init board_prom_init(void)
                strcpy(cfe_version, "unknown");
        printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
 
-       if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET)) {
-               printk(KERN_ERR PFX "invalid nvram checksum\n");
-               return;
-       }
+       bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET);
 
        board_name = bcm63xx_nvram_get_name();
        /* find board by name */
index 620611680839e42d1aa16741aca00526f352e39f..a4b8864f93072d8e305d6a7bcca4953b2cbcc4a5 100644 (file)
@@ -38,7 +38,7 @@ struct bcm963xx_nvram {
 static struct bcm963xx_nvram nvram;
 static int mac_addr_used;
 
-int __init bcm63xx_nvram_init(void *addr)
+void __init bcm63xx_nvram_init(void *addr)
 {
        unsigned int check_len;
        u32 crc, expected_crc;
@@ -60,9 +60,8 @@ int __init bcm63xx_nvram_init(void *addr)
        crc = crc32_le(~0, (u8 *)&nvram, check_len);
 
        if (crc != expected_crc)
-               return -EINVAL;
-
-       return 0;
+               pr_warn("nvram checksum failed, contents may be invalid (expected %08x, got %08x)\n",
+                       expected_crc, crc);
 }
 
 u8 *bcm63xx_nvram_get_name(void)
index 314231be788cd7365c55e3501187600296932c38..35e18e98beb96b04151999aac8bf037129efc324 100644 (file)
@@ -157,4 +157,4 @@ int __init bcm63xx_register_devices(void)
        return board_register_devices();
 }
 
-device_initcall(bcm63xx_register_devices);
+arch_initcall(bcm63xx_register_devices);
index c594a3d4f743be31d2933e5ed5589f423d8a3743..b0baa299f899b3c2322c0a4346cc4947dcfc2457 100644 (file)
@@ -174,7 +174,10 @@ static int octeon_kexec_prepare(struct kimage *image)
 
 static void octeon_generic_shutdown(void)
 {
-       int cpu, i;
+       int i;
+#ifdef CONFIG_SMP
+       int cpu;
+#endif
        struct cvmx_bootmem_desc *bootmem_desc;
        void *named_block_array_ptr;
 
index 62d6a3b4d3b7b512550e558001934f3e55a7917f..4e0b6bc1165edcbae2f44663390daa2c63c017d9 100644 (file)
@@ -9,10 +9,8 @@
  *
  * Initialized the local nvram copy from the target address and checks
  * its checksum.
- *
- * Returns 0 on success.
  */
-int __init bcm63xx_nvram_init(void *nvram);
+void bcm63xx_nvram_init(void *nvram);
 
 /**
  * bcm63xx_nvram_get_name() - returns the board name according to nvram
index d9c82841903775734d6a462de251deaba1058715..193c0912d38e651519b8fb8b7bbc9fa31d7893e8 100644 (file)
 /* #define cpu_has_prefetch    ? */
 #define cpu_has_mcheck         1
 /* #define cpu_has_ejtag       ? */
-#ifdef CONFIG_CPU_HAS_LLSC
 #define cpu_has_llsc           1
-#else
-#define cpu_has_llsc           0
-#endif
 /* #define cpu_has_vtag_icache ? */
 /* #define cpu_has_dc_aliases  ? */
 /* #define cpu_has_ic_fills_f_dc ? */
index 12b70c25906a0d3a32d095b52d3766bc2285e115..0da44d422f5b0242380bfc0dde4973b547c1900e 100644 (file)
@@ -1166,7 +1166,10 @@ do {                                                                     \
        unsigned int __dspctl;                                          \
                                                                        \
        __asm__ __volatile__(                                           \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
        "       rddsp   %0, %x1                                 \n"     \
+       "       .set pop                                        \n"     \
        : "=r" (__dspctl)                                               \
        : "i" (mask));                                                  \
        __dspctl;                                                       \
@@ -1175,30 +1178,198 @@ do {                                                                   \
 #define wrdsp(val, mask)                                               \
 do {                                                                   \
        __asm__ __volatile__(                                           \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
        "       wrdsp   %0, %x1                                 \n"     \
+       "       .set pop                                        \n"     \
        :                                                               \
        : "r" (val), "i" (mask));                                       \
 } while (0)
 
-#define mflo0() ({ long mflo0; __asm__("mflo %0, $ac0" : "=r" (mflo0)); mflo0;})
-#define mflo1() ({ long mflo1; __asm__("mflo %0, $ac1" : "=r" (mflo1)); mflo1;})
-#define mflo2() ({ long mflo2; __asm__("mflo %0, $ac2" : "=r" (mflo2)); mflo2;})
-#define mflo3() ({ long mflo3; __asm__("mflo %0, $ac3" : "=r" (mflo3)); mflo3;})
-
-#define mfhi0() ({ long mfhi0; __asm__("mfhi %0, $ac0" : "=r" (mfhi0)); mfhi0;})
-#define mfhi1() ({ long mfhi1; __asm__("mfhi %0, $ac1" : "=r" (mfhi1)); mfhi1;})
-#define mfhi2() ({ long mfhi2; __asm__("mfhi %0, $ac2" : "=r" (mfhi2)); mfhi2;})
-#define mfhi3() ({ long mfhi3; __asm__("mfhi %0, $ac3" : "=r" (mfhi3)); mfhi3;})
-
-#define mtlo0(x) __asm__("mtlo %0, $ac0" ::"r" (x))
-#define mtlo1(x) __asm__("mtlo %0, $ac1" ::"r" (x))
-#define mtlo2(x) __asm__("mtlo %0, $ac2" ::"r" (x))
-#define mtlo3(x) __asm__("mtlo %0, $ac3" ::"r" (x))
-
-#define mthi0(x) __asm__("mthi %0, $ac0" ::"r" (x))
-#define mthi1(x) __asm__("mthi %0, $ac1" ::"r" (x))
-#define mthi2(x) __asm__("mthi %0, $ac2" ::"r" (x))
-#define mthi3(x) __asm__("mthi %0, $ac3" ::"r" (x))
+#define mflo0()                                                                \
+({                                                                     \
+       long mflo0;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mflo %0, $ac0                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mflo0));                                                \
+       mflo0;                                                          \
+})
+
+#define mflo1()                                                                \
+({                                                                     \
+       long mflo1;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mflo %0, $ac1                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mflo1));                                                \
+       mflo1;                                                          \
+})
+
+#define mflo2()                                                                \
+({                                                                     \
+       long mflo2;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mflo %0, $ac2                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mflo2));                                                \
+       mflo2;                                                          \
+})
+
+#define mflo3()                                                                \
+({                                                                     \
+       long mflo3;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mflo %0, $ac3                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mflo3));                                                \
+       mflo3;                                                          \
+})
+
+#define mfhi0()                                                                \
+({                                                                     \
+       long mfhi0;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mfhi %0, $ac0                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mfhi0));                                                \
+       mfhi0;                                                          \
+})
+
+#define mfhi1()                                                                \
+({                                                                     \
+       long mfhi1;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mfhi %0, $ac1                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mfhi1));                                                \
+       mfhi1;                                                          \
+})
+
+#define mfhi2()                                                                \
+({                                                                     \
+       long mfhi2;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mfhi %0, $ac2                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mfhi2));                                                \
+       mfhi2;                                                          \
+})
+
+#define mfhi3()                                                                \
+({                                                                     \
+       long mfhi3;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mfhi %0, $ac3                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mfhi3));                                                \
+       mfhi3;                                                          \
+})
+
+
+#define mtlo0(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mtlo %0, $ac0                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mtlo1(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mtlo %0, $ac1                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mtlo2(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mtlo %0, $ac2                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mtlo3(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mtlo %0, $ac3                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mthi0(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mthi %0, $ac0                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mthi1(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mthi %0, $ac1                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mthi2(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mthi %0, $ac2                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mthi3(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mthi %0, $ac3                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
 
 #else
 
index 99fc547af9d3517257c8cc46f1deffcf3b07cff8..eab99e536b5c9137e5cd1f117fa57ca1318c6c54 100644 (file)
@@ -31,7 +31,7 @@
 #define PAGE_SHIFT     16
 #endif
 #define PAGE_SIZE      (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK      (~(PAGE_SIZE - 1))
+#define PAGE_MASK      (~((1 << PAGE_SHIFT) - 1))
 
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 #define HPAGE_SHIFT    (PAGE_SHIFT + PAGE_SHIFT - 3)
index 197f6367c201c122171b7e81cbcebc328a683a7f..8efe5a9e2c3e68a1ab5cffe718fe58bbd815abb4 100644 (file)
@@ -21,6 +21,6 @@
 #include <asm/sigcontext.h>
 #include <asm/siginfo.h>
 
-#define __ARCH_HAS_ODD_SIGACTION
+#define __ARCH_HAS_IRIX_SIGACTION
 
 #endif /* _ASM_SIGNAL_H */
index d6b18b4d0f3a99c7c96f58a27d77c1fd62777f61..addb9f556b71836de758580005a0a603fc040f64 100644 (file)
@@ -72,6 +72,12 @@ typedef unsigned long old_sigset_t;          /* at least 32 bits */
  *
  * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
  * Unix names RESETHAND and NODEFER respectively.
+ *
+ * SA_RESTORER used to be defined as 0x04000000 but only the O32 ABI ever
+ * supported its use and no libc was using it, so the entire sa-restorer
+ * functionality was removed with lmo commit 39bffc12c3580ab for 2.5.48
+ * retaining only the SA_RESTORER definition as a reminder to avoid
+ * accidental reuse of the mask bit.
  */
 #define SA_ONSTACK     0x08000000
 #define SA_RESETHAND   0x80000000
@@ -84,8 +90,6 @@ typedef unsigned long old_sigset_t;           /* at least 32 bits */
 #define SA_NOMASK      SA_NODEFER
 #define SA_ONESHOT     SA_RESETHAND
 
-#define SA_RESTORER    0x04000000      /* Only for o32 */
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index f81d98f6184c2f89ff7f69530247a2b6181245fd..de75fb50562bfec163b876e312e9b6a0d72a7c23 100644 (file)
@@ -100,29 +100,16 @@ obj-$(CONFIG_HW_PERF_EVENTS)      += perf_event_mipsxx.o
 obj-$(CONFIG_JUMP_LABEL)       += jump_label.o
 
 #
-# DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is safe
-# to enable DSP assembler support here even if the MIPS Release 2 CPU we
-# are targetting does not support DSP because all code-paths making use of
-# it properly check that the running CPU *actually does* support these
-# instructions.
+# DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is not
+# safe to unconditionnaly use the assembler -mdsp / -mdspr2 switches
+# here because the compiler may use DSP ASE instructions (such as lwx) in
+# code paths where we cannot check that the CPU we are running on supports it.
+# Proper abstraction using HAVE_AS_DSP and macros is done in
+# arch/mips/include/asm/mipsregs.h.
 #
 ifeq ($(CONFIG_CPU_MIPSR2), y)
 CFLAGS_DSP                     = -DHAVE_AS_DSP
 
-#
-# Check if assembler supports DSP ASE
-#
-ifeq ($(call cc-option-yn,-mdsp), y)
-CFLAGS_DSP                     += -mdsp
-endif
-
-#
-# Check if assembler supports DSP ASE Rev2
-#
-ifeq ($(call cc-option-yn,-mdspr2), y)
-CFLAGS_DSP                     += -mdspr2
-endif
-
 CFLAGS_signal.o                        = $(CFLAGS_DSP)
 CFLAGS_signal32.o              = $(CFLAGS_DSP)
 CFLAGS_process.o               = $(CFLAGS_DSP)
index 6bfccc227a95f850d31c64ce1b6e6c863f62ba77..5fe66a0c32245366bc56079eca0a160a7b9bc0cb 100644 (file)
@@ -580,6 +580,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                c->tlbsize = 48;
                break;
        case PRID_IMP_VR41XX:
+               set_isa(c, MIPS_CPU_ISA_III);
+               c->options = R4K_OPTS;
+               c->tlbsize = 32;
                switch (c->processor_id & 0xf0) {
                case PRID_REV_VR4111:
                        c->cputype = CPU_VR4111;
@@ -604,6 +607,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                                __cpu_name[cpu] = "NEC VR4131";
                        } else {
                                c->cputype = CPU_VR4133;
+                               c->options |= MIPS_CPU_LLSC;
                                __cpu_name[cpu] = "NEC VR4133";
                        }
                        break;
@@ -613,9 +617,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                        __cpu_name[cpu] = "NEC Vr41xx";
                        break;
                }
-               set_isa(c, MIPS_CPU_ISA_III);
-               c->options = R4K_OPTS;
-               c->tlbsize = 32;
                break;
        case PRID_IMP_R4300:
                c->cputype = CPU_R4300;
@@ -1226,10 +1227,8 @@ __cpuinit void cpu_probe(void)
        if (c->options & MIPS_CPU_FPU) {
                c->fpu_id = cpu_get_fpu_id();
 
-               if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
-                   c->isa_level == MIPS_CPU_ISA_M32R2 ||
-                   c->isa_level == MIPS_CPU_ISA_M64R1 ||
-                   c->isa_level == MIPS_CPU_ISA_M64R2) {
+               if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
+                                   MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
                        if (c->fpu_id & MIPS_FPIR_3D)
                                c->ases |= MIPS_ASE_MIPS3D;
                }
index 8eeee1c860c08cd5ea0228e8387668cc2aaa0cc5..db9655f08892d73738664e45a48e088f941b263a 100644 (file)
@@ -171,7 +171,7 @@ SYSCALL_DEFINE6(32_ipc, u32, call, long, first, long, second, long, third,
                err = compat_sys_shmctl(first, second, compat_ptr(ptr));
                break;
        default:
-               err = -EINVAL;
+               err = -ENOSYS;
                break;
        }
 
index 1658676733576e74867347f0f7d122df0c5a023e..33d067148e61ba6d1526529ef735b24f2c3017c3 100644 (file)
        PTR_L   a5, PT_R9(sp)
        PTR_L   a6, PT_R10(sp)
        PTR_L   a7, PT_R11(sp)
-#else
-       PTR_ADDIU       sp, PT_SIZE
 #endif
-.endm
+       PTR_ADDIU       sp, PT_SIZE
+       .endm
 
        .macro RETURN_BACK
        jr ra
@@ -68,7 +67,11 @@ NESTED(ftrace_caller, PT_SIZE, ra)
        .globl _mcount
 _mcount:
        b       ftrace_stub
-       addiu sp,sp,8
+#ifdef CONFIG_32BIT
+        addiu sp,sp,8
+#else
+        nop
+#endif
 
        /* When tracing is activated, it calls ftrace_caller+8 (aka here) */
        lw      t1, function_trace_stop
index 135c4aadccbe35d9a49415170dce3d2b9e05a697..7a54f74b7818ad402a70221eb2090dc91f5643f8 100644 (file)
@@ -67,7 +67,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        if (cpu_has_mips_r) {
                seq_printf(m, "isa\t\t\t:");
                if (cpu_has_mips_1)
-                       seq_printf(m, "%s", "mips1");
+                       seq_printf(m, "%s", " mips1");
                if (cpu_has_mips_2)
                        seq_printf(m, "%s", " mips2");
                if (cpu_has_mips_3)
index a200b5bdbb870c0d5b7121503f9c1032f62c956a..c3abb88170fc01a6a4cfeeda10bd7c3f144707ec 100644 (file)
@@ -1571,7 +1571,7 @@ void __cpuinit per_cpu_trap_init(bool is_boot_cpu)
 #ifdef CONFIG_64BIT
        status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX;
 #endif
-       if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
+       if (current_cpu_data.isa_level & MIPS_CPU_ISA_IV)
                status_set |= ST0_XX;
        if (cpu_has_dsp)
                status_set |= ST0_MX;
index 81f1dcfdcab8c212ebbac6c5159291dc8b8e1162..a64daee740ee0414ee6a8db474b32893ae51ab1d 100644 (file)
@@ -90,12 +90,12 @@ int __mips_test_and_set_bit(unsigned long nr,
        unsigned bit = nr & SZLONG_MASK;
        unsigned long mask;
        unsigned long flags;
-       unsigned long res;
+       int res;
 
        a += nr >> SZLONG_LOG;
        mask = 1UL << bit;
        raw_local_irq_save(flags);
-       res = (mask & *a);
+       res = (mask & *a) != 0;
        *a |= mask;
        raw_local_irq_restore(flags);
        return res;
@@ -116,12 +116,12 @@ int __mips_test_and_set_bit_lock(unsigned long nr,
        unsigned bit = nr & SZLONG_MASK;
        unsigned long mask;
        unsigned long flags;
-       unsigned long res;
+       int res;
 
        a += nr >> SZLONG_LOG;
        mask = 1UL << bit;
        raw_local_irq_save(flags);
-       res = (mask & *a);
+       res = (mask & *a) != 0;
        *a |= mask;
        raw_local_irq_restore(flags);
        return res;
@@ -141,12 +141,12 @@ int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
        unsigned bit = nr & SZLONG_MASK;
        unsigned long mask;
        unsigned long flags;
-       unsigned long res;
+       int res;
 
        a += nr >> SZLONG_LOG;
        mask = 1UL << bit;
        raw_local_irq_save(flags);
-       res = (mask & *a);
+       res = (mask & *a) != 0;
        *a &= ~mask;
        raw_local_irq_restore(flags);
        return res;
@@ -166,12 +166,12 @@ int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        unsigned bit = nr & SZLONG_MASK;
        unsigned long mask;
        unsigned long flags;
-       unsigned long res;
+       int res;
 
        a += nr >> SZLONG_LOG;
        mask = 1UL << bit;
        raw_local_irq_save(flags);
-       res = (mask & *a);
+       res = (mask & *a) != 0;
        *a ^= mask;
        raw_local_irq_restore(flags);
        return res;
index 507147aebd417d612633e1104b83fd8bff08cbce..a6adffbb4e5f0a5ccc5ec268c18c718b69c5a8da 100644 (file)
@@ -270,7 +270,7 @@ LEAF(csum_partial)
 #endif
 
        /* odd buffer alignment? */
-#ifdef CPU_MIPSR2
+#ifdef CONFIG_CPU_MIPSR2
        wsbh    v1, sum
        movn    sum, v1, t7
 #else
@@ -670,7 +670,7 @@ EXC(        sb      t0, NBYTES-2(dst), .Ls_exc)
        addu    sum, v1
 #endif
 
-#ifdef CPU_MIPSR2
+#ifdef CONFIG_CPU_MIPSR2
        wsbh    v1, sum
        movn    sum, v1, odd
 #else
index ecca559b8d7b4313431e120b82dc88edf5b7e807..2078915eacb9c9ff740ec2daa1a65274ad1de7a9 100644 (file)
@@ -1247,10 +1247,8 @@ static void __cpuinit setup_scache(void)
                return;
 
        default:
-               if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
-                   c->isa_level == MIPS_CPU_ISA_M32R2 ||
-                   c->isa_level == MIPS_CPU_ISA_M64R1 ||
-                   c->isa_level == MIPS_CPU_ISA_M64R2) {
+               if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
+                                   MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
 #ifdef CONFIG_MIPS_CPU_SCACHE
                        if (mips_sc_init ()) {
                                scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
index 93d937b4b1ba6fdc01460b2b55e586fbd10dda10..df96da7e939b540f9b1b9c73dae3f73162845d8e 100644 (file)
@@ -98,10 +98,8 @@ static inline int __init mips_sc_probe(void)
        c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 
        /* Ignore anything but MIPSxx processors */
-       if (c->isa_level != MIPS_CPU_ISA_M32R1 &&
-           c->isa_level != MIPS_CPU_ISA_M32R2 &&
-           c->isa_level != MIPS_CPU_ISA_M64R1 &&
-           c->isa_level != MIPS_CPU_ISA_M64R2)
+       if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
+                             MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)))
                return 0;
 
        /* Does this MIPS32/MIPS64 CPU have a config2 register? */
index 38a80c83fd6743c1a2e025d83b7f02d02c2f6bd5..d1faece21b6a78f4c79e20e3cfbaec448d281fad 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/tlbmisc.h>
 
-#ifdef CONFIG_DEBUG_PCI
+#ifdef CONFIG_PCI_DEBUG
 #define DBG(x...) printk(KERN_DEBUG x)
 #else
 #define DBG(x...) do {} while (0)
@@ -162,7 +162,7 @@ static int config_access(unsigned char access_type, struct pci_bus *bus,
        if (status & (1 << 29)) {
                *data = 0xffffffff;
                error = -1;
-               DBG("alchemy-pci: master abort on cfg access %d bus %d dev %d",
+               DBG("alchemy-pci: master abort on cfg access %d bus %d dev %d\n",
                    access_type, bus->number, device);
        } else if ((status >> 28) & 0xf) {
                DBG("alchemy-pci: PCI ERR detected: dev %d, status %lx\n",
index 0872f12f268d427ef4b9eac26d4498b9985d1beb..594e60d6a43b256d5f65f04e751f624610b41b3d 100644 (file)
@@ -115,7 +115,6 @@ static void pcibios_scanbus(struct pci_controller *hose)
                        pci_bus_assign_resources(bus);
                        pci_enable_bridges(bus);
                }
-               bus->dev.of_node = hose->of_node;
        }
 }
 
@@ -169,6 +168,13 @@ void pci_load_of_ranges(struct pci_controller *hose, struct device_node *node)
                }
        }
 }
+
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
+{
+       struct pci_controller *hose = bus->sysdata;
+
+       return of_node_get(hose->of_node);
+}
 #endif
 
 static DEFINE_MUTEX(pci_scan_mutex);
index 01d95e2f058184b33e3fac4b3ca9ff2c7a2932b6..113e28206503ae55e8915d7382d17dc059a20eee 100644 (file)
@@ -65,8 +65,10 @@ ifndef CONFIG_FUNCTION_TRACER
 endif
 
 # Use long jumps instead of long branches (needed if your linker fails to
-# link a too big vmlinux executable)
-cflags-$(CONFIG_MLONGCALLS)    += -mlong-calls
+# link a too big vmlinux executable). Not enabled for building modules.
+ifdef CONFIG_MLONGCALLS
+KBUILD_CFLAGS_KERNEL += -mlong-calls
+endif
 
 # select which processor to optimise for
 cflags-$(CONFIG_PA7100)                += -march=1.1 -mschedule=7100
index 79f694f3ad9bf96de1d2f73ed39efb6c7819f20c..f0e2784e7ccacd6c6d0856ce87d1f1d26e81c083 100644 (file)
@@ -140,7 +140,10 @@ static inline void *kmap(struct page *page)
        return page_address(page);
 }
 
-#define kunmap(page)                   kunmap_parisc(page_address(page))
+static inline void kunmap(struct page *page)
+{
+       kunmap_parisc(page_address(page));
+}
 
 static inline void *kmap_atomic(struct page *page)
 {
index 7df49fad29f937bba828dd185b85af13602552ad..1e40d7f86be389a3d8c0cff976784fca04489285 100644 (file)
@@ -16,6 +16,8 @@
 #include <asm/processor.h>
 #include <asm/cache.h>
 
+extern spinlock_t pa_dbit_lock;
+
 /*
  * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel
  * memory.  For the return value to be meaningful, ADDR must be >=
@@ -44,8 +46,11 @@ extern void purge_tlb_entries(struct mm_struct *, unsigned long);
 
 #define set_pte_at(mm, addr, ptep, pteval)                      \
        do {                                                    \
+               unsigned long flags;                            \
+               spin_lock_irqsave(&pa_dbit_lock, flags);        \
                set_pte(ptep, pteval);                          \
                purge_tlb_entries(mm, addr);                    \
+               spin_unlock_irqrestore(&pa_dbit_lock, flags);   \
        } while (0)
 
 #endif /* !__ASSEMBLY__ */
@@ -435,48 +440,46 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);
 
 static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
-#ifdef CONFIG_SMP
+       pte_t pte;
+       unsigned long flags;
+
        if (!pte_young(*ptep))
                return 0;
-       return test_and_clear_bit(xlate_pabit(_PAGE_ACCESSED_BIT), &pte_val(*ptep));
-#else
-       pte_t pte = *ptep;
-       if (!pte_young(pte))
+
+       spin_lock_irqsave(&pa_dbit_lock, flags);
+       pte = *ptep;
+       if (!pte_young(pte)) {
+               spin_unlock_irqrestore(&pa_dbit_lock, flags);
                return 0;
-       set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte));
+       }
+       set_pte(ptep, pte_mkold(pte));
+       purge_tlb_entries(vma->vm_mm, addr);
+       spin_unlock_irqrestore(&pa_dbit_lock, flags);
        return 1;
-#endif
 }
 
-extern spinlock_t pa_dbit_lock;
-
 struct mm_struct;
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        pte_t old_pte;
+       unsigned long flags;
 
-       spin_lock(&pa_dbit_lock);
+       spin_lock_irqsave(&pa_dbit_lock, flags);
        old_pte = *ptep;
        pte_clear(mm,addr,ptep);
-       spin_unlock(&pa_dbit_lock);
+       purge_tlb_entries(mm, addr);
+       spin_unlock_irqrestore(&pa_dbit_lock, flags);
 
        return old_pte;
 }
 
 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
-#ifdef CONFIG_SMP
-       unsigned long new, old;
-
-       do {
-               old = pte_val(*ptep);
-               new = pte_val(pte_wrprotect(__pte (old)));
-       } while (cmpxchg((unsigned long *) ptep, old, new) != old);
+       unsigned long flags;
+       spin_lock_irqsave(&pa_dbit_lock, flags);
+       set_pte(ptep, pte_wrprotect(*ptep));
        purge_tlb_entries(mm, addr);
-#else
-       pte_t old_pte = *ptep;
-       set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
-#endif
+       spin_unlock_irqrestore(&pa_dbit_lock, flags);
 }
 
 #define pte_same(A,B)  (pte_val(A) == pte_val(B))
index 4ba2c93770f1f47c83226dc97b6e25c89d9b0bd6..e0a82358517e032677cd563ae7aad33e37fef11f 100644 (file)
@@ -181,30 +181,24 @@ struct exception_data {
 #if !defined(CONFIG_64BIT)
 
 #define __put_kernel_asm64(__val,ptr) do {                 \
-       u64 __val64 = (u64)(__val);                         \
-       u32 hi = (__val64) >> 32;                           \
-       u32 lo = (__val64) & 0xffffffff;                    \
        __asm__ __volatile__ (                              \
                "\n1:\tstw %2,0(%1)"                        \
-               "\n2:\tstw %3,4(%1)\n\t"                    \
+               "\n2:\tstw %R2,4(%1)\n\t"                   \
                ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\
                ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\
                : "=r"(__pu_err)                            \
-               : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
+               : "r"(ptr), "r"(__val), "0"(__pu_err) \
                : "r1");                                    \
 } while (0)
 
 #define __put_user_asm64(__val,ptr) do {                   \
-       u64 __val64 = (u64)(__val);                         \
-       u32 hi = (__val64) >> 32;                           \
-       u32 lo = (__val64) & 0xffffffff;                    \
        __asm__ __volatile__ (                              \
                "\n1:\tstw %2,0(%%sr3,%1)"                  \
-               "\n2:\tstw %3,4(%%sr3,%1)\n\t"              \
+               "\n2:\tstw %R2,4(%%sr3,%1)\n\t"             \
                ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\
                ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\
                : "=r"(__pu_err)                            \
-               : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
+               : "r"(ptr), "r"(__val), "0"(__pu_err) \
                : "r1");                                    \
 } while (0)
 
index 4b12890642eb84289abd01772a5ee9121616aeec..83ded26cad065af6cda1d1dc725dec381e48a669 100644 (file)
@@ -421,14 +421,11 @@ void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
        /* Note: purge_tlb_entries can be called at startup with
           no context.  */
 
-       /* Disable preemption while we play with %sr1.  */
-       preempt_disable();
-       mtsp(mm->context, 1);
        purge_tlb_start(flags);
+       mtsp(mm->context, 1);
        pdtlb(addr);
        pitlb(addr);
        purge_tlb_end(flags);
-       preempt_enable();
 }
 EXPORT_SYMBOL(purge_tlb_entries);
 
index 6795dc6c995f7fbbcef5d6128e4ae707eb39d748..568b2c61ea0208de80bcd1f5fdc54f7aafa95a30 100644 (file)
@@ -120,11 +120,13 @@ extern void __ashrdi3(void);
 extern void __ashldi3(void);
 extern void __lshrdi3(void);
 extern void __muldi3(void);
+extern void __ucmpdi2(void);
 
 EXPORT_SYMBOL(__ashrdi3);
 EXPORT_SYMBOL(__ashldi3);
 EXPORT_SYMBOL(__lshrdi3);
 EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
 
 asmlinkage void * __canonicalize_funcptr_for_compare(void *);
 EXPORT_SYMBOL(__canonicalize_funcptr_for_compare);
index 5f2e6904d14aecb897773538b1eadd001fde93f5..5651536ac733929b44efe69d131562eab125b215 100644 (file)
@@ -2,6 +2,7 @@
 # Makefile for parisc-specific library files
 #
 
-lib-y  := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o
+lib-y  := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o \
+          ucmpdi2.o
 
 obj-y  := iomap.o
diff --git a/arch/parisc/lib/ucmpdi2.c b/arch/parisc/lib/ucmpdi2.c
new file mode 100644 (file)
index 0000000..149c016
--- /dev/null
@@ -0,0 +1,25 @@
+#include <linux/module.h>
+
+union ull_union {
+       unsigned long long ull;
+       struct {
+               unsigned int high;
+               unsigned int low;
+       } ui;
+};
+
+int __ucmpdi2(unsigned long long a, unsigned long long b)
+{
+       union ull_union au = {.ull = a};
+       union ull_union bu = {.ull = b};
+
+       if (au.ui.high < bu.ui.high)
+               return 0;
+       else if (au.ui.high > bu.ui.high)
+               return 2;
+       if (au.ui.low < bu.ui.low)
+               return 0;
+       else if (au.ui.low > bu.ui.low)
+               return 2;
+       return 1;
+}
index 256c5bf0adb7a87cb0429bc02c435f3cfecbd3b5..04d69c4a5ac2d6326839d8bcf23342ff509926ce 100644 (file)
@@ -304,7 +304,7 @@ syscall_exit_work:
        subi    r12,r12,TI_FLAGS
 
 4:     /* Anything else left to do? */
-       SET_DEFAULT_THREAD_PPR(r3, r9)          /* Set thread.ppr = 3 */
+       SET_DEFAULT_THREAD_PPR(r3, r10)         /* Set thread.ppr = 3 */
        andi.   r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
        beq     .ret_from_except_lite
 
@@ -657,7 +657,7 @@ resume_kernel:
        /* Clear _TIF_EMULATE_STACK_STORE flag */
        lis     r11,_TIF_EMULATE_STACK_STORE@h
        addi    r5,r9,TI_FLAGS
-       ldarx   r4,0,r5
+0:     ldarx   r4,0,r5
        andc    r4,r4,r11
        stdcx.  r4,0,r5
        bne-    0b
index 59dd545fdde188761e140c2f6969b9b9e348662b..16e77a81ab4f29d5090b3f65b600d738fe6ed9cf 100644 (file)
@@ -555,10 +555,12 @@ static inline void tm_recheckpoint_new_task(struct task_struct *new)
                new->thread.regs->msr |=
                        (MSR_FP | new->thread.fpexc_mode);
        }
+#ifdef CONFIG_ALTIVEC
        if (msr & MSR_VEC) {
                do_load_up_transact_altivec(&new->thread);
                new->thread.regs->msr |= MSR_VEC;
        }
+#endif
        /* We may as well turn on VSX too since all the state is restored now */
        if (msr & MSR_VSX)
                new->thread.regs->msr |= MSR_VSX;
index 3acb28e245b411d65ebcc8c68bfeec802e7f4737..95068bf569adc17cf51d7e32bd650daaba234b17 100644 (file)
@@ -866,10 +866,12 @@ static long restore_tm_user_regs(struct pt_regs *regs,
                do_load_up_transact_fpu(&current->thread);
                regs->msr |= (MSR_FP | current->thread.fpexc_mode);
        }
+#ifdef CONFIG_ALTIVEC
        if (msr & MSR_VEC) {
                do_load_up_transact_altivec(&current->thread);
                regs->msr |= MSR_VEC;
        }
+#endif
 
        return 0;
 }
index 995f8543cb57ed869b603fee7c5d178c1d1af066..c1794286098ca2f78c5e32f4c01b0891ca04fc78 100644 (file)
@@ -522,10 +522,12 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
                do_load_up_transact_fpu(&current->thread);
                regs->msr |= (MSR_FP | current->thread.fpexc_mode);
        }
+#ifdef CONFIG_ALTIVEC
        if (msr & MSR_VEC) {
                do_load_up_transact_altivec(&current->thread);
                regs->msr |= MSR_VEC;
        }
+#endif
 
        return err;
 }
index 84dbace657ce197fb7a71d17e61042e87fb271c8..2da67e7a16d58650e10a0b6113b705bd88a6f2d3 100644 (file)
@@ -309,6 +309,7 @@ _GLOBAL(tm_recheckpoint)
        or      r5, r6, r5                      /* Set MSR.FP+.VSX/.VEC */
        mtmsr   r5
 
+#ifdef CONFIG_ALTIVEC
        /* FP and VEC registers:  These are recheckpointed from thread.fpr[]
         * and thread.vr[] respectively.  The thread.transact_fpr[] version
         * is more modern, and will be loaded subsequently by any FPUnavailable
@@ -323,6 +324,7 @@ _GLOBAL(tm_recheckpoint)
        REST_32VRS(0, r5, r3)                   /* r5 scratch, r3 THREAD ptr */
        ld      r5, THREAD_VRSAVE(r3)
        mtspr   SPRN_VRSAVE, r5
+#endif
 
 dont_restore_vec:
        andi.   r0, r4, MSR_FP
index 41cefd43655ff2616478778295072a1509d0f1ad..33db48a8ce241e1ee9ee0bce50bf991bb550b332 100644 (file)
 #define E500_PID_NUM   3
 #define E500_TLB_NUM   2
 
-#define E500_TLB_VALID 1
-#define E500_TLB_BITMAP 2
+/* entry is mapped somewhere in host TLB */
+#define E500_TLB_VALID         (1 << 0)
+/* TLB1 entry is mapped by host TLB1, tracked by bitmaps */
+#define E500_TLB_BITMAP                (1 << 1)
+/* TLB1 entry is mapped by host TLB0 */
 #define E500_TLB_TLB0          (1 << 2)
 
 struct tlbe_ref {
-       pfn_t pfn;
-       unsigned int flags; /* E500_TLB_* */
+       pfn_t pfn;              /* valid only for TLB0, except briefly */
+       unsigned int flags;     /* E500_TLB_* */
 };
 
 struct tlbe_priv {
-       struct tlbe_ref ref; /* TLB0 only -- TLB1 uses tlb_refs */
+       struct tlbe_ref ref;
 };
 
 #ifdef CONFIG_KVM_E500V2
@@ -63,17 +66,6 @@ struct kvmppc_vcpu_e500 {
 
        unsigned int gtlb_nv[E500_TLB_NUM];
 
-       /*
-        * information associated with each host TLB entry --
-        * TLB1 only for now.  If/when guest TLB1 entries can be
-        * mapped with host TLB0, this will be used for that too.
-        *
-        * We don't want to use this for guest TLB0 because then we'd
-        * have the overhead of doing the translation again even if
-        * the entry is still in the guest TLB (e.g. we swapped out
-        * and back, and our host TLB entries got evicted).
-        */
-       struct tlbe_ref *tlb_refs[E500_TLB_NUM];
        unsigned int host_tlb1_nv;
 
        u32 svr;
index a222edfb9a9bce72e7d642b05853398b493bc679..1c6a9d729df4a26ca3ad6c9f1c94008d681f7d42 100644 (file)
@@ -193,8 +193,11 @@ void inval_gtlbe_on_host(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
        struct tlbe_ref *ref = &vcpu_e500->gtlb_priv[tlbsel][esel].ref;
 
        /* Don't bother with unmapped entries */
-       if (!(ref->flags & E500_TLB_VALID))
-               return;
+       if (!(ref->flags & E500_TLB_VALID)) {
+               WARN(ref->flags & (E500_TLB_BITMAP | E500_TLB_TLB0),
+                    "%s: flags %x\n", __func__, ref->flags);
+               WARN_ON(tlbsel == 1 && vcpu_e500->g2h_tlb1_map[esel]);
+       }
 
        if (tlbsel == 1 && ref->flags & E500_TLB_BITMAP) {
                u64 tmp = vcpu_e500->g2h_tlb1_map[esel];
@@ -248,7 +251,7 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
                                         pfn_t pfn)
 {
        ref->pfn = pfn;
-       ref->flags = E500_TLB_VALID;
+       ref->flags |= E500_TLB_VALID;
 
        if (tlbe_is_writable(gtlbe))
                kvm_set_pfn_dirty(pfn);
@@ -257,6 +260,7 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
 static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
 {
        if (ref->flags & E500_TLB_VALID) {
+               /* FIXME: don't log bogus pfn for TLB1 */
                trace_kvm_booke206_ref_release(ref->pfn, ref->flags);
                ref->flags = 0;
        }
@@ -274,36 +278,23 @@ static void clear_tlb1_bitmap(struct kvmppc_vcpu_e500 *vcpu_e500)
 
 static void clear_tlb_privs(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
-       int tlbsel = 0;
-       int i;
-
-       for (i = 0; i < vcpu_e500->gtlb_params[tlbsel].entries; i++) {
-               struct tlbe_ref *ref =
-                       &vcpu_e500->gtlb_priv[tlbsel][i].ref;
-               kvmppc_e500_ref_release(ref);
-       }
-}
-
-static void clear_tlb_refs(struct kvmppc_vcpu_e500 *vcpu_e500)
-{
-       int stlbsel = 1;
+       int tlbsel;
        int i;
 
-       kvmppc_e500_tlbil_all(vcpu_e500);
-
-       for (i = 0; i < host_tlb_params[stlbsel].entries; i++) {
-               struct tlbe_ref *ref =
-                       &vcpu_e500->tlb_refs[stlbsel][i];
-               kvmppc_e500_ref_release(ref);
+       for (tlbsel = 0; tlbsel <= 1; tlbsel++) {
+               for (i = 0; i < vcpu_e500->gtlb_params[tlbsel].entries; i++) {
+                       struct tlbe_ref *ref =
+                               &vcpu_e500->gtlb_priv[tlbsel][i].ref;
+                       kvmppc_e500_ref_release(ref);
+               }
        }
-
-       clear_tlb_privs(vcpu_e500);
 }
 
 void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       clear_tlb_refs(vcpu_e500);
+       kvmppc_e500_tlbil_all(vcpu_e500);
+       clear_tlb_privs(vcpu_e500);
        clear_tlb1_bitmap(vcpu_e500);
 }
 
@@ -458,8 +449,6 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
                gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
        }
 
-       /* Drop old ref and setup new one. */
-       kvmppc_e500_ref_release(ref);
        kvmppc_e500_ref_setup(ref, gtlbe, pfn);
 
        kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
@@ -507,14 +496,15 @@ static int kvmppc_e500_tlb1_map_tlb1(struct kvmppc_vcpu_e500 *vcpu_e500,
        if (unlikely(vcpu_e500->host_tlb1_nv >= tlb1_max_shadow_size()))
                vcpu_e500->host_tlb1_nv = 0;
 
-       vcpu_e500->tlb_refs[1][sesel] = *ref;
-       vcpu_e500->g2h_tlb1_map[esel] |= (u64)1 << sesel;
-       vcpu_e500->gtlb_priv[1][esel].ref.flags |= E500_TLB_BITMAP;
        if (vcpu_e500->h2g_tlb1_rmap[sesel]) {
-               unsigned int idx = vcpu_e500->h2g_tlb1_rmap[sesel];
+               unsigned int idx = vcpu_e500->h2g_tlb1_rmap[sesel] - 1;
                vcpu_e500->g2h_tlb1_map[idx] &= ~(1ULL << sesel);
        }
-       vcpu_e500->h2g_tlb1_rmap[sesel] = esel;
+
+       vcpu_e500->gtlb_priv[1][esel].ref.flags |= E500_TLB_BITMAP;
+       vcpu_e500->g2h_tlb1_map[esel] |= (u64)1 << sesel;
+       vcpu_e500->h2g_tlb1_rmap[sesel] = esel + 1;
+       WARN_ON(!(ref->flags & E500_TLB_VALID));
 
        return sesel;
 }
@@ -526,13 +516,12 @@ static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500,
                u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe,
                struct kvm_book3e_206_tlb_entry *stlbe, int esel)
 {
-       struct tlbe_ref ref;
+       struct tlbe_ref *ref = &vcpu_e500->gtlb_priv[1][esel].ref;
        int sesel;
        int r;
 
-       ref.flags = 0;
        r = kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, stlbe,
-                                  &ref);
+                                  ref);
        if (r)
                return r;
 
@@ -544,7 +533,7 @@ static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500,
        }
 
        /* Otherwise map into TLB1 */
-       sesel = kvmppc_e500_tlb1_map_tlb1(vcpu_e500, &ref, esel);
+       sesel = kvmppc_e500_tlb1_map_tlb1(vcpu_e500, ref, esel);
        write_stlbe(vcpu_e500, gtlbe, stlbe, 1, sesel);
 
        return 0;
@@ -565,7 +554,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
        case 0:
                priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
 
-               /* Triggers after clear_tlb_refs or on initial mapping */
+               /* Triggers after clear_tlb_privs or on initial mapping */
                if (!(priv->ref.flags & E500_TLB_VALID)) {
                        kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
                } else {
@@ -665,35 +654,16 @@ int e500_mmu_host_init(struct kvmppc_vcpu_e500 *vcpu_e500)
                host_tlb_params[0].entries / host_tlb_params[0].ways;
        host_tlb_params[1].sets = 1;
 
-       vcpu_e500->tlb_refs[0] =
-               kzalloc(sizeof(struct tlbe_ref) * host_tlb_params[0].entries,
-                       GFP_KERNEL);
-       if (!vcpu_e500->tlb_refs[0])
-               goto err;
-
-       vcpu_e500->tlb_refs[1] =
-               kzalloc(sizeof(struct tlbe_ref) * host_tlb_params[1].entries,
-                       GFP_KERNEL);
-       if (!vcpu_e500->tlb_refs[1])
-               goto err;
-
        vcpu_e500->h2g_tlb1_rmap = kzalloc(sizeof(unsigned int) *
                                           host_tlb_params[1].entries,
                                           GFP_KERNEL);
        if (!vcpu_e500->h2g_tlb1_rmap)
-               goto err;
+               return -EINVAL;
 
        return 0;
-
-err:
-       kfree(vcpu_e500->tlb_refs[0]);
-       kfree(vcpu_e500->tlb_refs[1]);
-       return -EINVAL;
 }
 
 void e500_mmu_host_uninit(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
        kfree(vcpu_e500->h2g_tlb1_rmap);
-       kfree(vcpu_e500->tlb_refs[0]);
-       kfree(vcpu_e500->tlb_refs[1]);
 }
index 1f89d26e65fb72534e130ed755bfe3874740316f..2f4baa074b2ebf0bf9cfe497055afbe9460ec4a5 100644 (file)
@@ -108,6 +108,8 @@ void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
 {
 }
 
+static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu_on_cpu);
+
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
@@ -136,8 +138,11 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        mtspr(SPRN_GDEAR, vcpu->arch.shared->dar);
        mtspr(SPRN_GESR, vcpu->arch.shared->esr);
 
-       if (vcpu->arch.oldpir != mfspr(SPRN_PIR))
+       if (vcpu->arch.oldpir != mfspr(SPRN_PIR) ||
+           __get_cpu_var(last_vcpu_on_cpu) != vcpu) {
                kvmppc_e500_tlbil_all(vcpu_e500);
+               __get_cpu_var(last_vcpu_on_cpu) = vcpu;
+       }
 
        kvmppc_load_guest_fp(vcpu);
 }
index 0da39fed355aa25fc17e516cf52d66042ddcc0e4..299731e9036b5e4361d7a49ca52938d0953d96e4 100644 (file)
@@ -186,7 +186,13 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
                                           (0x1UL << 4), &dummy1, &dummy2);
                if (lpar_rc == H_SUCCESS)
                        return i;
-               BUG_ON(lpar_rc != H_NOT_FOUND);
+
+               /*
+                * The test for adjunct partition is performed before the
+                * ANDCOND test.  H_RESOURCE may be returned, so we need to
+                * check for that as well.
+                */
+               BUG_ON(lpar_rc != H_NOT_FOUND && lpar_rc != H_RESOURCE);
 
                slot_offset++;
                slot_offset &= 0x7;
index eb8fb629f00bba774b195a475471d630d6bd8bd0..bda6ba6f3cf52d645ad337fea070b730dc46f438 100644 (file)
@@ -375,19 +375,6 @@ config PACK_STACK
 
          Say Y if you are unsure.
 
-config SMALL_STACK
-       def_bool n
-       prompt "Use 8kb for kernel stack instead of 16kb"
-       depends on PACK_STACK && 64BIT && !LOCKDEP
-       help
-         If you say Y here and the compiler supports the -mkernel-backchain
-         option the kernel will use a smaller kernel stack size. The reduced
-         size is 8kb instead of 16kb. This allows to run more threads on a
-         system and reduces the pressure on the memory management for higher
-         order page allocations.
-
-         Say N if you are unsure.
-
 config CHECK_STACK
        def_bool y
        prompt "Detect kernel stack overflow"
index 7e3ce78d42902e636de522d8f568e00e0f75701f..a7d68a467ce884d77a9c615db5fcba0cdb251e71 100644 (file)
@@ -55,22 +55,12 @@ cflags-$(CONFIG_FRAME_POINTER) += -fno-optimize-sibling-calls
 ifeq ($(call cc-option-yn,-mkernel-backchain),y)
 cflags-$(CONFIG_PACK_STACK)  += -mkernel-backchain -D__PACK_STACK
 aflags-$(CONFIG_PACK_STACK)  += -D__PACK_STACK
-cflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
-aflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
-ifdef CONFIG_SMALL_STACK
-STACK_SIZE := $(shell echo $$(($(STACK_SIZE)/2)) )
-endif
 endif
 
 # new style option for packed stacks
 ifeq ($(call cc-option-yn,-mpacked-stack),y)
 cflags-$(CONFIG_PACK_STACK)  += -mpacked-stack -D__PACK_STACK
 aflags-$(CONFIG_PACK_STACK)  += -D__PACK_STACK
-cflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
-aflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
-ifdef CONFIG_SMALL_STACK
-STACK_SIZE := $(shell echo $$(($(STACK_SIZE)/2)) )
-endif
 endif
 
 ifeq ($(call cc-option-yn,-mstack-size=8192 -mstack-guard=128),y)
index 9fd4a40c67521296cbbc22d5da23340bc6910284..bb5dd496614f1871a72e1f9737c7a30b66982ae8 100644 (file)
@@ -105,9 +105,7 @@ void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
 int hypfs_dbfs_init(void)
 {
        dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
-       if (IS_ERR(dbfs_dir))
-               return PTR_ERR(dbfs_dir);
-       return 0;
+       return PTR_RET(dbfs_dir);
 }
 
 void hypfs_dbfs_exit(void)
index 15422933c60ba4b4d9ca12e2187d3154bff4656f..4d8604e311f3aaf6b1799bd78760bcc52a5befab 100644 (file)
@@ -61,8 +61,6 @@ extern const char _sb_findmap[];
 
 #ifndef CONFIG_64BIT
 
-#define __BITOPS_ALIGN         3
-#define __BITOPS_WORDSIZE      32
 #define __BITOPS_OR            "or"
 #define __BITOPS_AND           "nr"
 #define __BITOPS_XOR           "xr"
@@ -81,8 +79,6 @@ extern const char _sb_findmap[];
 
 #else /* CONFIG_64BIT */
 
-#define __BITOPS_ALIGN         7
-#define __BITOPS_WORDSIZE      64
 #define __BITOPS_OR            "ogr"
 #define __BITOPS_AND           "ngr"
 #define __BITOPS_XOR           "xgr"
@@ -101,8 +97,7 @@ extern const char _sb_findmap[];
 
 #endif /* CONFIG_64BIT */
 
-#define __BITOPS_WORDS(bits) (((bits)+__BITOPS_WORDSIZE-1)/__BITOPS_WORDSIZE)
-#define __BITOPS_BARRIER() asm volatile("" : : : "memory")
+#define __BITOPS_WORDS(bits) (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG)
 
 #ifdef CONFIG_SMP
 /*
@@ -114,9 +109,9 @@ static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
        addr = (unsigned long) ptr;
        /* calculate address for CS */
-       addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+       addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
        /* make OR mask */
-       mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+       mask = 1UL << (nr & (BITS_PER_LONG - 1));
        /* Do the atomic update. */
        __BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
 }
@@ -130,9 +125,9 @@ static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
        addr = (unsigned long) ptr;
        /* calculate address for CS */
-       addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+       addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
        /* make AND mask */
-       mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1)));
+       mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
        /* Do the atomic update. */
        __BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
 }
@@ -146,9 +141,9 @@ static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
        addr = (unsigned long) ptr;
        /* calculate address for CS */
-       addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+       addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
        /* make XOR mask */
-       mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+       mask = 1UL << (nr & (BITS_PER_LONG - 1));
        /* Do the atomic update. */
        __BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
 }
@@ -163,12 +158,12 @@ test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
        addr = (unsigned long) ptr;
        /* calculate address for CS */
-       addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+       addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
        /* make OR/test mask */
-       mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+       mask = 1UL << (nr & (BITS_PER_LONG - 1));
        /* Do the atomic update. */
        __BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
-       __BITOPS_BARRIER();
+       barrier();
        return (old & mask) != 0;
 }
 
@@ -182,12 +177,12 @@ test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
        addr = (unsigned long) ptr;
        /* calculate address for CS */
-       addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+       addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
        /* make AND/test mask */
-       mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1)));
+       mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
        /* Do the atomic update. */
        __BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
-       __BITOPS_BARRIER();
+       barrier();
        return (old ^ new) != 0;
 }
 
@@ -201,12 +196,12 @@ test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
        addr = (unsigned long) ptr;
        /* calculate address for CS */
-       addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+       addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
        /* make XOR/test mask */
-       mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+       mask = 1UL << (nr & (BITS_PER_LONG - 1));
        /* Do the atomic update. */
        __BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
-       __BITOPS_BARRIER();
+       barrier();
        return (old & mask) != 0;
 }
 #endif /* CONFIG_SMP */
@@ -218,7 +213,7 @@ static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
 {
        unsigned long addr;
 
-       addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+       addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
        asm volatile(
                "       oc      %O0(1,%R0),%1"
                : "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc" );
@@ -229,7 +224,7 @@ __constant_set_bit(const unsigned long nr, volatile unsigned long *ptr)
 {
        unsigned long addr;
 
-       addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+       addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
        *(unsigned char *) addr |= 1 << (nr & 7);
 }
 
@@ -246,7 +241,7 @@ __clear_bit(unsigned long nr, volatile unsigned long *ptr)
 {
        unsigned long addr;
 
-       addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+       addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
        asm volatile(
                "       nc      %O0(1,%R0),%1"
                : "=Q" (*(char *) addr) : "Q" (_ni_bitmap[nr & 7]) : "cc" );
@@ -257,7 +252,7 @@ __constant_clear_bit(const unsigned long nr, volatile unsigned long *ptr)
 {
        unsigned long addr;
 
-       addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+       addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
        *(unsigned char *) addr &= ~(1 << (nr & 7));
 }
 
@@ -273,7 +268,7 @@ static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
 {
        unsigned long addr;
 
-       addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+       addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
        asm volatile(
                "       xc      %O0(1,%R0),%1"
                : "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc" );
@@ -284,7 +279,7 @@ __constant_change_bit(const unsigned long nr, volatile unsigned long *ptr)
 {
        unsigned long addr;
 
-       addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+       addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
        *(unsigned char *) addr ^= 1 << (nr & 7);
 }
 
@@ -302,7 +297,7 @@ test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr)
        unsigned long addr;
        unsigned char ch;
 
-       addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+       addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
        ch = *(unsigned char *) addr;
        asm volatile(
                "       oc      %O0(1,%R0),%1"
@@ -321,7 +316,7 @@ test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr)
        unsigned long addr;
        unsigned char ch;
 
-       addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+       addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
        ch = *(unsigned char *) addr;
        asm volatile(
                "       nc      %O0(1,%R0),%1"
@@ -340,7 +335,7 @@ test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr)
        unsigned long addr;
        unsigned char ch;
 
-       addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+       addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
        ch = *(unsigned char *) addr;
        asm volatile(
                "       xc      %O0(1,%R0),%1"
@@ -376,7 +371,7 @@ static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr
        unsigned long addr;
        unsigned char ch;
 
-       addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+       addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
        ch = *(volatile unsigned char *) addr;
        return (ch >> (nr & 7)) & 1;
 }
@@ -384,7 +379,7 @@ static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr
 static inline int 
 __constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
     return (((volatile char *) addr)
-           [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7))) != 0;
+           [(nr^(BITS_PER_LONG-8))>>3] & (1<<(nr&7))) != 0;
 }
 
 #define test_bit(nr,addr) \
@@ -693,18 +688,18 @@ static inline int find_next_bit_left(const unsigned long *addr,
 
        if (offset >= size)
                return size;
-       bit = offset & (__BITOPS_WORDSIZE - 1);
+       bit = offset & (BITS_PER_LONG - 1);
        offset -= bit;
        size -= offset;
-       p = addr + offset / __BITOPS_WORDSIZE;
+       p = addr + offset / BITS_PER_LONG;
        if (bit) {
                set = __flo_word(0, *p & (~0UL << bit));
                if (set >= size)
                        return size + offset;
-               if (set < __BITOPS_WORDSIZE)
+               if (set < BITS_PER_LONG)
                        return set + offset;
-               offset += __BITOPS_WORDSIZE;
-               size -= __BITOPS_WORDSIZE;
+               offset += BITS_PER_LONG;
+               size -= BITS_PER_LONG;
                p++;
        }
        return offset + find_first_bit_left(p, size);
@@ -736,22 +731,22 @@ static inline int find_next_zero_bit (const unsigned long * addr,
 
        if (offset >= size)
                return size;
-       bit = offset & (__BITOPS_WORDSIZE - 1);
+       bit = offset & (BITS_PER_LONG - 1);
        offset -= bit;
        size -= offset;
-       p = addr + offset / __BITOPS_WORDSIZE;
+       p = addr + offset / BITS_PER_LONG;
        if (bit) {
                /*
-                * __ffz_word returns __BITOPS_WORDSIZE
+                * __ffz_word returns BITS_PER_LONG
                 * if no zero bit is present in the word.
                 */
                set = __ffz_word(bit, *p >> bit);
                if (set >= size)
                        return size + offset;
-               if (set < __BITOPS_WORDSIZE)
+               if (set < BITS_PER_LONG)
                        return set + offset;
-               offset += __BITOPS_WORDSIZE;
-               size -= __BITOPS_WORDSIZE;
+               offset += BITS_PER_LONG;
+               size -= BITS_PER_LONG;
                p++;
        }
        return offset + find_first_zero_bit(p, size);
@@ -773,22 +768,22 @@ static inline int find_next_bit (const unsigned long * addr,
 
        if (offset >= size)
                return size;
-       bit = offset & (__BITOPS_WORDSIZE - 1);
+       bit = offset & (BITS_PER_LONG - 1);
        offset -= bit;
        size -= offset;
-       p = addr + offset / __BITOPS_WORDSIZE;
+       p = addr + offset / BITS_PER_LONG;
        if (bit) {
                /*
-                * __ffs_word returns __BITOPS_WORDSIZE
+                * __ffs_word returns BITS_PER_LONG
                 * if no one bit is present in the word.
                 */
                set = __ffs_word(0, *p & (~0UL << bit));
                if (set >= size)
                        return size + offset;
-               if (set < __BITOPS_WORDSIZE)
+               if (set < BITS_PER_LONG)
                        return set + offset;
-               offset += __BITOPS_WORDSIZE;
-               size -= __BITOPS_WORDSIZE;
+               offset += BITS_PER_LONG;
+               size -= BITS_PER_LONG;
                p++;
        }
        return offset + find_first_bit(p, size);
@@ -843,22 +838,22 @@ static inline int find_next_zero_bit_le(void *vaddr, unsigned long size,
 
         if (offset >= size)
                 return size;
-       bit = offset & (__BITOPS_WORDSIZE - 1);
+       bit = offset & (BITS_PER_LONG - 1);
        offset -= bit;
        size -= offset;
-       p = addr + offset / __BITOPS_WORDSIZE;
+       p = addr + offset / BITS_PER_LONG;
         if (bit) {
                /*
-                * s390 version of ffz returns __BITOPS_WORDSIZE
+                * s390 version of ffz returns BITS_PER_LONG
                 * if no zero bit is present in the word.
                 */
                set = __ffz_word(bit, __load_ulong_le(p, 0) >> bit);
                if (set >= size)
                        return size + offset;
-               if (set < __BITOPS_WORDSIZE)
+               if (set < BITS_PER_LONG)
                        return set + offset;
-               offset += __BITOPS_WORDSIZE;
-               size -= __BITOPS_WORDSIZE;
+               offset += BITS_PER_LONG;
+               size -= BITS_PER_LONG;
                p++;
         }
        return offset + find_first_zero_bit_le(p, size);
@@ -885,22 +880,22 @@ static inline int find_next_bit_le(void *vaddr, unsigned long size,
 
        if (offset >= size)
                return size;
-       bit = offset & (__BITOPS_WORDSIZE - 1);
+       bit = offset & (BITS_PER_LONG - 1);
        offset -= bit;
        size -= offset;
-       p = addr + offset / __BITOPS_WORDSIZE;
+       p = addr + offset / BITS_PER_LONG;
        if (bit) {
                /*
-                * s390 version of ffz returns __BITOPS_WORDSIZE
+                * s390 version of ffz returns BITS_PER_LONG
                 * if no zero bit is present in the word.
                 */
                set = __ffs_word(0, __load_ulong_le(p, 0) & (~0UL << bit));
                if (set >= size)
                        return size + offset;
-               if (set < __BITOPS_WORDSIZE)
+               if (set < BITS_PER_LONG)
                        return set + offset;
-               offset += __BITOPS_WORDSIZE;
-               size -= __BITOPS_WORDSIZE;
+               offset += BITS_PER_LONG;
+               size -= BITS_PER_LONG;
                p++;
        }
        return offset + find_first_bit_le(p, size);
index e6061617a50b071ed2a8b4a8da01e562de49d836..f201af8be580ddc876de2f5de96952aaaf493cb5 100644 (file)
@@ -220,7 +220,8 @@ extern void ccw_device_get_id(struct ccw_device *, struct ccw_dev_id *);
 #define to_ccwdrv(n) container_of(n, struct ccw_driver, driver)
 
 extern struct ccw_device *ccw_device_probe_console(void);
-extern int ccw_device_force_console(void);
+extern void ccw_device_wait_idle(struct ccw_device *);
+extern int ccw_device_force_console(struct ccw_device *);
 
 int ccw_device_siosl(struct ccw_device *);
 
index ad2b924167d799f4b410a1bc38e4350656f3da4c..ffb898961c8d28ecdc385443a37d8f523cf72daf 100644 (file)
@@ -296,8 +296,6 @@ static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1,
        return 0;
 }
 
-extern void wait_cons_dev(void);
-
 extern void css_schedule_reprobe(void);
 
 extern void reipl_ccw_dev(struct ccw_dev_id *id);
index f8c6df6cd1f02c93910de5fba976b1c4161879dd..c1e7c646727cd4c71c56a5040a477a6d8618d565 100644 (file)
@@ -70,6 +70,22 @@ typedef u32          compat_ulong_t;
 typedef u64            compat_u64;
 typedef u32            compat_uptr_t;
 
+typedef struct {
+       u32 mask;
+       u32 addr;
+} __aligned(8) psw_compat_t;
+
+typedef struct {
+       psw_compat_t psw;
+       u32 gprs[NUM_GPRS];
+       u32 acrs[NUM_ACRS];
+       u32 orig_gpr2;
+} s390_compat_regs;
+
+typedef struct {
+       u32 gprs_high[NUM_GPRS];
+} s390_compat_regs_high;
+
 struct compat_timespec {
        compat_time_t   tv_sec;
        s32             tv_nsec;
@@ -124,18 +140,33 @@ struct compat_flock64 {
 };
 
 struct compat_statfs {
-       s32             f_type;
-       s32             f_bsize;
-       s32             f_blocks;
-       s32             f_bfree;
-       s32             f_bavail;
-       s32             f_files;
-       s32             f_ffree;
+       u32             f_type;
+       u32             f_bsize;
+       u32             f_blocks;
+       u32             f_bfree;
+       u32             f_bavail;
+       u32             f_files;
+       u32             f_ffree;
+       compat_fsid_t   f_fsid;
+       u32             f_namelen;
+       u32             f_frsize;
+       u32             f_flags;
+       u32             f_spare[4];
+};
+
+struct compat_statfs64 {
+       u32             f_type;
+       u32             f_bsize;
+       u64             f_blocks;
+       u64             f_bfree;
+       u64             f_bavail;
+       u64             f_files;
+       u64             f_ffree;
        compat_fsid_t   f_fsid;
-       s32             f_namelen;
-       s32             f_frsize;
-       s32             f_flags;
-       s32             f_spare[5];
+       u32             f_namelen;
+       u32             f_frsize;
+       u32             f_flags;
+       u32             f_spare[4];
 };
 
 #define COMPAT_RLIM_OLD_INFINITY       0x7fffffff
@@ -248,8 +279,6 @@ static inline int is_compat_task(void)
        return is_32bit_task();
 }
 
-#endif
-
 static inline void __user *arch_compat_alloc_user_space(long len)
 {
        unsigned long stack;
@@ -260,6 +289,8 @@ static inline void __user *arch_compat_alloc_user_space(long len)
        return (void __user *) (stack - len);
 }
 
+#endif
+
 struct compat_ipc64_perm {
        compat_key_t key;
        __compat_uid32_t uid;
index 1bfdf24b85a20bfdab742d9d0c2f04cfb03d9adb..78f4f8711d58a78f0a3e277b13719bd1514f38ea 100644 (file)
  */
 
 #include <asm/ptrace.h>
+#include <asm/compat.h>
+#include <asm/syscall.h>
 #include <asm/user.h>
 
 typedef s390_fp_regs elf_fpregset_t;
@@ -180,18 +182,31 @@ extern unsigned long elf_hwcap;
 extern char elf_platform[];
 #define ELF_PLATFORM (elf_platform)
 
-#ifdef CONFIG_64BIT
+#ifndef CONFIG_COMPAT
+#define SET_PERSONALITY(ex) \
+do {                                                           \
+       set_personality(PER_LINUX |                             \
+               (current->personality & (~PER_MASK)));          \
+       current_thread_info()->sys_call_table =                 \
+               (unsigned long) &sys_call_table;                \
+} while (0)
+#else /* CONFIG_COMPAT */
 #define SET_PERSONALITY(ex)                                    \
 do {                                                           \
        if (personality(current->personality) != PER_LINUX32)   \
                set_personality(PER_LINUX |                     \
                        (current->personality & ~PER_MASK));    \
-       if ((ex).e_ident[EI_CLASS] == ELFCLASS32)               \
+       if ((ex).e_ident[EI_CLASS] == ELFCLASS32) {             \
                set_thread_flag(TIF_31BIT);                     \
-       else                                                    \
+               current_thread_info()->sys_call_table =         \
+                       (unsigned long) &sys_call_table_emu;    \
+       } else {                                                \
                clear_thread_flag(TIF_31BIT);                   \
+               current_thread_info()->sys_call_table =         \
+                       (unsigned long) &sys_call_table;        \
+       }                                                       \
 } while (0)
-#endif /* CONFIG_64BIT */
+#endif /* CONFIG_COMPAT */
 
 #define STACK_RND_MASK 0x7ffUL
 
index 27cb32185ce1d950e5a6097198a1864a69e6594b..379d96e2105ea1d60f79a4cd881593a188a61c01 100644 (file)
@@ -50,10 +50,6 @@ void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
 #define ioremap_nocache(addr, size)    ioremap(addr, size)
 #define ioremap_wc                     ioremap_nocache
 
-/* TODO: s390 cannot support io_remap_pfn_range... */
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)               \
-       remap_pfn_range(vma, vaddr, pfn, size, prot)
-
 static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
 {
        return (void __iomem *) offset;
index 05333b7f0469772ae265cb82839cb4870cd88718..6c1801235db961363a14512dda7c306ab2d9a724 100644 (file)
@@ -140,6 +140,7 @@ static inline bool zdev_enabled(struct zpci_dev *zdev)
 struct zpci_dev *zpci_alloc_device(void);
 int zpci_create_device(struct zpci_dev *);
 int zpci_enable_device(struct zpci_dev *);
+int zpci_disable_device(struct zpci_dev *);
 void zpci_stop_device(struct zpci_dev *);
 void zpci_free_device(struct zpci_dev *);
 int zpci_scan_device(struct zpci_dev *);
index 6bbec4265b6eb182339fdabdab75114ea32878c8..1ca5d1047c71742f5e3c5681c89a4b98e4e87530 100644 (file)
@@ -7,14 +7,11 @@ extern debug_info_t *pci_debug_msg_id;
 extern debug_info_t *pci_debug_err_id;
 
 #ifdef CONFIG_PCI_DEBUG
-#define zpci_dbg(fmt, args...)                                                 \
-       do {                                                                    \
-               if (pci_debug_msg_id->level >= 2)                               \
-                       debug_sprintf_event(pci_debug_msg_id, 2, fmt , ## args);\
-       } while (0)
+#define zpci_dbg(imp, fmt, args...)                            \
+       debug_sprintf_event(pci_debug_msg_id, imp, fmt, ##args)
 
 #else /* !CONFIG_PCI_DEBUG */
-#define zpci_dbg(fmt, args...) do { } while (0)
+#define zpci_dbg(imp, fmt, args...) do { } while (0)
 #endif
 
 #define zpci_err(text...)                                                      \
index 1486a98d5dad2f95c801bcd85f4450f8f4576215..e6a2bdd4d7059e4e5bfa9e86c77a08554f6cfb1a 100644 (file)
@@ -1,10 +1,6 @@
 #ifndef _ASM_S390_PCI_INSN_H
 #define _ASM_S390_PCI_INSN_H
 
-#include <linux/delay.h>
-
-#define ZPCI_INSN_BUSY_DELAY   1       /* 1 microsecond */
-
 /* Load/Store status codes */
 #define ZPCI_PCI_ST_FUNC_NOT_ENABLED           4
 #define ZPCI_PCI_ST_FUNC_IN_ERR                        8
@@ -82,199 +78,12 @@ struct zpci_fib {
        u64 reserved7;
 } __packed;
 
-/* Modify PCI Function Controls */
-static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
-{
-       u8 cc;
-
-       asm volatile (
-               "       .insn   rxy,0xe300000000d0,%[req],%[fib]\n"
-               "       ipm     %[cc]\n"
-               "       srl     %[cc],28\n"
-               : [cc] "=d" (cc), [req] "+d" (req), [fib] "+Q" (*fib)
-               : : "cc");
-       *status = req >> 24 & 0xff;
-       return cc;
-}
-
-static inline int mpcifc_instr(u64 req, struct zpci_fib *fib)
-{
-       u8 cc, status;
-
-       do {
-               cc = __mpcifc(req, fib, &status);
-               if (cc == 2)
-                       msleep(ZPCI_INSN_BUSY_DELAY);
-       } while (cc == 2);
-
-       if (cc)
-               printk_once(KERN_ERR "%s: error cc: %d  status: %d\n",
-                            __func__, cc, status);
-       return (cc) ? -EIO : 0;
-}
-
-/* Refresh PCI Translations */
-static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
-{
-       register u64 __addr asm("2") = addr;
-       register u64 __range asm("3") = range;
-       u8 cc;
-
-       asm volatile (
-               "       .insn   rre,0xb9d30000,%[fn],%[addr]\n"
-               "       ipm     %[cc]\n"
-               "       srl     %[cc],28\n"
-               : [cc] "=d" (cc), [fn] "+d" (fn)
-               : [addr] "d" (__addr), "d" (__range)
-               : "cc");
-       *status = fn >> 24 & 0xff;
-       return cc;
-}
-
-static inline int rpcit_instr(u64 fn, u64 addr, u64 range)
-{
-       u8 cc, status;
-
-       do {
-               cc = __rpcit(fn, addr, range, &status);
-               if (cc == 2)
-                       udelay(ZPCI_INSN_BUSY_DELAY);
-       } while (cc == 2);
-
-       if (cc)
-               printk_once(KERN_ERR "%s: error cc: %d  status: %d  dma_addr: %Lx  size: %Lx\n",
-                           __func__, cc, status, addr, range);
-       return (cc) ? -EIO : 0;
-}
-
-/* Store PCI function controls */
-static inline u8 __stpcifc(u32 handle, u8 space, struct zpci_fib *fib, u8 *status)
-{
-       u64 fn = (u64) handle << 32 | space << 16;
-       u8 cc;
-
-       asm volatile (
-               "       .insn   rxy,0xe300000000d4,%[fn],%[fib]\n"
-               "       ipm     %[cc]\n"
-               "       srl     %[cc],28\n"
-               : [cc] "=d" (cc), [fn] "+d" (fn), [fib] "=m" (*fib)
-               : : "cc");
-       *status = fn >> 24 & 0xff;
-       return cc;
-}
-
-/* Set Interruption Controls */
-static inline void sic_instr(u16 ctl, char *unused, u8 isc)
-{
-       asm volatile (
-               "       .insn   rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n"
-               : : [ctl] "d" (ctl), [isc] "d" (isc << 27), [u] "Q" (*unused));
-}
-
-/* PCI Load */
-static inline u8 __pcilg(u64 *data, u64 req, u64 offset, u8 *status)
-{
-       register u64 __req asm("2") = req;
-       register u64 __offset asm("3") = offset;
-       u64 __data;
-       u8 cc;
-
-       asm volatile (
-               "       .insn   rre,0xb9d20000,%[data],%[req]\n"
-               "       ipm     %[cc]\n"
-               "       srl     %[cc],28\n"
-               : [cc] "=d" (cc), [data] "=d" (__data), [req] "+d" (__req)
-               :  "d" (__offset)
-               : "cc");
-       *status = __req >> 24 & 0xff;
-       *data = __data;
-       return cc;
-}
-
-static inline int pcilg_instr(u64 *data, u64 req, u64 offset)
-{
-       u8 cc, status;
-
-       do {
-               cc = __pcilg(data, req, offset, &status);
-               if (cc == 2)
-                       udelay(ZPCI_INSN_BUSY_DELAY);
-       } while (cc == 2);
-
-       if (cc) {
-               printk_once(KERN_ERR "%s: error cc: %d  status: %d  req: %Lx  offset: %Lx\n",
-                           __func__, cc, status, req, offset);
-               /* TODO: on IO errors set data to 0xff...
-                * here or in users of pcilg (le conversion)?
-                */
-       }
-       return (cc) ? -EIO : 0;
-}
-
-/* PCI Store */
-static inline u8 __pcistg(u64 data, u64 req, u64 offset, u8 *status)
-{
-       register u64 __req asm("2") = req;
-       register u64 __offset asm("3") = offset;
-       u8 cc;
-
-       asm volatile (
-               "       .insn   rre,0xb9d00000,%[data],%[req]\n"
-               "       ipm     %[cc]\n"
-               "       srl     %[cc],28\n"
-               : [cc] "=d" (cc), [req] "+d" (__req)
-               : "d" (__offset), [data] "d" (data)
-               : "cc");
-       *status = __req >> 24 & 0xff;
-       return cc;
-}
-
-static inline int pcistg_instr(u64 data, u64 req, u64 offset)
-{
-       u8 cc, status;
-
-       do {
-               cc = __pcistg(data, req, offset, &status);
-               if (cc == 2)
-                       udelay(ZPCI_INSN_BUSY_DELAY);
-       } while (cc == 2);
-
-       if (cc)
-               printk_once(KERN_ERR "%s: error cc: %d  status: %d  req: %Lx  offset: %Lx\n",
-                       __func__, cc, status, req, offset);
-       return (cc) ? -EIO : 0;
-}
-
-/* PCI Store Block */
-static inline u8 __pcistb(const u64 *data, u64 req, u64 offset, u8 *status)
-{
-       u8 cc;
-
-       asm volatile (
-               "       .insn   rsy,0xeb00000000d0,%[req],%[offset],%[data]\n"
-               "       ipm     %[cc]\n"
-               "       srl     %[cc],28\n"
-               : [cc] "=d" (cc), [req] "+d" (req)
-               : [offset] "d" (offset), [data] "Q" (*data)
-               : "cc");
-       *status = req >> 24 & 0xff;
-       return cc;
-}
-
-static inline int pcistb_instr(const u64 *data, u64 req, u64 offset)
-{
-       u8 cc, status;
-
-       do {
-               cc = __pcistb(data, req, offset, &status);
-               if (cc == 2)
-                       udelay(ZPCI_INSN_BUSY_DELAY);
-       } while (cc == 2);
 
-       if (cc)
-               printk_once(KERN_ERR "%s: error cc: %d  status: %d  req: %Lx  offset: %Lx\n",
-                           __func__, cc, status, req, offset);
-       return (cc) ? -EIO : 0;
-}
+int s390pci_mod_fc(u64 req, struct zpci_fib *fib);
+int s390pci_refresh_trans(u64 fn, u64 addr, u64 range);
+int s390pci_load(u64 *data, u64 req, u64 offset);
+int s390pci_store(u64 data, u64 req, u64 offset);
+int s390pci_store_block(const u64 *data, u64 req, u64 offset);
+void set_irq_ctrl(u16 ctl, char *unused, u8 isc);
 
 #endif
index 5fd81f31d6c77184ae6cd5e01dff0b1721c31a59..83a9caa6ae530fb1f500d86c3bf207f32f2a8b21 100644 (file)
@@ -36,7 +36,7 @@ static inline RETTYPE zpci_read_##RETTYPE(const volatile void __iomem *addr)  \
        u64 data;                                                               \
        int rc;                                                                 \
                                                                                \
-       rc = pcilg_instr(&data, req, ZPCI_OFFSET(addr));                        \
+       rc = s390pci_load(&data, req, ZPCI_OFFSET(addr));                       \
        if (rc)                                                                 \
                data = -1ULL;                                                   \
        return (RETTYPE) data;                                                  \
@@ -50,7 +50,7 @@ static inline void zpci_write_##VALTYPE(VALTYPE val,                          \
        u64 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, LENGTH);               \
        u64 data = (VALTYPE) val;                                               \
                                                                                \
-       pcistg_instr(data, req, ZPCI_OFFSET(addr));                             \
+       s390pci_store(data, req, ZPCI_OFFSET(addr));                            \
 }
 
 zpci_read(8, u64)
@@ -83,15 +83,18 @@ static inline int zpci_write_single(u64 req, const u64 *data, u64 offset, u8 len
                val = 0;                /* let FW report error */
                break;
        }
-       return pcistg_instr(val, req, offset);
+       return s390pci_store(val, req, offset);
 }
 
 static inline int zpci_read_single(u64 req, u64 *dst, u64 offset, u8 len)
 {
        u64 data;
-       u8 cc;
+       int cc;
+
+       cc = s390pci_load(&data, req, offset);
+       if (cc)
+               goto out;
 
-       cc = pcilg_instr(&data,  req, offset);
        switch (len) {
        case 1:
                *((u8 *) dst) = (u8) data;
@@ -106,12 +109,13 @@ static inline int zpci_read_single(u64 req, u64 *dst, u64 offset, u8 len)
                *((u64 *) dst) = (u64) data;
                break;
        }
+out:
        return cc;
 }
 
 static inline int zpci_write_block(u64 req, const u64 *data, u64 offset)
 {
-       return pcistb_instr(data, req, offset);
+       return s390pci_store_block(data, req, offset);
 }
 
 static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max)
index 4a2930844d43a078492732cf156d392ac10fc29e..4a64c0e5428fdc4956d495d3702365469e1cbd0e 100644 (file)
@@ -57,6 +57,10 @@ extern unsigned long zero_page_mask;
         (((unsigned long)(vaddr)) &zero_page_mask))))
 #define __HAVE_COLOR_ZERO_PAGE
 
+/* TODO: s390 cannot support io_remap_pfn_range... */
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)               \
+       remap_pfn_range(vma, vaddr, pfn, size, prot)
+
 #endif /* !__ASSEMBLY__ */
 
 /*
@@ -344,6 +348,7 @@ extern unsigned long MODULES_END;
 #define _REGION3_ENTRY_CO      0x100   /* change-recording override        */
 
 /* Bits in the segment table entry */
+#define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address       */
 #define _SEGMENT_ENTRY_ORIGIN  ~0x7ffUL/* segment table origin             */
 #define _SEGMENT_ENTRY_RO      0x200   /* page protection bit              */
 #define _SEGMENT_ENTRY_INV     0x20    /* invalid segment table entry      */
@@ -759,6 +764,8 @@ void gmap_disable(struct gmap *gmap);
 int gmap_map_segment(struct gmap *gmap, unsigned long from,
                     unsigned long to, unsigned long length);
 int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
+unsigned long __gmap_translate(unsigned long address, struct gmap *);
+unsigned long gmap_translate(unsigned long address, struct gmap *);
 unsigned long __gmap_fault(unsigned long address, struct gmap *);
 unsigned long gmap_fault(unsigned long address, struct gmap *);
 void gmap_discard(unsigned long from, unsigned long to, struct gmap *);
@@ -1531,7 +1538,8 @@ extern int s390_enable_sie(void);
 /*
  * No page table caches to initialise
  */
-#define pgtable_cache_init()   do { } while (0)
+static inline void pgtable_cache_init(void) { }
+static inline void check_pgt_cache(void) { }
 
 #include <asm-generic/pgtable.h>
 
index 94e749c90230d9f824949429d505625f90f7b4e7..6b499870662f2dddbb14dd613943ef10e6303b89 100644 (file)
@@ -161,7 +161,8 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
 
 extern void show_code(struct pt_regs *regs);
 extern void print_fn_code(unsigned char *code, unsigned long len);
-extern int insn_to_mnemonic(unsigned char *instruction, char buf[8]);
+extern int insn_to_mnemonic(unsigned char *instruction, char *buf,
+                           unsigned int len);
 
 unsigned long get_wchan(struct task_struct *p);
 #define task_pt_regs(tsk) ((struct pt_regs *) \
index 3ee5da3bc10ca26993c76072ec9195b1ec866c28..559512a455dabba842d5f4ade3b580fa61ea4b44 100644 (file)
@@ -9,9 +9,7 @@
 #include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
-#ifndef __s390x__
-#else /* __s390x__ */
-#endif /* __s390x__ */
+
 extern long psw_kernel_bits;
 extern long psw_user_bits;
 
@@ -77,8 +75,6 @@ struct per_struct_kernel {
 #define PER_CONTROL_SUSPENSION         0x00400000UL
 #define PER_CONTROL_ALTERATION         0x00200000UL
 
-#ifdef __s390x__
-#endif /* __s390x__ */
 /*
  * These are defined as per linux/ptrace.h, which see.
  */
index fe7b99759e12ffcdf5f2df9880f86f91df3c9800..cd29d2f4e4f355512ecbafd0cfcc0c7fab05042a 100644 (file)
@@ -23,6 +23,7 @@
  * type here is what we want [need] for both 32 bit and 64 bit systems.
  */
 extern const unsigned int sys_call_table[];
+extern const unsigned int sys_call_table_emu[];
 
 static inline long syscall_get_nr(struct task_struct *task,
                                  struct pt_regs *regs)
index 9e2cfe0349c3c5f50177a870ba6061ec7bd85dd0..eb5f64d26d06190de4695d38e9190449859588df 100644 (file)
 #define THREAD_ORDER 1
 #define ASYNC_ORDER  1
 #else /* CONFIG_64BIT */
-#ifndef __SMALL_STACK
 #define THREAD_ORDER 2
 #define ASYNC_ORDER  2
-#else
-#define THREAD_ORDER 1
-#define ASYNC_ORDER  1
-#endif
 #endif /* CONFIG_64BIT */
 
 #define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
@@ -41,6 +36,7 @@ struct thread_info {
        struct task_struct      *task;          /* main task structure */
        struct exec_domain      *exec_domain;   /* execution domain */
        unsigned long           flags;          /* low level flags */
+       unsigned long           sys_call_table; /* System call table address */
        unsigned int            cpu;            /* current CPU */
        int                     preempt_count;  /* 0 => preemptable, <0 => BUG */
        struct restart_block    restart_block;
index a5ca214b34fdb1271e4fad48d9c7c7fb8c5a9437..3aa9f1ec5b295f0c530998610d04fa7de34dc93f 100644 (file)
@@ -215,12 +215,6 @@ typedef struct
         unsigned long addr;
 } __attribute__ ((aligned(8))) psw_t;
 
-typedef struct
-{
-       __u32   mask;
-       __u32   addr;
-} __attribute__ ((aligned(8))) psw_compat_t;
-
 #ifndef __s390x__
 
 #define PSW_MASK_PER           0x40000000UL
@@ -295,20 +289,6 @@ typedef struct
        unsigned long orig_gpr2;
 } s390_regs;
 
-typedef struct
-{
-       psw_compat_t    psw;
-       __u32           gprs[NUM_GPRS];
-       __u32           acrs[NUM_ACRS];
-       __u32           orig_gpr2;
-} s390_compat_regs;
-
-typedef struct
-{
-       __u32           gprs_high[NUM_GPRS];
-} s390_compat_regs_high;
-
-
 /*
  * Now for the user space program event recording (trace) definitions.
  * The following structures are used only for the ptrace interface, don't
index 5acca0a34c20c7cd243f8843cce3a41655a8ee27..a61d538756f29c9ec6f932aec471c2f74de93e8a 100644 (file)
@@ -7,9 +7,6 @@
 #ifndef _S390_STATFS_H
 #define _S390_STATFS_H
 
-#ifndef __s390x__
-#include <asm-generic/statfs.h>
-#else
 /*
  * We can't use <asm-generic/statfs.h> because in 64-bit mode
  * we mix ints of different sizes in our struct statfs.
@@ -21,49 +18,33 @@ typedef __kernel_fsid_t     fsid_t;
 #endif
 
 struct statfs {
-       int  f_type;
-       int  f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
+       unsigned int    f_type;
+       unsigned int    f_bsize;
+       unsigned long   f_blocks;
+       unsigned long   f_bfree;
+       unsigned long   f_bavail;
+       unsigned long   f_files;
+       unsigned long   f_ffree;
        __kernel_fsid_t f_fsid;
-       int  f_namelen;
-       int  f_frsize;
-       int  f_flags;
-       int  f_spare[4];
+       unsigned int    f_namelen;
+       unsigned int    f_frsize;
+       unsigned int    f_flags;
+       unsigned int    f_spare[4];
 };
 
 struct statfs64 {
-       int  f_type;
-       int  f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
+       unsigned int    f_type;
+       unsigned int    f_bsize;
+       unsigned long   f_blocks;
+       unsigned long   f_bfree;
+       unsigned long   f_bavail;
+       unsigned long   f_files;
+       unsigned long   f_ffree;
        __kernel_fsid_t f_fsid;
-       int  f_namelen;
-       int  f_frsize;
-       int  f_flags;
-       int  f_spare[4];
+       unsigned int    f_namelen;
+       unsigned int    f_frsize;
+       unsigned int    f_flags;
+       unsigned int    f_spare[4];
 };
 
-struct compat_statfs64 {
-       __u32 f_type;
-       __u32 f_bsize;
-       __u64 f_blocks;
-       __u64 f_bfree;
-       __u64 f_bavail;
-       __u64 f_files;
-       __u64 f_ffree;
-       __kernel_fsid_t f_fsid;
-       __u32 f_namelen;
-       __u32 f_frsize;
-       __u32 f_flags;
-       __u32 f_spare[4];
-};
-
-#endif /* __s390x__ */
 #endif
index 2ac311ef5c9b11a3b37aa4f5586a240aa14679a6..1386fcaf4ef6c7854838df1563604bca1d74603a 100644 (file)
@@ -13,6 +13,14 @@ endif
 #
 CFLAGS_smp.o   := -Wno-nonnull
 
+#
+# Disable tailcall optimizations for stack / callchain walking functions
+# since this might generate broken code when accessing register 15 and
+# passing its content to other functions.
+#
+CFLAGS_stacktrace.o    += -fno-optimize-sibling-calls
+CFLAGS_dumpstack.o     += -fno-optimize-sibling-calls
+
 #
 # Pass UTS_MACHINE for user_regset definition
 #
@@ -20,10 +28,11 @@ CFLAGS_ptrace.o             += -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
 CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 
-obj-y  :=  bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \
-           processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \
-           debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \
-           sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
+obj-y  := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o
+obj-y  += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
+obj-y  += debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o
+obj-y  += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
+obj-y  += dumpstack.o
 
 obj-y  += $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y  += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
index fface87056eb6f50357ae0d376ee55ccbb972e87..7a82f9f7010015e4d73349a1a46426017a4088dd 100644 (file)
@@ -35,6 +35,7 @@ int main(void)
        DEFINE(__TI_task, offsetof(struct thread_info, task));
        DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain));
        DEFINE(__TI_flags, offsetof(struct thread_info, flags));
+       DEFINE(__TI_sysc_table, offsetof(struct thread_info, sys_call_table));
        DEFINE(__TI_cpu, offsetof(struct thread_info, cpu));
        DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count));
        DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer));
index 6de049fbe62dced08c1deddb4330077d3d4158ae..c439ac9ced092a6a8c4ea710b3127c4bb6cb3014 100644 (file)
@@ -362,6 +362,7 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
                /* set extra registers only for synchronous signals */
                regs->gprs[4] = regs->int_code & 127;
                regs->gprs[5] = regs->int_parm_long;
+               regs->gprs[6] = task_thread_info(current)->last_break;
        }
 
        /* Place signal number on stack to allow backtrace from handler.  */
@@ -421,6 +422,7 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->gprs[2] = map_signal(sig);
        regs->gprs[3] = (__force __u64) &frame->info;
        regs->gprs[4] = (__force __u64) &frame->uc;
+       regs->gprs[5] = task_thread_info(current)->last_break;
        return 0;
 
 give_sigsegv:
index 3ad5e95401604046371eea84bb02a68a345d5266..7f4a4a8c847c7a3807fd6d913f0ca93fe5b874b8 100644 (file)
@@ -1696,14 +1696,15 @@ static struct insn *find_insn(unsigned char *code)
  * insn_to_mnemonic - decode an s390 instruction
  * @instruction: instruction to decode
  * @buf: buffer to fill with mnemonic
+ * @len: length of buffer
  *
  * Decode the instruction at @instruction and store the corresponding
- * mnemonic into @buf.
+ * mnemonic into @buf of length @len.
  * @buf is left unchanged if the instruction could not be decoded.
  * Returns:
  *  %0 on success, %-ENOENT if the instruction was not found.
  */
-int insn_to_mnemonic(unsigned char *instruction, char buf[8])
+int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len)
 {
        struct insn *insn;
 
@@ -1711,10 +1712,10 @@ int insn_to_mnemonic(unsigned char *instruction, char buf[8])
        if (!insn)
                return -ENOENT;
        if (insn->name[0] == '\0')
-               snprintf(buf, 8, "%s",
+               snprintf(buf, len, "%s",
                         long_insn_name[(int) insn->name[1]]);
        else
-               snprintf(buf, 8, "%.5s", insn->name);
+               snprintf(buf, len, "%.5s", insn->name);
        return 0;
 }
 EXPORT_SYMBOL_GPL(insn_to_mnemonic);
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
new file mode 100644 (file)
index 0000000..03dce39
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Stack dumping functions
+ *
+ *  Copyright IBM Corp. 1999, 2013
+ */
+
+#include <linux/kallsyms.h>
+#include <linux/hardirq.h>
+#include <linux/kprobes.h>
+#include <linux/utsname.h>
+#include <linux/export.h>
+#include <linux/kdebug.h>
+#include <linux/ptrace.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/debug.h>
+#include <asm/ipl.h>
+
+#ifndef CONFIG_64BIT
+#define LONG "%08lx "
+#define FOURLONG "%08lx %08lx %08lx %08lx\n"
+static int kstack_depth_to_print = 12;
+#else /* CONFIG_64BIT */
+#define LONG "%016lx "
+#define FOURLONG "%016lx %016lx %016lx %016lx\n"
+static int kstack_depth_to_print = 20;
+#endif /* CONFIG_64BIT */
+
+/*
+ * For show_trace we have tree different stack to consider:
+ *   - the panic stack which is used if the kernel stack has overflown
+ *   - the asynchronous interrupt stack (cpu related)
+ *   - the synchronous kernel stack (process related)
+ * The stack trace can start at any of the three stack and can potentially
+ * touch all of them. The order is: panic stack, async stack, sync stack.
+ */
+static unsigned long
+__show_trace(unsigned long sp, unsigned long low, unsigned long high)
+{
+       struct stack_frame *sf;
+       struct pt_regs *regs;
+
+       while (1) {
+               sp = sp & PSW_ADDR_INSN;
+               if (sp < low || sp > high - sizeof(*sf))
+                       return sp;
+               sf = (struct stack_frame *) sp;
+               printk("([<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
+               print_symbol("%s)\n", sf->gprs[8] & PSW_ADDR_INSN);
+               /* Follow the backchain. */
+               while (1) {
+                       low = sp;
+                       sp = sf->back_chain & PSW_ADDR_INSN;
+                       if (!sp)
+                               break;
+                       if (sp <= low || sp > high - sizeof(*sf))
+                               return sp;
+                       sf = (struct stack_frame *) sp;
+                       printk(" [<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
+                       print_symbol("%s\n", sf->gprs[8] & PSW_ADDR_INSN);
+               }
+               /* Zero backchain detected, check for interrupt frame. */
+               sp = (unsigned long) (sf + 1);
+               if (sp <= low || sp > high - sizeof(*regs))
+                       return sp;
+               regs = (struct pt_regs *) sp;
+               printk(" [<%016lx>] ", regs->psw.addr & PSW_ADDR_INSN);
+               print_symbol("%s\n", regs->psw.addr & PSW_ADDR_INSN);
+               low = sp;
+               sp = regs->gprs[15];
+       }
+}
+
+static void show_trace(struct task_struct *task, unsigned long *stack)
+{
+       register unsigned long __r15 asm ("15");
+       unsigned long sp;
+
+       sp = (unsigned long) stack;
+       if (!sp)
+               sp = task ? task->thread.ksp : __r15;
+       printk("Call Trace:\n");
+#ifdef CONFIG_CHECK_STACK
+       sp = __show_trace(sp, S390_lowcore.panic_stack - 4096,
+                         S390_lowcore.panic_stack);
+#endif
+       sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE,
+                         S390_lowcore.async_stack);
+       if (task)
+               __show_trace(sp, (unsigned long) task_stack_page(task),
+                            (unsigned long) task_stack_page(task) + THREAD_SIZE);
+       else
+               __show_trace(sp, S390_lowcore.thread_info,
+                            S390_lowcore.thread_info + THREAD_SIZE);
+       if (!task)
+               task = current;
+       debug_show_held_locks(task);
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+       register unsigned long *__r15 asm ("15");
+       unsigned long *stack;
+       int i;
+
+       if (!sp)
+               stack = task ? (unsigned long *) task->thread.ksp : __r15;
+       else
+               stack = sp;
+
+       for (i = 0; i < kstack_depth_to_print; i++) {
+               if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
+                       break;
+               if ((i * sizeof(long) % 32) == 0)
+                       printk("%s       ", i == 0 ? "" : "\n");
+               printk(LONG, *stack++);
+       }
+       printk("\n");
+       show_trace(task, sp);
+}
+
+static void show_last_breaking_event(struct pt_regs *regs)
+{
+#ifdef CONFIG_64BIT
+       printk("Last Breaking-Event-Address:\n");
+       printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
+       print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
+#endif
+}
+
+/*
+ * The architecture-independent dump_stack generator
+ */
+void dump_stack(void)
+{
+       printk("CPU: %d %s %s %.*s\n",
+              task_thread_info(current)->cpu, print_tainted(),
+              init_utsname()->release,
+              (int)strcspn(init_utsname()->version, " "),
+              init_utsname()->version);
+       printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
+              current->comm, current->pid, current,
+              (void *) current->thread.ksp);
+       show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
+
+static inline int mask_bits(struct pt_regs *regs, unsigned long bits)
+{
+       return (regs->psw.mask & bits) / ((~bits + 1) & bits);
+}
+
+void show_registers(struct pt_regs *regs)
+{
+       char *mode;
+
+       mode = user_mode(regs) ? "User" : "Krnl";
+       printk("%s PSW : %p %p",
+              mode, (void *) regs->psw.mask,
+              (void *) regs->psw.addr);
+       print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN);
+       printk("           R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
+              "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
+              mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
+              mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY),
+              mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT),
+              mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
+              mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
+#ifdef CONFIG_64BIT
+       printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
+#endif
+       printk("\n%s GPRS: " FOURLONG, mode,
+              regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
+       printk("           " FOURLONG,
+              regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
+       printk("           " FOURLONG,
+              regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
+       printk("           " FOURLONG,
+              regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
+       show_code(regs);
+}
+
+void show_regs(struct pt_regs *regs)
+{
+       printk("CPU: %d %s %s %.*s\n",
+              task_thread_info(current)->cpu, print_tainted(),
+              init_utsname()->release,
+              (int)strcspn(init_utsname()->version, " "),
+              init_utsname()->version);
+       printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
+              current->comm, current->pid, current,
+              (void *) current->thread.ksp);
+       show_registers(regs);
+       /* Show stack backtrace if pt_regs is from kernel mode */
+       if (!user_mode(regs))
+               show_trace(NULL, (unsigned long *) regs->gprs[15]);
+       show_last_breaking_event(regs);
+}
+
+static DEFINE_SPINLOCK(die_lock);
+
+void die(struct pt_regs *regs, const char *str)
+{
+       static int die_counter;
+
+       oops_enter();
+       lgr_info_log();
+       debug_stop_all();
+       console_verbose();
+       spin_lock_irq(&die_lock);
+       bust_spinlocks(1);
+       printk("%s: %04x [#%d] ", str, regs->int_code & 0xffff, ++die_counter);
+#ifdef CONFIG_PREEMPT
+       printk("PREEMPT ");
+#endif
+#ifdef CONFIG_SMP
+       printk("SMP ");
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+       printk("DEBUG_PAGEALLOC");
+#endif
+       printk("\n");
+       notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
+       print_modules();
+       show_regs(regs);
+       bust_spinlocks(0);
+       add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
+       spin_unlock_irq(&die_lock);
+       if (in_interrupt())
+               panic("Fatal exception in interrupt");
+       if (panic_on_oops)
+               panic("Fatal exception: panic_on_oops");
+       oops_exit();
+       do_exit(SIGSEGV);
+}
index 94feff7d613233dca1ad45702181f161bb425caf..4d5e6f8a7978cb005d0ae15fe3d1837175f285d1 100644 (file)
@@ -45,6 +45,7 @@ _TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
+STACK_INIT  = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE
 
 #define BASED(name) name-system_call(%r13)
 
@@ -97,10 +98,10 @@ STACK_SIZE  = 1 << STACK_SHIFT
        sra     %r14,\shift
        jnz     1f
        CHECK_STACK 1<<\shift,\savearea
+       ahi     %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        j       2f
 1:     l       %r15,\stack             # load target stack
-2:     ahi     %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       la      %r11,STACK_FRAME_OVERHEAD(%r15)
+2:     la      %r11,STACK_FRAME_OVERHEAD(%r15)
        .endm
 
        .macro  ADD64 high,low,timer
@@ -150,7 +151,7 @@ ENTRY(__switch_to)
        l       %r4,__THREAD_info(%r2)          # get thread_info of prev
        l       %r5,__THREAD_info(%r3)          # get thread_info of next
        lr      %r15,%r5
-       ahi     %r15,STACK_SIZE                 # end of kernel stack of next
+       ahi     %r15,STACK_INIT                 # end of kernel stack of next
        st      %r3,__LC_CURRENT                # store task struct of next
        st      %r5,__LC_THREAD_INFO            # store thread info of next
        st      %r15,__LC_KERNEL_STACK          # store end of kernel stack
@@ -178,7 +179,6 @@ sysc_stm:
        l       %r13,__LC_SVC_NEW_PSW+4
 sysc_per:
        l       %r15,__LC_KERNEL_STACK
-       ahi     %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        la      %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs
 sysc_vtime:
        UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER
@@ -188,6 +188,7 @@ sysc_vtime:
        mvc     __PT_INT_CODE(4,%r11),__LC_SVC_ILC
 sysc_do_svc:
        oi      __TI_flags+3(%r12),_TIF_SYSCALL
+       l       %r10,__TI_sysc_table(%r12)      # 31 bit system call table
        lh      %r8,__PT_INT_CODE+2(%r11)
        sla     %r8,2                           # shift and test for svc0
        jnz     sysc_nr_ok
@@ -198,7 +199,6 @@ sysc_do_svc:
        lr      %r8,%r1
        sla     %r8,2
 sysc_nr_ok:
-       l       %r10,BASED(.Lsys_call_table)    # 31 bit system call table
        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
        st      %r2,__PT_ORIG_GPR2(%r11)
        st      %r7,STACK_FRAME_OVERHEAD(%r15)
@@ -359,11 +359,11 @@ ENTRY(pgm_check_handler)
        tm      __LC_PGM_ILC+3,0x80     # check for per exception
        jnz     pgm_svcper              # -> single stepped svc
 0:     CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC
+       ahi     %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        j       2f
 1:     UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER
        l       %r15,__LC_KERNEL_STACK
-2:     ahi     %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       la      %r11,STACK_FRAME_OVERHEAD(%r15)
+2:     la      %r11,STACK_FRAME_OVERHEAD(%r15)
        stm     %r0,%r7,__PT_R0(%r11)
        mvc     __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC
        stm     %r8,%r9,__PT_PSW(%r11)
@@ -485,7 +485,6 @@ io_work:
 #
 io_work_user:
        l       %r1,__LC_KERNEL_STACK
-       ahi     %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        mvc     STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1)
        la      %r11,STACK_FRAME_OVERHEAD(%r1)
@@ -646,7 +645,6 @@ mcck_skip:
        tm      __PT_PSW+1(%r11),0x01   # returning to user ?
        jno     mcck_return
        l       %r1,__LC_KERNEL_STACK   # switch to kernel stack
-       ahi     %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        mvc     STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1)
        la      %r11,STACK_FRAME_OVERHEAD(%r15)
@@ -674,6 +672,7 @@ mcck_panic:
        sra     %r14,PAGE_SHIFT
        jz      0f
        l       %r15,__LC_PANIC_STACK
+       j       mcck_skip
 0:     ahi     %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        j       mcck_skip
 
@@ -714,12 +713,10 @@ ENTRY(restart_int_handler)
  */
 stack_overflow:
        l       %r15,__LC_PANIC_STACK   # change to panic stack
-       ahi     %r15,-__PT_SIZE         # create pt_regs
-       stm     %r0,%r7,__PT_R0(%r15)
-       stm     %r8,%r9,__PT_PSW(%r15)
+       la      %r11,STACK_FRAME_OVERHEAD(%r15)
+       stm     %r0,%r7,__PT_R0(%r11)
+       stm     %r8,%r9,__PT_PSW(%r11)
        mvc     __PT_R8(32,%r11),0(%r14)
-       lr      %r15,%r11
-       ahi     %r15,-STACK_FRAME_OVERHEAD
        l       %r1,BASED(1f)
        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
        lr      %r2,%r11                # pass pointer to pt_regs
@@ -799,15 +796,14 @@ cleanup_system_call:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
        # set up saved register 11
        l       %r15,__LC_KERNEL_STACK
-       ahi     %r15,-__PT_SIZE
-       st      %r15,12(%r11)           # r11 pt_regs pointer
+       la      %r9,STACK_FRAME_OVERHEAD(%r15)
+       st      %r9,12(%r11)            # r11 pt_regs pointer
        # fill pt_regs
-       mvc     __PT_R8(32,%r15),__LC_SAVE_AREA_SYNC
-       stm     %r0,%r7,__PT_R0(%r15)
-       mvc     __PT_PSW(8,%r15),__LC_SVC_OLD_PSW
-       mvc     __PT_INT_CODE(4,%r15),__LC_SVC_ILC
+       mvc     __PT_R8(32,%r9),__LC_SAVE_AREA_SYNC
+       stm     %r0,%r7,__PT_R0(%r9)
+       mvc     __PT_PSW(8,%r9),__LC_SVC_OLD_PSW
+       mvc     __PT_INT_CODE(4,%r9),__LC_SVC_ILC
        # setup saved register 15
-       ahi     %r15,-STACK_FRAME_OVERHEAD
        st      %r15,28(%r11)           # r15 stack pointer
        # set new psw address and exit
        l       %r9,BASED(cleanup_table+4)      # sysc_do_svc + 0x80000000
@@ -910,7 +906,6 @@ cleanup_idle_wait:
 .Ltrace_enter:         .long   do_syscall_trace_enter
 .Ltrace_exit:          .long   do_syscall_trace_exit
 .Lschedule_tail:       .long   schedule_tail
-.Lsys_call_table:      .long   sys_call_table
 .Lsysc_per:            .long   sysc_per + 0x80000000
 #ifdef CONFIG_TRACE_IRQFLAGS
 .Lhardirqs_on:         .long   trace_hardirqs_on_caller
index c3a736a3ed4458f0187d8f041f62fb1e590d877e..aa0ab02e9595f8c6d21d6827a8b0ca261c0d71ec 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/cputime.h>
 
 extern void *restart_stack;
+extern unsigned long suspend_zero_pages;
 
 void system_call(void);
 void pgm_check_handler(void);
index 2e6d60c55f909259803a1b52d7fdc6d04277fd0b..4c17eece707eb94d0b08c55b63a25b7788fb0c56 100644 (file)
@@ -39,6 +39,7 @@ __PT_R15     =        __PT_GPRS + 120
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
+STACK_INIT = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE
 
 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING | _TIF_PER_TRAP )
@@ -124,10 +125,10 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
        srag    %r14,%r14,\shift
        jnz     1f
        CHECK_STACK 1<<\shift,\savearea
+       aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        j       2f
 1:     lg      %r15,\stack             # load target stack
-2:     aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       la      %r11,STACK_FRAME_OVERHEAD(%r15)
+2:     la      %r11,STACK_FRAME_OVERHEAD(%r15)
        .endm
 
        .macro UPDATE_VTIME scratch,enter_timer
@@ -177,7 +178,7 @@ ENTRY(__switch_to)
        lg      %r4,__THREAD_info(%r2)          # get thread_info of prev
        lg      %r5,__THREAD_info(%r3)          # get thread_info of next
        lgr     %r15,%r5
-       aghi    %r15,STACK_SIZE                 # end of kernel stack of next
+       aghi    %r15,STACK_INIT                 # end of kernel stack of next
        stg     %r3,__LC_CURRENT                # store task struct of next
        stg     %r5,__LC_THREAD_INFO            # store thread info of next
        stg     %r15,__LC_KERNEL_STACK          # store end of kernel stack
@@ -203,10 +204,8 @@ sysc_stmg:
        stmg    %r8,%r15,__LC_SAVE_AREA_SYNC
        lg      %r10,__LC_LAST_BREAK
        lg      %r12,__LC_THREAD_INFO
-       larl    %r13,system_call
 sysc_per:
        lg      %r15,__LC_KERNEL_STACK
-       aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        la      %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs
 sysc_vtime:
        UPDATE_VTIME %r13,__LC_SYNC_ENTER_TIMER
@@ -217,6 +216,7 @@ sysc_vtime:
        mvc     __PT_INT_CODE(4,%r11),__LC_SVC_ILC
 sysc_do_svc:
        oi      __TI_flags+7(%r12),_TIF_SYSCALL
+       lg      %r10,__TI_sysc_table(%r12)      # address of system call table
        llgh    %r8,__PT_INT_CODE+2(%r11)
        slag    %r8,%r8,2                       # shift and test for svc 0
        jnz     sysc_nr_ok
@@ -227,13 +227,6 @@ sysc_do_svc:
        sth     %r1,__PT_INT_CODE+2(%r11)
        slag    %r8,%r1,2
 sysc_nr_ok:
-       larl    %r10,sys_call_table             # 64 bit system call table
-#ifdef CONFIG_COMPAT
-       tm      __TI_flags+5(%r12),(_TIF_31BIT>>16)
-       jno     sysc_noemu
-       larl    %r10,sys_call_table_emu         # 31 bit system call table
-sysc_noemu:
-#endif
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
        stg     %r2,__PT_ORIG_GPR2(%r11)
        stg     %r7,STACK_FRAME_OVERHEAD(%r15)
@@ -389,6 +382,7 @@ ENTRY(pgm_check_handler)
        tm      __LC_PGM_ILC+3,0x80     # check for per exception
        jnz     pgm_svcper              # -> single stepped svc
 0:     CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC
+       aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        j       2f
 1:     UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER
        LAST_BREAK %r14
@@ -398,8 +392,7 @@ ENTRY(pgm_check_handler)
        tm      __LC_PGM_ILC+2,0x02     # check for transaction abort
        jz      2f
        mvc     __THREAD_trap_tdb(256,%r14),0(%r13)
-2:     aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       la      %r11,STACK_FRAME_OVERHEAD(%r15)
+2:     la      %r11,STACK_FRAME_OVERHEAD(%r15)
        stmg    %r0,%r7,__PT_R0(%r11)
        mvc     __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
        stmg    %r8,%r9,__PT_PSW(%r11)
@@ -526,7 +519,6 @@ io_work:
 #
 io_work_user:
        lg      %r1,__LC_KERNEL_STACK
-       aghi    %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        mvc     STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1)
        la      %r11,STACK_FRAME_OVERHEAD(%r1)
@@ -688,7 +680,6 @@ mcck_skip:
        tm      __PT_PSW+1(%r11),0x01   # returning to user ?
        jno     mcck_return
        lg      %r1,__LC_KERNEL_STACK   # switch to kernel stack
-       aghi    %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        mvc     STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1)
        la      %r11,STACK_FRAME_OVERHEAD(%r1)
@@ -755,14 +746,12 @@ ENTRY(restart_int_handler)
  * Setup a pt_regs so that show_trace can provide a good call trace.
  */
 stack_overflow:
-       lg      %r11,__LC_PANIC_STACK   # change to panic stack
-       aghi    %r11,-__PT_SIZE         # create pt_regs
+       lg      %r15,__LC_PANIC_STACK   # change to panic stack
+       la      %r11,STACK_FRAME_OVERHEAD(%r15)
        stmg    %r0,%r7,__PT_R0(%r11)
        stmg    %r8,%r9,__PT_PSW(%r11)
        mvc     __PT_R8(64,%r11),0(%r14)
        stg     %r10,__PT_ORIG_GPR2(%r11) # store last break to orig_gpr2
-       lgr     %r15,%r11
-       aghi    %r15,-STACK_FRAME_OVERHEAD
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
        lgr     %r2,%r11                # pass pointer to pt_regs
        jg      kernel_stack_overflow
@@ -846,15 +835,14 @@ cleanup_system_call:
        mvc     __TI_last_break(8,%r12),16(%r11)
 0:     # set up saved register r11
        lg      %r15,__LC_KERNEL_STACK
-       aghi    %r15,-__PT_SIZE
-       stg     %r15,24(%r11)           # r11 pt_regs pointer
+       la      %r9,STACK_FRAME_OVERHEAD(%r15)
+       stg     %r9,24(%r11)            # r11 pt_regs pointer
        # fill pt_regs
-       mvc     __PT_R8(64,%r15),__LC_SAVE_AREA_SYNC
-       stmg    %r0,%r7,__PT_R0(%r15)
-       mvc     __PT_PSW(16,%r15),__LC_SVC_OLD_PSW
-       mvc     __PT_INT_CODE(4,%r15),__LC_SVC_ILC
+       mvc     __PT_R8(64,%r9),__LC_SAVE_AREA_SYNC
+       stmg    %r0,%r7,__PT_R0(%r9)
+       mvc     __PT_PSW(16,%r9),__LC_SVC_OLD_PSW
+       mvc     __PT_INT_CODE(4,%r9),__LC_SVC_ILC
        # setup saved register r15
-       aghi    %r15,-STACK_FRAME_OVERHEAD
        stg     %r15,56(%r11)           # r15 stack pointer
        # set new psw address and exit
        larl    %r9,sysc_do_svc
@@ -1011,6 +999,7 @@ sys_call_table:
 #ifdef CONFIG_COMPAT
 
 #define SYSCALL(esa,esame,emu) .long emu
+       .globl  sys_call_table_emu
 sys_call_table_emu:
 #include "syscalls.S"
 #undef SYSCALL
index b3de27700016a18c8a3764db54d6a5cae5e77d5d..ac2178161ec3b80bae5324728e62ead072f97c91 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/reboot.h>
 #include <linux/ftrace.h>
 #include <linux/debug_locks.h>
+#include <linux/suspend.h>
 #include <asm/cio.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
@@ -67,6 +68,35 @@ void setup_regs(void)
        memcpy((void *) SAVE_AREA_BASE, (void *) sa, sizeof(struct save_area));
 }
 
+/*
+ * PM notifier callback for kdump
+ */
+static int machine_kdump_pm_cb(struct notifier_block *nb, unsigned long action,
+                              void *ptr)
+{
+       switch (action) {
+       case PM_SUSPEND_PREPARE:
+       case PM_HIBERNATION_PREPARE:
+               if (crashk_res.start)
+                       crash_map_reserved_pages();
+               break;
+       case PM_POST_SUSPEND:
+       case PM_POST_HIBERNATION:
+               if (crashk_res.start)
+                       crash_unmap_reserved_pages();
+               break;
+       default:
+               return NOTIFY_DONE;
+       }
+       return NOTIFY_OK;
+}
+
+static int __init machine_kdump_pm_init(void)
+{
+       pm_notifier(machine_kdump_pm_cb, 0);
+       return 0;
+}
+arch_initcall(machine_kdump_pm_init);
 #endif
 
 /*
index 29268859d8eebc405bc013fee0a2d05ee86d71b8..0f419c5765c86993e4aa48fb8c9bcd702aa4bf7d 100644 (file)
@@ -377,11 +377,14 @@ static void __init setup_lowcore(void)
                PSW_MASK_DAT | PSW_MASK_MCHECK;
        lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
        lc->clock_comparator = -1ULL;
-       lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
+       lc->kernel_stack = ((unsigned long) &init_thread_union)
+               + THREAD_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
        lc->async_stack = (unsigned long)
-               __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
+               __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0)
+               + ASYNC_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
        lc->panic_stack = (unsigned long)
-               __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
+               __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0)
+               + PAGE_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
        lc->current_task = (unsigned long) init_thread_union.thread_info.task;
        lc->thread_info = (unsigned long) &init_thread_union;
        lc->machine_flags = S390_lowcore.machine_flags;
index 549c9d173c0fdc0c5681ab9ba77b92f372af2c71..8bde89eafd88cfcab63da6645322eb2e34a978ea 100644 (file)
@@ -181,8 +181,10 @@ static int __cpuinit pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
        lc = pcpu->lowcore;
        memcpy(lc, &S390_lowcore, 512);
        memset((char *) lc + 512, 0, sizeof(*lc) - 512);
-       lc->async_stack = pcpu->async_stack + ASYNC_SIZE;
-       lc->panic_stack = pcpu->panic_stack + PAGE_SIZE;
+       lc->async_stack = pcpu->async_stack + ASYNC_SIZE
+               - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
+       lc->panic_stack = pcpu->panic_stack + PAGE_SIZE
+               - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
        lc->cpu_nr = cpu;
 #ifndef CONFIG_64BIT
        if (MACHINE_HAS_IEEE) {
@@ -253,7 +255,8 @@ static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk)
        struct _lowcore *lc = pcpu->lowcore;
        struct thread_info *ti = task_thread_info(tsk);
 
-       lc->kernel_stack = (unsigned long) task_stack_page(tsk) + THREAD_SIZE;
+       lc->kernel_stack = (unsigned long) task_stack_page(tsk)
+               + THREAD_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
        lc->thread_info = (unsigned long) task_thread_info(tsk);
        lc->current_task = (unsigned long) tsk;
        lc->user_timer = ti->user_timer;
@@ -810,8 +813,10 @@ void __init smp_prepare_boot_cpu(void)
        pcpu->state = CPU_STATE_CONFIGURED;
        pcpu->address = boot_cpu_address;
        pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix();
-       pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE;
-       pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE;
+       pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE
+               + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
+       pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE
+               + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
        S390_lowcore.percpu_offset = __per_cpu_offset[0];
        smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN);
        set_cpu_present(0, true);
index aa1494d0e380f907f56c74e53198dcad2dff592d..c479d2f9605ba6ef3dede5a669be872f97494b0f 100644 (file)
@@ -41,6 +41,7 @@ struct page_key_data {
 static struct page_key_data *page_key_data;
 static struct page_key_data *page_key_rp, *page_key_wp;
 static unsigned long page_key_rx, page_key_wx;
+unsigned long suspend_zero_pages;
 
 /*
  * For each page in the hibernation image one additional byte is
@@ -149,6 +150,36 @@ int pfn_is_nosave(unsigned long pfn)
        return 0;
 }
 
+/*
+ * PM notifier callback for suspend
+ */
+static int suspend_pm_cb(struct notifier_block *nb, unsigned long action,
+                        void *ptr)
+{
+       switch (action) {
+       case PM_SUSPEND_PREPARE:
+       case PM_HIBERNATION_PREPARE:
+               suspend_zero_pages = __get_free_pages(GFP_KERNEL, LC_ORDER);
+               if (!suspend_zero_pages)
+                       return NOTIFY_BAD;
+               break;
+       case PM_POST_SUSPEND:
+       case PM_POST_HIBERNATION:
+               free_pages(suspend_zero_pages, LC_ORDER);
+               break;
+       default:
+               return NOTIFY_DONE;
+       }
+       return NOTIFY_OK;
+}
+
+static int __init suspend_pm_init(void)
+{
+       pm_notifier(suspend_pm_cb, 0);
+       return 0;
+}
+arch_initcall(suspend_pm_init);
+
 void save_processor_state(void)
 {
        /* swsusp_arch_suspend() actually saves all cpu register contents.
index d4ca4e0617b52ae12e039a6110ef4872f9de07ee..c487be4cfc81c5a9cf288b448ec049b0f11fec66 100644 (file)
@@ -36,8 +36,8 @@ ENTRY(swsusp_arch_suspend)
        /* Store prefix register on stack */
        stpx    __SF_EMPTY(%r15)
 
-       /* Save prefix register contents for lowcore */
-       llgf    %r4,__SF_EMPTY(%r15)
+       /* Save prefix register contents for lowcore copy */
+       llgf    %r10,__SF_EMPTY(%r15)
 
        /* Get pointer to save area */
        lghi    %r1,0x1000
@@ -91,7 +91,18 @@ ENTRY(swsusp_arch_suspend)
        xc      __SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
        spx     __SF_EMPTY(%r15)
 
+       /* Save absolute zero pages */
+       larl    %r2,suspend_zero_pages
+       lg      %r2,0(%r2)
+       lghi    %r4,0
+       lghi    %r3,2*PAGE_SIZE
+       lghi    %r5,2*PAGE_SIZE
+1:     mvcle   %r2,%r4,0
+       jo      1b
+
+       /* Copy lowcore to absolute zero lowcore */
        lghi    %r2,0
+       lgr     %r4,%r10
        lghi    %r3,2*PAGE_SIZE
        lghi    %r5,2*PAGE_SIZE
 1:     mvcle   %r2,%r4,0
@@ -248,8 +259,20 @@ restore_registers:
        /* Load old stack */
        lg      %r15,0x2f8(%r13)
 
+       /* Save prefix register */
+       mvc __SF_EMPTY(4,%r15),0x318(%r13)
+
+       /* Restore absolute zero pages */
+       lghi    %r2,0
+       larl    %r4,suspend_zero_pages
+       lg      %r4,0(%r4)
+       lghi    %r3,2*PAGE_SIZE
+       lghi    %r5,2*PAGE_SIZE
+1:     mvcle   %r2,%r4,0
+       jo      1b
+
        /* Restore prefix register */
-       spx     0x318(%r13)
+       spx     __SF_EMPTY(%r15)
 
        /* Activate DAT */
        stosm   __SF_EMPTY(%r15),0x04
index 13dd63fba367e1ccd7b113f4ad2a6ebf25af7845..c5762324d9ee435367314d8fa2f03e32e2365f0e 100644 (file)
  * 'Traps.c' handles hardware traps and faults after we have saved some
  * state in 'asm.s'.
  */
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
+#include <linux/module.h>
 #include <linux/ptrace.h>
-#include <linux/timer.h>
+#include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/seq_file.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/kdebug.h>
-#include <linux/kallsyms.h>
-#include <linux/reboot.h>
-#include <linux/kprobes.h>
-#include <linux/bug.h>
-#include <linux/utsname.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <linux/atomic.h>
-#include <asm/mathemu.h>
-#include <asm/cpcmd.h>
-#include <asm/lowcore.h>
-#include <asm/debug.h>
-#include <asm/ipl.h>
 #include "entry.h"
 
 int show_unhandled_signals = 1;
 
-#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
-
-#ifndef CONFIG_64BIT
-#define LONG "%08lx "
-#define FOURLONG "%08lx %08lx %08lx %08lx\n"
-static int kstack_depth_to_print = 12;
-#else /* CONFIG_64BIT */
-#define LONG "%016lx "
-#define FOURLONG "%016lx %016lx %016lx %016lx\n"
-static int kstack_depth_to_print = 20;
-#endif /* CONFIG_64BIT */
-
 static inline void __user *get_trap_ip(struct pt_regs *regs)
 {
 #ifdef CONFIG_64BIT
@@ -72,215 +39,6 @@ static inline void __user *get_trap_ip(struct pt_regs *regs)
 #endif
 }
 
-/*
- * For show_trace we have tree different stack to consider:
- *   - the panic stack which is used if the kernel stack has overflown
- *   - the asynchronous interrupt stack (cpu related)
- *   - the synchronous kernel stack (process related)
- * The stack trace can start at any of the three stack and can potentially
- * touch all of them. The order is: panic stack, async stack, sync stack.
- */
-static unsigned long
-__show_trace(unsigned long sp, unsigned long low, unsigned long high)
-{
-       struct stack_frame *sf;
-       struct pt_regs *regs;
-
-       while (1) {
-               sp = sp & PSW_ADDR_INSN;
-               if (sp < low || sp > high - sizeof(*sf))
-                       return sp;
-               sf = (struct stack_frame *) sp;
-               printk("([<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
-               print_symbol("%s)\n", sf->gprs[8] & PSW_ADDR_INSN);
-               /* Follow the backchain. */
-               while (1) {
-                       low = sp;
-                       sp = sf->back_chain & PSW_ADDR_INSN;
-                       if (!sp)
-                               break;
-                       if (sp <= low || sp > high - sizeof(*sf))
-                               return sp;
-                       sf = (struct stack_frame *) sp;
-                       printk(" [<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
-                       print_symbol("%s\n", sf->gprs[8] & PSW_ADDR_INSN);
-               }
-               /* Zero backchain detected, check for interrupt frame. */
-               sp = (unsigned long) (sf + 1);
-               if (sp <= low || sp > high - sizeof(*regs))
-                       return sp;
-               regs = (struct pt_regs *) sp;
-               printk(" [<%016lx>] ", regs->psw.addr & PSW_ADDR_INSN);
-               print_symbol("%s\n", regs->psw.addr & PSW_ADDR_INSN);
-               low = sp;
-               sp = regs->gprs[15];
-       }
-}
-
-static void show_trace(struct task_struct *task, unsigned long *stack)
-{
-       register unsigned long __r15 asm ("15");
-       unsigned long sp;
-
-       sp = (unsigned long) stack;
-       if (!sp)
-               sp = task ? task->thread.ksp : __r15;
-       printk("Call Trace:\n");
-#ifdef CONFIG_CHECK_STACK
-       sp = __show_trace(sp, S390_lowcore.panic_stack - 4096,
-                         S390_lowcore.panic_stack);
-#endif
-       sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE,
-                         S390_lowcore.async_stack);
-       if (task)
-               __show_trace(sp, (unsigned long) task_stack_page(task),
-                            (unsigned long) task_stack_page(task) + THREAD_SIZE);
-       else
-               __show_trace(sp, S390_lowcore.thread_info,
-                            S390_lowcore.thread_info + THREAD_SIZE);
-       if (!task)
-               task = current;
-       debug_show_held_locks(task);
-}
-
-void show_stack(struct task_struct *task, unsigned long *sp)
-{
-       register unsigned long * __r15 asm ("15");
-       unsigned long *stack;
-       int i;
-
-       if (!sp)
-               stack = task ? (unsigned long *) task->thread.ksp : __r15;
-       else
-               stack = sp;
-
-       for (i = 0; i < kstack_depth_to_print; i++) {
-               if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
-                       break;
-               if ((i * sizeof(long) % 32) == 0)
-                       printk("%s       ", i == 0 ? "" : "\n");
-               printk(LONG, *stack++);
-       }
-       printk("\n");
-       show_trace(task, sp);
-}
-
-static void show_last_breaking_event(struct pt_regs *regs)
-{
-#ifdef CONFIG_64BIT
-       printk("Last Breaking-Event-Address:\n");
-       printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
-       print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
-#endif
-}
-
-/*
- * The architecture-independent dump_stack generator
- */
-void dump_stack(void)
-{
-       printk("CPU: %d %s %s %.*s\n",
-              task_thread_info(current)->cpu, print_tainted(),
-              init_utsname()->release,
-              (int)strcspn(init_utsname()->version, " "),
-              init_utsname()->version);
-       printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
-              current->comm, current->pid, current,
-              (void *) current->thread.ksp);
-       show_stack(NULL, NULL);
-}
-EXPORT_SYMBOL(dump_stack);
-
-static inline int mask_bits(struct pt_regs *regs, unsigned long bits)
-{
-       return (regs->psw.mask & bits) / ((~bits + 1) & bits);
-}
-
-void show_registers(struct pt_regs *regs)
-{
-       char *mode;
-
-       mode = user_mode(regs) ? "User" : "Krnl";
-       printk("%s PSW : %p %p",
-              mode, (void *) regs->psw.mask,
-              (void *) regs->psw.addr);
-       print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN);
-       printk("           R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
-              "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
-              mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
-              mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY),
-              mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT),
-              mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
-              mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
-#ifdef CONFIG_64BIT
-       printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
-#endif
-       printk("\n%s GPRS: " FOURLONG, mode,
-              regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
-       printk("           " FOURLONG,
-              regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
-       printk("           " FOURLONG,
-              regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
-       printk("           " FOURLONG,
-              regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
-
-       show_code(regs);
-}      
-
-void show_regs(struct pt_regs *regs)
-{
-       printk("CPU: %d %s %s %.*s\n",
-              task_thread_info(current)->cpu, print_tainted(),
-              init_utsname()->release,
-              (int)strcspn(init_utsname()->version, " "),
-              init_utsname()->version);
-       printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
-              current->comm, current->pid, current,
-              (void *) current->thread.ksp);
-       show_registers(regs);
-       /* Show stack backtrace if pt_regs is from kernel mode */
-       if (!user_mode(regs))
-               show_trace(NULL, (unsigned long *) regs->gprs[15]);
-       show_last_breaking_event(regs);
-}
-
-static DEFINE_SPINLOCK(die_lock);
-
-void die(struct pt_regs *regs, const char *str)
-{
-       static int die_counter;
-
-       oops_enter();
-       lgr_info_log();
-       debug_stop_all();
-       console_verbose();
-       spin_lock_irq(&die_lock);
-       bust_spinlocks(1);
-       printk("%s: %04x [#%d] ", str, regs->int_code & 0xffff, ++die_counter);
-#ifdef CONFIG_PREEMPT
-       printk("PREEMPT ");
-#endif
-#ifdef CONFIG_SMP
-       printk("SMP ");
-#endif
-#ifdef CONFIG_DEBUG_PAGEALLOC
-       printk("DEBUG_PAGEALLOC");
-#endif
-       printk("\n");
-       notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
-       print_modules();
-       show_regs(regs);
-       bust_spinlocks(0);
-       add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
-       spin_unlock_irq(&die_lock);
-       if (in_interrupt())
-               panic("Fatal exception in interrupt");
-       if (panic_on_oops)
-               panic("Fatal exception: panic_on_oops");
-       oops_exit();
-       do_exit(SIGSEGV);
-}
-
 static inline void report_user_fault(struct pt_regs *regs, int signr)
 {
        if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
index 2b29e62351d3a09f8e59af8b3d43721700e40fee..53252d2d472007358c4dc9fd788665a8b260e2f3 100644 (file)
@@ -117,7 +117,7 @@ TRACE_EVENT(kvm_s390_intercept_instruction,
                           __entry->instruction,
                           insn_to_mnemonic((unsigned char *)
                                            &__entry->instruction,
-                                        __entry->insn) ?
+                                        __entry->insn, sizeof(__entry->insn)) ?
                           "unknown" : __entry->insn)
        );
 
index dff631d34b45b2630551813454ede86ba94dca84..466fb3383960442b7624e51990536d2cf0b8c65d 100644 (file)
@@ -77,42 +77,69 @@ static size_t copy_in_kernel(size_t count, void __user *to,
  * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address
  * contains the (negative) exception code.
  */
-static __always_inline unsigned long follow_table(struct mm_struct *mm,
-                                                 unsigned long addr, int write)
+#ifdef CONFIG_64BIT
+static unsigned long follow_table(struct mm_struct *mm,
+                                 unsigned long address, int write)
 {
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *ptep;
+       unsigned long *table = (unsigned long *)__pa(mm->pgd);
+
+       switch (mm->context.asce_bits & _ASCE_TYPE_MASK) {
+       case _ASCE_TYPE_REGION1:
+               table = table + ((address >> 53) & 0x7ff);
+               if (unlikely(*table & _REGION_ENTRY_INV))
+                       return -0x39UL;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       case _ASCE_TYPE_REGION2:
+               table = table + ((address >> 42) & 0x7ff);
+               if (unlikely(*table & _REGION_ENTRY_INV))
+                       return -0x3aUL;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       case _ASCE_TYPE_REGION3:
+               table = table + ((address >> 31) & 0x7ff);
+               if (unlikely(*table & _REGION_ENTRY_INV))
+                       return -0x3bUL;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       case _ASCE_TYPE_SEGMENT:
+               table = table + ((address >> 20) & 0x7ff);
+               if (unlikely(*table & _SEGMENT_ENTRY_INV))
+                       return -0x10UL;
+               if (unlikely(*table & _SEGMENT_ENTRY_LARGE)) {
+                       if (write && (*table & _SEGMENT_ENTRY_RO))
+                               return -0x04UL;
+                       return (*table & _SEGMENT_ENTRY_ORIGIN_LARGE) +
+                               (address & ~_SEGMENT_ENTRY_ORIGIN_LARGE);
+               }
+               table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
+       }
+       table = table + ((address >> 12) & 0xff);
+       if (unlikely(*table & _PAGE_INVALID))
+               return -0x11UL;
+       if (write && (*table & _PAGE_RO))
+               return -0x04UL;
+       return (*table & PAGE_MASK) + (address & ~PAGE_MASK);
+}
 
-       pgd = pgd_offset(mm, addr);
-       if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
-               return -0x3aUL;
+#else /* CONFIG_64BIT */
 
-       pud = pud_offset(pgd, addr);
-       if (pud_none(*pud) || unlikely(pud_bad(*pud)))
-               return -0x3bUL;
+static unsigned long follow_table(struct mm_struct *mm,
+                                 unsigned long address, int write)
+{
+       unsigned long *table = (unsigned long *)__pa(mm->pgd);
 
-       pmd = pmd_offset(pud, addr);
-       if (pmd_none(*pmd))
+       table = table + ((address >> 20) & 0x7ff);
+       if (unlikely(*table & _SEGMENT_ENTRY_INV))
                return -0x10UL;
-       if (pmd_large(*pmd)) {
-               if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
-                       return -0x04UL;
-               return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
-       }
-       if (unlikely(pmd_bad(*pmd)))
-               return -0x10UL;
-
-       ptep = pte_offset_map(pmd, addr);
-       if (!pte_present(*ptep))
+       table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
+       table = table + ((address >> 12) & 0xff);
+       if (unlikely(*table & _PAGE_INVALID))
                return -0x11UL;
-       if (write && (!pte_write(*ptep) || !pte_dirty(*ptep)))
+       if (write && (*table & _PAGE_RO))
                return -0x04UL;
-
-       return (pte_val(*ptep) & PAGE_MASK) + (addr & ~PAGE_MASK);
+       return (*table & PAGE_MASK) + (address & ~PAGE_MASK);
 }
 
+#endif /* CONFIG_64BIT */
+
 static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
                                             size_t n, int write_user)
 {
@@ -197,7 +224,7 @@ size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
 
 static size_t clear_user_pt(size_t n, void __user *to)
 {
-       void *zpage = &empty_zero_page;
+       void *zpage = (void *) empty_zero_page;
        long done, size, ret;
 
        done = 0;
index 479e94282910199d8268efd05b5f0e2be0d4526e..9d84a1feefef0e57005f6a31ae50079ebec3a15b 100644 (file)
@@ -458,12 +458,10 @@ static int __init cmm_init(void)
        if (rc)
                goto out_pm;
        cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
-       rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0;
-       if (rc)
-               goto out_kthread;
-       return 0;
+       if (!IS_ERR(cmm_thread_ptr))
+               return 0;
 
-out_kthread:
+       rc = PTR_ERR(cmm_thread_ptr);
        unregister_pm_notifier(&cmm_power_notifier);
 out_pm:
        unregister_oom_notifier(&cmm_oom_nb);
index 2fb9e63b8fc44e58ae415dddefa3a067f48071da..047c3e4c59a2e4ad03ea7812b8a5da8a6ab20f9a 100644 (file)
@@ -395,8 +395,13 @@ void __kprobes do_protection_exception(struct pt_regs *regs)
        int fault;
 
        trans_exc_code = regs->int_parm_long;
-       /* Protection exception is suppressing, decrement psw address. */
-       regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16);
+       /*
+        * Protection exceptions are suppressing, decrement psw address.
+        * The exception to this rule are aborted transactions, for these
+        * the PSW already points to the correct location.
+        */
+       if (!(regs->int_code & 0x200))
+               regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16);
        /*
         * Check for low-address protection.  This needs to be treated
         * as a special case because the translation exception code
index 49ce6bb2c6416431a3f168134f78ea4b1c71a0b4..9f9c315b4c0780dcf1acfbb74017a156ec908a34 100644 (file)
@@ -63,10 +63,18 @@ static unsigned long __init setup_zero_pages(void)
                break;
        case 0x2097:    /* z10 */
        case 0x2098:    /* z10 */
-       default:
+       case 0x2817:    /* z196 */
+       case 0x2818:    /* z196 */
                order = 2;
                break;
+       case 0x2827:    /* zEC12 */
+       default:
+               order = 5;
+               break;
        }
+       /* Limit number of empty zero pages for small memory sizes */
+       if (order > 2 && totalram_pages <= 16384)
+               order = 2;
 
        empty_zero_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
        if (!empty_zero_page)
index d21040ed5e5901937327e5806f20218b1d880cb8..80adfbf75065d487a572226eafd21450bc84962d 100644 (file)
@@ -9,31 +9,25 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 
+static inline unsigned long sske_frame(unsigned long addr, unsigned char skey)
+{
+       asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],9,0"
+                    : [addr] "+a" (addr) : [skey] "d" (skey));
+       return addr;
+}
+
 void storage_key_init_range(unsigned long start, unsigned long end)
 {
-       unsigned long boundary, function, size;
+       unsigned long boundary, size;
 
        while (start < end) {
-               if (MACHINE_HAS_EDAT2) {
-                       /* set storage keys for a 2GB frame */
-                       function = 0x22000 | PAGE_DEFAULT_KEY;
-                       size = 1UL << 31;
-                       boundary = (start + size) & ~(size - 1);
-                       if (boundary <= end) {
-                               do {
-                                       start = pfmf(function, start);
-                               } while (start < boundary);
-                               continue;
-                       }
-               }
                if (MACHINE_HAS_EDAT1) {
                        /* set storage keys for a 1MB frame */
-                       function = 0x21000 | PAGE_DEFAULT_KEY;
                        size = 1UL << 20;
                        boundary = (start + size) & ~(size - 1);
                        if (boundary <= end) {
                                do {
-                                       start = pfmf(function, start);
+                                       start = sske_frame(start, PAGE_DEFAULT_KEY);
                                } while (start < boundary);
                                continue;
                        }
index ae44d2a34313258b7a570a25cab979c24c4f5a20..bd954e96f51c8ea0256a9244f15c4a0349adc6b1 100644 (file)
@@ -379,75 +379,183 @@ out_unmap:
 }
 EXPORT_SYMBOL_GPL(gmap_map_segment);
 
-/*
- * this function is assumed to be called with mmap_sem held
- */
-unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
+static unsigned long *gmap_table_walk(unsigned long address, struct gmap *gmap)
 {
-       unsigned long *table, vmaddr, segment;
-       struct mm_struct *mm;
-       struct gmap_pgtable *mp;
-       struct gmap_rmap *rmap;
-       struct vm_area_struct *vma;
-       struct page *page;
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
+       unsigned long *table;
 
-       current->thread.gmap_addr = address;
-       mm = gmap->mm;
-       /* Walk the gmap address space page table */
        table = gmap->table + ((address >> 53) & 0x7ff);
        if (unlikely(*table & _REGION_ENTRY_INV))
-               return -EFAULT;
+               return ERR_PTR(-EFAULT);
        table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
        table = table + ((address >> 42) & 0x7ff);
        if (unlikely(*table & _REGION_ENTRY_INV))
-               return -EFAULT;
+               return ERR_PTR(-EFAULT);
        table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
        table = table + ((address >> 31) & 0x7ff);
        if (unlikely(*table & _REGION_ENTRY_INV))
-               return -EFAULT;
+               return ERR_PTR(-EFAULT);
        table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
        table = table + ((address >> 20) & 0x7ff);
+       return table;
+}
+
+/**
+ * __gmap_translate - translate a guest address to a user space address
+ * @address: guest address
+ * @gmap: pointer to guest mapping meta data structure
+ *
+ * Returns user space address which corresponds to the guest address or
+ * -EFAULT if no such mapping exists.
+ * This function does not establish potentially missing page table entries.
+ * The mmap_sem of the mm that belongs to the address space must be held
+ * when this function gets called.
+ */
+unsigned long __gmap_translate(unsigned long address, struct gmap *gmap)
+{
+       unsigned long *segment_ptr, vmaddr, segment;
+       struct gmap_pgtable *mp;
+       struct page *page;
 
+       current->thread.gmap_addr = address;
+       segment_ptr = gmap_table_walk(address, gmap);
+       if (IS_ERR(segment_ptr))
+               return PTR_ERR(segment_ptr);
        /* Convert the gmap address to an mm address. */
-       segment = *table;
-       if (likely(!(segment & _SEGMENT_ENTRY_INV))) {
+       segment = *segment_ptr;
+       if (!(segment & _SEGMENT_ENTRY_INV)) {
                page = pfn_to_page(segment >> PAGE_SHIFT);
                mp = (struct gmap_pgtable *) page->index;
                return mp->vmaddr | (address & ~PMD_MASK);
        } else if (segment & _SEGMENT_ENTRY_RO) {
                vmaddr = segment & _SEGMENT_ENTRY_ORIGIN;
-               vma = find_vma(mm, vmaddr);
-               if (!vma || vma->vm_start > vmaddr)
-                       return -EFAULT;
-
-               /* Walk the parent mm page table */
-               pgd = pgd_offset(mm, vmaddr);
-               pud = pud_alloc(mm, pgd, vmaddr);
-               if (!pud)
-                       return -ENOMEM;
-               pmd = pmd_alloc(mm, pud, vmaddr);
-               if (!pmd)
-                       return -ENOMEM;
-               if (!pmd_present(*pmd) &&
-                   __pte_alloc(mm, vma, pmd, vmaddr))
-                       return -ENOMEM;
-               /* pmd now points to a valid segment table entry. */
-               rmap = kmalloc(sizeof(*rmap), GFP_KERNEL|__GFP_REPEAT);
-               if (!rmap)
-                       return -ENOMEM;
-               /* Link gmap segment table entry location to page table. */
-               page = pmd_page(*pmd);
-               mp = (struct gmap_pgtable *) page->index;
-               rmap->entry = table;
-               spin_lock(&mm->page_table_lock);
+               return vmaddr | (address & ~PMD_MASK);
+       }
+       return -EFAULT;
+}
+EXPORT_SYMBOL_GPL(__gmap_translate);
+
+/**
+ * gmap_translate - translate a guest address to a user space address
+ * @address: guest address
+ * @gmap: pointer to guest mapping meta data structure
+ *
+ * Returns user space address which corresponds to the guest address or
+ * -EFAULT if no such mapping exists.
+ * This function does not establish potentially missing page table entries.
+ */
+unsigned long gmap_translate(unsigned long address, struct gmap *gmap)
+{
+       unsigned long rc;
+
+       down_read(&gmap->mm->mmap_sem);
+       rc = __gmap_translate(address, gmap);
+       up_read(&gmap->mm->mmap_sem);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(gmap_translate);
+
+static int gmap_connect_pgtable(unsigned long segment,
+                               unsigned long *segment_ptr,
+                               struct gmap *gmap)
+{
+       unsigned long vmaddr;
+       struct vm_area_struct *vma;
+       struct gmap_pgtable *mp;
+       struct gmap_rmap *rmap;
+       struct mm_struct *mm;
+       struct page *page;
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+
+       mm = gmap->mm;
+       vmaddr = segment & _SEGMENT_ENTRY_ORIGIN;
+       vma = find_vma(mm, vmaddr);
+       if (!vma || vma->vm_start > vmaddr)
+               return -EFAULT;
+       /* Walk the parent mm page table */
+       pgd = pgd_offset(mm, vmaddr);
+       pud = pud_alloc(mm, pgd, vmaddr);
+       if (!pud)
+               return -ENOMEM;
+       pmd = pmd_alloc(mm, pud, vmaddr);
+       if (!pmd)
+               return -ENOMEM;
+       if (!pmd_present(*pmd) &&
+           __pte_alloc(mm, vma, pmd, vmaddr))
+               return -ENOMEM;
+       /* pmd now points to a valid segment table entry. */
+       rmap = kmalloc(sizeof(*rmap), GFP_KERNEL|__GFP_REPEAT);
+       if (!rmap)
+               return -ENOMEM;
+       /* Link gmap segment table entry location to page table. */
+       page = pmd_page(*pmd);
+       mp = (struct gmap_pgtable *) page->index;
+       rmap->entry = segment_ptr;
+       spin_lock(&mm->page_table_lock);
+       if (*segment_ptr == segment) {
                list_add(&rmap->list, &mp->mapper);
-               spin_unlock(&mm->page_table_lock);
                /* Set gmap segment table entry to page table. */
-               *table = pmd_val(*pmd) & PAGE_MASK;
-               return vmaddr | (address & ~PMD_MASK);
+               *segment_ptr = pmd_val(*pmd) & PAGE_MASK;
+               rmap = NULL;
+       }
+       spin_unlock(&mm->page_table_lock);
+       kfree(rmap);
+       return 0;
+}
+
+static void gmap_disconnect_pgtable(struct mm_struct *mm, unsigned long *table)
+{
+       struct gmap_rmap *rmap, *next;
+       struct gmap_pgtable *mp;
+       struct page *page;
+       int flush;
+
+       flush = 0;
+       spin_lock(&mm->page_table_lock);
+       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+       mp = (struct gmap_pgtable *) page->index;
+       list_for_each_entry_safe(rmap, next, &mp->mapper, list) {
+               *rmap->entry =
+                       _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
+               list_del(&rmap->list);
+               kfree(rmap);
+               flush = 1;
+       }
+       spin_unlock(&mm->page_table_lock);
+       if (flush)
+               __tlb_flush_global();
+}
+
+/*
+ * this function is assumed to be called with mmap_sem held
+ */
+unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
+{
+       unsigned long *segment_ptr, segment;
+       struct gmap_pgtable *mp;
+       struct page *page;
+       int rc;
+
+       current->thread.gmap_addr = address;
+       segment_ptr = gmap_table_walk(address, gmap);
+       if (IS_ERR(segment_ptr))
+               return -EFAULT;
+       /* Convert the gmap address to an mm address. */
+       while (1) {
+               segment = *segment_ptr;
+               if (!(segment & _SEGMENT_ENTRY_INV)) {
+                       /* Page table is present */
+                       page = pfn_to_page(segment >> PAGE_SHIFT);
+                       mp = (struct gmap_pgtable *) page->index;
+                       return mp->vmaddr | (address & ~PMD_MASK);
+               }
+               if (!(segment & _SEGMENT_ENTRY_RO))
+                       /* Nothing mapped in the gmap address space. */
+                       break;
+               rc = gmap_connect_pgtable(segment, segment_ptr, gmap);
+               if (rc)
+                       return rc;
        }
        return -EFAULT;
 }
@@ -511,29 +619,6 @@ void gmap_discard(unsigned long from, unsigned long to, struct gmap *gmap)
 }
 EXPORT_SYMBOL_GPL(gmap_discard);
 
-void gmap_unmap_notifier(struct mm_struct *mm, unsigned long *table)
-{
-       struct gmap_rmap *rmap, *next;
-       struct gmap_pgtable *mp;
-       struct page *page;
-       int flush;
-
-       flush = 0;
-       spin_lock(&mm->page_table_lock);
-       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-       mp = (struct gmap_pgtable *) page->index;
-       list_for_each_entry_safe(rmap, next, &mp->mapper, list) {
-               *rmap->entry =
-                       _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
-               list_del(&rmap->list);
-               kfree(rmap);
-               flush = 1;
-       }
-       spin_unlock(&mm->page_table_lock);
-       if (flush)
-               __tlb_flush_global();
-}
-
 static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
                                                    unsigned long vmaddr)
 {
@@ -586,8 +671,8 @@ static inline void page_table_free_pgste(unsigned long *table)
 {
 }
 
-static inline void gmap_unmap_notifier(struct mm_struct *mm,
-                                         unsigned long *table)
+static inline void gmap_disconnect_pgtable(struct mm_struct *mm,
+                                          unsigned long *table)
 {
 }
 
@@ -653,7 +738,7 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
        unsigned int bit, mask;
 
        if (mm_has_pgste(mm)) {
-               gmap_unmap_notifier(mm, table);
+               gmap_disconnect_pgtable(mm, table);
                return page_table_free_pgste(table);
        }
        /* Free 1K/2K page table fragment of a 4K page */
@@ -696,7 +781,7 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table)
 
        mm = tlb->mm;
        if (mm_has_pgste(mm)) {
-               gmap_unmap_notifier(mm, table);
+               gmap_disconnect_pgtable(mm, table);
                table = (unsigned long *) (__pa(table) | FRAG_MASK);
                tlb_remove_table(tlb, table);
                return;
index 0972e91cced229a5162cd893f871667b78b42760..82f165f8078c1b2fc209495bcc2847b2602e210d 100644 (file)
@@ -747,10 +747,9 @@ void bpf_jit_compile(struct sk_filter *fp)
 
        if (!bpf_jit_enable)
                return;
-       addrs = kmalloc(fp->len * sizeof(*addrs), GFP_KERNEL);
+       addrs = kcalloc(fp->len, sizeof(*addrs), GFP_KERNEL);
        if (addrs == NULL)
                return;
-       memset(addrs, 0, fp->len * sizeof(*addrs));
        memset(&jit, 0, sizeof(cjit));
        memset(&cjit, 0, sizeof(cjit));
 
index f0f426a113ceb8e111bb0fe6c23f8943a989b56a..086a2e37935d22cd48d9cb879d30651d89c03e2f 100644 (file)
@@ -2,5 +2,5 @@
 # Makefile for the s390 PCI subsystem.
 #
 
-obj-$(CONFIG_PCI)      += pci.o pci_dma.o pci_clp.o pci_msi.o \
-                          pci_sysfs.o pci_event.o pci_debug.o
+obj-$(CONFIG_PCI)      += pci.o pci_dma.o pci_clp.o pci_msi.o pci_sysfs.o \
+                          pci_event.o pci_debug.o pci_insn.o
index 27b4c17855b9dfdd60ac8fa480fe935428094914..e6f15b5d8b7d0f8d15c18d71869b5df488606056 100644 (file)
@@ -99,9 +99,6 @@ static int __read_mostly aisb_max;
 static struct kmem_cache *zdev_irq_cache;
 static struct kmem_cache *zdev_fmb_cache;
 
-debug_info_t *pci_debug_msg_id;
-debug_info_t *pci_debug_err_id;
-
 static inline int irq_to_msi_nr(unsigned int irq)
 {
        return irq & ZPCI_MSI_MASK;
@@ -179,7 +176,7 @@ static int zpci_register_airq(struct zpci_dev *zdev, unsigned int aisb,
        fib->aisb = (u64) bucket->aisb + aisb / 8;
        fib->aisbo = aisb & ZPCI_MSI_MASK;
 
-       rc = mpcifc_instr(req, fib);
+       rc = s390pci_mod_fc(req, fib);
        pr_debug("%s mpcifc returned noi: %d\n", __func__, fib->noi);
 
        free_page((unsigned long) fib);
@@ -209,7 +206,7 @@ static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args
        fib->iota = args->iota;
        fib->fmb_addr = args->fmb_addr;
 
-       rc = mpcifc_instr(req, fib);
+       rc = s390pci_mod_fc(req, fib);
        free_page((unsigned long) fib);
        return rc;
 }
@@ -249,10 +246,9 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
        if (zdev->fmb)
                return -EINVAL;
 
-       zdev->fmb = kmem_cache_alloc(zdev_fmb_cache, GFP_KERNEL);
+       zdev->fmb = kmem_cache_zalloc(zdev_fmb_cache, GFP_KERNEL);
        if (!zdev->fmb)
                return -ENOMEM;
-       memset(zdev->fmb, 0, sizeof(*zdev->fmb));
        WARN_ON((u64) zdev->fmb & 0xf);
 
        args.fmb_addr = virt_to_phys(zdev->fmb);
@@ -284,12 +280,12 @@ static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len)
        u64 data;
        int rc;
 
-       rc = pcilg_instr(&data, req, offset);
-       data = data << ((8 - len) * 8);
-       data = le64_to_cpu(data);
-       if (!rc)
+       rc = s390pci_load(&data, req, offset);
+       if (!rc) {
+               data = data << ((8 - len) * 8);
+               data = le64_to_cpu(data);
                *val = (u32) data;
-       else
+       else
                *val = 0xffffffff;
        return rc;
 }
@@ -302,7 +298,7 @@ static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len)
 
        data = cpu_to_le64(data);
        data = data >> ((8 - len) * 8);
-       rc = pcistg_instr(data, req, offset);
+       rc = s390pci_store(data, req, offset);
        return rc;
 }
 
@@ -409,20 +405,28 @@ static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
                    int size, u32 *val)
 {
        struct zpci_dev *zdev = get_zdev_by_bus(bus);
+       int ret;
 
        if (!zdev || devfn != ZPCI_DEVFN)
-               return 0;
-       return zpci_cfg_load(zdev, where, val, size);
+               ret = -ENODEV;
+       else
+               ret = zpci_cfg_load(zdev, where, val, size);
+
+       return ret;
 }
 
 static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
                     int size, u32 val)
 {
        struct zpci_dev *zdev = get_zdev_by_bus(bus);
+       int ret;
 
        if (!zdev || devfn != ZPCI_DEVFN)
-               return 0;
-       return zpci_cfg_store(zdev, where, val, size);
+               ret = -ENODEV;
+       else
+               ret = zpci_cfg_store(zdev, where, val, size);
+
+       return ret;
 }
 
 static struct pci_ops pci_root_ops = {
@@ -474,7 +478,7 @@ scan:
        }
 
        /* enable interrupts again */
-       sic_instr(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
+       set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
 
        /* check again to not lose initiative */
        rmb();
@@ -596,19 +600,6 @@ static void zpci_map_resources(struct zpci_dev *zdev)
        }
 };
 
-static void zpci_unmap_resources(struct pci_dev *pdev)
-{
-       resource_size_t len;
-       int i;
-
-       for (i = 0; i < PCI_BAR_COUNT; i++) {
-               len = pci_resource_len(pdev, i);
-               if (!len)
-                       continue;
-               pci_iounmap(pdev, (void *) pdev->resource[i].start);
-       }
-};
-
 struct zpci_dev *zpci_alloc_device(void)
 {
        struct zpci_dev *zdev;
@@ -636,32 +627,6 @@ void zpci_free_device(struct zpci_dev *zdev)
        kfree(zdev);
 }
 
-/* Called on removal of pci_dev, leaves zpci and bus device */
-static void zpci_remove_device(struct pci_dev *pdev)
-{
-       struct zpci_dev *zdev = get_zdev(pdev);
-
-       dev_info(&pdev->dev, "Removing device %u\n", zdev->domain);
-       zdev->state = ZPCI_FN_STATE_CONFIGURED;
-       zpci_dma_exit_device(zdev);
-       zpci_fmb_disable_device(zdev);
-       zpci_sysfs_remove_device(&pdev->dev);
-       zpci_unmap_resources(pdev);
-       list_del(&zdev->entry);         /* can be called from init */
-       zdev->pdev = NULL;
-}
-
-static void zpci_scan_devices(void)
-{
-       struct zpci_dev *zdev;
-
-       mutex_lock(&zpci_list_lock);
-       list_for_each_entry(zdev, &zpci_list, entry)
-               if (zdev->state == ZPCI_FN_STATE_CONFIGURED)
-                       zpci_scan_device(zdev);
-       mutex_unlock(&zpci_list_lock);
-}
-
 /*
  * Too late for any s390 specific setup, since interrupts must be set up
  * already which requires DMA setup too and the pci scan will access the
@@ -688,12 +653,6 @@ int pcibios_enable_device(struct pci_dev *pdev, int mask)
        return 0;
 }
 
-void pcibios_disable_device(struct pci_dev *pdev)
-{
-       zpci_remove_device(pdev);
-       pdev->sysdata = NULL;
-}
-
 int pcibios_add_platform_entries(struct pci_dev *pdev)
 {
        return zpci_sysfs_add_device(&pdev->dev);
@@ -789,7 +748,7 @@ static int __init zpci_irq_init(void)
        spin_lock_init(&bucket->lock);
        /* set summary to 1 to be called every time for the ISC */
        *zpci_irq_si = 1;
-       sic_instr(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
+       set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
        return 0;
 
 out_ai:
@@ -872,7 +831,19 @@ static void zpci_free_iomap(struct zpci_dev *zdev, int entry)
        spin_unlock(&zpci_iomap_lock);
 }
 
-static int zpci_create_device_bus(struct zpci_dev *zdev)
+int pcibios_add_device(struct pci_dev *pdev)
+{
+       struct zpci_dev *zdev = get_zdev(pdev);
+
+       zdev->pdev = pdev;
+       zpci_debug_init_device(zdev);
+       zpci_fmb_enable_device(zdev);
+       zpci_map_resources(zdev);
+
+       return 0;
+}
+
+static int zpci_scan_bus(struct zpci_dev *zdev)
 {
        struct resource *res;
        LIST_HEAD(resources);
@@ -909,8 +880,8 @@ static int zpci_create_device_bus(struct zpci_dev *zdev)
                pci_add_resource(&resources, res);
        }
 
-       zdev->bus = pci_create_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
-                                       zdev, &resources);
+       zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
+                                     zdev, &resources);
        if (!zdev->bus)
                return -EIO;
 
@@ -959,6 +930,13 @@ out:
 }
 EXPORT_SYMBOL_GPL(zpci_enable_device);
 
+int zpci_disable_device(struct zpci_dev *zdev)
+{
+       zpci_dma_exit_device(zdev);
+       return clp_disable_fh(zdev);
+}
+EXPORT_SYMBOL_GPL(zpci_disable_device);
+
 int zpci_create_device(struct zpci_dev *zdev)
 {
        int rc;
@@ -967,9 +945,16 @@ int zpci_create_device(struct zpci_dev *zdev)
        if (rc)
                goto out;
 
-       rc = zpci_create_device_bus(zdev);
+       if (zdev->state == ZPCI_FN_STATE_CONFIGURED) {
+               rc = zpci_enable_device(zdev);
+               if (rc)
+                       goto out_free;
+
+               zdev->state = ZPCI_FN_STATE_ONLINE;
+       }
+       rc = zpci_scan_bus(zdev);
        if (rc)
-               goto out_bus;
+               goto out_disable;
 
        mutex_lock(&zpci_list_lock);
        list_add_tail(&zdev->entry, &zpci_list);
@@ -977,21 +962,12 @@ int zpci_create_device(struct zpci_dev *zdev)
                hotplug_ops->create_slot(zdev);
        mutex_unlock(&zpci_list_lock);
 
-       if (zdev->state == ZPCI_FN_STATE_STANDBY)
-               return 0;
-
-       rc = zpci_enable_device(zdev);
-       if (rc)
-               goto out_start;
        return 0;
 
-out_start:
-       mutex_lock(&zpci_list_lock);
-       list_del(&zdev->entry);
-       if (hotplug_ops)
-               hotplug_ops->remove_slot(zdev);
-       mutex_unlock(&zpci_list_lock);
-out_bus:
+out_disable:
+       if (zdev->state == ZPCI_FN_STATE_ONLINE)
+               zpci_disable_device(zdev);
+out_free:
        zpci_free_domain(zdev);
 out:
        return rc;
@@ -1016,15 +992,9 @@ int zpci_scan_device(struct zpci_dev *zdev)
                goto out;
        }
 
-       zpci_debug_init_device(zdev);
-       zpci_fmb_enable_device(zdev);
-       zpci_map_resources(zdev);
        pci_bus_add_devices(zdev->bus);
 
-       /* now that pdev was added to the bus mark it as used */
-       zdev->state = ZPCI_FN_STATE_ONLINE;
        return 0;
-
 out:
        zpci_dma_exit_device(zdev);
        clp_disable_fh(zdev);
@@ -1087,13 +1057,13 @@ void zpci_deregister_hp_ops(void)
 }
 EXPORT_SYMBOL_GPL(zpci_deregister_hp_ops);
 
-unsigned int s390_pci_probe = 1;
+unsigned int s390_pci_probe;
 EXPORT_SYMBOL_GPL(s390_pci_probe);
 
 char * __init pcibios_setup(char *str)
 {
-       if (!strcmp(str, "off")) {
-               s390_pci_probe = 0;
+       if (!strcmp(str, "on")) {
+               s390_pci_probe = 1;
                return NULL;
        }
        return str;
@@ -1138,7 +1108,6 @@ static int __init pci_base_init(void)
        if (rc)
                goto out_find;
 
-       zpci_scan_devices();
        return 0;
 
 out_find:
index f339fe2feb15d0b5a786554ca0da960cbf9a2795..bd34359d1546cc0c0eb4625ab3a25e0c72470604 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <asm/pci_debug.h>
 #include <asm/pci_clp.h>
 
 /*
@@ -144,6 +145,7 @@ int clp_add_pci_device(u32 fid, u32 fh, int configured)
        struct zpci_dev *zdev;
        int rc;
 
+       zpci_dbg(3, "add fid:%x, fh:%x, c:%d\n", fid, fh, configured);
        zdev = zpci_alloc_device();
        if (IS_ERR(zdev))
                return PTR_ERR(zdev);
@@ -204,8 +206,8 @@ static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
        if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
                *fh = rrb->response.fh;
        else {
-               pr_err("Set PCI FN failed with response: %x  cc: %d\n",
-                       rrb->response.hdr.rsp, rc);
+               zpci_dbg(0, "SPF fh:%x, cc:%d, resp:%x\n", *fh, rc,
+                        rrb->response.hdr.rsp);
                rc = -EIO;
        }
        clp_free_block(rrb);
@@ -221,6 +223,8 @@ int clp_enable_fh(struct zpci_dev *zdev, u8 nr_dma_as)
        if (!rc)
                /* Success -> store enabled handle in zdev */
                zdev->fh = fh;
+
+       zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
        return rc;
 }
 
@@ -237,9 +241,8 @@ int clp_disable_fh(struct zpci_dev *zdev)
        if (!rc)
                /* Success -> store disabled handle in zdev */
                zdev->fh = fh;
-       else
-               dev_err(&zdev->pdev->dev,
-                       "Failed to disable fn handle: 0x%x\n", fh);
+
+       zpci_dbg(3, "dis fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
        return rc;
 }
 
index a5d07bc2a547d723211f9f47afc562769217e650..771b82359af421b1a213b276b39bbe0b8d84c5a6 100644 (file)
 #include <linux/kernel.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <asm/debug.h>
 
 #include <asm/pci_dma.h>
 
 static struct dentry *debugfs_root;
+debug_info_t *pci_debug_msg_id;
+EXPORT_SYMBOL_GPL(pci_debug_msg_id);
+debug_info_t *pci_debug_err_id;
+EXPORT_SYMBOL_GPL(pci_debug_err_id);
 
 static char *pci_perf_names[] = {
        /* hardware counters */
@@ -168,7 +173,6 @@ int __init zpci_debug_init(void)
                return -EINVAL;
        debug_register_view(pci_debug_msg_id, &debug_sprintf_view);
        debug_set_level(pci_debug_msg_id, 3);
-       zpci_dbg("Debug view initialized\n");
 
        /* error log */
        pci_debug_err_id = debug_register("pci_error", 2, 1, 16);
@@ -176,7 +180,6 @@ int __init zpci_debug_init(void)
                return -EINVAL;
        debug_register_view(pci_debug_err_id, &debug_hex_ascii_view);
        debug_set_level(pci_debug_err_id, 6);
-       zpci_err("Debug view initialized\n");
 
        debugfs_root = debugfs_create_dir("pci", NULL);
        return 0;
index a547419907c3a46be4e7a64c36f3f1a776abcfcf..f8e69d5bc0a90631cb12c43fbe3b01e02786e7ea 100644 (file)
@@ -169,8 +169,9 @@ static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa,
                 * needs to be redone!
                 */
                goto no_refresh;
-       rc = rpcit_instr((u64) zdev->fh << 32, start_dma_addr,
-                         nr_pages * PAGE_SIZE);
+
+       rc = s390pci_refresh_trans((u64) zdev->fh << 32, start_dma_addr,
+                                  nr_pages * PAGE_SIZE);
 
 no_refresh:
        spin_unlock_irqrestore(&zdev->dma_table_lock, irq_flags);
@@ -268,8 +269,6 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
        int flags = ZPCI_PTE_VALID;
        dma_addr_t dma_addr;
 
-       WARN_ON_ONCE(offset > PAGE_SIZE);
-
        /* This rounds up number of pages based on size and offset */
        nr_pages = iommu_num_pages(pa, size, PAGE_SIZE);
        iommu_page_index = dma_alloc_iommu(zdev, nr_pages);
@@ -291,7 +290,7 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
 
        if (!dma_update_trans(zdev, pa, dma_addr, size, flags)) {
                atomic64_add(nr_pages, (atomic64_t *) &zdev->fmb->mapped_pages);
-               return dma_addr + offset;
+               return dma_addr + (offset & ~PAGE_MASK);
        }
 
 out_free:
diff --git a/arch/s390/pci/pci_insn.c b/arch/s390/pci/pci_insn.c
new file mode 100644 (file)
index 0000000..22eeb9d
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * s390 specific pci instructions
+ *
+ * Copyright IBM Corp. 2013
+ */
+
+#include <linux/export.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <asm/pci_insn.h>
+#include <asm/processor.h>
+
+#define ZPCI_INSN_BUSY_DELAY   1       /* 1 microsecond */
+
+/* Modify PCI Function Controls */
+static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
+{
+       u8 cc;
+
+       asm volatile (
+               "       .insn   rxy,0xe300000000d0,%[req],%[fib]\n"
+               "       ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               : [cc] "=d" (cc), [req] "+d" (req), [fib] "+Q" (*fib)
+               : : "cc");
+       *status = req >> 24 & 0xff;
+       return cc;
+}
+
+int s390pci_mod_fc(u64 req, struct zpci_fib *fib)
+{
+       u8 cc, status;
+
+       do {
+               cc = __mpcifc(req, fib, &status);
+               if (cc == 2)
+                       msleep(ZPCI_INSN_BUSY_DELAY);
+       } while (cc == 2);
+
+       if (cc)
+               printk_once(KERN_ERR "%s: error cc: %d  status: %d\n",
+                            __func__, cc, status);
+       return (cc) ? -EIO : 0;
+}
+
+/* Refresh PCI Translations */
+static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
+{
+       register u64 __addr asm("2") = addr;
+       register u64 __range asm("3") = range;
+       u8 cc;
+
+       asm volatile (
+               "       .insn   rre,0xb9d30000,%[fn],%[addr]\n"
+               "       ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               : [cc] "=d" (cc), [fn] "+d" (fn)
+               : [addr] "d" (__addr), "d" (__range)
+               : "cc");
+       *status = fn >> 24 & 0xff;
+       return cc;
+}
+
+int s390pci_refresh_trans(u64 fn, u64 addr, u64 range)
+{
+       u8 cc, status;
+
+       do {
+               cc = __rpcit(fn, addr, range, &status);
+               if (cc == 2)
+                       udelay(ZPCI_INSN_BUSY_DELAY);
+       } while (cc == 2);
+
+       if (cc)
+               printk_once(KERN_ERR "%s: error cc: %d  status: %d  dma_addr: %Lx  size: %Lx\n",
+                           __func__, cc, status, addr, range);
+       return (cc) ? -EIO : 0;
+}
+
+/* Set Interruption Controls */
+void set_irq_ctrl(u16 ctl, char *unused, u8 isc)
+{
+       asm volatile (
+               "       .insn   rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n"
+               : : [ctl] "d" (ctl), [isc] "d" (isc << 27), [u] "Q" (*unused));
+}
+
+/* PCI Load */
+static inline int __pcilg(u64 *data, u64 req, u64 offset, u8 *status)
+{
+       register u64 __req asm("2") = req;
+       register u64 __offset asm("3") = offset;
+       int cc = -ENXIO;
+       u64 __data;
+
+       asm volatile (
+               "       .insn   rre,0xb9d20000,%[data],%[req]\n"
+               "0:     ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               "1:\n"
+               EX_TABLE(0b, 1b)
+               : [cc] "+d" (cc), [data] "=d" (__data), [req] "+d" (__req)
+               :  "d" (__offset)
+               : "cc");
+       *status = __req >> 24 & 0xff;
+       if (!cc)
+               *data = __data;
+
+       return cc;
+}
+
+int s390pci_load(u64 *data, u64 req, u64 offset)
+{
+       u8 status;
+       int cc;
+
+       do {
+               cc = __pcilg(data, req, offset, &status);
+               if (cc == 2)
+                       udelay(ZPCI_INSN_BUSY_DELAY);
+       } while (cc == 2);
+
+       if (cc)
+               printk_once(KERN_ERR "%s: error cc: %d  status: %d  req: %Lx  offset: %Lx\n",
+                           __func__, cc, status, req, offset);
+       return (cc > 0) ? -EIO : cc;
+}
+EXPORT_SYMBOL_GPL(s390pci_load);
+
+/* PCI Store */
+static inline int __pcistg(u64 data, u64 req, u64 offset, u8 *status)
+{
+       register u64 __req asm("2") = req;
+       register u64 __offset asm("3") = offset;
+       int cc = -ENXIO;
+
+       asm volatile (
+               "       .insn   rre,0xb9d00000,%[data],%[req]\n"
+               "0:     ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               "1:\n"
+               EX_TABLE(0b, 1b)
+               : [cc] "+d" (cc), [req] "+d" (__req)
+               : "d" (__offset), [data] "d" (data)
+               : "cc");
+       *status = __req >> 24 & 0xff;
+       return cc;
+}
+
+int s390pci_store(u64 data, u64 req, u64 offset)
+{
+       u8 status;
+       int cc;
+
+       do {
+               cc = __pcistg(data, req, offset, &status);
+               if (cc == 2)
+                       udelay(ZPCI_INSN_BUSY_DELAY);
+       } while (cc == 2);
+
+       if (cc)
+               printk_once(KERN_ERR "%s: error cc: %d  status: %d  req: %Lx  offset: %Lx\n",
+                       __func__, cc, status, req, offset);
+       return (cc > 0) ? -EIO : cc;
+}
+EXPORT_SYMBOL_GPL(s390pci_store);
+
+/* PCI Store Block */
+static inline int __pcistb(const u64 *data, u64 req, u64 offset, u8 *status)
+{
+       int cc = -ENXIO;
+
+       asm volatile (
+               "       .insn   rsy,0xeb00000000d0,%[req],%[offset],%[data]\n"
+               "0:     ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               "1:\n"
+               EX_TABLE(0b, 1b)
+               : [cc] "+d" (cc), [req] "+d" (req)
+               : [offset] "d" (offset), [data] "Q" (*data)
+               : "cc");
+       *status = req >> 24 & 0xff;
+       return cc;
+}
+
+int s390pci_store_block(const u64 *data, u64 req, u64 offset)
+{
+       u8 status;
+       int cc;
+
+       do {
+               cc = __pcistb(data, req, offset, &status);
+               if (cc == 2)
+                       udelay(ZPCI_INSN_BUSY_DELAY);
+       } while (cc == 2);
+
+       if (cc)
+               printk_once(KERN_ERR "%s: error cc: %d  status: %d  req: %Lx  offset: %Lx\n",
+                           __func__, cc, status, req, offset);
+       return (cc > 0) ? -EIO : cc;
+}
+EXPORT_SYMBOL_GPL(s390pci_store_block);
index 0297931335e158f53ab8c556fdf7cb42190146c7..b097aed05a9b8585531278fc2f5d38d988d2a461 100644 (file)
@@ -18,8 +18,9 @@
 
 /* mapping of irq numbers to msi_desc */
 static struct hlist_head *msi_hash;
-static unsigned int msihash_shift = 6;
-#define msi_hashfn(nr) hash_long(nr, msihash_shift)
+static const unsigned int msi_hash_bits = 8;
+#define MSI_HASH_BUCKETS (1U << msi_hash_bits)
+#define msi_hashfn(nr) hash_long(nr, msi_hash_bits)
 
 static DEFINE_SPINLOCK(msi_map_lock);
 
@@ -74,6 +75,7 @@ int zpci_setup_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi,
        map->irq = nr;
        map->msi = msi;
        zdev->msi_map[nr & ZPCI_MSI_MASK] = map;
+       INIT_HLIST_NODE(&map->msi_chain);
 
        pr_debug("%s hashing irq: %u  to bucket nr: %llu\n",
                __func__, nr, msi_hashfn(nr));
@@ -125,11 +127,11 @@ int __init zpci_msihash_init(void)
 {
        unsigned int i;
 
-       msi_hash = kmalloc(256 * sizeof(*msi_hash), GFP_KERNEL);
+       msi_hash = kmalloc(MSI_HASH_BUCKETS * sizeof(*msi_hash), GFP_KERNEL);
        if (!msi_hash)
                return -ENOMEM;
 
-       for (i = 0; i < (1U << msihash_shift); i++)
+       for (i = 0; i < MSI_HASH_BUCKETS; i++)
                INIT_HLIST_HEAD(&msi_hash[i]);
        return 0;
 }
index e26d430ce2fdb94b7c85281db75367acf41e2321..ff18e3cfb6b1ffe3e75df94fdd68319b912ab1d8 100644 (file)
@@ -2,11 +2,16 @@
 
 
 generic-y += clkdev.h
+generic-y += cputime.h
 generic-y += div64.h
+generic-y += emergency-restart.h
 generic-y += exec.h
 generic-y += local64.h
+generic-y += mutex.h
 generic-y += irq_regs.h
 generic-y += local.h
 generic-y += module.h
+generic-y += serial.h
 generic-y += trace_clock.h
+generic-y += types.h
 generic-y += word-at-a-time.h
diff --git a/arch/sparc/include/asm/cputime.h b/arch/sparc/include/asm/cputime.h
deleted file mode 100644 (file)
index 1a642b8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SPARC_CPUTIME_H
-#define __SPARC_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __SPARC_CPUTIME_H */
diff --git a/arch/sparc/include/asm/emergency-restart.h b/arch/sparc/include/asm/emergency-restart.h
deleted file mode 100644 (file)
index 108d8c4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/sparc/include/asm/mutex.h b/arch/sparc/include/asm/mutex.h
deleted file mode 100644 (file)
index 458c1f7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
index 08fcce90316b36654dea14af5525a94a0cded6e8..7619f2f792aff549905ca49d1a70b3cd7514979c 100644 (file)
@@ -915,6 +915,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
        return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
 }
 
+#include <asm/tlbflush.h>
 #include <asm-generic/pgtable.h>
 
 /* We provide our own get_unmapped_area to cope with VA holes and
diff --git a/arch/sparc/include/asm/serial.h b/arch/sparc/include/asm/serial.h
deleted file mode 100644 (file)
index f90d61c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SPARC_SERIAL_H
-#define __SPARC_SERIAL_H
-
-#define BASE_BAUD ( 1843200 / 16 )
-
-#endif /* __SPARC_SERIAL_H */
index b73da3c5f10a9140ba730836d3e496af3e2358c6..3c8917f054dee450fcc48e7f50d189b88bc19401 100644 (file)
@@ -36,7 +36,6 @@ typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long,
                       unsigned long, unsigned long);
 
 void cpu_panic(void);
-extern void smp4m_irq_rotate(int cpu);
 
 /*
  *     General functions that each host system must provide.
@@ -46,7 +45,6 @@ void sun4m_init_smp(void);
 void sun4d_init_smp(void);
 
 void smp_callin(void);
-void smp_boot_cpus(void);
 void smp_store_cpu_info(int);
 
 void smp_resched_interrupt(void);
@@ -107,9 +105,6 @@ extern int hard_smp_processor_id(void);
 
 #define raw_smp_processor_id()         (current_thread_info()->cpu)
 
-#define prof_multiplier(__cpu)         cpu_data(__cpu).multiplier
-#define prof_counter(__cpu)            cpu_data(__cpu).counter
-
 void smp_setup_cpu_possible_map(void);
 
 #endif /* !(__ASSEMBLY__) */
index cad36f56fa03e6605797c4dca13f5127048b47d7..c7de3323819c5389a8c1855f09aa542cd67f4d41 100644 (file)
@@ -18,8 +18,7 @@ do {                                          \
         * and 2 stores in this critical code path.  -DaveM
         */
 #define switch_to(prev, next, last)                                    \
-do {   flush_tlb_pending();                                            \
-       save_and_clear_fpu();                                           \
+do {   save_and_clear_fpu();                                           \
        /* If you are tempted to conditionalize the following */        \
        /* so that ASI is only written if it changes, think again. */   \
        __asm__ __volatile__("wr %%g0, %0, %%asi"                       \
index 2ef463494153a65adec7c7a59a37c0095fda2649..f0d6a9700f4c8351e20be4743d9782c590b9e016 100644 (file)
 struct tlb_batch {
        struct mm_struct *mm;
        unsigned long tlb_nr;
+       unsigned long active;
        unsigned long vaddrs[TLB_BATCH_NR];
 };
 
 extern void flush_tsb_kernel_range(unsigned long start, unsigned long end);
 extern void flush_tsb_user(struct tlb_batch *tb);
+extern void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr);
 
 /* TLB flush operations. */
 
-extern void flush_tlb_pending(void);
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+                                 unsigned long vmaddr)
+{
+}
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+                                  unsigned long start, unsigned long end)
+{
+}
+
+#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
 
-#define flush_tlb_range(vma,start,end) \
-       do { (void)(start); flush_tlb_pending(); } while (0)
-#define flush_tlb_page(vma,addr)       flush_tlb_pending()
-#define flush_tlb_mm(mm)               flush_tlb_pending()
+extern void flush_tlb_pending(void);
+extern void arch_enter_lazy_mmu_mode(void);
+extern void arch_leave_lazy_mmu_mode(void);
+#define arch_flush_lazy_mmu_mode()      do {} while (0)
 
 /* Local cpu only.  */
 extern void __flush_tlb_all(void);
-
+extern void __flush_tlb_page(unsigned long context, unsigned long vaddr);
 extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
 
 #ifndef CONFIG_SMP
@@ -38,15 +54,24 @@ do {        flush_tsb_kernel_range(start,end); \
        __flush_tlb_kernel_range(start,end); \
 } while (0)
 
+static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
+{
+       __flush_tlb_page(CTX_HWBITS(mm->context), vaddr);
+}
+
 #else /* CONFIG_SMP */
 
 extern void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr);
 
 #define flush_tlb_kernel_range(start, end) \
 do {   flush_tsb_kernel_range(start,end); \
        smp_flush_tlb_kernel_range(start, end); \
 } while (0)
 
+#define global_flush_tlb_page(mm, vaddr) \
+       smp_flush_tlb_page(mm, vaddr)
+
 #endif /* ! CONFIG_SMP */
 
 #endif /* _SPARC64_TLBFLUSH_H */
index ce175aff71b75e29fdf65cf70d8a17f2a07c5d2a..b5843ee09fb53a6e4438b29140adbd34d9c887c1 100644 (file)
@@ -44,7 +44,6 @@ header-y += swab.h
 header-y += termbits.h
 header-y += termios.h
 header-y += traps.h
-header-y += types.h
 header-y += uctx.h
 header-y += unistd.h
 header-y += utrap.h
diff --git a/arch/sparc/include/uapi/asm/types.h b/arch/sparc/include/uapi/asm/types.h
deleted file mode 100644 (file)
index 383d156..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _SPARC_TYPES_H
-#define _SPARC_TYPES_H
-/*
- * This file is never included by application software unless
- * explicitly requested (e.g., via linux/types.h) in which case the
- * application is Linux specific so (user-) name space pollution is
- * not a major issue.  However, for interoperability, libraries still
- * need to be careful to avoid a name clashes.
- */
-
-#if defined(__sparc__)
-
-#include <asm-generic/int-ll64.h>
-
-#endif /* defined(__sparc__) */
-
-#endif /* defined(_SPARC_TYPES_H) */
index 537eb66abd0654054aef7402ffaf857ad3971a85..ca64d2a86ec03e4189b88367906456e99de77a14 100644 (file)
@@ -849,7 +849,7 @@ void smp_tsb_sync(struct mm_struct *mm)
 }
 
 extern unsigned long xcall_flush_tlb_mm;
-extern unsigned long xcall_flush_tlb_pending;
+extern unsigned long xcall_flush_tlb_page;
 extern unsigned long xcall_flush_tlb_kernel_range;
 extern unsigned long xcall_fetch_glob_regs;
 extern unsigned long xcall_fetch_glob_pmu;
@@ -1074,23 +1074,56 @@ local_flush_and_out:
        put_cpu();
 }
 
+struct tlb_pending_info {
+       unsigned long ctx;
+       unsigned long nr;
+       unsigned long *vaddrs;
+};
+
+static void tlb_pending_func(void *info)
+{
+       struct tlb_pending_info *t = info;
+
+       __flush_tlb_pending(t->ctx, t->nr, t->vaddrs);
+}
+
 void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs)
 {
        u32 ctx = CTX_HWBITS(mm->context);
+       struct tlb_pending_info info;
        int cpu = get_cpu();
 
+       info.ctx = ctx;
+       info.nr = nr;
+       info.vaddrs = vaddrs;
+
        if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
                cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
        else
-               smp_cross_call_masked(&xcall_flush_tlb_pending,
-                                     ctx, nr, (unsigned long) vaddrs,
-                                     mm_cpumask(mm));
+               smp_call_function_many(mm_cpumask(mm), tlb_pending_func,
+                                      &info, 1);
 
        __flush_tlb_pending(ctx, nr, vaddrs);
 
        put_cpu();
 }
 
+void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
+{
+       unsigned long context = CTX_HWBITS(mm->context);
+       int cpu = get_cpu();
+
+       if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
+               cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
+       else
+               smp_cross_call_masked(&xcall_flush_tlb_page,
+                                     context, vaddr, 0,
+                                     mm_cpumask(mm));
+       __flush_tlb_page(context, vaddr);
+
+       put_cpu();
+}
+
 void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
        start &= PAGE_MASK;
index 48d00e72ce15ba41304f8390ab29324402f052b2..8ec4e9c0251a3e414acf58327b0fd167890caa95 100644 (file)
@@ -119,11 +119,7 @@ void bit_map_clear(struct bit_map *t, int offset, int len)
 
 void bit_map_init(struct bit_map *t, unsigned long *map, int size)
 {
-
-       if ((size & 07) != 0)
-               BUG();
-       memset(map, 0, size>>3);
-
+       bitmap_zero(map, size);
        memset(t, 0, sizeof *t);
        spin_lock_init(&t->lock);
        t->map = map;
index 0f4f7191fbbad93d6600ac409f6baae24c911d5e..28f96f27c7683e1201d5ca6e53409e391594aff4 100644 (file)
@@ -34,7 +34,7 @@
 #define IOMMU_RNGE     IOMMU_RNGE_256MB
 #define IOMMU_START    0xF0000000
 #define IOMMU_WINSIZE  (256*1024*1024U)
-#define IOMMU_NPTES    (IOMMU_WINSIZE/PAGE_SIZE)       /* 64K PTEs, 265KB */
+#define IOMMU_NPTES    (IOMMU_WINSIZE/PAGE_SIZE)       /* 64K PTEs, 256KB */
 #define IOMMU_ORDER    6                               /* 4096 * (1<<6) */
 
 /* srmmu.c */
index c38bb72e3e80e4c122ea469a4edaba8e18cc3939..036c2797dece1c6443894b9e3ce95c066e4142fe 100644 (file)
@@ -280,7 +280,9 @@ static void __init srmmu_nocache_init(void)
                SRMMU_NOCACHE_ALIGN_MAX, 0UL);
        memset(srmmu_nocache_pool, 0, srmmu_nocache_size);
 
-       srmmu_nocache_bitmap = __alloc_bootmem(bitmap_bits >> 3, SMP_CACHE_BYTES, 0UL);
+       srmmu_nocache_bitmap =
+               __alloc_bootmem(BITS_TO_LONGS(bitmap_bits) * sizeof(long),
+                               SMP_CACHE_BYTES, 0UL);
        bit_map_init(&srmmu_nocache_map, srmmu_nocache_bitmap, bitmap_bits);
 
        srmmu_swapper_pg_dir = __srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE);
index ba6ae7ffdc2c9d5d1e3bbbb8d2af3b68a2f2572e..83d89bcb44afcace24b757b02ce5305c1e762afe 100644 (file)
@@ -24,11 +24,17 @@ static DEFINE_PER_CPU(struct tlb_batch, tlb_batch);
 void flush_tlb_pending(void)
 {
        struct tlb_batch *tb = &get_cpu_var(tlb_batch);
+       struct mm_struct *mm = tb->mm;
 
-       if (tb->tlb_nr) {
-               flush_tsb_user(tb);
+       if (!tb->tlb_nr)
+               goto out;
 
-               if (CTX_VALID(tb->mm->context)) {
+       flush_tsb_user(tb);
+
+       if (CTX_VALID(mm->context)) {
+               if (tb->tlb_nr == 1) {
+                       global_flush_tlb_page(mm, tb->vaddrs[0]);
+               } else {
 #ifdef CONFIG_SMP
                        smp_flush_tlb_pending(tb->mm, tb->tlb_nr,
                                              &tb->vaddrs[0]);
@@ -37,12 +43,30 @@ void flush_tlb_pending(void)
                                            tb->tlb_nr, &tb->vaddrs[0]);
 #endif
                }
-               tb->tlb_nr = 0;
        }
 
+       tb->tlb_nr = 0;
+
+out:
        put_cpu_var(tlb_batch);
 }
 
+void arch_enter_lazy_mmu_mode(void)
+{
+       struct tlb_batch *tb = &__get_cpu_var(tlb_batch);
+
+       tb->active = 1;
+}
+
+void arch_leave_lazy_mmu_mode(void)
+{
+       struct tlb_batch *tb = &__get_cpu_var(tlb_batch);
+
+       if (tb->tlb_nr)
+               flush_tlb_pending();
+       tb->active = 0;
+}
+
 static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
                              bool exec)
 {
@@ -60,6 +84,12 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
                nr = 0;
        }
 
+       if (!tb->active) {
+               global_flush_tlb_page(mm, vaddr);
+               flush_tsb_user_page(mm, vaddr);
+               goto out;
+       }
+
        if (nr == 0)
                tb->mm = mm;
 
@@ -68,6 +98,7 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
        if (nr >= TLB_BATCH_NR)
                flush_tlb_pending();
 
+out:
        put_cpu_var(tlb_batch);
 }
 
index 428982b9becfe267b33ad2745efb36b5dc861a11..2cc3bce5ee914a158a16960c4ece028cc959b83a 100644 (file)
@@ -7,11 +7,10 @@
 #include <linux/preempt.h>
 #include <linux/slab.h>
 #include <asm/page.h>
-#include <asm/tlbflush.h>
-#include <asm/tlb.h>
-#include <asm/mmu_context.h>
 #include <asm/pgtable.h>
+#include <asm/mmu_context.h>
 #include <asm/tsb.h>
+#include <asm/tlb.h>
 #include <asm/oplib.h>
 
 extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
@@ -46,23 +45,27 @@ void flush_tsb_kernel_range(unsigned long start, unsigned long end)
        }
 }
 
-static void __flush_tsb_one(struct tlb_batch *tb, unsigned long hash_shift,
-                           unsigned long tsb, unsigned long nentries)
+static void __flush_tsb_one_entry(unsigned long tsb, unsigned long v,
+                                 unsigned long hash_shift,
+                                 unsigned long nentries)
 {
-       unsigned long i;
+       unsigned long tag, ent, hash;
 
-       for (i = 0; i < tb->tlb_nr; i++) {
-               unsigned long v = tb->vaddrs[i];
-               unsigned long tag, ent, hash;
+       v &= ~0x1UL;
+       hash = tsb_hash(v, hash_shift, nentries);
+       ent = tsb + (hash * sizeof(struct tsb));
+       tag = (v >> 22UL);
 
-               v &= ~0x1UL;
+       tsb_flush(ent, tag);
+}
 
-               hash = tsb_hash(v, hash_shift, nentries);
-               ent = tsb + (hash * sizeof(struct tsb));
-               tag = (v >> 22UL);
+static void __flush_tsb_one(struct tlb_batch *tb, unsigned long hash_shift,
+                           unsigned long tsb, unsigned long nentries)
+{
+       unsigned long i;
 
-               tsb_flush(ent, tag);
-       }
+       for (i = 0; i < tb->tlb_nr; i++)
+               __flush_tsb_one_entry(tsb, tb->vaddrs[i], hash_shift, nentries);
 }
 
 void flush_tsb_user(struct tlb_batch *tb)
@@ -90,6 +93,30 @@ void flush_tsb_user(struct tlb_batch *tb)
        spin_unlock_irqrestore(&mm->context.lock, flags);
 }
 
+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr)
+{
+       unsigned long nentries, base, flags;
+
+       spin_lock_irqsave(&mm->context.lock, flags);
+
+       base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
+       nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
+       if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+               base = __pa(base);
+       __flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
+
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+       if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
+               base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
+               nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
+               if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+                       base = __pa(base);
+               __flush_tsb_one_entry(base, vaddr, HPAGE_SHIFT, nentries);
+       }
+#endif
+       spin_unlock_irqrestore(&mm->context.lock, flags);
+}
+
 #define HV_PGSZ_IDX_BASE       HV_PGSZ_IDX_8K
 #define HV_PGSZ_MASK_BASE      HV_PGSZ_MASK_8K
 
index f8e13d421fcbf415dd49a50bc2ed4aaf2b3b6494..432aa0cb1b38caa75076938700c60761699dc920 100644 (file)
@@ -52,6 +52,33 @@ __flush_tlb_mm:              /* 18 insns */
        nop
        nop
 
+       .align          32
+       .globl          __flush_tlb_page
+__flush_tlb_page:      /* 22 insns */
+       /* %o0 = context, %o1 = vaddr */
+       rdpr            %pstate, %g7
+       andn            %g7, PSTATE_IE, %g2
+       wrpr            %g2, %pstate
+       mov             SECONDARY_CONTEXT, %o4
+       ldxa            [%o4] ASI_DMMU, %g2
+       stxa            %o0, [%o4] ASI_DMMU
+       andcc           %o1, 1, %g0
+       andn            %o1, 1, %o3
+       be,pn           %icc, 1f
+        or             %o3, 0x10, %o3
+       stxa            %g0, [%o3] ASI_IMMU_DEMAP
+1:     stxa            %g0, [%o3] ASI_DMMU_DEMAP
+       membar          #Sync
+       stxa            %g2, [%o4] ASI_DMMU
+       sethi           %hi(KERNBASE), %o4
+       flush           %o4
+       retl
+        wrpr           %g7, 0x0, %pstate
+       nop
+       nop
+       nop
+       nop
+
        .align          32
        .globl          __flush_tlb_pending
 __flush_tlb_pending:   /* 26 insns */
@@ -203,6 +230,31 @@ __cheetah_flush_tlb_mm: /* 19 insns */
        retl
         wrpr           %g7, 0x0, %pstate
 
+__cheetah_flush_tlb_page:      /* 22 insns */
+       /* %o0 = context, %o1 = vaddr */
+       rdpr            %pstate, %g7
+       andn            %g7, PSTATE_IE, %g2
+       wrpr            %g2, 0x0, %pstate
+       wrpr            %g0, 1, %tl
+       mov             PRIMARY_CONTEXT, %o4
+       ldxa            [%o4] ASI_DMMU, %g2
+       srlx            %g2, CTX_PGSZ1_NUC_SHIFT, %o3
+       sllx            %o3, CTX_PGSZ1_NUC_SHIFT, %o3
+       or              %o0, %o3, %o0   /* Preserve nucleus page size fields */
+       stxa            %o0, [%o4] ASI_DMMU
+       andcc           %o1, 1, %g0
+       be,pn           %icc, 1f
+        andn           %o1, 1, %o3
+       stxa            %g0, [%o3] ASI_IMMU_DEMAP
+1:     stxa            %g0, [%o3] ASI_DMMU_DEMAP       
+       membar          #Sync
+       stxa            %g2, [%o4] ASI_DMMU
+       sethi           %hi(KERNBASE), %o4
+       flush           %o4
+       wrpr            %g0, 0, %tl
+       retl
+        wrpr           %g7, 0x0, %pstate
+
 __cheetah_flush_tlb_pending:   /* 27 insns */
        /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
        rdpr            %pstate, %g7
@@ -269,6 +321,20 @@ __hypervisor_flush_tlb_mm: /* 10 insns */
        retl
         nop
 
+__hypervisor_flush_tlb_page: /* 11 insns */
+       /* %o0 = context, %o1 = vaddr */
+       mov             %o0, %g2
+       mov             %o1, %o0              /* ARG0: vaddr + IMMU-bit */
+       mov             %g2, %o1              /* ARG1: mmu context */
+       mov             HV_MMU_ALL, %o2       /* ARG2: flags */
+       srlx            %o0, PAGE_SHIFT, %o0
+       sllx            %o0, PAGE_SHIFT, %o0
+       ta              HV_MMU_UNMAP_ADDR_TRAP
+       brnz,pn         %o0, __hypervisor_tlb_tl0_error
+        mov            HV_MMU_UNMAP_ADDR_TRAP, %o1
+       retl
+        nop
+
 __hypervisor_flush_tlb_pending: /* 16 insns */
        /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
        sllx            %o1, 3, %g1
@@ -339,6 +405,13 @@ cheetah_patch_cachetlbops:
        call            tlb_patch_one
         mov            19, %o2
 
+       sethi           %hi(__flush_tlb_page), %o0
+       or              %o0, %lo(__flush_tlb_page), %o0
+       sethi           %hi(__cheetah_flush_tlb_page), %o1
+       or              %o1, %lo(__cheetah_flush_tlb_page), %o1
+       call            tlb_patch_one
+        mov            22, %o2
+
        sethi           %hi(__flush_tlb_pending), %o0
        or              %o0, %lo(__flush_tlb_pending), %o0
        sethi           %hi(__cheetah_flush_tlb_pending), %o1
@@ -397,10 +470,9 @@ xcall_flush_tlb_mm:        /* 21 insns */
        nop
        nop
 
-       .globl          xcall_flush_tlb_pending
-xcall_flush_tlb_pending:       /* 21 insns */
-       /* %g5=context, %g1=nr, %g7=vaddrs[] */
-       sllx            %g1, 3, %g1
+       .globl          xcall_flush_tlb_page
+xcall_flush_tlb_page:  /* 17 insns */
+       /* %g5=context, %g1=vaddr */
        mov             PRIMARY_CONTEXT, %g4
        ldxa            [%g4] ASI_DMMU, %g2
        srlx            %g2, CTX_PGSZ1_NUC_SHIFT, %g4
@@ -408,20 +480,16 @@ xcall_flush_tlb_pending:  /* 21 insns */
        or              %g5, %g4, %g5
        mov             PRIMARY_CONTEXT, %g4
        stxa            %g5, [%g4] ASI_DMMU
-1:     sub             %g1, (1 << 3), %g1
-       ldx             [%g7 + %g1], %g5
-       andcc           %g5, 0x1, %g0
+       andcc           %g1, 0x1, %g0
        be,pn           %icc, 2f
-
-        andn           %g5, 0x1, %g5
+        andn           %g1, 0x1, %g5
        stxa            %g0, [%g5] ASI_IMMU_DEMAP
 2:     stxa            %g0, [%g5] ASI_DMMU_DEMAP
        membar          #Sync
-       brnz,pt         %g1, 1b
-        nop
        stxa            %g2, [%g4] ASI_DMMU
        retry
        nop
+       nop
 
        .globl          xcall_flush_tlb_kernel_range
 xcall_flush_tlb_kernel_range:  /* 25 insns */
@@ -656,15 +724,13 @@ __hypervisor_xcall_flush_tlb_mm: /* 21 insns */
        membar          #Sync
        retry
 
-       .globl          __hypervisor_xcall_flush_tlb_pending
-__hypervisor_xcall_flush_tlb_pending: /* 21 insns */
-       /* %g5=ctx, %g1=nr, %g7=vaddrs[], %g2,%g3,%g4,g6=scratch */
-       sllx            %g1, 3, %g1
+       .globl          __hypervisor_xcall_flush_tlb_page
+__hypervisor_xcall_flush_tlb_page: /* 17 insns */
+       /* %g5=ctx, %g1=vaddr */
        mov             %o0, %g2
        mov             %o1, %g3
        mov             %o2, %g4
-1:     sub             %g1, (1 << 3), %g1
-       ldx             [%g7 + %g1], %o0        /* ARG0: virtual address */
+       mov             %g1, %o0                /* ARG0: virtual address */
        mov             %g5, %o1                /* ARG1: mmu context */
        mov             HV_MMU_ALL, %o2         /* ARG2: flags */
        srlx            %o0, PAGE_SHIFT, %o0
@@ -673,8 +739,6 @@ __hypervisor_xcall_flush_tlb_pending: /* 21 insns */
        mov             HV_MMU_UNMAP_ADDR_TRAP, %g6
        brnz,a,pn       %o0, __hypervisor_tlb_xcall_error
         mov            %o0, %g5
-       brnz,pt         %g1, 1b
-        nop
        mov             %g2, %o0
        mov             %g3, %o1
        mov             %g4, %o2
@@ -757,6 +821,13 @@ hypervisor_patch_cachetlbops:
        call            tlb_patch_one
         mov            10, %o2
 
+       sethi           %hi(__flush_tlb_page), %o0
+       or              %o0, %lo(__flush_tlb_page), %o0
+       sethi           %hi(__hypervisor_flush_tlb_page), %o1
+       or              %o1, %lo(__hypervisor_flush_tlb_page), %o1
+       call            tlb_patch_one
+        mov            11, %o2
+
        sethi           %hi(__flush_tlb_pending), %o0
        or              %o0, %lo(__flush_tlb_pending), %o0
        sethi           %hi(__hypervisor_flush_tlb_pending), %o1
@@ -788,12 +859,12 @@ hypervisor_patch_cachetlbops:
        call            tlb_patch_one
         mov            21, %o2
 
-       sethi           %hi(xcall_flush_tlb_pending), %o0
-       or              %o0, %lo(xcall_flush_tlb_pending), %o0
-       sethi           %hi(__hypervisor_xcall_flush_tlb_pending), %o1
-       or              %o1, %lo(__hypervisor_xcall_flush_tlb_pending), %o1
+       sethi           %hi(xcall_flush_tlb_page), %o0
+       or              %o0, %lo(xcall_flush_tlb_page), %o0
+       sethi           %hi(__hypervisor_xcall_flush_tlb_page), %o1
+       or              %o1, %lo(__hypervisor_xcall_flush_tlb_page), %o1
        call            tlb_patch_one
-        mov            21, %o2
+        mov            17, %o2
 
        sethi           %hi(xcall_flush_tlb_kernel_range), %o0
        or              %o0, %lo(xcall_flush_tlb_kernel_range), %o0
index 241c0bb60b12e5cf4e9eedce50279d648d313e25..c96f9bbb760d54d79b2c0cc7208bf4e37964de9c 100644 (file)
 #include <asm/percpu.h>
 #include <arch/spr_def.h>
 
-/* Set and clear kernel interrupt masks. */
+/*
+ * Set and clear kernel interrupt masks.
+ *
+ * NOTE: __insn_mtspr() is a compiler builtin marked as a memory
+ * clobber.  We rely on it being equivalent to a compiler barrier in
+ * this code since arch_local_irq_save() and friends must act as
+ * compiler barriers.  This compiler semantic is baked into enough
+ * places that the compiler will maintain it going forward.
+ */
 #if CHIP_HAS_SPLIT_INTR_MASK()
 #if INT_PERF_COUNT < 32 || INT_AUX_PERF_COUNT < 32 || INT_MEM_ERROR >= 32
 # error Fix assumptions about which word various interrupts are in
index d1e15f7b59c68ab54ee62a137443270287f59f34..7a5aa1a7864e2371900e5ccba2d2a0f507fa834e 100644 (file)
@@ -1004,15 +1004,8 @@ void __cpuinit setup_cpu(int boot)
 
 #ifdef CONFIG_BLK_DEV_INITRD
 
-/*
- * Note that the kernel can potentially support other compression
- * techniques than gz, though we don't do so by default.  If we ever
- * decide to do so we can either look for other filename extensions,
- * or just allow a file with this name to be compressed with an
- * arbitrary compressor (somewhat counterintuitively).
- */
 static int __initdata set_initramfs_file;
-static char __initdata initramfs_file[128] = "initramfs.cpio.gz";
+static char __initdata initramfs_file[128] = "initramfs";
 
 static int __init setup_initramfs_file(char *str)
 {
@@ -1026,9 +1019,9 @@ static int __init setup_initramfs_file(char *str)
 early_param("initramfs_file", setup_initramfs_file);
 
 /*
- * We look for an "initramfs.cpio.gz" file in the hvfs.
- * If there is one, we allocate some memory for it and it will be
- * unpacked to the initramfs.
+ * We look for a file called "initramfs" in the hvfs.  If there is one, we
+ * allocate some memory for it and it will be unpacked to the initramfs.
+ * If it's compressed, the initd code will uncompress it first.
  */
 static void __init load_hv_initrd(void)
 {
@@ -1038,10 +1031,16 @@ static void __init load_hv_initrd(void)
 
        fd = hv_fs_findfile((HV_VirtAddr) initramfs_file);
        if (fd == HV_ENOENT) {
-               if (set_initramfs_file)
+               if (set_initramfs_file) {
                        pr_warning("No such hvfs initramfs file '%s'\n",
                                   initramfs_file);
-               return;
+                       return;
+               } else {
+                       /* Try old backwards-compatible name. */
+                       fd = hv_fs_findfile((HV_VirtAddr)"initramfs.cpio.gz");
+                       if (fd == HV_ENOENT)
+                               return;
+               }
        }
        BUG_ON(fd < 0);
        stat = hv_fs_fstat(fd);
index 70c0f3da0476a35ba93546689bb4b06b5f576bba..15b5cef4aa3857a386cb77cffd2ba74243b532c7 100644 (file)
@@ -1549,6 +1549,7 @@ config X86_SMAP
 config EFI
        bool "EFI runtime service support"
        depends on ACPI
+       select UCS2_STRING
        ---help---
          This enables the kernel to use EFI runtime services that are
          available (such as the EFI variable services).
index 8a84501acb1b965f2dbfe1d18b91799667af4fb3..5ef205c5f37b094a2e0358052775f01a8fe292b0 100644 (file)
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo head_$(BITS).o misc.o string.o cmdline.o early_serial_console.o piggy.o
+targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
@@ -29,7 +29,6 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
        $(obj)/piggy.o
 
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
-$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone
 
 ifeq ($(CONFIG_EFI_STUB), y)
        VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o
@@ -43,7 +42,7 @@ OBJCOPYFLAGS_vmlinux.bin :=  -R .comment -S
 $(obj)/vmlinux.bin: vmlinux FORCE
        $(call if_changed,objcopy)
 
-targets += vmlinux.bin.all vmlinux.relocs
+targets += $(patsubst $(obj)/%,%,$(VMLINUX_OBJS)) vmlinux.bin.all vmlinux.relocs
 
 CMD_RELOCS = arch/x86/tools/relocs
 quiet_cmd_relocs = RELOCS  $@
index c205035a6b96b836ef683ddf8592dbc9c82200e6..35ee62fccf9827c766007021ff1c65bbdb55c53b 100644 (file)
@@ -251,6 +251,51 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
        *size = len;
 }
 
+static efi_status_t setup_efi_vars(struct boot_params *params)
+{
+       struct setup_data *data;
+       struct efi_var_bootdata *efidata;
+       u64 store_size, remaining_size, var_size;
+       efi_status_t status;
+
+       if (sys_table->runtime->hdr.revision < EFI_2_00_SYSTEM_TABLE_REVISION)
+               return EFI_UNSUPPORTED;
+
+       data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
+
+       while (data && data->next)
+               data = (struct setup_data *)(unsigned long)data->next;
+
+       status = efi_call_phys4((void *)sys_table->runtime->query_variable_info,
+                               EFI_VARIABLE_NON_VOLATILE |
+                               EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                               EFI_VARIABLE_RUNTIME_ACCESS, &store_size,
+                               &remaining_size, &var_size);
+
+       if (status != EFI_SUCCESS)
+               return status;
+
+       status = efi_call_phys3(sys_table->boottime->allocate_pool,
+                               EFI_LOADER_DATA, sizeof(*efidata), &efidata);
+
+       if (status != EFI_SUCCESS)
+               return status;
+
+       efidata->data.type = SETUP_EFI_VARS;
+       efidata->data.len = sizeof(struct efi_var_bootdata) -
+               sizeof(struct setup_data);
+       efidata->data.next = 0;
+       efidata->store_size = store_size;
+       efidata->remaining_size = remaining_size;
+       efidata->max_var_size = var_size;
+
+       if (data)
+               data->next = (unsigned long)efidata;
+       else
+               params->hdr.setup_data = (unsigned long)efidata;
+
+}
+
 static efi_status_t setup_efi_pci(struct boot_params *params)
 {
        efi_pci_io_protocol *pci;
@@ -1157,6 +1202,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
 
        setup_graphics(boot_params);
 
+       setup_efi_vars(boot_params);
+
        setup_efi_pci(boot_params);
 
        status = efi_call_phys3(sys_table->boottime->allocate_pool,
index 60c89f30c727458df128543a6302e95aeede8758..2fb5d5884e2331b7d6d299621bfb5c91fa701bf2 100644 (file)
@@ -102,6 +102,13 @@ extern void efi_call_phys_epilog(void);
 extern void efi_unmap_memmap(void);
 extern void efi_memory_uc(u64 addr, unsigned long size);
 
+struct efi_var_bootdata {
+       struct setup_data data;
+       u64 store_size;
+       u64 remaining_size;
+       u64 max_var_size;
+};
+
 #ifdef CONFIG_EFI
 
 static inline bool efi_is_native(void)
index 5edd1742cfd02a9368ca28e604366fb428904ad8..7361e47db79f50158ada1cdde859c4871b99ee51 100644 (file)
@@ -703,7 +703,10 @@ static inline void arch_leave_lazy_mmu_mode(void)
        PVOP_VCALL0(pv_mmu_ops.lazy_mode.leave);
 }
 
-void arch_flush_lazy_mmu_mode(void);
+static inline void arch_flush_lazy_mmu_mode(void)
+{
+       PVOP_VCALL0(pv_mmu_ops.lazy_mode.flush);
+}
 
 static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx,
                                phys_addr_t phys, pgprot_t flags)
index 142236ed83af580c06e2e00893501e3fc38b0e65..b3b0ec1dac86d91ac6289b961afefe65f1f48d11 100644 (file)
@@ -91,6 +91,7 @@ struct pv_lazy_ops {
        /* Set deferred update mode, used for batching operations. */
        void (*enter)(void);
        void (*leave)(void);
+       void (*flush)(void);
 };
 
 struct pv_time_ops {
@@ -679,6 +680,7 @@ void paravirt_end_context_switch(struct task_struct *next);
 
 void paravirt_enter_lazy_mmu(void);
 void paravirt_leave_lazy_mmu(void);
+void paravirt_flush_lazy_mmu(void);
 
 void _paravirt_nop(void);
 u32 _paravirt_ident_32(u32);
index 1ace47b62592adabd69c568d1f842ffa33f057e2..2e188d68397c82930bdba80c52a87260546fcbd3 100644 (file)
@@ -29,13 +29,13 @@ extern const unsigned long sys_call_table[];
  */
 static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 {
-       return regs->orig_ax & __SYSCALL_MASK;
+       return regs->orig_ax;
 }
 
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
-       regs->ax = regs->orig_ax & __SYSCALL_MASK;
+       regs->ax = regs->orig_ax;
 }
 
 static inline long syscall_get_error(struct task_struct *task,
index 4fef20773b8f9fcf104702ac2d8ef0c29a05c235..c7797307fc2ba5b24adacced83c9587bc5d2a8de 100644 (file)
@@ -7,7 +7,7 @@
 
 #define tlb_flush(tlb)                                                 \
 {                                                                      \
-       if (tlb->fullmm == 0)                                           \
+       if (!tlb->fullmm && !tlb->need_flush_all)                       \
                flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end, 0UL); \
        else                                                            \
                flush_tlb_mm_range(tlb->mm, 0UL, TLB_FLUSH_ALL, 0UL);   \
index c15ddaf907107134d6cd2f8d86f554e510a6f848..08744242b8d24c9111d2275ff6d84752d725584e 100644 (file)
@@ -6,6 +6,7 @@
 #define SETUP_E820_EXT                 1
 #define SETUP_DTB                      2
 #define SETUP_PCI                      3
+#define SETUP_EFI_VARS                 4
 
 /* ram_size flags */
 #define RAMDISK_IMAGE_START_MASK       0x07FF
index a7d26d83fb700b254eca03d9ff5e8f6d56f7a0c5..8f4be53ea04b84f4eaa7a78a4bcd6e6e625c9afc 100644 (file)
@@ -35,13 +35,6 @@ static bool __init ms_hyperv_platform(void)
        if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
                return false;
 
-       /*
-        * Xen emulates Hyper-V to support enlightened Windows.
-        * Check to see first if we are on a Xen Hypervisor.
-        */
-       if (xen_cpuid_base())
-               return false;
-
        cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS,
              &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]);
 
@@ -82,12 +75,6 @@ static void __init ms_hyperv_init_platform(void)
 
        if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
                clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
-#if IS_ENABLED(CONFIG_HYPERV)
-       /*
-        * Setup the IDT for hypervisor callback.
-        */
-       alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, hyperv_callback_vector);
-#endif
 }
 
 const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
@@ -103,6 +90,11 @@ static irq_handler_t vmbus_isr;
 
 void hv_register_vmbus_handler(int irq, irq_handler_t handler)
 {
+       /*
+        * Setup the IDT for hypervisor callback.
+        */
+       alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, hyperv_callback_vector);
+
        vmbus_irq = irq;
        vmbus_isr = handler;
 }
index dab7580c47aee2e71e501afbfa94c17e2790777d..cc45deb791b01d103c01cbc527f8bfd023d51879 100644 (file)
@@ -153,8 +153,14 @@ static struct event_constraint intel_gen_event_constraints[] __read_mostly =
 };
 
 static struct extra_reg intel_snb_extra_regs[] __read_mostly = {
-       INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0),
-       INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1),
+       INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0),
+       INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3f807f8fffull, RSP_1),
+       EVENT_EXTRA_END
+};
+
+static struct extra_reg intel_snbep_extra_regs[] __read_mostly = {
+       INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0),
+       INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1),
        EVENT_EXTRA_END
 };
 
@@ -2097,7 +2103,10 @@ __init int intel_pmu_init(void)
                x86_pmu.event_constraints = intel_snb_event_constraints;
                x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints;
                x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
-               x86_pmu.extra_regs = intel_snb_extra_regs;
+               if (boot_cpu_data.x86_model == 45)
+                       x86_pmu.extra_regs = intel_snbep_extra_regs;
+               else
+                       x86_pmu.extra_regs = intel_snb_extra_regs;
                /* all extra regs are per-cpu when HT is on */
                x86_pmu.er_flags |= ERF_HAS_RSP_1;
                x86_pmu.er_flags |= ERF_NO_HT_SHARING;
@@ -2123,7 +2132,10 @@ __init int intel_pmu_init(void)
                x86_pmu.event_constraints = intel_ivb_event_constraints;
                x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints;
                x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
-               x86_pmu.extra_regs = intel_snb_extra_regs;
+               if (boot_cpu_data.x86_model == 62)
+                       x86_pmu.extra_regs = intel_snbep_extra_regs;
+               else
+                       x86_pmu.extra_regs = intel_snb_extra_regs;
                /* all extra regs are per-cpu when HT is on */
                x86_pmu.er_flags |= ERF_HAS_RSP_1;
                x86_pmu.er_flags |= ERF_NO_HT_SHARING;
index b05a575d56f42f4543504b999a3b4875de110772..26830f3af0df70eebb438ddc82f74240b49d618e 100644 (file)
@@ -314,10 +314,11 @@ int intel_pmu_drain_bts_buffer(void)
        if (top <= at)
                return 0;
 
+       memset(&regs, 0, sizeof(regs));
+
        ds->bts_index = ds->bts_buffer_base;
 
        perf_sample_data_init(&data, 0, event->hw.last_period);
-       regs.ip     = 0;
 
        /*
         * Prepare a generic sample, i.e. fill in the invariant fields.
index 577db8417d15b41fd71cce1f0bc813ba959c5b70..833d51d6ee065b908fa70ac1075a3acf6d2721a4 100644 (file)
@@ -45,9 +45,6 @@ static int __cpuinit x86_vendor(void)
        u32 eax = 0x00000000;
        u32 ebx, ecx = 0, edx;
 
-       if (!have_cpuid_p())
-               return X86_VENDOR_UNKNOWN;
-
        native_cpuid(&eax, &ebx, &ecx, &edx);
 
        if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx))
@@ -59,18 +56,45 @@ static int __cpuinit x86_vendor(void)
        return X86_VENDOR_UNKNOWN;
 }
 
+static int __cpuinit x86_family(void)
+{
+       u32 eax = 0x00000001;
+       u32 ebx, ecx = 0, edx;
+       int x86;
+
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+
+       x86 = (eax >> 8) & 0xf;
+       if (x86 == 15)
+               x86 += (eax >> 20) & 0xff;
+
+       return x86;
+}
+
 void __init load_ucode_bsp(void)
 {
-       int vendor = x86_vendor();
+       int vendor, x86;
+
+       if (!have_cpuid_p())
+               return;
 
-       if (vendor == X86_VENDOR_INTEL)
+       vendor = x86_vendor();
+       x86 = x86_family();
+
+       if (vendor == X86_VENDOR_INTEL && x86 >= 6)
                load_ucode_intel_bsp();
 }
 
 void __cpuinit load_ucode_ap(void)
 {
-       int vendor = x86_vendor();
+       int vendor, x86;
+
+       if (!have_cpuid_p())
+               return;
+
+       vendor = x86_vendor();
+       x86 = x86_family();
 
-       if (vendor == X86_VENDOR_INTEL)
+       if (vendor == X86_VENDOR_INTEL && x86 >= 6)
                load_ucode_intel_ap();
 }
index 17fff18a103104431c0e10e1543af6f027f64f72..8bfb335f74bb377776adb4b6b1da98dc17ed82ae 100644 (file)
@@ -263,6 +263,18 @@ void paravirt_leave_lazy_mmu(void)
        leave_lazy(PARAVIRT_LAZY_MMU);
 }
 
+void paravirt_flush_lazy_mmu(void)
+{
+       preempt_disable();
+
+       if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
+               arch_leave_lazy_mmu_mode();
+               arch_enter_lazy_mmu_mode();
+       }
+
+       preempt_enable();
+}
+
 void paravirt_start_context_switch(struct task_struct *prev)
 {
        BUG_ON(preemptible());
@@ -292,18 +304,6 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
        return this_cpu_read(paravirt_lazy_mode);
 }
 
-void arch_flush_lazy_mmu_mode(void)
-{
-       preempt_disable();
-
-       if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
-               arch_leave_lazy_mmu_mode();
-               arch_enter_lazy_mmu_mode();
-       }
-
-       preempt_enable();
-}
-
 struct pv_info pv_info = {
        .name = "bare hardware",
        .paravirt_enabled = 0,
@@ -475,6 +475,7 @@ struct pv_mmu_ops pv_mmu_ops = {
        .lazy_mode = {
                .enter = paravirt_nop,
                .leave = paravirt_nop,
+               .flush = paravirt_nop,
        },
 
        .set_fixmap = native_set_fixmap,
index 90d8cc930f5ed134735f7697e016a83e5657dcb8..fae9134a2de91f7b420fb554bb33f356de661f8f 100644 (file)
@@ -507,11 +507,14 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 /*
  * Keep the crash kernel below this limit.  On 32 bits earlier kernels
  * would limit the kernel to the low 512 MiB due to mapping restrictions.
+ * On 64bit, old kexec-tools need to under 896MiB.
  */
 #ifdef CONFIG_X86_32
-# define CRASH_KERNEL_ADDR_MAX (512 << 20)
+# define CRASH_KERNEL_ADDR_LOW_MAX     (512 << 20)
+# define CRASH_KERNEL_ADDR_HIGH_MAX    (512 << 20)
 #else
-# define CRASH_KERNEL_ADDR_MAX MAXMEM
+# define CRASH_KERNEL_ADDR_LOW_MAX     (896UL<<20)
+# define CRASH_KERNEL_ADDR_HIGH_MAX    MAXMEM
 #endif
 
 static void __init reserve_crashkernel_low(void)
@@ -521,19 +524,35 @@ static void __init reserve_crashkernel_low(void)
        unsigned long long low_base = 0, low_size = 0;
        unsigned long total_low_mem;
        unsigned long long base;
+       bool auto_set = false;
        int ret;
 
        total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT));
+       /* crashkernel=Y,low */
        ret = parse_crashkernel_low(boot_command_line, total_low_mem,
                                                &low_size, &base);
-       if (ret != 0 || low_size <= 0)
-               return;
+       if (ret != 0) {
+               /*
+                * two parts from lib/swiotlb.c:
+                *      swiotlb size: user specified with swiotlb= or default.
+                *      swiotlb overflow buffer: now is hardcoded to 32k.
+                *              We round it to 8M for other buffers that
+                *              may need to stay low too.
+                */
+               low_size = swiotlb_size_or_default() + (8UL<<20);
+               auto_set = true;
+       } else {
+               /* passed with crashkernel=0,low ? */
+               if (!low_size)
+                       return;
+       }
 
        low_base = memblock_find_in_range(low_size, (1ULL<<32),
                                        low_size, alignment);
 
        if (!low_base) {
-               pr_info("crashkernel low reservation failed - No suitable area found.\n");
+               if (!auto_set)
+                       pr_info("crashkernel low reservation failed - No suitable area found.\n");
 
                return;
        }
@@ -554,14 +573,22 @@ static void __init reserve_crashkernel(void)
        const unsigned long long alignment = 16<<20;    /* 16M */
        unsigned long long total_mem;
        unsigned long long crash_size, crash_base;
+       bool high = false;
        int ret;
 
        total_mem = memblock_phys_mem_size();
 
+       /* crashkernel=XM */
        ret = parse_crashkernel(boot_command_line, total_mem,
                        &crash_size, &crash_base);
-       if (ret != 0 || crash_size <= 0)
-               return;
+       if (ret != 0 || crash_size <= 0) {
+               /* crashkernel=X,high */
+               ret = parse_crashkernel_high(boot_command_line, total_mem,
+                               &crash_size, &crash_base);
+               if (ret != 0 || crash_size <= 0)
+                       return;
+               high = true;
+       }
 
        /* 0 means: find the address automatically */
        if (crash_base <= 0) {
@@ -569,7 +596,9 @@ static void __init reserve_crashkernel(void)
                 *  kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
                 */
                crash_base = memblock_find_in_range(alignment,
-                              CRASH_KERNEL_ADDR_MAX, crash_size, alignment);
+                                       high ? CRASH_KERNEL_ADDR_HIGH_MAX :
+                                              CRASH_KERNEL_ADDR_LOW_MAX,
+                                       crash_size, alignment);
 
                if (!crash_base) {
                        pr_info("crashkernel reservation failed - No suitable area found.\n");
index 02b51dd4e4ad37e4852efa0b40d110121ebbad83..f77df1c5de6eeb4ac341b9a9ac7f6afdb054b658 100644 (file)
@@ -1857,7 +1857,7 @@ int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data)
        if (!pv_eoi_enabled(vcpu))
                return 0;
        return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data,
-                                        addr);
+                                        addr, sizeof(u8));
 }
 
 void kvm_lapic_init(void)
index f19ac0aca60d9379ea5c625e8e6f35024d7bd239..e1721324c271e18430f43ee226a367c4495d18ab 100644 (file)
@@ -1823,7 +1823,8 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
                return 0;
        }
 
-       if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa))
+       if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
+                                       sizeof(u32)))
                return 1;
 
        vcpu->arch.apf.send_user_only = !(data & KVM_ASYNC_PF_SEND_ALWAYS);
@@ -1952,12 +1953,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 
                gpa_offset = data & ~(PAGE_MASK | 1);
 
-               /* Check that the address is 32-byte aligned. */
-               if (gpa_offset & (sizeof(struct pvclock_vcpu_time_info) - 1))
-                       break;
-
                if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
-                    &vcpu->arch.pv_time, data & ~1ULL))
+                    &vcpu->arch.pv_time, data & ~1ULL,
+                    sizeof(struct pvclock_vcpu_time_info)))
                        vcpu->arch.pv_time_enabled = false;
                else
                        vcpu->arch.pv_time_enabled = true;
@@ -1977,7 +1975,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                        return 1;
 
                if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime,
-                                                       data & KVM_STEAL_VALID_BITS))
+                                               data & KVM_STEAL_VALID_BITS,
+                                               sizeof(struct kvm_steal_time)))
                        return 1;
 
                vcpu->arch.st.msr_val = data;
index 1cbd89ca5569f2ce5d76a4bed1f21d6d52ed63e5..7114c63f047d06432a453884c4500474ea9681ea 100644 (file)
@@ -1334,6 +1334,7 @@ __init void lguest_init(void)
        pv_mmu_ops.read_cr3 = lguest_read_cr3;
        pv_mmu_ops.lazy_mode.enter = paravirt_enter_lazy_mmu;
        pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mmu_mode;
+       pv_mmu_ops.lazy_mode.flush = paravirt_flush_lazy_mmu;
        pv_mmu_ops.pte_update = lguest_pte_update;
        pv_mmu_ops.pte_update_defer = lguest_pte_update;
 
index 2b97525246d43c3397f9d2149adf859b24b2842b..0e883364abb5752d4ac07b031d241d6bd00585ab 100644 (file)
@@ -378,10 +378,12 @@ static noinline __kprobes int vmalloc_fault(unsigned long address)
        if (pgd_none(*pgd_ref))
                return -1;
 
-       if (pgd_none(*pgd))
+       if (pgd_none(*pgd)) {
                set_pgd(pgd, *pgd_ref);
-       else
+               arch_flush_lazy_mmu_mode();
+       } else {
                BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+       }
 
        /*
         * Below here mismatches are bugs because these lower tables
index b0086567271c9956b2196e3ba302e4a77009e811..0e38951e65eb0940bf57a3f6d8c8d01dff0674c7 100644 (file)
@@ -68,7 +68,7 @@ static int print_split(struct split_state *s)
                        s->gpg++;
                        i += GPS/PAGE_SIZE;
                } else if (level == PG_LEVEL_2M) {
-                       if (!(pte_val(*pte) & _PAGE_PSE)) {
+                       if ((pte_val(*pte) & _PAGE_PRESENT) && !(pte_val(*pte) & _PAGE_PSE)) {
                                printk(KERN_ERR
                                        "%lx level %d but not PSE %Lx\n",
                                        addr, level, (u64)pte_val(*pte));
index 091934e1d0d97ca26570eb9962aa1890e08e7bd8..fb4e73ec24d8d1b8b894b6c09f7c082a49dc1dcf 100644 (file)
@@ -467,7 +467,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
         * We are safe now. Check whether the new pgprot is the same:
         */
        old_pte = *kpte;
-       old_prot = new_prot = req_prot = pte_pgprot(old_pte);
+       old_prot = req_prot = pte_pgprot(old_pte);
 
        pgprot_val(req_prot) &= ~pgprot_val(cpa->mask_clr);
        pgprot_val(req_prot) |= pgprot_val(cpa->mask_set);
@@ -478,12 +478,12 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
         * a non present pmd. The canon_pgprot will clear _PAGE_GLOBAL
         * for the ancient hardware that doesn't support it.
         */
-       if (pgprot_val(new_prot) & _PAGE_PRESENT)
-               pgprot_val(new_prot) |= _PAGE_PSE | _PAGE_GLOBAL;
+       if (pgprot_val(req_prot) & _PAGE_PRESENT)
+               pgprot_val(req_prot) |= _PAGE_PSE | _PAGE_GLOBAL;
        else
-               pgprot_val(new_prot) &= ~(_PAGE_PSE | _PAGE_GLOBAL);
+               pgprot_val(req_prot) &= ~(_PAGE_PSE | _PAGE_GLOBAL);
 
-       new_prot = canon_pgprot(new_prot);
+       req_prot = canon_pgprot(req_prot);
 
        /*
         * old_pte points to the large page base address. So we need
@@ -1413,6 +1413,8 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
         * but that can deadlock->flush only current cpu:
         */
        __flush_tlb_all();
+
+       arch_flush_lazy_mmu_mode();
 }
 
 #ifdef CONFIG_HIBERNATION
index 193350b51f90af74508a8ec97217085bf3acdbab..17fda6a8b3c2df13adaee439b0ad6ab9f50796cb 100644 (file)
@@ -58,6 +58,13 @@ void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
 void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
 {
        paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
+       /*
+        * NOTE! For PAE, any changes to the top page-directory-pointer-table
+        * entries need a full cr3 reload to flush.
+        */
+#ifdef CONFIG_X86_PAE
+       tlb->need_flush_all = 1;
+#endif
        tlb_remove_page(tlb, virt_to_page(pmd));
 }
 
index 901177d75ff5e36663b3083ba7f7eb77ab4a86c8..305c68b8d53825fbda7f635de0ae4c1af43fe03b 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/sched.h>
 #include <linux/pci.h>
+#include <linux/pci-acpi.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/dmi.h>
@@ -170,6 +171,16 @@ void pcibios_fixup_bus(struct pci_bus *b)
                pcibios_fixup_device_resources(dev);
 }
 
+void pcibios_add_bus(struct pci_bus *bus)
+{
+       acpi_pci_add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+       acpi_pci_remove_bus(bus);
+}
+
 /*
  * Only use DMI information to set this if nothing was passed
  * on the kernel command line (which was parsed earlier).
index 94e76620460f8574b90848ce3f5556139351b7fa..4a9be6ddf05437e66ab8c94862a9b3e8a30e4373 100644 (file)
@@ -177,7 +177,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                goto error;
        i = 0;
        list_for_each_entry(msidesc, &dev->msi_list, list) {
-               irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
+               irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i],
                                               (type == PCI_CAP_ID_MSIX) ?
                                               "pcifront-msi-x" :
                                               "pcifront-msi",
@@ -244,7 +244,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                        dev_dbg(&dev->dev,
                                "xen: msi already bound to pirq=%d\n", pirq);
                }
-               irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0,
+               irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq,
                                               (type == PCI_CAP_ID_MSIX) ?
                                               "msi-x" : "msi",
                                               DOMID_SELF);
@@ -326,7 +326,7 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                }
 
                ret = xen_bind_pirq_msi_to_irq(dev, msidesc,
-                                              map_irq.pirq, map_irq.index,
+                                              map_irq.pirq,
                                               (type == PCI_CAP_ID_MSIX) ?
                                               "msi-x" : "msi",
                                                domid);
index 5f2ecaf3f9d8609ccdc7a56e4d232fd13bdd8dcc..e4a86a677ce163ec5f911fb14db65590d813aee1 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/io.h>
 #include <linux/reboot.h>
 #include <linux/bcd.h>
+#include <linux/ucs2_string.h>
 
 #include <asm/setup.h>
 #include <asm/efi.h>
 
 #define EFI_DEBUG      1
 
+/*
+ * There's some additional metadata associated with each
+ * variable. Intel's reference implementation is 60 bytes - bump that
+ * to account for potential alignment constraints
+ */
+#define VAR_METADATA_SIZE 64
+
 struct efi __read_mostly efi = {
        .mps        = EFI_INVALID_TABLE_ADDR,
        .acpi       = EFI_INVALID_TABLE_ADDR,
@@ -69,6 +77,13 @@ struct efi_memory_map memmap;
 static struct efi efi_phys __initdata;
 static efi_system_table_t efi_systab __initdata;
 
+static u64 efi_var_store_size;
+static u64 efi_var_remaining_size;
+static u64 efi_var_max_var_size;
+static u64 boot_used_size;
+static u64 boot_var_size;
+static u64 active_size;
+
 unsigned long x86_efi_facility;
 
 /*
@@ -98,6 +113,15 @@ static int __init setup_add_efi_memmap(char *arg)
 }
 early_param("add_efi_memmap", setup_add_efi_memmap);
 
+static bool efi_no_storage_paranoia;
+
+static int __init setup_storage_paranoia(char *arg)
+{
+       efi_no_storage_paranoia = true;
+       return 0;
+}
+early_param("efi_no_storage_paranoia", setup_storage_paranoia);
+
 
 static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
 {
@@ -162,8 +186,53 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
                                               efi_char16_t *name,
                                               efi_guid_t *vendor)
 {
-       return efi_call_virt3(get_next_variable,
-                             name_size, name, vendor);
+       efi_status_t status;
+       static bool finished = false;
+       static u64 var_size;
+
+       status = efi_call_virt3(get_next_variable,
+                               name_size, name, vendor);
+
+       if (status == EFI_NOT_FOUND) {
+               finished = true;
+               if (var_size < boot_used_size) {
+                       boot_var_size = boot_used_size - var_size;
+                       active_size += boot_var_size;
+               } else {
+                       printk(KERN_WARNING FW_BUG  "efi: Inconsistent initial sizes\n");
+               }
+       }
+
+       if (boot_used_size && !finished) {
+               unsigned long size;
+               u32 attr;
+               efi_status_t s;
+               void *tmp;
+
+               s = virt_efi_get_variable(name, vendor, &attr, &size, NULL);
+
+               if (s != EFI_BUFFER_TOO_SMALL || !size)
+                       return status;
+
+               tmp = kmalloc(size, GFP_ATOMIC);
+
+               if (!tmp)
+                       return status;
+
+               s = virt_efi_get_variable(name, vendor, &attr, &size, tmp);
+
+               if (s == EFI_SUCCESS && (attr & EFI_VARIABLE_NON_VOLATILE)) {
+                       var_size += size;
+                       var_size += ucs2_strsize(name, 1024);
+                       active_size += size;
+                       active_size += VAR_METADATA_SIZE;
+                       active_size += ucs2_strsize(name, 1024);
+               }
+
+               kfree(tmp);
+       }
+
+       return status;
 }
 
 static efi_status_t virt_efi_set_variable(efi_char16_t *name,
@@ -172,9 +241,34 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
                                          unsigned long data_size,
                                          void *data)
 {
-       return efi_call_virt5(set_variable,
-                             name, vendor, attr,
-                             data_size, data);
+       efi_status_t status;
+       u32 orig_attr = 0;
+       unsigned long orig_size = 0;
+
+       status = virt_efi_get_variable(name, vendor, &orig_attr, &orig_size,
+                                      NULL);
+
+       if (status != EFI_BUFFER_TOO_SMALL)
+               orig_size = 0;
+
+       status = efi_call_virt5(set_variable,
+                               name, vendor, attr,
+                               data_size, data);
+
+       if (status == EFI_SUCCESS) {
+               if (orig_size) {
+                       active_size -= orig_size;
+                       active_size -= ucs2_strsize(name, 1024);
+                       active_size -= VAR_METADATA_SIZE;
+               }
+               if (data_size) {
+                       active_size += data_size;
+                       active_size += ucs2_strsize(name, 1024);
+                       active_size += VAR_METADATA_SIZE;
+               }
+       }
+
+       return status;
 }
 
 static efi_status_t virt_efi_query_variable_info(u32 attr,
@@ -682,6 +776,9 @@ void __init efi_init(void)
        char vendor[100] = "unknown";
        int i = 0;
        void *tmp;
+       struct setup_data *data;
+       struct efi_var_bootdata *efi_var_data;
+       u64 pa_data;
 
 #ifdef CONFIG_X86_32
        if (boot_params.efi_info.efi_systab_hi ||
@@ -699,6 +796,22 @@ void __init efi_init(void)
        if (efi_systab_init(efi_phys.systab))
                return;
 
+       pa_data = boot_params.hdr.setup_data;
+       while (pa_data) {
+               data = early_ioremap(pa_data, sizeof(*efi_var_data));
+               if (data->type == SETUP_EFI_VARS) {
+                       efi_var_data = (struct efi_var_bootdata *)data;
+
+                       efi_var_store_size = efi_var_data->store_size;
+                       efi_var_remaining_size = efi_var_data->remaining_size;
+                       efi_var_max_var_size = efi_var_data->max_var_size;
+               }
+               pa_data = data->next;
+               early_iounmap(data, sizeof(*efi_var_data));
+       }
+
+       boot_used_size = efi_var_store_size - efi_var_remaining_size;
+
        set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
 
        /*
@@ -999,3 +1112,48 @@ u64 efi_mem_attributes(unsigned long phys_addr)
        }
        return 0;
 }
+
+/*
+ * Some firmware has serious problems when using more than 50% of the EFI
+ * variable store, i.e. it triggers bugs that can brick machines. Ensure that
+ * we never use more than this safe limit.
+ *
+ * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
+ * store.
+ */
+efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
+{
+       efi_status_t status;
+       u64 storage_size, remaining_size, max_size;
+
+       status = efi.query_variable_info(attributes, &storage_size,
+                                        &remaining_size, &max_size);
+       if (status != EFI_SUCCESS)
+               return status;
+
+       if (!max_size && remaining_size > size)
+               printk_once(KERN_ERR FW_BUG "Broken EFI implementation"
+                           " is returning MaxVariableSize=0\n");
+       /*
+        * Some firmware implementations refuse to boot if there's insufficient
+        * space in the variable store. We account for that by refusing the
+        * write if permitting it would reduce the available space to under
+        * 50%. However, some firmware won't reclaim variable space until
+        * after the used (not merely the actively used) space drops below
+        * a threshold. We can approximate that case with the value calculated
+        * above. If both the firmware and our calculations indicate that the
+        * available space would drop below 50%, refuse the write.
+        */
+
+       if (!storage_size || size > remaining_size ||
+           (max_size && size > max_size))
+               return EFI_OUT_OF_RESOURCES;
+
+       if (!efi_no_storage_paranoia &&
+           ((active_size + size + VAR_METADATA_SIZE > storage_size / 2) &&
+            (remaining_size - size < storage_size / 2)))
+               return EFI_OUT_OF_RESOURCES;
+
+       return EFI_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(efi_query_variable_store);
index c8e1c7b95c3bfa9beb9a839e61061b6b37ffba2a..ddbd54a9b845d08abf73f3004d637ee8dad72eac 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/pci.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
+#include <linux/edd.h>
 
 #include <xen/xen.h>
 #include <xen/events.h>
@@ -1306,6 +1307,55 @@ static const struct machine_ops xen_machine_ops __initconst = {
        .emergency_restart = xen_emergency_restart,
 };
 
+static void __init xen_boot_params_init_edd(void)
+{
+#if IS_ENABLED(CONFIG_EDD)
+       struct xen_platform_op op;
+       struct edd_info *edd_info;
+       u32 *mbr_signature;
+       unsigned nr;
+       int ret;
+
+       edd_info = boot_params.eddbuf;
+       mbr_signature = boot_params.edd_mbr_sig_buffer;
+
+       op.cmd = XENPF_firmware_info;
+
+       op.u.firmware_info.type = XEN_FW_DISK_INFO;
+       for (nr = 0; nr < EDDMAXNR; nr++) {
+               struct edd_info *info = edd_info + nr;
+
+               op.u.firmware_info.index = nr;
+               info->params.length = sizeof(info->params);
+               set_xen_guest_handle(op.u.firmware_info.u.disk_info.edd_params,
+                                    &info->params);
+               ret = HYPERVISOR_dom0_op(&op);
+               if (ret)
+                       break;
+
+#define C(x) info->x = op.u.firmware_info.u.disk_info.x
+               C(device);
+               C(version);
+               C(interface_support);
+               C(legacy_max_cylinder);
+               C(legacy_max_head);
+               C(legacy_sectors_per_track);
+#undef C
+       }
+       boot_params.eddbuf_entries = nr;
+
+       op.u.firmware_info.type = XEN_FW_DISK_MBR_SIGNATURE;
+       for (nr = 0; nr < EDD_MBR_SIG_MAX; nr++) {
+               op.u.firmware_info.index = nr;
+               ret = HYPERVISOR_dom0_op(&op);
+               if (ret)
+                       break;
+               mbr_signature[nr] = op.u.firmware_info.u.disk_mbr_signature.mbr_signature;
+       }
+       boot_params.edd_mbr_sig_buf_entries = nr;
+#endif
+}
+
 /*
  * Set up the GDT and segment registers for -fstack-protector.  Until
  * we do this, we have to be careful not to call any stack-protected
@@ -1508,6 +1558,8 @@ asmlinkage void __init xen_start_kernel(void)
                /* Avoid searching for BIOS MP tables */
                x86_init.mpparse.find_smp_config = x86_init_noop;
                x86_init.mpparse.get_smp_config = x86_init_uint_noop;
+
+               xen_boot_params_init_edd();
        }
 #ifdef CONFIG_PCI
        /* PCI BIOS service won't work from a PV guest. */
@@ -1589,8 +1641,11 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
        switch (action) {
        case CPU_UP_PREPARE:
                xen_vcpu_setup(cpu);
-               if (xen_have_vector_callback)
+               if (xen_have_vector_callback) {
                        xen_init_lock_cpu(cpu);
+                       if (xen_feature(XENFEAT_hvm_safe_pvclock))
+                               xen_setup_timer(cpu);
+               }
                break;
        default:
                break;
index 6afbb2ca9a0ac450f79c6628b7cd9cd7c2ceeccf..e006c18d288a39ebec3343b2c240eced7a6fec34 100644 (file)
@@ -1748,14 +1748,18 @@ static void *m2v(phys_addr_t maddr)
 }
 
 /* Set the page permissions on an identity-mapped pages */
-static void set_page_prot(void *addr, pgprot_t prot)
+static void set_page_prot_flags(void *addr, pgprot_t prot, unsigned long flags)
 {
        unsigned long pfn = __pa(addr) >> PAGE_SHIFT;
        pte_t pte = pfn_pte(pfn, prot);
 
-       if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0))
+       if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, flags))
                BUG();
 }
+static void set_page_prot(void *addr, pgprot_t prot)
+{
+       return set_page_prot_flags(addr, prot, UVMF_NONE);
+}
 #ifdef CONFIG_X86_32
 static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
 {
@@ -1839,12 +1843,12 @@ static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end,
                                 unsigned long addr)
 {
        if (*pt_base == PFN_DOWN(__pa(addr))) {
-               set_page_prot((void *)addr, PAGE_KERNEL);
+               set_page_prot_flags((void *)addr, PAGE_KERNEL, UVMF_INVLPG);
                clear_page((void *)addr);
                (*pt_base)++;
        }
        if (*pt_end == PFN_DOWN(__pa(addr))) {
-               set_page_prot((void *)addr, PAGE_KERNEL);
+               set_page_prot_flags((void *)addr, PAGE_KERNEL, UVMF_INVLPG);
                clear_page((void *)addr);
                (*pt_end)--;
        }
@@ -2196,6 +2200,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = {
        .lazy_mode = {
                .enter = paravirt_enter_lazy_mmu,
                .leave = xen_leave_lazy_mmu,
+               .flush = paravirt_flush_lazy_mmu,
        },
 
        .set_fixmap = xen_set_fixmap,
index 09ea61d2e02f7f8993c1f08ab77d3d9460bb8447..0d466d7c71759b2bb48f4bedadf7fb724df8c2da 100644 (file)
@@ -144,6 +144,13 @@ static int xen_smp_intr_init(unsigned int cpu)
                goto fail;
        per_cpu(xen_callfuncsingle_irq, cpu) = rc;
 
+       /*
+        * The IRQ worker on PVHVM goes through the native path and uses the
+        * IPI mechanism.
+        */
+       if (xen_hvm_domain())
+               return 0;
+
        callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
        rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
                                    cpu,
@@ -167,6 +174,9 @@ static int xen_smp_intr_init(unsigned int cpu)
        if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0)
                unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu),
                                       NULL);
+       if (xen_hvm_domain())
+               return rc;
+
        if (per_cpu(xen_irq_work, cpu) >= 0)
                unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
 
@@ -418,7 +428,7 @@ static int xen_cpu_disable(void)
 
 static void xen_cpu_die(unsigned int cpu)
 {
-       while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
+       while (xen_pv_domain() && HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
                current->state = TASK_UNINTERRUPTIBLE;
                schedule_timeout(HZ/10);
        }
@@ -426,7 +436,8 @@ static void xen_cpu_die(unsigned int cpu)
        unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
        unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
        unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
-       unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
+       if (!xen_hvm_domain())
+               unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
        xen_uninit_lock_cpu(cpu);
        xen_teardown_timer(cpu);
 }
@@ -657,11 +668,7 @@ static int __cpuinit xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
 
 static void xen_hvm_cpu_die(unsigned int cpu)
 {
-       unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL);
-       unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
-       unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
-       unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
-       unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
+       xen_cpu_die(cpu);
        native_cpu_die(cpu);
 }
 
index f7a080ef03543e190b2475be811dd601d8b7c53d..8b54603ce81613fee6783a6d3869b0021878feb4 100644 (file)
@@ -364,6 +364,16 @@ void __cpuinit xen_init_lock_cpu(int cpu)
        int irq;
        const char *name;
 
+       WARN(per_cpu(lock_kicker_irq, cpu) > 0, "spinlock on CPU%d exists on IRQ%d!\n",
+            cpu, per_cpu(lock_kicker_irq, cpu));
+
+       /*
+        * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23
+        * (xen: disable PV spinlocks on HVM)
+        */
+       if (xen_hvm_domain())
+               return;
+
        name = kasprintf(GFP_KERNEL, "spinlock%d", cpu);
        irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR,
                                     cpu,
@@ -382,11 +392,26 @@ void __cpuinit xen_init_lock_cpu(int cpu)
 
 void xen_uninit_lock_cpu(int cpu)
 {
+       /*
+        * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23
+        * (xen: disable PV spinlocks on HVM)
+        */
+       if (xen_hvm_domain())
+               return;
+
        unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL);
+       per_cpu(lock_kicker_irq, cpu) = -1;
 }
 
 void __init xen_init_spinlocks(void)
 {
+       /*
+        * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23
+        * (xen: disable PV spinlocks on HVM)
+        */
+       if (xen_hvm_domain())
+               return;
+
        BUILD_BUG_ON(sizeof(struct xen_spinlock) > sizeof(arch_spinlock_t));
 
        pv_lock_ops.spin_is_locked = xen_spin_is_locked;
index 0296a95225017912cec06b9794683e62b20a5382..3d88bfdf9e1c092a23e9d4be143630a074a92926 100644 (file)
@@ -377,7 +377,7 @@ static const struct clock_event_device xen_vcpuop_clockevent = {
 
 static const struct clock_event_device *xen_clockevent =
        &xen_timerop_clockevent;
-static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events);
+static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events) = { .irq = -1 };
 
 static irqreturn_t xen_timer_interrupt(int irq, void *dev_id)
 {
@@ -401,6 +401,9 @@ void xen_setup_timer(int cpu)
        struct clock_event_device *evt;
        int irq;
 
+       evt = &per_cpu(xen_clock_events, cpu);
+       WARN(evt->irq >= 0, "IRQ%d for CPU%d is already allocated\n", evt->irq, cpu);
+
        printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu);
 
        name = kasprintf(GFP_KERNEL, "timer%d", cpu);
@@ -413,7 +416,6 @@ void xen_setup_timer(int cpu)
                                      IRQF_FORCE_RESUME,
                                      name, NULL);
 
-       evt = &per_cpu(xen_clock_events, cpu);
        memcpy(evt, xen_clockevent, sizeof(*evt));
 
        evt->cpumask = cpumask_of(cpu);
@@ -426,6 +428,7 @@ void xen_teardown_timer(int cpu)
        BUG_ON(cpu == 0);
        evt = &per_cpu(xen_clock_events, cpu);
        unbind_from_irqhandler(evt->irq, NULL);
+       evt->irq = -1;
 }
 
 void xen_setup_cpu_clockevents(void)
@@ -497,7 +500,11 @@ static void xen_hvm_setup_cpu_clockevents(void)
 {
        int cpu = smp_processor_id();
        xen_setup_runstate_info(cpu);
-       xen_setup_timer(cpu);
+       /*
+        * xen_setup_timer(cpu) - snprintf is bad in atomic context. Hence
+        * doing it xen_hvm_cpu_notify (which gets called by smp_init during
+        * early bootup and also during CPU hotplug events).
+        */
        xen_setup_cpu_clockevents();
 }
 
index 074b758efc42cf116d61f4755f0107f491890980..7c288358a745ad2312e93080201e341cf2b69207 100644 (file)
@@ -39,6 +39,7 @@
 
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
+EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
 
 DEFINE_IDA(blk_queue_ida);
index 6206a934eb8c85a2f21636759f1b64afe8e3fb70..5efc5a647183b688fe0e4312c7ad5bcb3dad403b 100644 (file)
@@ -229,6 +229,8 @@ queue_store_##name(struct request_queue *q, const char *page, size_t count) \
        unsigned long val;                                              \
        ssize_t ret;                                                    \
        ret = queue_var_store(&val, page, count);                       \
+       if (ret < 0)                                                    \
+                return ret;                                            \
        if (neg)                                                        \
                val = !val;                                             \
                                                                        \
index ae95ee6a58aad6d005affa10bb270bdf1008e986..789cdea05893bb8e3420ede5d1aa65e7af408e1b 100644 (file)
@@ -257,7 +257,6 @@ void delete_partition(struct gendisk *disk, int partno)
 
        hd_struct_put(part);
 }
-EXPORT_SYMBOL(delete_partition);
 
 static ssize_t whole_disk_show(struct device *dev,
                               struct device_attribute *attr, char *buf)
index ef5356cd280a54c086e4f8ff964245e38748a391..0262210cad386bde9b75f45d823c730920a54756 100644 (file)
@@ -161,6 +161,8 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock,
        else if (len < ds)
                msg->msg_flags |= MSG_TRUNC;
 
+       msg->msg_namelen = 0;
+
        lock_sock(sk);
        if (ctx->more) {
                ctx->more = 0;
index 6a6dfc062d2a47f04449fbb0e1c3f3852be337dc..a1c4f0a555832089129eb77be3680aea03856148 100644 (file)
@@ -432,6 +432,7 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
        long copied = 0;
 
        lock_sock(sk);
+       msg->msg_namelen = 0;
        for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
             iovlen--, iov++) {
                unsigned long seglen = iov->iov_len;
index 137ad1ec54383ceda3e515490ffc794a0242f907..13ccbda34ff979fbeb037b88ae400f4e248789a7 100644 (file)
@@ -44,6 +44,7 @@ struct crypto_rfc4543_ctx {
 
 struct crypto_rfc4543_req_ctx {
        u8 auth_tag[16];
+       u8 assocbuf[32];
        struct scatterlist cipher[1];
        struct scatterlist payload[2];
        struct scatterlist assoc[2];
@@ -1133,9 +1134,19 @@ static struct aead_request *crypto_rfc4543_crypt(struct aead_request *req,
        scatterwalk_crypto_chain(payload, dst, vdst == req->iv + 8, 2);
        assoclen += 8 + req->cryptlen - (enc ? 0 : authsize);
 
-       sg_init_table(assoc, 2);
-       sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
-                   req->assoc->offset);
+       if (req->assoc->length == req->assoclen) {
+               sg_init_table(assoc, 2);
+               sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
+                           req->assoc->offset);
+       } else {
+               BUG_ON(req->assoclen > sizeof(rctx->assocbuf));
+
+               scatterwalk_map_and_copy(rctx->assocbuf, req->assoc, 0,
+                                        req->assoclen, 0);
+
+               sg_init_table(assoc, 2);
+               sg_set_buf(assoc, rctx->assocbuf, req->assoclen);
+       }
        scatterwalk_crypto_chain(assoc, payload, 0, 2);
 
        aead_request_set_tfm(subreq, ctx->child);
index 92ed9692c47e8f63e4f5bae061f2ed29e62b4e76..4bf68c8d479733b71d33332e41afaa90654511ff 100644 (file)
@@ -396,7 +396,7 @@ config ACPI_CUSTOM_METHOD
 
 config ACPI_BGRT
        bool "Boottime Graphics Resource Table support"
-       depends on EFI
+       depends on EFI && X86
         help
          This driver adds support for exposing the ACPI Boottime Graphics
          Resource Table, which allows the operating system to obtain
index 82045e3f5caca124fd4f12c7605314e1f572580e..a82c7626aa9bc684ea96e92460cdfd7f8b2b83a3 100644 (file)
@@ -90,7 +90,7 @@ void acpi_i2c_register_devices(struct i2c_adapter *adapter)
        acpi_handle handle;
        acpi_status status;
 
-       handle = ACPI_HANDLE(&adapter->dev);
+       handle = ACPI_HANDLE(adapter->dev.parent);
        if (!handle)
                return;
 
index 5ff17306612771d04dd684020041fe61056906ab..ac8688b897056c247b0e2f35fb4ffbba599e2ffe 100644 (file)
@@ -65,44 +65,12 @@ static struct acpi_scan_handler pci_root_handler = {
        .detach = acpi_pci_root_remove,
 };
 
-/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */
+/* Lock to protect both acpi_pci_roots lists */
 static DEFINE_MUTEX(acpi_pci_root_lock);
 static LIST_HEAD(acpi_pci_roots);
-static LIST_HEAD(acpi_pci_drivers);
 
 static DEFINE_MUTEX(osc_lock);
 
-int acpi_pci_register_driver(struct acpi_pci_driver *driver)
-{
-       int n = 0;
-       struct acpi_pci_root *root;
-
-       mutex_lock(&acpi_pci_root_lock);
-       list_add_tail(&driver->node, &acpi_pci_drivers);
-       if (driver->add)
-               list_for_each_entry(root, &acpi_pci_roots, node) {
-                       driver->add(root);
-                       n++;
-               }
-       mutex_unlock(&acpi_pci_root_lock);
-
-       return n;
-}
-EXPORT_SYMBOL(acpi_pci_register_driver);
-
-void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
-{
-       struct acpi_pci_root *root;
-
-       mutex_lock(&acpi_pci_root_lock);
-       list_del(&driver->node);
-       if (driver->remove)
-               list_for_each_entry(root, &acpi_pci_roots, node)
-                       driver->remove(root);
-       mutex_unlock(&acpi_pci_root_lock);
-}
-EXPORT_SYMBOL(acpi_pci_unregister_driver);
-
 /**
  * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
  * @handle - the ACPI CA node in question.
@@ -413,9 +381,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
        acpi_status status;
        int result;
        struct acpi_pci_root *root;
-       struct acpi_pci_driver *driver;
        u32 flags, base_flags;
-       bool is_osc_granted = false;
 
        root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
        if (!root)
@@ -476,6 +442,30 @@ static int acpi_pci_root_add(struct acpi_device *device,
        flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
        acpi_pci_osc_support(root, flags);
 
+       /*
+        * TBD: Need PCI interface for enumeration/configuration of roots.
+        */
+
+       mutex_lock(&acpi_pci_root_lock);
+       list_add_tail(&root->node, &acpi_pci_roots);
+       mutex_unlock(&acpi_pci_root_lock);
+
+       /*
+        * Scan the Root Bridge
+        * --------------------
+        * Must do this prior to any attempt to bind the root device, as the
+        * PCI namespace does not get created until this call is made (and
+        * thus the root bridge's pci_dev does not exist).
+        */
+       root->bus = pci_acpi_scan_root(root);
+       if (!root->bus) {
+               printk(KERN_ERR PREFIX
+                           "Bus %04x:%02x not present in PCI namespace\n",
+                           root->segment, (unsigned int)root->secondary.start);
+               result = -ENODEV;
+               goto out_del_root;
+       }
+
        /* Indicate support for various _OSC capabilities. */
        if (pci_ext_cfg_avail())
                flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
@@ -494,6 +484,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
                        flags = base_flags;
                }
        }
+
        if (!pcie_ports_disabled
            && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
                flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
@@ -514,54 +505,28 @@ static int acpi_pci_root_add(struct acpi_device *device,
                status = acpi_pci_osc_control_set(device->handle, &flags,
                                       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
                if (ACPI_SUCCESS(status)) {
-                       is_osc_granted = true;
                        dev_info(&device->dev,
                                "ACPI _OSC control (0x%02x) granted\n", flags);
+                       if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
+                               /*
+                                * We have ASPM control, but the FADT indicates
+                                * that it's unsupported. Clear it.
+                                */
+                               pcie_clear_aspm(root->bus);
+                       }
                } else {
-                       is_osc_granted = false;
                        dev_info(&device->dev,
                                "ACPI _OSC request failed (%s), "
                                "returned control mask: 0x%02x\n",
                                acpi_format_exception(status), flags);
+                       pr_info("ACPI _OSC control for PCIe not granted, "
+                               "disabling ASPM\n");
+                       pcie_no_aspm();
                }
        } else {
                dev_info(&device->dev,
-                       "Unable to request _OSC control "
-                       "(_OSC support mask: 0x%02x)\n", flags);
-       }
-
-       /*
-        * TBD: Need PCI interface for enumeration/configuration of roots.
-        */
-
-       mutex_lock(&acpi_pci_root_lock);
-       list_add_tail(&root->node, &acpi_pci_roots);
-       mutex_unlock(&acpi_pci_root_lock);
-
-       /*
-        * Scan the Root Bridge
-        * --------------------
-        * Must do this prior to any attempt to bind the root device, as the
-        * PCI namespace does not get created until this call is made (and 
-        * thus the root bridge's pci_dev does not exist).
-        */
-       root->bus = pci_acpi_scan_root(root);
-       if (!root->bus) {
-               printk(KERN_ERR PREFIX
-                           "Bus %04x:%02x not present in PCI namespace\n",
-                           root->segment, (unsigned int)root->secondary.start);
-               result = -ENODEV;
-               goto out_del_root;
-       }
-
-       /* ASPM setting */
-       if (is_osc_granted) {
-               if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
-                       pcie_clear_aspm(root->bus);
-       } else {
-               pr_info("ACPI _OSC control for PCIe not granted, "
-                       "disabling ASPM\n");
-               pcie_no_aspm();
+                        "Unable to request _OSC control "
+                        "(_OSC support mask: 0x%02x)\n", flags);
        }
 
        pci_acpi_add_bus_pm_notifier(device, root->bus);
@@ -573,12 +538,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
                pci_assign_unassigned_bus_resources(root->bus);
        }
 
-       mutex_lock(&acpi_pci_root_lock);
-       list_for_each_entry(driver, &acpi_pci_drivers, node)
-               if (driver->add)
-                       driver->add(root);
-       mutex_unlock(&acpi_pci_root_lock);
-
        /* need to after hot-added ioapic is registered */
        if (system_state != SYSTEM_BOOTING)
                pci_enable_bridges(root->bus);
@@ -599,16 +558,9 @@ end:
 static void acpi_pci_root_remove(struct acpi_device *device)
 {
        struct acpi_pci_root *root = acpi_driver_data(device);
-       struct acpi_pci_driver *driver;
 
        pci_stop_root_bus(root->bus);
 
-       mutex_lock(&acpi_pci_root_lock);
-       list_for_each_entry_reverse(driver, &acpi_pci_drivers, node)
-               if (driver->remove)
-                       driver->remove(root);
-       mutex_unlock(&acpi_pci_root_lock);
-
        device_set_run_wake(root->bus->bridge, false);
        pci_acpi_remove_bus_pm_notifier(device);
 
index cd1434eb1de8d806e28f794ff2e1d55d69020989..033d1179bdb56bb0937e067cb907b9f4272f282d 100644 (file)
@@ -9,6 +9,9 @@
  *  Copyright (C) 2007-2008 Hewlett-Packard Development Company, L.P.
  *     Alex Chiang <achiang@hp.com>
  *
+ *  Copyright (C) 2013 Huawei Tech. Co., Ltd.
+ *     Jiang Liu <jiang.liu@huawei.com>
+ *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
  *  version 2, as published by the Free Software Foundation.
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
+#include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
 #include <linux/dmi.h>
 
 static bool debug;
@@ -61,20 +63,12 @@ ACPI_MODULE_NAME("pci_slot");
 #define SLOT_NAME_SIZE 21              /* Inspired by #define in acpiphp.h */
 
 struct acpi_pci_slot {
-       acpi_handle root_handle;        /* handle of the root bridge */
        struct pci_slot *pci_slot;      /* corresponding pci_slot */
        struct list_head list;          /* node in the list of slots */
 };
 
-static int acpi_pci_slot_add(struct acpi_pci_root *root);
-static void acpi_pci_slot_remove(struct acpi_pci_root *root);
-
 static LIST_HEAD(slot_list);
 static DEFINE_MUTEX(slot_list_lock);
-static struct acpi_pci_driver acpi_pci_slot_driver = {
-       .add = acpi_pci_slot_add,
-       .remove = acpi_pci_slot_remove,
-};
 
 static int
 check_slot(acpi_handle handle, unsigned long long *sun)
@@ -113,21 +107,8 @@ out:
        return device;
 }
 
-struct callback_args {
-       acpi_walk_callback      user_function;  /* only for walk_p2p_bridge */
-       struct pci_bus          *pci_bus;
-       acpi_handle             root_handle;
-};
-
 /*
- * register_slot
- *
- * Called once for each SxFy object in the namespace. Don't worry about
- * calling pci_create_slot multiple times for the same pci_bus:device,
- * since each subsequent call simply bumps the refcount on the pci_slot.
- *
- * The number of calls to pci_destroy_slot from unregister_slot is
- * symmetrical.
+ * Check whether handle has an associated slot and create PCI slot if it has.
  */
 static acpi_status
 register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
@@ -137,13 +118,22 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        char name[SLOT_NAME_SIZE];
        struct acpi_pci_slot *slot;
        struct pci_slot *pci_slot;
-       struct callback_args *parent_context = context;
-       struct pci_bus *pci_bus = parent_context->pci_bus;
+       struct pci_bus *pci_bus = context;
 
        device = check_slot(handle, &sun);
        if (device < 0)
                return AE_OK;
 
+       /*
+        * There may be multiple PCI functions associated with the same slot.
+        * Check whether PCI slot has already been created for this PCI device.
+        */
+       list_for_each_entry(slot, &slot_list, list) {
+               pci_slot = slot->pci_slot;
+               if (pci_slot->bus == pci_bus && pci_slot->number == device)
+                       return AE_OK;
+       }
+
        slot = kmalloc(sizeof(*slot), GFP_KERNEL);
        if (!slot) {
                err("%s: cannot allocate memory\n", __func__);
@@ -158,12 +148,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
                return AE_OK;
        }
 
-       slot->root_handle = parent_context->root_handle;
        slot->pci_slot = pci_slot;
-       INIT_LIST_HEAD(&slot->list);
-       mutex_lock(&slot_list_lock);
        list_add(&slot->list, &slot_list);
-       mutex_unlock(&slot_list_lock);
 
        get_device(&pci_bus->dev);
 
@@ -173,131 +159,24 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        return AE_OK;
 }
 
-/*
- * walk_p2p_bridge - discover and walk p2p bridges
- * @handle: points to an acpi_pci_root
- * @context: p2p_bridge_context pointer
- *
- * Note that when we call ourselves recursively, we pass a different
- * value of pci_bus in the child_context.
- */
-static acpi_status
-walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       int device, function;
-       unsigned long long adr;
-       acpi_status status;
-       acpi_handle dummy_handle;
-       acpi_walk_callback user_function;
-
-       struct pci_dev *dev;
-       struct pci_bus *pci_bus;
-       struct callback_args child_context;
-       struct callback_args *parent_context = context;
-
-       pci_bus = parent_context->pci_bus;
-       user_function = parent_context->user_function;
-
-       status = acpi_get_handle(handle, "_ADR", &dummy_handle);
-       if (ACPI_FAILURE(status))
-               return AE_OK;
-
-       status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
-       if (ACPI_FAILURE(status))
-               return AE_OK;
-
-       device = (adr >> 16) & 0xffff;
-       function = adr & 0xffff;
-
-       dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function));
-       if (!dev || !dev->subordinate)
-               goto out;
-
-       child_context.pci_bus = dev->subordinate;
-       child_context.user_function = user_function;
-       child_context.root_handle = parent_context->root_handle;
-
-       dbg("p2p bridge walk, pci_bus = %x\n", dev->subordinate->number);
-       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    user_function, NULL, &child_context, NULL);
-       if (ACPI_FAILURE(status))
-               goto out;
-
-       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    walk_p2p_bridge, NULL, &child_context, NULL);
-out:
-       pci_dev_put(dev);
-       return AE_OK;
-}
-
-/*
- * walk_root_bridge - generic root bridge walker
- * @root: poiner of an acpi_pci_root
- * @user_function: user callback for slot objects
- *
- * Call user_function for all objects underneath this root bridge.
- * Walk p2p bridges underneath us and call user_function on those too.
- */
-static int
-walk_root_bridge(struct acpi_pci_root *root, acpi_walk_callback user_function)
-{
-       acpi_status status;
-       acpi_handle handle = root->device->handle;
-       struct pci_bus *pci_bus = root->bus;
-       struct callback_args context;
-
-       context.pci_bus = pci_bus;
-       context.user_function = user_function;
-       context.root_handle = handle;
-
-       dbg("root bridge walk, pci_bus = %x\n", pci_bus->number);
-       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    user_function, NULL, &context, NULL);
-       if (ACPI_FAILURE(status))
-               return status;
-
-       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    walk_p2p_bridge, NULL, &context, NULL);
-       if (ACPI_FAILURE(status))
-               err("%s: walk_p2p_bridge failure - %d\n", __func__, status);
-
-       return status;
-}
-
-/*
- * acpi_pci_slot_add
- * @handle: points to an acpi_pci_root
- */
-static int
-acpi_pci_slot_add(struct acpi_pci_root *root)
+void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle)
 {
-       acpi_status status;
-
-       status = walk_root_bridge(root, register_slot);
-       if (ACPI_FAILURE(status))
-               err("%s: register_slot failure - %d\n", __func__, status);
-
-       return status;
+       mutex_lock(&slot_list_lock);
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+                           register_slot, NULL, bus, NULL);
+       mutex_unlock(&slot_list_lock);
 }
 
-/*
- * acpi_pci_slot_remove
- * @handle: points to an acpi_pci_root
- */
-static void
-acpi_pci_slot_remove(struct acpi_pci_root *root)
+void acpi_pci_slot_remove(struct pci_bus *bus)
 {
        struct acpi_pci_slot *slot, *tmp;
-       struct pci_bus *pbus;
-       acpi_handle handle = root->device->handle;
 
        mutex_lock(&slot_list_lock);
        list_for_each_entry_safe(slot, tmp, &slot_list, list) {
-               if (slot->root_handle == handle) {
+               if (slot->pci_slot->bus == bus) {
                        list_del(&slot->list);
-                       pbus = slot->pci_slot->bus;
                        pci_destroy_slot(slot->pci_slot);
-                       put_device(&pbus->dev);
+                       put_device(&bus->dev);
                        kfree(slot);
                }
        }
@@ -332,5 +211,4 @@ static struct dmi_system_id acpi_pci_slot_dmi_table[] __initdata = {
 void __init acpi_pci_slot_init(void)
 {
        dmi_check_system(acpi_pci_slot_dmi_table);
-       acpi_pci_register_driver(&acpi_pci_slot_driver);
 }
index fc95308e9a114896289922869ff068f486fdf788..ee255c60bdacc5a53849d23a5f0c1332e5f64b22 100644 (file)
@@ -66,7 +66,8 @@ module_param(latency_factor, uint, 0644);
 
 static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device);
 
-static struct acpi_processor_cx *acpi_cstate[CPUIDLE_STATE_MAX];
+static DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX],
+                                                               acpi_cstate);
 
 static int disabled_by_idle_boot_param(void)
 {
@@ -722,7 +723,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
                struct cpuidle_driver *drv, int index)
 {
        struct acpi_processor *pr;
-       struct acpi_processor_cx *cx = acpi_cstate[index];
+       struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
        pr = __this_cpu_read(processors);
 
@@ -745,7 +746,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
  */
 static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
 {
-       struct acpi_processor_cx *cx = acpi_cstate[index];
+       struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
        ACPI_FLUSH_CPU_CACHE();
 
@@ -775,7 +776,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
                struct cpuidle_driver *drv, int index)
 {
        struct acpi_processor *pr;
-       struct acpi_processor_cx *cx = acpi_cstate[index];
+       struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
        pr = __this_cpu_read(processors);
 
@@ -833,7 +834,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
                struct cpuidle_driver *drv, int index)
 {
        struct acpi_processor *pr;
-       struct acpi_processor_cx *cx = acpi_cstate[index];
+       struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
        pr = __this_cpu_read(processors);
 
@@ -960,7 +961,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
                    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
                        continue;
 #endif
-               acpi_cstate[count] = cx;
+               per_cpu(acpi_cstate[count], dev->cpu) = cx;
 
                count++;
                if (count == CPUIDLE_STATE_MAX)
index 5e7e991717d76f97981fcff3d0a221879b47fcea..f54d1985e59465a049af9cffd76d8f7f38a20e4a 100644 (file)
@@ -1790,7 +1790,6 @@ int __init acpi_scan_init(void)
        acpi_platform_init();
        acpi_csrt_init();
        acpi_container_init();
-       acpi_pci_slot_init();
 
        mutex_lock(&acpi_scan_lock);
        /*
index 6a67b07de49439a1bbe3da827ef4750bd74269a8..251e57d38942cdec01790d5fa02cb2c7aed87535 100644 (file)
@@ -415,17 +415,17 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        /* Marvell */
        { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },        /* 6145 */
        { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },        /* 6121 */
-       { PCI_DEVICE(0x1b4b, 0x9123),
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
          .class = PCI_CLASS_STORAGE_SATA_AHCI,
          .class_mask = 0xffffff,
          .driver_data = board_ahci_yes_fbs },                  /* 88se9128 */
-       { PCI_DEVICE(0x1b4b, 0x9125),
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9125 */
-       { PCI_DEVICE(0x1b4b, 0x917a),
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
-       { PCI_DEVICE(0x1b4b, 0x9192),
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 on some Gigabyte */
-       { PCI_DEVICE(0x1b4b, 0x91a3),
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
          .driver_data = board_ahci_yes_fbs },
 
        /* Promise */
index ffdd32d22602296875ff395a1fdc08e32509c393..2f48123d74c4c85d84180e3e7a39c712a1b7a175 100644 (file)
@@ -150,6 +150,7 @@ enum piix_controller_ids {
        tolapai_sata,
        piix_pata_vmw,                  /* PIIX4 for VMware, spurious DMA_ERR */
        ich8_sata_snb,
+       ich8_2port_sata_snb,
 };
 
 struct piix_map_db {
@@ -304,7 +305,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
        /* SATA Controller IDE (Lynx Point) */
        { 0x8086, 0x8c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
        /* SATA Controller IDE (Lynx Point) */
-       { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
        /* SATA Controller IDE (Lynx Point) */
        { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        /* SATA Controller IDE (Lynx Point-LP) */
@@ -439,6 +440,7 @@ static const struct piix_map_db *piix_map_db_table[] = {
        [ich8m_apple_sata]      = &ich8m_apple_map_db,
        [tolapai_sata]          = &tolapai_map_db,
        [ich8_sata_snb]         = &ich8_map_db,
+       [ich8_2port_sata_snb]   = &ich8_2port_map_db,
 };
 
 static struct pci_bits piix_enable_bits[] = {
@@ -1242,6 +1244,16 @@ static struct ata_port_info piix_port_info[] = {
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &piix_sata_ops,
        },
+
+       [ich8_2port_sata_snb] =
+       {
+               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR
+                                       | PIIX_FLAG_PIO16,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &piix_sata_ops,
+       },
 };
 
 #define AHCI_PCI_BAR 5
index 497adea1f0d641452f8b107d135af6a30c8164bd..63c743baf920217181bdb6fcd7cde0f3dc61d0c6 100644 (file)
@@ -2329,7 +2329,7 @@ int ata_dev_configure(struct ata_device *dev)
                 * from SATA Settings page of Identify Device Data Log.
                 */
                if (ata_id_has_devslp(dev->id)) {
-                       u8 sata_setting[ATA_SECT_SIZE];
+                       u8 *sata_setting = ap->sector_buf;
                        int i, j;
 
                        dev->flags |= ATA_DFLAG_DEVSLP;
@@ -2439,6 +2439,9 @@ int ata_dev_configure(struct ata_device *dev)
                dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
                                         dev->max_sectors);
 
+       if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48)
+               dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
        if (ap->ops->dev_config)
                ap->ops->dev_config(dev);
 
@@ -4100,6 +4103,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        /* Weird ATAPI devices */
        { "TORiSAN DVD-ROM DRD-N216", NULL,     ATA_HORKAGE_MAX_SEC_128 },
        { "QUANTUM DAT    DAT72-000", NULL,     ATA_HORKAGE_ATAPI_MOD16_DMA },
+       { "Slimtype DVD A  DS8A8SH", NULL,      ATA_HORKAGE_MAX_SEC_LBA48 },
 
        /* Devices we expect to fail diagnostics */
 
index 318b41358187739fe0671fe1c0be118668575da8..ff44787e5a457930dc8580ed72cb09386a8acf13 100644 (file)
@@ -532,8 +532,8 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
                        struct scsi_sense_hdr sshdr;
                        scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
                                             &sshdr);
-                       if (sshdr.sense_key == 0 &&
-                           sshdr.asc == 0 && sshdr.ascq == 0)
+                       if (sshdr.sense_key == RECOVERED_ERROR &&
+                           sshdr.asc == 0 && sshdr.ascq == 0x1d)
                                cmd_result &= ~SAM_STAT_CHECK_CONDITION;
                }
 
@@ -618,8 +618,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
                        struct scsi_sense_hdr sshdr;
                        scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
                                                &sshdr);
-                       if (sshdr.sense_key == 0 &&
-                               sshdr.asc == 0 && sshdr.ascq == 0)
+                       if (sshdr.sense_key == RECOVERED_ERROR &&
+                           sshdr.asc == 0 && sshdr.ascq == 0x1d)
                                cmd_result &= ~SAM_STAT_CHECK_CONDITION;
                }
 
index 5f74587ef258f4598e16c37bf9284d108c475ead..71671c42ef457e3486f13b770114a0c09459a708 100644 (file)
@@ -46,6 +46,7 @@
 #include "power.h"
 
 static DEFINE_MUTEX(dev_pm_qos_mtx);
+static DEFINE_MUTEX(dev_pm_qos_sysfs_mtx);
 
 static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
 
@@ -216,12 +217,17 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
        struct pm_qos_constraints *c;
        struct pm_qos_flags *f;
 
-       mutex_lock(&dev_pm_qos_mtx);
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
 
        /*
         * If the device's PM QoS resume latency limit or PM QoS flags have been
         * exposed to user space, they have to be hidden at this point.
         */
+       pm_qos_sysfs_remove_latency(dev);
+       pm_qos_sysfs_remove_flags(dev);
+
+       mutex_lock(&dev_pm_qos_mtx);
+
        __dev_pm_qos_hide_latency_limit(dev);
        __dev_pm_qos_hide_flags(dev);
 
@@ -254,6 +260,8 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
 
  out:
        mutex_unlock(&dev_pm_qos_mtx);
+
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
 }
 
 /**
@@ -558,6 +566,14 @@ static void __dev_pm_qos_drop_user_request(struct device *dev,
        kfree(req);
 }
 
+static void dev_pm_qos_drop_user_request(struct device *dev,
+                                        enum dev_pm_qos_req_type type)
+{
+       mutex_lock(&dev_pm_qos_mtx);
+       __dev_pm_qos_drop_user_request(dev, type);
+       mutex_unlock(&dev_pm_qos_mtx);
+}
+
 /**
  * dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space.
  * @dev: Device whose PM QoS latency limit is to be exposed to user space.
@@ -581,6 +597,8 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
                return ret;
        }
 
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
+
        mutex_lock(&dev_pm_qos_mtx);
 
        if (IS_ERR_OR_NULL(dev->power.qos))
@@ -591,26 +609,27 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
        if (ret < 0) {
                __dev_pm_qos_remove_request(req);
                kfree(req);
+               mutex_unlock(&dev_pm_qos_mtx);
                goto out;
        }
-
        dev->power.qos->latency_req = req;
+
+       mutex_unlock(&dev_pm_qos_mtx);
+
        ret = pm_qos_sysfs_add_latency(dev);
        if (ret)
-               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
+               dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
 
  out:
-       mutex_unlock(&dev_pm_qos_mtx);
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
        return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
 
 static void __dev_pm_qos_hide_latency_limit(struct device *dev)
 {
-       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) {
-               pm_qos_sysfs_remove_latency(dev);
+       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req)
                __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
-       }
 }
 
 /**
@@ -619,9 +638,15 @@ static void __dev_pm_qos_hide_latency_limit(struct device *dev)
  */
 void dev_pm_qos_hide_latency_limit(struct device *dev)
 {
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
+
+       pm_qos_sysfs_remove_latency(dev);
+
        mutex_lock(&dev_pm_qos_mtx);
        __dev_pm_qos_hide_latency_limit(dev);
        mutex_unlock(&dev_pm_qos_mtx);
+
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
 
@@ -649,6 +674,8 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
        }
 
        pm_runtime_get_sync(dev);
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
+
        mutex_lock(&dev_pm_qos_mtx);
 
        if (IS_ERR_OR_NULL(dev->power.qos))
@@ -659,16 +686,19 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
        if (ret < 0) {
                __dev_pm_qos_remove_request(req);
                kfree(req);
+               mutex_unlock(&dev_pm_qos_mtx);
                goto out;
        }
-
        dev->power.qos->flags_req = req;
+
+       mutex_unlock(&dev_pm_qos_mtx);
+
        ret = pm_qos_sysfs_add_flags(dev);
        if (ret)
-               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+               dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
 
  out:
-       mutex_unlock(&dev_pm_qos_mtx);
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
        pm_runtime_put(dev);
        return ret;
 }
@@ -676,10 +706,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
 
 static void __dev_pm_qos_hide_flags(struct device *dev)
 {
-       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) {
-               pm_qos_sysfs_remove_flags(dev);
+       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req)
                __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
-       }
 }
 
 /**
@@ -689,9 +717,15 @@ static void __dev_pm_qos_hide_flags(struct device *dev)
 void dev_pm_qos_hide_flags(struct device *dev)
 {
        pm_runtime_get_sync(dev);
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
+
+       pm_qos_sysfs_remove_flags(dev);
+
        mutex_lock(&dev_pm_qos_mtx);
        __dev_pm_qos_hide_flags(dev);
        mutex_unlock(&dev_pm_qos_mtx);
+
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
        pm_runtime_put(dev);
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
index e6732cf7c06eea7aedf62e383a390ef3e61c3fe2..79f4fca9877a579cd3b5c787fa7de4c1ed75612f 100644 (file)
@@ -398,7 +398,7 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
                        base = 0;
 
                if (max < rbnode->base_reg + rbnode->blklen)
-                       end = rbnode->base_reg + rbnode->blklen - max;
+                       end = max - rbnode->base_reg + 1;
                else
                        end = rbnode->blklen;
 
index 3d2367501fd0521ee4e472df6126b6ea25ee09a3..58cfb3232428f05b702d5b7b3a569429b9f8fe5c 100644 (file)
@@ -710,12 +710,12 @@ skip_format_initialization:
                }
        }
 
+       regmap_debugfs_init(map, config->name);
+
        ret = regcache_init(map, config);
        if (ret != 0)
                goto err_range;
 
-       regmap_debugfs_init(map, config->name);
-
        /* Add a devres resource for dev_get_regmap() */
        m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
        if (!m) {
@@ -1036,6 +1036,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                        kfree(async->work_buf);
                        kfree(async);
                }
+
+               return ret;
        }
 
        trace_regmap_hw_write_start(map->dev, reg,
index 25ef5c014fcaa4255e0e3009991b6a9ac1ff18c7..92b6d7c51e39590b3780f17c88737009b7becbbf 100644 (file)
@@ -51,8 +51,9 @@ new_skb(ulong len)
 {
        struct sk_buff *skb;
 
-       skb = alloc_skb(len, GFP_ATOMIC);
+       skb = alloc_skb(len + MAX_HEADER, GFP_ATOMIC);
        if (skb) {
+               skb_reserve(skb, MAX_HEADER);
                skb_reset_mac_header(skb);
                skb_reset_network_header(skb);
                skb->protocol = __constant_htons(ETH_P_AOE);
index fe5f6403417f892d744a034ea0bdda9a21596fda..dfe758382eafe71861f244f3436ce2db06f5f541 100644 (file)
@@ -922,6 +922,11 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
                lo->lo_flags |= LO_FLAGS_PARTSCAN;
        if (lo->lo_flags & LO_FLAGS_PARTSCAN)
                ioctl_by_bdev(bdev, BLKRRPART, 0);
+
+       /* Grab the block_device to prevent its destruction after we
+        * put /dev/loopXX inode. Later in loop_clr_fd() we bdput(bdev).
+        */
+       bdgrab(bdev);
        return 0;
 
 out_clr:
@@ -1031,8 +1036,10 @@ static int loop_clr_fd(struct loop_device *lo)
        memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
        memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
        memset(lo->lo_file_name, 0, LO_NAME_SIZE);
-       if (bdev)
+       if (bdev) {
+               bdput(bdev);
                invalidate_bdev(bdev);
+       }
        set_capacity(lo->lo_disk, 0);
        loop_sysfs_exit(lo);
        if (bdev) {
@@ -1044,29 +1051,12 @@ static int loop_clr_fd(struct loop_device *lo)
        lo->lo_state = Lo_unbound;
        /* This is safe: open() is still holding a reference. */
        module_put(THIS_MODULE);
+       if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev)
+               ioctl_by_bdev(bdev, BLKRRPART, 0);
        lo->lo_flags = 0;
        if (!part_shift)
                lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
        mutex_unlock(&lo->lo_ctl_mutex);
-
-       /*
-        * Remove all partitions, since BLKRRPART won't remove user
-        * added partitions when max_part=0
-        */
-       if (bdev) {
-               struct disk_part_iter piter;
-               struct hd_struct *part;
-
-               mutex_lock_nested(&bdev->bd_mutex, 1);
-               invalidate_partition(bdev->bd_disk, 0);
-               disk_part_iter_init(&piter, bdev->bd_disk,
-                                       DISK_PITER_INCL_EMPTY);
-               while ((part = disk_part_iter_next(&piter)))
-                       delete_partition(bdev->bd_disk, part->partno);
-               disk_part_iter_exit(&piter);
-               mutex_unlock(&bdev->bd_mutex);
-       }
-
        /*
         * Need not hold lo_ctl_mutex to fput backing file.
         * Calling fput holding lo_ctl_mutex triggers a circular
index 92250af84e7d151a8da57ed2cf6d22d8e3313e9d..32c678028e53c36ec8a52183799ad97642c666e8 100644 (file)
 /* Device instance number, incremented each time a device is probed. */
 static int instance;
 
+struct list_head online_list;
+struct list_head removing_list;
+spinlock_t dev_lock;
+
 /*
  * Global variable used to hold the major block device number
  * allocated in mtip_init().
  */
 static int mtip_major;
 static struct dentry *dfs_parent;
+static struct dentry *dfs_device_status;
 
 static u32 cpu_use[NR_CPUS];
 
@@ -243,40 +248,31 @@ static inline void release_slot(struct mtip_port *port, int tag)
 /*
  * Reset the HBA (without sleeping)
  *
- * Just like hba_reset, except does not call sleep, so can be
- * run from interrupt/tasklet context.
- *
  * @dd Pointer to the driver data structure.
  *
  * return value
  *     0       The reset was successful.
  *     -1      The HBA Reset bit did not clear.
  */
-static int hba_reset_nosleep(struct driver_data *dd)
+static int mtip_hba_reset(struct driver_data *dd)
 {
        unsigned long timeout;
 
-       /* Chip quirk: quiesce any chip function */
-       mdelay(10);
-
        /* Set the reset bit */
        writel(HOST_RESET, dd->mmio + HOST_CTL);
 
        /* Flush */
        readl(dd->mmio + HOST_CTL);
 
-       /*
-        * Wait 10ms then spin for up to 1 second
-        * waiting for reset acknowledgement
-        */
-       timeout = jiffies + msecs_to_jiffies(1000);
-       mdelay(10);
-       while ((readl(dd->mmio + HOST_CTL) & HOST_RESET)
-                && time_before(jiffies, timeout))
-               mdelay(1);
+       /* Spin for up to 2 seconds, waiting for reset acknowledgement */
+       timeout = jiffies + msecs_to_jiffies(2000);
+       do {
+               mdelay(10);
+               if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))
+                       return -1;
 
-       if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))
-               return -1;
+       } while ((readl(dd->mmio + HOST_CTL) & HOST_RESET)
+                && time_before(jiffies, timeout));
 
        if (readl(dd->mmio + HOST_CTL) & HOST_RESET)
                return -1;
@@ -481,7 +477,7 @@ static void mtip_restart_port(struct mtip_port *port)
                dev_warn(&port->dd->pdev->dev,
                        "PxCMD.CR not clear, escalating reset\n");
 
-               if (hba_reset_nosleep(port->dd))
+               if (mtip_hba_reset(port->dd))
                        dev_err(&port->dd->pdev->dev,
                                "HBA reset escalation failed.\n");
 
@@ -527,6 +523,26 @@ static void mtip_restart_port(struct mtip_port *port)
 
 }
 
+static int mtip_device_reset(struct driver_data *dd)
+{
+       int rv = 0;
+
+       if (mtip_check_surprise_removal(dd->pdev))
+               return 0;
+
+       if (mtip_hba_reset(dd) < 0)
+               rv = -EFAULT;
+
+       mdelay(1);
+       mtip_init_port(dd->port);
+       mtip_start_port(dd->port);
+
+       /* Enable interrupts on the HBA. */
+       writel(readl(dd->mmio + HOST_CTL) | HOST_IRQ_EN,
+                                       dd->mmio + HOST_CTL);
+       return rv;
+}
+
 /*
  * Helper function for tag logging
  */
@@ -632,7 +648,7 @@ static void mtip_timeout_function(unsigned long int data)
        if (cmdto_cnt) {
                print_tags(port->dd, "timed out", tagaccum, cmdto_cnt);
                if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
-                       mtip_restart_port(port);
+                       mtip_device_reset(port->dd);
                        wake_up_interruptible(&port->svc_wait);
                }
                clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
@@ -1283,11 +1299,11 @@ static int mtip_exec_internal_command(struct mtip_port *port,
        int rv = 0, ready2go = 1;
        struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL];
        unsigned long to;
+       struct driver_data *dd = port->dd;
 
        /* Make sure the buffer is 8 byte aligned. This is asic specific. */
        if (buffer & 0x00000007) {
-               dev_err(&port->dd->pdev->dev,
-                       "SG buffer is not 8 byte aligned\n");
+               dev_err(&dd->pdev->dev, "SG buffer is not 8 byte aligned\n");
                return -EFAULT;
        }
 
@@ -1300,23 +1316,21 @@ static int mtip_exec_internal_command(struct mtip_port *port,
                mdelay(100);
        } while (time_before(jiffies, to));
        if (!ready2go) {
-               dev_warn(&port->dd->pdev->dev,
+               dev_warn(&dd->pdev->dev,
                        "Internal cmd active. new cmd [%02X]\n", fis->command);
                return -EBUSY;
        }
        set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
        port->ic_pause_timer = 0;
 
-       if (fis->command == ATA_CMD_SEC_ERASE_UNIT)
-               clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
-       else if (fis->command == ATA_CMD_DOWNLOAD_MICRO)
-               clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
+       clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+       clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
 
        if (atomic == GFP_KERNEL) {
                if (fis->command != ATA_CMD_STANDBYNOW1) {
                        /* wait for io to complete if non atomic */
                        if (mtip_quiesce_io(port, 5000) < 0) {
-                               dev_warn(&port->dd->pdev->dev,
+                               dev_warn(&dd->pdev->dev,
                                        "Failed to quiesce IO\n");
                                release_slot(port, MTIP_TAG_INTERNAL);
                                clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
@@ -1361,58 +1375,84 @@ static int mtip_exec_internal_command(struct mtip_port *port,
        /* Issue the command to the hardware */
        mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL);
 
-       /* Poll if atomic, wait_for_completion otherwise */
        if (atomic == GFP_KERNEL) {
                /* Wait for the command to complete or timeout. */
-               if (wait_for_completion_timeout(
+               if (wait_for_completion_interruptible_timeout(
                                &wait,
-                               msecs_to_jiffies(timeout)) == 0) {
-                       dev_err(&port->dd->pdev->dev,
-                               "Internal command did not complete [%d] "
-                               "within timeout of  %lu ms\n",
-                               atomic, timeout);
-                       if (mtip_check_surprise_removal(port->dd->pdev) ||
+                               msecs_to_jiffies(timeout)) <= 0) {
+                       if (rv == -ERESTARTSYS) { /* interrupted */
+                               dev_err(&dd->pdev->dev,
+                                       "Internal command [%02X] was interrupted after %lu ms\n",
+                                       fis->command, timeout);
+                               rv = -EINTR;
+                               goto exec_ic_exit;
+                       } else if (rv == 0) /* timeout */
+                               dev_err(&dd->pdev->dev,
+                                       "Internal command did not complete [%02X] within timeout of  %lu ms\n",
+                                       fis->command, timeout);
+                       else
+                               dev_err(&dd->pdev->dev,
+                                       "Internal command [%02X] wait returned code [%d] after %lu ms - unhandled\n",
+                                       fis->command, rv, timeout);
+
+                       if (mtip_check_surprise_removal(dd->pdev) ||
                                test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
-                                               &port->dd->dd_flag)) {
+                                               &dd->dd_flag)) {
+                               dev_err(&dd->pdev->dev,
+                                       "Internal command [%02X] wait returned due to SR\n",
+                                       fis->command);
                                rv = -ENXIO;
                                goto exec_ic_exit;
                        }
+                       mtip_device_reset(dd); /* recover from timeout issue */
                        rv = -EAGAIN;
+                       goto exec_ic_exit;
                }
        } else {
+               u32 hba_stat, port_stat;
+
                /* Spin for <timeout> checking if command still outstanding */
                timeout = jiffies + msecs_to_jiffies(timeout);
                while ((readl(port->cmd_issue[MTIP_TAG_INTERNAL])
                                & (1 << MTIP_TAG_INTERNAL))
                                && time_before(jiffies, timeout)) {
-                       if (mtip_check_surprise_removal(port->dd->pdev)) {
+                       if (mtip_check_surprise_removal(dd->pdev)) {
                                rv = -ENXIO;
                                goto exec_ic_exit;
                        }
                        if ((fis->command != ATA_CMD_STANDBYNOW1) &&
                                test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
-                                               &port->dd->dd_flag)) {
+                                               &dd->dd_flag)) {
                                rv = -ENXIO;
                                goto exec_ic_exit;
                        }
-                       if (readl(port->mmio + PORT_IRQ_STAT) & PORT_IRQ_ERR) {
-                               atomic_inc(&int_cmd->active); /* error */
-                               break;
+                       port_stat = readl(port->mmio + PORT_IRQ_STAT);
+                       if (!port_stat)
+                               continue;
+
+                       if (port_stat & PORT_IRQ_ERR) {
+                               dev_err(&dd->pdev->dev,
+                                       "Internal command [%02X] failed\n",
+                                       fis->command);
+                               mtip_device_reset(dd);
+                               rv = -EIO;
+                               goto exec_ic_exit;
+                       } else {
+                               writel(port_stat, port->mmio + PORT_IRQ_STAT);
+                               hba_stat = readl(dd->mmio + HOST_IRQ_STAT);
+                               if (hba_stat)
+                                       writel(hba_stat,
+                                               dd->mmio + HOST_IRQ_STAT);
                        }
+                       break;
                }
        }
 
-       if (atomic_read(&int_cmd->active) > 1) {
-               dev_err(&port->dd->pdev->dev,
-                       "Internal command [%02X] failed\n", fis->command);
-               rv = -EIO;
-       }
        if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
                        & (1 << MTIP_TAG_INTERNAL)) {
                rv = -ENXIO;
-               if (!test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
-                                       &port->dd->dd_flag)) {
-                       mtip_restart_port(port);
+               if (!test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)) {
+                       mtip_device_reset(dd);
                        rv = -EAGAIN;
                }
        }
@@ -1724,7 +1764,8 @@ static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id,
  *      -EINVAL                Invalid parameters passed in, trim not supported
  *      -EIO           Error submitting trim request to hw
  */
-static int mtip_send_trim(struct driver_data *dd, unsigned int lba, unsigned int len)
+static int mtip_send_trim(struct driver_data *dd, unsigned int lba,
+                               unsigned int len)
 {
        int i, rv = 0;
        u64 tlba, tlen, sect_left;
@@ -1810,45 +1851,6 @@ static bool mtip_hw_get_capacity(struct driver_data *dd, sector_t *sectors)
        return (bool) !!port->identify_valid;
 }
 
-/*
- * Reset the HBA.
- *
- * Resets the HBA by setting the HBA Reset bit in the Global
- * HBA Control register. After setting the HBA Reset bit the
- * function waits for 1 second before reading the HBA Reset
- * bit to make sure it has cleared. If HBA Reset is not clear
- * an error is returned. Cannot be used in non-blockable
- * context.
- *
- * @dd Pointer to the driver data structure.
- *
- * return value
- *     0  The reset was successful.
- *     -1 The HBA Reset bit did not clear.
- */
-static int mtip_hba_reset(struct driver_data *dd)
-{
-       mtip_deinit_port(dd->port);
-
-       /* Set the reset bit */
-       writel(HOST_RESET, dd->mmio + HOST_CTL);
-
-       /* Flush */
-       readl(dd->mmio + HOST_CTL);
-
-       /* Wait for reset to clear */
-       ssleep(1);
-
-       /* Check the bit has cleared */
-       if (readl(dd->mmio + HOST_CTL) & HOST_RESET) {
-               dev_err(&dd->pdev->dev,
-                       "Reset bit did not clear.\n");
-               return -1;
-       }
-
-       return 0;
-}
-
 /*
  * Display the identify command data.
  *
@@ -2710,6 +2712,100 @@ static ssize_t mtip_hw_show_status(struct device *dev,
 
 static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL);
 
+/* debugsfs entries */
+
+static ssize_t show_device_status(struct device_driver *drv, char *buf)
+{
+       int size = 0;
+       struct driver_data *dd, *tmp;
+       unsigned long flags;
+       char id_buf[42];
+       u16 status = 0;
+
+       spin_lock_irqsave(&dev_lock, flags);
+       size += sprintf(&buf[size], "Devices Present:\n");
+       list_for_each_entry_safe(dd, tmp, &online_list, online_list) {
+               if (dd->pdev) {
+                       if (dd->port &&
+                           dd->port->identify &&
+                           dd->port->identify_valid) {
+                               strlcpy(id_buf,
+                                       (char *) (dd->port->identify + 10), 21);
+                               status = *(dd->port->identify + 141);
+                       } else {
+                               memset(id_buf, 0, 42);
+                               status = 0;
+                       }
+
+                       if (dd->port &&
+                           test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags)) {
+                               size += sprintf(&buf[size],
+                                       " device %s %s (ftl rebuild %d %%)\n",
+                                       dev_name(&dd->pdev->dev),
+                                       id_buf,
+                                       status);
+                       } else {
+                               size += sprintf(&buf[size],
+                                       " device %s %s\n",
+                                       dev_name(&dd->pdev->dev),
+                                       id_buf);
+                       }
+               }
+       }
+
+       size += sprintf(&buf[size], "Devices Being Removed:\n");
+       list_for_each_entry_safe(dd, tmp, &removing_list, remove_list) {
+               if (dd->pdev) {
+                       if (dd->port &&
+                           dd->port->identify &&
+                           dd->port->identify_valid) {
+                               strlcpy(id_buf,
+                                       (char *) (dd->port->identify+10), 21);
+                               status = *(dd->port->identify + 141);
+                       } else {
+                               memset(id_buf, 0, 42);
+                               status = 0;
+                       }
+
+                       if (dd->port &&
+                           test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags)) {
+                               size += sprintf(&buf[size],
+                                       " device %s %s (ftl rebuild %d %%)\n",
+                                       dev_name(&dd->pdev->dev),
+                                       id_buf,
+                                       status);
+                       } else {
+                               size += sprintf(&buf[size],
+                                       " device %s %s\n",
+                                       dev_name(&dd->pdev->dev),
+                                       id_buf);
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&dev_lock, flags);
+
+       return size;
+}
+
+static ssize_t mtip_hw_read_device_status(struct file *f, char __user *ubuf,
+                                               size_t len, loff_t *offset)
+{
+       int size = *offset;
+       char buf[MTIP_DFS_MAX_BUF_SIZE];
+
+       if (!len || *offset)
+               return 0;
+
+       size += show_device_status(NULL, buf);
+
+       *offset = size <= len ? size : len;
+       size = copy_to_user(ubuf, buf, *offset);
+       if (size)
+               return -EFAULT;
+
+       return *offset;
+}
+
 static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,
                                  size_t len, loff_t *offset)
 {
@@ -2804,6 +2900,13 @@ static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf,
        return *offset;
 }
 
+static const struct file_operations mtip_device_status_fops = {
+       .owner  = THIS_MODULE,
+       .open   = simple_open,
+       .read   = mtip_hw_read_device_status,
+       .llseek = no_llseek,
+};
+
 static const struct file_operations mtip_regs_fops = {
        .owner  = THIS_MODULE,
        .open   = simple_open,
@@ -4161,6 +4264,7 @@ static int mtip_pci_probe(struct pci_dev *pdev,
        const struct cpumask *node_mask;
        int cpu, i = 0, j = 0;
        int my_node = NUMA_NO_NODE;
+       unsigned long flags;
 
        /* Allocate memory for this devices private data. */
        my_node = pcibus_to_node(pdev->bus);
@@ -4218,6 +4322,9 @@ static int mtip_pci_probe(struct pci_dev *pdev,
        dd->pdev        = pdev;
        dd->numa_node   = my_node;
 
+       INIT_LIST_HEAD(&dd->online_list);
+       INIT_LIST_HEAD(&dd->remove_list);
+
        memset(dd->workq_name, 0, 32);
        snprintf(dd->workq_name, 31, "mtipq%d", dd->instance);
 
@@ -4305,6 +4412,14 @@ static int mtip_pci_probe(struct pci_dev *pdev,
        instance++;
        if (rv != MTIP_FTL_REBUILD_MAGIC)
                set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
+       else
+               rv = 0; /* device in rebuild state, return 0 from probe */
+
+       /* Add to online list even if in ftl rebuild */
+       spin_lock_irqsave(&dev_lock, flags);
+       list_add(&dd->online_list, &online_list);
+       spin_unlock_irqrestore(&dev_lock, flags);
+
        goto done;
 
 block_initialize_err:
@@ -4338,9 +4453,15 @@ static void mtip_pci_remove(struct pci_dev *pdev)
 {
        struct driver_data *dd = pci_get_drvdata(pdev);
        int counter = 0;
+       unsigned long flags;
 
        set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
 
+       spin_lock_irqsave(&dev_lock, flags);
+       list_del_init(&dd->online_list);
+       list_add(&dd->remove_list, &removing_list);
+       spin_unlock_irqrestore(&dev_lock, flags);
+
        if (mtip_check_surprise_removal(pdev)) {
                while (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) {
                        counter++;
@@ -4366,6 +4487,10 @@ static void mtip_pci_remove(struct pci_dev *pdev)
 
        pci_disable_msi(pdev);
 
+       spin_lock_irqsave(&dev_lock, flags);
+       list_del_init(&dd->remove_list);
+       spin_unlock_irqrestore(&dev_lock, flags);
+
        kfree(dd);
        pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
 }
@@ -4513,6 +4638,11 @@ static int __init mtip_init(void)
 
        pr_info(MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
 
+       spin_lock_init(&dev_lock);
+
+       INIT_LIST_HEAD(&online_list);
+       INIT_LIST_HEAD(&removing_list);
+
        /* Allocate a major block device number to use with this driver. */
        error = register_blkdev(0, MTIP_DRV_NAME);
        if (error <= 0) {
@@ -4522,11 +4652,18 @@ static int __init mtip_init(void)
        }
        mtip_major = error;
 
-       if (!dfs_parent) {
-               dfs_parent = debugfs_create_dir("rssd", NULL);
-               if (IS_ERR_OR_NULL(dfs_parent)) {
-                       pr_warn("Error creating debugfs parent\n");
-                       dfs_parent = NULL;
+       dfs_parent = debugfs_create_dir("rssd", NULL);
+       if (IS_ERR_OR_NULL(dfs_parent)) {
+               pr_warn("Error creating debugfs parent\n");
+               dfs_parent = NULL;
+       }
+       if (dfs_parent) {
+               dfs_device_status = debugfs_create_file("device_status",
+                                       S_IRUGO, dfs_parent, NULL,
+                                       &mtip_device_status_fops);
+               if (IS_ERR_OR_NULL(dfs_device_status)) {
+                       pr_err("Error creating device_status node\n");
+                       dfs_device_status = NULL;
                }
        }
 
index 3bffff5f670cc66f55f01ca5953f9d47702468ac..8e8334c9dd0f08139c9061bfced2111fe661c208 100644 (file)
@@ -129,9 +129,9 @@ enum {
        MTIP_PF_EH_ACTIVE_BIT       = 1, /* error handling */
        MTIP_PF_SE_ACTIVE_BIT       = 2, /* secure erase */
        MTIP_PF_DM_ACTIVE_BIT       = 3, /* download microcde */
-       MTIP_PF_PAUSE_IO      = ((1 << MTIP_PF_IC_ACTIVE_BIT) | \
-                               (1 << MTIP_PF_EH_ACTIVE_BIT) | \
-                               (1 << MTIP_PF_SE_ACTIVE_BIT) | \
+       MTIP_PF_PAUSE_IO      = ((1 << MTIP_PF_IC_ACTIVE_BIT) |
+                               (1 << MTIP_PF_EH_ACTIVE_BIT) |
+                               (1 << MTIP_PF_SE_ACTIVE_BIT) |
                                (1 << MTIP_PF_DM_ACTIVE_BIT)),
 
        MTIP_PF_SVC_THD_ACTIVE_BIT  = 4,
@@ -144,9 +144,9 @@ enum {
        MTIP_DDF_REMOVE_PENDING_BIT = 1,
        MTIP_DDF_OVER_TEMP_BIT      = 2,
        MTIP_DDF_WRITE_PROTECT_BIT  = 3,
-       MTIP_DDF_STOP_IO      = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \
-                               (1 << MTIP_DDF_SEC_LOCK_BIT) | \
-                               (1 << MTIP_DDF_OVER_TEMP_BIT) | \
+       MTIP_DDF_STOP_IO      = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) |
+                               (1 << MTIP_DDF_SEC_LOCK_BIT) |
+                               (1 << MTIP_DDF_OVER_TEMP_BIT) |
                                (1 << MTIP_DDF_WRITE_PROTECT_BIT)),
 
        MTIP_DDF_CLEANUP_BIT        = 5,
@@ -180,7 +180,7 @@ struct mtip_work {
 
 #define MTIP_TRIM_TIMEOUT_MS           240000
 #define MTIP_MAX_TRIM_ENTRIES          8
-#define MTIP_MAX_TRIM_ENTRY_LEN        0xfff8
+#define MTIP_MAX_TRIM_ENTRY_LEN                0xfff8
 
 struct mtip_trim_entry {
        u32 lba;   /* starting lba of region */
@@ -501,6 +501,10 @@ struct driver_data {
        atomic_t irq_workers_active;
 
        int isr_binding;
+
+       struct list_head online_list; /* linkage for online list */
+
+       struct list_head remove_list; /* linkage for removing list */
 };
 
 #endif
index f556f8a8b3f9b476949c6133f39778c49502e380..b7b7a88d9f689cdd3697ac8074de1887e7d50c15 100644 (file)
@@ -1742,9 +1742,10 @@ static int rbd_img_request_submit(struct rbd_img_request *img_request)
        struct rbd_device *rbd_dev = img_request->rbd_dev;
        struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
        struct rbd_obj_request *obj_request;
+       struct rbd_obj_request *next_obj_request;
 
        dout("%s: img %p\n", __func__, img_request);
-       for_each_obj_request(img_request, obj_request) {
+       for_each_obj_request_safe(img_request, obj_request, next_obj_request) {
                int ret;
 
                obj_request->callback = rbd_img_obj_callback;
index e3f9a99b8522e41dd2a4005142ea396838f26bbf..d784650d14f0d113c5d852e47d9dd676741e3b4f 100644 (file)
@@ -373,26 +373,14 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
        struct hpet_dev *devp;
        unsigned long addr;
 
-       if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
-               return -EINVAL;
-
        devp = file->private_data;
        addr = devp->hd_hpets->hp_hpet_phys;
 
        if (addr & (PAGE_SIZE - 1))
                return -ENOSYS;
 
-       vma->vm_flags |= VM_IO;
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-       if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
-                                       PAGE_SIZE, vma->vm_page_prot)) {
-               printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
-                       __func__);
-               return -EAGAIN;
-       }
-
-       return 0;
+       return vm_iomap_memory(vma, addr, PAGE_SIZE);
 #else
        return -ENOSYS;
 #endif
index 69ae5972713cf814e968c3c9d9ad8743d3dd240d..a0f7724852eb84d2ccb20eebc8e4309ea48a085c 100644 (file)
@@ -380,6 +380,15 @@ void hwrng_unregister(struct hwrng *rng)
 }
 EXPORT_SYMBOL_GPL(hwrng_unregister);
 
+static void __exit hwrng_exit(void)
+{
+       mutex_lock(&rng_mutex);
+       BUG_ON(current_rng);
+       kfree(rng_buffer);
+       mutex_unlock(&rng_mutex);
+}
+
+module_exit(hwrng_exit);
 
 MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
 MODULE_LICENSE("GPL");
index e905d5f5305180cd7cc77a8690e51ae53bed3fec..ce5f3fc25d6dbf1f7c45ff4cad6d2349da202d1a 100644 (file)
@@ -149,7 +149,8 @@ struct ports_device {
        spinlock_t ports_lock;
 
        /* To protect the vq operations for the control channel */
-       spinlock_t cvq_lock;
+       spinlock_t c_ivq_lock;
+       spinlock_t c_ovq_lock;
 
        /* The current config space is stored here */
        struct virtio_console_config config;
@@ -569,11 +570,14 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
        vq = portdev->c_ovq;
 
        sg_init_one(sg, &cpkt, sizeof(cpkt));
+
+       spin_lock(&portdev->c_ovq_lock);
        if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) == 0) {
                virtqueue_kick(vq);
                while (!virtqueue_get_buf(vq, &len))
                        cpu_relax();
        }
+       spin_unlock(&portdev->c_ovq_lock);
        return 0;
 }
 
@@ -1436,7 +1440,7 @@ static int add_port(struct ports_device *portdev, u32 id)
                 * rproc_serial does not want the console port, only
                 * the generic port implementation.
                 */
-               port->host_connected = port->guest_connected = true;
+               port->host_connected = true;
        else if (!use_multiport(port->portdev)) {
                /*
                 * If we're not using multiport support,
@@ -1709,23 +1713,23 @@ static void control_work_handler(struct work_struct *work)
        portdev = container_of(work, struct ports_device, control_work);
        vq = portdev->c_ivq;
 
-       spin_lock(&portdev->cvq_lock);
+       spin_lock(&portdev->c_ivq_lock);
        while ((buf = virtqueue_get_buf(vq, &len))) {
-               spin_unlock(&portdev->cvq_lock);
+               spin_unlock(&portdev->c_ivq_lock);
 
                buf->len = len;
                buf->offset = 0;
 
                handle_control_message(portdev, buf);
 
-               spin_lock(&portdev->cvq_lock);
+               spin_lock(&portdev->c_ivq_lock);
                if (add_inbuf(portdev->c_ivq, buf) < 0) {
                        dev_warn(&portdev->vdev->dev,
                                 "Error adding buffer to queue\n");
                        free_buf(buf, false);
                }
        }
-       spin_unlock(&portdev->cvq_lock);
+       spin_unlock(&portdev->c_ivq_lock);
 }
 
 static void out_intr(struct virtqueue *vq)
@@ -1752,13 +1756,23 @@ static void in_intr(struct virtqueue *vq)
        port->inbuf = get_inbuf(port);
 
        /*
-        * Don't queue up data when port is closed.  This condition
+        * Normally the port should not accept data when the port is
+        * closed. For generic serial ports, the host won't (shouldn't)
+        * send data till the guest is connected. But this condition
         * can be reached when a console port is not yet connected (no
-        * tty is spawned) and the host sends out data to console
-        * ports.  For generic serial ports, the host won't
-        * (shouldn't) send data till the guest is connected.
+        * tty is spawned) and the other side sends out data over the
+        * vring, or when a remote devices start sending data before
+        * the ports are opened.
+        *
+        * A generic serial port will discard data if not connected,
+        * while console ports and rproc-serial ports accepts data at
+        * any time. rproc-serial is initiated with guest_connected to
+        * false because port_fops_open expects this. Console ports are
+        * hooked up with an HVC console and is initialized with
+        * guest_connected to true.
         */
-       if (!port->guest_connected)
+
+       if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev))
                discard_port_data(port);
 
        spin_unlock_irqrestore(&port->inbuf_lock, flags);
@@ -1986,10 +2000,12 @@ static int virtcons_probe(struct virtio_device *vdev)
        if (multiport) {
                unsigned int nr_added_bufs;
 
-               spin_lock_init(&portdev->cvq_lock);
+               spin_lock_init(&portdev->c_ivq_lock);
+               spin_lock_init(&portdev->c_ovq_lock);
                INIT_WORK(&portdev->control_work, &control_work_handler);
 
-               nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+               nr_added_bufs = fill_queue(portdev->c_ivq,
+                                          &portdev->c_ivq_lock);
                if (!nr_added_bufs) {
                        dev_err(&vdev->dev,
                                "Error allocating buffers for control queue\n");
@@ -2140,7 +2156,7 @@ static int virtcons_restore(struct virtio_device *vdev)
                return ret;
 
        if (use_multiport(portdev))
-               fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+               fill_queue(portdev->c_ivq, &portdev->c_ivq_lock);
 
        list_for_each_entry(port, &portdev->ports, list) {
                port->in_vq = portdev->in_vqs[port->id];
index 1e2de730536282da499d60a57397f56b7d871c5e..f873dcefe0de63b4271ac82302a24892dbe4803d 100644 (file)
@@ -703,7 +703,7 @@ static void tegra20_pll_init(void)
        clks[pll_a_out0] = clk;
 
        /* PLLE */
-       clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, NULL,
+       clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, pmc_base,
                             0, 100000000, &pll_e_params,
                             0, pll_e_freq_table, NULL);
        clk_register_clkdev(clk, "pll_e", NULL);
index 4e5b7fb8927cb5304e3baf37dc3ccb87e71c31b9..37d23a0f8c569f93896808fa53c7a9c09b29d0a9 100644 (file)
@@ -178,10 +178,16 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
 
 static int cpu0_cpufreq_probe(struct platform_device *pdev)
 {
-       struct device_node *np;
+       struct device_node *np, *parent;
        int ret;
 
-       for_each_child_of_node(of_find_node_by_path("/cpus"), np) {
+       parent = of_find_node_by_path("/cpus");
+       if (!parent) {
+               pr_err("failed to find OF /cpus\n");
+               return -ENOENT;
+       }
+
+       for_each_child_of_node(parent, np) {
                if (of_get_property(np, "operating-points", NULL))
                        break;
        }
index 46bde01eee623bd443d582013425257fbd11ec50..cc4bd2f6838a30febb93e8bc1f9c55978cb2c19c 100644 (file)
@@ -14,8 +14,8 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef _CPUFREQ_GOVERNER_H
-#define _CPUFREQ_GOVERNER_H
+#ifndef _CPUFREQ_GOVERNOR_H
+#define _CPUFREQ_GOVERNOR_H
 
 #include <linux/cpufreq.h>
 #include <linux/kobject.h>
@@ -175,4 +175,4 @@ bool need_load_eval(struct cpu_dbs_common_info *cdbs,
                unsigned int sampling_rate);
 int cpufreq_governor_dbs(struct dbs_data *dbs_data,
                struct cpufreq_policy *policy, unsigned int event);
-#endif /* _CPUFREQ_GOVERNER_H */
+#endif /* _CPUFREQ_GOVERNOR_H */
index ad72922919ed79b181a83467dea455216676d56c..6133ef5cf671ba6caf7cf79c67c8afa903fdc23e 100644 (file)
@@ -502,7 +502,6 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
 
        sample_time = cpu->pstate_policy->sample_rate_ms;
        delay = msecs_to_jiffies(sample_time);
-       delay -= jiffies % delay;
        mod_timer_pinned(&cpu->timer, jiffies + delay);
 }
 
index 8bc5fef07e7a797f7cdde6e8f3f15445afde4993..22c9063e012064a07fb114f5568e6dac23093bc7 100644 (file)
@@ -1750,7 +1750,7 @@ static struct platform_driver cryp_driver = {
        .shutdown = ux500_cryp_shutdown,
        .driver = {
                .owner = THIS_MODULE,
-               .name  = "cryp1"
+               .name  = "cryp1",
                .pm    = &ux500_cryp_pm,
        }
 };
index 80b69971cf28d01752abd3654a8cc296f25a8380..aeaea32bcfdacd5fed2eb7e53536169348791cc8 100644 (file)
@@ -83,6 +83,7 @@ config INTEL_IOP_ADMA
 
 config DW_DMAC
        tristate "Synopsys DesignWare AHB DMA support"
+       depends on GENERIC_HARDIRQS
        select DMA_ENGINE
        default y if CPU_AT32AP7000
        help
index 6e13f262139a89acabf4c512ce8461d62e810a61..88cfc61329d20fb137a46ff852569bf8b567c60a 100644 (file)
@@ -310,8 +310,6 @@ static void atc_complete_all(struct at_dma_chan *atchan)
 
        dev_vdbg(chan2dev(&atchan->chan_common), "complete all\n");
 
-       BUG_ON(atc_chan_is_enabled(atchan));
-
        /*
         * Submit queued descriptors ASAP, i.e. before we go through
         * the completed ones.
@@ -368,6 +366,9 @@ static void atc_advance_work(struct at_dma_chan *atchan)
 {
        dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n");
 
+       if (atc_chan_is_enabled(atchan))
+               return;
+
        if (list_empty(&atchan->active_list) ||
            list_is_singular(&atchan->active_list)) {
                atc_complete_all(atchan);
@@ -1078,9 +1079,7 @@ static void atc_issue_pending(struct dma_chan *chan)
                return;
 
        spin_lock_irqsave(&atchan->lock, flags);
-       if (!atc_chan_is_enabled(atchan)) {
-               atc_advance_work(atchan);
-       }
+       atc_advance_work(atchan);
        spin_unlock_irqrestore(&atchan->lock, flags);
 }
 
index c4b4fd2acc42b8fc605ccc70a71907ab3668794c..08b43bf3715816951d23cc71dd49ca9b810b55f1 100644 (file)
@@ -276,12 +276,20 @@ static void omap_dma_issue_pending(struct dma_chan *chan)
 
        spin_lock_irqsave(&c->vc.lock, flags);
        if (vchan_issue_pending(&c->vc) && !c->desc) {
-               struct omap_dmadev *d = to_omap_dma_dev(chan->device);
-               spin_lock(&d->lock);
-               if (list_empty(&c->node))
-                       list_add_tail(&c->node, &d->pending);
-               spin_unlock(&d->lock);
-               tasklet_schedule(&d->task);
+               /*
+                * c->cyclic is used only by audio and in this case the DMA need
+                * to be started without delay.
+                */
+               if (!c->cyclic) {
+                       struct omap_dmadev *d = to_omap_dma_dev(chan->device);
+                       spin_lock(&d->lock);
+                       if (list_empty(&c->node))
+                               list_add_tail(&c->node, &d->pending);
+                       spin_unlock(&d->lock);
+                       tasklet_schedule(&d->task);
+               } else {
+                       omap_dma_start_desc(c);
+               }
        }
        spin_unlock_irqrestore(&c->vc.lock, flags);
 }
index 7181531227595475a907a4955b69324bb5c5e460..5dbc5946c4c3d9931585ac2440f64274f477fe02 100644 (file)
@@ -2882,7 +2882,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 {
        struct dma_pl330_platdata *pdat;
        struct dma_pl330_dmac *pdmac;
-       struct dma_pl330_chan *pch;
+       struct dma_pl330_chan *pch, *_p;
        struct pl330_info *pi;
        struct dma_device *pd;
        struct resource *res;
@@ -2984,7 +2984,16 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        ret = dma_async_device_register(pd);
        if (ret) {
                dev_err(&adev->dev, "unable to register DMAC\n");
-               goto probe_err2;
+               goto probe_err3;
+       }
+
+       if (adev->dev.of_node) {
+               ret = of_dma_controller_register(adev->dev.of_node,
+                                        of_dma_pl330_xlate, pdmac);
+               if (ret) {
+                       dev_err(&adev->dev,
+                       "unable to register DMA to the generic DT DMA helpers\n");
+               }
        }
 
        dev_info(&adev->dev,
@@ -2995,16 +3004,21 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,
                pi->pcfg.num_peri, pi->pcfg.num_events);
 
-       ret = of_dma_controller_register(adev->dev.of_node,
-                                        of_dma_pl330_xlate, pdmac);
-       if (ret) {
-               dev_err(&adev->dev,
-               "unable to register DMA to the generic DT DMA helpers\n");
-               goto probe_err2;
-       }
-
        return 0;
+probe_err3:
+       amba_set_drvdata(adev, NULL);
 
+       /* Idle the DMAC */
+       list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
+                       chan.device_node) {
+
+               /* Remove the channel */
+               list_del(&pch->chan.device_node);
+
+               /* Flush the channel */
+               pl330_control(&pch->chan, DMA_TERMINATE_ALL, 0);
+               pl330_free_chan_resources(&pch->chan);
+       }
 probe_err2:
        pl330_del(pi);
 probe_err1:
@@ -3023,8 +3037,10 @@ static int pl330_remove(struct amba_device *adev)
        if (!pdmac)
                return 0;
 
-       of_dma_controller_free(adev->dev.of_node);
+       if (adev->dev.of_node)
+               of_dma_controller_free(adev->dev.of_node);
 
+       dma_async_device_unregister(&pdmac->ddma);
        amba_set_drvdata(adev, NULL);
 
        /* Idle the DMAC */
index 806c77bfd434e7b6459197627265d8367340e4a2..272a3ec3595703b6dbdaa440108eb569410cf65f 100644 (file)
@@ -275,19 +275,18 @@ static int __init eisa_request_resources(struct eisa_root_device *root,
                }
                
                if (slot) {
-                       edev->res[i].name  = NULL;
                        edev->res[i].start = SLOT_ADDRESS(root, slot)
                                             + (i * 0x400);
                        edev->res[i].end   = edev->res[i].start + 0xff;
                        edev->res[i].flags = IORESOURCE_IO;
                } else {
-                       edev->res[i].name  = NULL;
                        edev->res[i].start = SLOT_ADDRESS(root, slot)
                                             + EISA_VENDOR_ID_OFFSET;
                        edev->res[i].end   = edev->res[i].start + 3;
-                       edev->res[i].flags = IORESOURCE_BUSY;
+                       edev->res[i].flags = IORESOURCE_IO | IORESOURCE_BUSY;
                }
 
+               dev_printk(KERN_DEBUG, &edev->dev, "%pR\n", &edev->res[i]);
                if (request_resource(root->res, &edev->res[i]))
                        goto failed;
        }
@@ -314,41 +313,40 @@ static int __init eisa_probe(struct eisa_root_device *root)
 {
         int i, c;
        struct eisa_device *edev;
+       char *enabled_str;
 
-       printk(KERN_INFO "EISA: Probing bus %d at %s\n",
-              root->bus_nr, dev_name(root->dev));
+       dev_info(root->dev, "Probing EISA bus %d\n", root->bus_nr);
 
        /* First try to get hold of slot 0. If there is no device
         * here, simply fail, unless root->force_probe is set. */
        
        edev = kzalloc(sizeof(*edev), GFP_KERNEL);
        if (!edev) {
-               printk(KERN_ERR "EISA: Couldn't allocate mainboard slot\n");
+               dev_err(root->dev, "EISA: Couldn't allocate mainboard slot\n");
                return -ENOMEM;
        }
                
-       if (eisa_request_resources(root, edev, 0)) {
-               printk(KERN_WARNING \
-                      "EISA: Cannot allocate resource for mainboard\n");
+       if (eisa_init_device(root, edev, 0)) {
                kfree(edev);
                if (!root->force_probe)
-                       return -EBUSY;
+                       return -ENODEV;
                goto force_probe;
        }
 
-       if (eisa_init_device(root, edev, 0)) {
-               eisa_release_resources(edev);
+       if (eisa_request_resources(root, edev, 0)) {
+               dev_warn(root->dev,
+                        "EISA: Cannot allocate resource for mainboard\n");
                kfree(edev);
                if (!root->force_probe)
-                       return -ENODEV;
+                       return -EBUSY;
                goto force_probe;
        }
 
-       printk(KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig);
+       dev_info(&edev->dev, "EISA: Mainboard %s detected\n", edev->id.sig);
 
        if (eisa_register_device(edev)) {
-               printk(KERN_ERR "EISA: Failed to register %s\n",
-                      edev->id.sig);
+               dev_err(&edev->dev, "EISA: Failed to register %s\n",
+                       edev->id.sig);
                eisa_release_resources(edev);
                kfree(edev);
        }
@@ -358,55 +356,47 @@ static int __init eisa_probe(struct eisa_root_device *root)
         for (c = 0, i = 1; i <= root->slots; i++) {
                edev = kzalloc(sizeof(*edev), GFP_KERNEL);
                if (!edev) {
-                       printk(KERN_ERR "EISA: Out of memory for slot %d\n", i);
+                       dev_err(root->dev, "EISA: Out of memory for slot %d\n",
+                               i);
                        continue;
                }
 
-               if (eisa_request_resources(root, edev, i)) {
-                       printk(KERN_WARNING \
-                              "Cannot allocate resource for EISA slot %d\n",
-                              i);
+               if (eisa_init_device(root, edev, i)) {
                        kfree(edev);
                        continue;
                }
 
-               if (eisa_init_device(root, edev, i)) {
-                       eisa_release_resources(edev);
+               if (eisa_request_resources(root, edev, i)) {
+                       dev_warn(root->dev,
+                                "Cannot allocate resource for EISA slot %d\n",
+                                i);
                        kfree(edev);
                        continue;
                }
-               
-               printk(KERN_INFO "EISA: slot %d : %s detected",
-                      i, edev->id.sig);
-                       
-               switch (edev->state) {
-               case EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED:
-                       printk(" (forced enabled)");
-                       break;
-
-               case EISA_CONFIG_FORCED:
-                       printk(" (forced disabled)");
-                       break;
-
-               case 0:
-                       printk(" (disabled)");
-                       break;
-               }
-                       
-               printk (".\n");
+
+               if (edev->state == (EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED))
+                       enabled_str = " (forced enabled)";
+               else if (edev->state == EISA_CONFIG_FORCED)
+                       enabled_str = " (forced disabled)";
+               else if (edev->state == 0)
+                       enabled_str = " (disabled)";
+               else
+                       enabled_str = "";
+
+               dev_info(&edev->dev, "EISA: slot %d: %s detected%s\n", i,
+                        edev->id.sig, enabled_str);
 
                c++;
 
                if (eisa_register_device(edev)) {
-                       printk(KERN_ERR "EISA: Failed to register %s\n",
-                              edev->id.sig);
+                       dev_err(&edev->dev, "EISA: Failed to register %s\n",
+                               edev->id.sig);
                        eisa_release_resources(edev);
                        kfree(edev);
                }
         }
 
-       printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s");
-
+       dev_info(root->dev, "EISA: Detected %d card%s\n", c, c == 1 ? "" : "s");
        return 0;
 }
 
index cdae207028a720f5080b3a55c9cf63e3e7b84424..a333bf3517de63a445c2636e85fb43cdc1d54c23 100644 (file)
 /* There is only *one* pci_eisa device per machine, right ? */
 static struct eisa_root_device pci_eisa_root;
 
-static int __init pci_eisa_init(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int __init pci_eisa_init(struct pci_dev *pdev)
 {
-       int rc;
+       int rc, i;
+       struct resource *res, *bus_res = NULL;
 
        if ((rc = pci_enable_device (pdev))) {
-               printk (KERN_ERR "pci_eisa : Could not enable device %s\n",
-                       pci_name(pdev));
+               dev_err(&pdev->dev, "Could not enable device\n");
                return rc;
        }
 
+       /*
+        * The Intel 82375 PCI-EISA bridge is a subtractive-decode PCI
+        * device, so the resources available on EISA are the same as those
+        * available on the 82375 bus.  This works the same as a PCI-PCI
+        * bridge in subtractive-decode mode (see pci_read_bridge_bases()).
+        * We assume other PCI-EISA bridges are similar.
+        *
+        * eisa_root_register() can only deal with a single io port resource,
+       *  so we use the first valid io port resource.
+        */
+       pci_bus_for_each_resource(pdev->bus, res, i)
+               if (res && (res->flags & IORESOURCE_IO)) {
+                       bus_res = res;
+                       break;
+               }
+
+       if (!bus_res) {
+               dev_err(&pdev->dev, "No resources available\n");
+               return -1;
+       }
+
        pci_eisa_root.dev              = &pdev->dev;
-       pci_eisa_root.res              = pdev->bus->resource[0];
-       pci_eisa_root.bus_base_addr    = pdev->bus->resource[0]->start;
+       pci_eisa_root.res              = bus_res;
+       pci_eisa_root.bus_base_addr    = bus_res->start;
        pci_eisa_root.slots            = EISA_MAX_SLOTS;
        pci_eisa_root.dma_mask         = pdev->dma_mask;
        dev_set_drvdata(pci_eisa_root.dev, &pci_eisa_root);
 
        if (eisa_root_register (&pci_eisa_root)) {
-               printk (KERN_ERR "pci_eisa : Could not register EISA root\n");
+               dev_err(&pdev->dev, "Could not register EISA root\n");
                return -1;
        }
 
        return 0;
 }
 
-static struct pci_device_id pci_eisa_pci_tbl[] = {
-       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-         PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
-       { 0, }
-};
+/*
+ * We have to call pci_eisa_init_early() before pnpacpi_init()/isapnp_init().
+ *   Otherwise pnp resource will get enabled early and could prevent eisa
+ *   to be initialized.
+ * Also need to make sure pci_eisa_init_early() is called after
+ * x86/pci_subsys_init().
+ * So need to use subsys_initcall_sync with it.
+ */
+static int __init pci_eisa_init_early(void)
+{
+       struct pci_dev *dev = NULL;
+       int ret;
 
-static struct pci_driver __refdata pci_eisa_driver = {
-       .name           = "pci_eisa",
-       .id_table       = pci_eisa_pci_tbl,
-       .probe          = pci_eisa_init,
-};
+       for_each_pci_dev(dev)
+               if ((dev->class >> 8) == PCI_CLASS_BRIDGE_EISA) {
+                       ret = pci_eisa_init(dev);
+                       if (ret)
+                               return ret;
+               }
 
-static int __init pci_eisa_init_module (void)
-{
-       return pci_register_driver (&pci_eisa_driver);
+       return 0;
 }
-
-device_initcall(pci_eisa_init_module);
-MODULE_DEVICE_TABLE(pci, pci_eisa_pci_tbl);
+subsys_initcall_sync(pci_eisa_init_early);
index 42c759a4d047f6754ddf8676a390d8d0dcdffafb..3e532002e4d1c01a3d21cd84c3a4a5e22e5e2440 100644 (file)
@@ -39,6 +39,7 @@ config FIRMWARE_MEMMAP
 config EFI_VARS
        tristate "EFI Variable Support via sysfs"
        depends on EFI
+       select UCS2_STRING
        default n
        help
          If you say Y here, you are able to get EFI (Extensible Firmware
index 7acafb80fd4c79b19b1c53551bb5e7e8612af707..f4baa11d3644d80377c3bdc34d86550d1c2eaeef 100644 (file)
@@ -80,6 +80,7 @@
 #include <linux/slab.h>
 #include <linux/pstore.h>
 #include <linux/ctype.h>
+#include <linux/ucs2_string.h>
 
 #include <linux/fs.h>
 #include <linux/ramfs.h>
@@ -172,51 +173,6 @@ static void efivar_update_sysfs_entries(struct work_struct *);
 static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries);
 static bool efivar_wq_enabled = true;
 
-/* Return the number of unicode characters in data */
-static unsigned long
-utf16_strnlen(efi_char16_t *s, size_t maxlength)
-{
-       unsigned long length = 0;
-
-       while (*s++ != 0 && length < maxlength)
-               length++;
-       return length;
-}
-
-static inline unsigned long
-utf16_strlen(efi_char16_t *s)
-{
-       return utf16_strnlen(s, ~0UL);
-}
-
-/*
- * Return the number of bytes is the length of this string
- * Note: this is NOT the same as the number of unicode characters
- */
-static inline unsigned long
-utf16_strsize(efi_char16_t *data, unsigned long maxlength)
-{
-       return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
-}
-
-static inline int
-utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
-{
-       while (1) {
-               if (len == 0)
-                       return 0;
-               if (*a < *b)
-                       return -1;
-               if (*a > *b)
-                       return 1;
-               if (*a == 0) /* implies *b == 0 */
-                       return 0;
-               a++;
-               b++;
-               len--;
-       }
-}
-
 static bool
 validate_device_path(struct efi_variable *var, int match, u8 *buffer,
                     unsigned long len)
@@ -268,7 +224,7 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer,
        u16 filepathlength;
        int i, desclength = 0, namelen;
 
-       namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName));
+       namelen = ucs2_strnlen(var->VariableName, sizeof(var->VariableName));
 
        /* Either "Boot" or "Driver" followed by four digits of hex */
        for (i = match; i < match+4; i++) {
@@ -291,7 +247,7 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer,
         * There's no stored length for the description, so it has to be
         * found by hand
         */
-       desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
+       desclength = ucs2_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
 
        /* Each boot entry must have a descriptor */
        if (!desclength)
@@ -436,24 +392,12 @@ static efi_status_t
 check_var_size_locked(struct efivars *efivars, u32 attributes,
                        unsigned long size)
 {
-       u64 storage_size, remaining_size, max_size;
-       efi_status_t status;
        const struct efivar_operations *fops = efivars->ops;
 
-       if (!efivars->ops->query_variable_info)
+       if (!efivars->ops->query_variable_store)
                return EFI_UNSUPPORTED;
 
-       status = fops->query_variable_info(attributes, &storage_size,
-                                          &remaining_size, &max_size);
-
-       if (status != EFI_SUCCESS)
-               return status;
-
-       if (!storage_size || size > remaining_size || size > max_size ||
-           (remaining_size - size) < (storage_size / 2))
-               return EFI_OUT_OF_RESOURCES;
-
-       return status;
+       return fops->query_variable_store(attributes, size);
 }
 
 
@@ -593,7 +537,7 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
        spin_lock_irq(&efivars->lock);
 
        status = check_var_size_locked(efivars, new_var->Attributes,
-              new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
+              new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));
 
        if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
                status = efivars->ops->set_variable(new_var->VariableName,
@@ -771,7 +715,7 @@ static ssize_t efivarfs_file_write(struct file *file,
         * QueryVariableInfo() isn't supported by the firmware.
         */
 
-       varsize = datasize + utf16_strsize(var->var.VariableName, 1024);
+       varsize = datasize + ucs2_strsize(var->var.VariableName, 1024);
        status = check_var_size(efivars, attributes, varsize);
 
        if (status != EFI_SUCCESS) {
@@ -1223,7 +1167,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
 
                inode = NULL;
 
-               len = utf16_strlen(entry->var.VariableName);
+               len = ucs2_strlen(entry->var.VariableName);
 
                /* name, plus '-', plus GUID, plus NUL*/
                name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC);
@@ -1481,8 +1425,8 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
 
                if (efi_guidcmp(entry->var.VendorGuid, vendor))
                        continue;
-               if (utf16_strncmp(entry->var.VariableName, efi_name,
-                                 utf16_strlen(efi_name))) {
+               if (ucs2_strncmp(entry->var.VariableName, efi_name,
+                                 ucs2_strlen(efi_name))) {
                        /*
                         * Check if an old format,
                         * which doesn't support holding
@@ -1494,8 +1438,8 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
                        for (i = 0; i < DUMP_NAME_LEN; i++)
                                efi_name_old[i] = name_old[i];
 
-                       if (utf16_strncmp(entry->var.VariableName, efi_name_old,
-                                         utf16_strlen(efi_name_old)))
+                       if (ucs2_strncmp(entry->var.VariableName, efi_name_old,
+                                         ucs2_strlen(efi_name_old)))
                                continue;
                }
 
@@ -1573,8 +1517,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
         * Does this variable already exist?
         */
        list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
-               strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
-               strsize2 = utf16_strsize(new_var->VariableName, 1024);
+               strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
+               strsize2 = ucs2_strsize(new_var->VariableName, 1024);
                if (strsize1 == strsize2 &&
                        !memcmp(&(search_efivar->var.VariableName),
                                new_var->VariableName, strsize1) &&
@@ -1590,7 +1534,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
        }
 
        status = check_var_size_locked(efivars, new_var->Attributes,
-              new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
+              new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));
 
        if (status && status != EFI_UNSUPPORTED) {
                spin_unlock_irq(&efivars->lock);
@@ -1614,7 +1558,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
 
        /* Create the entry in sysfs.  Locking is not required here */
        status = efivar_create_sysfs_entry(efivars,
-                                          utf16_strsize(new_var->VariableName,
+                                          ucs2_strsize(new_var->VariableName,
                                                         1024),
                                           new_var->VariableName,
                                           &new_var->VendorGuid);
@@ -1644,8 +1588,8 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
         * Does this variable already exist?
         */
        list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
-               strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
-               strsize2 = utf16_strsize(del_var->VariableName, 1024);
+               strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
+               strsize2 = ucs2_strsize(del_var->VariableName, 1024);
                if (strsize1 == strsize2 &&
                        !memcmp(&(search_efivar->var.VariableName),
                                del_var->VariableName, strsize1) &&
@@ -1684,16 +1628,17 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
        return count;
 }
 
-static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor)
+static bool variable_is_present(struct efivars *efivars,
+                               efi_char16_t *variable_name,
+                               efi_guid_t *vendor)
 {
        struct efivar_entry *entry, *n;
-       struct efivars *efivars = &__efivars;
        unsigned long strsize1, strsize2;
        bool found = false;
 
-       strsize1 = utf16_strsize(variable_name, 1024);
+       strsize1 = ucs2_strsize(variable_name, 1024);
        list_for_each_entry_safe(entry, n, &efivars->list, list) {
-               strsize2 = utf16_strsize(entry->var.VariableName, 1024);
+               strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
                if (strsize1 == strsize2 &&
                        !memcmp(variable_name, &(entry->var.VariableName),
                                strsize2) &&
@@ -1759,8 +1704,8 @@ static void efivar_update_sysfs_entries(struct work_struct *work)
                        if (status != EFI_SUCCESS) {
                                break;
                        } else {
-                               if (!variable_is_present(variable_name,
-                                   &vendor)) {
+                               if (!variable_is_present(efivars,
+                                   variable_name, &vendor)) {
                                        found = true;
                                        break;
                                }
@@ -2064,7 +2009,8 @@ int register_efivars(struct efivars *efivars,
                         * we'll ever see a different variable name,
                         * and may end up looping here forever.
                         */
-                       if (variable_is_present(variable_name, &vendor_guid)) {
+                       if (variable_is_present(efivars, variable_name,
+                                               &vendor_guid)) {
                                dup_variable_bug(variable_name, &vendor_guid,
                                                 variable_name_size);
                                status = EFI_NOT_FOUND;
@@ -2131,7 +2077,7 @@ efivars_init(void)
        ops.get_variable = efi.get_variable;
        ops.set_variable = efi.set_variable;
        ops.get_next_variable = efi.get_next_variable;
-       ops.query_variable_info = efi.query_variable_info;
+       ops.query_variable_store = efi_query_variable_store;
 
        error = register_efivars(&__efivars, &ops, efi_kobj);
        if (error)
index f9dbd503fc40fb0f1bccd0fa8f0995816a06b538..de3c317bd3e2d46f788c09d4af95a68dbbc97c69 100644 (file)
@@ -214,7 +214,7 @@ static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
         * If it can't be trusted, assume that the pin can be used as a GPIO.
         */
        if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f)))
-               return 1;
+               return 0;
 
        return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV;
 }
index 24059462c87fb23f6481304ae8d1bf819c2785e4..9391cf16e990db6a46870004754df0983568bd8e 100644 (file)
@@ -575,7 +575,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
                                                chip->gpio_chip.ngpio,
                                                irq_base,
                                                &pca953x_irq_simple_ops,
-                                               NULL);
+                                               chip);
                if (!chip->domain)
                        return -ENODEV;
 
index 9cc108d2b77081bc6aa666d08f394e09d2d8f623..8325f580c0f1b93149f4856db784093aaf20d177 100644 (file)
@@ -642,7 +642,12 @@ static struct platform_driver pxa_gpio_driver = {
                .of_match_table = of_match_ptr(pxa_gpio_dt_ids),
        },
 };
-module_platform_driver(pxa_gpio_driver);
+
+static int __init pxa_gpio_init(void)
+{
+       return platform_driver_register(&pxa_gpio_driver);
+}
+postcore_initcall(pxa_gpio_init);
 
 #ifdef CONFIG_PM
 static int pxa_gpio_suspend(void)
index 770476a9da87fbc4ca3a0a64008768602db8f14d..3ce5bc38ac3180b015548271eeeb0b6a3c6c5543 100644 (file)
@@ -307,11 +307,15 @@ static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {
        .xlate = irq_domain_xlate_twocell,
 };
 
-static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio,
+               struct device_node *np)
 {
-       int base = stmpe_gpio->irq_base;
+       int base = 0;
 
-       stmpe_gpio->domain = irq_domain_add_simple(NULL,
+       if (!np)
+               base = stmpe_gpio->irq_base;
+
+       stmpe_gpio->domain = irq_domain_add_simple(np,
                                stmpe_gpio->chip.ngpio, base,
                                &stmpe_gpio_irq_simple_ops, stmpe_gpio);
        if (!stmpe_gpio->domain) {
@@ -346,6 +350,9 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
        stmpe_gpio->chip = template_chip;
        stmpe_gpio->chip.ngpio = stmpe->num_gpios;
        stmpe_gpio->chip.dev = &pdev->dev;
+#ifdef CONFIG_OF
+       stmpe_gpio->chip.of_node = np;
+#endif
        stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
 
        if (pdata)
@@ -366,7 +373,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
                goto out_free;
 
        if (irq >= 0) {
-               ret = stmpe_gpio_irq_init(stmpe_gpio);
+               ret = stmpe_gpio_irq_init(stmpe_gpio, np);
                if (ret)
                        goto out_disable;
 
index 792c3e3795cae819caedaf12121052b47ad34a89..dd64a06dc5b4b4415a17286a53aad3d1453f8e36 100644 (file)
@@ -2326,7 +2326,6 @@ int drm_mode_addfb(struct drm_device *dev,
        fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
        if (IS_ERR(fb)) {
                DRM_DEBUG_KMS("could not create framebuffer\n");
-               drm_modeset_unlock_all(dev);
                return PTR_ERR(fb);
        }
 
@@ -2506,7 +2505,6 @@ int drm_mode_addfb2(struct drm_device *dev,
        fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
        if (IS_ERR(fb)) {
                DRM_DEBUG_KMS("could not create framebuffer\n");
-               drm_modeset_unlock_all(dev);
                return PTR_ERR(fb);
        }
 
index 59d6b9bf204bbd2d76b8440b3f7d435def394fe7..892ff9f959754263eb318da91347cbfffcc25ae7 100644 (file)
@@ -1544,10 +1544,10 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
        if (!fb_helper->fb)
                return 0;
 
-       drm_modeset_lock_all(dev);
+       mutex_lock(&fb_helper->dev->mode_config.mutex);
        if (!drm_fb_helper_is_bound(fb_helper)) {
                fb_helper->delayed_hotplug = true;
-               drm_modeset_unlock_all(dev);
+               mutex_unlock(&fb_helper->dev->mode_config.mutex);
                return 0;
        }
        DRM_DEBUG_KMS("\n");
@@ -1558,9 +1558,11 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 
        count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
                                                    max_height);
+       mutex_unlock(&fb_helper->dev->mode_config.mutex);
+
+       drm_modeset_lock_all(dev);
        drm_setup_crtcs(fb_helper);
        drm_modeset_unlock_all(dev);
-
        drm_fb_helper_set_par(fb_helper->fbdev);
 
        return 0;
index 13fdcd10a6051ddd9359af281390748528a6885e..429e07d0b0f147f2c9f672d65a18849f0c57f0f4 100644 (file)
@@ -123,6 +123,7 @@ int drm_open(struct inode *inode, struct file *filp)
        int retcode = 0;
        int need_setup = 0;
        struct address_space *old_mapping;
+       struct address_space *old_imapping;
 
        minor = idr_find(&drm_minors_idr, minor_id);
        if (!minor)
@@ -137,6 +138,7 @@ int drm_open(struct inode *inode, struct file *filp)
        if (!dev->open_count++)
                need_setup = 1;
        mutex_lock(&dev->struct_mutex);
+       old_imapping = inode->i_mapping;
        old_mapping = dev->dev_mapping;
        if (old_mapping == NULL)
                dev->dev_mapping = &inode->i_data;
@@ -159,8 +161,8 @@ int drm_open(struct inode *inode, struct file *filp)
 
 err_undo:
        mutex_lock(&dev->struct_mutex);
-       filp->f_mapping = old_mapping;
-       inode->i_mapping = old_mapping;
+       filp->f_mapping = old_imapping;
+       inode->i_mapping = old_imapping;
        iput(container_of(dev->dev_mapping, struct inode, i_data));
        dev->dev_mapping = old_mapping;
        mutex_unlock(&dev->struct_mutex);
index 04fa6f1808d151249f38fdf2974ee365eac7a047..f83f0719922e47b3e79cae946ce4ce9bdcbb9cd5 100644 (file)
@@ -506,7 +506,7 @@ drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
 }
 EXPORT_SYMBOL(drm_gtf_mode);
 
-#if IS_ENABLED(CONFIG_VIDEOMODE)
+#ifdef CONFIG_VIDEOMODE_HELPERS
 int drm_display_mode_from_videomode(const struct videomode *vm,
                                    struct drm_display_mode *dmode)
 {
@@ -523,26 +523,25 @@ int drm_display_mode_from_videomode(const struct videomode *vm,
        dmode->clock = vm->pixelclock / 1000;
 
        dmode->flags = 0;
-       if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
+       if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
                dmode->flags |= DRM_MODE_FLAG_PHSYNC;
-       else if (vm->dmt_flags & VESA_DMT_HSYNC_LOW)
+       else if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
                dmode->flags |= DRM_MODE_FLAG_NHSYNC;
-       if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH)
+       if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
                dmode->flags |= DRM_MODE_FLAG_PVSYNC;
-       else if (vm->dmt_flags & VESA_DMT_VSYNC_LOW)
+       else if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
                dmode->flags |= DRM_MODE_FLAG_NVSYNC;
-       if (vm->data_flags & DISPLAY_FLAGS_INTERLACED)
+       if (vm->flags & DISPLAY_FLAGS_INTERLACED)
                dmode->flags |= DRM_MODE_FLAG_INTERLACE;
-       if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN)
+       if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
                dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
        drm_mode_set_name(dmode);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
-#endif
 
-#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+#ifdef CONFIG_OF
 /**
  * of_get_drm_display_mode - get a drm_display_mode from devicetree
  * @np: device_node with the timing specification
@@ -572,7 +571,8 @@ int of_get_drm_display_mode(struct device_node *np,
        return 0;
 }
 EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
-#endif
+#endif /* CONFIG_OF */
+#endif /* CONFIG_VIDEOMODE_HELPERS */
 
 /**
  * drm_mode_set_name - set the name on a mode
index 3b11ab0fbc960ab1ff58fd842a2d51ff10ca15db..9a48e1a2d417ce7d294af15dd393ea93ec419cbb 100644 (file)
@@ -57,7 +57,7 @@ eb_create(struct drm_i915_gem_execbuffer2 *args)
        if (eb == NULL) {
                int size = args->buffer_count;
                int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
-               BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head)));
+               BUILD_BUG_ON_NOT_POWER_OF_2(PAGE_SIZE / sizeof(struct hlist_head));
                while (count > 2*size)
                        count >>= 1;
                eb = kzalloc(count*sizeof(struct hlist_head) +
index 32a3693905ecb14f697fd82b4f8a2419e2818552..1ce45a0a2d3e35bed35c03386f4f63a6b9ef0f97 100644 (file)
@@ -45,6 +45,9 @@
 
 struct intel_crt {
        struct intel_encoder base;
+       /* DPMS state is stored in the connector, which we need in the
+        * encoder's enable/disable callbacks */
+       struct intel_connector *connector;
        bool force_hotplug_required;
        u32 adpa_reg;
 };
@@ -81,29 +84,6 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
        return true;
 }
 
-static void intel_disable_crt(struct intel_encoder *encoder)
-{
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-       struct intel_crt *crt = intel_encoder_to_crt(encoder);
-       u32 temp;
-
-       temp = I915_READ(crt->adpa_reg);
-       temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
-       temp &= ~ADPA_DAC_ENABLE;
-       I915_WRITE(crt->adpa_reg, temp);
-}
-
-static void intel_enable_crt(struct intel_encoder *encoder)
-{
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-       struct intel_crt *crt = intel_encoder_to_crt(encoder);
-       u32 temp;
-
-       temp = I915_READ(crt->adpa_reg);
-       temp |= ADPA_DAC_ENABLE;
-       I915_WRITE(crt->adpa_reg, temp);
-}
-
 /* Note: The caller is required to filter out dpms modes not supported by the
  * platform. */
 static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
@@ -135,6 +115,19 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
        I915_WRITE(crt->adpa_reg, temp);
 }
 
+static void intel_disable_crt(struct intel_encoder *encoder)
+{
+       intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void intel_enable_crt(struct intel_encoder *encoder)
+{
+       struct intel_crt *crt = intel_encoder_to_crt(encoder);
+
+       intel_crt_set_dpms(encoder, crt->connector->base.dpms);
+}
+
+
 static void intel_crt_dpms(struct drm_connector *connector, int mode)
 {
        struct drm_device *dev = connector->dev;
@@ -746,6 +739,7 @@ void intel_crt_init(struct drm_device *dev)
        }
 
        connector = &intel_connector->base;
+       crt->connector = intel_connector;
        drm_connector_init(dev, &intel_connector->base,
                           &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
 
index d7d4afe013417f489934dbab8e5bafbf48614aa9..8fc93f90a7cdf9262d52186697b09ca84879b137 100644 (file)
@@ -2559,12 +2559,15 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 {
        struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
        struct intel_dp *intel_dp = &intel_dig_port->dp;
+       struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
        i2c_del_adapter(&intel_dp->adapter);
        drm_encoder_cleanup(encoder);
        if (is_edp(intel_dp)) {
                cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+               mutex_lock(&dev->mode_config.mutex);
                ironlake_panel_vdd_off_sync(intel_dp);
+               mutex_unlock(&dev->mode_config.mutex);
        }
        kfree(intel_dig_port);
 }
index fe22bb780e1d048efc76e92d7296ab98f94294db..78d8e919509fb1e0a5b6df59d9782693593cbdae 100644 (file)
@@ -751,8 +751,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
        int i;
        unsigned char misc = 0;
        unsigned char ext_vga[6];
-       unsigned char ext_vga_index24;
-       unsigned char dac_index90 = 0;
        u8 bppshift;
 
        static unsigned char dacvalue[] = {
@@ -803,7 +801,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
                option2 = 0x0000b000;
                break;
        case G200_ER:
-               dac_index90 = 0;
                break;
        }
 
@@ -852,10 +849,8 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
                WREG_DAC(i, dacvalue[i]);
        }
 
-       if (mdev->type == G200_ER) {
-               WREG_DAC(0x90, dac_index90);
-       }
-
+       if (mdev->type == G200_ER)
+               WREG_DAC(0x90, 0);
 
        if (option)
                pci_write_config_dword(dev->pdev, PCI_MGA_OPTION, option);
@@ -952,8 +947,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
        if (mdev->type == G200_WB)
                ext_vga[1] |= 0x88;
 
-       ext_vga_index24 = 0x05;
-
        /* Set pixel clocks */
        misc = 0x2d;
        WREG8(MGA_MISC_OUT, misc);
@@ -965,7 +958,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
        }
 
        if (mdev->type == G200_ER)
-               WREG_ECRT(24, ext_vga_index24);
+               WREG_ECRT(0x24, 0x5);
 
        if (mdev->type == G200_EV) {
                WREG_ECRT(6, 0);
index e816f06637a7210e9862a68734b753d447ffc28e..0e2c1a4f16595b09a5fa2023ac93691fd74da3b9 100644 (file)
@@ -248,6 +248,22 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
        }
 }
 
+static void
+nouveau_bios_shadow_platform(struct nouveau_bios *bios)
+{
+       struct pci_dev *pdev = nv_device(bios)->pdev;
+       size_t size;
+
+       void __iomem *rom = pci_platform_rom(pdev, &size);
+       if (rom && size) {
+               bios->data = kmalloc(size, GFP_KERNEL);
+               if (bios->data) {
+                       memcpy_fromio(bios->data, rom, size);
+                       bios->size = size;
+               }
+       }
+}
+
 static int
 nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
 {
@@ -288,6 +304,7 @@ nouveau_bios_shadow(struct nouveau_bios *bios)
                { "PROM", nouveau_bios_shadow_prom, false, 0, 0, NULL },
                { "ACPI", nouveau_bios_shadow_acpi, true, 0, 0, NULL },
                { "PCIROM", nouveau_bios_shadow_pci, true, 0, 0, NULL },
+               { "PLATFORM", nouveau_bios_shadow_platform, true, 0, 0, NULL },
                {}
        };
        struct methods *mthd, *best;
index 3b6dc883e150a4b8d3493cfd6104d7f827967e98..5eb3e0da7c6eb1eb213e527021668ddd96bccaa1 100644 (file)
@@ -391,7 +391,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_device *device = nv_device(drm->device);
        struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
-       struct nouveau_abi16_chan *chan, *temp;
+       struct nouveau_abi16_chan *chan = NULL, *temp;
        struct nouveau_abi16_ntfy *ntfy;
        struct nouveau_object *object;
        struct nv_dma_class args = {};
@@ -404,10 +404,11 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        if (unlikely(nv_device(abi16->device)->card_type >= NV_C0))
                return nouveau_abi16_put(abi16, -EINVAL);
 
-       list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
-               if (chan->chan->handle == (NVDRM_CHAN | info->channel))
+       list_for_each_entry(temp, &abi16->channels, head) {
+               if (temp->chan->handle == (NVDRM_CHAN | info->channel)) {
+                       chan = temp;
                        break;
-               chan = NULL;
+               }
        }
 
        if (!chan)
@@ -459,17 +460,18 @@ nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS)
 {
        struct drm_nouveau_gpuobj_free *fini = data;
        struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
-       struct nouveau_abi16_chan *chan, *temp;
+       struct nouveau_abi16_chan *chan = NULL, *temp;
        struct nouveau_abi16_ntfy *ntfy;
        int ret;
 
        if (unlikely(!abi16))
                return -ENOMEM;
 
-       list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
-               if (chan->chan->handle == (NVDRM_CHAN | fini->channel))
+       list_for_each_entry(temp, &abi16->channels, head) {
+               if (temp->chan->handle == (NVDRM_CHAN | fini->channel)) {
+                       chan = temp;
                        break;
-               chan = NULL;
+               }
        }
 
        if (!chan)
index d1099365bfc1f47d6aa1be0e640f66c3fb66fcf2..c95decf543e904cbe89a6792fa9c709a2b87ad17 100644 (file)
@@ -71,12 +71,26 @@ module_param_named(modeset, nouveau_modeset, int, 0400);
 
 static struct drm_driver driver;
 
+static int
+nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
+{
+       struct nouveau_drm *drm =
+               container_of(event, struct nouveau_drm, vblank[head]);
+       drm_handle_vblank(drm->dev, head);
+       return NVKM_EVENT_KEEP;
+}
+
 static int
 nouveau_drm_vblank_enable(struct drm_device *dev, int head)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_disp *pdisp = nouveau_disp(drm->device);
-       nouveau_event_get(pdisp->vblank, head, &drm->vblank);
+
+       if (WARN_ON_ONCE(head > ARRAY_SIZE(drm->vblank)))
+               return -EIO;
+       WARN_ON_ONCE(drm->vblank[head].func);
+       drm->vblank[head].func = nouveau_drm_vblank_handler;
+       nouveau_event_get(pdisp->vblank, head, &drm->vblank[head]);
        return 0;
 }
 
@@ -85,16 +99,11 @@ nouveau_drm_vblank_disable(struct drm_device *dev, int head)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_disp *pdisp = nouveau_disp(drm->device);
-       nouveau_event_put(pdisp->vblank, head, &drm->vblank);
-}
-
-static int
-nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
-{
-       struct nouveau_drm *drm =
-               container_of(event, struct nouveau_drm, vblank);
-       drm_handle_vblank(drm->dev, head);
-       return NVKM_EVENT_KEEP;
+       if (drm->vblank[head].func)
+               nouveau_event_put(pdisp->vblank, head, &drm->vblank[head]);
+       else
+               WARN_ON_ONCE(1);
+       drm->vblank[head].func = NULL;
 }
 
 static u64
@@ -292,7 +301,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
 
        dev->dev_private = drm;
        drm->dev = dev;
-       drm->vblank.func = nouveau_drm_vblank_handler;
 
        INIT_LIST_HEAD(&drm->clients);
        spin_lock_init(&drm->tile.lock);
index b25df374c901df36f1c6e9408225ef9a2ed4b813..9c39bafbef2c23680fa757fdd251e158a56ae931 100644 (file)
@@ -113,7 +113,7 @@ struct nouveau_drm {
        struct nvbios vbios;
        struct nouveau_display *display;
        struct backlight_device *backlight;
-       struct nouveau_eventh vblank;
+       struct nouveau_eventh vblank[4];
 
        /* power management */
        struct nouveau_pm *pm;
index 7f0e6c3f37d1fae4983bd6d8270364e52f00fc30..1ddc03e51bf47789b65992db64a3784cf0dad424 100644 (file)
@@ -479,7 +479,7 @@ nv50_display_flip_wait(void *data)
 {
        struct nv50_display_flip *flip = data;
        if (nouveau_bo_rd32(flip->disp->sync, flip->chan->addr / 4) ==
-                                             flip->chan->data);
+                                             flip->chan->data)
                return true;
        usleep_range(1, 2);
        return false;
index b8015913d3823547425b91b1a1c323db6cb3bfb2..fa3c56fba294fe1a433b2d7b6a3e1507e357d1ca 100644 (file)
@@ -99,6 +99,29 @@ static bool radeon_read_bios(struct radeon_device *rdev)
        return true;
 }
 
+static bool radeon_read_platform_bios(struct radeon_device *rdev)
+{
+       uint8_t __iomem *bios;
+       size_t size;
+
+       rdev->bios = NULL;
+
+       bios = pci_platform_rom(rdev->pdev, &size);
+       if (!bios) {
+               return false;
+       }
+
+       if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+               return false;
+       }
+       rdev->bios = kmemdup(bios, size, GFP_KERNEL);
+       if (rdev->bios == NULL) {
+               return false;
+       }
+
+       return true;
+}
+
 #ifdef CONFIG_ACPI
 /* ATRM is used to get the BIOS on the discrete cards in
  * dual-gpu systems.
@@ -620,6 +643,9 @@ bool radeon_get_bios(struct radeon_device *rdev)
        if (r == false) {
                r = radeon_read_disabled_bios(rdev);
        }
+       if (r == false) {
+               r = radeon_read_platform_bios(rdev);
+       }
        if (r == false || rdev->bios == NULL) {
                DRM_ERROR("Unable to locate a BIOS ROM\n");
                rdev->bios = NULL;
index d24d04013476bc4f9b1493518b8cb80f6de1f045..e461e99724552f96014581f81f191df8baed89ef 100644 (file)
@@ -4,8 +4,7 @@ config DRM_TILCDC
        select DRM_KMS_HELPER
        select DRM_KMS_CMA_HELPER
        select DRM_GEM_CMA_HELPER
-       select OF_VIDEOMODE
-       select OF_DISPLAY_TIMING
+       select VIDEOMODE_HELPERS
        select BACKLIGHT_CLASS_DEVICE
        help
          Choose this option if you have an TI SoC with LCDC display
index 580b74e2022b26f9fc950142361321d775f6a9be..90ee49786372b5ae875a090ad60f7808acb00de1 100644 (file)
@@ -173,7 +173,7 @@ static int panel_connector_get_modes(struct drm_connector *connector)
                struct drm_display_mode *mode = drm_mode_create(dev);
                struct videomode vm;
 
-               if (videomode_from_timing(timings, &vm, i))
+               if (videomode_from_timings(timings, &vm, i))
                        break;
 
                drm_display_mode_from_videomode(&vm, mode);
index fe5cdbcf263605b7b5ec853b4d5f354f7c754b13..b44d548c56f8e43a3e14878622c8f8ed3507bf35 100644 (file)
@@ -61,6 +61,10 @@ static int udl_get_modes(struct drm_connector *connector)
        int ret;
 
        edid = (struct edid *)udl_get_edid(udl);
+       if (!edid) {
+               drm_mode_connector_update_edid_property(connector, NULL);
+               return 0;
+       }
 
        /*
         * We only read the main block, but if the monitor reports extension
index 512b01c04ea7610bcb6466208255a9d83a36cb1d..aa341d135867eea541c9ffdd7113f75641eef5c4 100644 (file)
@@ -2077,7 +2077,6 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_MASTERKIT, USB_DEVICE_ID_MASTERKIT_MA901RADIO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
@@ -2244,6 +2243,18 @@ bool hid_ignore(struct hid_device *hdev)
                     hdev->product <= USB_DEVICE_ID_VELLEMAN_K8061_LAST))
                        return true;
                break;
+       case USB_VENDOR_ID_ATMEL_V_USB:
+               /* Masterkit MA901 usb radio based on Atmel tiny85 chip and
+                * it has the same USB ID as many Atmel V-USB devices. This
+                * usb radio is handled by radio-ma901.c driver so we want
+                * ignore the hid. Check the name, bus, product and ignore
+                * if we have MA901 usb radio.
+                */
+               if (hdev->product == USB_DEVICE_ID_ATMEL_V_USB &&
+                       hdev->bus == BUS_USB &&
+                       strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0)
+                       return true;
+               break;
        }
 
        if (hdev->type == HID_TYPE_USBMOUSE &&
index c4388776f4e470ae527470fb47357c220bbf9624..5309fd5eb0ebae7357044046f91ec9e0efe7e345 100644 (file)
 #define USB_VENDOR_ID_ATMEL            0x03eb
 #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c
 #define USB_DEVICE_ID_ATMEL_MXT_DIGITIZER      0x2118
+#define USB_VENDOR_ID_ATMEL_V_USB      0x16c0
+#define USB_DEVICE_ID_ATMEL_V_USB      0x05df
 
 #define USB_VENDOR_ID_AUREAL           0x0755
 #define USB_DEVICE_ID_AUREAL_W01RN     0x2626
 #define USB_VENDOR_ID_MADCATZ          0x0738
 #define USB_DEVICE_ID_MADCATZ_BEATPAD  0x4540
 
-#define USB_VENDOR_ID_MASTERKIT                        0x16c0
-#define USB_DEVICE_ID_MASTERKIT_MA901RADIO     0x05df
-
 #define USB_VENDOR_ID_MCC              0x09db
 #define USB_DEVICE_ID_MCC_PMD1024LS    0x0076
 #define USB_DEVICE_ID_MCC_PMD1208LS    0x007a
index f7f113ba083eb43fb1073d189a4979f7d4d6d724..a8ce44296cfddaf34a486a7c78edde4836cd3115 100644 (file)
@@ -462,6 +462,21 @@ static int magicmouse_input_mapping(struct hid_device *hdev,
        return 0;
 }
 
+static void magicmouse_input_configured(struct hid_device *hdev,
+               struct hid_input *hi)
+
+{
+       struct magicmouse_sc *msc = hid_get_drvdata(hdev);
+
+       int ret = magicmouse_setup_input(msc->input, hdev);
+       if (ret) {
+               hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
+               /* clean msc->input to notify probe() of the failure */
+               msc->input = NULL;
+       }
+}
+
+
 static int magicmouse_probe(struct hid_device *hdev,
        const struct hid_device_id *id)
 {
@@ -493,15 +508,10 @@ static int magicmouse_probe(struct hid_device *hdev,
                goto err_free;
        }
 
-       /* We do this after hid-input is done parsing reports so that
-        * hid-input uses the most natural button and axis IDs.
-        */
-       if (msc->input) {
-               ret = magicmouse_setup_input(msc->input, hdev);
-               if (ret) {
-                       hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
-                       goto err_stop_hw;
-               }
+       if (!msc->input) {
+               hid_err(hdev, "magicmouse input not registered\n");
+               ret = -ENOMEM;
+               goto err_stop_hw;
        }
 
        if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
@@ -568,6 +578,7 @@ static struct hid_driver magicmouse_driver = {
        .remove = magicmouse_remove,
        .raw_event = magicmouse_raw_event,
        .input_mapping = magicmouse_input_mapping,
+       .input_configured = magicmouse_input_configured,
 };
 module_hid_driver(magicmouse_driver);
 
index db713c0dfba4d6c6272ac19c79b793595a9cdad7..461a0d739d75b0d646d9197a89ed6852f932be07 100644 (file)
@@ -416,6 +416,8 @@ static int __hwspin_lock_request(struct hwspinlock *hwlock)
        ret = pm_runtime_get_sync(dev);
        if (ret < 0) {
                dev_err(dev, "%s: can't power on device\n", __func__);
+               pm_runtime_put_noidle(dev);
+               module_put(dev->driver->owner);
                return ret;
        }
 
index 0ceb6e1b0f6595fb0ca006bec70a3501bcd83594..e3085c487ace5943650e79ae7ffdde03d0ffcfb9 100644 (file)
@@ -182,7 +182,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
        adap->algo = &i2c_dw_algo;
        adap->dev.parent = &pdev->dev;
        adap->dev.of_node = pdev->dev.of_node;
-       ACPI_HANDLE_SET(&adap->dev, ACPI_HANDLE(&pdev->dev));
 
        r = i2c_add_numbered_adapter(adap);
        if (r) {
index 5d66750138647d619d9521922a3d2c5421db73e4..1a38dd7dfe4e56c9b749cac1e741fe4ad092024c 100644 (file)
@@ -465,6 +465,7 @@ static const struct x86_cpu_id intel_idle_ids[] = {
        ICPU(0x3c, idle_cpu_hsw),
        ICPU(0x3f, idle_cpu_hsw),
        ICPU(0x45, idle_cpu_hsw),
+       ICPU(0x46, idle_cpu_hsw),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
index 08a6c6d39e5666228cd842b1597fc5d9dcf48052..911205d3d5a0bf255fae65126740ab47eaa4a8ef 100644 (file)
@@ -44,7 +44,7 @@
 #include "qib.h"
 #include "qib_7220.h"
 
-#define SD7220_FW_NAME "intel/sd7220.fw"
+#define SD7220_FW_NAME "qlogic/sd7220.fw"
 MODULE_FIRMWARE(SD7220_FW_NAME);
 
 /*
index 1daa97913b7d20068845865a405387404fffe1d8..0bfd8cf252002d4095dc699cf8277931b1ec00a0 100644 (file)
@@ -359,7 +359,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                case 0x802: /* Intuos4 General Pen */
                case 0x804: /* Intuos4 Marker Pen */
                case 0x40802: /* Intuos4 Classic Pen */
-               case 0x18803: /* DTH2242 Grip Pen */
+               case 0x18802: /* DTH2242 Grip Pen */
                case 0x022:
                        wacom->tool[idx] = BTN_TOOL_PEN;
                        break;
@@ -1912,7 +1912,7 @@ static const struct wacom_features wacom_features_0xBB =
        { "Wacom Intuos4 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 2047,
          63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xBC =
-       { "Wacom Intuos4 WL",     WACOM_PKGLEN_INTUOS,    40840, 25400, 2047,
+       { "Wacom Intuos4 WL",     WACOM_PKGLEN_INTUOS,    40640, 25400, 2047,
          63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0x26 =
        { "Wacom Intuos5 touch S", WACOM_PKGLEN_INTUOS,  31496, 19685, 2047,
@@ -2144,7 +2144,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x44) },
        { USB_DEVICE_WACOM(0x45) },
        { USB_DEVICE_WACOM(0x59) },
-       { USB_DEVICE_WACOM(0x5D) },
+       { USB_DEVICE_DETAILED(0x5D, USB_CLASS_HID, 0, 0) },
        { USB_DEVICE_WACOM(0xB0) },
        { USB_DEVICE_WACOM(0xB1) },
        { USB_DEVICE_WACOM(0xB2) },
@@ -2209,7 +2209,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
        { USB_DEVICE_WACOM(0xF8) },
-       { USB_DEVICE_WACOM(0xF6) },
+       { USB_DEVICE_DETAILED(0xF6, USB_CLASS_HID, 0, 0) },
        { USB_DEVICE_WACOM(0xFA) },
        { USB_DEVICE_LENOVO(0x6004) },
        { }
index b287ca33833df792350baad6f82fefbe1494e038..830183737b0ffd2001e85b1e444dc3c66723f33a 100644 (file)
@@ -173,7 +173,7 @@ static inline u16 get_device_id(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
 
-       return calc_devid(pdev->bus->number, pdev->devfn);
+       return PCI_DEVID(pdev->bus->number, pdev->devfn);
 }
 
 static struct iommu_dev_data *get_dev_data(struct device *dev)
@@ -649,26 +649,26 @@ retry:
        case EVENT_TYPE_ILL_DEV:
                printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x "
                       "address=0x%016llx flags=0x%04x]\n",
-                      PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+                      PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
                       address, flags);
                dump_dte_entry(devid);
                break;
        case EVENT_TYPE_IO_FAULT:
                printk("IO_PAGE_FAULT device=%02x:%02x.%x "
                       "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
-                      PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+                      PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
                       domid, address, flags);
                break;
        case EVENT_TYPE_DEV_TAB_ERR:
                printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
                       "address=0x%016llx flags=0x%04x]\n",
-                      PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+                      PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
                       address, flags);
                break;
        case EVENT_TYPE_PAGE_TAB_ERR:
                printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
                       "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
-                      PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+                      PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
                       domid, address, flags);
                break;
        case EVENT_TYPE_ILL_CMD:
@@ -682,13 +682,13 @@ retry:
        case EVENT_TYPE_IOTLB_INV_TO:
                printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x "
                       "address=0x%016llx]\n",
-                      PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+                      PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
                       address);
                break;
        case EVENT_TYPE_INV_DEV_REQ:
                printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x "
                       "address=0x%016llx flags=0x%04x]\n",
-                      PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+                      PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
                       address, flags);
                break;
        default:
index e3c2d74b7684596790fd0293461dc74922a850ba..2f46881256a2d2cc0b6e5672e66a111326d021b0 100644 (file)
@@ -406,7 +406,7 @@ static int __init find_last_devid_on_pci(int bus, int dev, int fn, int cap_ptr)
        u32 cap;
 
        cap = read_pci_config(bus, dev, fn, cap_ptr+MMIO_RANGE_OFFSET);
-       update_last_devid(calc_devid(MMIO_GET_BUS(cap), MMIO_GET_LD(cap)));
+       update_last_devid(PCI_DEVID(MMIO_GET_BUS(cap), MMIO_GET_LD(cap)));
 
        return 0;
 }
@@ -423,7 +423,7 @@ static int __init find_last_devid_from_ivhd(struct ivhd_header *h)
        p += sizeof(*h);
        end += h->length;
 
-       find_last_devid_on_pci(PCI_BUS(h->devid),
+       find_last_devid_on_pci(PCI_BUS_NUM(h->devid),
                        PCI_SLOT(h->devid),
                        PCI_FUNC(h->devid),
                        h->cap_ptr);
@@ -784,10 +784,10 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
                        DUMP_printk("  DEV_ALL\t\t\t first devid: %02x:%02x.%x"
                                    " last device %02x:%02x.%x flags: %02x\n",
-                                   PCI_BUS(iommu->first_device),
+                                   PCI_BUS_NUM(iommu->first_device),
                                    PCI_SLOT(iommu->first_device),
                                    PCI_FUNC(iommu->first_device),
-                                   PCI_BUS(iommu->last_device),
+                                   PCI_BUS_NUM(iommu->last_device),
                                    PCI_SLOT(iommu->last_device),
                                    PCI_FUNC(iommu->last_device),
                                    e->flags);
@@ -801,7 +801,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
                        DUMP_printk("  DEV_SELECT\t\t\t devid: %02x:%02x.%x "
                                    "flags: %02x\n",
-                                   PCI_BUS(e->devid),
+                                   PCI_BUS_NUM(e->devid),
                                    PCI_SLOT(e->devid),
                                    PCI_FUNC(e->devid),
                                    e->flags);
@@ -813,7 +813,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
                        DUMP_printk("  DEV_SELECT_RANGE_START\t "
                                    "devid: %02x:%02x.%x flags: %02x\n",
-                                   PCI_BUS(e->devid),
+                                   PCI_BUS_NUM(e->devid),
                                    PCI_SLOT(e->devid),
                                    PCI_FUNC(e->devid),
                                    e->flags);
@@ -827,11 +827,11 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
                        DUMP_printk("  DEV_ALIAS\t\t\t devid: %02x:%02x.%x "
                                    "flags: %02x devid_to: %02x:%02x.%x\n",
-                                   PCI_BUS(e->devid),
+                                   PCI_BUS_NUM(e->devid),
                                    PCI_SLOT(e->devid),
                                    PCI_FUNC(e->devid),
                                    e->flags,
-                                   PCI_BUS(e->ext >> 8),
+                                   PCI_BUS_NUM(e->ext >> 8),
                                    PCI_SLOT(e->ext >> 8),
                                    PCI_FUNC(e->ext >> 8));
 
@@ -846,11 +846,11 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
                        DUMP_printk("  DEV_ALIAS_RANGE\t\t "
                                    "devid: %02x:%02x.%x flags: %02x "
                                    "devid_to: %02x:%02x.%x\n",
-                                   PCI_BUS(e->devid),
+                                   PCI_BUS_NUM(e->devid),
                                    PCI_SLOT(e->devid),
                                    PCI_FUNC(e->devid),
                                    e->flags,
-                                   PCI_BUS(e->ext >> 8),
+                                   PCI_BUS_NUM(e->ext >> 8),
                                    PCI_SLOT(e->ext >> 8),
                                    PCI_FUNC(e->ext >> 8));
 
@@ -864,7 +864,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
                        DUMP_printk("  DEV_EXT_SELECT\t\t devid: %02x:%02x.%x "
                                    "flags: %02x ext: %08x\n",
-                                   PCI_BUS(e->devid),
+                                   PCI_BUS_NUM(e->devid),
                                    PCI_SLOT(e->devid),
                                    PCI_FUNC(e->devid),
                                    e->flags, e->ext);
@@ -877,7 +877,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
                        DUMP_printk("  DEV_EXT_SELECT_RANGE\t devid: "
                                    "%02x:%02x.%x flags: %02x ext: %08x\n",
-                                   PCI_BUS(e->devid),
+                                   PCI_BUS_NUM(e->devid),
                                    PCI_SLOT(e->devid),
                                    PCI_FUNC(e->devid),
                                    e->flags, e->ext);
@@ -890,7 +890,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
                case IVHD_DEV_RANGE_END:
 
                        DUMP_printk("  DEV_RANGE_END\t\t devid: %02x:%02x.%x\n",
-                                   PCI_BUS(e->devid),
+                                   PCI_BUS_NUM(e->devid),
                                    PCI_SLOT(e->devid),
                                    PCI_FUNC(e->devid));
 
@@ -924,7 +924,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
                        DUMP_printk("  DEV_SPECIAL(%s[%d])\t\tdevid: %02x:%02x.%x\n",
                                    var, (int)handle,
-                                   PCI_BUS(devid),
+                                   PCI_BUS_NUM(devid),
                                    PCI_SLOT(devid),
                                    PCI_FUNC(devid));
 
@@ -1086,7 +1086,7 @@ static int __init init_iommu_all(struct acpi_table_header *table)
 
                        DUMP_printk("device: %02x:%02x.%01x cap: %04x "
                                    "seg: %d flags: %01x info %04x\n",
-                                   PCI_BUS(h->devid), PCI_SLOT(h->devid),
+                                   PCI_BUS_NUM(h->devid), PCI_SLOT(h->devid),
                                    PCI_FUNC(h->devid), h->cap_ptr,
                                    h->pci_seg, h->flags, h->info);
                        DUMP_printk("       mmio-addr: %016llx\n",
@@ -1116,7 +1116,7 @@ static int iommu_init_pci(struct amd_iommu *iommu)
        int cap_ptr = iommu->cap_ptr;
        u32 range, misc, low, high;
 
-       iommu->dev = pci_get_bus_and_slot(PCI_BUS(iommu->devid),
+       iommu->dev = pci_get_bus_and_slot(PCI_BUS_NUM(iommu->devid),
                                          iommu->devid & 0xff);
        if (!iommu->dev)
                return -ENODEV;
@@ -1128,9 +1128,9 @@ static int iommu_init_pci(struct amd_iommu *iommu)
        pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET,
                              &misc);
 
-       iommu->first_device = calc_devid(MMIO_GET_BUS(range),
+       iommu->first_device = PCI_DEVID(MMIO_GET_BUS(range),
                                         MMIO_GET_FD(range));
-       iommu->last_device = calc_devid(MMIO_GET_BUS(range),
+       iommu->last_device = PCI_DEVID(MMIO_GET_BUS(range),
                                        MMIO_GET_LD(range));
 
        if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB)))
@@ -1388,8 +1388,8 @@ static int __init init_unity_map_range(struct ivmd_header *m)
 
        DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x"
                    " range_start: %016llx range_end: %016llx flags: %x\n", s,
-                   PCI_BUS(e->devid_start), PCI_SLOT(e->devid_start),
-                   PCI_FUNC(e->devid_start), PCI_BUS(e->devid_end),
+                   PCI_BUS_NUM(e->devid_start), PCI_SLOT(e->devid_start),
+                   PCI_FUNC(e->devid_start), PCI_BUS_NUM(e->devid_end),
                    PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end),
                    e->address_start, e->address_end, m->flags);
 
index e38ab438bb342e241c1b5e545a0b01a4e4ea5017..ec36cf63e0ca0a10c14c46fc610dfe3644795c4a 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
+#include <linux/pci.h>
 
 /*
  * Maximum number of IOMMUs supported
 
 #define MAX_DOMAIN_ID 65536
 
-/* FIXME: move this macro to <linux/pci.h> */
-#define PCI_BUS(x) (((x) >> 8) & 0xff)
-
 /* Protection domain flags */
 #define PD_DMA_OPS_MASK                (1UL << 0) /* domain used for dma_ops */
 #define PD_DEFAULT_MASK                (1UL << 1) /* domain is a default dma_ops
@@ -703,13 +701,6 @@ extern int amd_iommu_max_glx_val;
  */
 extern void iommu_flush_all_caches(struct amd_iommu *iommu);
 
-/* takes bus and device/function and returns the device id
- * FIXME: should that be in generic PCI code? */
-static inline u16 calc_devid(u8 bus, u8 devfn)
-{
-       return (((u16)bus) << 8) | devfn;
-}
-
 static inline int get_ioapic_devid(int id)
 {
        struct devid_map *entry;
index a32e0d5aa45f43eb71c91ab9020696436212ae95..fc6aebf1e4b2630493b8e3ff89a2f76650019ef9 100644 (file)
@@ -236,7 +236,8 @@ static int gic_retrigger(struct irq_data *d)
        if (gic_arch_extn.irq_retrigger)
                return gic_arch_extn.irq_retrigger(d);
 
-       return -ENXIO;
+       /* the genirq layer expects 0 if we can't retrigger in hardware */
+       return 0;
 }
 
 #ifdef CONFIG_SMP
index 66120bd46d15639613cdeaf09b4474db48550845..10744091e6cabb5f6bb55e59709eb4ba0350a98b 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "dm.h"
 #include "dm-bio-prison.h"
+#include "dm-bio-record.h"
 #include "dm-cache-metadata.h"
 
 #include <linux/dm-io.h>
@@ -201,10 +202,15 @@ struct per_bio_data {
        unsigned req_nr:2;
        struct dm_deferred_entry *all_io_entry;
 
-       /* writethrough fields */
+       /*
+        * writethrough fields.  These MUST remain at the end of this
+        * structure and the 'cache' member must be the first as it
+        * is used to determine the offsetof the writethrough fields.
+        */
        struct cache *cache;
        dm_cblock_t cblock;
        bio_end_io_t *saved_bi_end_io;
+       struct dm_bio_details bio_details;
 };
 
 struct dm_cache_migration {
@@ -513,16 +519,28 @@ static void save_stats(struct cache *cache)
 /*----------------------------------------------------------------
  * Per bio data
  *--------------------------------------------------------------*/
-static struct per_bio_data *get_per_bio_data(struct bio *bio)
+
+/*
+ * If using writeback, leave out struct per_bio_data's writethrough fields.
+ */
+#define PB_DATA_SIZE_WB (offsetof(struct per_bio_data, cache))
+#define PB_DATA_SIZE_WT (sizeof(struct per_bio_data))
+
+static size_t get_per_bio_data_size(struct cache *cache)
+{
+       return cache->features.write_through ? PB_DATA_SIZE_WT : PB_DATA_SIZE_WB;
+}
+
+static struct per_bio_data *get_per_bio_data(struct bio *bio, size_t data_size)
 {
-       struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
+       struct per_bio_data *pb = dm_per_bio_data(bio, data_size);
        BUG_ON(!pb);
        return pb;
 }
 
-static struct per_bio_data *init_per_bio_data(struct bio *bio)
+static struct per_bio_data *init_per_bio_data(struct bio *bio, size_t data_size)
 {
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       struct per_bio_data *pb = get_per_bio_data(bio, data_size);
 
        pb->tick = false;
        pb->req_nr = dm_bio_get_target_bio_nr(bio);
@@ -556,7 +574,8 @@ static void remap_to_cache(struct cache *cache, struct bio *bio,
 static void check_if_tick_bio_needed(struct cache *cache, struct bio *bio)
 {
        unsigned long flags;
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
        spin_lock_irqsave(&cache->lock, flags);
        if (cache->need_tick_bio &&
@@ -635,7 +654,7 @@ static void defer_writethrough_bio(struct cache *cache, struct bio *bio)
 
 static void writethrough_endio(struct bio *bio, int err)
 {
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       struct per_bio_data *pb = get_per_bio_data(bio, PB_DATA_SIZE_WT);
        bio->bi_end_io = pb->saved_bi_end_io;
 
        if (err) {
@@ -643,6 +662,7 @@ static void writethrough_endio(struct bio *bio, int err)
                return;
        }
 
+       dm_bio_restore(&pb->bio_details, bio);
        remap_to_cache(pb->cache, bio, pb->cblock);
 
        /*
@@ -662,11 +682,12 @@ static void writethrough_endio(struct bio *bio, int err)
 static void remap_to_origin_then_cache(struct cache *cache, struct bio *bio,
                                       dm_oblock_t oblock, dm_cblock_t cblock)
 {
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       struct per_bio_data *pb = get_per_bio_data(bio, PB_DATA_SIZE_WT);
 
        pb->cache = cache;
        pb->cblock = cblock;
        pb->saved_bi_end_io = bio->bi_end_io;
+       dm_bio_record(&pb->bio_details, bio);
        bio->bi_end_io = writethrough_endio;
 
        remap_to_origin_clear_discard(pb->cache, bio, oblock);
@@ -1035,7 +1056,8 @@ static void defer_bio(struct cache *cache, struct bio *bio)
 
 static void process_flush_bio(struct cache *cache, struct bio *bio)
 {
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
        BUG_ON(bio->bi_size);
        if (!pb->req_nr)
@@ -1107,7 +1129,8 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
        dm_oblock_t block = get_bio_block(cache, bio);
        struct dm_bio_prison_cell *cell_prealloc, *old_ocell, *new_ocell;
        struct policy_result lookup_result;
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
        bool discarded_block = is_discarded_oblock(cache, block);
        bool can_migrate = discarded_block || spare_migration_bandwidth(cache);
 
@@ -1881,7 +1904,6 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 
        cache->ti = ca->ti;
        ti->private = cache;
-       ti->per_bio_data_size = sizeof(struct per_bio_data);
        ti->num_flush_bios = 2;
        ti->flush_supported = true;
 
@@ -1890,6 +1912,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        ti->discard_zeroes_data_unsupported = true;
 
        memcpy(&cache->features, &ca->features, sizeof(cache->features));
+       ti->per_bio_data_size = get_per_bio_data_size(cache);
 
        cache->callbacks.congested_fn = cache_is_congested;
        dm_table_add_target_callbacks(ti->table, &cache->callbacks);
@@ -2092,6 +2115,7 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
 
        int r;
        dm_oblock_t block = get_bio_block(cache, bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
        bool can_migrate = false;
        bool discarded_block;
        struct dm_bio_prison_cell *cell;
@@ -2108,7 +2132,7 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
                return DM_MAPIO_REMAPPED;
        }
 
-       pb = init_per_bio_data(bio);
+       pb = init_per_bio_data(bio, pb_data_size);
 
        if (bio->bi_rw & (REQ_FLUSH | REQ_FUA | REQ_DISCARD)) {
                defer_bio(cache, bio);
@@ -2193,7 +2217,8 @@ static int cache_end_io(struct dm_target *ti, struct bio *bio, int error)
 {
        struct cache *cache = ti->private;
        unsigned long flags;
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
        if (pb->tick) {
                policy_tick(cache->policy);
index 7e469260fe5eba5272ab56f74d9bd1c38fc2cfbf..9a0bdad9ad8fad49eaf8ee0d0ad916df247f0f3c 100644 (file)
@@ -611,6 +611,7 @@ static void dec_pending(struct dm_io *io, int error)
                        queue_io(md, bio);
                } else {
                        /* done with normal IO or empty flush */
+                       trace_block_bio_complete(md->queue, bio, io_error);
                        bio_endio(bio, io_error);
                }
        }
index 24909eb13fec1b0bf22e40caa4ff7a76967f80e4..f4e87bfc7567923944d2fce13da4c7d636479566 100644 (file)
@@ -184,6 +184,8 @@ static void return_io(struct bio *return_bi)
                return_bi = bi->bi_next;
                bi->bi_next = NULL;
                bi->bi_size = 0;
+               trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
+                                        bi, 0);
                bio_endio(bi, 0);
                bi = return_bi;
        }
@@ -3914,6 +3916,8 @@ static void raid5_align_endio(struct bio *bi, int error)
        rdev_dec_pending(rdev, conf->mddev);
 
        if (!error && uptodate) {
+               trace_block_bio_complete(bdev_get_queue(raid_bi->bi_bdev),
+                                        raid_bi, 0);
                bio_endio(raid_bi, 0);
                if (atomic_dec_and_test(&conf->active_aligned_reads))
                        wake_up(&conf->wait_for_stripe);
@@ -4382,6 +4386,8 @@ static void make_request(struct mddev *mddev, struct bio * bi)
                if ( rw == WRITE )
                        md_write_end(mddev);
 
+               trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
+                                        bi, 0);
                bio_endio(bi, 0);
        }
 }
@@ -4758,8 +4764,11 @@ static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
                handled++;
        }
        remaining = raid5_dec_bi_active_stripes(raid_bio);
-       if (remaining == 0)
+       if (remaining == 0) {
+               trace_block_bio_complete(bdev_get_queue(raid_bio->bi_bdev),
+                                        raid_bio, 0);
                bio_endio(raid_bio, 0);
+       }
        if (atomic_dec_and_test(&conf->active_aligned_reads))
                wake_up(&conf->wait_for_stripe);
        return handled;
index f19cd7367040dea00a01b0e01767afea8a83096d..4faaf8053f2698a1b399474f3156ea0eb5afb811 100644 (file)
@@ -610,7 +610,7 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
               __func__, 'A' + layer, segment * isdbt_rate[m][f][i]/1000,
                rate, rate);
 
-       state->estimated_rate[i] = rate;
+       state->estimated_rate[layer] = rate;
 }
 
 
index d4de021dc844e88776f67e7b08018cf9ab11b394..31ce7698acb9393ba275c95e7f14b0d6d146eaa7 100644 (file)
@@ -461,7 +461,7 @@ int cx25821_video_register(struct cx25821_dev *dev)
 
        spin_lock_init(&dev->slock);
 
-       for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) {
+       for (i = 0; i < VID_CHANNEL_NUM; ++i) {
                cx25821_init_controls(dev, i);
 
                cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper,
index 05d7b6333461c68f5aaeb919ad1c9dc584cf5952..a0639e77997357d96422568422e2ef28c12a2772 100644 (file)
@@ -204,7 +204,7 @@ config VIDEO_SAMSUNG_EXYNOS_GSC
 
 config VIDEO_SH_VEU
        tristate "SuperH VEU mem2mem video processing driver"
-       depends on VIDEO_DEV && VIDEO_V4L2
+       depends on VIDEO_DEV && VIDEO_V4L2 && GENERIC_HARDIRQS
        select VIDEOBUF2_DMA_CONTIG
        select V4L2_MEM2MEM_DEV
        help
index c61f590029ad7c05ef75911c69e5fdbe50f24e8e..348dafc0318aae60de8d18660334cb5244e2dd98 100644 (file)
@@ -347,9 +347,20 @@ static void usb_ma901radio_release(struct v4l2_device *v4l2_dev)
 static int usb_ma901radio_probe(struct usb_interface *intf,
                                const struct usb_device_id *id)
 {
+       struct usb_device *dev = interface_to_usbdev(intf);
        struct ma901radio_device *radio;
        int retval = 0;
 
+       /* Masterkit MA901 usb radio has the same USB ID as many others
+        * Atmel V-USB devices. Let's make additional checks to be sure
+        * that this is our device.
+        */
+
+       if (dev->product && dev->manufacturer &&
+               (strncmp(dev->product, "MA901", 5) != 0
+               || strncmp(dev->manufacturer, "www.masterkit.ru", 16) != 0))
+               return -ENODEV;
+
        radio = kzalloc(sizeof(struct ma901radio_device), GFP_KERNEL);
        if (!radio) {
                dev_err(&intf->dev, "kzalloc for ma901radio_device failed\n");
index 39c2ecadb273d374b41be572bee6431e7b81e784..ea98f7e9ccd19d6ef8ea862616bcc4c0f3055b8d 100644 (file)
@@ -4,7 +4,7 @@
 
 config VMWARE_VMCI
        tristate "VMware VMCI Driver"
-       depends on X86 && PCI
+       depends on X86 && PCI && NET
        help
          This is VMware's Virtual Machine Communication Interface.  It enables
          high-speed communication between host and guest in a virtual
index 92ab30ab00dcab1d0bc6405a94bbe3aeffcfb128..dc571ebc1aa0be8680f4a20397653e9d4a7f84cf 100644 (file)
@@ -1123,33 +1123,6 @@ static unsigned long mtdchar_get_unmapped_area(struct file *file,
 }
 #endif
 
-static inline unsigned long get_vm_size(struct vm_area_struct *vma)
-{
-       return vma->vm_end - vma->vm_start;
-}
-
-static inline resource_size_t get_vm_offset(struct vm_area_struct *vma)
-{
-       return (resource_size_t) vma->vm_pgoff << PAGE_SHIFT;
-}
-
-/*
- * Set a new vm offset.
- *
- * Verify that the incoming offset really works as a page offset,
- * and that the offset and size fit in a resource_size_t.
- */
-static inline int set_vm_offset(struct vm_area_struct *vma, resource_size_t off)
-{
-       pgoff_t pgoff = off >> PAGE_SHIFT;
-       if (off != (resource_size_t) pgoff << PAGE_SHIFT)
-               return -EINVAL;
-       if (off + get_vm_size(vma) - 1 < off)
-               return -EINVAL;
-       vma->vm_pgoff = pgoff;
-       return 0;
-}
-
 /*
  * set up a mapping for shared memory segments
  */
@@ -1159,45 +1132,17 @@ static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
        struct mtd_file_info *mfi = file->private_data;
        struct mtd_info *mtd = mfi->mtd;
        struct map_info *map = mtd->priv;
-       resource_size_t start, off;
-       unsigned long len, vma_len;
 
         /* This is broken because it assumes the MTD device is map-based
           and that mtd->priv is a valid struct map_info.  It should be
           replaced with something that uses the mtd_get_unmapped_area()
           operation properly. */
        if (0 /*mtd->type == MTD_RAM || mtd->type == MTD_ROM*/) {
-               off = get_vm_offset(vma);
-               start = map->phys;
-               len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
-               start &= PAGE_MASK;
-               vma_len = get_vm_size(vma);
-
-               /* Overflow in off+len? */
-               if (vma_len + off < off)
-                       return -EINVAL;
-               /* Does it fit in the mapping? */
-               if (vma_len + off > len)
-                       return -EINVAL;
-
-               off += start;
-               /* Did that overflow? */
-               if (off < start)
-                       return -EINVAL;
-               if (set_vm_offset(vma, off) < 0)
-                       return -EINVAL;
-               vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
-
 #ifdef pgprot_noncached
-               if (file->f_flags & O_DSYNC || off >= __pa(high_memory))
+               if (file->f_flags & O_DSYNC || map->phys >= __pa(high_memory))
                        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 #endif
-               if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-                                      vma->vm_end - vma->vm_start,
-                                      vma->vm_page_prot))
-                       return -EAGAIN;
-
-               return 0;
+               return vm_iomap_memory(vma, map->phys, map->size);
        }
        return -ENOSYS;
 #else
index 6bbd90e1123c59c58329505537568a2ec2d5b9b0..dbbea0eec134f1b2f0225161a33111264450f48e 100644 (file)
@@ -846,8 +846,10 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
                if (bond->dev->flags & IFF_ALLMULTI)
                        dev_set_allmulti(old_active->dev, -1);
 
+               netif_addr_lock_bh(bond->dev);
                netdev_for_each_mc_addr(ha, bond->dev)
                        dev_mc_del(old_active->dev, ha->addr);
+               netif_addr_unlock_bh(bond->dev);
        }
 
        if (new_active) {
@@ -858,8 +860,10 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
                if (bond->dev->flags & IFF_ALLMULTI)
                        dev_set_allmulti(new_active->dev, 1);
 
+               netif_addr_lock_bh(bond->dev);
                netdev_for_each_mc_addr(ha, bond->dev)
                        dev_mc_add(new_active->dev, ha->addr);
+               netif_addr_unlock_bh(bond->dev);
        }
 }
 
@@ -1901,11 +1905,29 @@ err_dest_symlinks:
        bond_destroy_slave_symlinks(bond_dev, slave_dev);
 
 err_detach:
+       if (!USES_PRIMARY(bond->params.mode)) {
+               netif_addr_lock_bh(bond_dev);
+               bond_mc_list_flush(bond_dev, slave_dev);
+               netif_addr_unlock_bh(bond_dev);
+       }
+       bond_del_vlans_from_slave(bond, slave_dev);
        write_lock_bh(&bond->lock);
        bond_detach_slave(bond, new_slave);
+       if (bond->primary_slave == new_slave)
+               bond->primary_slave = NULL;
        write_unlock_bh(&bond->lock);
+       if (bond->curr_active_slave == new_slave) {
+               read_lock(&bond->lock);
+               write_lock_bh(&bond->curr_slave_lock);
+               bond_change_active_slave(bond, NULL);
+               bond_select_active_slave(bond);
+               write_unlock_bh(&bond->curr_slave_lock);
+               read_unlock(&bond->lock);
+       }
+       slave_disable_netpoll(new_slave);
 
 err_close:
+       slave_dev->priv_flags &= ~IFF_BONDING;
        dev_close(slave_dev);
 
 err_unset_master:
@@ -1976,12 +1998,11 @@ static int __bond_release_one(struct net_device *bond_dev,
                return -EINVAL;
        }
 
+       write_unlock_bh(&bond->lock);
        /* unregister rx_handler early so bond_handle_frame wouldn't be called
         * for this slave anymore.
         */
        netdev_rx_handler_unregister(slave_dev);
-       write_unlock_bh(&bond->lock);
-       synchronize_net();
        write_lock_bh(&bond->lock);
 
        if (!all && !bond->params.fail_over_mac) {
@@ -3169,11 +3190,20 @@ static int bond_slave_netdev_event(unsigned long event,
                                   struct net_device *slave_dev)
 {
        struct slave *slave = bond_slave_get_rtnl(slave_dev);
-       struct bonding *bond = slave->bond;
-       struct net_device *bond_dev = slave->bond->dev;
+       struct bonding *bond;
+       struct net_device *bond_dev;
        u32 old_speed;
        u8 old_duplex;
 
+       /* A netdev event can be generated while enslaving a device
+        * before netdev_rx_handler_register is called in which case
+        * slave will be NULL
+        */
+       if (!slave)
+               return NOTIFY_DONE;
+       bond_dev = slave->bond->dev;
+       bond = slave->bond;
+
        switch (event) {
        case NETDEV_UNREGISTER:
                if (bond->setup_by_slave)
@@ -3287,20 +3317,22 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
  */
 static int bond_xmit_hash_policy_l23(struct sk_buff *skb, int count)
 {
-       struct ethhdr *data = (struct ethhdr *)skb->data;
-       struct iphdr *iph;
-       struct ipv6hdr *ipv6h;
+       const struct ethhdr *data;
+       const struct iphdr *iph;
+       const struct ipv6hdr *ipv6h;
        u32 v6hash;
-       __be32 *s, *d;
+       const __be32 *s, *d;
 
        if (skb->protocol == htons(ETH_P_IP) &&
-           skb_network_header_len(skb) >= sizeof(*iph)) {
+           pskb_network_may_pull(skb, sizeof(*iph))) {
                iph = ip_hdr(skb);
+               data = (struct ethhdr *)skb->data;
                return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
                        (data->h_dest[5] ^ data->h_source[5])) % count;
        } else if (skb->protocol == htons(ETH_P_IPV6) &&
-                  skb_network_header_len(skb) >= sizeof(*ipv6h)) {
+                  pskb_network_may_pull(skb, sizeof(*ipv6h))) {
                ipv6h = ipv6_hdr(skb);
+               data = (struct ethhdr *)skb->data;
                s = &ipv6h->saddr.s6_addr32[0];
                d = &ipv6h->daddr.s6_addr32[0];
                v6hash = (s[1] ^ d[1]) ^ (s[2] ^ d[2]) ^ (s[3] ^ d[3]);
@@ -3319,33 +3351,36 @@ static int bond_xmit_hash_policy_l23(struct sk_buff *skb, int count)
 static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
 {
        u32 layer4_xor = 0;
-       struct iphdr *iph;
-       struct ipv6hdr *ipv6h;
-       __be32 *s, *d;
-       __be16 *layer4hdr;
+       const struct iphdr *iph;
+       const struct ipv6hdr *ipv6h;
+       const __be32 *s, *d;
+       const __be16 *l4 = NULL;
+       __be16 _l4[2];
+       int noff = skb_network_offset(skb);
+       int poff;
 
        if (skb->protocol == htons(ETH_P_IP) &&
-           skb_network_header_len(skb) >= sizeof(*iph)) {
+           pskb_may_pull(skb, noff + sizeof(*iph))) {
                iph = ip_hdr(skb);
-               if (!ip_is_fragment(iph) &&
-                   (iph->protocol == IPPROTO_TCP ||
-                    iph->protocol == IPPROTO_UDP) &&
-                   (skb_headlen(skb) - skb_network_offset(skb) >=
-                    iph->ihl * sizeof(u32) + sizeof(*layer4hdr) * 2)) {
-                       layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
-                       layer4_xor = ntohs(*layer4hdr ^ *(layer4hdr + 1));
+               poff = proto_ports_offset(iph->protocol);
+
+               if (!ip_is_fragment(iph) && poff >= 0) {
+                       l4 = skb_header_pointer(skb, noff + (iph->ihl << 2) + poff,
+                                               sizeof(_l4), &_l4);
+                       if (l4)
+                               layer4_xor = ntohs(l4[0] ^ l4[1]);
                }
                return (layer4_xor ^
                        ((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count;
        } else if (skb->protocol == htons(ETH_P_IPV6) &&
-                  skb_network_header_len(skb) >= sizeof(*ipv6h)) {
+                  pskb_may_pull(skb, noff + sizeof(*ipv6h))) {
                ipv6h = ipv6_hdr(skb);
-               if ((ipv6h->nexthdr == IPPROTO_TCP ||
-                    ipv6h->nexthdr == IPPROTO_UDP) &&
-                   (skb_headlen(skb) - skb_network_offset(skb) >=
-                    sizeof(*ipv6h) + sizeof(*layer4hdr) * 2)) {
-                       layer4hdr = (__be16 *)(ipv6h + 1);
-                       layer4_xor = ntohs(*layer4hdr ^ *(layer4hdr + 1));
+               poff = proto_ports_offset(ipv6h->nexthdr);
+               if (poff >= 0) {
+                       l4 = skb_header_pointer(skb, noff + sizeof(*ipv6h) + poff,
+                                               sizeof(_l4), &_l4);
+                       if (l4)
+                               layer4_xor = ntohs(l4[0] ^ l4[1]);
                }
                s = &ipv6h->saddr.s6_addr32[0];
                d = &ipv6h->daddr.s6_addr32[0];
@@ -4847,9 +4882,18 @@ static int __net_init bond_net_init(struct net *net)
 static void __net_exit bond_net_exit(struct net *net)
 {
        struct bond_net *bn = net_generic(net, bond_net_id);
+       struct bonding *bond, *tmp_bond;
+       LIST_HEAD(list);
 
        bond_destroy_sysfs(bn);
        bond_destroy_proc_dir(bn);
+
+       /* Kill off any bonds created after unregistering bond rtnl ops */
+       rtnl_lock();
+       list_for_each_entry_safe(bond, tmp_bond, &bn->dev_list, bond_list)
+               unregister_netdevice_queue(bond->dev, &list);
+       unregister_netdevice_many(&list);
+       rtnl_unlock();
 }
 
 static struct pernet_operations bond_net_ops = {
index db103e03ba05b4b32b2efbb168a820fe5f71f999..ea7a388f484306710a33375f3a553fd1ecc5b621 100644 (file)
@@ -527,7 +527,7 @@ static ssize_t bonding_store_arp_interval(struct device *d,
                goto out;
        }
        if (new_value < 0) {
-               pr_err("%s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
+               pr_err("%s: Invalid arp_interval value %d not in range 0-%d; rejected.\n",
                       bond->dev->name, new_value, INT_MAX);
                ret = -EINVAL;
                goto out;
@@ -542,14 +542,15 @@ static ssize_t bonding_store_arp_interval(struct device *d,
        pr_info("%s: Setting ARP monitoring interval to %d.\n",
                bond->dev->name, new_value);
        bond->params.arp_interval = new_value;
-       if (bond->params.miimon) {
-               pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
-                       bond->dev->name, bond->dev->name);
-               bond->params.miimon = 0;
-       }
-       if (!bond->params.arp_targets[0]) {
-               pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
-                       bond->dev->name);
+       if (new_value) {
+               if (bond->params.miimon) {
+                       pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
+                               bond->dev->name, bond->dev->name);
+                       bond->params.miimon = 0;
+               }
+               if (!bond->params.arp_targets[0])
+                       pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
+                               bond->dev->name);
        }
        if (bond->dev->flags & IFF_UP) {
                /* If the interface is up, we may need to fire off
@@ -557,10 +558,13 @@ static ssize_t bonding_store_arp_interval(struct device *d,
                 * timer will get fired off when the open function
                 * is called.
                 */
-               cancel_delayed_work_sync(&bond->mii_work);
-               queue_delayed_work(bond->wq, &bond->arp_work, 0);
+               if (!new_value) {
+                       cancel_delayed_work_sync(&bond->arp_work);
+               } else {
+                       cancel_delayed_work_sync(&bond->mii_work);
+                       queue_delayed_work(bond->wq, &bond->arp_work, 0);
+               }
        }
-
 out:
        rtnl_unlock();
        return ret;
@@ -702,7 +706,7 @@ static ssize_t bonding_store_downdelay(struct device *d,
        }
        if (new_value < 0) {
                pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
-                      bond->dev->name, new_value, 1, INT_MAX);
+                      bond->dev->name, new_value, 0, INT_MAX);
                ret = -EINVAL;
                goto out;
        } else {
@@ -757,8 +761,8 @@ static ssize_t bonding_store_updelay(struct device *d,
                goto out;
        }
        if (new_value < 0) {
-               pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
-                      bond->dev->name, new_value, 1, INT_MAX);
+               pr_err("%s: Invalid up delay value %d not in range %d-%d; rejected.\n",
+                      bond->dev->name, new_value, 0, INT_MAX);
                ret = -EINVAL;
                goto out;
        } else {
@@ -968,37 +972,37 @@ static ssize_t bonding_store_miimon(struct device *d,
        }
        if (new_value < 0) {
                pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n",
-                      bond->dev->name, new_value, 1, INT_MAX);
+                      bond->dev->name, new_value, 0, INT_MAX);
                ret = -EINVAL;
                goto out;
-       } else {
-               pr_info("%s: Setting MII monitoring interval to %d.\n",
-                       bond->dev->name, new_value);
-               bond->params.miimon = new_value;
-               if (bond->params.updelay)
-                       pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
-                               bond->dev->name,
-                               bond->params.updelay * bond->params.miimon);
-               if (bond->params.downdelay)
-                       pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
-                               bond->dev->name,
-                               bond->params.downdelay * bond->params.miimon);
-               if (bond->params.arp_interval) {
-                       pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
-                               bond->dev->name);
-                       bond->params.arp_interval = 0;
-                       if (bond->params.arp_validate) {
-                               bond->params.arp_validate =
-                                       BOND_ARP_VALIDATE_NONE;
-                       }
-               }
-
-               if (bond->dev->flags & IFF_UP) {
-                       /* If the interface is up, we may need to fire off
-                        * the MII timer. If the interface is down, the
-                        * timer will get fired off when the open function
-                        * is called.
-                        */
+       }
+       pr_info("%s: Setting MII monitoring interval to %d.\n",
+               bond->dev->name, new_value);
+       bond->params.miimon = new_value;
+       if (bond->params.updelay)
+               pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
+                       bond->dev->name,
+                       bond->params.updelay * bond->params.miimon);
+       if (bond->params.downdelay)
+               pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
+                       bond->dev->name,
+                       bond->params.downdelay * bond->params.miimon);
+       if (new_value && bond->params.arp_interval) {
+               pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
+                       bond->dev->name);
+               bond->params.arp_interval = 0;
+               if (bond->params.arp_validate)
+                       bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
+       }
+       if (bond->dev->flags & IFF_UP) {
+               /* If the interface is up, we may need to fire off
+                * the MII timer. If the interface is down, the
+                * timer will get fired off when the open function
+                * is called.
+                */
+               if (!new_value) {
+                       cancel_delayed_work_sync(&bond->mii_work);
+               } else {
                        cancel_delayed_work_sync(&bond->arp_work);
                        queue_delayed_work(bond->wq, &bond->mii_work, 0);
                }
index f32b9fc6a983205151feabc8512e1fac5a7df88a..9aa0c64c33c81c9f296ed5f08b0d3666ee989816 100644 (file)
@@ -929,6 +929,7 @@ static int mcp251x_open(struct net_device *net)
        struct mcp251x_priv *priv = netdev_priv(net);
        struct spi_device *spi = priv->spi;
        struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+       unsigned long flags;
        int ret;
 
        ret = open_candev(net);
@@ -945,9 +946,14 @@ static int mcp251x_open(struct net_device *net)
        priv->tx_skb = NULL;
        priv->tx_len = 0;
 
+       flags = IRQF_ONESHOT;
+       if (pdata->irq_flags)
+               flags |= pdata->irq_flags;
+       else
+               flags |= IRQF_TRIGGER_FALLING;
+
        ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist,
-                 pdata->irq_flags ? pdata->irq_flags : IRQF_TRIGGER_FALLING,
-                 DEVICE_NAME, priv);
+                                  flags, DEVICE_NAME, priv);
        if (ret) {
                dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
                if (pdata->transceiver_enable)
index b39ca5b3ea7faee34c2264ea7fbc6ac14e3caf35..ff2ba86cd4a495cdd29020f02561a1f31926ff11 100644 (file)
@@ -46,6 +46,7 @@ config CAN_EMS_PCI
 config CAN_PEAK_PCMCIA
        tristate "PEAK PCAN-PC Card"
        depends on PCMCIA
+       depends on HAS_IOPORT
        ---help---
          This driver is for the PCAN-PC Card PCMCIA adapter (1 or 2 channels)
          from PEAK-System (http://www.peak-system.com). To compile this
index a042cdc260dc720f982c44ae1bf8da315c0faaf6..3c18d7d000edaabe3b8ec93f1d2841d3300df087 100644 (file)
@@ -348,7 +348,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
         */
        if ((priv->read_reg(priv, REG_CR) & REG_CR_BASICCAN_INITIAL_MASK) ==
            REG_CR_BASICCAN_INITIAL &&
-           (priv->read_reg(priv, REG_SR) == REG_SR_BASICCAN_INITIAL) &&
+           (priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_BASICCAN_INITIAL) &&
            (priv->read_reg(priv, REG_IR) == REG_IR_BASICCAN_INITIAL))
                flag = 1;
 
@@ -360,7 +360,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
         * See states on p. 23 of the Datasheet.
         */
        if (priv->read_reg(priv, REG_MOD) == REG_MOD_PELICAN_INITIAL &&
-           priv->read_reg(priv, REG_SR) == REG_SR_PELICAN_INITIAL &&
+           priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_PELICAN_INITIAL &&
            priv->read_reg(priv, REG_IR) == REG_IR_PELICAN_INITIAL)
                return flag;
 
index daf4013a8fc720ca0c73a9df96b647ad5c314839..e4df307eaa9081b9e39a81731714e0bd3969ea3b 100644 (file)
@@ -92,7 +92,7 @@ static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
         */
        spin_lock_irqsave(&priv->cmdreg_lock, flags);
        priv->write_reg(priv, REG_CMR, val);
-       priv->read_reg(priv, REG_SR);
+       priv->read_reg(priv, SJA1000_REG_SR);
        spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
 }
 
@@ -502,7 +502,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
 
        while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
                n++;
-               status = priv->read_reg(priv, REG_SR);
+               status = priv->read_reg(priv, SJA1000_REG_SR);
                /* check for absent controller due to hw unplug */
                if (status == 0xFF && sja1000_is_absent(priv))
                        return IRQ_NONE;
@@ -530,7 +530,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
                        /* receive interrupt */
                        while (status & SR_RBS) {
                                sja1000_rx(dev);
-                               status = priv->read_reg(priv, REG_SR);
+                               status = priv->read_reg(priv, SJA1000_REG_SR);
                                /* check for absent controller */
                                if (status == 0xFF && sja1000_is_absent(priv))
                                        return IRQ_NONE;
index afa99847a5101ffa6399726b57d4189f6c3057f5..aa48e053da27ce26ed394e8a4584ef9805828372 100644 (file)
@@ -56,7 +56,7 @@
 /* SJA1000 registers - manual section 6.4 (Pelican Mode) */
 #define REG_MOD                0x00
 #define REG_CMR                0x01
-#define REG_SR         0x02
+#define SJA1000_REG_SR         0x02
 #define REG_IR         0x03
 #define REG_IER                0x04
 #define REG_ALC                0x0B
index 6433b81256cdafd1cfe35fcc1a37d0a378411f59..8e0c4a0019397f61af74d44da1b60ca0c61032d2 100644 (file)
@@ -96,8 +96,8 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
        struct net_device *dev;
        struct sja1000_priv *priv;
        struct resource res;
-       const u32 *prop;
-       int err, irq, res_size, prop_size;
+       u32 prop;
+       int err, irq, res_size;
        void __iomem *base;
 
        err = of_address_to_resource(np, 0, &res);
@@ -138,27 +138,27 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
        priv->read_reg = sja1000_ofp_read_reg;
        priv->write_reg = sja1000_ofp_write_reg;
 
-       prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size);
-       if (prop && (prop_size ==  sizeof(u32)))
-               priv->can.clock.freq = *prop / 2;
+       err = of_property_read_u32(np, "nxp,external-clock-frequency", &prop);
+       if (!err)
+               priv->can.clock.freq = prop / 2;
        else
                priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */
 
-       prop = of_get_property(np, "nxp,tx-output-mode", &prop_size);
-       if (prop && (prop_size == sizeof(u32)))
-               priv->ocr |= *prop & OCR_MODE_MASK;
+       err = of_property_read_u32(np, "nxp,tx-output-mode", &prop);
+       if (!err)
+               priv->ocr |= prop & OCR_MODE_MASK;
        else
                priv->ocr |= OCR_MODE_NORMAL; /* default */
 
-       prop = of_get_property(np, "nxp,tx-output-config", &prop_size);
-       if (prop && (prop_size == sizeof(u32)))
-               priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK;
+       err = of_property_read_u32(np, "nxp,tx-output-config", &prop);
+       if (!err)
+               priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK;
        else
                priv->ocr |= OCR_TX0_PULLDOWN; /* default */
 
-       prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size);
-       if (prop && (prop_size == sizeof(u32)) && *prop) {
-               u32 divider = priv->can.clock.freq * 2 / *prop;
+       err = of_property_read_u32(np, "nxp,clock-out-frequency", &prop);
+       if (!err && prop) {
+               u32 divider = priv->can.clock.freq * 2 / prop;
 
                if (divider > 1)
                        priv->cdr |= divider / 2 - 1;
@@ -168,8 +168,7 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
                priv->cdr |= CDR_CLK_OFF; /* default */
        }
 
-       prop = of_get_property(np, "nxp,no-comparator-bypass", NULL);
-       if (!prop)
+       if (!of_property_read_bool(np, "nxp,no-comparator-bypass"))
                priv->cdr |= CDR_CBP; /* default */
 
        priv->irq_flags = IRQF_SHARED;
index cab306a9888ea5a5ac0036058eaa0290968dbbec..e1d26433d61921b3e0460421212006bcb5e0e9ee 100644 (file)
@@ -828,7 +828,7 @@ static int ax_probe(struct platform_device *pdev)
        struct ei_device *ei_local;
        struct ax_device *ax;
        struct resource *irq, *mem, *mem2;
-       resource_size_t mem_size, mem2_size = 0;
+       unsigned long mem_size, mem2_size = 0;
        int ret = 0;
 
        dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
index 829b5ad71d0da0a4634cd211bc3f5ffc67215db6..b5fd934585e9f9f14595f60a2ec2e069cd2bed35 100644 (file)
@@ -186,7 +186,7 @@ struct atl1e_tpd_desc {
 /* how about 0x2000 */
 #define MAX_TX_BUF_LEN      0x2000
 #define MAX_TX_BUF_SHIFT    13
-/*#define MAX_TX_BUF_LEN  0x3000 */
+#define MAX_TSO_SEG_SIZE    0x3c00
 
 /* rrs word 1 bit 0:31 */
 #define RRS_RX_CSUM_MASK       0xFFFF
@@ -438,7 +438,6 @@ struct atl1e_adapter {
        struct atl1e_hw        hw;
        struct atl1e_hw_stats  hw_stats;
 
-       bool have_msi;
        u32 wol;
        u16 link_speed;
        u16 link_duplex;
index 92f4734f860d3f18ece977946b4562c028df35e6..ac25f05ff68f03b9eda25867d0ace6707efc2d41 100644 (file)
@@ -1849,34 +1849,19 @@ static void atl1e_free_irq(struct atl1e_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
 
        free_irq(adapter->pdev->irq, netdev);
-
-       if (adapter->have_msi)
-               pci_disable_msi(adapter->pdev);
 }
 
 static int atl1e_request_irq(struct atl1e_adapter *adapter)
 {
        struct pci_dev    *pdev   = adapter->pdev;
        struct net_device *netdev = adapter->netdev;
-       int flags = 0;
        int err = 0;
 
-       adapter->have_msi = true;
-       err = pci_enable_msi(pdev);
-       if (err) {
-               netdev_dbg(netdev,
-                          "Unable to allocate MSI interrupt Error: %d\n", err);
-               adapter->have_msi = false;
-       }
-
-       if (!adapter->have_msi)
-               flags |= IRQF_SHARED;
-       err = request_irq(pdev->irq, atl1e_intr, flags, netdev->name, netdev);
+       err = request_irq(pdev->irq, atl1e_intr, IRQF_SHARED, netdev->name,
+                         netdev);
        if (err) {
                netdev_dbg(adapter->netdev,
                           "Unable to allocate interrupt Error: %d\n", err);
-               if (adapter->have_msi)
-                       pci_disable_msi(pdev);
                return err;
        }
        netdev_dbg(netdev, "atl1e_request_irq OK\n");
@@ -2344,6 +2329,7 @@ static int atl1e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        INIT_WORK(&adapter->reset_task, atl1e_reset_task);
        INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task);
+       netif_set_gso_max_size(netdev, MAX_TSO_SEG_SIZE);
        err = register_netdev(netdev);
        if (err) {
                netdev_err(netdev, "register netdevice failed\n");
index 4046f97378c29fa737d7123347ba1e940bd8e46d..57619dd4a92b0ef08ff0b990ae26db355bb732f3 100644 (file)
@@ -2614,6 +2614,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                        }
                }
 
+               /* initialize FW coalescing state machines in RAM */
+               bnx2x_update_coalesce(bp);
+
                /* setup the leading queue */
                rc = bnx2x_setup_leading(bp);
                if (rc) {
@@ -4580,11 +4583,11 @@ static void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
        u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
        u32 addr = BAR_CSTRORM_INTMEM +
                   CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(fw_sb_id, sb_index);
-       u16 flags = REG_RD16(bp, addr);
+       u8 flags = REG_RD8(bp, addr);
        /* clear and set */
        flags &= ~HC_INDEX_DATA_HC_ENABLED;
        flags |= enable_flag;
-       REG_WR16(bp, addr, flags);
+       REG_WR8(bp, addr, flags);
        DP(NETIF_MSG_IFUP,
           "port %x fw_sb_id %d sb_index %d disable %d\n",
           port, fw_sb_id, sb_index, disable);
index 77ebae0ac64aa9a4e681a506129c5a835d85ef4e..0283f343b0d1efd82be8f7fcb8b392823d0111e0 100644 (file)
@@ -13437,13 +13437,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
 {
        struct bnx2x *bp = params->bp;
        u16 base_page, next_page, not_kr2_device, lane;
-       int sigdet = bnx2x_warpcore_get_sigdet(phy, params);
-
-       if (!sigdet) {
-               if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
-                       bnx2x_kr2_recovery(params, vars, phy);
-               return;
-       }
+       int sigdet;
 
        /* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery
         * since some switches tend to reinit the AN process and clear the
@@ -13454,6 +13448,16 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
                vars->check_kr2_recovery_cnt--;
                return;
        }
+
+       sigdet = bnx2x_warpcore_get_sigdet(phy, params);
+       if (!sigdet) {
+               if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+                       bnx2x_kr2_recovery(params, vars, phy);
+                       DP(NETIF_MSG_LINK, "No sigdet\n");
+               }
+               return;
+       }
+
        lane = bnx2x_get_warpcore_lane(phy, params);
        CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
                          MDIO_AER_BLOCK_AER_REG, lane);
index e81a747ea8ce0ee4461fea92565fa32b15ea6682..c50696b396f1cb88196d4f682d61d902d0da9fc6 100644 (file)
@@ -4947,7 +4947,7 @@ static void bnx2x_after_function_update(struct bnx2x *bp)
                                  q);
        }
 
-       if (!NO_FCOE(bp)) {
+       if (!NO_FCOE(bp) && CNIC_ENABLED(bp)) {
                fp = &bp->fp[FCOE_IDX(bp)];
                queue_params.q_obj = &bnx2x_sp_obj(bp, fp).q_obj;
 
@@ -9878,6 +9878,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
                                REG_RD(bp, NIG_REG_NIG_INT_STS_CLR_0);
                        }
                }
+               if (!CHIP_IS_E1x(bp))
+                       /* block FW from writing to host */
+                       REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0);
+
                /* wait until BRB is empty */
                tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS);
                while (timer_count) {
@@ -13354,6 +13358,7 @@ static int bnx2x_unregister_cnic(struct net_device *dev)
        RCU_INIT_POINTER(bp->cnic_ops, NULL);
        mutex_unlock(&bp->cnic_mutex);
        synchronize_rcu();
+       bp->cnic_enabled = false;
        kfree(bp->cnic_kwq);
        bp->cnic_kwq = NULL;
 
index 67d2663b3974aeaf03acfeb9500704ee5659ab8a..17a972734ba746d9218df4bf025218a91ebee947 100644 (file)
@@ -14604,8 +14604,11 @@ static void tg3_read_vpd(struct tg3 *tp)
                if (j + len > block_end)
                        goto partno;
 
-               memcpy(tp->fw_ver, &vpd_data[j], len);
-               strncat(tp->fw_ver, " bc ", vpdlen - len - 1);
+               if (len >= sizeof(tp->fw_ver))
+                       len = sizeof(tp->fw_ver) - 1;
+               memset(tp->fw_ver, 0, sizeof(tp->fw_ver));
+               snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len,
+                        &vpd_data[j]);
        }
 
 partno:
index a170065b597382ed9408239d98c36cec98a535a2..b0ebc9f6d55e9844e1ebe9367e9340681cba2a72 100644 (file)
 #define XGMAC_FLOW_CTRL_FCB_BPA        0x00000001      /* Flow Control Busy ... */
 
 /* XGMAC_INT_STAT reg */
+#define XGMAC_INT_STAT_PMTIM   0x00800000      /* PMT Interrupt Mask */
 #define XGMAC_INT_STAT_PMT     0x0080          /* PMT Interrupt Status */
 #define XGMAC_INT_STAT_LPI     0x0040          /* LPI Interrupt Status */
 
@@ -960,6 +961,9 @@ static int xgmac_hw_init(struct net_device *dev)
        writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_STATUS);
        writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_INTR_ENA);
 
+       /* Mask power mgt interrupt */
+       writel(XGMAC_INT_STAT_PMTIM, ioaddr + XGMAC_INT_STAT);
+
        /* XGMAC requires AXI bus init. This is a 'magic number' for now */
        writel(0x0077000E, ioaddr + XGMAC_DMA_AXI_BUS);
 
@@ -1141,6 +1145,9 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
                struct sk_buff *skb;
                int frame_len;
 
+               if (!dma_ring_cnt(priv->rx_head, priv->rx_tail, DMA_RX_RING_SZ))
+                       break;
+
                entry = priv->rx_tail;
                p = priv->dma_rx + entry;
                if (desc_get_owner(p))
@@ -1825,7 +1832,7 @@ static void xgmac_pmt(void __iomem *ioaddr, unsigned long mode)
        unsigned int pmt = 0;
 
        if (mode & WAKE_MAGIC)
-               pmt |= XGMAC_PMT_POWERDOWN | XGMAC_PMT_MAGIC_PKT;
+               pmt |= XGMAC_PMT_POWERDOWN | XGMAC_PMT_MAGIC_PKT_EN;
        if (mode & WAKE_UCAST)
                pmt |= XGMAC_PMT_POWERDOWN | XGMAC_PMT_GLBL_UNICAST;
 
index 8cdf02503d13d5bdd52348f77995c0ce47618f1c..9eada8e86078fe83981223e023bd45f3929b1a70 100644 (file)
@@ -257,6 +257,107 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
                tmp = readl(reg);
 }
 
+/*
+ * Sleep, either by using msleep() or if we are suspending, then
+ * use mdelay() to sleep.
+ */
+static void dm9000_msleep(board_info_t *db, unsigned int ms)
+{
+       if (db->in_suspend)
+               mdelay(ms);
+       else
+               msleep(ms);
+}
+
+/* Read a word from phyxcer */
+static int
+dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
+{
+       board_info_t *db = netdev_priv(dev);
+       unsigned long flags;
+       unsigned int reg_save;
+       int ret;
+
+       mutex_lock(&db->addr_lock);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       /* Save previous register address */
+       reg_save = readb(db->io_addr);
+
+       /* Fill the phyxcer register into REG_0C */
+       iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+       /* Issue phyxcer read command */
+       iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);
+
+       writeb(reg_save, db->io_addr);
+       spin_unlock_irqrestore(&db->lock, flags);
+
+       dm9000_msleep(db, 1);           /* Wait read complete */
+
+       spin_lock_irqsave(&db->lock, flags);
+       reg_save = readb(db->io_addr);
+
+       iow(db, DM9000_EPCR, 0x0);      /* Clear phyxcer read command */
+
+       /* The read data keeps on REG_0D & REG_0E */
+       ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
+
+       /* restore the previous address */
+       writeb(reg_save, db->io_addr);
+       spin_unlock_irqrestore(&db->lock, flags);
+
+       mutex_unlock(&db->addr_lock);
+
+       dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
+       return ret;
+}
+
+/* Write a word to phyxcer */
+static void
+dm9000_phy_write(struct net_device *dev,
+                int phyaddr_unused, int reg, int value)
+{
+       board_info_t *db = netdev_priv(dev);
+       unsigned long flags;
+       unsigned long reg_save;
+
+       dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
+       mutex_lock(&db->addr_lock);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       /* Save previous register address */
+       reg_save = readb(db->io_addr);
+
+       /* Fill the phyxcer register into REG_0C */
+       iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+       /* Fill the written data into REG_0D & REG_0E */
+       iow(db, DM9000_EPDRL, value);
+       iow(db, DM9000_EPDRH, value >> 8);
+
+       /* Issue phyxcer write command */
+       iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);
+
+       writeb(reg_save, db->io_addr);
+       spin_unlock_irqrestore(&db->lock, flags);
+
+       dm9000_msleep(db, 1);           /* Wait write complete */
+
+       spin_lock_irqsave(&db->lock, flags);
+       reg_save = readb(db->io_addr);
+
+       iow(db, DM9000_EPCR, 0x0);      /* Clear phyxcer write command */
+
+       /* restore the previous address */
+       writeb(reg_save, db->io_addr);
+
+       spin_unlock_irqrestore(&db->lock, flags);
+       mutex_unlock(&db->addr_lock);
+}
+
 /* dm9000_set_io
  *
  * select the specified set of io routines to use with the
@@ -795,6 +896,9 @@ dm9000_init_dm9000(struct net_device *dev)
 
        iow(db, DM9000_GPCR, GPCR_GEP_CNTL);    /* Let GPIO0 output */
 
+       dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
+       dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */
+
        ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
 
        /* if wol is needed, then always set NCR_WAKEEN otherwise we end
@@ -1201,109 +1305,6 @@ dm9000_open(struct net_device *dev)
        return 0;
 }
 
-/*
- * Sleep, either by using msleep() or if we are suspending, then
- * use mdelay() to sleep.
- */
-static void dm9000_msleep(board_info_t *db, unsigned int ms)
-{
-       if (db->in_suspend)
-               mdelay(ms);
-       else
-               msleep(ms);
-}
-
-/*
- *   Read a word from phyxcer
- */
-static int
-dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
-{
-       board_info_t *db = netdev_priv(dev);
-       unsigned long flags;
-       unsigned int reg_save;
-       int ret;
-
-       mutex_lock(&db->addr_lock);
-
-       spin_lock_irqsave(&db->lock,flags);
-
-       /* Save previous register address */
-       reg_save = readb(db->io_addr);
-
-       /* Fill the phyxcer register into REG_0C */
-       iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
-       iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);   /* Issue phyxcer read command */
-
-       writeb(reg_save, db->io_addr);
-       spin_unlock_irqrestore(&db->lock,flags);
-
-       dm9000_msleep(db, 1);           /* Wait read complete */
-
-       spin_lock_irqsave(&db->lock,flags);
-       reg_save = readb(db->io_addr);
-
-       iow(db, DM9000_EPCR, 0x0);      /* Clear phyxcer read command */
-
-       /* The read data keeps on REG_0D & REG_0E */
-       ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
-
-       /* restore the previous address */
-       writeb(reg_save, db->io_addr);
-       spin_unlock_irqrestore(&db->lock,flags);
-
-       mutex_unlock(&db->addr_lock);
-
-       dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
-       return ret;
-}
-
-/*
- *   Write a word to phyxcer
- */
-static void
-dm9000_phy_write(struct net_device *dev,
-                int phyaddr_unused, int reg, int value)
-{
-       board_info_t *db = netdev_priv(dev);
-       unsigned long flags;
-       unsigned long reg_save;
-
-       dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
-       mutex_lock(&db->addr_lock);
-
-       spin_lock_irqsave(&db->lock,flags);
-
-       /* Save previous register address */
-       reg_save = readb(db->io_addr);
-
-       /* Fill the phyxcer register into REG_0C */
-       iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
-       /* Fill the written data into REG_0D & REG_0E */
-       iow(db, DM9000_EPDRL, value);
-       iow(db, DM9000_EPDRH, value >> 8);
-
-       iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);   /* Issue phyxcer write command */
-
-       writeb(reg_save, db->io_addr);
-       spin_unlock_irqrestore(&db->lock, flags);
-
-       dm9000_msleep(db, 1);           /* Wait write complete */
-
-       spin_lock_irqsave(&db->lock,flags);
-       reg_save = readb(db->io_addr);
-
-       iow(db, DM9000_EPCR, 0x0);      /* Clear phyxcer write command */
-
-       /* restore the previous address */
-       writeb(reg_save, db->io_addr);
-
-       spin_unlock_irqrestore(&db->lock, flags);
-       mutex_unlock(&db->addr_lock);
-}
-
 static void
 dm9000_shutdown(struct net_device *dev)
 {
@@ -1502,7 +1503,12 @@ dm9000_probe(struct platform_device *pdev)
        db->flags |= DM9000_PLATF_SIMPLE_PHY;
 #endif
 
-       dm9000_reset(db);
+       /* Fixing bug on dm9000_probe, takeover dm9000_reset(db),
+        * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo
+        * while probe stage.
+        */
+
+       iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST);
 
        /* try multiple times, DM9000 sometimes gets the read wrong */
        for (i = 0; i < 8; i++) {
index 55688bd1a3ef0bb83ed90391c33bce894a16da89..9ce058adababcf28c83f644819b0b501079ef898 100644 (file)
@@ -69,7 +69,9 @@
 #define NCR_WAKEEN          (1<<6)
 #define NCR_FCOL            (1<<4)
 #define NCR_FDX             (1<<3)
-#define NCR_LBK             (3<<1)
+
+#define NCR_RESERVED        (3<<1)
+#define NCR_MAC_LBK         (1<<1)
 #define NCR_RST                    (1<<0)
 
 #define NSR_SPEED           (1<<7)
 #define ISR_LNKCHNG            (1<<5)
 #define ISR_UNDERRUN           (1<<4)
 
+/* Davicom MII registers.
+ */
+
+#define MII_DM_DSPCR           0x1b    /* DSP Control Register */
+
+#define DSPCR_INIT_PARAM       0xE100  /* DSP init parameter */
+
 #endif /* _DM9000X_H_ */
 
index 08e54f3d288bc9a2e23faa8bb954dcb4bd8cf584..2886c9b63f9099059d3c8c0fe7a86cddc912854f 100644 (file)
@@ -759,8 +759,9 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
 
        if (vlan_tx_tag_present(skb)) {
                vlan_tag = be_get_tx_vlan_tag(adapter, skb);
-               __vlan_put_tag(skb, vlan_tag);
-               skb->vlan_tci = 0;
+               skb = __vlan_put_tag(skb, vlan_tag);
+               if (skb)
+                       skb->vlan_tci = 0;
        }
 
        return skb;
index 911d0253dbb209d7dc787641cc442c9d12ef370a..73195f643c9c3b23e45a0fac4008caa919473a25 100644 (file)
@@ -345,6 +345,53 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        return NETDEV_TX_OK;
 }
 
+/* Init RX & TX buffer descriptors
+ */
+static void fec_enet_bd_init(struct net_device *dev)
+{
+       struct fec_enet_private *fep = netdev_priv(dev);
+       struct bufdesc *bdp;
+       unsigned int i;
+
+       /* Initialize the receive buffer descriptors. */
+       bdp = fep->rx_bd_base;
+       for (i = 0; i < RX_RING_SIZE; i++) {
+
+               /* Initialize the BD for every fragment in the page. */
+               if (bdp->cbd_bufaddr)
+                       bdp->cbd_sc = BD_ENET_RX_EMPTY;
+               else
+                       bdp->cbd_sc = 0;
+               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+       }
+
+       /* Set the last buffer to wrap */
+       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+       bdp->cbd_sc |= BD_SC_WRAP;
+
+       fep->cur_rx = fep->rx_bd_base;
+
+       /* ...and the same for transmit */
+       bdp = fep->tx_bd_base;
+       fep->cur_tx = bdp;
+       for (i = 0; i < TX_RING_SIZE; i++) {
+
+               /* Initialize the BD for every fragment in the page. */
+               bdp->cbd_sc = 0;
+               if (bdp->cbd_bufaddr && fep->tx_skbuff[i]) {
+                       dev_kfree_skb_any(fep->tx_skbuff[i]);
+                       fep->tx_skbuff[i] = NULL;
+               }
+               bdp->cbd_bufaddr = 0;
+               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+       }
+
+       /* Set the last buffer to wrap */
+       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+       bdp->cbd_sc |= BD_SC_WRAP;
+       fep->dirty_tx = bdp;
+}
+
 /* This function is called to start or restart the FEC during a link
  * change.  This only happens when switching between half and full
  * duplex.
@@ -388,6 +435,8 @@ fec_restart(struct net_device *ndev, int duplex)
        /* Set maximum receive buffer size. */
        writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
 
+       fec_enet_bd_init(ndev);
+
        /* Set receive and transmit descriptor base. */
        writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
        if (fep->bufdesc_ex)
@@ -397,7 +446,6 @@ fec_restart(struct net_device *ndev, int duplex)
                writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
                        * RX_RING_SIZE, fep->hwp + FEC_X_DES_START);
 
-       fep->cur_rx = fep->rx_bd_base;
 
        for (i = 0; i <= TX_RING_MOD_MASK; i++) {
                if (fep->tx_skbuff[i]) {
@@ -954,6 +1002,7 @@ static void fec_enet_adjust_link(struct net_device *ndev)
        } else {
                if (fep->link) {
                        fec_stop(ndev);
+                       fep->link = phy_dev->link;
                        status_change = 1;
                }
        }
@@ -1597,8 +1646,6 @@ static int fec_enet_init(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
        struct bufdesc *cbd_base;
-       struct bufdesc *bdp;
-       unsigned int i;
 
        /* Allocate memory for buffer descriptors. */
        cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
@@ -1608,6 +1655,7 @@ static int fec_enet_init(struct net_device *ndev)
                return -ENOMEM;
        }
 
+       memset(cbd_base, 0, PAGE_SIZE);
        spin_lock_init(&fep->hw_lock);
 
        fep->netdev = ndev;
@@ -1631,35 +1679,6 @@ static int fec_enet_init(struct net_device *ndev)
        writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
        netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT);
 
-       /* Initialize the receive buffer descriptors. */
-       bdp = fep->rx_bd_base;
-       for (i = 0; i < RX_RING_SIZE; i++) {
-
-               /* Initialize the BD for every fragment in the page. */
-               bdp->cbd_sc = 0;
-               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-       }
-
-       /* Set the last buffer to wrap */
-       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
-       bdp->cbd_sc |= BD_SC_WRAP;
-
-       /* ...and the same for transmit */
-       bdp = fep->tx_bd_base;
-       fep->cur_tx = bdp;
-       for (i = 0; i < TX_RING_SIZE; i++) {
-
-               /* Initialize the BD for every fragment in the page. */
-               bdp->cbd_sc = 0;
-               bdp->cbd_bufaddr = 0;
-               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-       }
-
-       /* Set the last buffer to wrap */
-       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
-       bdp->cbd_sc |= BD_SC_WRAP;
-       fep->dirty_tx = bdp;
-
        fec_restart(ndev, 0);
 
        return 0;
index ec800b093e7eb22536b7247289d13c0450b9552f..d2bea3f07c73782504dffef8862d5a77944c7290 100644 (file)
@@ -870,7 +870,7 @@ err_unlock:
 }
 
 static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
-       void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
+       int (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
 {
        struct cb *cb;
        unsigned long flags;
@@ -888,10 +888,13 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
        nic->cbs_avail--;
        cb->skb = skb;
 
+       err = cb_prepare(nic, cb, skb);
+       if (err)
+               goto err_unlock;
+
        if (unlikely(!nic->cbs_avail))
                err = -ENOSPC;
 
-       cb_prepare(nic, cb, skb);
 
        /* Order is important otherwise we'll be in a race with h/w:
         * set S-bit in current first, then clear S-bit in previous. */
@@ -1091,7 +1094,7 @@ static void e100_get_defaults(struct nic *nic)
        nic->mii.mdio_write = mdio_write;
 }
 
-static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+static int e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 {
        struct config *config = &cb->u.config;
        u8 *c = (u8 *)config;
@@ -1181,6 +1184,7 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
        netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
                     "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
                     c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
+       return 0;
 }
 
 /*************************************************************************
@@ -1331,7 +1335,7 @@ static const struct firmware *e100_request_firmware(struct nic *nic)
        return fw;
 }
 
-static void e100_setup_ucode(struct nic *nic, struct cb *cb,
+static int e100_setup_ucode(struct nic *nic, struct cb *cb,
                             struct sk_buff *skb)
 {
        const struct firmware *fw = (void *)skb;
@@ -1358,6 +1362,7 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb,
        cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80);
 
        cb->command = cpu_to_le16(cb_ucode | cb_el);
+       return 0;
 }
 
 static inline int e100_load_ucode_wait(struct nic *nic)
@@ -1400,18 +1405,20 @@ static inline int e100_load_ucode_wait(struct nic *nic)
        return err;
 }
 
-static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
+static int e100_setup_iaaddr(struct nic *nic, struct cb *cb,
        struct sk_buff *skb)
 {
        cb->command = cpu_to_le16(cb_iaaddr);
        memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN);
+       return 0;
 }
 
-static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+static int e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 {
        cb->command = cpu_to_le16(cb_dump);
        cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr +
                offsetof(struct mem, dump_buf));
+       return 0;
 }
 
 static int e100_phy_check_without_mii(struct nic *nic)
@@ -1581,7 +1588,7 @@ static int e100_hw_init(struct nic *nic)
        return 0;
 }
 
-static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+static int e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 {
        struct net_device *netdev = nic->netdev;
        struct netdev_hw_addr *ha;
@@ -1596,6 +1603,7 @@ static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
                memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &ha->addr,
                        ETH_ALEN);
        }
+       return 0;
 }
 
 static void e100_set_multicast_list(struct net_device *netdev)
@@ -1756,11 +1764,18 @@ static void e100_watchdog(unsigned long data)
                  round_jiffies(jiffies + E100_WATCHDOG_PERIOD));
 }
 
-static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
+static int e100_xmit_prepare(struct nic *nic, struct cb *cb,
        struct sk_buff *skb)
 {
+       dma_addr_t dma_addr;
        cb->command = nic->tx_command;
 
+       dma_addr = pci_map_single(nic->pdev,
+                                 skb->data, skb->len, PCI_DMA_TODEVICE);
+       /* If we can't map the skb, have the upper layer try later */
+       if (pci_dma_mapping_error(nic->pdev, dma_addr))
+               return -ENOMEM;
+
        /*
         * Use the last 4 bytes of the SKB payload packet as the CRC, used for
         * testing, ie sending frames with bad CRC.
@@ -1777,11 +1792,10 @@ static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
        cb->u.tcb.tcb_byte_count = 0;
        cb->u.tcb.threshold = nic->tx_threshold;
        cb->u.tcb.tbd_count = 1;
-       cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
-               skb->data, skb->len, PCI_DMA_TODEVICE));
-       /* check for mapping failure? */
+       cb->u.tcb.tbd.buf_addr = cpu_to_le32(dma_addr);
        cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
        skb_tx_timestamp(skb);
+       return 0;
 }
 
 static netdev_tx_t e100_xmit_frame(struct sk_buff *skb,
index 43462d596a4e5b04050793d66e26b0172a4f78de..ffd287196bf875560e40e5330c68e0a84b50e930 100644 (file)
@@ -1053,6 +1053,10 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
                txdr->buffer_info[i].dma =
                        dma_map_single(&pdev->dev, skb->data, skb->len,
                                       DMA_TO_DEVICE);
+               if (dma_mapping_error(&pdev->dev, txdr->buffer_info[i].dma)) {
+                       ret_val = 4;
+                       goto err_nomem;
+               }
                tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma);
                tx_desc->lower.data = cpu_to_le32(skb->len);
                tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP |
@@ -1069,7 +1073,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
        rxdr->buffer_info = kcalloc(rxdr->count, sizeof(struct e1000_buffer),
                                    GFP_KERNEL);
        if (!rxdr->buffer_info) {
-               ret_val = 4;
+               ret_val = 5;
                goto err_nomem;
        }
 
@@ -1077,7 +1081,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
        rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
                                        GFP_KERNEL);
        if (!rxdr->desc) {
-               ret_val = 5;
+               ret_val = 6;
                goto err_nomem;
        }
        memset(rxdr->desc, 0, rxdr->size);
@@ -1101,7 +1105,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 
                skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
                if (!skb) {
-                       ret_val = 6;
+                       ret_val = 7;
                        goto err_nomem;
                }
                skb_reserve(skb, NET_IP_ALIGN);
@@ -1110,6 +1114,10 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
                rxdr->buffer_info[i].dma =
                        dma_map_single(&pdev->dev, skb->data,
                                       E1000_RXBUFFER_2048, DMA_FROM_DEVICE);
+               if (dma_mapping_error(&pdev->dev, rxdr->buffer_info[i].dma)) {
+                       ret_val = 8;
+                       goto err_nomem;
+               }
                rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma);
                memset(skb->data, 0x00, skb->len);
        }
index 948b86ffa4f027753eec3f5b57b45b90277947ab..7e615e2bf7e6a4e96971945d33e3e332301e88bb 100644 (file)
@@ -848,11 +848,16 @@ check_page:
                        }
                }
 
-               if (!buffer_info->dma)
+               if (!buffer_info->dma) {
                        buffer_info->dma = dma_map_page(&pdev->dev,
                                                        buffer_info->page, 0,
                                                        PAGE_SIZE,
                                                        DMA_FROM_DEVICE);
+                       if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+                               adapter->alloc_rx_buff_failed++;
+                               break;
+                       }
+               }
 
                rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
                rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
index 25151401c2abe54dcec7fe1fe6f48791e0660a64..ab577a763a20d96cb68c151b8f3ceb483af6f8bf 100644 (file)
@@ -284,18 +284,10 @@ struct igb_q_vector {
 enum e1000_ring_flags_t {
        IGB_RING_FLAG_RX_SCTP_CSUM,
        IGB_RING_FLAG_RX_LB_VLAN_BSWAP,
-       IGB_RING_FLAG_RX_BUILD_SKB_ENABLED,
        IGB_RING_FLAG_TX_CTX_IDX,
        IGB_RING_FLAG_TX_DETECT_HANG
 };
 
-#define ring_uses_build_skb(ring) \
-       test_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
-#define set_ring_build_skb_enabled(ring) \
-       set_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
-#define clear_ring_build_skb_enabled(ring) \
-       clear_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
-
 #define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS)
 
 #define IGB_RX_DESC(R, i)          \
index 8496adfc6a685580f6ec1c50b86f0fed62b2b121..64f75291e3a5ca5402dfbee6dccb7a68bf1f1dd0 100644 (file)
@@ -3350,20 +3350,6 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
        wr32(E1000_RXDCTL(reg_idx), rxdctl);
 }
 
-static void igb_set_rx_buffer_len(struct igb_adapter *adapter,
-                                 struct igb_ring *rx_ring)
-{
-#define IGB_MAX_BUILD_SKB_SIZE \
-       (SKB_WITH_OVERHEAD(IGB_RX_BUFSZ) - \
-        (NET_SKB_PAD + NET_IP_ALIGN + IGB_TS_HDR_LEN))
-
-       /* set build_skb flag */
-       if (adapter->max_frame_size <= IGB_MAX_BUILD_SKB_SIZE)
-               set_ring_build_skb_enabled(rx_ring);
-       else
-               clear_ring_build_skb_enabled(rx_ring);
-}
-
 /**
  * igb_configure_rx - Configure receive Unit after Reset
  * @adapter: board private structure
@@ -3383,11 +3369,8 @@ static void igb_configure_rx(struct igb_adapter *adapter)
 
        /* Setup the HW Rx Head and Tail Descriptor Pointers and
         * the Base and Length of the Rx Descriptor Ring */
-       for (i = 0; i < adapter->num_rx_queues; i++) {
-               struct igb_ring *rx_ring = adapter->rx_ring[i];
-               igb_set_rx_buffer_len(adapter, rx_ring);
-               igb_configure_rx_ring(adapter, rx_ring);
-       }
+       for (i = 0; i < adapter->num_rx_queues; i++)
+               igb_configure_rx_ring(adapter, adapter->rx_ring[i]);
 }
 
 /**
@@ -6203,78 +6186,6 @@ static bool igb_add_rx_frag(struct igb_ring *rx_ring,
        return igb_can_reuse_rx_page(rx_buffer, page, truesize);
 }
 
-static struct sk_buff *igb_build_rx_buffer(struct igb_ring *rx_ring,
-                                          union e1000_adv_rx_desc *rx_desc)
-{
-       struct igb_rx_buffer *rx_buffer;
-       struct sk_buff *skb;
-       struct page *page;
-       void *page_addr;
-       unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
-#if (PAGE_SIZE < 8192)
-       unsigned int truesize = IGB_RX_BUFSZ;
-#else
-       unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
-                               SKB_DATA_ALIGN(NET_SKB_PAD +
-                                              NET_IP_ALIGN +
-                                              size);
-#endif
-
-       /* If we spanned a buffer we have a huge mess so test for it */
-       BUG_ON(unlikely(!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)));
-
-       rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
-       page = rx_buffer->page;
-       prefetchw(page);
-
-       page_addr = page_address(page) + rx_buffer->page_offset;
-
-       /* prefetch first cache line of first page */
-       prefetch(page_addr + NET_SKB_PAD + NET_IP_ALIGN);
-#if L1_CACHE_BYTES < 128
-       prefetch(page_addr + L1_CACHE_BYTES + NET_SKB_PAD + NET_IP_ALIGN);
-#endif
-
-       /* build an skb to around the page buffer */
-       skb = build_skb(page_addr, truesize);
-       if (unlikely(!skb)) {
-               rx_ring->rx_stats.alloc_failed++;
-               return NULL;
-       }
-
-       /* we are reusing so sync this buffer for CPU use */
-       dma_sync_single_range_for_cpu(rx_ring->dev,
-                                     rx_buffer->dma,
-                                     rx_buffer->page_offset,
-                                     IGB_RX_BUFSZ,
-                                     DMA_FROM_DEVICE);
-
-       /* update pointers within the skb to store the data */
-       skb_reserve(skb, NET_IP_ALIGN + NET_SKB_PAD);
-       __skb_put(skb, size);
-
-       /* pull timestamp out of packet data */
-       if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
-               igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb);
-               __skb_pull(skb, IGB_TS_HDR_LEN);
-       }
-
-       if (igb_can_reuse_rx_page(rx_buffer, page, truesize)) {
-               /* hand second half of page back to the ring */
-               igb_reuse_rx_page(rx_ring, rx_buffer);
-       } else {
-               /* we are not reusing the buffer so unmap it */
-               dma_unmap_page(rx_ring->dev, rx_buffer->dma,
-                              PAGE_SIZE, DMA_FROM_DEVICE);
-       }
-
-       /* clear contents of buffer_info */
-       rx_buffer->dma = 0;
-       rx_buffer->page = NULL;
-
-       return skb;
-}
-
 static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,
                                           union e1000_adv_rx_desc *rx_desc,
                                           struct sk_buff *skb)
@@ -6690,10 +6601,7 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
                rmb();
 
                /* retrieve a buffer from the ring */
-               if (ring_uses_build_skb(rx_ring))
-                       skb = igb_build_rx_buffer(rx_ring, rx_desc);
-               else
-                       skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
+               skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
 
                /* exit if we failed to retrieve a buffer */
                if (!skb)
@@ -6780,14 +6688,6 @@ static bool igb_alloc_mapped_page(struct igb_ring *rx_ring,
        return true;
 }
 
-static inline unsigned int igb_rx_offset(struct igb_ring *rx_ring)
-{
-       if (ring_uses_build_skb(rx_ring))
-               return NET_SKB_PAD + NET_IP_ALIGN;
-       else
-               return 0;
-}
-
 /**
  * igb_alloc_rx_buffers - Replace used receive buffers; packet split
  * @adapter: address of board private structure
@@ -6814,9 +6714,7 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
                 * Refresh the desc even if buffer_addrs didn't change
                 * because each write-back erases this info.
                 */
-               rx_desc->read.pkt_addr = cpu_to_le64(bi->dma +
-                                                    bi->page_offset +
-                                                    igb_rx_offset(rx_ring));
+               rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
 
                rx_desc++;
                bi++;
index ea48083734359e52b229f592e84abf7654a82523..b5f94abe3cffc9c406f8e2aaa27ed9cd77ad6542 100644 (file)
@@ -2159,6 +2159,10 @@ map_skb:
                                                  skb->data,
                                                  adapter->rx_buffer_len,
                                                  DMA_FROM_DEVICE);
+               if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+                       adapter->alloc_rx_buff_failed++;
+                       break;
+               }
 
                rx_desc = IXGB_RX_DESC(*rx_ring, i);
                rx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
@@ -2168,7 +2172,8 @@ map_skb:
                rx_desc->status = 0;
 
 
-               if (++i == rx_ring->count) i = 0;
+               if (++i == rx_ring->count)
+                       i = 0;
                buffer_info = &rx_ring->buffer_info[i];
        }
 
index db5611ae407ed5ec3a2c90341e96c12e6945ff9d..79f4a26ea6cc580c1b23cd72fee362c3c495880a 100644 (file)
@@ -7922,12 +7922,19 @@ static int __init ixgbe_init_module(void)
        ixgbe_dbg_init();
 #endif /* CONFIG_DEBUG_FS */
 
+       ret = pci_register_driver(&ixgbe_driver);
+       if (ret) {
+#ifdef CONFIG_DEBUG_FS
+               ixgbe_dbg_exit();
+#endif /* CONFIG_DEBUG_FS */
+               return ret;
+       }
+
 #ifdef CONFIG_IXGBE_DCA
        dca_register_notify(&dca_notifier);
 #endif
 
-       ret = pci_register_driver(&ixgbe_driver);
-       return ret;
+       return 0;
 }
 
 module_init(ixgbe_init_module);
index d44b4d21268ceafb33cd47c636db2809db2542f8..97e33669c0b9b4c6e4bc105ab5f125dffabd9ee0 100644 (file)
@@ -1049,6 +1049,12 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
        if ((vf >= adapter->num_vfs) || (vlan > 4095) || (qos > 7))
                return -EINVAL;
        if (vlan || qos) {
+               if (adapter->vfinfo[vf].pf_vlan)
+                       err = ixgbe_set_vf_vlan(adapter, false,
+                                               adapter->vfinfo[vf].pf_vlan,
+                                               vf);
+               if (err)
+                       goto out;
                err = ixgbe_set_vf_vlan(adapter, true, vlan, vf);
                if (err)
                        goto out;
index edfba9370922f54632f96440d394772a9da9054b..434e33c527df102adf5052854bc92d816588b4ba 100644 (file)
@@ -33,6 +33,7 @@ config MV643XX_ETH
 
 config MVMDIO
        tristate "Marvell MDIO interface support"
+       select PHYLIB
        ---help---
          This driver supports the MDIO interface found in the network
          interface units of the Marvell EBU SoCs (Kirkwood, Orion5x,
@@ -45,7 +46,6 @@ config MVMDIO
 config MVNETA
        tristate "Marvell Armada 370/XP network interface support"
        depends on MACH_ARMADA_370_XP
-       select PHYLIB
        select MVMDIO
        ---help---
          This driver supports the network interface units in the
index cd345b8969bcaa75643a34da5819af5d569a1523..a47a097c21e13b1373fb6fa896374d8d6ffcd04c 100644 (file)
@@ -374,7 +374,6 @@ static int rxq_number = 8;
 static int txq_number = 8;
 
 static int rxq_def;
-static int txq_def;
 
 #define MVNETA_DRIVER_NAME "mvneta"
 #define MVNETA_DRIVER_VERSION "1.0"
@@ -1475,7 +1474,8 @@ error:
 static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
 {
        struct mvneta_port *pp = netdev_priv(dev);
-       struct mvneta_tx_queue *txq = &pp->txqs[txq_def];
+       u16 txq_id = skb_get_queue_mapping(skb);
+       struct mvneta_tx_queue *txq = &pp->txqs[txq_id];
        struct mvneta_tx_desc *tx_desc;
        struct netdev_queue *nq;
        int frags = 0;
@@ -1485,7 +1485,7 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
                goto out;
 
        frags = skb_shinfo(skb)->nr_frags + 1;
-       nq    = netdev_get_tx_queue(dev, txq_def);
+       nq    = netdev_get_tx_queue(dev, txq_id);
 
        /* Get a descriptor for the first part of the packet */
        tx_desc = mvneta_txq_next_desc_get(txq);
@@ -2689,7 +2689,7 @@ static int mvneta_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       dev = alloc_etherdev_mq(sizeof(struct mvneta_port), 8);
+       dev = alloc_etherdev_mqs(sizeof(struct mvneta_port), txq_number, rxq_number);
        if (!dev)
                return -ENOMEM;
 
@@ -2771,16 +2771,17 @@ static int mvneta_probe(struct platform_device *pdev)
 
        netif_napi_add(dev, &pp->napi, mvneta_poll, pp->weight);
 
+       dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
+       dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+       dev->vlan_features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+       dev->priv_flags |= IFF_UNICAST_FLT;
+
        err = register_netdev(dev);
        if (err < 0) {
                dev_err(&pdev->dev, "failed to register\n");
                goto err_deinit;
        }
 
-       dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
-       dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM;
-       dev->priv_flags |= IFF_UNICAST_FLT;
-
        netdev_info(dev, "mac: %pM\n", dev->dev_addr);
 
        platform_set_drvdata(pdev, pp->dev);
@@ -2843,4 +2844,3 @@ module_param(rxq_number, int, S_IRUGO);
 module_param(txq_number, int, S_IRUGO);
 
 module_param(rxq_def, int, S_IRUGO);
-module_param(txq_def, int, S_IRUGO);
index fc07ca35721b29ba07dba97bf6e52dc74f446534..6a0e671fcecd6e399952056646130578191ba57d 100644 (file)
@@ -1067,7 +1067,7 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 space)
                sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
                sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
 
-               tp = space - 2048/8;
+               tp = space - 8192/8;
                sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
                sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
        } else {
index 615ac63ea8603a802896d2bd810d4c2ac874204c..ec6dcd80152bdd46550b0aaf0865d00a01261a93 100644 (file)
@@ -2074,7 +2074,7 @@ enum {
        GM_IS_RX_FF_OR  = 1<<1, /* Receive FIFO Overrun */
        GM_IS_RX_COMPL  = 1<<0, /* Frame Reception Complete */
 
-#define GMAC_DEF_MSK     GM_IS_TX_FF_UR
+#define GMAC_DEF_MSK     (GM_IS_TX_FF_UR | GM_IS_RX_FF_OR)
 };
 
 /*     GMAC_LINK_CTRL  16 bit  GMAC Link Control Reg (YUKON only) */
index f278b10ef7140a6e195056e11a12075de02afabc..30d78f806dc3735dd3d8a4aa0c9a21a867976cd2 100644 (file)
@@ -411,8 +411,8 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 
 static void mlx4_en_u64_to_mac(unsigned char dst_mac[ETH_ALEN + 2], u64 src_mac)
 {
-       unsigned int i;
-       for (i = ETH_ALEN - 1; i; --i) {
+       int i;
+       for (i = ETH_ALEN - 1; i >= 0; --i) {
                dst_mac[i] = src_mac & 0xff;
                src_mac >>= 8;
        }
index 33bcb63d56a2355c93dbd1306f24bce816eab23c..8fb481252e2cb653f45f7543f7e41c70cef9401e 100644 (file)
@@ -528,7 +528,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
        for (; rxfc != 0; rxfc--) {
                rxh = ks8851_rdreg32(ks, KS_RXFHSR);
                rxstat = rxh & 0xffff;
-               rxlen = rxh >> 16;
+               rxlen = (rxh >> 16) & 0xfff;
 
                netif_dbg(ks, rx_status, ks->netdev,
                          "rx: stat 0x%04x, len 0x%04x\n", rxstat, rxlen);
index cd5ae8813cb3967537bc047a475db69329993736..edd63f1230f3d0076f9bfbdcff146f62a6c2acaa 100644 (file)
@@ -1500,6 +1500,12 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
                }
        } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
 
+       /* Make sure carrier is off and queue is stopped during loopback */
+       if (netif_running(netdev)) {
+               netif_carrier_off(netdev);
+               netif_stop_queue(netdev);
+       }
+
        ret = qlcnic_do_lb_test(adapter, mode);
 
        qlcnic_83xx_clear_lb_mode(adapter, mode);
@@ -2780,6 +2786,7 @@ static u64 *qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter,
 void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data)
 {
        struct qlcnic_cmd_args cmd;
+       struct net_device *netdev = adapter->netdev;
        int ret = 0;
 
        qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS);
@@ -2789,7 +2796,7 @@ void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data)
        data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
                                      QLC_83XX_STAT_TX, &ret);
        if (ret) {
-               dev_info(&adapter->pdev->dev, "Error getting MAC stats\n");
+               netdev_err(netdev, "Error getting Tx stats\n");
                goto out;
        }
        /* Get MAC stats */
@@ -2799,8 +2806,7 @@ void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data)
        data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
                                      QLC_83XX_STAT_MAC, &ret);
        if (ret) {
-               dev_info(&adapter->pdev->dev,
-                        "Error getting Rx stats\n");
+               netdev_err(netdev, "Error getting MAC stats\n");
                goto out;
        }
        /* Get Rx stats */
@@ -2810,8 +2816,7 @@ void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data)
        data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
                                      QLC_83XX_STAT_RX, &ret);
        if (ret)
-               dev_info(&adapter->pdev->dev,
-                        "Error getting Tx stats\n");
+               netdev_err(netdev, "Error getting Rx stats\n");
 out:
        qlcnic_free_mbx_args(&cmd);
 }
index 0e630061bff31b41192d4b8fc7978e2be839e274..5fa847fe388a9df3b7f78b44b63f72bffaaeeced 100644 (file)
@@ -358,8 +358,7 @@ set_flags:
                memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
        }
        opcode = TX_ETHER_PKT;
-       if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
-           skb_shinfo(skb)->gso_size > 0) {
+       if (skb_is_gso(skb)) {
                hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
                first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
                first_desc->total_hdr_length = hdr_len;
index 987fb6f8adc3b34a1089b9e44de928de5fba0119..5ef328af61d0ab9fcbc1c098b323f444fbd63854 100644 (file)
@@ -200,10 +200,10 @@ beacon_err:
        }
 
        err = qlcnic_config_led(adapter, b_state, b_rate);
-       if (!err)
+       if (!err) {
                err = len;
-       else
                ahw->beacon_state = b_state;
+       }
 
        if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
                qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
index a131d7b5d2fe00e1f96997bef8f8afa54186aaa5..7e8d68263963aa5928f5ef1f145ad27624c14ce2 100644 (file)
@@ -18,7 +18,7 @@
  */
 #define DRV_NAME       "qlge"
 #define DRV_STRING     "QLogic 10 Gigabit PCI-E Ethernet Driver "
-#define DRV_VERSION    "v1.00.00.31"
+#define DRV_VERSION    "v1.00.00.32"
 
 #define WQ_ADDR_ALIGN  0x3     /* 4 byte alignment */
 
index 6f316ab23257dc7343776d92db05cc471561d681..0780e039b2718d902805414daeb6844b7d2086e7 100644 (file)
@@ -379,13 +379,13 @@ static int ql_get_settings(struct net_device *ndev,
 
        ecmd->supported = SUPPORTED_10000baseT_Full;
        ecmd->advertising = ADVERTISED_10000baseT_Full;
-       ecmd->autoneg = AUTONEG_ENABLE;
        ecmd->transceiver = XCVR_EXTERNAL;
        if ((qdev->link_status & STS_LINK_TYPE_MASK) ==
                                STS_LINK_TYPE_10GBASET) {
                ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
                ecmd->advertising |= (ADVERTISED_TP | ADVERTISED_Autoneg);
                ecmd->port = PORT_TP;
+               ecmd->autoneg = AUTONEG_ENABLE;
        } else {
                ecmd->supported |= SUPPORTED_FIBRE;
                ecmd->advertising |= ADVERTISED_FIBRE;
index b13ab544a7eb56760063474b598163227f27942f..8033555e53c2f6f524211b4d848dcc13a0e14f78 100644 (file)
@@ -1434,11 +1434,13 @@ map_error:
 }
 
 /* Categorizing receive firmware frame errors */
-static void ql_categorize_rx_err(struct ql_adapter *qdev, u8 rx_err)
+static void ql_categorize_rx_err(struct ql_adapter *qdev, u8 rx_err,
+                                struct rx_ring *rx_ring)
 {
        struct nic_stats *stats = &qdev->nic_stats;
 
        stats->rx_err_count++;
+       rx_ring->rx_errors++;
 
        switch (rx_err & IB_MAC_IOCB_RSP_ERR_MASK) {
        case IB_MAC_IOCB_RSP_ERR_CODE_ERR:
@@ -1474,6 +1476,12 @@ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev,
        struct bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring);
        struct napi_struct *napi = &rx_ring->napi;
 
+       /* Frame error, so drop the packet. */
+       if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
+               ql_categorize_rx_err(qdev, ib_mac_rsp->flags2, rx_ring);
+               put_page(lbq_desc->p.pg_chunk.page);
+               return;
+       }
        napi->dev = qdev->ndev;
 
        skb = napi_get_frags(napi);
@@ -1529,6 +1537,12 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,
        addr = lbq_desc->p.pg_chunk.va;
        prefetch(addr);
 
+       /* Frame error, so drop the packet. */
+       if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
+               ql_categorize_rx_err(qdev, ib_mac_rsp->flags2, rx_ring);
+               goto err_out;
+       }
+
        /* The max framesize filter on this chip is set higher than
         * MTU since FCoE uses 2k frames.
         */
@@ -1614,6 +1628,13 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev,
        memcpy(skb_put(new_skb, length), skb->data, length);
        skb = new_skb;
 
+       /* Frame error, so drop the packet. */
+       if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
+               ql_categorize_rx_err(qdev, ib_mac_rsp->flags2, rx_ring);
+               dev_kfree_skb_any(skb);
+               return;
+       }
+
        /* loopback self test for ethtool */
        if (test_bit(QL_SELFTEST, &qdev->flags)) {
                ql_check_lb_frame(qdev, skb);
@@ -1919,6 +1940,13 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev,
                return;
        }
 
+       /* Frame error, so drop the packet. */
+       if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
+               ql_categorize_rx_err(qdev, ib_mac_rsp->flags2, rx_ring);
+               dev_kfree_skb_any(skb);
+               return;
+       }
+
        /* The max framesize filter on this chip is set higher than
         * MTU since FCoE uses 2k frames.
         */
@@ -2000,12 +2028,6 @@ static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev,
 
        QL_DUMP_IB_MAC_RSP(ib_mac_rsp);
 
-       /* Frame error, so drop the packet. */
-       if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
-               ql_categorize_rx_err(qdev, ib_mac_rsp->flags2);
-               return (unsigned long)length;
-       }
-
        if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) {
                /* The data and headers are split into
                 * separate buffers.
index 28fb50a1e9c350851b3844592bf85adea877f604..4ecbe64a758d8b05dd5a016a9659b20bfdfb90c5 100644 (file)
@@ -3818,6 +3818,30 @@ static void rtl_init_mdio_ops(struct rtl8169_private *tp)
        }
 }
 
+static void rtl_speed_down(struct rtl8169_private *tp)
+{
+       u32 adv;
+       int lpa;
+
+       rtl_writephy(tp, 0x1f, 0x0000);
+       lpa = rtl_readphy(tp, MII_LPA);
+
+       if (lpa & (LPA_10HALF | LPA_10FULL))
+               adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full;
+       else if (lpa & (LPA_100HALF | LPA_100FULL))
+               adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+                     ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
+       else
+               adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+                     ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+                     (tp->mii.supports_gmii ?
+                      ADVERTISED_1000baseT_Half |
+                      ADVERTISED_1000baseT_Full : 0);
+
+       rtl8169_set_speed(tp->dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
+                         adv);
+}
+
 static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
 {
        void __iomem *ioaddr = tp->mmio_addr;
@@ -3848,9 +3872,7 @@ static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
        if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
                return false;
 
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_writephy(tp, MII_BMCR, 0x0000);
-
+       rtl_speed_down(tp);
        rtl_wol_suspend_quirk(tp);
 
        return true;
index bf5e3cf97c4d89d55b92b66a46ee37787acb934c..6ed333fe5c04cd36618c465c0a3bec8dafbe8fcc 100644 (file)
@@ -1216,10 +1216,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
                if (felic_stat & ECSR_LCHNG) {
                        /* Link Changed */
                        if (mdp->cd->no_psr || mdp->no_ether_link) {
-                               if (mdp->link == PHY_DOWN)
-                                       link_stat = 0;
-                               else
-                                       link_stat = PHY_ST_LINK;
+                               goto ignore_link;
                        } else {
                                link_stat = (sh_eth_read(ndev, PSR));
                                if (mdp->ether_link_active_low)
@@ -1242,6 +1239,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
                }
        }
 
+ignore_link:
        if (intr_status & EESR_TWB) {
                /* Write buck end. unused write back interrupt */
                if (intr_status & EESR_TABT)    /* Transmit Abort int */
@@ -1326,12 +1324,18 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
        struct sh_eth_private *mdp = netdev_priv(ndev);
        struct sh_eth_cpu_data *cd = mdp->cd;
        irqreturn_t ret = IRQ_NONE;
-       u32 intr_status = 0;
+       unsigned long intr_status;
 
        spin_lock(&mdp->lock);
 
-       /* Get interrpt stat */
+       /* Get interrupt status */
        intr_status = sh_eth_read(ndev, EESR);
+       /* Mask it with the interrupt mask, forcing ECI interrupt to be always
+        * enabled since it's the one that  comes thru regardless of the mask,
+        * and we need to fully handle it in sh_eth_error() in order to quench
+        * it as it doesn't get cleared by just writing 1 to the ECI bit...
+        */
+       intr_status &= sh_eth_read(ndev, EESIPR) | DMAC_M_ECI;
        /* Clear interrupt */
        if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
                        EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
@@ -1373,7 +1377,7 @@ static void sh_eth_adjust_link(struct net_device *ndev)
        struct phy_device *phydev = mdp->phydev;
        int new_state = 0;
 
-       if (phydev->link != PHY_DOWN) {
+       if (phydev->link) {
                if (phydev->duplex != mdp->duplex) {
                        new_state = 1;
                        mdp->duplex = phydev->duplex;
@@ -1387,17 +1391,21 @@ static void sh_eth_adjust_link(struct net_device *ndev)
                        if (mdp->cd->set_rate)
                                mdp->cd->set_rate(ndev);
                }
-               if (mdp->link == PHY_DOWN) {
+               if (!mdp->link) {
                        sh_eth_write(ndev,
                                (sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR);
                        new_state = 1;
                        mdp->link = phydev->link;
+                       if (mdp->cd->no_psr || mdp->no_ether_link)
+                               sh_eth_rcv_snd_enable(ndev);
                }
        } else if (mdp->link) {
                new_state = 1;
-               mdp->link = PHY_DOWN;
+               mdp->link = 0;
                mdp->speed = 0;
                mdp->duplex = -1;
+               if (mdp->cd->no_psr || mdp->no_ether_link)
+                       sh_eth_rcv_snd_disable(ndev);
        }
 
        if (new_state && netif_msg_link(mdp))
@@ -1414,7 +1422,7 @@ static int sh_eth_phy_init(struct net_device *ndev)
        snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
                mdp->mii_bus->id , mdp->phy_id);
 
-       mdp->link = PHY_DOWN;
+       mdp->link = 0;
        mdp->speed = 0;
        mdp->duplex = -1;
 
index e6655678458e5984fee032c6593e719a631d9c42..828be4515008145507f59a5bbe34ac64eb28090b 100644 (file)
@@ -723,7 +723,7 @@ struct sh_eth_private {
        u32 phy_id;                                     /* PHY ID */
        struct mii_bus *mii_bus;        /* MDIO bus control */
        struct phy_device *phydev;      /* PHY device control */
-       enum phy_state link;
+       int link;
        phy_interface_t phy_interface;
        int msg_enable;
        int speed;
index 0c74a702d4610597da59200be253306c7b4db534..50617c5a0bdb5e63fc930f7af277a1a9fb139af4 100644 (file)
@@ -149,6 +149,7 @@ void dwmac_mmc_intr_all_mask(void __iomem *ioaddr)
 {
        writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK);
        writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK);
+       writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_IPC_INTR_MASK);
 }
 
 /* This reads the MAC core counters (if actaully supported).
index df32a090d08e0c96841a9958b1c1319eb6cbbc19..4781d3d8e18204ad7fc11d06d102fd2eb6829da4 100644 (file)
@@ -436,7 +436,7 @@ void cpsw_tx_handler(void *token, int len, int status)
         * queue is stopped then start the queue as we have free desc for tx
         */
        if (unlikely(netif_queue_stopped(ndev)))
-               netif_start_queue(ndev);
+               netif_wake_queue(ndev);
        cpts_tx_timestamp(priv->cpts, skb);
        priv->stats.tx_packets++;
        priv->stats.tx_bytes += len;
@@ -1380,7 +1380,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                        memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
 
                if (data->dual_emac) {
-                       if (of_property_read_u32(node, "dual_emac_res_vlan",
+                       if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
                                                 &prop)) {
                                pr_err("Missing dual_emac_res_vlan in DT.\n");
                                slave_data->dual_emac_res_vlan = i+1;
index ae1b77aa199f87ab947c185b552d9274266dac91..72300bc9e3783842ef3608be24f0f33d2ed0f69b 100644 (file)
@@ -1053,7 +1053,7 @@ static void emac_tx_handler(void *token, int len, int status)
         * queue is stopped then start the queue as we have free desc for tx
         */
        if (unlikely(netif_queue_stopped(ndev)))
-               netif_start_queue(ndev);
+               netif_wake_queue(ndev);
        ndev->stats.tx_packets++;
        ndev->stats.tx_bytes += len;
        dev_kfree_skb_any(skb);
index 1cd77483da50114c2c309ab70a69dff134c3a919..f5f0f09e4cc5e2160a9fc40c8fad83b5ab295287 100644 (file)
@@ -470,8 +470,10 @@ static void netvsc_send_completion(struct hv_device *device,
                        packet->trans_id;
 
                /* Notify the layer above us */
-               nvsc_packet->completion.send.send_completion(
-                       nvsc_packet->completion.send.send_completion_ctx);
+               if (nvsc_packet)
+                       nvsc_packet->completion.send.send_completion(
+                               nvsc_packet->completion.send.
+                               send_completion_ctx);
 
                num_outstanding_sends =
                        atomic_dec_return(&net_device->num_outstanding_sends);
@@ -498,6 +500,7 @@ int netvsc_send(struct hv_device *device,
        int ret = 0;
        struct nvsp_message sendMessage;
        struct net_device *ndev;
+       u64 req_id;
 
        net_device = get_outbound_net_device(device);
        if (!net_device)
@@ -518,20 +521,24 @@ int netvsc_send(struct hv_device *device,
                0xFFFFFFFF;
        sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0;
 
+       if (packet->completion.send.send_completion)
+               req_id = (u64)packet;
+       else
+               req_id = 0;
+
        if (packet->page_buf_cnt) {
                ret = vmbus_sendpacket_pagebuffer(device->channel,
                                                  packet->page_buf,
                                                  packet->page_buf_cnt,
                                                  &sendMessage,
                                                  sizeof(struct nvsp_message),
-                                                 (unsigned long)packet);
+                                                 req_id);
        } else {
                ret = vmbus_sendpacket(device->channel, &sendMessage,
                                sizeof(struct nvsp_message),
-                               (unsigned long)packet,
+                               req_id,
                                VM_PKT_DATA_INBAND,
                                VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
        }
 
        if (ret == 0) {
index 5f85205cd12b81284ba7f23dfc89aa7ef50d3c10..8341b62e552166a4f796f7977b6f31a2b945bcdd 100644 (file)
@@ -241,13 +241,11 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
 
        if (status == 1) {
                netif_carrier_on(net);
-               netif_wake_queue(net);
                ndev_ctx = netdev_priv(net);
                schedule_delayed_work(&ndev_ctx->dwork, 0);
                schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
        } else {
                netif_carrier_off(net);
-               netif_tx_disable(net);
        }
 }
 
index 2b657d4d63a8cc86950db8f50c805c3f96e017d1..0775f0aefd1e67715ab77750ac898660d3ca6267 100644 (file)
@@ -61,9 +61,6 @@ struct rndis_request {
 
 static void rndis_filter_send_completion(void *ctx);
 
-static void rndis_filter_send_request_completion(void *ctx);
-
-
 
 static struct rndis_device *get_rndis_device(void)
 {
@@ -241,10 +238,7 @@ static int rndis_filter_send_request(struct rndis_device *dev,
                        packet->page_buf[0].len;
        }
 
-       packet->completion.send.send_completion_ctx = req;/* packet; */
-       packet->completion.send.send_completion =
-               rndis_filter_send_request_completion;
-       packet->completion.send.send_completion_tid = (unsigned long)dev;
+       packet->completion.send.send_completion = NULL;
 
        ret = netvsc_send(dev->net_dev->dev, packet);
        return ret;
@@ -999,9 +993,3 @@ static void rndis_filter_send_completion(void *ctx)
        /* Pass it back to the original handler */
        filter_pkt->completion(filter_pkt->completion_ctx);
 }
-
-
-static void rndis_filter_send_request_completion(void *ctx)
-{
-       /* Noop */
-}
index b7c457adc0dc7439cc2a842409ed3871207f079b..729ed533bb33834fac05825be4b344a755e0e859 100644 (file)
@@ -1594,7 +1594,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
                if (tun->flags & TUN_TAP_MQ &&
                    (tun->numqueues + tun->numdisabled > 1))
-                       return err;
+                       return -EBUSY;
        }
        else {
                char *name;
index 16c842997291483eb12306d9ccf0a638772f18f0..6bd91676d2cbb9a46b43108ae1fa994d4fca84f9 100644 (file)
@@ -134,7 +134,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
                goto error;
 
        if (skb) {
-               if (skb->len <= sizeof(ETH_HLEN))
+               if (skb->len <= ETH_HLEN)
                        goto error;
 
                /* mapping VLANs to MBIM sessions:
index 968d5d50751dc120b406f54fffca49b46eafa230..2a3579f679103da7864260f114f98419852eaecd 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
+#include <linux/etherdevice.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
 #include <linux/usb/cdc.h>
@@ -52,6 +53,96 @@ struct qmi_wwan_state {
        struct usb_interface *data;
 };
 
+/* default ethernet address used by the modem */
+static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3};
+
+/* Make up an ethernet header if the packet doesn't have one.
+ *
+ * A firmware bug common among several devices cause them to send raw
+ * IP packets under some circumstances.  There is no way for the
+ * driver/host to know when this will happen.  And even when the bug
+ * hits, some packets will still arrive with an intact header.
+ *
+ * The supported devices are only capably of sending IPv4, IPv6 and
+ * ARP packets on a point-to-point link. Any packet with an ethernet
+ * header will have either our address or a broadcast/multicast
+ * address as destination.  ARP packets will always have a header.
+ *
+ * This means that this function will reliably add the appropriate
+ * header iff necessary, provided our hardware address does not start
+ * with 4 or 6.
+ *
+ * Another common firmware bug results in all packets being addressed
+ * to 00:a0:c6:00:00:00 despite the host address being different.
+ * This function will also fixup such packets.
+ */
+static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+       __be16 proto;
+
+       /* usbnet rx_complete guarantees that skb->len is at least
+        * hard_header_len, so we can inspect the dest address without
+        * checking skb->len
+        */
+       switch (skb->data[0] & 0xf0) {
+       case 0x40:
+               proto = htons(ETH_P_IP);
+               break;
+       case 0x60:
+               proto = htons(ETH_P_IPV6);
+               break;
+       case 0x00:
+               if (is_multicast_ether_addr(skb->data))
+                       return 1;
+               /* possibly bogus destination - rewrite just in case */
+               skb_reset_mac_header(skb);
+               goto fix_dest;
+       default:
+               /* pass along other packets without modifications */
+               return 1;
+       }
+       if (skb_headroom(skb) < ETH_HLEN)
+               return 0;
+       skb_push(skb, ETH_HLEN);
+       skb_reset_mac_header(skb);
+       eth_hdr(skb)->h_proto = proto;
+       memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
+fix_dest:
+       memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
+       return 1;
+}
+
+/* very simplistic detection of IPv4 or IPv6 headers */
+static bool possibly_iphdr(const char *data)
+{
+       return (data[0] & 0xd0) == 0x40;
+}
+
+/* disallow addresses which may be confused with IP headers */
+static int qmi_wwan_mac_addr(struct net_device *dev, void *p)
+{
+       int ret;
+       struct sockaddr *addr = p;
+
+       ret = eth_prepare_mac_addr_change(dev, p);
+       if (ret < 0)
+               return ret;
+       if (possibly_iphdr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+       eth_commit_mac_addr_change(dev, p);
+       return 0;
+}
+
+static const struct net_device_ops qmi_wwan_netdev_ops = {
+       .ndo_open               = usbnet_open,
+       .ndo_stop               = usbnet_stop,
+       .ndo_start_xmit         = usbnet_start_xmit,
+       .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_set_mac_address    = qmi_wwan_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
 /* using a counter to merge subdriver requests with our own into a combined state */
 static int qmi_wwan_manage_power(struct usbnet *dev, int on)
 {
@@ -229,6 +320,18 @@ next_desc:
                usb_driver_release_interface(driver, info->data);
        }
 
+       /* Never use the same address on both ends of the link, even
+        * if the buggy firmware told us to.
+        */
+       if (!compare_ether_addr(dev->net->dev_addr, default_modem_addr))
+               eth_hw_addr_random(dev->net);
+
+       /* make MAC addr easily distinguishable from an IP header */
+       if (possibly_iphdr(dev->net->dev_addr)) {
+               dev->net->dev_addr[0] |= 0x02;  /* set local assignment bit */
+               dev->net->dev_addr[0] &= 0xbf;  /* clear "IP" bit */
+       }
+       dev->net->netdev_ops = &qmi_wwan_netdev_ops;
 err:
        return status;
 }
@@ -307,6 +410,7 @@ static const struct driver_info     qmi_wwan_info = {
        .bind           = qmi_wwan_bind,
        .unbind         = qmi_wwan_unbind,
        .manage_power   = qmi_wwan_manage_power,
+       .rx_fixup       = qmi_wwan_rx_fixup,
 };
 
 #define HUAWEI_VENDOR_ID       0x12D1
index 9abe51710f229377cb9f405ffedb198eab580738..1a15ec14c386f3c4e05808722bd84a196d82f3a8 100644 (file)
@@ -914,8 +914,12 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
 static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct usbnet *dev = netdev_priv(netdev);
+       int ret;
+
+       if (new_mtu > MAX_SINGLE_PACKET_SIZE)
+               return -EINVAL;
 
-       int ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu);
+       ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN);
        if (ret < 0) {
                netdev_warn(dev->net, "Failed to set mac rx frame length\n");
                return ret;
@@ -1324,7 +1328,7 @@ static int smsc75xx_reset(struct usbnet *dev)
 
        netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x\n", buf);
 
-       ret = smsc75xx_set_rx_max_frame_length(dev, 1514);
+       ret = smsc75xx_set_rx_max_frame_length(dev, dev->net->mtu + ETH_HLEN);
        if (ret < 0) {
                netdev_warn(dev->net, "Failed to set max rx frame length\n");
                return ret;
@@ -2134,8 +2138,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                        else if (rx_cmd_a & (RX_CMD_A_LONG | RX_CMD_A_RUNT))
                                dev->net->stats.rx_frame_errors++;
                } else {
-                       /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
-                       if (unlikely(size > (ETH_FRAME_LEN + 12))) {
+                       /* MAX_SINGLE_PACKET_SIZE + 4(CRC) + 2(COE) + 4(Vlan) */
+                       if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12))) {
                                netif_dbg(dev, rx_err, dev->net,
                                          "size err rx_cmd_a=0x%08x\n",
                                          rx_cmd_a);
index 28fd99203f6447e4d3545b0fd12b920733ffc10c..bdee2ed67219b6e1c56a0f03a6a28391ba3283aa 100644 (file)
@@ -519,7 +519,7 @@ static const u32 ar9580_1p0_mac_core[][2] = {
        {0x00008258, 0x00000000},
        {0x0000825c, 0x40000000},
        {0x00008260, 0x00080922},
-       {0x00008264, 0x9bc00010},
+       {0x00008264, 0x9d400010},
        {0x00008268, 0xffffffff},
        {0x0000826c, 0x0000ffff},
        {0x00008270, 0x00000000},
index 467b60014b7b73720b25440c584ae9a49c968bcc..73fe8d6db566789ad2c6f34021d607c48a380855 100644 (file)
@@ -143,14 +143,14 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
        u32 sz, i;
        struct channel_detector *cd;
 
-       cd = kmalloc(sizeof(*cd), GFP_KERNEL);
+       cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
        if (cd == NULL)
                goto fail;
 
        INIT_LIST_HEAD(&cd->head);
        cd->freq = freq;
        sz = sizeof(cd->detectors) * dpd->num_radar_types;
-       cd->detectors = kzalloc(sz, GFP_KERNEL);
+       cd->detectors = kzalloc(sz, GFP_ATOMIC);
        if (cd->detectors == NULL)
                goto fail;
 
index 91b8dceeadb10ef6c9f84d20f4a5bba6cd1500dd..5e48c5515b8ccc0b59fac41844fd4a0a7c41883e 100644 (file)
@@ -218,7 +218,7 @@ static bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts)
 {
        struct pulse_elem *p = pool_get_pulse_elem();
        if (p == NULL) {
-               p = kmalloc(sizeof(*p), GFP_KERNEL);
+               p = kmalloc(sizeof(*p), GFP_ATOMIC);
                if (p == NULL) {
                        DFS_POOL_STAT_INC(pulse_alloc_error);
                        return false;
@@ -299,7 +299,7 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde,
                ps.deadline_ts = ps.first_ts + ps.dur;
                new_ps = pool_get_pseq_elem();
                if (new_ps == NULL) {
-                       new_ps = kmalloc(sizeof(*new_ps), GFP_KERNEL);
+                       new_ps = kmalloc(sizeof(*new_ps), GFP_ATOMIC);
                        if (new_ps == NULL) {
                                DFS_POOL_STAT_INC(pseq_alloc_error);
                                return false;
index 716058b675571b32c6693656dafeb567868b25cb..a47f5e05fc04835d6b747b8ba4553c91d6614178 100644 (file)
@@ -796,7 +796,7 @@ static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
         * required version.
         */
        if (priv->fw_version_major != MAJOR_VERSION_REQ ||
-           priv->fw_version_minor != MINOR_VERSION_REQ) {
+           priv->fw_version_minor < MINOR_VERSION_REQ) {
                dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
                        MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
                return -EINVAL;
index 39c84ecf6a42b345dc67d9cb52c7d3b45957525a..7fdac6c7b3ea5dc030136d66c4574c4d8373a82e 100644 (file)
@@ -170,7 +170,8 @@ void ath_rx_poll(unsigned long data)
 {
        struct ath_softc *sc = (struct ath_softc *)data;
 
-       ieee80211_queue_work(sc->hw, &sc->hw_check_work);
+       if (!test_bit(SC_OP_INVALID, &sc->sc_flags))
+               ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 }
 
 /*
index 6e66f9c6782b966ac249b4bd31ecc25e6a9456b2..988372d218a4dd24015a1b19d104839fab8f0080 100644 (file)
@@ -280,6 +280,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
        if (r) {
                ath_err(common,
                        "Unable to reset channel, reset status %d\n", r);
+
+               ath9k_hw_enable_interrupts(ah);
+               ath9k_queue_reset(sc, RESET_TYPE_BB_HANG);
+
                goto out;
        }
 
index 38bc5a7997ffd43b9a8c8f45a6329fe4ffdac5c1..122146943bf204693b540b124f6c947bec34833b 100644 (file)
@@ -1487,8 +1487,12 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
        const struct b43_dma_ops *ops;
        struct b43_dmaring *ring;
        struct b43_dmadesc_meta *meta;
+       static const struct b43_txstatus fake; /* filled with 0 */
+       const struct b43_txstatus *txstat;
        int slot, firstused;
        bool frame_succeed;
+       int skip;
+       static u8 err_out1, err_out2;
 
        ring = parse_cookie(dev, status->cookie, &slot);
        if (unlikely(!ring))
@@ -1501,13 +1505,36 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
        firstused = ring->current_slot - ring->used_slots + 1;
        if (firstused < 0)
                firstused = ring->nr_slots + firstused;
+
+       skip = 0;
        if (unlikely(slot != firstused)) {
                /* This possibly is a firmware bug and will result in
-                * malfunction, memory leaks and/or stall of DMA functionality. */
-               b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. "
-                      "Expected %d, but got %d\n",
-                      ring->index, firstused, slot);
-               return;
+                * malfunction, memory leaks and/or stall of DMA functionality.
+                */
+               if (slot == next_slot(ring, next_slot(ring, firstused))) {
+                       /* If a single header/data pair was missed, skip over
+                        * the first two slots in an attempt to recover.
+                        */
+                       slot = firstused;
+                       skip = 2;
+                       if (!err_out1) {
+                               /* Report the error once. */
+                               b43dbg(dev->wl,
+                                      "Skip on DMA ring %d slot %d.\n",
+                                      ring->index, slot);
+                               err_out1 = 1;
+                       }
+               } else {
+                       /* More than a single header/data pair were missed.
+                        * Report this error once.
+                        */
+                       if (!err_out2)
+                               b43dbg(dev->wl,
+                                      "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n",
+                                      ring->index, firstused, slot);
+                       err_out2 = 1;
+                       return;
+               }
        }
 
        ops = ring->ops;
@@ -1522,11 +1549,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
                               slot, firstused, ring->index);
                        break;
                }
+
                if (meta->skb) {
                        struct b43_private_tx_info *priv_info =
-                               b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
+                            b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
 
-                       unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+                       unmap_descbuffer(ring, meta->dmaaddr,
+                                        meta->skb->len, 1);
                        kfree(priv_info->bouncebuffer);
                        priv_info->bouncebuffer = NULL;
                } else {
@@ -1538,8 +1567,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
                        struct ieee80211_tx_info *info;
 
                        if (unlikely(!meta->skb)) {
-                               /* This is a scatter-gather fragment of a frame, so
-                                * the skb pointer must not be NULL. */
+                               /* This is a scatter-gather fragment of a frame,
+                                * so the skb pointer must not be NULL.
+                                */
                                b43dbg(dev->wl, "TX status unexpected NULL skb "
                                       "at slot %d (first=%d) on ring %d\n",
                                       slot, firstused, ring->index);
@@ -1550,9 +1580,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 
                        /*
                         * Call back to inform the ieee80211 subsystem about
-                        * the status of the transmission.
+                        * the status of the transmission. When skipping over
+                        * a missed TX status report, use a status structure
+                        * filled with zeros to indicate that the frame was not
+                        * sent (frame_count 0) and not acknowledged
                         */
-                       frame_succeed = b43_fill_txstatus_report(dev, info, status);
+                       if (unlikely(skip))
+                               txstat = &fake;
+                       else
+                               txstat = status;
+
+                       frame_succeed = b43_fill_txstatus_report(dev, info,
+                                                                txstat);
 #ifdef CONFIG_B43_DEBUG
                        if (frame_succeed)
                                ring->nr_succeed_tx_packets++;
@@ -1580,12 +1619,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
                /* Everything unmapped and free'd. So it's not used anymore. */
                ring->used_slots--;
 
-               if (meta->is_last_fragment) {
+               if (meta->is_last_fragment && !skip) {
                        /* This is the last scatter-gather
                         * fragment of the frame. We are done. */
                        break;
                }
                slot = next_slot(ring, slot);
+               if (skip > 0)
+                       --skip;
        }
        if (ring->stopped) {
                B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
index 3c35382ee6c23ebfbaed8d1dcfdf33e804faec96..b70f220bc4b378e626a59752fca5bce965456340 100644 (file)
@@ -1564,7 +1564,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
        u16 clip_off[2] = { 0xFFFF, 0xFFFF };
 
        u8 vcm_final = 0;
-       s8 offset[4];
+       s32 offset[4];
        s32 results[8][4] = { };
        s32 results_min[4] = { };
        s32 poll_results[4] = { };
@@ -1615,7 +1615,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
                }
                for (i = 0; i < 4; i += 2) {
                        s32 curr;
-                       s32 mind = 40;
+                       s32 mind = 0x100000;
                        s32 minpoll = 249;
                        u8 minvcm = 0;
                        if (2 * core != i)
@@ -1732,7 +1732,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
        u8 regs_save_radio[2];
        u16 regs_save_phy[2];
 
-       s8 offset[4];
+       s32 offset[4];
        u8 core;
        u8 rail;
 
@@ -1799,7 +1799,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
        }
 
        for (i = 0; i < 4; i++) {
-               s32 mind = 40;
+               s32 mind = 0x100000;
                u8 minvcm = 0;
                s32 minpoll = 249;
                s32 curr;
@@ -5165,7 +5165,8 @@ static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
 #endif
 #ifdef CONFIG_B43_SSB
        case B43_BUS_SSB:
-               /* FIXME */
+               ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,
+                                           avoid);
                break;
 #endif
        }
index 4469321c0eb3ea3924f68b02ff6863516ec9b333..35fc68be158d5b548e5c273ee85f7e3bf057a162 100644 (file)
@@ -3317,15 +3317,15 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
                goto err;
        }
 
-       /* External image takes precedence if specified */
        if (brcmf_sdbrcm_download_code_file(bus)) {
                brcmf_err("dongle image file download failed\n");
                goto err;
        }
 
-       /* External nvram takes precedence if specified */
-       if (brcmf_sdbrcm_download_nvram(bus))
+       if (brcmf_sdbrcm_download_nvram(bus)) {
                brcmf_err("dongle nvram file download failed\n");
+               goto err;
+       }
 
        /* Take arm out of reset */
        if (brcmf_sdbrcm_download_state(bus, false)) {
index 2af9c0f0798d9e5cc2e484b0599a7d50aede68e5..78da3eff75e8a1c5c126a60aab7bc90d7663a314 100644 (file)
@@ -1891,8 +1891,10 @@ static s32
 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
              u8 key_idx, const u8 *mac_addr, struct key_params *params)
 {
+       struct brcmf_if *ifp = netdev_priv(ndev);
        struct brcmf_wsec_key key;
        s32 err = 0;
+       u8 keybuf[8];
 
        memset(&key, 0, sizeof(key));
        key.index = (u32) key_idx;
@@ -1916,8 +1918,9 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
                brcmf_dbg(CONN, "Setting the key index %d\n", key.index);
                memcpy(key.data, params->key, key.len);
 
-               if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
-                       u8 keybuf[8];
+               if ((ifp->vif->mode != WL_MODE_AP) &&
+                   (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
+                       brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
                        memcpy(keybuf, &key.data[24], sizeof(keybuf));
                        memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
                        memcpy(&key.data[16], keybuf, sizeof(keybuf));
@@ -2013,7 +2016,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                break;
        case WLAN_CIPHER_SUITE_TKIP:
                if (ifp->vif->mode != WL_MODE_AP) {
-                       brcmf_dbg(CONN, "Swapping key\n");
+                       brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
                        memcpy(keybuf, &key.data[24], sizeof(keybuf));
                        memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
                        memcpy(&key.data[16], keybuf, sizeof(keybuf));
@@ -2118,8 +2121,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
                err = -EAGAIN;
                goto done;
        }
-       switch (wsec & ~SES_OW_ENABLED) {
-       case WEP_ENABLED:
+       if (wsec & WEP_ENABLED) {
                sec = &profile->sec;
                if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
                        params.cipher = WLAN_CIPHER_SUITE_WEP40;
@@ -2128,16 +2130,13 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
                        params.cipher = WLAN_CIPHER_SUITE_WEP104;
                        brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
                }
-               break;
-       case TKIP_ENABLED:
+       } else if (wsec & TKIP_ENABLED) {
                params.cipher = WLAN_CIPHER_SUITE_TKIP;
                brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
-               break;
-       case AES_ENABLED:
+       } else if (wsec & AES_ENABLED) {
                params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
                brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
-               break;
-       default:
+       } else  {
                brcmf_err("Invalid algo (0x%x)\n", wsec);
                err = -EINVAL;
                goto done;
@@ -3824,8 +3823,9 @@ exit:
 static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       s32 err = -EPERM;
+       s32 err;
        struct brcmf_fil_bss_enable_le bss_enable;
+       struct brcmf_join_params join_params;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -3833,16 +3833,21 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
                /* Due to most likely deauths outstanding we sleep */
                /* first to make sure they get processed by fw. */
                msleep(400);
-               err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
-               if (err < 0) {
-                       brcmf_err("setting AP mode failed %d\n", err);
-                       goto exit;
-               }
+
+               memset(&join_params, 0, sizeof(join_params));
+               err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+                                            &join_params, sizeof(join_params));
+               if (err < 0)
+                       brcmf_err("SET SSID error (%d)\n", err);
                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
-               if (err < 0) {
+               if (err < 0)
                        brcmf_err("BRCMF_C_UP error %d\n", err);
-                       goto exit;
-               }
+               err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
+               if (err < 0)
+                       brcmf_err("setting AP mode failed %d\n", err);
+               err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0);
+               if (err < 0)
+                       brcmf_err("setting INFRA mode failed %d\n", err);
        } else {
                bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
                bss_enable.enable = cpu_to_le32(0);
@@ -3855,7 +3860,6 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
        set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
        clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
 
-exit:
        return err;
 }
 
@@ -4122,10 +4126,6 @@ static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
                         BIT(NL80211_IFTYPE_ADHOC) |
                         BIT(NL80211_IFTYPE_AP)
        },
-       {
-               .max = 1,
-               .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
-       },
        {
                .max = 1,
                .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
@@ -4183,8 +4183,7 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
                                 BIT(NL80211_IFTYPE_ADHOC) |
                                 BIT(NL80211_IFTYPE_AP) |
                                 BIT(NL80211_IFTYPE_P2P_CLIENT) |
-                                BIT(NL80211_IFTYPE_P2P_GO) |
-                                BIT(NL80211_IFTYPE_P2P_DEVICE);
+                                BIT(NL80211_IFTYPE_P2P_GO);
        wiphy->iface_combinations = brcmf_iface_combos;
        wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
        wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
index c6451c61407a8c4510c97056bde23ef1ee88c060..e2340b231aa163cfba03f8b8f90c0822003a385d 100644 (file)
@@ -274,6 +274,130 @@ static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br)
        }
 }
 
+/**
+ * This function frees the WL per-device resources.
+ *
+ * This function frees resources owned by the WL device pointed to
+ * by the wl parameter.
+ *
+ * precondition: can both be called locked and unlocked
+ *
+ */
+static void brcms_free(struct brcms_info *wl)
+{
+       struct brcms_timer *t, *next;
+
+       /* free ucode data */
+       if (wl->fw.fw_cnt)
+               brcms_ucode_data_free(&wl->ucode);
+       if (wl->irq)
+               free_irq(wl->irq, wl);
+
+       /* kill dpc */
+       tasklet_kill(&wl->tasklet);
+
+       if (wl->pub) {
+               brcms_debugfs_detach(wl->pub);
+               brcms_c_module_unregister(wl->pub, "linux", wl);
+       }
+
+       /* free common resources */
+       if (wl->wlc) {
+               brcms_c_detach(wl->wlc);
+               wl->wlc = NULL;
+               wl->pub = NULL;
+       }
+
+       /* virtual interface deletion is deferred so we cannot spinwait */
+
+       /* wait for all pending callbacks to complete */
+       while (atomic_read(&wl->callbacks) > 0)
+               schedule();
+
+       /* free timers */
+       for (t = wl->timers; t; t = next) {
+               next = t->next;
+#ifdef DEBUG
+               kfree(t->name);
+#endif
+               kfree(t);
+       }
+}
+
+/*
+* called from both kernel as from this kernel module (error flow on attach)
+* precondition: perimeter lock is not acquired.
+*/
+static void brcms_remove(struct bcma_device *pdev)
+{
+       struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
+       struct brcms_info *wl = hw->priv;
+
+       if (wl->wlc) {
+               wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
+               wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+               ieee80211_unregister_hw(hw);
+       }
+
+       brcms_free(wl);
+
+       bcma_set_drvdata(pdev, NULL);
+       ieee80211_free_hw(hw);
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static void brcms_release_fw(struct brcms_info *wl)
+{
+       int i;
+       for (i = 0; i < MAX_FW_IMAGES; i++) {
+               release_firmware(wl->fw.fw_bin[i]);
+               release_firmware(wl->fw.fw_hdr[i]);
+       }
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
+{
+       int status;
+       struct device *device = &pdev->dev;
+       char fw_name[100];
+       int i;
+
+       memset(&wl->fw, 0, sizeof(struct brcms_firmware));
+       for (i = 0; i < MAX_FW_IMAGES; i++) {
+               if (brcms_firmwares[i] == NULL)
+                       break;
+               sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
+                       UCODE_LOADER_API_VER);
+               status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
+               if (status) {
+                       wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+                                 KBUILD_MODNAME, fw_name);
+                       return status;
+               }
+               sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
+                       UCODE_LOADER_API_VER);
+               status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
+               if (status) {
+                       wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+                                 KBUILD_MODNAME, fw_name);
+                       return status;
+               }
+               wl->fw.hdr_num_entries[i] =
+                   wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
+       }
+       wl->fw.fw_cnt = i;
+       status = brcms_ucode_data_init(wl, &wl->ucode);
+       brcms_release_fw(wl);
+       return status;
+}
+
 static void brcms_ops_tx(struct ieee80211_hw *hw,
                         struct ieee80211_tx_control *control,
                         struct sk_buff *skb)
@@ -306,6 +430,14 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
        if (!blocked)
                wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
 
+       if (!wl->ucode.bcm43xx_bomminor) {
+               err = brcms_request_fw(wl, wl->wlc->hw->d11core);
+               if (err) {
+                       brcms_remove(wl->wlc->hw->d11core);
+                       return -ENOENT;
+               }
+       }
+
        spin_lock_bh(&wl->lock);
        /* avoid acknowledging frames before a non-monitor device is added */
        wl->mute_tx = true;
@@ -793,128 +925,6 @@ void brcms_dpc(unsigned long data)
        wake_up(&wl->tx_flush_wq);
 }
 
-/*
- * Precondition: Since this function is called in brcms_pci_probe() context,
- * no locking is required.
- */
-static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
-{
-       int status;
-       struct device *device = &pdev->dev;
-       char fw_name[100];
-       int i;
-
-       memset(&wl->fw, 0, sizeof(struct brcms_firmware));
-       for (i = 0; i < MAX_FW_IMAGES; i++) {
-               if (brcms_firmwares[i] == NULL)
-                       break;
-               sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
-                       UCODE_LOADER_API_VER);
-               status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
-               if (status) {
-                       wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
-                                 KBUILD_MODNAME, fw_name);
-                       return status;
-               }
-               sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
-                       UCODE_LOADER_API_VER);
-               status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
-               if (status) {
-                       wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
-                                 KBUILD_MODNAME, fw_name);
-                       return status;
-               }
-               wl->fw.hdr_num_entries[i] =
-                   wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
-       }
-       wl->fw.fw_cnt = i;
-       return brcms_ucode_data_init(wl, &wl->ucode);
-}
-
-/*
- * Precondition: Since this function is called in brcms_pci_probe() context,
- * no locking is required.
- */
-static void brcms_release_fw(struct brcms_info *wl)
-{
-       int i;
-       for (i = 0; i < MAX_FW_IMAGES; i++) {
-               release_firmware(wl->fw.fw_bin[i]);
-               release_firmware(wl->fw.fw_hdr[i]);
-       }
-}
-
-/**
- * This function frees the WL per-device resources.
- *
- * This function frees resources owned by the WL device pointed to
- * by the wl parameter.
- *
- * precondition: can both be called locked and unlocked
- *
- */
-static void brcms_free(struct brcms_info *wl)
-{
-       struct brcms_timer *t, *next;
-
-       /* free ucode data */
-       if (wl->fw.fw_cnt)
-               brcms_ucode_data_free(&wl->ucode);
-       if (wl->irq)
-               free_irq(wl->irq, wl);
-
-       /* kill dpc */
-       tasklet_kill(&wl->tasklet);
-
-       if (wl->pub) {
-               brcms_debugfs_detach(wl->pub);
-               brcms_c_module_unregister(wl->pub, "linux", wl);
-       }
-
-       /* free common resources */
-       if (wl->wlc) {
-               brcms_c_detach(wl->wlc);
-               wl->wlc = NULL;
-               wl->pub = NULL;
-       }
-
-       /* virtual interface deletion is deferred so we cannot spinwait */
-
-       /* wait for all pending callbacks to complete */
-       while (atomic_read(&wl->callbacks) > 0)
-               schedule();
-
-       /* free timers */
-       for (t = wl->timers; t; t = next) {
-               next = t->next;
-#ifdef DEBUG
-               kfree(t->name);
-#endif
-               kfree(t);
-       }
-}
-
-/*
-* called from both kernel as from this kernel module (error flow on attach)
-* precondition: perimeter lock is not acquired.
-*/
-static void brcms_remove(struct bcma_device *pdev)
-{
-       struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
-       struct brcms_info *wl = hw->priv;
-
-       if (wl->wlc) {
-               wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
-               wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
-               ieee80211_unregister_hw(hw);
-       }
-
-       brcms_free(wl);
-
-       bcma_set_drvdata(pdev, NULL);
-       ieee80211_free_hw(hw);
-}
-
 static irqreturn_t brcms_isr(int irq, void *dev_id)
 {
        struct brcms_info *wl;
@@ -1047,18 +1057,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
        spin_lock_init(&wl->lock);
        spin_lock_init(&wl->isr_lock);
 
-       /* prepare ucode */
-       if (brcms_request_fw(wl, pdev) < 0) {
-               wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
-                         "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
-               brcms_release_fw(wl);
-               brcms_remove(pdev);
-               return NULL;
-       }
-
        /* common load-time initialization */
        wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err);
-       brcms_release_fw(wl);
        if (!wl->wlc) {
                wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
                          KBUILD_MODNAME, err);
index 21a824232478f2ac02d593495ac5fe82ff94df77..18d37645e2cde25f2d291a94bd51a3e3675db5be 100644 (file)
@@ -1137,9 +1137,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
        gain0_15 = ((biq1 & 0xf) << 12) |
                   ((tia & 0xf) << 8) |
                   ((lna2 & 0x3) << 6) |
-                  ((lna2 & 0x3) << 4) |
-                  ((lna1 & 0x3) << 2) |
-                  ((lna1 & 0x3) << 0);
+                  ((lna2 &
+                    0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
 
        mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
        mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
@@ -1157,8 +1156,6 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
        }
 
        mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
-       mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-       mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
 
 }
 
@@ -1331,43 +1328,6 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
        return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
 }
 
-static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
-                                     u16 tia_gain, u16 lna2_gain)
-{
-       u32 i_thresh_l, q_thresh_l;
-       u32 i_thresh_h, q_thresh_h;
-       struct lcnphy_iq_est iq_est_h, iq_est_l;
-
-       wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
-                                              lna2_gain, 0);
-
-       wlc_lcnphy_rx_gain_override_enable(pi, true);
-       wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
-       udelay(500);
-       write_radio_reg(pi, RADIO_2064_REG112, 0);
-       if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
-               return false;
-
-       wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
-       udelay(500);
-       write_radio_reg(pi, RADIO_2064_REG112, 0);
-       if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
-               return false;
-
-       i_thresh_l = (iq_est_l.i_pwr << 1);
-       i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
-
-       q_thresh_l = (iq_est_l.q_pwr << 1);
-       q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
-       if ((iq_est_h.i_pwr > i_thresh_l) &&
-           (iq_est_h.i_pwr < i_thresh_h) &&
-           (iq_est_h.q_pwr > q_thresh_l) &&
-           (iq_est_h.q_pwr < q_thresh_h))
-               return true;
-
-       return false;
-}
-
 static bool
 wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
                     const struct lcnphy_rx_iqcomp *iqcomp,
@@ -1382,8 +1342,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
            RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
            rfoverride3_old, rfoverride3val_old, rfoverride4_old,
            rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
-       int tia_gain, lna2_gain, biq1_gain;
-       bool set_gain;
+       int tia_gain;
+       u32 received_power, rx_pwr_threshold;
        u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
        u16 values_to_save[11];
        s16 *ptr;
@@ -1408,134 +1368,126 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
                goto cal_done;
        }
 
-       WARN_ON(module != 1);
-       tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-       wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-       for (i = 0; i < 11; i++)
-               values_to_save[i] =
-                       read_radio_reg(pi, rxiq_cal_rf_reg[i]);
-       Core1TxControl_old = read_phy_reg(pi, 0x631);
-
-       or_phy_reg(pi, 0x631, 0x0015);
-
-       RFOverride0_old = read_phy_reg(pi, 0x44c);
-       RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
-       rfoverride2_old = read_phy_reg(pi, 0x4b0);
-       rfoverride2val_old = read_phy_reg(pi, 0x4b1);
-       rfoverride3_old = read_phy_reg(pi, 0x4f9);
-       rfoverride3val_old = read_phy_reg(pi, 0x4fa);
-       rfoverride4_old = read_phy_reg(pi, 0x938);
-       rfoverride4val_old = read_phy_reg(pi, 0x939);
-       afectrlovr_old = read_phy_reg(pi, 0x43b);
-       afectrlovrval_old = read_phy_reg(pi, 0x43c);
-       old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-       old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
-
-       tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
-       if (tx_gain_override_old) {
-               wlc_lcnphy_get_tx_gain(pi, &old_gains);
-               tx_gain_index_old = pi_lcn->lcnphy_current_index;
-       }
-
-       wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+       if (module == 1) {
 
-       mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-       mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+               tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+               wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
 
-       mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-       mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+               for (i = 0; i < 11; i++)
+                       values_to_save[i] =
+                               read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+               Core1TxControl_old = read_phy_reg(pi, 0x631);
+
+               or_phy_reg(pi, 0x631, 0x0015);
+
+               RFOverride0_old = read_phy_reg(pi, 0x44c);
+               RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+               rfoverride2_old = read_phy_reg(pi, 0x4b0);
+               rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+               rfoverride3_old = read_phy_reg(pi, 0x4f9);
+               rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+               rfoverride4_old = read_phy_reg(pi, 0x938);
+               rfoverride4val_old = read_phy_reg(pi, 0x939);
+               afectrlovr_old = read_phy_reg(pi, 0x43b);
+               afectrlovrval_old = read_phy_reg(pi, 0x43c);
+               old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+               old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+
+               tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+               if (tx_gain_override_old) {
+                       wlc_lcnphy_get_tx_gain(pi, &old_gains);
+                       tx_gain_index_old = pi_lcn->lcnphy_current_index;
+               }
 
-       write_radio_reg(pi, RADIO_2064_REG116, 0x06);
-       write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
-       write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
-       write_radio_reg(pi, RADIO_2064_REG098, 0x03);
-       write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
-       mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
-       write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
-       write_radio_reg(pi, RADIO_2064_REG114, 0x01);
-       write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
-       write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
-
-       mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
-       mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
-       mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
-       mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
-       mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
-       mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
-       mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
-       mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
-       mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
-       mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+               wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
 
-       mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
-       mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+               mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+               mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
 
-       write_phy_reg(pi, 0x6da, 0xffff);
-       or_phy_reg(pi, 0x6db, 0x3);
+               mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+               mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
 
-       wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
-       set_gain = false;
-
-       lna2_gain = 3;
-       while ((lna2_gain >= 0) && !set_gain) {
-               tia_gain = 4;
-
-               while ((tia_gain >= 0) && !set_gain) {
-                       biq1_gain = 6;
-
-                       while ((biq1_gain >= 0) && !set_gain) {
-                               set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
-                                                                    (u16)
-                                                                    biq1_gain,
-                                                                    (u16)
-                                                                    tia_gain,
-                                                                    (u16)
-                                                                    lna2_gain);
-                               biq1_gain -= 1;
-                       }
+               write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+               write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+               write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+               write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+               write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+               mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+               write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+               write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+               write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+               write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+
+               mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+               mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+               mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+               mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+               mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+               mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+               mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+               mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+               mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+               mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+
+               mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+               mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+               wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
+               write_phy_reg(pi, 0x6da, 0xffff);
+               or_phy_reg(pi, 0x6db, 0x3);
+               wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+               wlc_lcnphy_rx_gain_override_enable(pi, true);
+
+               tia_gain = 8;
+               rx_pwr_threshold = 950;
+               while (tia_gain > 0) {
                        tia_gain -= 1;
+                       wlc_lcnphy_set_rx_gain_by_distribution(pi,
+                                                              0, 0, 2, 2,
+                                                              (u16)
+                                                              tia_gain, 1, 0);
+                       udelay(500);
+
+                       received_power =
+                               wlc_lcnphy_measure_digital_power(pi, 2000);
+                       if (received_power < rx_pwr_threshold)
+                               break;
                }
-               lna2_gain -= 1;
-       }
+               result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
 
-       if (set_gain)
-               result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
-       else
-               result = false;
+               wlc_lcnphy_stop_tx_tone(pi);
 
-       wlc_lcnphy_stop_tx_tone(pi);
+               write_phy_reg(pi, 0x631, Core1TxControl_old);
 
-       write_phy_reg(pi, 0x631, Core1TxControl_old);
-
-       write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
-       write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
-       write_phy_reg(pi, 0x4b0, rfoverride2_old);
-       write_phy_reg(pi, 0x4b1, rfoverride2val_old);
-       write_phy_reg(pi, 0x4f9, rfoverride3_old);
-       write_phy_reg(pi, 0x4fa, rfoverride3val_old);
-       write_phy_reg(pi, 0x938, rfoverride4_old);
-       write_phy_reg(pi, 0x939, rfoverride4val_old);
-       write_phy_reg(pi, 0x43b, afectrlovr_old);
-       write_phy_reg(pi, 0x43c, afectrlovrval_old);
-       write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
-       write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+               write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+               write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+               write_phy_reg(pi, 0x4b0, rfoverride2_old);
+               write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+               write_phy_reg(pi, 0x4f9, rfoverride3_old);
+               write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+               write_phy_reg(pi, 0x938, rfoverride4_old);
+               write_phy_reg(pi, 0x939, rfoverride4val_old);
+               write_phy_reg(pi, 0x43b, afectrlovr_old);
+               write_phy_reg(pi, 0x43c, afectrlovrval_old);
+               write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+               write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
 
-       wlc_lcnphy_clear_trsw_override(pi);
+               wlc_lcnphy_clear_trsw_override(pi);
 
-       mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+               mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
 
-       for (i = 0; i < 11; i++)
-               write_radio_reg(pi, rxiq_cal_rf_reg[i],
-                               values_to_save[i]);
+               for (i = 0; i < 11; i++)
+                       write_radio_reg(pi, rxiq_cal_rf_reg[i],
+                                       values_to_save[i]);
 
-       if (tx_gain_override_old)
-               wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
-       else
-               wlc_lcnphy_disable_tx_gain_override(pi);
+               if (tx_gain_override_old)
+                       wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+               else
+                       wlc_lcnphy_disable_tx_gain_override(pi);
 
-       wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
-       wlc_lcnphy_rx_gain_override_enable(pi, false);
+               wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+               wlc_lcnphy_rx_gain_override_enable(pi, false);
+       }
 
 cal_done:
        kfree(ptr);
@@ -1829,17 +1781,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
                write_radio_reg(pi, RADIO_2064_REG038, 3);
                write_radio_reg(pi, RADIO_2064_REG091, 7);
        }
-
-       if (!(pi->sh->boardflags & BFL_FEM)) {
-               u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
-                       0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};
-
-               write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
-               write_radio_reg(pi, RADIO_2064_REG091, 0x3);
-               write_radio_reg(pi, RADIO_2064_REG038, 0x3);
-
-               write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
-       }
 }
 
 static int
@@ -2034,16 +1975,6 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
                } else {
                        mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
                        mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-                       mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
-                       mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
-                       mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
-                       mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
-                       mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
-                       mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
-                       mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
-                       mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
-                       mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
-                       mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
                }
        } else {
                mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
@@ -2130,14 +2061,12 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
                    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
 
        mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
-       mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
 }
 
 static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 {
        struct phytbl_info tab;
        u32 rfseq, ind;
-       u8 tssi_sel;
 
        tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
        tab.tbl_width = 32;
@@ -2159,13 +2088,7 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 
        mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
 
-       if (pi->sh->boardflags & BFL_FEM) {
-               tssi_sel = 0x1;
-               wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
-       } else {
-               tssi_sel = 0xe;
-               wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA);
-       }
+       wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
        mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
 
        mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
@@ -2201,10 +2124,9 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
        mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
 
        if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-               mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel);
+               mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
                mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
        } else {
-               mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1);
                mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
                mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
        }
@@ -2251,10 +2173,6 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 
        mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
 
-       mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
-       mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
-       mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-
        wlc_lcnphy_pwrctrl_rssiparams(pi);
 }
 
@@ -2873,8 +2791,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
                read_radio_reg(pi, RADIO_2064_REG007) & 1;
        u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
        u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
-       u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
-
        idleTssi = read_phy_reg(pi, 0x4ab);
        suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
                         MCTL_EN_MAC));
@@ -2892,12 +2808,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
        mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
        mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
        wlc_lcnphy_tssi_setup(pi);
-
-       mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
-       mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
-
-       wlc_lcnphy_set_bbmult(pi, 0x0);
-
        wlc_phy_do_dummy_tx(pi, true, OFF);
        idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
                    >> 0);
@@ -2919,7 +2829,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
 
        mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
 
-       wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
        wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
        wlc_lcnphy_set_tx_gain(pi, &old_gains);
        wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
@@ -3133,11 +3042,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
                        wlc_lcnphy_write_table(pi, &tab);
                        tab.tbl_offset++;
                }
-               mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
-               mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
-               mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
-               mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
-               mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
 
                mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
 
@@ -3939,6 +3843,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
        target_gains.pad_gain = 21;
        target_gains.dac_gain = 0;
        wlc_lcnphy_set_tx_gain(pi, &target_gains);
+       wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
 
        if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
 
@@ -3949,7 +3854,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
                                        lcnphy_recal ? LCNPHY_CAL_RECAL :
                                        LCNPHY_CAL_FULL), false);
        } else {
-               wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
                wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
        }
 
@@ -4374,22 +4278,17 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
        if (CHSPEC_IS5G(pi->radio_chanspec))
                pa_gain = 0x70;
        else
-               pa_gain = 0x60;
+               pa_gain = 0x70;
 
        if (pi->sh->boardflags & BFL_FEM)
                pa_gain = 0x10;
-
        tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
        tab.tbl_width = 32;
        tab.tbl_len = 1;
        tab.tbl_ptr = &val;
 
        for (j = 0; j < 128; j++) {
-               if (pi->sh->boardflags & BFL_FEM)
-                       gm_gain = gain_table[j].gm;
-               else
-                       gm_gain = 15;
-
+               gm_gain = gain_table[j].gm;
                val = (((u32) pa_gain << 24) |
                       (gain_table[j].pad << 16) |
                       (gain_table[j].pga << 8) | gm_gain);
@@ -4600,10 +4499,7 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
 
        write_phy_reg(pi, 0x4ea, 0x4688);
 
-       if (pi->sh->boardflags & BFL_FEM)
-               mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
-       else
-               mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
+       mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
 
        mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
 
@@ -4614,13 +4510,6 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
        wlc_lcnphy_rcal(pi);
 
        wlc_lcnphy_rc_cal(pi);
-
-       if (!(pi->sh->boardflags & BFL_FEM)) {
-               write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
-               write_radio_reg(pi, RADIO_2064_REG033, 0x19);
-               write_radio_reg(pi, RADIO_2064_REG039, 0xe);
-       }
-
 }
 
 static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
@@ -4650,20 +4539,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
                wlc_lcnphy_write_table(pi, &tab);
        }
 
-       if (!(pi->sh->boardflags & BFL_FEM)) {
-               tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-               tab.tbl_width = 16;
-               tab.tbl_ptr = &val;
-               tab.tbl_len = 1;
+       tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+       tab.tbl_width = 16;
+       tab.tbl_ptr = &val;
+       tab.tbl_len = 1;
 
-               val = 150;
-               tab.tbl_offset = 0;
-               wlc_lcnphy_write_table(pi, &tab);
+       val = 114;
+       tab.tbl_offset = 0;
+       wlc_lcnphy_write_table(pi, &tab);
 
-               val = 220;
-               tab.tbl_offset = 1;
-               wlc_lcnphy_write_table(pi, &tab);
-       }
+       val = 130;
+       tab.tbl_offset = 1;
+       wlc_lcnphy_write_table(pi, &tab);
+
+       val = 6;
+       tab.tbl_offset = 8;
+       wlc_lcnphy_write_table(pi, &tab);
 
        if (CHSPEC_IS2G(pi->radio_chanspec)) {
                if (pi->sh->boardflags & BFL_FEM)
@@ -5055,7 +4946,6 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
                wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
 
        mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
-       wlc_lcnphy_tssi_setup(pi);
 }
 
 void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
@@ -5094,7 +4984,8 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
        if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
                return false;
 
-       if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+       if ((pi->sh->boardflags & BFL_FEM) &&
+           (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
                if (pi_lcn->lcnphy_tempsense_option == 3) {
                        pi->hwpwrctrl = true;
                        pi->hwpwrctrl_capable = true;
index b7e95acc2084033dd5c27de24b80bebd78f8dfbe..622c01ca72c5d24e8bfc55c3b84ad61633c4bb92 100644 (file)
@@ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
 };
 
 static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
-       0x0009,
        0x000a,
-       0x0005,
-       0x0006,
        0x0009,
-       0x000a,
-       0x0005,
        0x0006,
-       0x0009,
-       0x000a,
        0x0005,
-       0x0006,
-       0x0009,
        0x000a,
-       0x0005,
-       0x0006,
        0x0009,
-       0x000a,
-       0x0005,
        0x0006,
-       0x0009,
-       0x000a,
        0x0005,
-       0x0006,
-       0x0009,
        0x000a,
-       0x0005,
-       0x0006,
        0x0009,
-       0x000a,
-       0x0005,
        0x0006,
-       0x0009,
-       0x000a,
        0x0005,
-       0x0006,
-       0x0009,
        0x000a,
-       0x0005,
-       0x0006,
        0x0009,
-       0x000a,
-       0x0005,
        0x0006,
-       0x0009,
-       0x000a,
        0x0005,
-       0x0006,
+       0x000a,
        0x0009,
+       0x0006,
+       0x0005,
        0x000a,
+       0x0009,
+       0x0006,
        0x0005,
+       0x000a,
+       0x0009,
        0x0006,
+       0x0005,
+       0x000a,
        0x0009,
+       0x0006,
+       0x0005,
        0x000a,
+       0x0009,
+       0x0006,
        0x0005,
+       0x000a,
+       0x0009,
        0x0006,
+       0x0005,
+       0x000a,
        0x0009,
+       0x0006,
+       0x0005,
        0x000a,
+       0x0009,
+       0x0006,
        0x0005,
+       0x000a,
+       0x0009,
        0x0006,
+       0x0005,
+       0x000a,
        0x0009,
+       0x0006,
+       0x0005,
        0x000a,
+       0x0009,
+       0x0006,
        0x0005,
+       0x000a,
+       0x0009,
        0x0006,
+       0x0005,
 };
 
 static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
index e8324b5e5bfe836610f5680f86cf9c742fc4061b..6c7493c2d698e6a2c83de679131890726aff6456 100644 (file)
@@ -2152,7 +2152,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
        int rate_idx;
        int i;
        u32 rate;
-       u8 use_green = il4965_rs_use_green(il, sta);
+       u8 use_green;
        u8 active_tbl = 0;
        u8 valid_tx_ant;
        struct il_station_priv *sta_priv;
@@ -2160,6 +2160,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
        if (!sta || !lq_sta)
                return;
 
+       use_green = il4965_rs_use_green(il, sta);
        sta_priv = (void *)sta->drv_priv;
 
        i = lq_sta->last_txrate_idx;
index 86ea5f4c39398077efa5e13c4a16a7dcf769bf05..44ca0e57f9f76fd8b3b58c183a630fdb057f78ad 100644 (file)
@@ -1261,6 +1261,15 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                return -EIO;
        }
 
+       /*
+        * This can happen upon FW ASSERT: we clear the STATUS_FW_ERROR flag
+        * in iwl_down but cancel the workers only later.
+        */
+       if (!priv->ucode_loaded) {
+               IWL_ERR(priv, "Fw not loaded - dropping CMD: %x\n", cmd->id);
+               return -EIO;
+       }
+
        /*
         * Synchronous commands from this op-mode must hold
         * the mutex, this ensures we don't try to send two
index 23be948cf16220828e1b3bcbceeb5aff31ced74b..a82b6b39d4ff6df26375334963aa3d42114f7c32 100644 (file)
@@ -1419,6 +1419,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 
        mutex_lock(&priv->mutex);
 
+       if (changes & BSS_CHANGED_IDLE && bss_conf->idle) {
+               /*
+                * If we go idle, then clearly no "passive-no-rx"
+                * workaround is needed any more, this is a reset.
+                */
+               iwlagn_lift_passive_no_rx(priv);
+       }
+
        if (unlikely(!iwl_is_ready(priv))) {
                IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
                mutex_unlock(&priv->mutex);
@@ -1450,16 +1458,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
                        priv->timestamp = bss_conf->sync_tsf;
                        ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
                } else {
-                       /*
-                        * If we disassociate while there are pending
-                        * frames, just wake up the queues and let the
-                        * frames "escape" ... This shouldn't really
-                        * be happening to start with, but we should
-                        * not get stuck in this case either since it
-                        * can happen if userspace gets confused.
-                        */
-                       iwlagn_lift_passive_no_rx(priv);
-
                        ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 
                        if (ctx->ctxid == IWL_RXON_CTX_BSS)
index 6aec2df3bb27768fcfbcb5555384746a9e5026ec..d1a670d7b10cfd05f28c07624616f436ebf6c321 100644 (file)
@@ -1192,7 +1192,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
                        memset(&info->status, 0, sizeof(info->status));
 
                        if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
-                           iwl_is_associated_ctx(ctx) && ctx->vif &&
+                           ctx->vif &&
                            ctx->vif->type == NL80211_IFTYPE_STATION) {
                                /* block and stop all queues */
                                priv->passive_no_rx = true;
index 736fe9bb140ebab643e065742469ef0a9f667e31..1a4ac9236a4446e2d8b30722cad23e826756a660 100644 (file)
@@ -367,6 +367,8 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
                return -EIO;
        }
 
+       priv->ucode_loaded = true;
+
        if (ucode_type != IWL_UCODE_WOWLAN) {
                /* delay a bit to give rfkill time to run */
                msleep(5);
@@ -380,8 +382,6 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
                return ret;
        }
 
-       priv->ucode_loaded = true;
-
        return 0;
 }
 
index 17bedc50e753d62613055eb3662c4095fe9f41bf..12c4f31ca8fbddcc95925cebf4b269b150a64ef2 100644 (file)
@@ -475,6 +475,10 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
 
        /* If platform's RF_KILL switch is NOT set to KILL */
        hw_rfkill = iwl_is_rfkill_set(trans);
+       if (hw_rfkill)
+               set_bit(STATUS_RFKILL, &trans_pcie->status);
+       else
+               clear_bit(STATUS_RFKILL, &trans_pcie->status);
        iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
        if (hw_rfkill && !run_in_rfkill)
                return -ERFKILL;
@@ -641,6 +645,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
 
 static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 {
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        bool hw_rfkill;
        int err;
 
@@ -656,6 +661,10 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
        iwl_enable_rfkill_int(trans);
 
        hw_rfkill = iwl_is_rfkill_set(trans);
+       if (hw_rfkill)
+               set_bit(STATUS_RFKILL, &trans_pcie->status);
+       else
+               clear_bit(STATUS_RFKILL, &trans_pcie->status);
        iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 
        return 0;
@@ -694,6 +703,10 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
                 * op_mode.
                 */
                hw_rfkill = iwl_is_rfkill_set(trans);
+               if (hw_rfkill)
+                       set_bit(STATUS_RFKILL, &trans_pcie->status);
+               else
+                       clear_bit(STATUS_RFKILL, &trans_pcie->status);
                iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
        }
 }
index 8595c16f74deb8bdcf531725e3c65c0986d58745..cb5c6792e3a8de2679022370c140263b8e1e9e57 100644 (file)
@@ -1264,7 +1264,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
        for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
                int copy = 0;
 
-               if (!cmd->len)
+               if (!cmd->len[i])
                        continue;
 
                /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
index a44023a7bd571ca228be0a4fe16f09d4fe42a1a8..8aaf56ade4d9d086f36b7dee9d880f7628b50b23 100644 (file)
@@ -1892,7 +1892,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
                }
        }
 
-       for (i = 0; i < request->n_channels; i++) {
+       for (i = 0; i < min_t(u32, request->n_channels,
+                             MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
                chan = request->channels[i];
                priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
                priv->user_scan_cfg->chan_list[i].radio_type = chan->band;
index 5c395e2e6a2b874fb0257424663a73cb7abf0c17..feb20461339767df1c8912b216b9d62a1c11f5da 100644 (file)
@@ -1508,6 +1508,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
                }
                memcpy(adapter->upld_buf, skb->data,
                       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
+               skb_push(skb, INTF_HEADER_LEN);
                if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
                                           PCI_DMA_FROMDEVICE))
                        return -1;
index d215b4d3c51b57db90eee2293f6c153059fe037b..e7f6deaf715e5020c56685c1b8daf4d55ac9b945 100644 (file)
@@ -1393,8 +1393,10 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
                        queue_work(adapter->workqueue, &adapter->main_work);
 
                        /* Perform internal scan synchronously */
-                       if (!priv->scan_request)
+                       if (!priv->scan_request) {
+                               dev_dbg(adapter->dev, "wait internal scan\n");
                                mwifiex_wait_queue_complete(adapter, cmd_node);
+                       }
                } else {
                        spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
                                               flags);
@@ -1793,7 +1795,12 @@ check_next_scan:
                /* Need to indicate IOCTL complete */
                if (adapter->curr_cmd->wait_q_enabled) {
                        adapter->cmd_wait_q.status = 0;
-                       mwifiex_complete_cmd(adapter, adapter->curr_cmd);
+                       if (!priv->scan_request) {
+                               dev_dbg(adapter->dev,
+                                       "complete internal scan\n");
+                               mwifiex_complete_cmd(adapter,
+                                                    adapter->curr_cmd);
+                       }
                }
                if (priv->report_scan_result)
                        priv->report_scan_result = false;
index 2bf4efa331867acaea139bb81dcca75a66532ef4..76cd47eb901e089bbf58669c8eb5fc7da6631a7a 100644 (file)
@@ -20,6 +20,7 @@ if RT2X00
 config RT2400PCI
        tristate "Ralink rt2400 (PCI/PCMCIA) support"
        depends on PCI
+       select RT2X00_LIB_MMIO
        select RT2X00_LIB_PCI
        select EEPROM_93CX6
        ---help---
@@ -31,6 +32,7 @@ config RT2400PCI
 config RT2500PCI
        tristate "Ralink rt2500 (PCI/PCMCIA) support"
        depends on PCI
+       select RT2X00_LIB_MMIO
        select RT2X00_LIB_PCI
        select EEPROM_93CX6
        ---help---
@@ -43,6 +45,7 @@ config RT61PCI
        tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support"
        depends on PCI
        select RT2X00_LIB_PCI
+       select RT2X00_LIB_MMIO
        select RT2X00_LIB_FIRMWARE
        select RT2X00_LIB_CRYPTO
        select CRC_ITU_T
@@ -57,6 +60,7 @@ config RT2800PCI
        tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support"
        depends on PCI || SOC_RT288X || SOC_RT305X
        select RT2800_LIB
+       select RT2X00_LIB_MMIO
        select RT2X00_LIB_PCI if PCI
        select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X
        select RT2X00_LIB_FIRMWARE
@@ -185,6 +189,9 @@ endif
 config RT2800_LIB
        tristate
 
+config RT2X00_LIB_MMIO
+       tristate
+
 config RT2X00_LIB_PCI
        tristate
        select RT2X00_LIB
index 349d5b8284a4f6c64faaa58d6b750864c3a8252e..f069d8bc5b678332151d7a6fe337f44e29205d82 100644 (file)
@@ -9,6 +9,7 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)    += rt2x00leds.o
 
 obj-$(CONFIG_RT2X00_LIB)               += rt2x00lib.o
+obj-$(CONFIG_RT2X00_LIB_MMIO)          += rt2x00mmio.o
 obj-$(CONFIG_RT2X00_LIB_PCI)           += rt2x00pci.o
 obj-$(CONFIG_RT2X00_LIB_SOC)           += rt2x00soc.o
 obj-$(CONFIG_RT2X00_LIB_USB)           += rt2x00usb.o
index 221beaaa83f12c59554302569639ca87f83765b5..dcfb54e0c516beb21faa4ae0b4409592b8455756 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 
 #include "rt2x00.h"
+#include "rt2x00mmio.h"
 #include "rt2x00pci.h"
 #include "rt2400pci.h"
 
index 39edc59e8d038613a07b4dce764e0033be2501cf..e1d2dc9ed28a6801c727b484a6e596e346d45175 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 
 #include "rt2x00.h"
+#include "rt2x00mmio.h"
 #include "rt2x00pci.h"
 #include "rt2500pci.h"
 
index ded73da4de0b0d52cd6331d837c8c68e86b87749..ba5a05625aaa70b5dcba84081a4bbea5a5970a9d 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/eeprom_93cx6.h>
 
 #include "rt2x00.h"
+#include "rt2x00mmio.h"
 #include "rt2x00pci.h"
 #include "rt2x00soc.h"
 #include "rt2800lib.h"
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c
new file mode 100644 (file)
index 0000000..d84a680
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the
+       Free Software Foundation, Inc.,
+       59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+       Module: rt2x00mmio
+       Abstract: rt2x00 generic mmio device routines.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+
+/*
+ * Register access.
+ */
+int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
+                          const unsigned int offset,
+                          const struct rt2x00_field32 field,
+                          u32 *reg)
+{
+       unsigned int i;
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return 0;
+
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2x00pci_register_read(rt2x00dev, offset, reg);
+               if (!rt2x00_get_field32(*reg, field))
+                       return 1;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       printk_once(KERN_ERR "%s() Indirect register access failed: "
+             "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg);
+       *reg = ~0;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
+
+bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue = rt2x00dev->rx;
+       struct queue_entry *entry;
+       struct queue_entry_priv_pci *entry_priv;
+       struct skb_frame_desc *skbdesc;
+       int max_rx = 16;
+
+       while (--max_rx) {
+               entry = rt2x00queue_get_entry(queue, Q_INDEX);
+               entry_priv = entry->priv_data;
+
+               if (rt2x00dev->ops->lib->get_entry_state(entry))
+                       break;
+
+               /*
+                * Fill in desc fields of the skb descriptor
+                */
+               skbdesc = get_skb_frame_desc(entry->skb);
+               skbdesc->desc = entry_priv->desc;
+               skbdesc->desc_len = entry->queue->desc_size;
+
+               /*
+                * DMA is already done, notify rt2x00lib that
+                * it finished successfully.
+                */
+               rt2x00lib_dmastart(entry);
+               rt2x00lib_dmadone(entry);
+
+               /*
+                * Send the frame to rt2x00lib for further processing.
+                */
+               rt2x00lib_rxdone(entry, GFP_ATOMIC);
+       }
+
+       return !max_rx;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
+
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
+{
+       unsigned int i;
+
+       for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
+               msleep(10);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
+
+/*
+ * Device initialization handlers.
+ */
+static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
+                                    struct data_queue *queue)
+{
+       struct queue_entry_priv_pci *entry_priv;
+       void *addr;
+       dma_addr_t dma;
+       unsigned int i;
+
+       /*
+        * Allocate DMA memory for descriptor and buffer.
+        */
+       addr = dma_alloc_coherent(rt2x00dev->dev,
+                                 queue->limit * queue->desc_size,
+                                 &dma, GFP_KERNEL);
+       if (!addr)
+               return -ENOMEM;
+
+       memset(addr, 0, queue->limit * queue->desc_size);
+
+       /*
+        * Initialize all queue entries to contain valid addresses.
+        */
+       for (i = 0; i < queue->limit; i++) {
+               entry_priv = queue->entries[i].priv_data;
+               entry_priv->desc = addr + i * queue->desc_size;
+               entry_priv->desc_dma = dma + i * queue->desc_size;
+       }
+
+       return 0;
+}
+
+static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
+                                    struct data_queue *queue)
+{
+       struct queue_entry_priv_pci *entry_priv =
+           queue->entries[0].priv_data;
+
+       if (entry_priv->desc)
+               dma_free_coherent(rt2x00dev->dev,
+                                 queue->limit * queue->desc_size,
+                                 entry_priv->desc, entry_priv->desc_dma);
+       entry_priv->desc = NULL;
+}
+
+int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       int status;
+
+       /*
+        * Allocate DMA
+        */
+       queue_for_each(rt2x00dev, queue) {
+               status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
+               if (status)
+                       goto exit;
+       }
+
+       /*
+        * Register interrupt handler.
+        */
+       status = request_irq(rt2x00dev->irq,
+                            rt2x00dev->ops->lib->irq_handler,
+                            IRQF_SHARED, rt2x00dev->name, rt2x00dev);
+       if (status) {
+               ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
+                     rt2x00dev->irq, status);
+               goto exit;
+       }
+
+       return 0;
+
+exit:
+       queue_for_each(rt2x00dev, queue)
+               rt2x00pci_free_queue_dma(rt2x00dev, queue);
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
+
+void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+
+       /*
+        * Free irq line.
+        */
+       free_irq(rt2x00dev->irq, rt2x00dev);
+
+       /*
+        * Free DMA
+        */
+       queue_for_each(rt2x00dev, queue)
+               rt2x00pci_free_queue_dma(rt2x00dev, queue);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
+
+/*
+ * rt2x00mmio module information.
+ */
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("rt2x00 mmio library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.h b/drivers/net/wireless/rt2x00/rt2x00mmio.h
new file mode 100644 (file)
index 0000000..4ecaf60
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the
+       Free Software Foundation, Inc.,
+       59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+       Module: rt2x00mmio
+       Abstract: Data structures for the rt2x00mmio module.
+ */
+
+#ifndef RT2X00MMIO_H
+#define RT2X00MMIO_H
+
+#include <linux/io.h>
+
+/*
+ * Register access.
+ */
+static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
+                                          const unsigned int offset,
+                                          u32 *value)
+{
+       *value = readl(rt2x00dev->csr.base + offset);
+}
+
+static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
+                                               const unsigned int offset,
+                                               void *value, const u32 length)
+{
+       memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
+}
+
+static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
+                                           const unsigned int offset,
+                                           u32 value)
+{
+       writel(value, rt2x00dev->csr.base + offset);
+}
+
+static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+                                                const unsigned int offset,
+                                                const void *value,
+                                                const u32 length)
+{
+       __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
+}
+
+/**
+ * rt2x00pci_regbusy_read - Read from register with busy check
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @field: Field to check if register is busy
+ * @reg: Pointer to where register contents should be stored
+ *
+ * This function will read the given register, and checks if the
+ * register is busy. If it is, it will sleep for a couple of
+ * microseconds before reading the register again. If the register
+ * is not read after a certain timeout, this function will return
+ * FALSE.
+ */
+int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
+                          const unsigned int offset,
+                          const struct rt2x00_field32 field,
+                          u32 *reg);
+
+/**
+ * struct queue_entry_priv_pci: Per entry PCI specific information
+ *
+ * @desc: Pointer to device descriptor
+ * @desc_dma: DMA pointer to &desc.
+ * @data: Pointer to device's entry memory.
+ * @data_dma: DMA pointer to &data.
+ */
+struct queue_entry_priv_pci {
+       __le32 *desc;
+       dma_addr_t desc_dma;
+};
+
+/**
+ * rt2x00pci_rxdone - Handle RX done events
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ *
+ * Returns true if there are still rx frames pending and false if all
+ * pending rx frames were processed.
+ */
+bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00pci_flush_queue - Flush data queue
+ * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
+ *
+ * This will wait for a maximum of 100ms, waiting for the queues
+ * to become empty.
+ */
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
+
+/*
+ * Device initialization handlers.
+ */
+int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev);
+void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
+
+#endif /* RT2X00MMIO_H */
index a0c8caef3b0a8f3616a4dd4a71e6eebeb3b939ae..e87865e331139148c86a19b6efccf6efdaa329e2 100644 (file)
 #include "rt2x00.h"
 #include "rt2x00pci.h"
 
-/*
- * Register access.
- */
-int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
-                          const unsigned int offset,
-                          const struct rt2x00_field32 field,
-                          u32 *reg)
-{
-       unsigned int i;
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return 0;
-
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00pci_register_read(rt2x00dev, offset, reg);
-               if (!rt2x00_get_field32(*reg, field))
-                       return 1;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       ERROR(rt2x00dev, "Indirect register access failed: "
-             "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
-       *reg = ~0;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
-
-bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue = rt2x00dev->rx;
-       struct queue_entry *entry;
-       struct queue_entry_priv_pci *entry_priv;
-       struct skb_frame_desc *skbdesc;
-       int max_rx = 16;
-
-       while (--max_rx) {
-               entry = rt2x00queue_get_entry(queue, Q_INDEX);
-               entry_priv = entry->priv_data;
-
-               if (rt2x00dev->ops->lib->get_entry_state(entry))
-                       break;
-
-               /*
-                * Fill in desc fields of the skb descriptor
-                */
-               skbdesc = get_skb_frame_desc(entry->skb);
-               skbdesc->desc = entry_priv->desc;
-               skbdesc->desc_len = entry->queue->desc_size;
-
-               /*
-                * DMA is already done, notify rt2x00lib that
-                * it finished successfully.
-                */
-               rt2x00lib_dmastart(entry);
-               rt2x00lib_dmadone(entry);
-
-               /*
-                * Send the frame to rt2x00lib for further processing.
-                */
-               rt2x00lib_rxdone(entry, GFP_ATOMIC);
-       }
-
-       return !max_rx;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
-
-void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
-{
-       unsigned int i;
-
-       for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
-               msleep(10);
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
-
-/*
- * Device initialization handlers.
- */
-static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
-                                    struct data_queue *queue)
-{
-       struct queue_entry_priv_pci *entry_priv;
-       void *addr;
-       dma_addr_t dma;
-       unsigned int i;
-
-       /*
-        * Allocate DMA memory for descriptor and buffer.
-        */
-       addr = dma_alloc_coherent(rt2x00dev->dev,
-                                 queue->limit * queue->desc_size,
-                                 &dma, GFP_KERNEL);
-       if (!addr)
-               return -ENOMEM;
-
-       memset(addr, 0, queue->limit * queue->desc_size);
-
-       /*
-        * Initialize all queue entries to contain valid addresses.
-        */
-       for (i = 0; i < queue->limit; i++) {
-               entry_priv = queue->entries[i].priv_data;
-               entry_priv->desc = addr + i * queue->desc_size;
-               entry_priv->desc_dma = dma + i * queue->desc_size;
-       }
-
-       return 0;
-}
-
-static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
-                                    struct data_queue *queue)
-{
-       struct queue_entry_priv_pci *entry_priv =
-           queue->entries[0].priv_data;
-
-       if (entry_priv->desc)
-               dma_free_coherent(rt2x00dev->dev,
-                                 queue->limit * queue->desc_size,
-                                 entry_priv->desc, entry_priv->desc_dma);
-       entry_priv->desc = NULL;
-}
-
-int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       int status;
-
-       /*
-        * Allocate DMA
-        */
-       queue_for_each(rt2x00dev, queue) {
-               status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
-               if (status)
-                       goto exit;
-       }
-
-       /*
-        * Register interrupt handler.
-        */
-       status = request_irq(rt2x00dev->irq,
-                            rt2x00dev->ops->lib->irq_handler,
-                            IRQF_SHARED, rt2x00dev->name, rt2x00dev);
-       if (status) {
-               ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
-                     rt2x00dev->irq, status);
-               goto exit;
-       }
-
-       return 0;
-
-exit:
-       queue_for_each(rt2x00dev, queue)
-               rt2x00pci_free_queue_dma(rt2x00dev, queue);
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
-
-void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-
-       /*
-        * Free irq line.
-        */
-       free_irq(rt2x00dev->irq, rt2x00dev);
-
-       /*
-        * Free DMA
-        */
-       queue_for_each(rt2x00dev, queue)
-               rt2x00pci_free_queue_dma(rt2x00dev, queue);
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
-
 /*
  * PCI driver handlers.
  */
index e2c99f2b9a1422f5e1dd1af1116f447f8b43c199..60d90b20f8b99216a8dd19b4926364be65725b28 100644 (file)
  */
 #define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops)
 
-/*
- * Register access.
- */
-static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
-                                          const unsigned int offset,
-                                          u32 *value)
-{
-       *value = readl(rt2x00dev->csr.base + offset);
-}
-
-static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
-                                               const unsigned int offset,
-                                               void *value, const u32 length)
-{
-       memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
-}
-
-static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
-                                           const unsigned int offset,
-                                           u32 value)
-{
-       writel(value, rt2x00dev->csr.base + offset);
-}
-
-static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
-                                                const unsigned int offset,
-                                                const void *value,
-                                                const u32 length)
-{
-       __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
-}
-
-/**
- * rt2x00pci_regbusy_read - Read from register with busy check
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @field: Field to check if register is busy
- * @reg: Pointer to where register contents should be stored
- *
- * This function will read the given register, and checks if the
- * register is busy. If it is, it will sleep for a couple of
- * microseconds before reading the register again. If the register
- * is not read after a certain timeout, this function will return
- * FALSE.
- */
-int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
-                          const unsigned int offset,
-                          const struct rt2x00_field32 field,
-                          u32 *reg);
-
-/**
- * struct queue_entry_priv_pci: Per entry PCI specific information
- *
- * @desc: Pointer to device descriptor
- * @desc_dma: DMA pointer to &desc.
- * @data: Pointer to device's entry memory.
- * @data_dma: DMA pointer to &data.
- */
-struct queue_entry_priv_pci {
-       __le32 *desc;
-       dma_addr_t desc_dma;
-};
-
-/**
- * rt2x00pci_rxdone - Handle RX done events
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- *
- * Returns true if there are still rx frames pending and false if all
- * pending rx frames were processed.
- */
-bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00pci_flush_queue - Flush data queue
- * @queue: Data queue to stop
- * @drop: True to drop all pending frames.
- *
- * This will wait for a maximum of 100ms, waiting for the queues
- * to become empty.
- */
-void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
-
-/*
- * Device initialization handlers.
- */
-int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev);
-void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
-
 /*
  * PCI driver handlers.
  */
index f95792cfcf8922e17222fec2feddc34f5117c308..9e3c8ff53e3fd9e0b4f723e96671eba005d75d62 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/eeprom_93cx6.h>
 
 #include "rt2x00.h"
+#include "rt2x00mmio.h"
 #include "rt2x00pci.h"
 #include "rt61pci.h"
 
index eef38cfd812ea330c76d799bd93caae1b7a5c0d8..ca33ae193935bc3c3e75ffa809aa0573a5e24692 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
-#include <linux/mei_bus.h>
+#include <linux/mei_cl_bus.h>
 
 #include <linux/nfc.h>
 #include <net/nfc/hci.h>
@@ -32,9 +32,6 @@
 
 #define MICROREAD_DRIVER_NAME "microread"
 
-#define MICROREAD_UUID UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, 0x94, \
-                              0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c)
-
 struct mei_nfc_hdr {
        u8 cmd;
        u8 status;
@@ -48,7 +45,7 @@ struct mei_nfc_hdr {
 #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
 
 struct microread_mei_phy {
-       struct mei_device *mei_device;
+       struct mei_cl_device *device;
        struct nfc_hci_dev *hdev;
 
        int powered;
@@ -105,14 +102,14 @@ static int microread_mei_write(void *phy_id, struct sk_buff *skb)
 
        MEI_DUMP_SKB_OUT("mei frame sent", skb);
 
-       r = mei_send(phy->device, skb->data, skb->len);
+       r = mei_cl_send(phy->device, skb->data, skb->len);
        if (r > 0)
                r = 0;
 
        return r;
 }
 
-static void microread_event_cb(struct mei_device *device, u32 events,
+static void microread_event_cb(struct mei_cl_device *device, u32 events,
                               void *context)
 {
        struct microread_mei_phy *phy = context;
@@ -120,7 +117,7 @@ static void microread_event_cb(struct mei_device *device, u32 events,
        if (phy->hard_fault != 0)
                return;
 
-       if (events & BIT(MEI_EVENT_RX)) {
+       if (events & BIT(MEI_CL_EVENT_RX)) {
                struct sk_buff *skb;
                int reply_size;
 
@@ -128,7 +125,7 @@ static void microread_event_cb(struct mei_device *device, u32 events,
                if (!skb)
                        return;
 
-               reply_size = mei_recv(device, skb->data, MEI_NFC_MAX_READ);
+               reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ);
                if (reply_size < MEI_NFC_HEADER_SIZE) {
                        kfree(skb);
                        return;
@@ -149,8 +146,8 @@ static struct nfc_phy_ops mei_phy_ops = {
        .disable = microread_mei_disable,
 };
 
-static int microread_mei_probe(struct mei_device *device,
-                              const struct mei_id *id)
+static int microread_mei_probe(struct mei_cl_device *device,
+                              const struct mei_cl_device_id *id)
 {
        struct microread_mei_phy *phy;
        int r;
@@ -164,9 +161,9 @@ static int microread_mei_probe(struct mei_device *device,
        }
 
        phy->device = device;
-       mei_set_clientdata(device, phy);
+       mei_cl_set_drvdata(device, phy);
 
-       r = mei_register_event_cb(device, microread_event_cb, phy);
+       r = mei_cl_register_event_cb(device, microread_event_cb, phy);
        if (r) {
                pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n");
                goto err_out;
@@ -186,9 +183,9 @@ err_out:
        return r;
 }
 
-static int microread_mei_remove(struct mei_device *device)
+static int microread_mei_remove(struct mei_cl_device *device)
 {
-       struct microread_mei_phy *phy = mei_get_clientdata(device);
+       struct microread_mei_phy *phy = mei_cl_get_drvdata(device);
 
        pr_info("Removing microread\n");
 
@@ -202,16 +199,15 @@ static int microread_mei_remove(struct mei_device *device)
        return 0;
 }
 
-static struct mei_id microread_mei_tbl[] = {
-       { MICROREAD_DRIVER_NAME, MICROREAD_UUID },
+static struct mei_cl_device_id microread_mei_tbl[] = {
+       { MICROREAD_DRIVER_NAME },
 
        /* required last entry */
        { }
 };
-
 MODULE_DEVICE_TABLE(mei, microread_mei_tbl);
 
-static struct mei_driver microread_driver = {
+static struct mei_cl_driver microread_driver = {
        .id_table = microread_mei_tbl,
        .name = MICROREAD_DRIVER_NAME,
 
@@ -225,7 +221,7 @@ static int microread_mei_init(void)
 
        pr_debug(DRIVER_DESC ": %s\n", __func__);
 
-       r = mei_driver_register(&microread_driver);
+       r = mei_cl_driver_register(&microread_driver);
        if (r) {
                pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n");
                return r;
@@ -236,7 +232,7 @@ static int microread_mei_init(void)
 
 static void microread_mei_exit(void)
 {
-       mei_driver_unregister(&microread_driver);
+       mei_cl_driver_unregister(&microread_driver);
 }
 
 module_init(microread_mei_init);
index 8647dc6f52d0cfab432826a1261118c487d29bad..748f8f3e9ff52a4634e277452a2d7b74ac72f999 100644 (file)
@@ -202,20 +202,16 @@ void pci_bus_add_devices(const struct pci_bus *bus)
                if (dev->is_added)
                        continue;
                retval = pci_bus_add_device(dev);
+               if (retval)
+                       dev_err(&dev->dev, "Error adding device (%d)\n",
+                               retval);
        }
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                BUG_ON(!dev->is_added);
-
                child = dev->subordinate;
-
-               if (!child)
-                       continue;
-               pci_bus_add_devices(child);
-
-               if (child->is_added)
-                       continue;
-               child->is_added = 1;
+               if (child)
+                       pci_bus_add_devices(child);
        }
 }
 
index 13e9e63a72665ab22ee431fdcd22392a2fb68c77..9fcb87f353d44cec965301af6799fd8b950d8794 100644 (file)
@@ -52,15 +52,12 @@ config HOTPLUG_PCI_IBM
          When in doubt, say N.
 
 config HOTPLUG_PCI_ACPI
-       tristate "ACPI PCI Hotplug driver"
-       depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK)
+       bool "ACPI PCI Hotplug driver"
+       depends on HOTPLUG_PCI=y && ((!ACPI_DOCK && ACPI) || (ACPI_DOCK))
        help
          Say Y here if you have a system that supports PCI Hotplug using
          ACPI.
 
-         To compile this driver as a module, choose M here: the
-         module will be called acpiphp.
-
          When in doubt, say N.
 
 config HOTPLUG_PCI_ACPI_IBM
index b70ac00a117e1eaa3c65939cd64555982a482f7a..6fdd49c6f0b91760978139827511a02a7bb10e7d 100644 (file)
@@ -73,8 +73,9 @@ static inline const char *slot_name(struct slot *slot)
  */
 struct acpiphp_bridge {
        struct list_head list;
+       struct list_head slots;
+       struct kref ref;
        acpi_handle handle;
-       struct acpiphp_slot *slots;
 
        /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
        struct acpiphp_func *func;
@@ -97,7 +98,7 @@ struct acpiphp_bridge {
  * PCI slot information for each *physical* PCI slot
  */
 struct acpiphp_slot {
-       struct acpiphp_slot *next;
+       struct list_head node;
        struct acpiphp_bridge *bridge;  /* parent */
        struct list_head funcs;         /* one slot may have different
                                           objects (i.e. for each function) */
@@ -119,7 +120,6 @@ struct acpiphp_slot {
  */
 struct acpiphp_func {
        struct acpiphp_slot *slot;      /* parent */
-       struct acpiphp_bridge *bridge;  /* Ejectable PCI-to-PCI bridge */
 
        struct list_head sibling;
        struct notifier_block nb;
@@ -146,10 +146,6 @@ struct acpiphp_attention_info
 #define ACPI_PCI_HOST_HID              "PNP0A03"
 
 /* ACPI _STA method value (ignore bit 4; battery present) */
-#define ACPI_STA_PRESENT               (0x00000001)
-#define ACPI_STA_ENABLED               (0x00000002)
-#define ACPI_STA_SHOW_IN_UI            (0x00000004)
-#define ACPI_STA_FUNCTIONING           (0x00000008)
 #define ACPI_STA_ALL                   (0x0000000f)
 
 /* bridge flags */
@@ -174,25 +170,24 @@ struct acpiphp_attention_info
 /* function prototypes */
 
 /* acpiphp_core.c */
-extern int acpiphp_register_attention(struct acpiphp_attention_info*info);
-extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
-extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot);
-extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
+int acpiphp_register_attention(struct acpiphp_attention_info*info);
+int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
+int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot);
+void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
 
 /* acpiphp_glue.c */
-extern int acpiphp_glue_init (void);
-extern void acpiphp_glue_exit (void);
 typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
 
-extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
-extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
-extern int acpiphp_eject_slot (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
+int acpiphp_enable_slot(struct acpiphp_slot *slot);
+int acpiphp_disable_slot(struct acpiphp_slot *slot);
+int acpiphp_eject_slot(struct acpiphp_slot *slot);
+u8 acpiphp_get_power_status(struct acpiphp_slot *slot);
+u8 acpiphp_get_attention_status(struct acpiphp_slot *slot);
+u8 acpiphp_get_latch_status(struct acpiphp_slot *slot);
+u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot);
 
 /* variables */
 extern bool acpiphp_debug;
+extern bool acpiphp_disabled;
 
 #endif /* _ACPIPHP_H */
index c2fd3095701f5a8bd3f91c56f7b7a8e51913d182..ca8127950fcd49397027370d82937246204a0e9b 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/pci-acpi.h>
 #include <linux/pci_hotplug.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
@@ -48,6 +49,7 @@
 #define SLOT_NAME_SIZE  21              /* {_SUN} */
 
 bool acpiphp_debug;
+bool acpiphp_disabled;
 
 /* local variables */
 static struct acpiphp_attention_info *attention_info;
@@ -60,7 +62,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+MODULE_PARM_DESC(disable, "disable acpiphp driver");
 module_param_named(debug, acpiphp_debug, bool, 0644);
+module_param_named(disable, acpiphp_disabled, bool, 0444);
 
 /* export the attention callback registration methods */
 EXPORT_SYMBOL_GPL(acpiphp_register_attention);
@@ -351,27 +355,9 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
 }
 
 
-static int __init acpiphp_init(void)
+void __init acpiphp_init(void)
 {
-       info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-
-       if (acpi_pci_disabled)
-               return 0;
-
-       /* read all the ACPI info from the system */
-       /* initialize internal data structure etc. */
-       return acpiphp_glue_init();
-}
-
-
-static void __exit acpiphp_exit(void)
-{
-       if (acpi_pci_disabled)
-               return;
-
-       /* deallocate internal data structures etc. */
-       acpiphp_glue_exit();
+       info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n",
+               acpiphp_disabled ? ", disabled by user; please report a bug"
+                                : "");
 }
-
-module_init(acpiphp_init);
-module_exit(acpiphp_exit);
index 270fdbadc19c93e97b62db8049a1542a748b1223..96fed19c6d90358833e37d1e9f55b1899b2d11b8 100644 (file)
@@ -54,6 +54,7 @@
 #include "acpiphp.h"
 
 static LIST_HEAD(bridge_list);
+static DEFINE_MUTEX(bridge_mutex);
 
 #define MY_NAME "acpiphp_glue"
 
@@ -61,6 +62,7 @@ static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
 static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context);
+static void free_bridge(struct kref *kref);
 
 /* callback routine to check for the existence of a pci dock device */
 static acpi_status
@@ -76,6 +78,39 @@ is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
        }
 }
 
+static inline void get_bridge(struct acpiphp_bridge *bridge)
+{
+       kref_get(&bridge->ref);
+}
+
+static inline void put_bridge(struct acpiphp_bridge *bridge)
+{
+       kref_put(&bridge->ref, free_bridge);
+}
+
+static void free_bridge(struct kref *kref)
+{
+       struct acpiphp_bridge *bridge;
+       struct acpiphp_slot *slot, *next;
+       struct acpiphp_func *func, *tmp;
+
+       bridge = container_of(kref, struct acpiphp_bridge, ref);
+
+       list_for_each_entry_safe(slot, next, &bridge->slots, node) {
+               list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) {
+                       kfree(func);
+               }
+               kfree(slot);
+       }
+
+       /* Release reference acquired by acpiphp_bridge_handle_to_function() */
+       if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)
+               put_bridge(bridge->func->slot->bridge);
+       put_device(&bridge->pci_bus->dev);
+       pci_dev_put(bridge->pci_dev);
+       kfree(bridge);
+}
+
 /*
  * the _DCK method can do funny things... and sometimes not
  * hah-hah funny.
@@ -154,9 +189,10 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        acpi_handle tmp;
        acpi_status status = AE_OK;
        unsigned long long adr, sun;
-       int device, function, retval;
+       int device, function, retval, found = 0;
        struct pci_bus *pbus = bridge->pci_bus;
        struct pci_dev *pdev;
+       u32 val;
 
        if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
                return AE_OK;
@@ -170,7 +206,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        device = (adr >> 16) & 0xffff;
        function = adr & 0xffff;
 
-       pdev = pbus->self;
+       pdev = bridge->pci_dev;
        if (pdev && device_is_managed_by_native_pciehp(pdev))
                return AE_OK;
 
@@ -178,7 +214,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        if (!newfunc)
                return AE_NO_MEMORY;
 
-       INIT_LIST_HEAD(&newfunc->sibling);
        newfunc->handle = handle;
        newfunc->function = function;
 
@@ -207,14 +242,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        }
 
        /* search for objects that share the same slot */
-       for (slot = bridge->slots; slot; slot = slot->next)
+       list_for_each_entry(slot, &bridge->slots, node)
                if (slot->device == device) {
                        if (slot->sun != sun)
                                warn("sibling found, but _SUN doesn't match!\n");
+                       found = 1;
                        break;
                }
 
-       if (!slot) {
+       if (!found) {
                slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
                if (!slot) {
                        kfree(newfunc);
@@ -227,9 +263,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
                INIT_LIST_HEAD(&slot->funcs);
                mutex_init(&slot->crit_sect);
 
-               slot->next = bridge->slots;
-               bridge->slots = slot;
-
+               mutex_lock(&bridge_mutex);
+               list_add_tail(&slot->node, &bridge->slots);
+               mutex_unlock(&bridge_mutex);
                bridge->nr_slots++;
 
                dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",
@@ -247,13 +283,13 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        }
 
        newfunc->slot = slot;
+       mutex_lock(&bridge_mutex);
        list_add_tail(&newfunc->sibling, &slot->funcs);
+       mutex_unlock(&bridge_mutex);
 
-       pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
-       if (pdev) {
+       if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function),
+                                      &val, 60*1000))
                slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
-               pci_dev_put(pdev);
-       }
 
        if (is_dock_device(handle)) {
                /* we don't want to call this device's _EJ0
@@ -290,7 +326,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 
  err_exit:
        bridge->nr_slots--;
-       bridge->slots = slot->next;
+       mutex_lock(&bridge_mutex);
+       list_del(&slot->node);
+       mutex_unlock(&bridge_mutex);
        kfree(slot);
        kfree(newfunc);
 
@@ -315,13 +353,17 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
        acpi_status status;
 
        /* must be added to the list prior to calling register_slot */
+       mutex_lock(&bridge_mutex);
        list_add(&bridge->list, &bridge_list);
+       mutex_unlock(&bridge_mutex);
 
        /* register all slot objects under this bridge */
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
                                     register_slot, NULL, bridge, NULL);
        if (ACPI_FAILURE(status)) {
+               mutex_lock(&bridge_mutex);
                list_del(&bridge->list);
+               mutex_unlock(&bridge_mutex);
                return;
        }
 
@@ -351,178 +393,46 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle
 {
        struct acpiphp_bridge *bridge;
        struct acpiphp_slot *slot;
-       struct acpiphp_func *func;
+       struct acpiphp_func *func = NULL;
 
+       mutex_lock(&bridge_mutex);
        list_for_each_entry(bridge, &bridge_list, list) {
-               for (slot = bridge->slots; slot; slot = slot->next) {
+               list_for_each_entry(slot, &bridge->slots, node) {
                        list_for_each_entry(func, &slot->funcs, sibling) {
-                               if (func->handle == handle)
+                               if (func->handle == handle) {
+                                       get_bridge(func->slot->bridge);
+                                       mutex_unlock(&bridge_mutex);
                                        return func;
+                               }
                        }
                }
        }
+       mutex_unlock(&bridge_mutex);
 
        return NULL;
 }
 
 
-static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
-{
-       acpi_handle dummy_handle;
-       struct acpiphp_func *func;
-
-       if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
-                                       "_EJ0", &dummy_handle))) {
-               bridge->flags |= BRIDGE_HAS_EJ0;
-
-               dbg("found ejectable p2p bridge\n");
-
-               /* make link between PCI bridge and PCI function */
-               func = acpiphp_bridge_handle_to_function(bridge->handle);
-               if (!func)
-                       return;
-               bridge->func = func;
-               func->bridge = bridge;
-       }
-}
-
-
-/* allocate and initialize host bridge data structure */
-static void add_host_bridge(struct acpi_pci_root *root)
-{
-       struct acpiphp_bridge *bridge;
-       acpi_handle handle = root->device->handle;
-
-       bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
-       if (bridge == NULL)
-               return;
-
-       bridge->handle = handle;
-
-       bridge->pci_bus = root->bus;
-
-       init_bridge_misc(bridge);
-}
-
-
-/* allocate and initialize PCI-to-PCI bridge data structure */
-static void add_p2p_bridge(acpi_handle *handle)
-{
-       struct acpiphp_bridge *bridge;
-
-       bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
-       if (bridge == NULL) {
-               err("out of memory\n");
-               return;
-       }
-
-       bridge->handle = handle;
-       config_p2p_bridge_flags(bridge);
-
-       bridge->pci_dev = acpi_get_pci_dev(handle);
-       bridge->pci_bus = bridge->pci_dev->subordinate;
-       if (!bridge->pci_bus) {
-               err("This is not a PCI-to-PCI bridge!\n");
-               goto err;
-       }
-
-       /*
-        * Grab a ref to the subordinate PCI bus in case the bus is
-        * removed via PCI core logical hotplug. The ref pins the bus
-        * (which we access during module unload).
-        */
-       get_device(&bridge->pci_bus->dev);
-
-       init_bridge_misc(bridge);
-       return;
- err:
-       pci_dev_put(bridge->pci_dev);
-       kfree(bridge);
-       return;
-}
-
-
-/* callback routine to find P2P bridges */
-static acpi_status
-find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       acpi_status status;
-       struct pci_dev *dev;
-
-       dev = acpi_get_pci_dev(handle);
-       if (!dev || !dev->subordinate)
-               goto out;
-
-       /* check if this bridge has ejectable slots */
-       if ((detect_ejectable_slots(handle) > 0)) {
-               dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
-               add_p2p_bridge(handle);
-       }
-
-       /* search P2P bridges under this p2p bridge */
-       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    find_p2p_bridge, NULL, NULL, NULL);
-       if (ACPI_FAILURE(status))
-               warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
-
- out:
-       pci_dev_put(dev);
-       return AE_OK;
-}
-
-
-/* find hot-pluggable slots, and then find P2P bridge */
-static int add_bridge(struct acpi_pci_root *root)
-{
-       acpi_status status;
-       unsigned long long tmp;
-       acpi_handle dummy_handle;
-       acpi_handle handle = root->device->handle;
-
-       /* if the bridge doesn't have _STA, we assume it is always there */
-       status = acpi_get_handle(handle, "_STA", &dummy_handle);
-       if (ACPI_SUCCESS(status)) {
-               status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
-               if (ACPI_FAILURE(status)) {
-                       dbg("%s: _STA evaluation failure\n", __func__);
-                       return 0;
-               }
-               if ((tmp & ACPI_STA_FUNCTIONING) == 0)
-                       /* don't register this object */
-                       return 0;
-       }
-
-       /* check if this bridge has ejectable slots */
-       if (detect_ejectable_slots(handle) > 0) {
-               dbg("found PCI host-bus bridge with hot-pluggable slots\n");
-               add_host_bridge(root);
-       }
-
-       /* search P2P bridges under this host bridge */
-       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    find_p2p_bridge, NULL, NULL, NULL);
-
-       if (ACPI_FAILURE(status))
-               warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
-
-       return 0;
-}
-
 static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
 {
        struct acpiphp_bridge *bridge;
 
+       mutex_lock(&bridge_mutex);
        list_for_each_entry(bridge, &bridge_list, list)
-               if (bridge->handle == handle)
+               if (bridge->handle == handle) {
+                       get_bridge(bridge);
+                       mutex_unlock(&bridge_mutex);
                        return bridge;
+               }
+       mutex_unlock(&bridge_mutex);
 
        return NULL;
 }
 
 static void cleanup_bridge(struct acpiphp_bridge *bridge)
 {
-       struct acpiphp_slot *slot, *next;
-       struct acpiphp_func *func, *tmp;
+       struct acpiphp_slot *slot;
+       struct acpiphp_func *func;
        acpi_status status;
        acpi_handle handle = bridge->handle;
 
@@ -543,10 +453,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
                        err("failed to install interrupt notify handler\n");
        }
 
-       slot = bridge->slots;
-       while (slot) {
-               next = slot->next;
-               list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) {
+       list_for_each_entry(slot, &bridge->slots, node) {
+               list_for_each_entry(func, &slot->funcs, sibling) {
                        if (is_dock_device(func->handle)) {
                                unregister_hotplug_dock_device(func->handle);
                                unregister_dock_notifier(&func->nb);
@@ -558,63 +466,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
                                if (ACPI_FAILURE(status))
                                        err("failed to remove notify handler\n");
                        }
-                       list_del(&func->sibling);
-                       kfree(func);
                }
                acpiphp_unregister_hotplug_slot(slot);
-               list_del(&slot->funcs);
-               kfree(slot);
-               slot = next;
        }
 
-       /*
-        * Only P2P bridges have a pci_dev
-        */
-       if (bridge->pci_dev)
-               put_device(&bridge->pci_bus->dev);
-
-       pci_dev_put(bridge->pci_dev);
+       mutex_lock(&bridge_mutex);
        list_del(&bridge->list);
-       kfree(bridge);
-}
-
-static acpi_status
-cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       struct acpiphp_bridge *bridge;
-
-       /* cleanup p2p bridges under this P2P bridge
-          in a depth-first manner */
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                               cleanup_p2p_bridge, NULL, NULL, NULL);
-
-       bridge = acpiphp_handle_to_bridge(handle);
-       if (bridge)
-               cleanup_bridge(bridge);
-
-       return AE_OK;
-}
-
-static void remove_bridge(struct acpi_pci_root *root)
-{
-       struct acpiphp_bridge *bridge;
-       acpi_handle handle = root->device->handle;
-
-       /* cleanup p2p bridges under this host bridge
-          in a depth-first manner */
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-                               (u32)1, cleanup_p2p_bridge, NULL, NULL, NULL);
-
-       /*
-        * On root bridges with hotplug slots directly underneath (ie,
-        * no p2p bridge between), we call cleanup_bridge(). 
-        *
-        * The else clause cleans up root bridges that either had no
-        * hotplug slots at all, or had a p2p bridge underneath.
-        */
-       bridge = acpiphp_handle_to_bridge(handle);
-       if (bridge)
-               cleanup_bridge(bridge);
+       mutex_unlock(&bridge_mutex);
 }
 
 static int power_on_slot(struct acpiphp_slot *slot)
@@ -798,6 +656,7 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev)
                }
        }
 }
+
 /**
  * enable_device - enable, configure a slot
  * @slot: slot to be enabled
@@ -810,9 +669,7 @@ static int __ref enable_device(struct acpiphp_slot *slot)
        struct pci_dev *dev;
        struct pci_bus *bus = slot->bridge->pci_bus;
        struct acpiphp_func *func;
-       int retval = 0;
        int num, max, pass;
-       acpi_status status;
 
        if (slot->flags & SLOT_ENABLED)
                goto err_exit;
@@ -867,23 +724,11 @@ static int __ref enable_device(struct acpiphp_slot *slot)
                        slot->flags &= (~SLOT_ENABLED);
                        continue;
                }
-
-               if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
-                   dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) {
-                       pci_dev_put(dev);
-                       continue;
-               }
-
-               status = find_p2p_bridge(func->handle, (u32)1, bus, NULL);
-               if (ACPI_FAILURE(status))
-                       warn("find_p2p_bridge failed (error code = 0x%x)\n",
-                               status);
-               pci_dev_put(dev);
        }
 
 
  err_exit:
-       return retval;
+       return 0;
 }
 
 /* return first device in slot, acquiring a reference on it */
@@ -912,23 +757,6 @@ static int disable_device(struct acpiphp_slot *slot)
 {
        struct acpiphp_func *func;
        struct pci_dev *pdev;
-       struct pci_bus *bus = slot->bridge->pci_bus;
-
-       /* The slot will be enabled when func 0 is added, so check
-          func 0 before disable the slot. */
-       pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
-       if (!pdev)
-               goto err_exit;
-       pci_dev_put(pdev);
-
-       list_for_each_entry(func, &slot->funcs, sibling) {
-               if (func->bridge) {
-                       /* cleanup p2p bridges under this P2P bridge */
-                       cleanup_p2p_bridge(func->bridge->handle,
-                                               (u32)1, NULL, NULL);
-                       func->bridge = NULL;
-               }
-       }
 
        /*
         * enable_device() enumerates all functions in this device via
@@ -947,7 +775,6 @@ static int disable_device(struct acpiphp_slot *slot)
 
        slot->flags &= (~SLOT_ENABLED);
 
-err_exit:
        return 0;
 }
 
@@ -1037,7 +864,7 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
 
        enabled = disabled = 0;
 
-       for (slot = bridge->slots; slot; slot = slot->next) {
+       list_for_each_entry(slot, &bridge->slots, node) {
                unsigned int status = get_slot_status(slot);
                if (slot->flags & SLOT_ENABLED) {
                        if (status == ACPI_STA_ALL)
@@ -1082,11 +909,11 @@ static void acpiphp_set_hpp_values(struct pci_bus *bus)
  */
 static void acpiphp_sanitize_bus(struct pci_bus *bus)
 {
-       struct pci_dev *dev;
+       struct pci_dev *dev, *tmp;
        int i;
        unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
 
-       list_for_each_entry(dev, &bus->devices, bus_list) {
+       list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
                for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
                        struct resource *res = &dev->resource[i];
                        if ((res->flags & type_mask) && !res->start &&
@@ -1118,6 +945,7 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
                dbg("%s: re-enumerating slots under %s\n",
                        __func__, objname);
                acpiphp_check_bridge(bridge);
+               put_bridge(bridge);
        }
        return AE_OK ;
 }
@@ -1195,6 +1023,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
 
        acpi_scan_lock_release();
        kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
+       put_bridge(bridge);
 }
 
 /**
@@ -1208,6 +1037,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
 static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
                                        void *context)
 {
+       struct acpiphp_bridge *bridge = context;
+
        /*
         * Currently the code adds all hotplug events to the kacpid_wq
         * queue when it should add hotplug events to the kacpi_hotplug_wq.
@@ -1216,6 +1047,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
         * For now just re-add this work to the kacpi_hotplug_wq so we
         * don't deadlock on hotplug actions.
         */
+       get_bridge(bridge);
        alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);
 }
 
@@ -1270,6 +1102,7 @@ static void _handle_hotplug_event_func(struct work_struct *work)
 
        acpi_scan_lock_release();
        kfree(hp_work); /* allocated in handle_hotplug_event_func */
+       put_bridge(func->slot->bridge);
 }
 
 /**
@@ -1283,6 +1116,8 @@ static void _handle_hotplug_event_func(struct work_struct *work)
 static void handle_hotplug_event_func(acpi_handle handle, u32 type,
                                      void *context)
 {
+       struct acpiphp_func *func = context;
+
        /*
         * Currently the code adds all hotplug events to the kacpid_wq
         * queue when it should add hotplug events to the kacpi_hotplug_wq.
@@ -1291,33 +1126,69 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,
         * For now just re-add this work to the kacpi_hotplug_wq so we
         * don't deadlock on hotplug actions.
         */
+       get_bridge(func->slot->bridge);
        alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func);
 }
 
-static struct acpi_pci_driver acpi_pci_hp_driver = {
-       .add =          add_bridge,
-       .remove =       remove_bridge,
-};
-
-/**
- * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures
+/*
+ * Create hotplug slots for the PCI bus.
+ * It should always return 0 to avoid skipping following notifiers.
  */
-int __init acpiphp_glue_init(void)
+void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle)
 {
-       acpi_pci_register_driver(&acpi_pci_hp_driver);
+       acpi_handle dummy_handle;
+       struct acpiphp_bridge *bridge;
 
-       return 0;
-}
+       if (acpiphp_disabled)
+               return;
 
+       if (detect_ejectable_slots(handle) <= 0)
+               return;
 
-/**
- * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures
- *
- * This function frees all data allocated in acpiphp_glue_init().
- */
-void  acpiphp_glue_exit(void)
+       bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
+       if (bridge == NULL) {
+               err("out of memory\n");
+               return;
+       }
+
+       INIT_LIST_HEAD(&bridge->slots);
+       kref_init(&bridge->ref);
+       bridge->handle = handle;
+       bridge->pci_dev = pci_dev_get(bus->self);
+       bridge->pci_bus = bus;
+
+       /*
+        * Grab a ref to the subordinate PCI bus in case the bus is
+        * removed via PCI core logical hotplug. The ref pins the bus
+        * (which we access during module unload).
+        */
+       get_device(&bus->dev);
+
+       if (!pci_is_root_bus(bridge->pci_bus) &&
+           ACPI_SUCCESS(acpi_get_handle(bridge->handle,
+                                       "_EJ0", &dummy_handle))) {
+               dbg("found ejectable p2p bridge\n");
+               bridge->flags |= BRIDGE_HAS_EJ0;
+               bridge->func = acpiphp_bridge_handle_to_function(handle);
+       }
+
+       init_bridge_misc(bridge);
+}
+
+/* Destroy hotplug slots associated with the PCI bus */
+void acpiphp_remove_slots(struct pci_bus *bus)
 {
-       acpi_pci_unregister_driver(&acpi_pci_hp_driver);
+       struct acpiphp_bridge *bridge, *tmp;
+
+       if (acpiphp_disabled)
+               return;
+
+       list_for_each_entry_safe(bridge, tmp, &bridge_list, list)
+               if (bridge->pci_bus == bus) {
+                       cleanup_bridge(bridge);
+                       put_bridge(bridge);
+                       break;
+               }
 }
 
 /**
@@ -1396,7 +1267,7 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot)
 
        sta = get_slot_status(slot);
 
-       return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1;
+       return (sta & ACPI_STA_DEVICE_UI) ? 0 : 1;
 }
 
 
index 9fff878cf0268c0c0cd4d160edf80dec51e67dd1..1356211431d0d464406be033993af91d3b87362a 100644 (file)
@@ -75,28 +75,36 @@ static inline const char *slot_name(struct slot *slot)
        return hotplug_slot_name(slot->hotplug_slot);
 }
 
-extern int cpci_hp_register_controller(struct cpci_hp_controller *controller);
-extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
-extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
-extern int cpci_hp_unregister_bus(struct pci_bus *bus);
-extern int cpci_hp_start(void);
-extern int cpci_hp_stop(void);
+int cpci_hp_register_controller(struct cpci_hp_controller *controller);
+int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
+int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
+int cpci_hp_unregister_bus(struct pci_bus *bus);
+int cpci_hp_start(void);
+int cpci_hp_stop(void);
 
 /*
  * Internal function prototypes, these functions should not be used by
  * board/chassis drivers.
  */
-extern u8 cpci_get_attention_status(struct slot *slot);
-extern u8 cpci_get_latch_status(struct slot *slot);
-extern u8 cpci_get_adapter_status(struct slot *slot);
-extern u16 cpci_get_hs_csr(struct slot * slot);
-extern int cpci_set_attention_status(struct slot *slot, int status);
-extern int cpci_check_and_clear_ins(struct slot * slot);
-extern int cpci_check_ext(struct slot * slot);
-extern int cpci_clear_ext(struct slot * slot);
-extern int cpci_led_on(struct slot * slot);
-extern int cpci_led_off(struct slot * slot);
-extern int cpci_configure_slot(struct slot *slot);
-extern int cpci_unconfigure_slot(struct slot *slot);
+u8 cpci_get_attention_status(struct slot *slot);
+u8 cpci_get_latch_status(struct slot *slot);
+u8 cpci_get_adapter_status(struct slot *slot);
+u16 cpci_get_hs_csr(struct slot * slot);
+int cpci_set_attention_status(struct slot *slot, int status);
+int cpci_check_and_clear_ins(struct slot * slot);
+int cpci_check_ext(struct slot * slot);
+int cpci_clear_ext(struct slot * slot);
+int cpci_led_on(struct slot * slot);
+int cpci_led_off(struct slot * slot);
+int cpci_configure_slot(struct slot *slot);
+int cpci_unconfigure_slot(struct slot *slot);
+
+#ifdef CONFIG_HOTPLUG_PCI_CPCI
+int cpci_hotplug_init(int debug);
+void cpci_hotplug_exit(void);
+#else
+static inline int cpci_hotplug_init(int debug) { return 0; }
+static inline void cpci_hotplug_exit(void) { }
+#endif
 
 #endif /* _CPCI_HOTPLUG_H */
index d8ffc73668013fe3356ca6b4ea3c35c99ad95c32..516b87738b6e522d7c6fea05c77a9b4da4c08e49 100644 (file)
@@ -404,50 +404,44 @@ struct resource_lists {
 
 
 /* debugfs functions for the hotplug controller info */
-extern void cpqhp_initialize_debugfs(void);
-extern void cpqhp_shutdown_debugfs(void);
-extern void cpqhp_create_debugfs_files(struct controller *ctrl);
-extern void cpqhp_remove_debugfs_files(struct controller *ctrl);
+void cpqhp_initialize_debugfs(void);
+void cpqhp_shutdown_debugfs(void);
+void cpqhp_create_debugfs_files(struct controller *ctrl);
+void cpqhp_remove_debugfs_files(struct controller *ctrl);
 
 /* controller functions */
-extern void cpqhp_pushbutton_thread(unsigned long event_pointer);
-extern irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data);
-extern int cpqhp_find_available_resources(struct controller *ctrl,
-                                         void __iomem *rom_start);
-extern int cpqhp_event_start_thread(void);
-extern void cpqhp_event_stop_thread(void);
-extern struct pci_func *cpqhp_slot_create(unsigned char busnumber);
-extern struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device,
-                                       unsigned char index);
-extern int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func);
-extern int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func);
-extern int cpqhp_hardware_test(struct controller *ctrl, int test_num);
+void cpqhp_pushbutton_thread(unsigned long event_pointer);
+irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data);
+int cpqhp_find_available_resources(struct controller *ctrl,
+                                  void __iomem *rom_start);
+int cpqhp_event_start_thread(void);
+void cpqhp_event_stop_thread(void);
+struct pci_func *cpqhp_slot_create(unsigned char busnumber);
+struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device,
+                                unsigned char index);
+int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func);
+int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func);
+int cpqhp_hardware_test(struct controller *ctrl, int test_num);
 
 /* resource functions */
-extern int     cpqhp_resource_sort_and_combine (struct pci_resource **head);
+int    cpqhp_resource_sort_and_combine (struct pci_resource **head);
 
 /* pci functions */
-extern int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
-extern int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num,
-                            u8 slot);
-extern int cpqhp_save_config(struct controller *ctrl, int busnumber,
-                            int is_hot_plug);
-extern int cpqhp_save_base_addr_length(struct controller *ctrl,
-                                      struct pci_func *func);
-extern int cpqhp_save_used_resources(struct controller *ctrl,
-                                    struct pci_func *func);
-extern int cpqhp_configure_board(struct controller *ctrl,
-                                struct pci_func *func);
-extern int cpqhp_save_slot_config(struct controller *ctrl,
-                                 struct pci_func *new_slot);
-extern int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func);
-extern void cpqhp_destroy_board_resources(struct pci_func *func);
-extern int cpqhp_return_board_resources        (struct pci_func *func,
-                                        struct resource_lists *resources);
-extern void cpqhp_destroy_resource_list(struct resource_lists *resources);
-extern int cpqhp_configure_device(struct controller *ctrl,
-                                 struct pci_func *func);
-extern int cpqhp_unconfigure_device(struct pci_func *func);
+int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num,
+                     u8 slot);
+int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug);
+int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func);
+int cpqhp_save_used_resources(struct controller *ctrl, struct pci_func *func);
+int cpqhp_configure_board(struct controller *ctrl, struct pci_func *func);
+int cpqhp_save_slot_config(struct controller *ctrl, struct pci_func *new_slot);
+int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func);
+void cpqhp_destroy_board_resources(struct pci_func *func);
+int cpqhp_return_board_resources(struct pci_func *func,
+                                struct resource_lists *resources);
+void cpqhp_destroy_resource_list(struct resource_lists *resources);
+int cpqhp_configure_device(struct controller *ctrl, struct pci_func *func);
+int cpqhp_unconfigure_device(struct pci_func *func);
 
 /* Global variables */
 extern int cpqhp_debug;
index e89c0702119df0d1852ea4376aa75be206accffe..34e4e54fcf15652e50345d9b2bd4f80a2be66e54 100644 (file)
 
 #ifndef CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM
 
-static inline void compaq_nvram_init (void __iomem *rom_start)
+static inline void compaq_nvram_init(void __iomem *rom_start)
 {
        return;
 }
 
-static inline int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
+static inline int compaq_nvram_load(void __iomem *rom_start, struct controller *ctrl)
 {
        return 0;
 }
 
-static inline int compaq_nvram_store (void __iomem *rom_start)
+static inline int compaq_nvram_store(void __iomem *rom_start)
 {
        return 0;
 }
 
 #else
 
-extern void compaq_nvram_init  (void __iomem *rom_start);
-extern int compaq_nvram_load   (void __iomem *rom_start, struct controller *ctrl);
-extern int compaq_nvram_store  (void __iomem *rom_start);
+void compaq_nvram_init(void __iomem *rom_start);
+int compaq_nvram_load(void __iomem *rom_start, struct controller *ctrl);
+int compaq_nvram_store(void __iomem *rom_start);
 
 #endif
 
index a8d391a4957db86ccd7bd41dd02ccfa67831e8e7..8c5b25871d02c86d3e3752669ad1e0c0d12d2fab 100644 (file)
@@ -275,17 +275,17 @@ extern struct list_head ibmphp_slot_head;
 * FUNCTION PROTOTYPES                                      *
 ***********************************************************/
 
-extern void ibmphp_free_ebda_hpc_queue (void);
-extern int ibmphp_access_ebda (void);
-extern struct slot *ibmphp_get_slot_from_physical_num (u8);
-extern int ibmphp_get_total_hp_slots (void);
-extern void ibmphp_free_ibm_slot (struct slot *);
-extern void ibmphp_free_bus_info_queue (void);
-extern void ibmphp_free_ebda_pci_rsrc_queue (void);
-extern struct bus_info *ibmphp_find_same_bus_num (u32);
-extern int ibmphp_get_bus_index (u8);
-extern u16 ibmphp_get_total_controllers (void);
-extern int ibmphp_register_pci (void);
+void ibmphp_free_ebda_hpc_queue(void);
+int ibmphp_access_ebda(void);
+struct slot *ibmphp_get_slot_from_physical_num(u8);
+int ibmphp_get_total_hp_slots(void);
+void ibmphp_free_ibm_slot(struct slot *);
+void ibmphp_free_bus_info_queue(void);
+void ibmphp_free_ebda_pci_rsrc_queue(void);
+struct bus_info *ibmphp_find_same_bus_num(u32);
+int ibmphp_get_bus_index(u8);
+u16 ibmphp_get_total_controllers(void);
+int ibmphp_register_pci(void);
 
 /* passed parameters */
 #define MEM            0
@@ -381,24 +381,24 @@ struct res_needed {
 
 /* functions */
 
-extern int ibmphp_rsrc_init (void);
-extern int ibmphp_add_resource (struct resource_node *);
-extern int ibmphp_remove_resource (struct resource_node *);
-extern int ibmphp_find_resource (struct bus_node *, u32, struct resource_node **, int);
-extern int ibmphp_check_resource (struct resource_node *, u8);
-extern int ibmphp_remove_bus (struct bus_node *, u8);
-extern void ibmphp_free_resources (void);
-extern int ibmphp_add_pfmem_from_mem (struct resource_node *);
-extern struct bus_node *ibmphp_find_res_bus (u8);
-extern void ibmphp_print_test (void);  /* for debugging purposes */
+int ibmphp_rsrc_init(void);
+int ibmphp_add_resource(struct resource_node *);
+int ibmphp_remove_resource(struct resource_node *);
+int ibmphp_find_resource(struct bus_node *, u32, struct resource_node **, int);
+int ibmphp_check_resource(struct resource_node *, u8);
+int ibmphp_remove_bus(struct bus_node *, u8);
+void ibmphp_free_resources(void);
+int ibmphp_add_pfmem_from_mem(struct resource_node *);
+struct bus_node *ibmphp_find_res_bus(u8);
+void ibmphp_print_test(void);  /* for debugging purposes */
 
-extern void ibmphp_hpc_initvars (void);
-extern int ibmphp_hpc_readslot (struct slot *, u8, u8 *);
-extern int ibmphp_hpc_writeslot (struct slot *, u8);
-extern void ibmphp_lock_operations (void);
-extern void ibmphp_unlock_operations (void);
-extern int ibmphp_hpc_start_poll_thread (void);
-extern void ibmphp_hpc_stop_poll_thread (void);
+void ibmphp_hpc_initvars(void);
+int ibmphp_hpc_readslot(struct slot *, u8, u8 *);
+int ibmphp_hpc_writeslot(struct slot *, u8);
+void ibmphp_lock_operations(void);
+void ibmphp_unlock_operations(void);
+int ibmphp_hpc_start_poll_thread(void);
+void ibmphp_hpc_stop_poll_thread(void);
 
 //----------------------------------------------------------------------------
 
@@ -749,11 +749,11 @@ struct controller {
 
 /* Functions */
 
-extern int ibmphp_init_devno (struct slot **); /* This function is called from EBDA, so we need it not be static */
-extern int ibmphp_do_disable_slot (struct slot *slot_cur);
-extern int ibmphp_update_slot_info (struct slot *);    /* This function is called from HPC, so we need it to not be be static */
-extern int ibmphp_configure_card (struct pci_func *, u8);
-extern int ibmphp_unconfigure_card (struct slot **, int);
+int ibmphp_init_devno(struct slot **); /* This function is called from EBDA, so we need it not be static */
+int ibmphp_do_disable_slot(struct slot *slot_cur);
+int ibmphp_update_slot_info(struct slot *);    /* This function is called from HPC, so we need it to not be be static */
+int ibmphp_configure_card(struct pci_func *, u8);
+int ibmphp_unconfigure_card(struct slot **, int);
 extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops;
 
 #endif                         //__IBMPHP_H
index 202f4a969eb56614adf540b286844ca9f5a93832..ec20f74c8981ce1a4790f0d3102759b4c68af8ef 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/pci_hotplug.h>
 #include <asm/uaccess.h>
 #include "../pci.h"
+#include "cpci_hotplug.h"
 
 #define MY_NAME        "pci_hotplug"
 
@@ -63,14 +64,6 @@ static bool debug;
 static LIST_HEAD(pci_hotplug_slot_list);
 static DEFINE_MUTEX(pci_hp_mutex);
 
-#ifdef CONFIG_HOTPLUG_PCI_CPCI
-extern int cpci_hotplug_init(int debug);
-extern void cpci_hotplug_exit(void);
-#else
-static inline int cpci_hotplug_init(int debug) { return 0; }
-static inline void cpci_hotplug_exit(void) { }
-#endif
-
 /* Weee, fun with macros... */
 #define GET_STATUS(name,type)  \
 static int get_##name (struct hotplug_slot *slot, type *value)         \
@@ -524,13 +517,11 @@ int pci_hp_deregister(struct hotplug_slot *hotplug)
  *
  * Returns 0 if successful, anything else for an error.
  */
-int __must_check pci_hp_change_slot_info(struct hotplug_slot *hotplug,
-                                        struct hotplug_slot_info *info)
+int pci_hp_change_slot_info(struct hotplug_slot *hotplug,
+                           struct hotplug_slot_info *info)
 {
-       struct pci_slot *slot;
        if (!hotplug || !info)
                return -ENODEV;
-       slot = hotplug->pci_slot;
 
        memcpy(hotplug->info, info, sizeof(struct hotplug_slot_info));
 
index 2c113de943233db361a41e2bdcd92202c37a32b7..7fb326983ed69a1a1c0796ab32cbd05c9200100c 100644 (file)
@@ -127,15 +127,15 @@ struct controller {
 #define NO_CMD_CMPL(ctrl)      ((ctrl)->slot_cap & PCI_EXP_SLTCAP_NCCS)
 #define PSN(ctrl)              ((ctrl)->slot_cap >> 19)
 
-extern int pciehp_sysfs_enable_slot(struct slot *slot);
-extern int pciehp_sysfs_disable_slot(struct slot *slot);
-extern u8 pciehp_handle_attention_button(struct slot *p_slot);
-extern u8 pciehp_handle_switch_change(struct slot *p_slot);
-extern u8 pciehp_handle_presence_change(struct slot *p_slot);
-extern u8 pciehp_handle_power_fault(struct slot *p_slot);
-extern int pciehp_configure_device(struct slot *p_slot);
-extern int pciehp_unconfigure_device(struct slot *p_slot);
-extern void pciehp_queue_pushbutton_work(struct work_struct *work);
+int pciehp_sysfs_enable_slot(struct slot *slot);
+int pciehp_sysfs_disable_slot(struct slot *slot);
+u8 pciehp_handle_attention_button(struct slot *p_slot);
+u8 pciehp_handle_switch_change(struct slot *p_slot);
+u8 pciehp_handle_presence_change(struct slot *p_slot);
+u8 pciehp_handle_power_fault(struct slot *p_slot);
+int pciehp_configure_device(struct slot *p_slot);
+int pciehp_unconfigure_device(struct slot *p_slot);
+void pciehp_queue_pushbutton_work(struct work_struct *work);
 struct controller *pcie_init(struct pcie_device *dev);
 int pcie_init_notification(struct controller *ctrl);
 int pciehp_enable_slot(struct slot *p_slot);
@@ -166,8 +166,8 @@ static inline const char *slot_name(struct slot *slot)
 #include <acpi/acpi_bus.h>
 #include <linux/pci-acpi.h>
 
-extern void __init pciehp_acpi_slot_detection_init(void);
-extern int pciehp_acpi_slot_detection_check(struct pci_dev *dev);
+void __init pciehp_acpi_slot_detection_init(void);
+int pciehp_acpi_slot_detection_check(struct pci_dev *dev);
 
 static inline void pciehp_firmware_init(void)
 {
index 24d709b7388c5c7440b157b98ffd8448eebbc6ab..ead7c534095e885572c85c6963d57742dcab7bec 100644 (file)
@@ -90,7 +90,7 @@ static int __init dummy_probe(struct pcie_device *dev)
        slot = kzalloc(sizeof(*slot), GFP_KERNEL);
        if (!slot)
                return -ENOMEM;
-       slot->number = slot_cap >> 19;
+       slot->number = (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19;
        list_for_each_entry(tmp, &dummy_slots, list) {
                if (tmp->number == slot->number)
                        dup_slot_id++;
index 4a0a59b82eae8c4f791166cc9c55a36b576498ba..81df93931ad00864e987552c4e83c4b3db0d1ba5 100644 (file)
 #ifndef _RPADLPAR_IO_H_
 #define _RPADLPAR_IO_H_
 
-extern int dlpar_sysfs_init(void);
-extern void dlpar_sysfs_exit(void);
+int dlpar_sysfs_init(void);
+void dlpar_sysfs_exit(void);
 
-extern int dlpar_add_slot(char *drc_name);
-extern int dlpar_remove_slot(char *drc_name);
+int dlpar_add_slot(char *drc_name);
+int dlpar_remove_slot(char *drc_name);
 
 #endif
index df5677440a0844c76a251379a6c0259a839c4027..3135856e5e1cc62eda01bb0af2fe4b9407dcc445 100644 (file)
@@ -86,18 +86,18 @@ extern struct list_head rpaphp_slot_head;
 /* function prototypes */
 
 /* rpaphp_pci.c */
-extern int rpaphp_enable_slot(struct slot *slot);
-extern int rpaphp_get_sensor_state(struct slot *slot, int *state);
+int rpaphp_enable_slot(struct slot *slot);
+int rpaphp_get_sensor_state(struct slot *slot, int *state);
 
 /* rpaphp_core.c */
-extern int rpaphp_add_slot(struct device_node *dn);
-extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
+int rpaphp_add_slot(struct device_node *dn);
+int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
                char **drc_name, char **drc_type, int *drc_power_domain);
 
 /* rpaphp_slot.c */
-extern void dealloc_slot_struct(struct slot *slot);
-extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
-extern int rpaphp_register_slot(struct slot *slot);
-extern int rpaphp_deregister_slot(struct slot *slot);
+void dealloc_slot_struct(struct slot *slot);
+struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
+int rpaphp_register_slot(struct slot *slot);
+int rpaphp_deregister_slot(struct slot *slot);
        
 #endif                         /* _PPC64PHP_H */
index 7db249a250168766ed3f8a73d17d2899bbb7d33c..46a7b738f61f14200d726b02d6ed25784b6b0b08 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
 #include <linux/init.h>
+#include <asm/pci_debug.h>
 #include <asm/sclp.h>
 
 #define SLOT_NAME_SIZE 10
@@ -49,6 +50,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
                return -EIO;
 
        rc = sclp_pci_configure(slot->zdev->fid);
+       zpci_dbg(3, "conf fid:%x, rc:%d\n", slot->zdev->fid, rc);
        if (!rc) {
                slot->zdev->state = ZPCI_FN_STATE_CONFIGURED;
                /* automatically scan the device after is was configured */
@@ -66,16 +68,16 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
        if (!zpci_fn_configured(slot->zdev->state))
                return -EIO;
 
+       rc = zpci_disable_device(slot->zdev);
+       if (rc)
+               return rc;
        /* TODO: we rely on the user to unbind/remove the device, is that plausible
         *       or do we need to trigger that here?
         */
        rc = sclp_pci_deconfigure(slot->zdev->fid);
-       if (!rc) {
-               /* Fixme: better call List-PCI to find the disabled FH
-                  for the FID since the FH should be opaque... */
-               slot->zdev->fh &= 0x7fffffff;
+       zpci_dbg(3, "deconf fid:%x, rc:%d\n", slot->zdev->fid, rc);
+       if (!rc)
                slot->zdev->state = ZPCI_FN_STATE_STANDBY;
-       }
        return rc;
 }
 
index b849f995075a8cd13927ce0ee725279638b5796e..e260f207a90e2f22b3be53388e6cc5ab1b294920 100644 (file)
@@ -168,19 +168,19 @@ struct controller {
 #define WRONG_BUS_FREQUENCY            0x0000000D
 #define POWER_FAILURE                  0x0000000E
 
-extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl);
-extern void shpchp_remove_ctrl_files(struct controller *ctrl);
-extern int shpchp_sysfs_enable_slot(struct slot *slot);
-extern int shpchp_sysfs_disable_slot(struct slot *slot);
-extern u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
-extern u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
-extern u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
-extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
-extern int shpchp_configure_device(struct slot *p_slot);
-extern int shpchp_unconfigure_device(struct slot *p_slot);
-extern void cleanup_slots(struct controller *ctrl);
-extern void shpchp_queue_pushbutton_work(struct work_struct *work);
-extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
+int __must_check shpchp_create_ctrl_files(struct controller *ctrl);
+void shpchp_remove_ctrl_files(struct controller *ctrl);
+int shpchp_sysfs_enable_slot(struct slot *slot);
+int shpchp_sysfs_disable_slot(struct slot *slot);
+u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
+u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
+u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
+u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
+int shpchp_configure_device(struct slot *p_slot);
+int shpchp_unconfigure_device(struct slot *p_slot);
+void cleanup_slots(struct controller *ctrl);
+void shpchp_queue_pushbutton_work(struct work_struct *work);
+int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
 
 static inline const char *slot_name(struct slot *slot)
 {
index eeb23ceae4a890c807e9a0ed630bf2bca91c09f6..e8c31fe20566fbd839c7c236b234ab873f2eb428 100644 (file)
@@ -85,7 +85,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
 }
 static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
 
-int __must_check shpchp_create_ctrl_files (struct controller *ctrl)
+int shpchp_create_ctrl_files (struct controller *ctrl)
 {
        return device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
 }
index 00cc78c7aa045e9eb5ff747afce8ac3b66a57e7d..d40bed7267695fba2ed344cf1d28de56eac8659a 100644 (file)
 #include <linux/slab.h>
 
 #include "pci.h"
-#include "msi.h"
 
 static int pci_msi_enable = 1;
 
+#define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1)
+
+
 /* Arch hooks */
 
 #ifndef arch_msi_check_device
@@ -111,32 +113,26 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)
 }
 #endif
 
-static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
+static void msi_set_enable(struct pci_dev *dev, int enable)
 {
        u16 control;
 
-       BUG_ON(!pos);
-
-       pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+       pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
        control &= ~PCI_MSI_FLAGS_ENABLE;
        if (enable)
                control |= PCI_MSI_FLAGS_ENABLE;
-       pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+       pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
 }
 
 static void msix_set_enable(struct pci_dev *dev, int enable)
 {
-       int pos;
        u16 control;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-       if (pos) {
-               pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
-               control &= ~PCI_MSIX_FLAGS_ENABLE;
-               if (enable)
-                       control |= PCI_MSIX_FLAGS_ENABLE;
-               pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
-       }
+       pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
+       control &= ~PCI_MSIX_FLAGS_ENABLE;
+       if (enable)
+               control |= PCI_MSIX_FLAGS_ENABLE;
+       pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
 }
 
 static inline __attribute_const__ u32 msi_mask(unsigned x)
@@ -247,18 +243,18 @@ void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
                msg->data = readl(base + PCI_MSIX_ENTRY_DATA);
        } else {
                struct pci_dev *dev = entry->dev;
-               int pos = entry->msi_attrib.pos;
+               int pos = dev->msi_cap;
                u16 data;
 
-               pci_read_config_dword(dev, msi_lower_address_reg(pos),
-                                       &msg->address_lo);
+               pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
+                                     &msg->address_lo);
                if (entry->msi_attrib.is_64) {
-                       pci_read_config_dword(dev, msi_upper_address_reg(pos),
-                                               &msg->address_hi);
-                       pci_read_config_word(dev, msi_data_reg(pos, 1), &data);
+                       pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
+                                             &msg->address_hi);
+                       pci_read_config_word(dev, pos + PCI_MSI_DATA_64, &data);
                } else {
                        msg->address_hi = 0;
-                       pci_read_config_word(dev, msi_data_reg(pos, 0), &data);
+                       pci_read_config_word(dev, pos + PCI_MSI_DATA_32, &data);
                }
                msg->data = data;
        }
@@ -302,24 +298,24 @@ void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
                writel(msg->data, base + PCI_MSIX_ENTRY_DATA);
        } else {
                struct pci_dev *dev = entry->dev;
-               int pos = entry->msi_attrib.pos;
+               int pos = dev->msi_cap;
                u16 msgctl;
 
-               pci_read_config_word(dev, msi_control_reg(pos), &msgctl);
+               pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
                msgctl &= ~PCI_MSI_FLAGS_QSIZE;
                msgctl |= entry->msi_attrib.multiple << 4;
-               pci_write_config_word(dev, msi_control_reg(pos), msgctl);
+               pci_write_config_word(dev, pos + PCI_MSI_FLAGS, msgctl);
 
-               pci_write_config_dword(dev, msi_lower_address_reg(pos),
-                                       msg->address_lo);
+               pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
+                                      msg->address_lo);
                if (entry->msi_attrib.is_64) {
-                       pci_write_config_dword(dev, msi_upper_address_reg(pos),
-                                               msg->address_hi);
-                       pci_write_config_word(dev, msi_data_reg(pos, 1),
-                                               msg->data);
+                       pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
+                                              msg->address_hi);
+                       pci_write_config_word(dev, pos + PCI_MSI_DATA_64,
+                                             msg->data);
                } else {
-                       pci_write_config_word(dev, msi_data_reg(pos, 0),
-                                               msg->data);
+                       pci_write_config_word(dev, pos + PCI_MSI_DATA_32,
+                                             msg->data);
                }
        }
        entry->msg = *msg;
@@ -391,7 +387,6 @@ static void pci_intx_for_msi(struct pci_dev *dev, int enable)
 
 static void __pci_restore_msi_state(struct pci_dev *dev)
 {
-       int pos;
        u16 control;
        struct msi_desc *entry;
 
@@ -399,22 +394,20 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
                return;
 
        entry = irq_get_msi_desc(dev->irq);
-       pos = entry->msi_attrib.pos;
 
        pci_intx_for_msi(dev, 0);
-       msi_set_enable(dev, pos, 0);
+       msi_set_enable(dev, 0);
        arch_restore_msi_irqs(dev, dev->irq);
 
-       pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+       pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
        msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
        control &= ~PCI_MSI_FLAGS_QSIZE;
        control |= (entry->msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE;
-       pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+       pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
 }
 
 static void __pci_restore_msix_state(struct pci_dev *dev)
 {
-       int pos;
        struct msi_desc *entry;
        u16 control;
 
@@ -422,13 +415,12 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
                return;
        BUG_ON(list_empty(&dev->msi_list));
        entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
-       pos = entry->msi_attrib.pos;
-       pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+       pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
 
        /* route the table */
        pci_intx_for_msi(dev, 0);
        control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL;
-       pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+       pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
 
        list_for_each_entry(entry, &dev->msi_list, list) {
                arch_restore_msi_irqs(dev, entry->irq);
@@ -436,7 +428,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
        }
 
        control &= ~PCI_MSIX_FLAGS_MASKALL;
-       pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+       pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
 }
 
 void pci_restore_msi_state(struct pci_dev *dev)
@@ -484,12 +476,12 @@ static struct msi_attribute mode_attribute =
        __ATTR(mode, S_IRUGO, show_msi_mode, NULL);
 
 
-struct attribute *msi_irq_default_attrs[] = {
+static struct attribute *msi_irq_default_attrs[] = {
        &mode_attribute.attr,
        NULL
 };
 
-void msi_kobj_release(struct kobject *kobj)
+static void msi_kobj_release(struct kobject *kobj)
 {
        struct msi_desc *entry = to_msi_desc(kobj);
 
@@ -552,27 +544,27 @@ out_unroll:
 static int msi_capability_init(struct pci_dev *dev, int nvec)
 {
        struct msi_desc *entry;
-       int pos, ret;
+       int ret;
        u16 control;
        unsigned mask;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
-       msi_set_enable(dev, pos, 0);    /* Disable MSI during set up */
+       msi_set_enable(dev, 0); /* Disable MSI during set up */
 
-       pci_read_config_word(dev, msi_control_reg(pos), &control);
+       pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
        /* MSI Entry Initialization */
        entry = alloc_msi_entry(dev);
        if (!entry)
                return -ENOMEM;
 
        entry->msi_attrib.is_msix       = 0;
-       entry->msi_attrib.is_64         = is_64bit_address(control);
+       entry->msi_attrib.is_64         = !!(control & PCI_MSI_FLAGS_64BIT);
        entry->msi_attrib.entry_nr      = 0;
-       entry->msi_attrib.maskbit       = is_mask_bit_support(control);
+       entry->msi_attrib.maskbit       = !!(control & PCI_MSI_FLAGS_MASKBIT);
        entry->msi_attrib.default_irq   = dev->irq;     /* Save IOAPIC IRQ */
-       entry->msi_attrib.pos           = pos;
+       entry->msi_attrib.pos           = dev->msi_cap;
 
-       entry->mask_pos = msi_mask_reg(pos, entry->msi_attrib.is_64);
+       entry->mask_pos = dev->msi_cap + (control & PCI_MSI_FLAGS_64BIT) ?
+               PCI_MSI_MASK_64 : PCI_MSI_MASK_32;
        /* All MSIs are unmasked by default, Mask them all */
        if (entry->msi_attrib.maskbit)
                pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
@@ -598,31 +590,30 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
 
        /* Set MSI enabled bits  */
        pci_intx_for_msi(dev, 0);
-       msi_set_enable(dev, pos, 1);
+       msi_set_enable(dev, 1);
        dev->msi_enabled = 1;
 
        dev->irq = entry->irq;
        return 0;
 }
 
-static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos,
-                                                       unsigned nr_entries)
+static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries)
 {
        resource_size_t phys_addr;
        u32 table_offset;
        u8 bir;
 
-       pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset);
-       bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
-       table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
+       pci_read_config_dword(dev, dev->msix_cap + PCI_MSIX_TABLE,
+                             &table_offset);
+       bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR);
+       table_offset &= PCI_MSIX_TABLE_OFFSET;
        phys_addr = pci_resource_start(dev, bir) + table_offset;
 
        return ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
 }
 
-static int msix_setup_entries(struct pci_dev *dev, unsigned pos,
-                               void __iomem *base, struct msix_entry *entries,
-                               int nvec)
+static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
+                             struct msix_entry *entries, int nvec)
 {
        struct msi_desc *entry;
        int i;
@@ -642,7 +633,7 @@ static int msix_setup_entries(struct pci_dev *dev, unsigned pos,
                entry->msi_attrib.is_64         = 1;
                entry->msi_attrib.entry_nr      = entries[i].entry;
                entry->msi_attrib.default_irq   = dev->irq;
-               entry->msi_attrib.pos           = pos;
+               entry->msi_attrib.pos           = dev->msix_cap;
                entry->mask_base                = base;
 
                list_add_tail(&entry->list, &dev->msi_list);
@@ -652,7 +643,7 @@ static int msix_setup_entries(struct pci_dev *dev, unsigned pos,
 }
 
 static void msix_program_entries(struct pci_dev *dev,
-                                       struct msix_entry *entries)
+                                struct msix_entry *entries)
 {
        struct msi_desc *entry;
        int i = 0;
@@ -682,23 +673,22 @@ static void msix_program_entries(struct pci_dev *dev,
 static int msix_capability_init(struct pci_dev *dev,
                                struct msix_entry *entries, int nvec)
 {
-       int pos, ret;
+       int ret;
        u16 control;
        void __iomem *base;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-       pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+       pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
 
        /* Ensure MSI-X is disabled while it is set up */
        control &= ~PCI_MSIX_FLAGS_ENABLE;
-       pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+       pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
 
        /* Request & Map MSI-X table region */
-       base = msix_map_region(dev, pos, multi_msix_capable(control));
+       base = msix_map_region(dev, msix_table_size(control));
        if (!base)
                return -ENOMEM;
 
-       ret = msix_setup_entries(dev, pos, base, entries, nvec);
+       ret = msix_setup_entries(dev, base, entries, nvec);
        if (ret)
                return ret;
 
@@ -712,7 +702,7 @@ static int msix_capability_init(struct pci_dev *dev,
         * interrupts coming in before they're fully set up.
         */
        control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE;
-       pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+       pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
 
        msix_program_entries(dev, entries);
 
@@ -727,7 +717,7 @@ static int msix_capability_init(struct pci_dev *dev,
        dev->msix_enabled = 1;
 
        control &= ~PCI_MSIX_FLAGS_MASKALL;
-       pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+       pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
 
        return 0;
 
@@ -795,9 +785,6 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)
        if (ret)
                return ret;
 
-       if (!pci_find_capability(dev, type))
-               return -EINVAL;
-
        return 0;
 }
 
@@ -816,13 +803,13 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)
  */
 int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
 {
-       int status, pos, maxvec;
+       int status, maxvec;
        u16 msgctl;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
-       if (!pos)
+       if (!dev->msi_cap)
                return -EINVAL;
-       pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
+
+       pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
        maxvec = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
        if (nvec > maxvec)
                return maxvec;
@@ -847,14 +834,13 @@ EXPORT_SYMBOL(pci_enable_msi_block);
 
 int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)
 {
-       int ret, pos, nvec;
+       int ret, nvec;
        u16 msgctl;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
-       if (!pos)
+       if (!dev->msi_cap)
                return -EINVAL;
 
-       pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
+       pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
        ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
 
        if (maxvec)
@@ -876,21 +862,19 @@ void pci_msi_shutdown(struct pci_dev *dev)
        struct msi_desc *desc;
        u32 mask;
        u16 ctrl;
-       unsigned pos;
 
        if (!pci_msi_enable || !dev || !dev->msi_enabled)
                return;
 
        BUG_ON(list_empty(&dev->msi_list));
        desc = list_first_entry(&dev->msi_list, struct msi_desc, list);
-       pos = desc->msi_attrib.pos;
 
-       msi_set_enable(dev, pos, 0);
+       msi_set_enable(dev, 0);
        pci_intx_for_msi(dev, 1);
        dev->msi_enabled = 0;
 
        /* Return the device with MSI unmasked as initial states */
-       pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl);
+       pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &ctrl);
        mask = msi_capable_mask(ctrl);
        /* Keep cached state to be restored */
        __msi_mask_irq(desc, mask, ~mask);
@@ -917,15 +901,13 @@ EXPORT_SYMBOL(pci_disable_msi);
  */
 int pci_msix_table_size(struct pci_dev *dev)
 {
-       int pos;
        u16 control;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-       if (!pos)
+       if (!dev->msix_cap)
                return 0;
 
-       pci_read_config_word(dev, msi_control_reg(pos), &control);
-       return multi_msix_capable(control);
+       pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
+       return msix_table_size(control);
 }
 
 /**
@@ -948,7 +930,7 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
        int status, nr_entries;
        int i, j;
 
-       if (!entries)
+       if (!entries || !dev->msix_cap)
                return -EINVAL;
 
        status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);
@@ -1048,15 +1030,17 @@ EXPORT_SYMBOL(pci_msi_enabled);
 
 void pci_msi_init_pci_dev(struct pci_dev *dev)
 {
-       int pos;
        INIT_LIST_HEAD(&dev->msi_list);
 
        /* Disable the msi hardware to avoid screaming interrupts
         * during boot.  This is the power on reset default so
         * usually this should be a noop.
         */
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
-       if (pos)
-               msi_set_enable(dev, pos, 0);
-       msix_set_enable(dev, 0);
+       dev->msi_cap = pci_find_capability(dev, PCI_CAP_ID_MSI);
+       if (dev->msi_cap)
+               msi_set_enable(dev, 0);
+
+       dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+       if (dev->msix_cap)
+               msix_set_enable(dev, 0);
 }
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
deleted file mode 100644 (file)
index 65c42f8..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2003-2004 Intel
- * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
- */
-
-#ifndef MSI_H
-#define MSI_H
-
-#define msi_control_reg(base)          (base + PCI_MSI_FLAGS)
-#define msi_lower_address_reg(base)    (base + PCI_MSI_ADDRESS_LO)
-#define msi_upper_address_reg(base)    (base + PCI_MSI_ADDRESS_HI)
-#define msi_data_reg(base, is64bit)    \
-       (base + ((is64bit == 1) ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32))
-#define msi_mask_reg(base, is64bit)    \
-       (base + ((is64bit == 1) ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32))
-#define is_64bit_address(control)      (!!(control & PCI_MSI_FLAGS_64BIT))
-#define is_mask_bit_support(control)   (!!(control & PCI_MSI_FLAGS_MASKBIT))
-
-#define msix_table_offset_reg(base)    (base + PCI_MSIX_TABLE)
-#define msix_pba_offset_reg(base)      (base + PCI_MSIX_PBA)
-#define msix_table_size(control)       ((control & PCI_MSIX_FLAGS_QSIZE)+1)
-#define multi_msix_capable(control)    msix_table_size((control))
-
-#endif /* MSI_H */
index dee5dddaa292a04ad2200c005ad59b959ed5ad7e..e4b1fb2c0f5d83029e0a62ffa4aaef36f4559da3 100644 (file)
@@ -53,14 +53,15 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
                return;
        }
 
-       if (!pci_dev->pm_cap || !pci_dev->pme_support
-            || pci_check_pme_status(pci_dev)) {
-               if (pci_dev->pme_poll)
-                       pci_dev->pme_poll = false;
+       /* Clear PME Status if set. */
+       if (pci_dev->pme_support)
+               pci_check_pme_status(pci_dev);
 
-               pci_wakeup_event(pci_dev);
-               pm_runtime_resume(&pci_dev->dev);
-       }
+       if (pci_dev->pme_poll)
+               pci_dev->pme_poll = false;
+
+       pci_wakeup_event(pci_dev);
+       pm_runtime_resume(&pci_dev->dev);
 
        if (pci_dev->subordinate)
                pci_pme_wakeup_bus(pci_dev->subordinate);
@@ -287,6 +288,32 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {
        .run_wake = acpi_pci_run_wake,
 };
 
+void acpi_pci_add_bus(struct pci_bus *bus)
+{
+       acpi_handle handle = NULL;
+
+       if (bus->bridge)
+               handle = ACPI_HANDLE(bus->bridge);
+       if (acpi_pci_disabled || handle == NULL)
+               return;
+
+       acpi_pci_slot_enumerate(bus, handle);
+       acpiphp_enumerate_slots(bus, handle);
+}
+
+void acpi_pci_remove_bus(struct pci_bus *bus)
+{
+       /*
+        * bus->bridge->acpi_node.handle has already been reset to NULL
+        * when acpi_pci_remove_bus() is called, so don't check ACPI handle.
+        */
+       if (acpi_pci_disabled)
+               return;
+
+       acpiphp_remove_slots(bus);
+       acpi_pci_slot_remove(bus);
+}
+
 /* ACPI bus type */
 static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
 {
@@ -361,7 +388,11 @@ static int __init acpi_pci_init(void)
        ret = register_acpi_bus_type(&acpi_pci_bus);
        if (ret)
                return 0;
+
        pci_set_platform_pm(&acpi_pci_platform_pm);
+       acpi_pci_slot_init();
+       acpiphp_init();
+
        return 0;
 }
 arch_initcall(acpi_pci_init);
index 1fa1e482a99976d36d8e91b2affee58af3bda693..79277fb36c6bf7a85b4634df28ff13d1905d703d 100644 (file)
@@ -390,9 +390,10 @@ static void pci_device_shutdown(struct device *dev)
 
        /*
         * Turn off Bus Master bit on the device to tell it to not
-        * continue to do DMA
+        * continue to do DMA. Don't touch devices in D3cold or unknown states.
         */
-       pci_clear_master(pci_dev);
+       if (pci_dev->current_state <= PCI_D3hot)
+               pci_clear_master(pci_dev);
 }
 
 #ifdef CONFIG_PM
index 9c6e9bb674ec54835d40e09b6c77d0683cd9265d..5b4a9d9cd200dd5a6ee32c3d343bbae0cf2ff8ac 100644 (file)
@@ -897,7 +897,7 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
 
        if (pci_resource_len(pdev, resno) == 0)
                return 0;
-       nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       nr = vma_pages(vma);
        start = vma->vm_pgoff;
        size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
        pci_start = (mmap_api == PCI_MMAP_PROCFS) ?
index b099e0025d2bb55dff5ec8ee922b617f86f68676..a899d8bb190d897e014f605eec53b496152a0cea 100644 (file)
@@ -646,15 +646,11 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)
                error = platform_pci_set_power_state(dev, state);
                if (!error)
                        pci_update_current_state(dev, state);
-               /* Fall back to PCI_D0 if native PM is not supported */
-               if (!dev->pm_cap)
-                       dev->current_state = PCI_D0;
-       } else {
+       } else
                error = -ENODEV;
-               /* Fall back to PCI_D0 if native PM is not supported */
-               if (!dev->pm_cap)
-                       dev->current_state = PCI_D0;
-       }
+
+       if (error && !dev->pm_cap) /* Fall back to PCI_D0 */
+               dev->current_state = PCI_D0;
 
        return error;
 }
@@ -1575,7 +1571,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
 {
        u16 pmcsr;
 
-       if (!dev->pm_cap)
+       if (!dev->pme_support)
                return;
 
        pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
@@ -1924,6 +1920,7 @@ void pci_pm_init(struct pci_dev *dev)
        dev->wakeup_prepared = false;
 
        dev->pm_cap = 0;
+       dev->pme_support = 0;
 
        /* find PCI PM capability in list */
        pm = pci_find_capability(dev, PCI_CAP_ID_PM);
@@ -1975,8 +1972,6 @@ void pci_pm_init(struct pci_dev *dev)
                device_set_wakeup_capable(&dev->dev, true);
                /* Disable the PME# generation functionality */
                pci_pme_active(dev, false);
-       } else {
-               dev->pme_support = 0;
        }
 }
 
@@ -2619,7 +2614,7 @@ void pci_release_selected_regions(struct pci_dev *pdev, int bars)
                        pci_release_region(pdev, i);
 }
 
-int __pci_request_selected_regions(struct pci_dev *pdev, int bars,
+static int __pci_request_selected_regions(struct pci_dev *pdev, int bars,
                                 const char *res_name, int excl)
 {
        int i;
@@ -3699,7 +3694,7 @@ static DEFINE_SPINLOCK(resource_alignment_lock);
  * RETURNS: Resource alignment if it is specified.
  *          Zero if it is not specified.
  */
-resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
+static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
 {
        int seg, bus, slot, func, align_order, count;
        resource_size_t align = 0;
@@ -3812,7 +3807,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
        }
 }
 
-ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)
+static ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)
 {
        if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1)
                count = RESOURCE_ALIGNMENT_PARAM_SIZE - 1;
@@ -3823,7 +3818,7 @@ ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)
        return count;
 }
 
-ssize_t pci_get_resource_alignment_param(char *buf, size_t size)
+static ssize_t pci_get_resource_alignment_param(char *buf, size_t size)
 {
        size_t count;
        spin_lock(&resource_alignment_lock);
index 7346ee68f47d198ce67df5a1445cef9203556b0b..68678ed76b0da93114280ae2ec878457159f63c5 100644 (file)
@@ -8,26 +8,25 @@
 
 /* Functions internal to the PCI core code */
 
-extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
-extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
+int pci_create_sysfs_dev_files(struct pci_dev *pdev);
+void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
 #if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI)
 static inline void pci_create_firmware_label_files(struct pci_dev *pdev)
 { return; }
 static inline void pci_remove_firmware_label_files(struct pci_dev *pdev)
 { return; }
 #else
-extern void pci_create_firmware_label_files(struct pci_dev *pdev);
-extern void pci_remove_firmware_label_files(struct pci_dev *pdev);
+void pci_create_firmware_label_files(struct pci_dev *pdev);
+void pci_remove_firmware_label_files(struct pci_dev *pdev);
 #endif
-extern void pci_cleanup_rom(struct pci_dev *dev);
+void pci_cleanup_rom(struct pci_dev *dev);
 #ifdef HAVE_PCI_MMAP
 enum pci_mmap_api {
        PCI_MMAP_SYSFS, /* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */
        PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/<BDF> */
 };
-extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
-                        struct vm_area_struct *vmai,
-                        enum pci_mmap_api mmap_api);
+int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,
+                 enum pci_mmap_api mmap_api);
 #endif
 int pci_probe_reset_function(struct pci_dev *dev);
 
@@ -60,17 +59,17 @@ struct pci_platform_pm_ops {
        int (*run_wake)(struct pci_dev *dev, bool enable);
 };
 
-extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
-extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
-extern void pci_power_up(struct pci_dev *dev);
-extern void pci_disable_enabled_device(struct pci_dev *dev);
-extern int pci_finish_runtime_suspend(struct pci_dev *dev);
-extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
-extern void pci_wakeup_bus(struct pci_bus *bus);
-extern void pci_config_pm_runtime_get(struct pci_dev *dev);
-extern void pci_config_pm_runtime_put(struct pci_dev *dev);
-extern void pci_pm_init(struct pci_dev *dev);
-extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
+int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
+void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
+void pci_power_up(struct pci_dev *dev);
+void pci_disable_enabled_device(struct pci_dev *dev);
+int pci_finish_runtime_suspend(struct pci_dev *dev);
+int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
+void pci_wakeup_bus(struct pci_bus *bus);
+void pci_config_pm_runtime_get(struct pci_dev *dev);
+void pci_config_pm_runtime_put(struct pci_dev *dev);
+void pci_pm_init(struct pci_dev *dev);
+void pci_allocate_cap_save_buffers(struct pci_dev *dev);
 void pci_free_cap_save_buffers(struct pci_dev *dev);
 
 static inline void pci_wakeup_event(struct pci_dev *dev)
@@ -96,7 +95,7 @@ struct pci_vpd {
        struct bin_attribute *attr; /* descriptor for sysfs VPD entry */
 };
 
-extern int pci_vpd_pci22_init(struct pci_dev *dev);
+int pci_vpd_pci22_init(struct pci_dev *dev);
 static inline void pci_vpd_release(struct pci_dev *dev)
 {
        if (dev->vpd)
@@ -105,9 +104,9 @@ static inline void pci_vpd_release(struct pci_dev *dev)
 
 /* PCI /proc functions */
 #ifdef CONFIG_PROC_FS
-extern int pci_proc_attach_device(struct pci_dev *dev);
-extern int pci_proc_detach_device(struct pci_dev *dev);
-extern int pci_proc_detach_bus(struct pci_bus *bus);
+int pci_proc_attach_device(struct pci_dev *dev);
+int pci_proc_detach_device(struct pci_dev *dev);
+int pci_proc_detach_bus(struct pci_bus *bus);
 #else
 static inline int pci_proc_attach_device(struct pci_dev *dev) { return 0; }
 static inline int pci_proc_detach_device(struct pci_dev *dev) { return 0; }
@@ -118,8 +117,8 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
 int pci_hp_add_bridge(struct pci_dev *dev);
 
 #ifdef HAVE_PCI_LEGACY
-extern void pci_create_legacy_files(struct pci_bus *bus);
-extern void pci_remove_legacy_files(struct pci_bus *bus);
+void pci_create_legacy_files(struct pci_bus *bus);
+void pci_remove_legacy_files(struct pci_bus *bus);
 #else
 static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
 static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
@@ -134,7 +133,7 @@ extern unsigned int pci_pm_d3_delay;
 
 #ifdef CONFIG_PCI_MSI
 void pci_no_msi(void);
-extern void pci_msi_init_pci_dev(struct pci_dev *dev);
+void pci_msi_init_pci_dev(struct pci_dev *dev);
 #else
 static inline void pci_no_msi(void) { }
 static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
@@ -198,12 +197,11 @@ enum pci_bar_type {
 
 bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *pl,
                                int crs_timeout);
-extern int pci_setup_device(struct pci_dev *dev);
-extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
-                               struct resource *res, unsigned int reg);
-extern int pci_resource_bar(struct pci_dev *dev, int resno,
-                           enum pci_bar_type *type);
-extern void pci_configure_ari(struct pci_dev *dev);
+int pci_setup_device(struct pci_dev *dev);
+int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
+                   struct resource *res, unsigned int reg);
+int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type);
+void pci_configure_ari(struct pci_dev *dev);
 
 /**
  * pci_ari_enabled - query ARI forwarding status
@@ -217,7 +215,7 @@ static inline int pci_ari_enabled(struct pci_bus *bus)
 }
 
 void pci_reassigndev_resource_alignment(struct pci_dev *dev);
-extern void pci_disable_bridge_window(struct pci_dev *dev);
+void pci_disable_bridge_window(struct pci_dev *dev);
 
 /* Single Root I/O Virtualization */
 struct pci_sriov {
@@ -241,7 +239,7 @@ struct pci_sriov {
 };
 
 #ifdef CONFIG_PCI_ATS
-extern void pci_restore_ats_state(struct pci_dev *dev);
+void pci_restore_ats_state(struct pci_dev *dev);
 #else
 static inline void pci_restore_ats_state(struct pci_dev *dev)
 {
@@ -249,14 +247,13 @@ static inline void pci_restore_ats_state(struct pci_dev *dev)
 #endif /* CONFIG_PCI_ATS */
 
 #ifdef CONFIG_PCI_IOV
-extern int pci_iov_init(struct pci_dev *dev);
-extern void pci_iov_release(struct pci_dev *dev);
-extern int pci_iov_resource_bar(struct pci_dev *dev, int resno,
-                               enum pci_bar_type *type);
-extern resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev,
-                                                   int resno);
-extern void pci_restore_iov_state(struct pci_dev *dev);
-extern int pci_iov_bus_range(struct pci_bus *bus);
+int pci_iov_init(struct pci_dev *dev);
+void pci_iov_release(struct pci_dev *dev);
+int pci_iov_resource_bar(struct pci_dev *dev, int resno,
+                        enum pci_bar_type *type);
+resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
+void pci_restore_iov_state(struct pci_dev *dev);
+int pci_iov_bus_range(struct pci_bus *bus);
 
 #else
 static inline int pci_iov_init(struct pci_dev *dev)
@@ -282,10 +279,10 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)
 
 #endif /* CONFIG_PCI_IOV */
 
-extern unsigned long pci_cardbus_resource_alignment(struct resource *);
+unsigned long pci_cardbus_resource_alignment(struct resource *);
 
 static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
-                                        struct resource *res)
+                                                    struct resource *res)
 {
 #ifdef CONFIG_PCI_IOV
        int resno = res - dev->resource;
@@ -298,7 +295,7 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
        return resource_alignment(res);
 }
 
-extern void pci_enable_acs(struct pci_dev *dev);
+void pci_enable_acs(struct pci_dev *dev);
 
 struct pci_dev_reset_methods {
        u16 vendor;
@@ -307,7 +304,7 @@ struct pci_dev_reset_methods {
 };
 
 #ifdef CONFIG_PCI_QUIRKS
-extern int pci_dev_specific_reset(struct pci_dev *dev, int probe);
+int pci_dev_specific_reset(struct pci_dev *dev, int probe);
 #else
 static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
 {
index fde4a32a0295082a95de76b6ea08dc1d59fdc2a9..569f82fc9e22bb826fbfca36ba74b891cc15b0d8 100644 (file)
@@ -82,4 +82,4 @@ endchoice
 
 config PCIE_PME
        def_bool y
-       depends on PCIEPORTBUS && PM_RUNTIME && ACPI
+       depends on PCIEPORTBUS && PM_RUNTIME
index 4e24cb8a94aec0ecee6e0e923f5ffee50439e601..587e7e853107136b81f416d0e1e932db855bfa61 100644 (file)
@@ -212,8 +212,8 @@ out:
        return ops->read(bus, devfn, where, size, val);
 }
 
-int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size,
-                 u32 val)
+static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where,
+                        int size, u32 val)
 {
        u32 *sim;
        struct aer_error *err;
@@ -334,13 +334,13 @@ static int aer_inject(struct aer_error_inj *einj)
                return -ENODEV;
        rpdev = pcie_find_root_port(dev);
        if (!rpdev) {
-               ret = -ENOTTY;
+               ret = -ENODEV;
                goto out_put;
        }
 
        pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
        if (!pos_cap_err) {
-               ret = -ENOTTY;
+               ret = -EPERM;
                goto out_put;
        }
        pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever);
@@ -350,7 +350,7 @@ static int aer_inject(struct aer_error_inj *einj)
 
        rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
        if (!rp_pos_cap_err) {
-               ret = -ENOTTY;
+               ret = -EPERM;
                goto out_put;
        }
 
index 22f840f4dda1065eb97b54da307b5f6d2dda0c5a..d12c77cd6991f75c8b62008dc4ce160d6ffec36f 100644 (file)
@@ -110,15 +110,15 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
 }
 
 extern struct bus_type pcie_port_bus_type;
-extern void aer_do_secondary_bus_reset(struct pci_dev *dev);
-extern int aer_init(struct pcie_device *dev);
-extern void aer_isr(struct work_struct *work);
-extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
-extern void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info);
-extern irqreturn_t aer_irq(int irq, void *context);
+void aer_do_secondary_bus_reset(struct pci_dev *dev);
+int aer_init(struct pcie_device *dev);
+void aer_isr(struct work_struct *work);
+void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
+void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info);
+irqreturn_t aer_irq(int irq, void *context);
 
 #ifdef CONFIG_ACPI_APEI
-extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
+int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
 #else
 static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
 {
index 564d97f94b6cd4d248b7cdad8b3b4e138144ff97..8ec8b4f485604e384de9bf7eddfe2c97c4cae5d5 100644 (file)
@@ -89,8 +89,6 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
        return -ENOSPC;
 }
 
-#define        PCI_BUS(x)      (((x) >> 8) & 0xff)
-
 /**
  * is_error_source - check whether the device is source of reported error
  * @dev: pointer to pci_dev to be checked
@@ -106,7 +104,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
         * When bus id is equal to 0, it might be a bad id
         * reported by root port.
         */
-       if (!nosourceid && (PCI_BUS(e_info->id) != 0)) {
+       if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) {
                /* Device ID match? */
                if (e_info->id == ((dev->bus->number << 8) | dev->devfn))
                        return true;
index 9ca0dc9ffd84ea369a20a05b087711111a7179ec..795db1f9d50c695893419b766697850c17511752 100644 (file)
@@ -19,8 +19,6 @@
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/pcieport_if.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
 #include <linux/pm_runtime.h>
 
 #include "../pci.h"
index eea2ca2375e6be13ef07cb6d766d78b4d96c5d12..d2eb80aab56956d299a48208ea5d296cda0dce66 100644 (file)
 #define get_descriptor_id(type, service) (((type - 4) << 4) | service)
 
 extern struct bus_type pcie_port_bus_type;
-extern int pcie_port_device_register(struct pci_dev *dev);
+int pcie_port_device_register(struct pci_dev *dev);
 #ifdef CONFIG_PM
-extern int pcie_port_device_suspend(struct device *dev);
-extern int pcie_port_device_resume(struct device *dev);
+int pcie_port_device_suspend(struct device *dev);
+int pcie_port_device_resume(struct device *dev);
 #endif
-extern void pcie_port_device_remove(struct pci_dev *dev);
-extern int __must_check pcie_port_bus_register(void);
-extern void pcie_port_bus_unregister(void);
+void pcie_port_device_remove(struct pci_dev *dev);
+int __must_check pcie_port_bus_register(void);
+void pcie_port_bus_unregister(void);
 
 struct pci_dev;
 
-extern void pcie_clear_root_pme_status(struct pci_dev *dev);
+void pcie_clear_root_pme_status(struct pci_dev *dev);
 
 #ifdef CONFIG_HOTPLUG_PCI_PCIE
 extern bool pciehp_msi_disabled;
@@ -59,7 +59,7 @@ static inline bool pcie_pme_no_msi(void)
        return pcie_pme_msi_disabled;
 }
 
-extern void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable);
+void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable);
 #else /* !CONFIG_PCIE_PME */
 static inline void pcie_pme_disable_msi(void) {}
 static inline bool pcie_pme_no_msi(void) { return false; }
@@ -67,7 +67,7 @@ static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {}
 #endif /* !CONFIG_PCIE_PME */
 
 #ifdef CONFIG_ACPI
-extern int pcie_port_acpi_setup(struct pci_dev *port, int *mask);
+int pcie_port_acpi_setup(struct pci_dev *port, int *mask);
 
 static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask)
 {
index a86b56e5f2f2c5c4761f029c79c674b078f13a1d..b4d2894ee3fc83c8e60a1fc8159452d8a54ad8dd 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "aer/aerdrv.h"
 #include "../pci.h"
+#include "portdrv.h"
 
 /**
  * pcie_port_acpi_setup - Request the BIOS to release control of PCIe services.
index 08c243ab034e9bc9172dfd593f4cb0ceabbe2f60..696caed5fdf557198db4bef5201df2a6c04c83d2 100644 (file)
@@ -184,14 +184,6 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
 #define PCIE_PORTDRV_PM_OPS    NULL
 #endif /* !PM */
 
-/*
- * PCIe port runtime suspend is broken for some chipsets, so use a
- * black list to disable runtime PM for these chipsets.
- */
-static const struct pci_device_id port_runtime_pm_black_list[] = {
-       { /* end: all zeroes */ }
-};
-
 /*
  * pcie_portdrv_probe - Probe PCI-Express port devices
  * @dev: PCI-Express port device being probed
@@ -225,16 +217,11 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
         * it by default.
         */
        dev->d3cold_allowed = false;
-       if (!pci_match_id(port_runtime_pm_black_list, dev))
-               pm_runtime_put_noidle(&dev->dev);
-
        return 0;
 }
 
 static void pcie_portdrv_remove(struct pci_dev *dev)
 {
-       if (!pci_match_id(port_runtime_pm_black_list, dev))
-               pm_runtime_get_noresume(&dev->dev);
        pcie_port_device_remove(dev);
        pci_disable_device(dev);
 }
@@ -272,11 +259,9 @@ static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
                                        enum pci_channel_state error)
 {
        struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER};
-       int ret;
-
-       /* can not fail */
-       ret = device_for_each_child(&dev->dev, &data, error_detected_iter);
 
+       /* get true return value from &data */
+       device_for_each_child(&dev->dev, &data, error_detected_iter);
        return data.result;
 }
 
@@ -308,10 +293,9 @@ static int mmio_enabled_iter(struct device *device, void *data)
 static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
 {
        pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
-       int retval;
 
        /* get true return value from &status */
-       retval = device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
+       device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
        return status;
 }
 
@@ -343,7 +327,6 @@ static int slot_reset_iter(struct device *device, void *data)
 static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
 {
        pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
-       int retval;
 
        /* If fatal, restore cfg space for possible link reset at upstream */
        if (dev->error_state == pci_channel_io_frozen) {
@@ -354,8 +337,7 @@ static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
        }
 
        /* get true return value from &status */
-       retval = device_for_each_child(&dev->dev, &status, slot_reset_iter);
-
+       device_for_each_child(&dev->dev, &status, slot_reset_iter);
        return status;
 }
 
@@ -381,9 +363,7 @@ static int resume_iter(struct device *device, void *data)
 
 static void pcie_portdrv_err_resume(struct pci_dev *dev)
 {
-       int retval;
-       /* nothing to do with error value, if it ever happens */
-       retval = device_for_each_child(&dev->dev, NULL, resume_iter);
+       device_for_each_child(&dev->dev, NULL, resume_iter);
 }
 
 /*
index b494066ef32f5f08e3f5d4f4b3d88acf9257d710..43ece5d41d36ca428068ef8b09f01f5956f10a25 100644 (file)
@@ -673,6 +673,8 @@ add_dev:
        ret = device_register(&child->dev);
        WARN_ON(ret < 0);
 
+       pcibios_add_bus(child);
+
        /* Create legacy_io and legacy_mem files for this bus */
        pci_create_legacy_files(child);
 
@@ -1627,8 +1629,7 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
        if (!bus->is_added) {
                dev_dbg(&bus->dev, "fixups for bus\n");
                pcibios_fixup_bus(bus);
-               if (pci_is_root_bus(bus))
-                       bus->is_added = 1;
+               bus->is_added = 1;
        }
 
        for (pass=0; pass < 2; pass++)
@@ -1661,6 +1662,14 @@ int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
        return 0;
 }
 
+void __weak pcibios_add_bus(struct pci_bus *bus)
+{
+}
+
+void __weak pcibios_remove_bus(struct pci_bus *bus)
+{
+}
+
 struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
                struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
@@ -1715,6 +1724,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
        if (error)
                goto class_dev_reg_err;
 
+       pcibios_add_bus(b);
+
        /* Create legacy_io and legacy_mem files for this bus */
        pci_create_legacy_files(b);
 
index 0369fb6fc1da412d2f55d8346d2dca0a9424b158..7d68aeebf56b1a53d447bd0e152643d85d06ea44 100644 (file)
@@ -324,29 +324,30 @@ static void quirk_cs5536_vsa(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
 
-static void quirk_io_region(struct pci_dev *dev, unsigned region,
-       unsigned size, int nr, const char *name)
+static void quirk_io_region(struct pci_dev *dev, int port,
+                               unsigned size, int nr, const char *name)
 {
-       region &= ~(size-1);
-       if (region) {
-               struct pci_bus_region bus_region;
-               struct resource *res = dev->resource + nr;
+       u16 region;
+       struct pci_bus_region bus_region;
+       struct resource *res = dev->resource + nr;
 
-               res->name = pci_name(dev);
-               res->start = region;
-               res->end = region + size - 1;
-               res->flags = IORESOURCE_IO;
+       pci_read_config_word(dev, port, &region);
+       region &= ~(size - 1);
 
-               /* Convert from PCI bus to resource space.  */
-               bus_region.start = res->start;
-               bus_region.end = res->end;
-               pcibios_bus_to_resource(dev, res, &bus_region);
+       if (!region)
+               return;
 
-               if (pci_claim_resource(dev, nr) == 0)
-                       dev_info(&dev->dev, "quirk: %pR claimed by %s\n",
-                                res, name);
-       }
-}      
+       res->name = pci_name(dev);
+       res->flags = IORESOURCE_IO;
+
+       /* Convert from PCI bus to resource space */
+       bus_region.start = region;
+       bus_region.end = region + size - 1;
+       pcibios_bus_to_resource(dev, res, &bus_region);
+
+       if (!pci_claim_resource(dev, nr))
+               dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name);
+}
 
 /*
  *     ATI Northbridge setups MCE the processor if you even
@@ -374,12 +375,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100,   quirk_ati_
  */
 static void quirk_ali7101_acpi(struct pci_dev *dev)
 {
-       u16 region;
-
-       pci_read_config_word(dev, 0xE0, &region);
-       quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI");
-       pci_read_config_word(dev, 0xE2, &region);
-       quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB");
+       quirk_io_region(dev, 0xE0, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI");
+       quirk_io_region(dev, 0xE2, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB");
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL,     PCI_DEVICE_ID_AL_M7101,         quirk_ali7101_acpi);
 
@@ -442,12 +439,10 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int
  */
 static void quirk_piix4_acpi(struct pci_dev *dev)
 {
-       u32 region, res_a;
+       u32 res_a;
 
-       pci_read_config_dword(dev, 0x40, &region);
-       quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI");
-       pci_read_config_dword(dev, 0x90, &region);
-       quirk_io_region(dev, region, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");
+       quirk_io_region(dev, 0x40, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI");
+       quirk_io_region(dev, 0x90, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");
 
        /* Device resource A has enables for some of the other ones */
        pci_read_config_dword(dev, 0x5c, &res_a);
@@ -491,7 +486,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,       PCI_DEVICE_ID_INTEL_82443MX_3,  qui
  */
 static void quirk_ich4_lpc_acpi(struct pci_dev *dev)
 {
-       u32 region;
        u8 enable;
 
        /*
@@ -503,22 +497,14 @@ static void quirk_ich4_lpc_acpi(struct pci_dev *dev)
        */
 
        pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
-       if (enable & ICH4_ACPI_EN) {
-               pci_read_config_dword(dev, ICH_PMBASE, &region);
-               region &= PCI_BASE_ADDRESS_IO_MASK;
-               if (region >= PCIBIOS_MIN_IO)
-                       quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
-                                       "ICH4 ACPI/GPIO/TCO");
-       }
+       if (enable & ICH4_ACPI_EN)
+               quirk_io_region(dev, ICH_PMBASE, 128, PCI_BRIDGE_RESOURCES,
+                                "ICH4 ACPI/GPIO/TCO");
 
        pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable);
-       if (enable & ICH4_GPIO_EN) {
-               pci_read_config_dword(dev, ICH4_GPIOBASE, &region);
-               region &= PCI_BASE_ADDRESS_IO_MASK;
-               if (region >= PCIBIOS_MIN_IO)
-                       quirk_io_region(dev, region, 64,
-                                       PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO");
-       }
+       if (enable & ICH4_GPIO_EN)
+               quirk_io_region(dev, ICH4_GPIOBASE, 64, PCI_BRIDGE_RESOURCES+1,
+                               "ICH4 GPIO");
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,                quirk_ich4_lpc_acpi);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,                quirk_ich4_lpc_acpi);
@@ -533,26 +519,17 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_ESB_1,               qui
 
 static void ich6_lpc_acpi_gpio(struct pci_dev *dev)
 {
-       u32 region;
        u8 enable;
 
        pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
-       if (enable & ICH6_ACPI_EN) {
-               pci_read_config_dword(dev, ICH_PMBASE, &region);
-               region &= PCI_BASE_ADDRESS_IO_MASK;
-               if (region >= PCIBIOS_MIN_IO)
-                       quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
-                                       "ICH6 ACPI/GPIO/TCO");
-       }
+       if (enable & ICH6_ACPI_EN)
+               quirk_io_region(dev, ICH_PMBASE, 128, PCI_BRIDGE_RESOURCES,
+                                "ICH6 ACPI/GPIO/TCO");
 
        pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable);
-       if (enable & ICH6_GPIO_EN) {
-               pci_read_config_dword(dev, ICH6_GPIOBASE, &region);
-               region &= PCI_BASE_ADDRESS_IO_MASK;
-               if (region >= PCIBIOS_MIN_IO)
-                       quirk_io_region(dev, region, 64,
-                                       PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO");
-       }
+       if (enable & ICH6_GPIO_EN)
+               quirk_io_region(dev, ICH6_GPIOBASE, 64, PCI_BRIDGE_RESOURCES+1,
+                               "ICH6 GPIO");
 }
 
 static void ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
@@ -650,13 +627,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_ICH10_1, qui
  */
 static void quirk_vt82c586_acpi(struct pci_dev *dev)
 {
-       u32 region;
-
-       if (dev->revision & 0x10) {
-               pci_read_config_dword(dev, 0x48, &region);
-               region &= PCI_BASE_ADDRESS_IO_MASK;
-               quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI");
-       }
+       if (dev->revision & 0x10)
+               quirk_io_region(dev, 0x48, 256, PCI_BRIDGE_RESOURCES,
+                               "vt82c586 ACPI");
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C586_3,     quirk_vt82c586_acpi);
 
@@ -668,18 +641,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,       PCI_DEVICE_ID_VIA_82C586_3,     quirk_vt
  */
 static void quirk_vt82c686_acpi(struct pci_dev *dev)
 {
-       u16 hm;
-       u32 smb;
-
        quirk_vt82c586_acpi(dev);
 
-       pci_read_config_word(dev, 0x70, &hm);
-       hm &= PCI_BASE_ADDRESS_IO_MASK;
-       quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c686 HW-mon");
+       quirk_io_region(dev, 0x70, 128, PCI_BRIDGE_RESOURCES+1,
+                                "vt82c686 HW-mon");
 
-       pci_read_config_dword(dev, 0x90, &smb);
-       smb &= PCI_BASE_ADDRESS_IO_MASK;
-       quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB");
+       quirk_io_region(dev, 0x90, 16, PCI_BRIDGE_RESOURCES+2, "vt82c686 SMB");
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C686_4,     quirk_vt82c686_acpi);
 
@@ -690,15 +657,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,        PCI_DEVICE_ID_VIA_82C686_4,     quirk_vt
  */
 static void quirk_vt8235_acpi(struct pci_dev *dev)
 {
-       u16 pm, smb;
-
-       pci_read_config_word(dev, 0x88, &pm);
-       pm &= PCI_BASE_ADDRESS_IO_MASK;
-       quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM");
-
-       pci_read_config_word(dev, 0xd0, &smb);
-       smb &= PCI_BASE_ADDRESS_IO_MASK;
-       quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1, "vt8235 SMB");
+       quirk_io_region(dev, 0x88, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM");
+       quirk_io_region(dev, 0xd0, 16, PCI_BRIDGE_RESOURCES+1, "vt8235 SMB");
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi);
 
@@ -2594,6 +2554,14 @@ static void quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)
                dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
        pci_dev_put(p);
 }
+static void quirk_msi_intx_disable_qca_bug(struct pci_dev *dev)
+{
+       /* AR816X/AR817X/E210X MSI is fixed at HW level from revision 0x18 */
+       if (dev->revision < 0x18) {
+               dev_info(&dev->dev, "set MSI_INTX_DISABLE_BUG flag\n");
+               dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
+       }
+}
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
                        PCI_DEVICE_ID_TIGON3_5780,
                        quirk_msi_intx_disable_bug);
@@ -2643,6 +2611,16 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1073,
                        quirk_msi_intx_disable_bug);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1083,
                        quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1090,
+                       quirk_msi_intx_disable_qca_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1091,
+                       quirk_msi_intx_disable_qca_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x10a0,
+                       quirk_msi_intx_disable_qca_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x10a1,
+                       quirk_msi_intx_disable_qca_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0xe091,
+                       quirk_msi_intx_disable_qca_bug);
 #endif /* CONFIG_PCI_MSI */
 
 /* Allow manual resource allocation for PCI hotplug bridges
index cc875e6ed159f1edb890946a96e78917bb6fe2c5..8fc54b7327bc02b59af4a6455bcf43bdaf597252 100644 (file)
@@ -50,10 +50,8 @@ void pci_remove_bus(struct pci_bus *bus)
        list_del(&bus->node);
        pci_bus_release_busn_res(bus);
        up_write(&pci_bus_sem);
-       if (!bus->is_added)
-               return;
-
        pci_remove_legacy_files(bus);
+       pcibios_remove_bus(bus);
        device_unregister(&bus->dev);
 }
 EXPORT_SYMBOL(pci_remove_bus);
index b41ac7756a4ba6ff7795804db13db00c6437c662..c5d0a08a87473a24dc43dacb8081abf7c737b852 100644 (file)
@@ -100,27 +100,6 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
        return min((size_t)(image - rom), size);
 }
 
-static loff_t pci_find_rom(struct pci_dev *pdev, size_t *size)
-{
-       struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
-       loff_t start;
-
-       /* assign the ROM an address if it doesn't have one */
-       if (res->parent == NULL && pci_assign_resource(pdev, PCI_ROM_RESOURCE))
-               return 0;
-       start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
-       *size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
-
-       if (*size == 0)
-               return 0;
-
-       /* Enable ROM space decodes */
-       if (pci_enable_rom(pdev))
-               return 0;
-
-       return start;
-}
-
 /**
  * pci_map_rom - map a PCI ROM to kernel space
  * @pdev: pointer to pci device struct
@@ -135,7 +114,7 @@ static loff_t pci_find_rom(struct pci_dev *pdev, size_t *size)
 void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
 {
        struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
-       loff_t start = 0;
+       loff_t start;
        void __iomem *rom;
 
        /*
@@ -154,21 +133,21 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
                        return (void __iomem *)(unsigned long)
                                pci_resource_start(pdev, PCI_ROM_RESOURCE);
                } else {
-                       start = pci_find_rom(pdev, size);
-               }
-       }
+                       /* assign the ROM an address if it doesn't have one */
+                       if (res->parent == NULL &&
+                           pci_assign_resource(pdev,PCI_ROM_RESOURCE))
+                               return NULL;
+                       start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
+                       *size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+                       if (*size == 0)
+                               return NULL;
 
-       /*
-        * Some devices may provide ROMs via a source other than the BAR
-        */
-       if (!start && pdev->rom && pdev->romlen) {
-               *size = pdev->romlen;
-               return phys_to_virt(pdev->rom);
+                       /* Enable ROM space decodes */
+                       if (pci_enable_rom(pdev))
+                               return NULL;
+               }
        }
 
-       if (!start)
-               return NULL;
-
        rom = ioremap(start, *size);
        if (!rom) {
                /* restore enable if ioremap fails */
@@ -202,8 +181,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
        if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
                return;
 
-       if (!pdev->rom || !pdev->romlen)
-               iounmap(rom);
+       iounmap(rom);
 
        /* Disable again before continuing, leave enabled if pci=rom */
        if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
@@ -227,7 +205,24 @@ void pci_cleanup_rom(struct pci_dev *pdev)
        }
 }
 
+/**
+ * pci_platform_rom - provides a pointer to any ROM image provided by the
+ * platform
+ * @pdev: pointer to pci device struct
+ * @size: pointer to receive size of pci window over ROM
+ */
+void __iomem *pci_platform_rom(struct pci_dev *pdev, size_t *size)
+{
+       if (pdev->rom && pdev->romlen) {
+               *size = pdev->romlen;
+               return phys_to_virt((phys_addr_t)pdev->rom);
+       }
+
+       return NULL;
+}
+
 EXPORT_SYMBOL(pci_map_rom);
 EXPORT_SYMBOL(pci_unmap_rom);
 EXPORT_SYMBOL_GPL(pci_enable_rom);
 EXPORT_SYMBOL_GPL(pci_disable_rom);
+EXPORT_SYMBOL(pci_platform_rom);
index 7e8739e25b9ecddd9b52d19c7bfc486f8c3e7ac7..16abaaa1f83caed1009fb04018ece089b0138f26 100644 (file)
@@ -1044,7 +1044,7 @@ handle_done:
        ;
 }
 
-void __ref __pci_bus_size_bridges(struct pci_bus *bus,
+static void __ref __pci_bus_size_bridges(struct pci_bus *bus,
                        struct list_head *realloc_head)
 {
        struct pci_dev *dev;
@@ -1545,6 +1545,8 @@ again:
 
 enable_all:
        retval = pci_reenable_device(bridge);
+       if (retval)
+               dev_err(&bridge->dev, "Error reenabling bridge (%d)\n", retval);
        pci_set_master(bridge);
        pci_enable_bridges(parent);
 }
index 81b88bda79307b9003f37d5eb36699342f75383d..07f2eddc09cefec8dd6a742b0f5a1f659cb6080c 100644 (file)
@@ -261,7 +261,6 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
 {
        struct resource *res = dev->resource + resno;
        resource_size_t align, size;
-       struct pci_bus *bus;
        int ret;
 
        align = pci_resource_alignment(dev, res);
@@ -271,7 +270,6 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
                return -EINVAL;
        }
 
-       bus = dev->bus;
        size = resource_size(res);
        ret = _pci_assign_resource(dev, resno, size, align);
 
index ac6412fb8d6fea4a03fe77f23530fb558b44230c..c1e9284a677b0b0ee33aa2b28c5e675ed6e3616b 100644 (file)
@@ -377,14 +377,17 @@ void pci_hp_create_module_link(struct pci_slot *pci_slot)
 {
        struct hotplug_slot *slot = pci_slot->hotplug;
        struct kobject *kobj = NULL;
-       int no_warn;
+       int ret;
 
        if (!slot || !slot->ops)
                return;
        kobj = kset_find_obj(module_kset, slot->ops->mod_name);
        if (!kobj)
                return;
-       no_warn = sysfs_create_link(&pci_slot->kobj, kobj, "module");
+       ret = sysfs_create_link(&pci_slot->kobj, kobj, "module");
+       if (ret)
+               dev_err(&pci_slot->bus->dev, "Error creating sysfs link (%d)\n",
+                       ret);
        kobject_put(kobj);
 }
 EXPORT_SYMBOL_GPL(pci_hp_create_module_link);
index 45cacf79f3a73b7dfd97fa8293458febc02b7da9..1a779bbfb87d2b8de61e964734981f4f9a6c891e 100644 (file)
@@ -134,7 +134,6 @@ static const struct key_entry hp_wmi_keymap[] = {
        { KE_KEY, 0x2142, { KEY_MEDIA } },
        { KE_KEY, 0x213b, { KEY_INFO } },
        { KE_KEY, 0x2169, { KEY_DIRECTION } },
-       { KE_KEY, 0x216a, { KEY_SETUP } },
        { KE_KEY, 0x231b, { KEY_HELP } },
        { KE_END, 0 }
 };
@@ -925,9 +924,6 @@ static int __init hp_wmi_init(void)
                err = hp_wmi_input_setup();
                if (err)
                        return err;
-               
-               //Enable magic for hotkeys that run on the SMBus
-               ec_write(0xe6,0x6e);
        }
 
        if (bios_capable) {
index 9a907567f41edf495f1c102d906ba63660de082e..edec135b1685d0525149bc21c724833398424cb1 100644 (file)
@@ -1964,9 +1964,6 @@ struct tp_nvram_state {
 /* kthread for the hotkey poller */
 static struct task_struct *tpacpi_hotkey_task;
 
-/* Acquired while the poller kthread is running, use to sync start/stop */
-static struct mutex hotkey_thread_mutex;
-
 /*
  * Acquire mutex to write poller control variables as an
  * atomic block.
@@ -2462,8 +2459,6 @@ static int hotkey_kthread(void *data)
        unsigned int poll_freq;
        bool was_frozen;
 
-       mutex_lock(&hotkey_thread_mutex);
-
        if (tpacpi_lifecycle == TPACPI_LIFE_EXITING)
                goto exit;
 
@@ -2523,7 +2518,6 @@ static int hotkey_kthread(void *data)
        }
 
 exit:
-       mutex_unlock(&hotkey_thread_mutex);
        return 0;
 }
 
@@ -2533,9 +2527,6 @@ static void hotkey_poll_stop_sync(void)
        if (tpacpi_hotkey_task) {
                kthread_stop(tpacpi_hotkey_task);
                tpacpi_hotkey_task = NULL;
-               mutex_lock(&hotkey_thread_mutex);
-               /* at this point, the thread did exit */
-               mutex_unlock(&hotkey_thread_mutex);
        }
 }
 
@@ -3234,7 +3225,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
        mutex_init(&hotkey_mutex);
 
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
-       mutex_init(&hotkey_thread_mutex);
        mutex_init(&hotkey_thread_data_mutex);
 #endif
 
index cc1f7bf53fd07c1c1788d0183b19e4ce41de8c1b..c6d77e20622c45f54e17e7063e3e498f781739c6 100644 (file)
@@ -4,7 +4,7 @@ menu "Remoteproc drivers"
 config REMOTEPROC
        tristate
        depends on HAS_DMA
-       select FW_CONFIG
+       select FW_LOADER
        select VIRTIO
 
 config OMAP_REMOTEPROC
index 29387df4bfc9aa40f73cb94a0dcc2b2d0044af68..8edb4aed5d368e551e968e9c841cfd9edb221b7a 100644 (file)
@@ -217,7 +217,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
         * TODO: support predefined notifyids (via resource table)
         */
        ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL);
-       if (ret) {
+       if (ret < 0) {
                dev_err(dev, "idr_alloc failed: %d\n", ret);
                dma_free_coherent(dev->parent, size, va, dma);
                return ret;
@@ -366,10 +366,12 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
        /* it is now safe to add the virtio device */
        ret = rproc_add_virtio_dev(rvdev, rsc->id);
        if (ret)
-               goto free_rvdev;
+               goto remove_rvdev;
 
        return 0;
 
+remove_rvdev:
+       list_del(&rvdev->node);
 free_rvdev:
        kfree(rvdev);
        return ret;
index a7743c069339d6b9d738054db0c9148a490d119b..fb95c4220052decb09117075d3a798dbbb6235b7 100644 (file)
@@ -240,6 +240,8 @@ static int sproc_drv_remove(struct platform_device *pdev)
 
        /* Unregister as remoteproc device */
        rproc_del(sproc->rproc);
+       dma_free_coherent(sproc->rproc->dev.parent, SPROC_FW_SIZE,
+                         sproc->fw_addr, sproc->fw_dma_addr);
        rproc_put(sproc->rproc);
 
        mdev->drv_data = NULL;
@@ -297,10 +299,13 @@ static int sproc_probe(struct platform_device *pdev)
        /* Register as a remoteproc device */
        err = rproc_add(rproc);
        if (err)
-               goto free_rproc;
+               goto free_mem;
 
        return 0;
 
+free_mem:
+       dma_free_coherent(rproc->dev.parent, SPROC_FW_SIZE,
+                         sproc->fw_addr, sproc->fw_dma_addr);
 free_rproc:
        /* Reset device data upon error */
        mdev->drv_data = NULL;
index 0a9f27e094ea9ea122ec0658c673a3249eb6e04e..434ebc3a99dc089d10a6d27e5be99faebb28aace 100644 (file)
@@ -44,7 +44,6 @@ static DECLARE_COMPLETION(at91_rtc_updated);
 static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
 static void __iomem *at91_rtc_regs;
 static int irq;
-static u32 at91_rtc_imr;
 
 /*
  * Decode time/date into rtc_time structure
@@ -109,11 +108,9 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
        cr = at91_rtc_read(AT91_RTC_CR);
        at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM);
 
-       at91_rtc_imr |= AT91_RTC_ACKUPD;
        at91_rtc_write(AT91_RTC_IER, AT91_RTC_ACKUPD);
        wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */
        at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD);
-       at91_rtc_imr &= ~AT91_RTC_ACKUPD;
 
        at91_rtc_write(AT91_RTC_TIMR,
                          bin2bcd(tm->tm_sec) << 0
@@ -145,7 +142,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
        tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
        tm->tm_year = at91_alarm_year - 1900;
 
-       alrm->enabled = (at91_rtc_imr & AT91_RTC_ALARM)
+       alrm->enabled = (at91_rtc_read(AT91_RTC_IMR) & AT91_RTC_ALARM)
                        ? 1 : 0;
 
        dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
@@ -171,7 +168,6 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
        tm.tm_sec = alrm->time.tm_sec;
 
        at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM);
-       at91_rtc_imr &= ~AT91_RTC_ALARM;
        at91_rtc_write(AT91_RTC_TIMALR,
                  bin2bcd(tm.tm_sec) << 0
                | bin2bcd(tm.tm_min) << 8
@@ -184,7 +180,6 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        if (alrm->enabled) {
                at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
-               at91_rtc_imr |= AT91_RTC_ALARM;
                at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM);
        }
 
@@ -201,12 +196,9 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 
        if (enabled) {
                at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
-               at91_rtc_imr |= AT91_RTC_ALARM;
                at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM);
-       } else {
+       } else
                at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM);
-               at91_rtc_imr &= ~AT91_RTC_ALARM;
-       }
 
        return 0;
 }
@@ -215,10 +207,12 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
  */
 static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
 {
+       unsigned long imr = at91_rtc_read(AT91_RTC_IMR);
+
        seq_printf(seq, "update_IRQ\t: %s\n",
-                       (at91_rtc_imr & AT91_RTC_ACKUPD) ? "yes" : "no");
+                       (imr & AT91_RTC_ACKUPD) ? "yes" : "no");
        seq_printf(seq, "periodic_IRQ\t: %s\n",
-                       (at91_rtc_imr & AT91_RTC_SECEV) ? "yes" : "no");
+                       (imr & AT91_RTC_SECEV) ? "yes" : "no");
 
        return 0;
 }
@@ -233,7 +227,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
        unsigned int rtsr;
        unsigned long events = 0;
 
-       rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_imr;
+       rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read(AT91_RTC_IMR);
        if (rtsr) {             /* this interrupt is shared!  Is it ours? */
                if (rtsr & AT91_RTC_ALARM)
                        events |= (RTC_AF | RTC_IRQF);
@@ -297,7 +291,6 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
        at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
                                        AT91_RTC_SECEV | AT91_RTC_TIMEV |
                                        AT91_RTC_CALEV);
-       at91_rtc_imr = 0;
 
        ret = request_irq(irq, at91_rtc_interrupt,
                                IRQF_SHARED,
@@ -336,7 +329,6 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
        at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
                                        AT91_RTC_SECEV | AT91_RTC_TIMEV |
                                        AT91_RTC_CALEV);
-       at91_rtc_imr = 0;
        free_irq(irq, pdev);
 
        rtc_device_unregister(rtc);
@@ -349,35 +341,31 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
 
 /* AT91RM9200 RTC Power management control */
 
-static u32 at91_rtc_bkpimr;
-
+static u32 at91_rtc_imr;
 
 static int at91_rtc_suspend(struct device *dev)
 {
        /* this IRQ is shared with DBGU and other hardware which isn't
         * necessarily doing PM like we are...
         */
-       at91_rtc_bkpimr = at91_rtc_imr & (AT91_RTC_ALARM|AT91_RTC_SECEV);
-       if (at91_rtc_bkpimr) {
-               if (device_may_wakeup(dev)) {
+       at91_rtc_imr = at91_rtc_read(AT91_RTC_IMR)
+                       & (AT91_RTC_ALARM|AT91_RTC_SECEV);
+       if (at91_rtc_imr) {
+               if (device_may_wakeup(dev))
                        enable_irq_wake(irq);
-               } else {
-                       at91_rtc_write(AT91_RTC_IDR, at91_rtc_bkpimr);
-                       at91_rtc_imr &= ~at91_rtc_bkpimr;
-               }
-}
+               else
+                       at91_rtc_write(AT91_RTC_IDR, at91_rtc_imr);
+       }
        return 0;
 }
 
 static int at91_rtc_resume(struct device *dev)
 {
-       if (at91_rtc_bkpimr) {
-               if (device_may_wakeup(dev)) {
+       if (at91_rtc_imr) {
+               if (device_may_wakeup(dev))
                        disable_irq_wake(irq);
-               } else {
-                       at91_rtc_imr |= at91_rtc_bkpimr;
-                       at91_rtc_write(AT91_RTC_IER, at91_rtc_bkpimr);
-               }
+               else
+                       at91_rtc_write(AT91_RTC_IER, at91_rtc_imr);
        }
        return 0;
 }
index 5f940b6844cbfb524de17c1e58cf755f18775bee..da1945e5f71449a99dd6ed5baa6a4aec23af7a64 100644 (file)
@@ -64,6 +64,7 @@
 #define        AT91_RTC_SCCR           0x1c                    /* Status Clear Command Register */
 #define        AT91_RTC_IER            0x20                    /* Interrupt Enable Register */
 #define        AT91_RTC_IDR            0x24                    /* Interrupt Disable Register */
+#define        AT91_RTC_IMR            0x28                    /* Interrupt Mask Register */
 
 #define        AT91_RTC_VER            0x2c                    /* Valid Entry Register */
 #define                AT91_RTC_NVTIM          (1 <<  0)               /* Non valid Time */
index f1b7fdc58a5f366ffe054576e8755851f60b2beb..82758cbb220be6a6bc2f27396c4063c6272ffeff 100644 (file)
@@ -246,7 +246,7 @@ static struct dentry *dasd_debugfs_setup(const char *name,
 static int dasd_state_known_to_basic(struct dasd_device *device)
 {
        struct dasd_block *block = device->block;
-       int rc;
+       int rc = 0;
 
        /* Allocate and register gendisk structure. */
        if (block) {
@@ -273,7 +273,8 @@ static int dasd_state_known_to_basic(struct dasd_device *device)
        DBF_DEV_EVENT(DBF_EMERG, device, "%s", "debug area created");
 
        device->state = DASD_STATE_BASIC;
-       return 0;
+
+       return rc;
 }
 
 /*
@@ -282,6 +283,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device)
 static int dasd_state_basic_to_known(struct dasd_device *device)
 {
        int rc;
+
        if (device->block) {
                dasd_profile_exit(&device->block->profile);
                if (device->block->debugfs_dentry)
@@ -332,8 +334,10 @@ static int dasd_state_basic_to_ready(struct dasd_device *device)
                if (block->base->discipline->do_analysis != NULL)
                        rc = block->base->discipline->do_analysis(block);
                if (rc) {
-                       if (rc != -EAGAIN)
+                       if (rc != -EAGAIN) {
                                device->state = DASD_STATE_UNFMT;
+                               goto out;
+                       }
                        return rc;
                }
                dasd_setup_queue(block);
@@ -341,11 +345,16 @@ static int dasd_state_basic_to_ready(struct dasd_device *device)
                             block->blocks << block->s2b_shift);
                device->state = DASD_STATE_READY;
                rc = dasd_scan_partitions(block);
-               if (rc)
+               if (rc) {
                        device->state = DASD_STATE_BASIC;
+                       return rc;
+               }
        } else {
                device->state = DASD_STATE_READY;
        }
+out:
+       if (device->discipline->basic_to_ready)
+               rc = device->discipline->basic_to_ready(device);
        return rc;
 }
 
@@ -368,6 +377,11 @@ static int dasd_state_ready_to_basic(struct dasd_device *device)
 {
        int rc;
 
+       if (device->discipline->ready_to_basic) {
+               rc = device->discipline->ready_to_basic(device);
+               if (rc)
+                       return rc;
+       }
        device->state = DASD_STATE_BASIC;
        if (device->block) {
                struct dasd_block *block = device->block;
@@ -402,16 +416,10 @@ static int dasd_state_unfmt_to_basic(struct dasd_device *device)
 static int
 dasd_state_ready_to_online(struct dasd_device * device)
 {
-       int rc;
        struct gendisk *disk;
        struct disk_part_iter piter;
        struct hd_struct *part;
 
-       if (device->discipline->ready_to_online) {
-               rc = device->discipline->ready_to_online(device);
-               if (rc)
-                       return rc;
-       }
        device->state = DASD_STATE_ONLINE;
        if (device->block) {
                dasd_schedule_block_bh(device->block);
@@ -444,6 +452,7 @@ static int dasd_state_online_to_ready(struct dasd_device *device)
                if (rc)
                        return rc;
        }
+
        device->state = DASD_STATE_READY;
        if (device->block && !(device->features & DASD_FEATURE_USERAW)) {
                disk = device->block->bdev->bd_disk;
@@ -2223,6 +2232,77 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
        return rc;
 }
 
+static inline int _wait_for_wakeup_queue(struct list_head *ccw_queue)
+{
+       struct dasd_ccw_req *cqr;
+
+       list_for_each_entry(cqr, ccw_queue, blocklist) {
+               if (cqr->callback_data != DASD_SLEEPON_END_TAG)
+                       return 0;
+       }
+
+       return 1;
+}
+
+static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible)
+{
+       struct dasd_device *device;
+       int rc;
+       struct dasd_ccw_req *cqr, *n;
+
+retry:
+       list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
+               device = cqr->startdev;
+               if (cqr->status != DASD_CQR_FILLED) /*could be failed*/
+                       continue;
+
+               if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags) &&
+                   !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
+                       cqr->status = DASD_CQR_FAILED;
+                       cqr->intrc = -EPERM;
+                       continue;
+               }
+               /*Non-temporary stop condition will trigger fail fast*/
+               if (device->stopped & ~DASD_STOPPED_PENDING &&
+                   test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
+                   !dasd_eer_enabled(device)) {
+                       cqr->status = DASD_CQR_FAILED;
+                       cqr->intrc = -EAGAIN;
+                       continue;
+               }
+
+               /*Don't try to start requests if device is stopped*/
+               if (interruptible) {
+                       rc = wait_event_interruptible(
+                               generic_waitq, !device->stopped);
+                       if (rc == -ERESTARTSYS) {
+                               cqr->status = DASD_CQR_FAILED;
+                               cqr->intrc = rc;
+                               continue;
+                       }
+               } else
+                       wait_event(generic_waitq, !(device->stopped));
+
+               if (!cqr->callback)
+                       cqr->callback = dasd_wakeup_cb;
+               cqr->callback_data = DASD_SLEEPON_START_TAG;
+               dasd_add_request_tail(cqr);
+       }
+
+       wait_event(generic_waitq, _wait_for_wakeup_queue(ccw_queue));
+
+       rc = 0;
+       list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
+               if (__dasd_sleep_on_erp(cqr))
+                       rc = 1;
+       }
+       if (rc)
+               goto retry;
+
+
+       return 0;
+}
+
 /*
  * Queue a request to the tail of the device ccw_queue and wait for
  * it's completion.
@@ -2232,6 +2312,15 @@ int dasd_sleep_on(struct dasd_ccw_req *cqr)
        return _dasd_sleep_on(cqr, 0);
 }
 
+/*
+ * Start requests from a ccw_queue and wait for their completion.
+ */
+int dasd_sleep_on_queue(struct list_head *ccw_queue)
+{
+       return _dasd_sleep_on_queue(ccw_queue, 0);
+}
+EXPORT_SYMBOL(dasd_sleep_on_queue);
+
 /*
  * Queue a request to the tail of the device ccw_queue and wait
  * interruptible for it's completion.
@@ -2662,6 +2751,26 @@ static void _dasd_wake_block_flush_cb(struct dasd_ccw_req *cqr, void *data)
        wake_up(&dasd_flush_wq);
 }
 
+/*
+ * Requeue a request back to the block request queue
+ * only works for block requests
+ */
+static int _dasd_requeue_request(struct dasd_ccw_req *cqr)
+{
+       struct dasd_block *block = cqr->block;
+       struct request *req;
+       unsigned long flags;
+
+       if (!block)
+               return -EINVAL;
+       spin_lock_irqsave(&block->queue_lock, flags);
+       req = (struct request *) cqr->callback_data;
+       blk_requeue_request(block->request_queue, req);
+       spin_unlock_irqrestore(&block->queue_lock, flags);
+
+       return 0;
+}
+
 /*
  * Go through all request on the dasd_block request queue, cancel them
  * on the respective dasd_device, and return them to the generic
@@ -3380,10 +3489,11 @@ EXPORT_SYMBOL_GPL(dasd_generic_verify_path);
 
 int dasd_generic_pm_freeze(struct ccw_device *cdev)
 {
+       struct dasd_device *device = dasd_device_from_cdev(cdev);
+       struct list_head freeze_queue;
        struct dasd_ccw_req *cqr, *n;
+       struct dasd_ccw_req *refers;
        int rc;
-       struct list_head freeze_queue;
-       struct dasd_device *device = dasd_device_from_cdev(cdev);
 
        if (IS_ERR(device))
                return PTR_ERR(device);
@@ -3396,7 +3506,8 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
 
        /* disallow new I/O  */
        dasd_device_set_stop_bits(device, DASD_STOPPED_PM);
-       /* clear active requests */
+
+       /* clear active requests and requeue them to block layer if possible */
        INIT_LIST_HEAD(&freeze_queue);
        spin_lock_irq(get_ccwdev_lock(cdev));
        rc = 0;
@@ -3416,7 +3527,6 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
                }
                list_move_tail(&cqr->devlist, &freeze_queue);
        }
-
        spin_unlock_irq(get_ccwdev_lock(cdev));
 
        list_for_each_entry_safe(cqr, n, &freeze_queue, devlist) {
@@ -3424,12 +3534,38 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
                           (cqr->status != DASD_CQR_CLEAR_PENDING));
                if (cqr->status == DASD_CQR_CLEARED)
                        cqr->status = DASD_CQR_QUEUED;
+
+               /* requeue requests to blocklayer will only work for
+                  block device requests */
+               if (_dasd_requeue_request(cqr))
+                       continue;
+
+               /* remove requests from device and block queue */
+               list_del_init(&cqr->devlist);
+               while (cqr->refers != NULL) {
+                       refers = cqr->refers;
+                       /* remove the request from the block queue */
+                       list_del(&cqr->blocklist);
+                       /* free the finished erp request */
+                       dasd_free_erp_request(cqr, cqr->memdev);
+                       cqr = refers;
+               }
+               if (cqr->block)
+                       list_del_init(&cqr->blocklist);
+               cqr->block->base->discipline->free_cp(
+                       cqr, (struct request *) cqr->callback_data);
        }
-       /* move freeze_queue to start of the ccw_queue */
-       spin_lock_irq(get_ccwdev_lock(cdev));
-       list_splice_tail(&freeze_queue, &device->ccw_queue);
-       spin_unlock_irq(get_ccwdev_lock(cdev));
 
+       /*
+        * if requests remain then they are internal request
+        * and go back to the device queue
+        */
+       if (!list_empty(&freeze_queue)) {
+               /* move freeze_queue to start of the ccw_queue */
+               spin_lock_irq(get_ccwdev_lock(cdev));
+               list_splice_tail(&freeze_queue, &device->ccw_queue);
+               spin_unlock_irq(get_ccwdev_lock(cdev));
+       }
        dasd_put_device(device);
        return rc;
 }
index c196827c228fb9f3ce79412e7422051f2307d14d..a71bb8aaca1de2a86497f1c7b9e07155019c47a0 100644 (file)
@@ -410,8 +410,7 @@ dasd_add_busid(const char *bus_id, int features)
        struct dasd_devmap *devmap, *new, *tmp;
        int hash;
 
-       new = (struct dasd_devmap *)
-               kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
+       new = kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
        if (!new)
                return ERR_PTR(-ENOMEM);
        spin_lock(&dasd_devmap_lock);
index 6999fd919e942ffbe48e9b16a5d3162c27df859f..6a44b27623ed1a8378e8201facad2afb22c75e92 100644 (file)
@@ -2022,7 +2022,7 @@ static int dasd_eckd_do_analysis(struct dasd_block *block)
                return dasd_eckd_end_analysis(block);
 }
 
-static int dasd_eckd_ready_to_online(struct dasd_device *device)
+static int dasd_eckd_basic_to_ready(struct dasd_device *device)
 {
        return dasd_alias_add_device(device);
 };
@@ -2031,6 +2031,11 @@ static int dasd_eckd_online_to_ready(struct dasd_device *device)
 {
        cancel_work_sync(&device->reload_device);
        cancel_work_sync(&device->kick_validate);
+       return 0;
+};
+
+static int dasd_eckd_ready_to_basic(struct dasd_device *device)
+{
        return dasd_alias_remove_device(device);
 };
 
@@ -2050,45 +2055,34 @@ dasd_eckd_fill_geometry(struct dasd_block *block, struct hd_geometry *geo)
 }
 
 static struct dasd_ccw_req *
-dasd_eckd_format_device(struct dasd_device * device,
-                       struct format_data_t * fdata)
+dasd_eckd_build_format(struct dasd_device *base,
+                      struct format_data_t *fdata)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *base_priv;
+       struct dasd_eckd_private *start_priv;
+       struct dasd_device *startdev;
        struct dasd_ccw_req *fcp;
        struct eckd_count *ect;
+       struct ch_t address;
        struct ccw1 *ccw;
        void *data;
        int rpt;
-       struct ch_t address;
        int cplength, datasize;
-       int i;
+       int i, j;
        int intensity = 0;
        int r0_perm;
+       int nr_tracks;
 
-       private = (struct dasd_eckd_private *) device->private;
-       rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize);
-       set_ch_t(&address,
-                fdata->start_unit / private->rdc_data.trk_per_cyl,
-                fdata->start_unit % private->rdc_data.trk_per_cyl);
+       startdev = dasd_alias_get_start_dev(base);
+       if (!startdev)
+               startdev = base;
 
-       /* Sanity checks. */
-       if (fdata->start_unit >=
-           (private->real_cyl * private->rdc_data.trk_per_cyl)) {
-               dev_warn(&device->cdev->dev, "Start track number %d used in "
-                        "formatting is too big\n", fdata->start_unit);
-               return ERR_PTR(-EINVAL);
-       }
-       if (fdata->start_unit > fdata->stop_unit) {
-               dev_warn(&device->cdev->dev, "Start track %d used in "
-                        "formatting exceeds end track\n", fdata->start_unit);
-               return ERR_PTR(-EINVAL);
-       }
-       if (dasd_check_blocksize(fdata->blksize) != 0) {
-               dev_warn(&device->cdev->dev,
-                        "The DASD cannot be formatted with block size %d\n",
-                        fdata->blksize);
-               return ERR_PTR(-EINVAL);
-       }
+       start_priv = (struct dasd_eckd_private *) startdev->private;
+       base_priv = (struct dasd_eckd_private *) base->private;
+
+       rpt = recs_per_track(&base_priv->rdc_data, 0, fdata->blksize);
+
+       nr_tracks = fdata->stop_unit - fdata->start_unit + 1;
 
        /*
         * fdata->intensity is a bit string that tells us what to do:
@@ -2106,149 +2100,282 @@ dasd_eckd_format_device(struct dasd_device * device,
                r0_perm = 1;
                intensity = fdata->intensity;
        }
+
        switch (intensity) {
        case 0x00:      /* Normal format */
        case 0x08:      /* Normal format, use cdl. */
-               cplength = 2 + rpt;
-               datasize = sizeof(struct DE_eckd_data) +
+               cplength = 2 + (rpt*nr_tracks);
+               datasize = sizeof(struct PFX_eckd_data) +
                        sizeof(struct LO_eckd_data) +
-                       rpt * sizeof(struct eckd_count);
+                       rpt * nr_tracks * sizeof(struct eckd_count);
                break;
        case 0x01:      /* Write record zero and format track. */
        case 0x09:      /* Write record zero and format track, use cdl. */
-               cplength = 3 + rpt;
-               datasize = sizeof(struct DE_eckd_data) +
+               cplength = 2 + rpt * nr_tracks;
+               datasize = sizeof(struct PFX_eckd_data) +
                        sizeof(struct LO_eckd_data) +
                        sizeof(struct eckd_count) +
-                       rpt * sizeof(struct eckd_count);
+                       rpt * nr_tracks * sizeof(struct eckd_count);
                break;
        case 0x04:      /* Invalidate track. */
        case 0x0c:      /* Invalidate track, use cdl. */
                cplength = 3;
-               datasize = sizeof(struct DE_eckd_data) +
+               datasize = sizeof(struct PFX_eckd_data) +
                        sizeof(struct LO_eckd_data) +
                        sizeof(struct eckd_count);
                break;
        default:
-               dev_warn(&device->cdev->dev, "An I/O control call used "
-                        "incorrect flags 0x%x\n", fdata->intensity);
+               dev_warn(&startdev->cdev->dev,
+                        "An I/O control call used incorrect flags 0x%x\n",
+                        fdata->intensity);
                return ERR_PTR(-EINVAL);
        }
        /* Allocate the format ccw request. */
-       fcp = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, device);
+       fcp = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength,
+                                  datasize, startdev);
        if (IS_ERR(fcp))
                return fcp;
 
+       start_priv->count++;
        data = fcp->data;
        ccw = fcp->cpaddr;
 
        switch (intensity & ~0x08) {
        case 0x00: /* Normal format. */
-               define_extent(ccw++, (struct DE_eckd_data *) data,
-                             fdata->start_unit, fdata->start_unit,
-                             DASD_ECKD_CCW_WRITE_CKD, device);
+               prefix(ccw++, (struct PFX_eckd_data *) data,
+                      fdata->start_unit, fdata->stop_unit,
+                      DASD_ECKD_CCW_WRITE_CKD, base, startdev);
                /* grant subsystem permission to format R0 */
                if (r0_perm)
-                       ((struct DE_eckd_data *)data)->ga_extended |= 0x04;
-               data += sizeof(struct DE_eckd_data);
+                       ((struct PFX_eckd_data *)data)
+                               ->define_extent.ga_extended |= 0x04;
+               data += sizeof(struct PFX_eckd_data);
                ccw[-1].flags |= CCW_FLAG_CC;
                locate_record(ccw++, (struct LO_eckd_data *) data,
-                             fdata->start_unit, 0, rpt,
-                             DASD_ECKD_CCW_WRITE_CKD, device,
+                             fdata->start_unit, 0, rpt*nr_tracks,
+                             DASD_ECKD_CCW_WRITE_CKD, base,
                              fdata->blksize);
                data += sizeof(struct LO_eckd_data);
                break;
        case 0x01: /* Write record zero + format track. */
-               define_extent(ccw++, (struct DE_eckd_data *) data,
-                             fdata->start_unit, fdata->start_unit,
-                             DASD_ECKD_CCW_WRITE_RECORD_ZERO,
-                             device);
-               data += sizeof(struct DE_eckd_data);
+               prefix(ccw++, (struct PFX_eckd_data *) data,
+                      fdata->start_unit, fdata->stop_unit,
+                      DASD_ECKD_CCW_WRITE_RECORD_ZERO,
+                      base, startdev);
+               data += sizeof(struct PFX_eckd_data);
                ccw[-1].flags |= CCW_FLAG_CC;
                locate_record(ccw++, (struct LO_eckd_data *) data,
-                             fdata->start_unit, 0, rpt + 1,
-                             DASD_ECKD_CCW_WRITE_RECORD_ZERO, device,
-                             device->block->bp_block);
+                             fdata->start_unit, 0, rpt * nr_tracks + 1,
+                             DASD_ECKD_CCW_WRITE_RECORD_ZERO, base,
+                             base->block->bp_block);
                data += sizeof(struct LO_eckd_data);
                break;
        case 0x04: /* Invalidate track. */
-               define_extent(ccw++, (struct DE_eckd_data *) data,
-                             fdata->start_unit, fdata->start_unit,
-                             DASD_ECKD_CCW_WRITE_CKD, device);
-               data += sizeof(struct DE_eckd_data);
+               prefix(ccw++, (struct PFX_eckd_data *) data,
+                      fdata->start_unit, fdata->stop_unit,
+                      DASD_ECKD_CCW_WRITE_CKD, base, startdev);
+               data += sizeof(struct PFX_eckd_data);
                ccw[-1].flags |= CCW_FLAG_CC;
                locate_record(ccw++, (struct LO_eckd_data *) data,
                              fdata->start_unit, 0, 1,
-                             DASD_ECKD_CCW_WRITE_CKD, device, 8);
+                             DASD_ECKD_CCW_WRITE_CKD, base, 8);
                data += sizeof(struct LO_eckd_data);
                break;
        }
-       if (intensity & 0x01) { /* write record zero */
-               ect = (struct eckd_count *) data;
-               data += sizeof(struct eckd_count);
-               ect->cyl = address.cyl;
-               ect->head = address.head;
-               ect->record = 0;
-               ect->kl = 0;
-               ect->dl = 8;
-               ccw[-1].flags |= CCW_FLAG_CC;
-               ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO;
-               ccw->flags = CCW_FLAG_SLI;
-               ccw->count = 8;
-               ccw->cda = (__u32)(addr_t) ect;
-               ccw++;
-       }
-       if ((intensity & ~0x08) & 0x04) {       /* erase track */
-               ect = (struct eckd_count *) data;
-               data += sizeof(struct eckd_count);
-               ect->cyl = address.cyl;
-               ect->head = address.head;
-               ect->record = 1;
-               ect->kl = 0;
-               ect->dl = 0;
-               ccw[-1].flags |= CCW_FLAG_CC;
-               ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
-               ccw->flags = CCW_FLAG_SLI;
-               ccw->count = 8;
-               ccw->cda = (__u32)(addr_t) ect;
-       } else {                /* write remaining records */
-               for (i = 0; i < rpt; i++) {
+
+       for (j = 0; j < nr_tracks; j++) {
+               /* calculate cylinder and head for the current track */
+               set_ch_t(&address,
+                        (fdata->start_unit + j) /
+                        base_priv->rdc_data.trk_per_cyl,
+                        (fdata->start_unit + j) %
+                        base_priv->rdc_data.trk_per_cyl);
+               if (intensity & 0x01) { /* write record zero */
                        ect = (struct eckd_count *) data;
                        data += sizeof(struct eckd_count);
                        ect->cyl = address.cyl;
                        ect->head = address.head;
-                       ect->record = i + 1;
+                       ect->record = 0;
                        ect->kl = 0;
-                       ect->dl = fdata->blksize;
-                       /* Check for special tracks 0-1 when formatting CDL */
-                       if ((intensity & 0x08) &&
-                           fdata->start_unit == 0) {
-                               if (i < 3) {
-                                       ect->kl = 4;
-                                       ect->dl = sizes_trk0[i] - 4;
-                               }
-                       }
-                       if ((intensity & 0x08) &&
-                           fdata->start_unit == 1) {
-                               ect->kl = 44;
-                               ect->dl = LABEL_SIZE - 44;
-                       }
+                       ect->dl = 8;
                        ccw[-1].flags |= CCW_FLAG_CC;
-                       ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
+                       ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO;
                        ccw->flags = CCW_FLAG_SLI;
                        ccw->count = 8;
                        ccw->cda = (__u32)(addr_t) ect;
                        ccw++;
                }
+               if ((intensity & ~0x08) & 0x04) {       /* erase track */
+                       ect = (struct eckd_count *) data;
+                       data += sizeof(struct eckd_count);
+                       ect->cyl = address.cyl;
+                       ect->head = address.head;
+                       ect->record = 1;
+                       ect->kl = 0;
+                       ect->dl = 0;
+                       ccw[-1].flags |= CCW_FLAG_CC;
+                       ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
+                       ccw->flags = CCW_FLAG_SLI;
+                       ccw->count = 8;
+                       ccw->cda = (__u32)(addr_t) ect;
+               } else {                /* write remaining records */
+                       for (i = 0; i < rpt; i++) {
+                               ect = (struct eckd_count *) data;
+                               data += sizeof(struct eckd_count);
+                               ect->cyl = address.cyl;
+                               ect->head = address.head;
+                               ect->record = i + 1;
+                               ect->kl = 0;
+                               ect->dl = fdata->blksize;
+                               /*
+                                * Check for special tracks 0-1
+                                * when formatting CDL
+                                */
+                               if ((intensity & 0x08) &&
+                                   fdata->start_unit == 0) {
+                                       if (i < 3) {
+                                               ect->kl = 4;
+                                               ect->dl = sizes_trk0[i] - 4;
+                                       }
+                               }
+                               if ((intensity & 0x08) &&
+                                   fdata->start_unit == 1) {
+                                       ect->kl = 44;
+                                       ect->dl = LABEL_SIZE - 44;
+                               }
+                               ccw[-1].flags |= CCW_FLAG_CC;
+                               if (i != 0 || j == 0)
+                                       ccw->cmd_code =
+                                               DASD_ECKD_CCW_WRITE_CKD;
+                               else
+                                       ccw->cmd_code =
+                                               DASD_ECKD_CCW_WRITE_CKD_MT;
+                               ccw->flags = CCW_FLAG_SLI;
+                               ccw->count = 8;
+                                       ccw->cda = (__u32)(addr_t) ect;
+                                       ccw++;
+                       }
+               }
        }
-       fcp->startdev = device;
-       fcp->memdev = device;
+
+       fcp->startdev = startdev;
+       fcp->memdev = startdev;
        fcp->retries = 256;
+       fcp->expires = startdev->default_expires * HZ;
        fcp->buildclk = get_tod_clock();
        fcp->status = DASD_CQR_FILLED;
+
        return fcp;
 }
 
+static int
+dasd_eckd_format_device(struct dasd_device *base,
+                       struct format_data_t *fdata)
+{
+       struct dasd_ccw_req *cqr, *n;
+       struct dasd_block *block;
+       struct dasd_eckd_private *private;
+       struct list_head format_queue;
+       struct dasd_device *device;
+       int old_stop, format_step;
+       int step, rc = 0;
+
+       block = base->block;
+       private = (struct dasd_eckd_private *) base->private;
+
+       /* Sanity checks. */
+       if (fdata->start_unit >=
+           (private->real_cyl * private->rdc_data.trk_per_cyl)) {
+               dev_warn(&base->cdev->dev,
+                        "Start track number %u used in formatting is too big\n",
+                        fdata->start_unit);
+               return -EINVAL;
+       }
+       if (fdata->stop_unit >=
+           (private->real_cyl * private->rdc_data.trk_per_cyl)) {
+               dev_warn(&base->cdev->dev,
+                        "Stop track number %u used in formatting is too big\n",
+                        fdata->stop_unit);
+               return -EINVAL;
+       }
+       if (fdata->start_unit > fdata->stop_unit) {
+               dev_warn(&base->cdev->dev,
+                        "Start track %u used in formatting exceeds end track\n",
+                        fdata->start_unit);
+               return -EINVAL;
+       }
+       if (dasd_check_blocksize(fdata->blksize) != 0) {
+               dev_warn(&base->cdev->dev,
+                        "The DASD cannot be formatted with block size %u\n",
+                        fdata->blksize);
+               return -EINVAL;
+       }
+
+       INIT_LIST_HEAD(&format_queue);
+       old_stop = fdata->stop_unit;
+
+       while (fdata->start_unit <= 1) {
+               fdata->stop_unit = fdata->start_unit;
+               cqr = dasd_eckd_build_format(base, fdata);
+               list_add(&cqr->blocklist, &format_queue);
+
+               fdata->stop_unit = old_stop;
+               fdata->start_unit++;
+
+               if (fdata->start_unit > fdata->stop_unit)
+                       goto sleep;
+       }
+
+retry:
+       format_step = 255 / recs_per_track(&private->rdc_data, 0,
+                                          fdata->blksize);
+       while (fdata->start_unit <= old_stop) {
+               step = fdata->stop_unit - fdata->start_unit + 1;
+               if (step > format_step)
+                       fdata->stop_unit = fdata->start_unit + format_step - 1;
+
+               cqr = dasd_eckd_build_format(base, fdata);
+               if (IS_ERR(cqr)) {
+                       if (PTR_ERR(cqr) == -ENOMEM) {
+                               /*
+                                * not enough memory available
+                                * go to out and start requests
+                                * retry after first requests were finished
+                                */
+                               fdata->stop_unit = old_stop;
+                               goto sleep;
+                       } else
+                               return PTR_ERR(cqr);
+               }
+               list_add(&cqr->blocklist, &format_queue);
+
+               fdata->start_unit = fdata->stop_unit + 1;
+               fdata->stop_unit = old_stop;
+       }
+
+sleep:
+       dasd_sleep_on_queue(&format_queue);
+
+       list_for_each_entry_safe(cqr, n, &format_queue, blocklist) {
+               device = cqr->startdev;
+               private = (struct dasd_eckd_private *) device->private;
+               if (cqr->status == DASD_CQR_FAILED)
+                       rc = -EIO;
+               list_del_init(&cqr->blocklist);
+               dasd_sfree_request(cqr, device);
+               private->count--;
+       }
+
+       /*
+        * in case of ENOMEM we need to retry after
+        * first requests are finished
+        */
+       if (fdata->start_unit <= fdata->stop_unit)
+               goto retry;
+
+       return rc;
+}
+
 static void dasd_eckd_handle_terminated_request(struct dasd_ccw_req *cqr)
 {
        cqr->status = DASD_CQR_FILLED;
@@ -4305,8 +4432,9 @@ static struct dasd_discipline dasd_eckd_discipline = {
        .uncheck_device = dasd_eckd_uncheck_device,
        .do_analysis = dasd_eckd_do_analysis,
        .verify_path = dasd_eckd_verify_path,
-       .ready_to_online = dasd_eckd_ready_to_online,
+       .basic_to_ready = dasd_eckd_basic_to_ready,
        .online_to_ready = dasd_eckd_online_to_ready,
+       .ready_to_basic = dasd_eckd_ready_to_basic,
        .fill_geometry = dasd_eckd_fill_geometry,
        .start_IO = dasd_start_IO,
        .term_IO = dasd_term_IO,
index 899e3f5a56e50db3f28d3649b56e6022ed566364..0785bd9bd5b60ddeca4a4bd3894e9949b76d661d 100644 (file)
@@ -300,10 +300,11 @@ struct dasd_discipline {
         * Last things to do when a device is set online, and first things
         * when it is set offline.
         */
-       int (*ready_to_online) (struct dasd_device *);
+       int (*basic_to_ready) (struct dasd_device *);
        int (*online_to_ready) (struct dasd_device *);
+       int (*ready_to_basic)  (struct dasd_device *);
 
-       /*
+       /* (struct dasd_device *);
         * Device operation functions. build_cp creates a ccw chain for
         * a block device request, start_io starts the request and
         * term_IO cancels it (e.g. in case of a timeout). format_device
@@ -317,8 +318,8 @@ struct dasd_discipline {
        int (*start_IO) (struct dasd_ccw_req *);
        int (*term_IO) (struct dasd_ccw_req *);
        void (*handle_terminated_request) (struct dasd_ccw_req *);
-       struct dasd_ccw_req *(*format_device) (struct dasd_device *,
-                                              struct format_data_t *);
+       int (*format_device) (struct dasd_device *,
+                             struct format_data_t *);
        int (*free_cp) (struct dasd_ccw_req *, struct request *);
 
        /*
@@ -672,6 +673,7 @@ int  dasd_term_IO(struct dasd_ccw_req *);
 void dasd_schedule_device_bh(struct dasd_device *);
 void dasd_schedule_block_bh(struct dasd_block *);
 int  dasd_sleep_on(struct dasd_ccw_req *);
+int  dasd_sleep_on_queue(struct list_head *);
 int  dasd_sleep_on_immediatly(struct dasd_ccw_req *);
 int  dasd_sleep_on_interruptible(struct dasd_ccw_req *);
 void dasd_device_set_timer(struct dasd_device *, int);
index 03c0e044455335df0c6d3a0cc5defbf5c15dd0a6..8be1b51e9311a4e0ec528620947e058095caecd5 100644 (file)
@@ -143,12 +143,12 @@ static int dasd_ioctl_resume(struct dasd_block *block)
 /*
  * performs formatting of _device_ according to _fdata_
  * Note: The discipline's format_function is assumed to deliver formatting
- * commands to format a single unit of the device. In terms of the ECKD
- * devices this means CCWs are generated to format a single track.
+ * commands to format multiple units of the device. In terms of the ECKD
+ * devices this means CCWs are generated to format multiple tracks.
  */
-static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
+static int
+dasd_format(struct dasd_block *block, struct format_data_t *fdata)
 {
-       struct dasd_ccw_req *cqr;
        struct dasd_device *base;
        int rc;
 
@@ -157,8 +157,8 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
                return -EPERM;
 
        if (base->state != DASD_STATE_BASIC) {
-               pr_warning("%s: The DASD cannot be formatted while it is "
-                          "enabled\n",  dev_name(&base->cdev->dev));
+               pr_warn("%s: The DASD cannot be formatted while it is enabled\n",
+                       dev_name(&base->cdev->dev));
                return -EBUSY;
        }
 
@@ -178,21 +178,10 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
                bdput(bdev);
        }
 
-       while (fdata->start_unit <= fdata->stop_unit) {
-               cqr = base->discipline->format_device(base, fdata);
-               if (IS_ERR(cqr))
-                       return PTR_ERR(cqr);
-               rc = dasd_sleep_on_interruptible(cqr);
-               dasd_sfree_request(cqr, cqr->memdev);
-               if (rc) {
-                       if (rc != -ERESTARTSYS)
-                               pr_err("%s: Formatting unit %d failed with "
-                                      "rc=%d\n", dev_name(&base->cdev->dev),
-                                      fdata->start_unit, rc);
-                       return rc;
-               }
-               fdata->start_unit++;
-       }
+       rc = base->discipline->format_device(base, fdata);
+       if (rc)
+               return rc;
+
        return 0;
 }
 
index 5ac9c935c151511a1a9b42cf76dc5efd87c4f71f..b303cab76a7f3787149837fdd3223b6d04c7d7bb 100644 (file)
@@ -307,7 +307,7 @@ static void scm_blk_handle_error(struct scm_request *scmrq)
        case EQC_WR_PROHIBIT:
                spin_lock_irqsave(&bdev->lock, flags);
                if (bdev->state != SCM_WR_PROHIBIT)
-                       pr_info("%lu: Write access to the SCM increment is suspended\n",
+                       pr_info("%lx: Write access to the SCM increment is suspended\n",
                                (unsigned long) bdev->scmdev->address);
                bdev->state = SCM_WR_PROHIBIT;
                spin_unlock_irqrestore(&bdev->lock, flags);
@@ -445,7 +445,7 @@ void scm_blk_set_available(struct scm_blk_dev *bdev)
 
        spin_lock_irqsave(&bdev->lock, flags);
        if (bdev->state == SCM_WR_PROHIBIT)
-               pr_info("%lu: Write access to the SCM increment is restored\n",
+               pr_info("%lx: Write access to the SCM increment is restored\n",
                        (unsigned long) bdev->scmdev->address);
        bdev->state = SCM_OPER;
        spin_unlock_irqrestore(&bdev->lock, flags);
@@ -463,12 +463,15 @@ static int __init scm_blk_init(void)
                goto out;
 
        scm_major = ret;
-       if (scm_alloc_rqs(nr_requests))
-               goto out_unreg;
+       ret = scm_alloc_rqs(nr_requests);
+       if (ret)
+               goto out_free;
 
        scm_debug = debug_register("scm_log", 16, 1, 16);
-       if (!scm_debug)
+       if (!scm_debug) {
+               ret = -ENOMEM;
                goto out_free;
+       }
 
        debug_register_view(scm_debug, &debug_hex_ascii_view);
        debug_set_level(scm_debug, 2);
@@ -483,7 +486,6 @@ out_dbf:
        debug_unregister(scm_debug);
 out_free:
        scm_free_rqs();
-out_unreg:
        unregister_blkdev(scm_major, "scm");
 out:
        return ret;
index f4bb61b0cea11c07d0ffda6b630f517850fdd90e..c0d102e3a48bf569d0c9744abb466317e942342b 100644 (file)
@@ -223,6 +223,8 @@ void scm_cluster_request_irq(struct scm_request *scmrq)
 
 bool scm_cluster_size_valid(void)
 {
-       return write_cluster_size == 0 || write_cluster_size == 32 ||
-               write_cluster_size == 64 || write_cluster_size == 128;
+       if (write_cluster_size == 1 || write_cluster_size > 128)
+               return false;
+
+       return !(write_cluster_size & (write_cluster_size - 1));
 }
index 5f6180d6ff08f50516215c20553f0c1ce5f4da42..c98cf52d78d19331adea46fc12cff94034f25b6b 100644 (file)
@@ -19,7 +19,7 @@ static void scm_notify(struct scm_device *scmdev, enum scm_event event)
 
        switch (event) {
        case SCM_CHANGE:
-               pr_info("%lu: The capabilities of the SCM increment changed\n",
+               pr_info("%lx: The capabilities of the SCM increment changed\n",
                        (unsigned long) scmdev->address);
                SCM_LOG(2, "State changed");
                SCM_LOG_STATE(2, scmdev);
index 7b00fa634d40bf96ac5fe119431a562871a92b57..eb5d22795c47a55744381ee3f9e70c1666701835 100644 (file)
@@ -502,7 +502,7 @@ static void raw3215_make_room(struct raw3215_info *raw, unsigned int length)
                raw3215_try_io(raw);
                raw->flags &= ~RAW3215_FLUSHING;
 #ifdef CONFIG_TN3215_CONSOLE
-               wait_cons_dev();
+               ccw_device_wait_idle(raw->cdev);
 #endif
                /* Enough room freed up ? */
                if (RAW3215_BUFFER_SIZE - raw->count >= length)
@@ -858,7 +858,7 @@ static void con3215_flush(void)
        raw = raw3215[0];  /* console 3215 is the first one */
        if (raw->port.flags & ASYNC_SUSPENDED)
                /* The console is still frozen for suspend. */
-               if (ccw_device_force_console())
+               if (ccw_device_force_console(raw->cdev))
                        /* Forcing didn't work, no panic message .. */
                        return;
        spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
index f4ff515db2515b3b8a48cf9bb9db397b5ba7b23a..0da3ae3cd63b3ae549e770f387a90237a594163a 100644 (file)
@@ -174,8 +174,7 @@ static void mon_free_mem(struct mon_private *monpriv)
        int i;
 
        for (i = 0; i < MON_MSGLIM; i++)
-               if (monpriv->msg_array[i])
-                       kfree(monpriv->msg_array[i]);
+               kfree(monpriv->msg_array[i]);
        kfree(monpriv);
 }
 
index 4c9030a5b9f268b4a78f43688ada94a383315438..24a08e8f19e1b9ed3366b5f035d4a0fd214bf97e 100644 (file)
@@ -796,7 +796,7 @@ struct raw3270 __init *raw3270_setup_console(struct ccw_device *cdev)
        do {
                __raw3270_reset_device(rp);
                while (!raw3270_state_final(rp)) {
-                       wait_cons_dev();
+                       ccw_device_wait_idle(rp->cdev);
                        barrier();
                }
        } while (rp->state != RAW3270_STATE_READY);
@@ -810,7 +810,7 @@ raw3270_wait_cons_dev(struct raw3270 *rp)
        unsigned long flags;
 
        spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
-       wait_cons_dev();
+       ccw_device_wait_idle(rp->cdev);
        spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
 }
 
@@ -1274,7 +1274,7 @@ void raw3270_pm_unfreeze(struct raw3270_view *view)
 
        rp = view->dev;
        if (rp && test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
-               ccw_device_force_console();
+               ccw_device_force_console(rp->cdev);
 #endif
 }
 
index cd798386b622173172906cc021306d9cc64941bf..178836ec252b3ddf2373a820e6c6c13e3cc51fbc 100644 (file)
@@ -561,6 +561,8 @@ static void __init sclp_add_standby_memory(void)
        add_memory_merged(0);
 }
 
+#define MEM_SCT_SIZE (1UL << SECTION_SIZE_BITS)
+
 static void __init insert_increment(u16 rn, int standby, int assigned)
 {
        struct memory_increment *incr, *new_incr;
@@ -573,7 +575,7 @@ static void __init insert_increment(u16 rn, int standby, int assigned)
        new_incr->rn = rn;
        new_incr->standby = standby;
        if (!standby)
-               new_incr->usecount = 1;
+               new_incr->usecount = rzm > MEM_SCT_SIZE ? rzm/MEM_SCT_SIZE : 1;
        last_rn = 0;
        prev = &sclp_mem_list;
        list_for_each_entry(incr, &sclp_mem_list, list) {
index b907dba24025e12239960f97feb0c5510d9d33cd..cee69dac3e182b6e2de94300b49ac9ec35658430 100644 (file)
@@ -915,7 +915,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
        int i, rc;
 
        /* Check if the tty3270 is already there. */
-       view = raw3270_find_view(&tty3270_fn, tty->index);
+       view = raw3270_find_view(&tty3270_fn, tty->index + RAW3270_FIRSTMINOR);
        if (!IS_ERR(view)) {
                tp = container_of(view, struct tty3270, view);
                tty->driver_data = tp;
@@ -927,15 +927,16 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
                tp->inattr = TF_INPUT;
                return tty_port_install(&tp->port, driver, tty);
        }
-       if (tty3270_max_index < tty->index)
-               tty3270_max_index = tty->index;
+       if (tty3270_max_index < tty->index + 1)
+               tty3270_max_index = tty->index + 1;
 
        /* Allocate tty3270 structure on first open. */
        tp = tty3270_alloc_view();
        if (IS_ERR(tp))
                return PTR_ERR(tp);
 
-       rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index);
+       rc = raw3270_add_view(&tp->view, &tty3270_fn,
+                             tty->index + RAW3270_FIRSTMINOR);
        if (rc) {
                tty3270_free_view(tp);
                return rc;
@@ -1846,12 +1847,12 @@ static const struct tty_operations tty3270_ops = {
 
 void tty3270_create_cb(int minor)
 {
-       tty_register_device(tty3270_driver, minor, NULL);
+       tty_register_device(tty3270_driver, minor - RAW3270_FIRSTMINOR, NULL);
 }
 
 void tty3270_destroy_cb(int minor)
 {
-       tty_unregister_device(tty3270_driver, minor);
+       tty_unregister_device(tty3270_driver, minor - RAW3270_FIRSTMINOR);
 }
 
 struct raw3270_notifier tty3270_notifier =
@@ -1884,7 +1885,8 @@ static int __init tty3270_init(void)
        driver->driver_name = "tty3270";
        driver->name = "3270/tty";
        driver->major = IBM_TTY3270_MAJOR;
-       driver->minor_start = 0;
+       driver->minor_start = RAW3270_FIRSTMINOR;
+       driver->name_base = RAW3270_FIRSTMINOR;
        driver->type = TTY_DRIVER_TYPE_SYSTEM;
        driver->subtype = SYSTEM_TYPE_TTY;
        driver->init_termios = tty_std_termios;
index 1d61a01576d213ac600e367e231272a2fbbcb5dc..22820610022c6e21a190c06d1b014ae7b900e33d 100644 (file)
@@ -127,7 +127,7 @@ static int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode)
        }
        if (mode == TO_USER) {
                if (copy_to_user((__force __user void*) dest + offs, buf,
-                                PAGE_SIZE))
+                                count - offs))
                        return -EFAULT;
        } else
                memcpy(dest + offs, buf, count - offs);
index 50ad5fdd815dca03e53f62c1c0798738d375f9e0..21fabc6d5a9c83bac80fda8d78495c26f9febe64 100644 (file)
@@ -376,6 +376,26 @@ static void chp_release(struct device *dev)
        kfree(cp);
 }
 
+/**
+ * chp_update_desc - update channel-path description
+ * @chp - channel-path
+ *
+ * Update the channel-path description of the specified channel-path.
+ * Return zero on success, non-zero otherwise.
+ */
+int chp_update_desc(struct channel_path *chp)
+{
+       int rc;
+
+       rc = chsc_determine_base_channel_path_desc(chp->chpid, &chp->desc);
+       if (rc)
+               return rc;
+
+       rc = chsc_determine_fmt1_channel_path_desc(chp->chpid, &chp->desc_fmt1);
+
+       return rc;
+}
+
 /**
  * chp_new - register a new channel-path
  * @chpid - channel-path ID
@@ -403,7 +423,7 @@ int chp_new(struct chp_id chpid)
        mutex_init(&chp->lock);
 
        /* Obtain channel path description and fill it in. */
-       ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+       ret = chp_update_desc(chp);
        if (ret)
                goto out_free;
        if ((chp->desc.flags & 0x80) == 0) {
index e1399dbee83430510ff6266e0bb02957916848cf..9284b785a06ff05bcb172f3916d09b999c43270f 100644 (file)
@@ -44,6 +44,7 @@ struct channel_path {
        struct mutex lock; /* Serialize access to below members. */
        int state;
        struct channel_path_desc desc;
+       struct channel_path_desc_fmt1 desc_fmt1;
        /* Channel-measurement related stuff: */
        int cmg;
        int shared;
@@ -62,6 +63,7 @@ int chp_is_registered(struct chp_id chpid);
 void *chp_get_chp_desc(struct chp_id chpid);
 void chp_remove_cmg_attr(struct channel_path *chp);
 int chp_add_cmg_attr(struct channel_path *chp);
+int chp_update_desc(struct channel_path *chp);
 int chp_new(struct chp_id chpid);
 void chp_cfg_schedule(struct chp_id chpid, int configure);
 void chp_cfg_cancel_deconfigure(struct chp_id chpid);
index e16c553f65561f453c4eed2a97eb4cda8a539231..8ea7d9b2c671a3555c7c5d2c57b505d9f338033c 100644 (file)
@@ -376,7 +376,7 @@ static void chsc_process_sei_chp_avail(struct chsc_sei_nt0_area *sei_area)
                        continue;
                }
                mutex_lock(&chp->lock);
-               chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+               chp_update_desc(chp);
                mutex_unlock(&chp->lock);
        }
 }
@@ -631,8 +631,8 @@ int chsc_chp_vary(struct chp_id chpid, int on)
         * Redo PathVerification on the devices the chpid connects to
         */
        if (on) {
-               /* Try to update the channel path descritor. */
-               chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+               /* Try to update the channel path description. */
+               chp_update_desc(chp);
                for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
                                           __s390_vary_chpid_on, &chpid);
        } else
@@ -825,9 +825,10 @@ int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
 {
        struct chsc_response_struct *chsc_resp;
        struct chsc_scpd *scpd_area;
+       unsigned long flags;
        int ret;
 
-       spin_lock_irq(&chsc_page_lock);
+       spin_lock_irqsave(&chsc_page_lock, flags);
        scpd_area = chsc_page;
        ret = chsc_determine_channel_path_desc(chpid, 0, 0, 1, 0, scpd_area);
        if (ret)
@@ -835,7 +836,7 @@ int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
        chsc_resp = (void *)&scpd_area->response;
        memcpy(desc, &chsc_resp->data, sizeof(*desc));
 out:
-       spin_unlock_irq(&chsc_page_lock);
+       spin_unlock_irqrestore(&chsc_page_lock, flags);
        return ret;
 }
 
index 986ef6a92a410ad893127ff786fe43774d9e0daa..935d80b4e9cedb5361d6d18aab013c73f4eab456 100644 (file)
@@ -471,15 +471,6 @@ int cio_disable_subchannel(struct subchannel *sch)
 }
 EXPORT_SYMBOL_GPL(cio_disable_subchannel);
 
-int cio_create_sch_lock(struct subchannel *sch)
-{
-       sch->lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
-       if (!sch->lock)
-               return -ENOMEM;
-       spin_lock_init(sch->lock);
-       return 0;
-}
-
 static int cio_check_devno_blacklisted(struct subchannel *sch)
 {
        if (is_blacklisted(sch->schid.ssid, sch->schib.pmcw.dev)) {
@@ -536,32 +527,19 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
        sprintf(dbf_txt, "valsch%x", schid.sch_no);
        CIO_TRACE_EVENT(4, dbf_txt);
 
-       /* Nuke all fields. */
-       memset(sch, 0, sizeof(struct subchannel));
-
-       sch->schid = schid;
-       if (cio_is_console(schid)) {
-               sch->lock = cio_get_console_lock();
-       } else {
-               err = cio_create_sch_lock(sch);
-               if (err)
-                       goto out;
-       }
-       mutex_init(&sch->reg_mutex);
-
        /*
         * The first subchannel that is not-operational (ccode==3)
-        *  indicates that there aren't any more devices available.
+        * indicates that there aren't any more devices available.
         * If stsch gets an exception, it means the current subchannel set
-        *  is not valid.
+        * is not valid.
         */
-       ccode = stsch_err (schid, &sch->schib);
+       ccode = stsch_err(schid, &sch->schib);
        if (ccode) {
                err = (ccode == 3) ? -ENXIO : ccode;
                goto out;
        }
-       /* Copy subchannel type from path management control word. */
        sch->st = sch->schib.pmcw.st;
+       sch->schid = schid;
 
        switch (sch->st) {
        case SUBCHANNEL_TYPE_IO:
@@ -578,11 +556,7 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
 
        CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n",
                      sch->schid.ssid, sch->schid.sch_no, sch->st);
-       return 0;
 out:
-       if (!cio_is_console(schid))
-               kfree(sch->lock);
-       sch->lock = NULL;
        return err;
 }
 
@@ -650,15 +624,13 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
 }
 
 #ifdef CONFIG_CCW_CONSOLE
-static struct subchannel console_subchannel;
-static struct io_subchannel_private console_priv;
-static int console_subchannel_in_use;
+static struct subchannel *console_sch;
 
 /*
  * Use cio_tsch to update the subchannel status and call the interrupt handler
- * if status had been pending. Called with the console_subchannel lock.
+ * if status had been pending. Called with the subchannel's lock held.
  */
-static void cio_tsch(struct subchannel *sch)
+void cio_tsch(struct subchannel *sch)
 {
        struct irb *irb;
        int irq_context;
@@ -675,6 +647,7 @@ static void cio_tsch(struct subchannel *sch)
                local_bh_disable();
                irq_enter();
        }
+       kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL);
        if (sch->driver && sch->driver->irq)
                sch->driver->irq(sch);
        else
@@ -685,135 +658,90 @@ static void cio_tsch(struct subchannel *sch)
        }
 }
 
-void *cio_get_console_priv(void)
-{
-       return &console_priv;
-}
-
-/*
- * busy wait for the next interrupt on the console
- */
-void wait_cons_dev(void)
+static int cio_test_for_console(struct subchannel_id schid, void *data)
 {
-       if (!console_subchannel_in_use)
-               return;
-
-       while (1) {
-               cio_tsch(&console_subchannel);
-               if (console_subchannel.schib.scsw.cmd.actl == 0)
-                       break;
-               udelay_simple(100);
-       }
-}
+       struct schib schib;
 
-static int
-cio_test_for_console(struct subchannel_id schid, void *data)
-{
-       if (stsch_err(schid, &console_subchannel.schib) != 0)
+       if (stsch_err(schid, &schib) != 0)
                return -ENXIO;
-       if ((console_subchannel.schib.pmcw.st == SUBCHANNEL_TYPE_IO) &&
-           console_subchannel.schib.pmcw.dnv &&
-           (console_subchannel.schib.pmcw.dev == console_devno)) {
+       if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv &&
+           (schib.pmcw.dev == console_devno)) {
                console_irq = schid.sch_no;
                return 1; /* found */
        }
        return 0;
 }
 
-
-static int
-cio_get_console_sch_no(void)
+static int cio_get_console_sch_no(void)
 {
        struct subchannel_id schid;
-       
+       struct schib schib;
+
        init_subchannel_id(&schid);
        if (console_irq != -1) {
                /* VM provided us with the irq number of the console. */
                schid.sch_no = console_irq;
-               if (stsch_err(schid, &console_subchannel.schib) != 0 ||
-                   (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) ||
-                   !console_subchannel.schib.pmcw.dnv)
+               if (stsch_err(schid, &schib) != 0 ||
+                   (schib.pmcw.st != SUBCHANNEL_TYPE_IO) || !schib.pmcw.dnv)
                        return -1;
-               console_devno = console_subchannel.schib.pmcw.dev;
+               console_devno = schib.pmcw.dev;
        } else if (console_devno != -1) {
                /* At least the console device number is known. */
                for_each_subchannel(cio_test_for_console, NULL);
-               if (console_irq == -1)
-                       return -1;
-       } else {
-               /* unlike in 2.4, we cannot autoprobe here, since
-                * the channel subsystem is not fully initialized.
-                * With some luck, the HWC console can take over */
-               return -1;
        }
        return console_irq;
 }
 
-struct subchannel *
-cio_probe_console(void)
+struct subchannel *cio_probe_console(void)
 {
-       int sch_no, ret;
        struct subchannel_id schid;
+       struct subchannel *sch;
+       int sch_no, ret;
 
-       if (xchg(&console_subchannel_in_use, 1) != 0)
-               return ERR_PTR(-EBUSY);
        sch_no = cio_get_console_sch_no();
        if (sch_no == -1) {
-               console_subchannel_in_use = 0;
                pr_warning("No CCW console was found\n");
                return ERR_PTR(-ENODEV);
        }
-       memset(&console_subchannel, 0, sizeof(struct subchannel));
        init_subchannel_id(&schid);
        schid.sch_no = sch_no;
-       ret = cio_validate_subchannel(&console_subchannel, schid);
-       if (ret) {
-               console_subchannel_in_use = 0;
-               return ERR_PTR(-ENODEV);
-       }
+       sch = css_alloc_subchannel(schid);
+       if (IS_ERR(sch))
+               return sch;
 
-       /*
-        * enable console I/O-interrupt subclass
-        */
        isc_register(CONSOLE_ISC);
-       console_subchannel.config.isc = CONSOLE_ISC;
-       console_subchannel.config.intparm = (u32)(addr_t)&console_subchannel;
-       ret = cio_commit_config(&console_subchannel);
+       sch->config.isc = CONSOLE_ISC;
+       sch->config.intparm = (u32)(addr_t)sch;
+       ret = cio_commit_config(sch);
        if (ret) {
                isc_unregister(CONSOLE_ISC);
-               console_subchannel_in_use = 0;
+               put_device(&sch->dev);
                return ERR_PTR(ret);
        }
-       return &console_subchannel;
-}
-
-void
-cio_release_console(void)
-{
-       console_subchannel.config.intparm = 0;
-       cio_commit_config(&console_subchannel);
-       isc_unregister(CONSOLE_ISC);
-       console_subchannel_in_use = 0;
+       console_sch = sch;
+       return sch;
 }
 
-/* Bah... hack to catch console special sausages. */
-int
-cio_is_console(struct subchannel_id schid)
+int cio_is_console(struct subchannel_id schid)
 {
-       if (!console_subchannel_in_use)
+       if (!console_sch)
                return 0;
-       return schid_equal(&schid, &console_subchannel.schid);
+       return schid_equal(&schid, &console_sch->schid);
 }
 
-struct subchannel *
-cio_get_console_subchannel(void)
+void cio_register_early_subchannels(void)
 {
-       if (!console_subchannel_in_use)
-               return NULL;
-       return &console_subchannel;
+       int ret;
+
+       if (!console_sch)
+               return;
+
+       ret = css_register_subchannel(console_sch);
+       if (ret)
+               put_device(&console_sch->dev);
 }
+#endif /* CONFIG_CCW_CONSOLE */
 
-#endif
 static int
 __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
 {
index 4a1ff5c2eb881355204ffe8e047cfbe3bb8e3706..d62f5e7f3cf100c217718614edabea5d5470a151 100644 (file)
@@ -121,23 +121,18 @@ extern int cio_commit_config(struct subchannel *sch);
 int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key);
 int cio_tm_intrg(struct subchannel *sch);
 
-int cio_create_sch_lock(struct subchannel *);
 void do_adapter_IO(u8 isc);
 void do_IRQ(struct pt_regs *);
 
 /* Use with care. */
 #ifdef CONFIG_CCW_CONSOLE
 extern struct subchannel *cio_probe_console(void);
-extern void cio_release_console(void);
 extern int cio_is_console(struct subchannel_id);
-extern struct subchannel *cio_get_console_subchannel(void);
-extern spinlock_t * cio_get_console_lock(void);
-extern void *cio_get_console_priv(void);
+extern void cio_register_early_subchannels(void);
+extern void cio_tsch(struct subchannel *sch);
 #else
 #define cio_is_console(schid) 0
-#define cio_get_console_subchannel() NULL
-#define cio_get_console_lock() NULL
-#define cio_get_console_priv() NULL
+static inline void cio_register_early_subchannels(void) {}
 #endif
 
 #endif
index a239237d43f3e7bc4d5262bb3ca34ccd067f65dd..1ebe5d3ddebb28e7caddb0ec742bc76ce1307f78 100644 (file)
@@ -137,37 +137,53 @@ out:
 
 static void css_sch_todo(struct work_struct *work);
 
-static struct subchannel *
-css_alloc_subchannel(struct subchannel_id schid)
+static int css_sch_create_locks(struct subchannel *sch)
+{
+       sch->lock = kmalloc(sizeof(*sch->lock), GFP_KERNEL);
+       if (!sch->lock)
+               return -ENOMEM;
+
+       spin_lock_init(sch->lock);
+       mutex_init(&sch->reg_mutex);
+
+       return 0;
+}
+
+static void css_subchannel_release(struct device *dev)
+{
+       struct subchannel *sch = to_subchannel(dev);
+
+       sch->config.intparm = 0;
+       cio_commit_config(sch);
+       kfree(sch->lock);
+       kfree(sch);
+}
+
+struct subchannel *css_alloc_subchannel(struct subchannel_id schid)
 {
        struct subchannel *sch;
        int ret;
 
-       sch = kmalloc (sizeof (*sch), GFP_KERNEL | GFP_DMA);
-       if (sch == NULL)
+       sch = kzalloc(sizeof(*sch), GFP_KERNEL | GFP_DMA);
+       if (!sch)
                return ERR_PTR(-ENOMEM);
-       ret = cio_validate_subchannel (sch, schid);
-       if (ret < 0) {
-               kfree(sch);
-               return ERR_PTR(ret);
-       }
+
+       ret = cio_validate_subchannel(sch, schid);
+       if (ret < 0)
+               goto err;
+
+       ret = css_sch_create_locks(sch);
+       if (ret)
+               goto err;
+
        INIT_WORK(&sch->todo_work, css_sch_todo);
+       sch->dev.release = &css_subchannel_release;
+       device_initialize(&sch->dev);
        return sch;
-}
-
-static void
-css_subchannel_release(struct device *dev)
-{
-       struct subchannel *sch;
 
-       sch = to_subchannel(dev);
-       if (!cio_is_console(sch->schid)) {
-               /* Reset intparm to zeroes. */
-               sch->config.intparm = 0;
-               cio_commit_config(sch);
-               kfree(sch->lock);
-               kfree(sch);
-       }
+err:
+       kfree(sch);
+       return ERR_PTR(ret);
 }
 
 static int css_sch_device_register(struct subchannel *sch)
@@ -177,7 +193,7 @@ static int css_sch_device_register(struct subchannel *sch)
        mutex_lock(&sch->reg_mutex);
        dev_set_name(&sch->dev, "0.%x.%04x", sch->schid.ssid,
                     sch->schid.sch_no);
-       ret = device_register(&sch->dev);
+       ret = device_add(&sch->dev);
        mutex_unlock(&sch->reg_mutex);
        return ret;
 }
@@ -228,16 +244,11 @@ void css_update_ssd_info(struct subchannel *sch)
 {
        int ret;
 
-       if (cio_is_console(sch->schid)) {
-               /* Console is initialized too early for functions requiring
-                * memory allocation. */
+       ret = chsc_get_ssd_info(sch->schid, &sch->ssd_info);
+       if (ret)
                ssd_from_pmcw(&sch->ssd_info, &sch->schib.pmcw);
-       } else {
-               ret = chsc_get_ssd_info(sch->schid, &sch->ssd_info);
-               if (ret)
-                       ssd_from_pmcw(&sch->ssd_info, &sch->schib.pmcw);
-               ssd_register_chpids(&sch->ssd_info);
-       }
+
+       ssd_register_chpids(&sch->ssd_info);
 }
 
 static ssize_t type_show(struct device *dev, struct device_attribute *attr,
@@ -275,14 +286,13 @@ static const struct attribute_group *default_subch_attr_groups[] = {
        NULL,
 };
 
-static int css_register_subchannel(struct subchannel *sch)
+int css_register_subchannel(struct subchannel *sch)
 {
        int ret;
 
        /* Initialize the subchannel structure */
        sch->dev.parent = &channel_subsystems[0]->device;
        sch->dev.bus = &css_bus_type;
-       sch->dev.release = &css_subchannel_release;
        sch->dev.groups = default_subch_attr_groups;
        /*
         * We don't want to generate uevents for I/O subchannels that don't
@@ -314,23 +324,19 @@ static int css_register_subchannel(struct subchannel *sch)
        return ret;
 }
 
-int css_probe_device(struct subchannel_id schid)
+static int css_probe_device(struct subchannel_id schid)
 {
-       int ret;
        struct subchannel *sch;
+       int ret;
+
+       sch = css_alloc_subchannel(schid);
+       if (IS_ERR(sch))
+               return PTR_ERR(sch);
 
-       if (cio_is_console(schid))
-               sch = cio_get_console_subchannel();
-       else {
-               sch = css_alloc_subchannel(schid);
-               if (IS_ERR(sch))
-                       return PTR_ERR(sch);
-       }
        ret = css_register_subchannel(sch);
-       if (ret) {
-               if (!cio_is_console(schid))
-                       put_device(&sch->dev);
-       }
+       if (ret)
+               put_device(&sch->dev);
+
        return ret;
 }
 
@@ -770,7 +776,7 @@ static int __init setup_css(int nr)
        css->pseudo_subchannel->dev.release = css_subchannel_release;
        dev_set_name(&css->pseudo_subchannel->dev, "defunct");
        mutex_init(&css->pseudo_subchannel->reg_mutex);
-       ret = cio_create_sch_lock(css->pseudo_subchannel);
+       ret = css_sch_create_locks(css->pseudo_subchannel);
        if (ret) {
                kfree(css->pseudo_subchannel);
                return ret;
@@ -870,8 +876,7 @@ static struct notifier_block css_power_notifier = {
 
 /*
  * Now that the driver core is running, we can setup our channel subsystem.
- * The struct subchannel's are created during probing (except for the
- * static console subchannel).
+ * The struct subchannel's are created during probing.
  */
 static int __init css_bus_init(void)
 {
@@ -1050,6 +1055,8 @@ int css_complete_work(void)
  */
 static int __init channel_subsystem_init_sync(void)
 {
+       /* Register subchannels which are already in use. */
+       cio_register_early_subchannels();
        /* Start initial subchannel evaluation. */
        css_schedule_eval_all();
        css_complete_work();
@@ -1065,9 +1072,8 @@ void channel_subsystem_reinit(void)
        chsc_enable_facility(CHSC_SDA_OC_MSS);
        chp_id_for_each(&chpid) {
                chp = chpid_to_chp(chpid);
-               if (!chp)
-                       continue;
-               chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+               if (chp)
+                       chp_update_desc(chp);
        }
 }
 
index 4af3dfe70ef53d075bb7cc96ea1064801ac777c6..b1de6033523806e8fa58e1f2ed87b31c0ca950d2 100644 (file)
@@ -101,7 +101,8 @@ extern int css_driver_register(struct css_driver *);
 extern void css_driver_unregister(struct css_driver *);
 
 extern void css_sch_device_unregister(struct subchannel *);
-extern int css_probe_device(struct subchannel_id);
+extern int css_register_subchannel(struct subchannel *);
+extern struct subchannel *css_alloc_subchannel(struct subchannel_id);
 extern struct subchannel *get_subchannel_by_schid(struct subchannel_id);
 extern int css_init_done;
 extern int max_ssid;
@@ -109,7 +110,6 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *),
                               int (*fn_unknown)(struct subchannel_id,
                               void *), void *data);
 extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
-extern void css_reiterate_subchannels(void);
 void css_update_ssd_info(struct subchannel *sch);
 
 struct channel_subsystem {
index c6767f5a58b23f3202a52113bc67ee295ab174f6..1ab5f6c36d9b4439db490797ca62aa239f04f7fa 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/list.h>
 #include <linux/device.h>
 #include <linux/workqueue.h>
+#include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/kernel_stat.h>
 
@@ -43,6 +44,10 @@ static DEFINE_SPINLOCK(recovery_lock);
 static int recovery_phase;
 static const unsigned long recovery_delay[] = { 3, 30, 300 };
 
+static atomic_t ccw_device_init_count = ATOMIC_INIT(0);
+static DECLARE_WAIT_QUEUE_HEAD(ccw_device_init_wq);
+static struct bus_type ccw_bus_type;
+
 /******************* bus type handling ***********************/
 
 /* The Linux driver model distinguishes between a bus type and
@@ -127,8 +132,6 @@ static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env)
        return ret;
 }
 
-static struct bus_type ccw_bus_type;
-
 static void io_subchannel_irq(struct subchannel *);
 static int io_subchannel_probe(struct subchannel *);
 static int io_subchannel_remove(struct subchannel *);
@@ -137,8 +140,6 @@ static int io_subchannel_sch_event(struct subchannel *, int);
 static int io_subchannel_chp_event(struct subchannel *, struct chp_link *,
                                   int);
 static void recovery_func(unsigned long data);
-wait_queue_head_t ccw_device_init_wq;
-atomic_t ccw_device_init_count;
 
 static struct css_device_id io_subchannel_ids[] = {
        { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, },
@@ -191,10 +192,7 @@ int __init io_subchannel_init(void)
 {
        int ret;
 
-       init_waitqueue_head(&ccw_device_init_wq);
-       atomic_set(&ccw_device_init_count, 0);
        setup_timer(&recovery_timer, recovery_func, 0);
-
        ret = bus_register(&ccw_bus_type);
        if (ret)
                return ret;
@@ -1086,19 +1084,14 @@ static int io_subchannel_probe(struct subchannel *sch)
                dev_set_uevent_suppress(&sch->dev, 0);
                kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
                cdev = sch_get_cdev(sch);
-               cdev->dev.groups = ccwdev_attr_groups;
-               device_initialize(&cdev->dev);
-               cdev->private->flags.initialized = 1;
-               ccw_device_register(cdev);
-               /*
-                * Check if the device is already online. If it is
-                * the reference count needs to be corrected since we
-                * didn't obtain a reference in ccw_device_set_online.
-                */
-               if (cdev->private->state != DEV_STATE_NOT_OPER &&
-                   cdev->private->state != DEV_STATE_OFFLINE &&
-                   cdev->private->state != DEV_STATE_BOXED)
-                       get_device(&cdev->dev);
+               rc = ccw_device_register(cdev);
+               if (rc) {
+                       /* Release online reference. */
+                       put_device(&cdev->dev);
+                       goto out_schedule;
+               }
+               if (atomic_dec_and_test(&ccw_device_init_count))
+                       wake_up(&ccw_device_init_wq);
                return 0;
        }
        io_subchannel_init_fields(sch);
@@ -1580,88 +1573,102 @@ out:
 }
 
 #ifdef CONFIG_CCW_CONSOLE
-static struct ccw_device console_cdev;
-static struct ccw_device_private console_private;
-static int console_cdev_in_use;
-
-static DEFINE_SPINLOCK(ccw_console_lock);
-
-spinlock_t * cio_get_console_lock(void)
-{
-       return &ccw_console_lock;
-}
-
 static int ccw_device_console_enable(struct ccw_device *cdev,
                                     struct subchannel *sch)
 {
-       struct io_subchannel_private *io_priv = cio_get_console_priv();
        int rc;
 
-       /* Attach subchannel private data. */
-       memset(io_priv, 0, sizeof(*io_priv));
-       set_io_private(sch, io_priv);
        io_subchannel_init_fields(sch);
        rc = cio_commit_config(sch);
        if (rc)
                return rc;
        sch->driver = &io_subchannel_driver;
-       /* Initialize the ccw_device structure. */
-       cdev->dev.parent= &sch->dev;
        sch_set_cdev(sch, cdev);
        io_subchannel_recog(cdev, sch);
        /* Now wait for the async. recognition to come to an end. */
        spin_lock_irq(cdev->ccwlock);
        while (!dev_fsm_final_state(cdev))
-               wait_cons_dev();
-       rc = -EIO;
-       if (cdev->private->state != DEV_STATE_OFFLINE)
+               ccw_device_wait_idle(cdev);
+
+       /* Hold on to an extra reference while device is online. */
+       get_device(&cdev->dev);
+       rc = ccw_device_online(cdev);
+       if (rc)
                goto out_unlock;
-       ccw_device_online(cdev);
+
        while (!dev_fsm_final_state(cdev))
-               wait_cons_dev();
-       if (cdev->private->state != DEV_STATE_ONLINE)
-               goto out_unlock;
-       rc = 0;
+               ccw_device_wait_idle(cdev);
+
+       if (cdev->private->state == DEV_STATE_ONLINE)
+               cdev->online = 1;
+       else
+               rc = -EIO;
 out_unlock:
        spin_unlock_irq(cdev->ccwlock);
+       if (rc) /* Give up online reference since onlining failed. */
+               put_device(&cdev->dev);
        return rc;
 }
 
-struct ccw_device *
-ccw_device_probe_console(void)
+struct ccw_device *ccw_device_probe_console(void)
 {
+       struct io_subchannel_private *io_priv;
+       struct ccw_device *cdev;
        struct subchannel *sch;
        int ret;
 
-       if (xchg(&console_cdev_in_use, 1) != 0)
-               return ERR_PTR(-EBUSY);
        sch = cio_probe_console();
-       if (IS_ERR(sch)) {
-               console_cdev_in_use = 0;
-               return (void *) sch;
+       if (IS_ERR(sch))
+               return ERR_CAST(sch);
+
+       io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
+       if (!io_priv) {
+               put_device(&sch->dev);
+               return ERR_PTR(-ENOMEM);
        }
-       memset(&console_cdev, 0, sizeof(struct ccw_device));
-       memset(&console_private, 0, sizeof(struct ccw_device_private));
-       console_cdev.private = &console_private;
-       console_private.cdev = &console_cdev;
-       console_private.int_class = IRQIO_CIO;
-       ret = ccw_device_console_enable(&console_cdev, sch);
+       cdev = io_subchannel_create_ccwdev(sch);
+       if (IS_ERR(cdev)) {
+               put_device(&sch->dev);
+               kfree(io_priv);
+               return cdev;
+       }
+       set_io_private(sch, io_priv);
+       ret = ccw_device_console_enable(cdev, sch);
        if (ret) {
-               cio_release_console();
-               console_cdev_in_use = 0;
+               set_io_private(sch, NULL);
+               put_device(&sch->dev);
+               put_device(&cdev->dev);
+               kfree(io_priv);
                return ERR_PTR(ret);
        }
-       console_cdev.online = 1;
-       return &console_cdev;
+       return cdev;
+}
+
+/**
+ * ccw_device_wait_idle() - busy wait for device to become idle
+ * @cdev: ccw device
+ *
+ * Poll until activity control is zero, that is, no function or data
+ * transfer is pending/active.
+ * Called with device lock being held.
+ */
+void ccw_device_wait_idle(struct ccw_device *cdev)
+{
+       struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
+       while (1) {
+               cio_tsch(sch);
+               if (sch->schib.scsw.cmd.actl == 0)
+                       break;
+               udelay_simple(100);
+       }
 }
 
 static int ccw_device_pm_restore(struct device *dev);
 
-int ccw_device_force_console(void)
+int ccw_device_force_console(struct ccw_device *cdev)
 {
-       if (!console_cdev_in_use)
-               return -ENODEV;
-       return ccw_device_pm_restore(&console_cdev.dev);
+       return ccw_device_pm_restore(&cdev->dev);
 }
 EXPORT_SYMBOL_GPL(ccw_device_force_console);
 #endif
index 7d4ecb65db00cfab037ff4e4d6684570fcdf54e7..8d1d298731722397d74fd0069ff3f6843df37bae 100644 (file)
@@ -81,8 +81,6 @@ dev_fsm_final_state(struct ccw_device *cdev)
                cdev->private->state == DEV_STATE_BOXED);
 }
 
-extern wait_queue_head_t ccw_device_init_wq;
-extern atomic_t ccw_device_init_count;
 int __init io_subchannel_init(void);
 
 void io_subchannel_recog_done(struct ccw_device *cdev);
index c77b6e06bf646a90ad01d6e33a61bc5411ecf884..4845d64f2842cd45dfa72aa360f513fd5683876f 100644 (file)
@@ -704,9 +704,9 @@ EXPORT_SYMBOL(ccw_device_tm_start_timeout);
 int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
 {
        struct subchannel *sch = to_subchannel(cdev->dev.parent);
-       struct channel_path_desc_fmt1 desc;
+       struct channel_path *chp;
        struct chp_id chpid;
-       int mdc = 0, ret, i;
+       int mdc = 0, i;
 
        /* Adjust requested path mask to excluded varied off paths. */
        if (mask)
@@ -719,14 +719,20 @@ int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
                if (!(mask & (0x80 >> i)))
                        continue;
                chpid.id = sch->schib.pmcw.chpid[i];
-               ret = chsc_determine_fmt1_channel_path_desc(chpid, &desc);
-               if (ret)
-                       return ret;
-               if (!desc.f)
+               chp = chpid_to_chp(chpid);
+               if (!chp)
+                       continue;
+
+               mutex_lock(&chp->lock);
+               if (!chp->desc_fmt1.f) {
+                       mutex_unlock(&chp->lock);
                        return 0;
-               if (!desc.r)
+               }
+               if (!chp->desc_fmt1.r)
                        mdc = 1;
-               mdc = mdc ? min(mdc, (int)desc.mdc) : desc.mdc;
+               mdc = mdc ? min_t(int, mdc, chp->desc_fmt1.mdc) :
+                           chp->desc_fmt1.mdc;
+               mutex_unlock(&chp->lock);
        }
 
        return mdc;
index 65d13e38803f9dddc11079b9a00176e7b94116d2..5a999084a229545cdda97c9b9bc6980acf45ea76 100644 (file)
@@ -17,7 +17,7 @@ struct idset {
 
 static inline unsigned long bitmap_size(int num_ssid, int num_id)
 {
-       return __BITOPS_WORDS(num_ssid * num_id) * sizeof(unsigned long);
+       return BITS_TO_LONGS(num_ssid * num_id) * sizeof(unsigned long);
 }
 
 static struct idset *idset_new(int num_ssid, int num_id)
index 8c0622399fcd67bd7353b6274a3d370b3d9caaa4..6ccb7457746b29e4e6ac0f53731bba725709f6a8 100644 (file)
@@ -769,6 +769,7 @@ struct qeth_card {
        unsigned long thread_start_mask;
        unsigned long thread_allowed_mask;
        unsigned long thread_running_mask;
+       struct task_struct *recovery_task;
        spinlock_t ip_lock;
        struct list_head ip_list;
        struct list_head *ip_tbd_list;
@@ -862,6 +863,8 @@ extern struct qeth_card_list_struct qeth_core_card_list;
 extern struct kmem_cache *qeth_core_header_cache;
 extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS];
 
+void qeth_set_recovery_task(struct qeth_card *);
+void qeth_clear_recovery_task(struct qeth_card *);
 void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
 int qeth_threads_running(struct qeth_card *, unsigned long);
 int qeth_wait_for_threads(struct qeth_card *, unsigned long);
index 0d73a999983d90ff632c0dcdcf6d54bedbd5a289..451f92020599e68add4a6b8a52888f672ad69084 100644 (file)
@@ -177,6 +177,23 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
        return "n/a";
 }
 
+void qeth_set_recovery_task(struct qeth_card *card)
+{
+       card->recovery_task = current;
+}
+EXPORT_SYMBOL_GPL(qeth_set_recovery_task);
+
+void qeth_clear_recovery_task(struct qeth_card *card)
+{
+       card->recovery_task = NULL;
+}
+EXPORT_SYMBOL_GPL(qeth_clear_recovery_task);
+
+static bool qeth_is_recovery_task(const struct qeth_card *card)
+{
+       return card->recovery_task == current;
+}
+
 void qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
                         int clear_start_mask)
 {
@@ -205,6 +222,8 @@ EXPORT_SYMBOL_GPL(qeth_threads_running);
 
 int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
 {
+       if (qeth_is_recovery_task(card))
+               return 0;
        return wait_event_interruptible(card->wait_q,
                        qeth_threads_running(card, threads) == 0);
 }
index d690166efeaffbd4d47f1d39d3111af232876e66..155b101bd7309432d32ce9ed915c1a3a1b889a60 100644 (file)
@@ -1143,6 +1143,7 @@ static int qeth_l2_recover(void *ptr)
        QETH_CARD_TEXT(card, 2, "recover2");
        dev_warn(&card->gdev->dev,
                "A recovery process has been started for the device\n");
+       qeth_set_recovery_task(card);
        __qeth_l2_set_offline(card->gdev, 1);
        rc = __qeth_l2_set_online(card->gdev, 1);
        if (!rc)
@@ -1153,6 +1154,7 @@ static int qeth_l2_recover(void *ptr)
                dev_warn(&card->gdev->dev, "The qeth device driver "
                                "failed to recover an error on the device\n");
        }
+       qeth_clear_recovery_task(card);
        qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
        qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
        return 0;
index 8710337dab3eceb4e5fa692d6a39accd697ba508..1f7edf1b26c33bff2b6a9baa6b163311a79fad6f 100644 (file)
@@ -3515,6 +3515,7 @@ static int qeth_l3_recover(void *ptr)
        QETH_CARD_TEXT(card, 2, "recover2");
        dev_warn(&card->gdev->dev,
                "A recovery process has been started for the device\n");
+       qeth_set_recovery_task(card);
        __qeth_l3_set_offline(card->gdev, 1);
        rc = __qeth_l3_set_online(card->gdev, 1);
        if (!rc)
@@ -3525,6 +3526,7 @@ static int qeth_l3_recover(void *ptr)
                dev_warn(&card->gdev->dev, "The qeth device driver "
                                "failed to recover an error on the device\n");
        }
+       qeth_clear_recovery_task(card);
        qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
        qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
        return 0;
index 1a9d1e3ce64cc94aa36581fd29cefb6084f3502f..c1441ed282eb911ff67a6363ce5a78f6cbe45199 100644 (file)
@@ -282,7 +282,7 @@ static irqreturn_t bbc_i2c_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void __init reset_one_i2c(struct bbc_i2c_bus *bp)
+static void reset_one_i2c(struct bbc_i2c_bus *bp)
 {
        writeb(I2C_PCF_PIN, bp->i2c_control_regs + 0x0);
        writeb(bp->own, bp->i2c_control_regs + 0x1);
@@ -291,7 +291,7 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp)
        writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0);
 }
 
-static struct bbc_i2c_bus * __init attach_one_i2c(struct platform_device *op, int index)
+static struct bbc_i2c_bus * attach_one_i2c(struct platform_device *op, int index)
 {
        struct bbc_i2c_bus *bp;
        struct device_node *dp;
index 2daf4b0da434c8711c4a7907916b1b8138c412f2..90bc7bd00966e9a87845bee59c1976a74d959fb3 100644 (file)
@@ -940,6 +940,7 @@ static int bnx2fc_libfc_config(struct fc_lport *lport)
        fc_exch_init(lport);
        fc_rport_init(lport);
        fc_disc_init(lport);
+       fc_disc_config(lport, lport);
        return 0;
 }
 
@@ -2133,6 +2134,7 @@ static int _bnx2fc_create(struct net_device *netdev,
        }
 
        ctlr = bnx2fc_to_ctlr(interface);
+       cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
        interface->vlan_id = vlan_id;
 
        interface->timer_work_queue =
@@ -2143,7 +2145,7 @@ static int _bnx2fc_create(struct net_device *netdev,
                goto ifput_err;
        }
 
-       lport = bnx2fc_if_create(interface, &interface->hba->pcidev->dev, 0);
+       lport = bnx2fc_if_create(interface, &cdev->dev, 0);
        if (!lport) {
                printk(KERN_ERR PFX "Failed to create interface (%s)\n",
                        netdev->name);
@@ -2159,8 +2161,6 @@ static int _bnx2fc_create(struct net_device *netdev,
        /* Make this master N_port */
        ctlr->lp = lport;
 
-       cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
-
        if (link_state == BNX2FC_CREATE_LINK_UP)
                cdev->enabled = FCOE_CTLR_ENABLED;
        else
index b5d92fc93c7023f6d0f395c5ce44c4589afeabea..9bfdc9a3f897a2e16dc9e0a34d5d6e47969c0d1c 100644 (file)
@@ -490,7 +490,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 {
        struct net_device *netdev = fcoe->netdev;
        struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe);
-       struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);
 
        rtnl_lock();
        if (!fcoe->removed)
@@ -501,7 +500,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
        /* tear-down the FCoE controller */
        fcoe_ctlr_destroy(fip);
        scsi_host_put(fip->lp->host);
-       fcoe_ctlr_device_delete(ctlr_dev);
        dev_put(netdev);
        module_put(THIS_MODULE);
 }
@@ -2194,6 +2192,8 @@ out_nodev:
  */
 static void fcoe_destroy_work(struct work_struct *work)
 {
+       struct fcoe_ctlr_device *cdev;
+       struct fcoe_ctlr *ctlr;
        struct fcoe_port *port;
        struct fcoe_interface *fcoe;
        struct Scsi_Host *shost;
@@ -2224,10 +2224,15 @@ static void fcoe_destroy_work(struct work_struct *work)
        mutex_lock(&fcoe_config_mutex);
 
        fcoe = port->priv;
+       ctlr = fcoe_to_ctlr(fcoe);
+       cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
+
        fcoe_if_destroy(port->lport);
        fcoe_interface_cleanup(fcoe);
 
        mutex_unlock(&fcoe_config_mutex);
+
+       fcoe_ctlr_device_delete(cdev);
 }
 
 /**
@@ -2335,7 +2340,9 @@ static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
                rc = -EIO;
                rtnl_unlock();
                fcoe_interface_cleanup(fcoe);
-               goto out_nortnl;
+               mutex_unlock(&fcoe_config_mutex);
+               fcoe_ctlr_device_delete(ctlr_dev);
+               goto out;
        }
 
        /* Make this the "master" N_Port */
@@ -2375,8 +2382,8 @@ static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
 
 out_nodev:
        rtnl_unlock();
-out_nortnl:
        mutex_unlock(&fcoe_config_mutex);
+out:
        return rc;
 }
 
index 08c3bc398da2c1b234dadb62a56f1e1b47da5500..a76247201be570987fe28b44545184bd777e65c0 100644 (file)
@@ -2814,6 +2814,47 @@ unlock:
                fc_lport_set_local_id(fip->lp, new_port_id);
 }
 
+/**
+ * fcoe_ctlr_mode_set() - Set or reset the ctlr's mode
+ * @lport: The local port to be (re)configured
+ * @fip:   The FCoE controller whose mode is changing
+ * @fip_mode: The new fip mode
+ *
+ * Note that the we shouldn't be changing the libfc discovery settings
+ * (fc_disc_config) while an lport is going through the libfc state
+ * machine. The mode can only be changed when a fcoe_ctlr device is
+ * disabled, so that should ensure that this routine is only called
+ * when nothing is happening.
+ */
+void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip,
+                       enum fip_state fip_mode)
+{
+       void *priv;
+
+       WARN_ON(lport->state != LPORT_ST_RESET &&
+               lport->state != LPORT_ST_DISABLED);
+
+       if (fip_mode == FIP_MODE_VN2VN) {
+               lport->rport_priv_size = sizeof(struct fcoe_rport);
+               lport->point_to_multipoint = 1;
+               lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
+               lport->tt.disc_start = fcoe_ctlr_disc_start;
+               lport->tt.disc_stop = fcoe_ctlr_disc_stop;
+               lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
+               priv = fip;
+       } else {
+               lport->rport_priv_size = 0;
+               lport->point_to_multipoint = 0;
+               lport->tt.disc_recv_req = NULL;
+               lport->tt.disc_start = NULL;
+               lport->tt.disc_stop = NULL;
+               lport->tt.disc_stop_final = NULL;
+               priv = lport;
+       }
+
+       fc_disc_config(lport, priv);
+}
+
 /**
  * fcoe_libfc_config() - Sets up libfc related properties for local port
  * @lport:    The local port to configure libfc for
@@ -2833,21 +2874,9 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
        fc_exch_init(lport);
        fc_elsct_init(lport);
        fc_lport_init(lport);
-       if (fip->mode == FIP_MODE_VN2VN)
-               lport->rport_priv_size = sizeof(struct fcoe_rport);
        fc_rport_init(lport);
-       if (fip->mode == FIP_MODE_VN2VN) {
-               lport->point_to_multipoint = 1;
-               lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
-               lport->tt.disc_start = fcoe_ctlr_disc_start;
-               lport->tt.disc_stop = fcoe_ctlr_disc_stop;
-               lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
-               mutex_init(&lport->disc.disc_mutex);
-               INIT_LIST_HEAD(&lport->disc.rports);
-               lport->disc.priv = fip;
-       } else {
-               fc_disc_init(lport);
-       }
+       fc_disc_init(lport);
+       fcoe_ctlr_mode_set(lport, fip, fip->mode);
        return 0;
 }
 EXPORT_SYMBOL_GPL(fcoe_libfc_config);
@@ -2875,6 +2904,7 @@ EXPORT_SYMBOL(fcoe_fcf_get_selected);
 void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
 {
        struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+       struct fc_lport *lport = ctlr->lp;
 
        mutex_lock(&ctlr->ctlr_mutex);
        switch (ctlr_dev->mode) {
@@ -2888,5 +2918,7 @@ void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
        }
 
        mutex_unlock(&ctlr->ctlr_mutex);
+
+       fcoe_ctlr_mode_set(lport, ctlr, ctlr->mode);
 }
 EXPORT_SYMBOL(fcoe_ctlr_set_fip_mode);
index a044f593e8b98437e208cc1b785ca58371483890..d0fa4b6c551fd677bfa14252525717cf4f32469d 100644 (file)
@@ -1899,8 +1899,8 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev)
                sdev->allow_restart = 1;
                blk_queue_rq_timeout(sdev->request_queue, 120 * HZ);
        }
-       scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
        spin_unlock_irqrestore(shost->host_lock, lock_flags);
+       scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
        return 0;
 }
 
index f328089a1060a95ac9872e6b480f5dfe3cb7e120..2197b57fb2251f541e0bfc0eab626ce670b66504 100644 (file)
@@ -5148,7 +5148,7 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd)
                ipr_trace;
        }
 
-       list_add_tail(&ipr_cmd->queue, &hrrq->hrrq_free_q);
+       list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
        if (!ipr_is_naca_model(res))
                res->needs_sync_complete = 1;
 
@@ -9349,7 +9349,10 @@ static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev)
        int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
-       rc = request_irq(pdev->irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
+       if (ioa_cfg->intr_flag == IPR_USE_MSIX)
+               rc = request_irq(ioa_cfg->vectors_info[0].vec, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
+       else
+               rc = request_irq(pdev->irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
        if (rc) {
                dev_err(&pdev->dev, "Can not assign irq %d\n", pdev->irq);
                return rc;
@@ -9371,7 +9374,10 @@ static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev)
 
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
-       free_irq(pdev->irq, ioa_cfg);
+       if (ioa_cfg->intr_flag == IPR_USE_MSIX)
+               free_irq(ioa_cfg->vectors_info[0].vec, ioa_cfg);
+       else
+               free_irq(pdev->irq, ioa_cfg);
 
        LEAVE;
 
@@ -9722,6 +9728,7 @@ static void __ipr_remove(struct pci_dev *pdev)
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
        wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
        flush_work(&ioa_cfg->work_q);
+       INIT_LIST_HEAD(&ioa_cfg->used_res_q);
        spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
 
        spin_lock(&ipr_driver_lock);
index 8e561e6a557cd956188366488d5b4ed3dfe66021..880a9068ca1268baf851ea8804f3bdb4216049f6 100644 (file)
@@ -712,12 +712,13 @@ static void fc_disc_stop_final(struct fc_lport *lport)
 }
 
 /**
- * fc_disc_init() - Initialize the discovery layer for a local port
- * @lport: The local port that needs the discovery layer to be initialized
+ * fc_disc_config() - Configure the discovery layer for a local port
+ * @lport: The local port that needs the discovery layer to be configured
+ * @priv: Private data structre for users of the discovery layer
  */
-int fc_disc_init(struct fc_lport *lport)
+void fc_disc_config(struct fc_lport *lport, void *priv)
 {
-       struct fc_disc *disc;
+       struct fc_disc *disc = &lport->disc;
 
        if (!lport->tt.disc_start)
                lport->tt.disc_start = fc_disc_start;
@@ -732,12 +733,21 @@ int fc_disc_init(struct fc_lport *lport)
                lport->tt.disc_recv_req = fc_disc_recv_req;
 
        disc = &lport->disc;
+
+       disc->priv = priv;
+}
+EXPORT_SYMBOL(fc_disc_config);
+
+/**
+ * fc_disc_init() - Initialize the discovery layer for a local port
+ * @lport: The local port that needs the discovery layer to be initialized
+ */
+void fc_disc_init(struct fc_lport *lport)
+{
+       struct fc_disc *disc = &lport->disc;
+
        INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
        mutex_init(&disc->disc_mutex);
        INIT_LIST_HEAD(&disc->rports);
-
-       disc->priv = lport;
-
-       return 0;
 }
 EXPORT_SYMBOL(fc_disc_init);
index aec2e0da50164ca688cc9e2ea95355f0aeaf4669..55cbd018015997bba484bfe5ffdbacabcc7e43db 100644 (file)
@@ -235,6 +235,17 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
        linkrate  = phy->linkrate;
        memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
 
+       /* Handle vacant phy - rest of dr data is not valid so skip it */
+       if (phy->phy_state == PHY_VACANT) {
+               memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
+               phy->attached_dev_type = NO_DEVICE;
+               if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) {
+                       phy->phy_id = phy_id;
+                       goto skip;
+               } else
+                       goto out;
+       }
+
        phy->attached_dev_type = to_dev_type(dr);
        if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
                goto out;
@@ -272,6 +283,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
        phy->phy->maximum_linkrate = dr->pmax_linkrate;
        phy->phy->negotiated_linkrate = phy->linkrate;
 
+ skip:
        if (new_phy)
                if (sas_phy_add(phy->phy)) {
                        sas_phy_free(phy->phy);
@@ -388,7 +400,7 @@ int sas_ex_phy_discover(struct domain_device *dev, int single)
        if (!disc_req)
                return -ENOMEM;
 
-       disc_resp = alloc_smp_req(DISCOVER_RESP_SIZE);
+       disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
        if (!disc_resp) {
                kfree(disc_req);
                return -ENOMEM;
index 74b67d98e952b43fd980430b0fa0d9c37c55f741..d43faf34c1e29221ddc02b3aedcb2c566a0ed5e8 100644 (file)
@@ -438,11 +438,12 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
        struct lpfc_rqe *temp_hrqe;
        struct lpfc_rqe *temp_drqe;
        struct lpfc_register doorbell;
-       int put_index = hq->host_index;
+       int put_index;
 
        /* sanity check on queue memory */
        if (unlikely(!hq) || unlikely(!dq))
                return -ENOMEM;
+       put_index = hq->host_index;
        temp_hrqe = hq->qe[hq->host_index].rqe;
        temp_drqe = dq->qe[dq->host_index].rqe;
 
index 408d2548a748af7c134a210fe687ad2e37663f62..684cc343cf09465aeceeb572af86d16827892e26 100644 (file)
@@ -1488,7 +1488,4 @@ struct megasas_mgmt_info {
        int max_index;
 };
 
-#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
-#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
-
 #endif                         /*LSI_MEGARAID_SAS_H */
index 9d53540207ec6ef03e175ee875fcfbbdcf371f8e..7c90d57b867e2c332e1a953a3c01892f971bd779 100644 (file)
@@ -3984,12 +3984,12 @@ static int megasas_probe_one(struct pci_dev *pdev,
        if (reset_devices) {
                pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
                if (pos) {
-                       pci_read_config_word(pdev, msi_control_reg(pos),
+                       pci_read_config_word(pdev, pos + PCI_MSIX_FLAGS,
                                             &control);
                        if (control & PCI_MSIX_FLAGS_ENABLE) {
                                dev_info(&pdev->dev, "resetting MSI-X\n");
                                pci_write_config_word(pdev,
-                                                     msi_control_reg(pos),
+                                                     pos + PCI_MSIX_FLAGS,
                                                      control &
                                                      ~PCI_MSIX_FLAGS_ENABLE);
                        }
index ce90d0546cddf3a0e7b85957c003266c05d2d6fd..74550922ad55e418eb7e37753e0983023728943b 100644 (file)
@@ -703,7 +703,7 @@ static struct pci_device_id mvs_pci_table[] = {
        { PCI_VDEVICE(TTI, 0x2744), chip_9480 },
        { PCI_VDEVICE(TTI, 0x2760), chip_9480 },
        {
-               .vendor         = 0x1b4b,
+               .vendor         = PCI_VENDOR_ID_MARVELL_EXT,
                .device         = 0x9480,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = 0x9480,
@@ -712,7 +712,7 @@ static struct pci_device_id mvs_pci_table[] = {
                .driver_data    = chip_9480,
        },
        {
-               .vendor         = 0x1b4b,
+               .vendor         = PCI_VENDOR_ID_MARVELL_EXT,
                .device         = 0x9445,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = 0x9480,
@@ -721,7 +721,7 @@ static struct pci_device_id mvs_pci_table[] = {
                .driver_data    = chip_9445,
        },
        {
-               .vendor         = 0x1b4b,
+               .vendor         = PCI_VENDOR_ID_MARVELL_EXT,
                .device         = 0x9485,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = 0x9480,
index 4594ccaaf49ba2ce3f697c2fab355efe493f122d..c3601b57a80c796cd32aebeb3c00f3d94e89b06f 100644 (file)
@@ -49,8 +49,8 @@ MODULE_AUTHOR("jyli@marvell.com");
 MODULE_DESCRIPTION("Marvell UMI Driver");
 
 static DEFINE_PCI_DEVICE_TABLE(mvumi_pci_table) = {
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9143) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9580) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9143) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9580) },
        { 0 }
 };
 
index e360135fd1bd59a8d851d90da6a6163d017e9d66..41f168702ac7ab76925a1bac5be69878c161c1c7 100644 (file)
@@ -32,7 +32,6 @@
 #define VER_BUILD              1500
 
 #define MV_DRIVER_NAME                 "mvumi"
-#define PCI_VENDOR_ID_MARVELL_2                0x1b4b
 #define PCI_DEVICE_ID_MARVELL_MV9143   0x9143
 #define PCI_DEVICE_ID_MARVELL_MV9580   0x9580
 
index 1d82eef4e1ebf33f2abc59b5b56a9c3b00f7f907..b3db9dcc261957c88d975246dbac839a1f017805 100644 (file)
@@ -1938,11 +1938,6 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
                    "Timer for the VP[%d] has stopped\n", vha->vp_idx);
        }
 
-       /* No pending activities shall be there on the vha now */
-       if (ql2xextended_error_logging & ql_dbg_user)
-               msleep(random32()%10);  /* Just to see if something falls on
-                                       * the net we have placed below */
-
        BUG_ON(atomic_read(&vha->vref_count));
 
        qla2x00_free_fcports(vha);
index 1626de52e32a764ae370c7c3bccd3bc65c4a7162..fbc305f1c87c5dafc34e95c9c6aa8004699f3820 100644 (file)
@@ -15,6 +15,7 @@
  * | Mailbox commands             |       0x115b       | 0x111a-0x111b  |
  * |                              |                    | 0x112c-0x112e  |
  * |                              |                    | 0x113a         |
+ * |                              |                    | 0x1155-0x1158  |
  * | Device Discovery             |       0x2087       | 0x2020-0x2022, |
  * |                              |                    | 0x2016         |
  * | Queue Command and IO tracing |       0x3031       | 0x3006-0x300b  |
@@ -401,7 +402,7 @@ qla2xxx_copy_atioqueues(struct qla_hw_data *ha, void *ptr,
                void *ring;
        } aq, *aqp;
 
-       if (!ha->tgt.atio_q_length)
+       if (!ha->tgt.atio_ring)
                return ptr;
 
        num_queues = 1;
index c6509911772b5569e9de368bca1a995897359b43..65c5ff75936b1a31c7d37529a74558482168d8af 100644 (file)
@@ -863,7 +863,6 @@ typedef struct {
 #define        MBX_1           BIT_1
 #define        MBX_0           BIT_0
 
-#define RNID_TYPE_SET_VERSION  0x9
 #define RNID_TYPE_ASIC_TEMP    0xC
 
 /*
index eb3ca21a7f17b3c36d08ced7bb6cf0344a85f81e..b310fa97b545c97b81119271a3938ad1ed0c3c4e 100644 (file)
@@ -357,9 +357,6 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *, dma_addr_t, uint16_t , uint16_t *,
 extern int
 qla2x00_disable_fce_trace(scsi_qla_host_t *, uint64_t *, uint64_t *);
 
-extern int
-qla2x00_set_driver_version(scsi_qla_host_t *, char *);
-
 extern int
 qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint8_t *,
        uint16_t, uint16_t, uint16_t, uint16_t);
index edf4d14a13356f788bd3bbdcf35c245b3bbc440c..b59203393cb22f0a991d299fcc2eac285f7cac9e 100644 (file)
@@ -619,8 +619,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
        if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))
                qla24xx_read_fcp_prio_cfg(vha);
 
-       qla2x00_set_driver_version(vha, QLA2XXX_VERSION);
-
        return (rval);
 }
 
@@ -1399,7 +1397,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
                        mq_size += ha->max_rsp_queues *
                            (rsp->length * sizeof(response_t));
                }
-               if (ha->tgt.atio_q_length)
+               if (ha->tgt.atio_ring)
                        mq_size += ha->tgt.atio_q_length * sizeof(request_t);
                /* Allocate memory for Fibre Channel Event Buffer. */
                if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha))
index 186dd59ce4fa097d2cb051a38db5b49f507eb2b0..43345af56431d011850ad5568b5154179b4b3432 100644 (file)
@@ -3866,64 +3866,6 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
        return rval;
 }
 
-int
-qla2x00_set_driver_version(scsi_qla_host_t *vha, char *version)
-{
-       int rval;
-       mbx_cmd_t mc;
-       mbx_cmd_t *mcp = &mc;
-       int len;
-       uint16_t dwlen;
-       uint8_t *str;
-       dma_addr_t str_dma;
-       struct qla_hw_data *ha = vha->hw;
-
-       if (!IS_FWI2_CAPABLE(ha) || IS_QLA82XX(ha))
-               return QLA_FUNCTION_FAILED;
-
-       ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1155,
-           "Entered %s.\n", __func__);
-
-       str = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &str_dma);
-       if (!str) {
-               ql_log(ql_log_warn, vha, 0x1156,
-                   "Failed to allocate driver version param.\n");
-               return QLA_MEMORY_ALLOC_FAILED;
-       }
-
-       memcpy(str, "\x7\x3\x11\x0", 4);
-       dwlen = str[0];
-       len = dwlen * sizeof(uint32_t) - 4;
-       memset(str + 4, 0, len);
-       if (len > strlen(version))
-               len = strlen(version);
-       memcpy(str + 4, version, len);
-
-       mcp->mb[0] = MBC_SET_RNID_PARAMS;
-       mcp->mb[1] = RNID_TYPE_SET_VERSION << 8 | dwlen;
-       mcp->mb[2] = MSW(LSD(str_dma));
-       mcp->mb[3] = LSW(LSD(str_dma));
-       mcp->mb[6] = MSW(MSD(str_dma));
-       mcp->mb[7] = LSW(MSD(str_dma));
-       mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
-       mcp->in_mb = MBX_0;
-       mcp->tov = MBX_TOV_SECONDS;
-       mcp->flags = 0;
-       rval = qla2x00_mailbox_command(vha, mcp);
-
-       if (rval != QLA_SUCCESS) {
-               ql_dbg(ql_dbg_mbx, vha, 0x1157,
-                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
-       } else {
-               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1158,
-                   "Done %s.\n", __func__);
-       }
-
-       dma_pool_free(ha->s_dma_pool, str, str_dma);
-
-       return rval;
-}
-
 static int
 qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
 {
index 2b6e478d9e33769f881d77b659839b29ae409b64..ec54036d1e12061e4ceee6ee8124270cf97f03f7 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.04.00.08-k"
+#define QLA2XXX_VERSION      "8.04.00.13-k"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   4
index 86974471af68bf1a27f9f940243fcf044d599a08..2a32036a9404be10941a71ac0f23afe46ca449f9 100644 (file)
@@ -4112,6 +4112,10 @@ static int st_probe(struct device *dev)
        tpnt->disk = disk;
        disk->private_data = &tpnt->driver;
        disk->queue = SDp->request_queue;
+       /* SCSI tape doesn't register this gendisk via add_disk().  Manually
+        * take queue reference that release_disk() expects. */
+       if (!blk_get_queue(disk->queue))
+               goto out_put_disk;
        tpnt->driver = &st_template;
 
        tpnt->device = SDp;
@@ -4185,7 +4189,7 @@ static int st_probe(struct device *dev)
        idr_preload_end();
        if (error < 0) {
                pr_warn("st: idr allocation failed: %d\n", error);
-               goto out_put_disk;
+               goto out_put_queue;
        }
        tpnt->index = error;
        sprintf(disk->disk_name, "st%d", tpnt->index);
@@ -4211,6 +4215,8 @@ out_remove_devs:
        spin_lock(&st_index_lock);
        idr_remove(&st_index_idr, tpnt->index);
        spin_unlock(&st_index_lock);
+out_put_queue:
+       blk_put_queue(disk->queue);
 out_put_disk:
        put_disk(disk);
        kfree(tpnt);
index f80eee74a3116c5a8935378d908fce904e3351f6..2be0de920d6756345de9cc78e04a7c1136ef9d4d 100644 (file)
@@ -55,6 +55,7 @@ comment "SPI Master Controller Drivers"
 
 config SPI_ALTERA
        tristate "Altera SPI Controller"
+       depends on GENERIC_HARDIRQS
        select SPI_BITBANG
        help
          This is the driver for the Altera SPI Controller.
@@ -310,7 +311,7 @@ config SPI_PXA2XX_DMA
 
 config SPI_PXA2XX
        tristate "PXA2xx SSP SPI master"
-       depends on ARCH_PXA || PCI || ACPI
+       depends on (ARCH_PXA || PCI || ACPI) && GENERIC_HARDIRQS
        select PXA_SSP if ARCH_PXA
        help
          This enables using a PXA2xx or Sodaville SSP port as a SPI master
index 9578af782a7732e3c9d4e4242c780f0bb7a21d01..d7df435d962e54db6a3121b55a4546f05bb69303 100644 (file)
@@ -152,7 +152,6 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
 static int bcm63xx_spi_setup(struct spi_device *spi)
 {
        struct bcm63xx_spi *bs;
-       int ret;
 
        bs = spi_master_get_devdata(spi->master);
 
@@ -490,7 +489,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
        default:
                dev_err(dev, "unsupported MSG_CTL width: %d\n",
                         bs->msg_ctl_width);
-               goto out_clk_disable;
+               goto out_err;
        }
 
        /* Initialize hardware */
index 89480b281d74715ad0eaa6cf63bf354546f99fc4..3e490ee7f275be30447ce5a3030f7872da634695 100644 (file)
@@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
 
                for (i = count; i > 0; i--) {
                        data = tx_buf ? *tx_buf++ : 0;
-                       if (len == EOFBYTE)
+                       if (len == EOFBYTE && t->cs_change)
                                setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
                        out_8(&fifo->txdata_8, data);
                        len--;
index 90b27a3508a65072bf8916fecea96f16ee73cbeb..810413883c79326d3cd31b18db2f9a8972a96967 100644 (file)
@@ -1168,7 +1168,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
 
        master->dev.parent = &pdev->dev;
        master->dev.of_node = pdev->dev.of_node;
-       ACPI_HANDLE_SET(&master->dev, ACPI_HANDLE(&pdev->dev));
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
 
index e862ab8853aa1f9ff242cdde3bf741dc2a257dd2..4188b2faac5cbb97a88225e39da14a78674ea74d 100644 (file)
@@ -994,25 +994,30 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
 {
        struct s3c64xx_spi_driver_data *sdd = data;
        struct spi_master *spi = sdd->master;
-       unsigned int val;
+       unsigned int val, clr = 0;
 
-       val = readl(sdd->regs + S3C64XX_SPI_PENDING_CLR);
+       val = readl(sdd->regs + S3C64XX_SPI_STATUS);
 
-       val &= S3C64XX_SPI_PND_RX_OVERRUN_CLR |
-               S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
-               S3C64XX_SPI_PND_TX_OVERRUN_CLR |
-               S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
-
-       writel(val, sdd->regs + S3C64XX_SPI_PENDING_CLR);
-
-       if (val & S3C64XX_SPI_PND_RX_OVERRUN_CLR)
+       if (val & S3C64XX_SPI_ST_RX_OVERRUN_ERR) {
+               clr = S3C64XX_SPI_PND_RX_OVERRUN_CLR;
                dev_err(&spi->dev, "RX overrun\n");
-       if (val & S3C64XX_SPI_PND_RX_UNDERRUN_CLR)
+       }
+       if (val & S3C64XX_SPI_ST_RX_UNDERRUN_ERR) {
+               clr |= S3C64XX_SPI_PND_RX_UNDERRUN_CLR;
                dev_err(&spi->dev, "RX underrun\n");
-       if (val & S3C64XX_SPI_PND_TX_OVERRUN_CLR)
+       }
+       if (val & S3C64XX_SPI_ST_TX_OVERRUN_ERR) {
+               clr |= S3C64XX_SPI_PND_TX_OVERRUN_CLR;
                dev_err(&spi->dev, "TX overrun\n");
-       if (val & S3C64XX_SPI_PND_TX_UNDERRUN_CLR)
+       }
+       if (val & S3C64XX_SPI_ST_TX_UNDERRUN_ERR) {
+               clr |= S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
                dev_err(&spi->dev, "TX underrun\n");
+       }
+
+       /* Clear the pending irq by setting and then clearing it */
+       writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR);
+       writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR);
 
        return IRQ_HANDLED;
 }
@@ -1036,9 +1041,13 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
        writel(0, regs + S3C64XX_SPI_MODE_CFG);
        writel(0, regs + S3C64XX_SPI_PACKET_CNT);
 
-       /* Clear any irq pending bits */
-       writel(readl(regs + S3C64XX_SPI_PENDING_CLR),
-                               regs + S3C64XX_SPI_PENDING_CLR);
+       /* Clear any irq pending bits, should set and clear the bits */
+       val = S3C64XX_SPI_PND_RX_OVERRUN_CLR |
+               S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
+               S3C64XX_SPI_PND_TX_OVERRUN_CLR |
+               S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
+       writel(val, regs + S3C64XX_SPI_PENDING_CLR);
+       writel(0, regs + S3C64XX_SPI_PENDING_CLR);
 
        writel(0, regs + S3C64XX_SPI_SWAP_CFG);
 
index b8698b389ef3ec6980da435317ec383f2c1ea22a..a829563f471380dfe04d530f8ec6155bff19c4a7 100644 (file)
@@ -858,21 +858,6 @@ static int tegra_slink_setup(struct spi_device *spi)
        return 0;
 }
 
-static int tegra_slink_prepare_transfer(struct spi_master *master)
-{
-       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
-
-       return pm_runtime_get_sync(tspi->dev);
-}
-
-static int tegra_slink_unprepare_transfer(struct spi_master *master)
-{
-       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
-
-       pm_runtime_put(tspi->dev);
-       return 0;
-}
-
 static int tegra_slink_transfer_one_message(struct spi_master *master,
                        struct spi_message *msg)
 {
@@ -885,6 +870,12 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
 
        msg->status = 0;
        msg->actual_length = 0;
+       ret = pm_runtime_get_sync(tspi->dev);
+       if (ret < 0) {
+               dev_err(tspi->dev, "runtime get failed: %d\n", ret);
+               goto done;
+       }
+
        single_xfer = list_is_singular(&msg->transfers);
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                INIT_COMPLETION(tspi->xfer_completion);
@@ -921,6 +912,8 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
 exit:
        tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
        tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
+       pm_runtime_put(tspi->dev);
+done:
        msg->status = ret;
        spi_finalize_current_message(master);
        return ret;
@@ -1148,9 +1141,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
        master->setup = tegra_slink_setup;
-       master->prepare_transfer_hardware = tegra_slink_prepare_transfer;
        master->transfer_one_message = tegra_slink_transfer_one_message;
-       master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer;
        master->num_chipselect = MAX_CHIP_SELECT;
        master->bus_num = -1;
 
index f996c600eb8c6a63b0d3122dd0b267a95d032555..004b10f184d4e7fe00916af3fc5acad6d7866139 100644 (file)
@@ -543,17 +543,16 @@ static void spi_pump_messages(struct kthread_work *work)
        /* Lock queue and check for queue work */
        spin_lock_irqsave(&master->queue_lock, flags);
        if (list_empty(&master->queue) || !master->running) {
-               if (master->busy && master->unprepare_transfer_hardware) {
-                       ret = master->unprepare_transfer_hardware(master);
-                       if (ret) {
-                               spin_unlock_irqrestore(&master->queue_lock, flags);
-                               dev_err(&master->dev,
-                                       "failed to unprepare transfer hardware\n");
-                               return;
-                       }
+               if (!master->busy) {
+                       spin_unlock_irqrestore(&master->queue_lock, flags);
+                       return;
                }
                master->busy = false;
                spin_unlock_irqrestore(&master->queue_lock, flags);
+               if (master->unprepare_transfer_hardware &&
+                   master->unprepare_transfer_hardware(master))
+                       dev_err(&master->dev,
+                               "failed to unprepare transfer hardware\n");
                return;
        }
 
@@ -984,7 +983,7 @@ static void acpi_register_spi_devices(struct spi_master *master)
        acpi_status status;
        acpi_handle handle;
 
-       handle = ACPI_HANDLE(&master->dev);
+       handle = ACPI_HANDLE(master->dev.parent);
        if (!handle)
                return;
 
index 4c0f6d883dd3bf689e1900d47285000f39734d5e..7b0bce9367626ad987eb900528a7b329a2f32261 100644 (file)
@@ -675,3 +675,32 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc)
                return 0;
        }
 }
+
+void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid)
+{
+       u32 pmu_ctl = 0;
+
+       switch (cc->dev->bus->chip_id) {
+       case 0x4322:
+               ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100070);
+               ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x1014140a);
+               ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888854);
+               if (spuravoid == 1)
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05201828);
+               else
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05001828);
+               pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
+               break;
+       case 43222:
+               /* TODO: BCM43222 requires updating PLLs too */
+               return;
+       default:
+               ssb_printk(KERN_ERR PFX
+                          "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
+                          cc->dev->bus->chip_id);
+               return;
+       }
+
+       chipco_set32(cc, SSB_CHIPCO_PMU_CTL, pmu_ctl);
+}
+EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate);
index ff1c5ee352cb91107d61f09ae277a33acff9fa26..cbe48ab417459de02ec06660934ec8b3ff8804c0 100644 (file)
@@ -409,6 +409,7 @@ static inline int core_alua_state_standby(
        case REPORT_LUNS:
        case RECEIVE_DIAGNOSTIC:
        case SEND_DIAGNOSTIC:
+               return 0;
        case MAINTENANCE_IN:
                switch (cdb[1] & 0x1f) {
                case MI_REPORT_TARGET_PGS:
@@ -451,6 +452,7 @@ static inline int core_alua_state_unavailable(
        switch (cdb[0]) {
        case INQUIRY:
        case REPORT_LUNS:
+               return 0;
        case MAINTENANCE_IN:
                switch (cdb[1] & 0x1f) {
                case MI_REPORT_TARGET_PGS:
@@ -491,6 +493,7 @@ static inline int core_alua_state_transition(
        switch (cdb[0]) {
        case INQUIRY:
        case REPORT_LUNS:
+               return 0;
        case MAINTENANCE_IN:
                switch (cdb[1] & 0x1f) {
                case MI_REPORT_TARGET_PGS:
index 484b6a3c9b03714a3eae559e061f3767cdc3af72..302909ccf18383831e5f6091f167be354b4db989 100644 (file)
@@ -2643,9 +2643,9 @@ static int mxser_probe(struct pci_dev *pdev,
                                mxvar_sdriver, brd->idx + i, &pdev->dev);
                if (IS_ERR(tty_dev)) {
                        retval = PTR_ERR(tty_dev);
-                       for (i--; i >= 0; i--)
+                       for (; i > 0; i--)
                                tty_unregister_device(mxvar_sdriver,
-                                       brd->idx + i);
+                                       brd->idx + i - 1);
                        goto err_relbrd;
                }
        }
@@ -2751,9 +2751,9 @@ static int __init mxser_module_init(void)
                        tty_dev = tty_port_register_device(&brd->ports[i].port,
                                        mxvar_sdriver, brd->idx + i, NULL);
                        if (IS_ERR(tty_dev)) {
-                               for (i--; i >= 0; i--)
+                               for (; i > 0; i--)
                                        tty_unregister_device(mxvar_sdriver,
-                                               brd->idx + i);
+                                               brd->idx + i - 1);
                                for (i = 0; i < brd->info->nports; i++)
                                        tty_port_destroy(&brd->ports[i].port);
                                free_irq(brd->irq, brd);
index b3455a970a1da01c0afcf013d8c31a49e1004005..35d9ab95c5cbb51d6092f67540678f00e4ee52bd 100644 (file)
@@ -429,7 +429,6 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
        struct uart_8250_port uart;
        int ret, line, flags = dev_id->driver_data;
-       struct resource *res = NULL;
 
        if (flags & UNKNOWN_DEV) {
                ret = serial_pnp_guess_board(dev);
@@ -440,12 +439,11 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
        memset(&uart, 0, sizeof(uart));
        if (pnp_irq_valid(dev, 0))
                uart.port.irq = pnp_irq(dev, 0);
-       if ((flags & CIR_PORT) && pnp_port_valid(dev, 2))
-               res = pnp_get_resource(dev, IORESOURCE_IO, 2);
-       else if (pnp_port_valid(dev, 0))
-               res = pnp_get_resource(dev, IORESOURCE_IO, 0);
-       if (pnp_resource_enabled(res)) {
-               uart.port.iobase = res->start;
+       if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
+               uart.port.iobase = pnp_port_start(dev, 2);
+               uart.port.iotype = UPIO_PORT;
+       } else if (pnp_port_valid(dev, 0)) {
+               uart.port.iobase = pnp_port_start(dev, 0);
                uart.port.iotype = UPIO_PORT;
        } else if (pnp_mem_valid(dev, 0)) {
                uart.port.mapbase = pnp_mem_start(dev, 0);
index 4dc41408ecb7f659c70ee4daedd96148bb96382d..30d4f7a783cd1f0bbfdf6ebaf491f2400153eaf0 100644 (file)
@@ -886,6 +886,17 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
        serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
        /* FIFO ENABLE, DMA MODE */
 
+       up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
+       /*
+        * NOTE: Setting OMAP_UART_SCR_RX_TRIG_GRANU1_MASK
+        * sets Enables the granularity of 1 for TRIGGER RX
+        * level. Along with setting RX FIFO trigger level
+        * to 1 (as noted below, 16 characters) and TLR[3:0]
+        * to zero this will result RX FIFO threshold level
+        * to 1 character, instead of 16 as noted in comment
+        * below.
+        */
+
        /* Set receive FIFO threshold to 16 characters and
         * transmit FIFO threshold to 16 spaces
         */
index 05400acbc456f1e9e888972e5c73c5c4f634d71c..b0452688308c6605bfc64168c790a442bef1407d 100644 (file)
@@ -941,6 +941,14 @@ void start_tty(struct tty_struct *tty)
 
 EXPORT_SYMBOL(start_tty);
 
+static void tty_update_time(struct timespec *time)
+{
+       unsigned long sec = get_seconds();
+       sec -= sec % 60;
+       if ((long)(sec - time->tv_sec) > 0)
+               time->tv_sec = sec;
+}
+
 /**
  *     tty_read        -       read method for tty device files
  *     @file: pointer to tty file
@@ -960,10 +968,11 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
                        loff_t *ppos)
 {
        int i;
+       struct inode *inode = file_inode(file);
        struct tty_struct *tty = file_tty(file);
        struct tty_ldisc *ld;
 
-       if (tty_paranoia_check(tty, file_inode(file), "tty_read"))
+       if (tty_paranoia_check(tty, inode, "tty_read"))
                return -EIO;
        if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
                return -EIO;
@@ -977,6 +986,9 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
                i = -EIO;
        tty_ldisc_deref(ld);
 
+       if (i > 0)
+               tty_update_time(&inode->i_atime);
+
        return i;
 }
 
@@ -1077,8 +1089,10 @@ static inline ssize_t do_tty_write(
                        break;
                cond_resched();
        }
-       if (written)
+       if (written) {
+               tty_update_time(&file_inode(file)->i_mtime);
                ret = written;
+       }
 out:
        tty_write_unlock(tty);
        return ret;
index 797f9d51473298582d166858b30e5e464ee2b18c..65d4e55552c68f01fa606331afcd3096bdc31300 100644 (file)
@@ -67,7 +67,6 @@ static void usb_port_device_release(struct device *dev)
 {
        struct usb_port *port_dev = to_usb_port(dev);
 
-       dev_pm_qos_hide_flags(dev);
        kfree(port_dev);
 }
 
index 8189cb6a86af29f870cd975d19c4c6b40020c40e..09d2e3ffd6fcefe6c7a7cf6c8c13c755b1c1fde5 100644 (file)
@@ -70,7 +70,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
                pci_write_config_word(pdev, PCI_COMMAND, cmd);
        }
 
-       msix_pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+       msix_pos = pdev->msix_cap;
        if (msix_pos) {
                u16 flags;
                u32 table;
@@ -78,8 +78,8 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
                pci_read_config_word(pdev, msix_pos + PCI_MSIX_FLAGS, &flags);
                pci_read_config_dword(pdev, msix_pos + PCI_MSIX_TABLE, &table);
 
-               vdev->msix_bar = table & PCI_MSIX_FLAGS_BIRMASK;
-               vdev->msix_offset = table & ~PCI_MSIX_FLAGS_BIRMASK;
+               vdev->msix_bar = table & PCI_MSIX_TABLE_BIR;
+               vdev->msix_offset = table & PCI_MSIX_TABLE_OFFSET;
                vdev->msix_size = ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) * 16;
        } else
                vdev->msix_bar = 0xFF;
@@ -183,7 +183,7 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type)
                u8 pos;
                u16 flags;
 
-               pos = pci_find_capability(vdev->pdev, PCI_CAP_ID_MSI);
+               pos = vdev->pdev->msi_cap;
                if (pos) {
                        pci_read_config_word(vdev->pdev,
                                             pos + PCI_MSI_FLAGS, &flags);
@@ -194,7 +194,7 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type)
                u8 pos;
                u16 flags;
 
-               pos = pci_find_capability(vdev->pdev, PCI_CAP_ID_MSIX);
+               pos = vdev->pdev->msix_cap;
                if (pos) {
                        pci_read_config_word(vdev->pdev,
                                             pos + PCI_MSIX_FLAGS, &flags);
@@ -346,6 +346,7 @@ static long vfio_pci_ioctl(void *device_data,
 
                if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
                        size_t size;
+                       int max = vfio_pci_get_irq_count(vdev, hdr.index);
 
                        if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
                                size = sizeof(uint8_t);
@@ -355,7 +356,7 @@ static long vfio_pci_ioctl(void *device_data,
                                return -EINVAL;
 
                        if (hdr.argsz - minsz < hdr.count * size ||
-                           hdr.count > vfio_pci_get_irq_count(vdev, hdr.index))
+                           hdr.start >= max || hdr.start + hdr.count > max)
                                return -EINVAL;
 
                        data = memdup_user((void __user *)(arg + minsz),
index 2968b4934659aab01dd626334a9ab7fc0e607383..957a0b98a5d90f689c68fb92ba76e60c72f89944 100644 (file)
@@ -74,9 +74,8 @@ enum {
 
 struct vhost_scsi {
        /* Protected by vhost_scsi->dev.mutex */
-       struct tcm_vhost_tpg *vs_tpg[VHOST_SCSI_MAX_TARGET];
+       struct tcm_vhost_tpg **vs_tpg;
        char vs_vhost_wwpn[TRANSPORT_IQN_LEN];
-       bool vs_endpoint;
 
        struct vhost_dev dev;
        struct vhost_virtqueue vqs[VHOST_SCSI_MAX_VQ];
@@ -579,9 +578,27 @@ static void tcm_vhost_submission_work(struct work_struct *work)
        }
 }
 
+static void vhost_scsi_send_bad_target(struct vhost_scsi *vs,
+       struct vhost_virtqueue *vq, int head, unsigned out)
+{
+       struct virtio_scsi_cmd_resp __user *resp;
+       struct virtio_scsi_cmd_resp rsp;
+       int ret;
+
+       memset(&rsp, 0, sizeof(rsp));
+       rsp.response = VIRTIO_SCSI_S_BAD_TARGET;
+       resp = vq->iov[out].iov_base;
+       ret = __copy_to_user(resp, &rsp, sizeof(rsp));
+       if (!ret)
+               vhost_add_used_and_signal(&vs->dev, vq, head, 0);
+       else
+               pr_err("Faulted on virtio_scsi_cmd_resp\n");
+}
+
 static void vhost_scsi_handle_vq(struct vhost_scsi *vs,
        struct vhost_virtqueue *vq)
 {
+       struct tcm_vhost_tpg **vs_tpg;
        struct virtio_scsi_cmd_req v_req;
        struct tcm_vhost_tpg *tv_tpg;
        struct tcm_vhost_cmd *tv_cmd;
@@ -590,8 +607,16 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs,
        int head, ret;
        u8 target;
 
-       /* Must use ioctl VHOST_SCSI_SET_ENDPOINT */
-       if (unlikely(!vs->vs_endpoint))
+       /*
+        * We can handle the vq only after the endpoint is setup by calling the
+        * VHOST_SCSI_SET_ENDPOINT ioctl.
+        *
+        * TODO: Check that we are running from vhost_worker which acts
+        * as read-side critical section for vhost kind of RCU.
+        * See the comments in struct vhost_virtqueue in drivers/vhost/vhost.h
+        */
+       vs_tpg = rcu_dereference_check(vq->private_data, 1);
+       if (!vs_tpg)
                return;
 
        mutex_lock(&vq->mutex);
@@ -661,23 +686,11 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs,
 
                /* Extract the tpgt */
                target = v_req.lun[1];
-               tv_tpg = vs->vs_tpg[target];
+               tv_tpg = ACCESS_ONCE(vs_tpg[target]);
 
                /* Target does not exist, fail the request */
                if (unlikely(!tv_tpg)) {
-                       struct virtio_scsi_cmd_resp __user *resp;
-                       struct virtio_scsi_cmd_resp rsp;
-
-                       memset(&rsp, 0, sizeof(rsp));
-                       rsp.response = VIRTIO_SCSI_S_BAD_TARGET;
-                       resp = vq->iov[out].iov_base;
-                       ret = __copy_to_user(resp, &rsp, sizeof(rsp));
-                       if (!ret)
-                               vhost_add_used_and_signal(&vs->dev,
-                                                         vq, head, 0);
-                       else
-                               pr_err("Faulted on virtio_scsi_cmd_resp\n");
-
+                       vhost_scsi_send_bad_target(vs, vq, head, out);
                        continue;
                }
 
@@ -690,22 +703,13 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs,
                if (IS_ERR(tv_cmd)) {
                        vq_err(vq, "vhost_scsi_allocate_cmd failed %ld\n",
                                        PTR_ERR(tv_cmd));
-                       break;
+                       goto err_cmd;
                }
                pr_debug("Allocated tv_cmd: %p exp_data_len: %d, data_direction"
                        ": %d\n", tv_cmd, exp_data_len, data_direction);
 
                tv_cmd->tvc_vhost = vs;
                tv_cmd->tvc_vq = vq;
-
-               if (unlikely(vq->iov[out].iov_len !=
-                               sizeof(struct virtio_scsi_cmd_resp))) {
-                       vq_err(vq, "Expecting virtio_scsi_cmd_resp, got %zu"
-                               " bytes, out: %d, in: %d\n",
-                               vq->iov[out].iov_len, out, in);
-                       break;
-               }
-
                tv_cmd->tvc_resp = vq->iov[out].iov_base;
 
                /*
@@ -725,7 +729,7 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs,
                                " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n",
                                scsi_command_size(tv_cmd->tvc_cdb),
                                TCM_VHOST_MAX_CDB_SIZE);
-                       break; /* TODO */
+                       goto err_free;
                }
                tv_cmd->tvc_lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF;
 
@@ -738,7 +742,7 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs,
                                        data_direction == DMA_TO_DEVICE);
                        if (unlikely(ret)) {
                                vq_err(vq, "Failed to map iov to sgl\n");
-                               break; /* TODO */
+                               goto err_free;
                        }
                }
 
@@ -759,6 +763,13 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs,
        }
 
        mutex_unlock(&vq->mutex);
+       return;
+
+err_free:
+       vhost_scsi_free_cmd(tv_cmd);
+err_cmd:
+       vhost_scsi_send_bad_target(vs, vq, head, out);
+       mutex_unlock(&vq->mutex);
 }
 
 static void vhost_scsi_ctl_handle_kick(struct vhost_work *work)
@@ -780,6 +791,20 @@ static void vhost_scsi_handle_kick(struct vhost_work *work)
        vhost_scsi_handle_vq(vs, vq);
 }
 
+static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index)
+{
+       vhost_poll_flush(&vs->dev.vqs[index].poll);
+}
+
+static void vhost_scsi_flush(struct vhost_scsi *vs)
+{
+       int i;
+
+       for (i = 0; i < VHOST_SCSI_MAX_VQ; i++)
+               vhost_scsi_flush_vq(vs, i);
+       vhost_work_flush(&vs->dev, &vs->vs_completion_work);
+}
+
 /*
  * Called from vhost_scsi_ioctl() context to walk the list of available
  * tcm_vhost_tpg with an active struct tcm_vhost_nexus
@@ -790,8 +815,10 @@ static int vhost_scsi_set_endpoint(
 {
        struct tcm_vhost_tport *tv_tport;
        struct tcm_vhost_tpg *tv_tpg;
+       struct tcm_vhost_tpg **vs_tpg;
+       struct vhost_virtqueue *vq;
+       int index, ret, i, len;
        bool match = false;
-       int index, ret;
 
        mutex_lock(&vs->dev.mutex);
        /* Verify that ring has been setup correctly. */
@@ -803,6 +830,15 @@ static int vhost_scsi_set_endpoint(
                }
        }
 
+       len = sizeof(vs_tpg[0]) * VHOST_SCSI_MAX_TARGET;
+       vs_tpg = kzalloc(len, GFP_KERNEL);
+       if (!vs_tpg) {
+               mutex_unlock(&vs->dev.mutex);
+               return -ENOMEM;
+       }
+       if (vs->vs_tpg)
+               memcpy(vs_tpg, vs->vs_tpg, len);
+
        mutex_lock(&tcm_vhost_mutex);
        list_for_each_entry(tv_tpg, &tcm_vhost_list, tv_tpg_list) {
                mutex_lock(&tv_tpg->tv_tpg_mutex);
@@ -817,14 +853,15 @@ static int vhost_scsi_set_endpoint(
                tv_tport = tv_tpg->tport;
 
                if (!strcmp(tv_tport->tport_name, t->vhost_wwpn)) {
-                       if (vs->vs_tpg[tv_tpg->tport_tpgt]) {
+                       if (vs->vs_tpg && vs->vs_tpg[tv_tpg->tport_tpgt]) {
                                mutex_unlock(&tv_tpg->tv_tpg_mutex);
                                mutex_unlock(&tcm_vhost_mutex);
                                mutex_unlock(&vs->dev.mutex);
+                               kfree(vs_tpg);
                                return -EEXIST;
                        }
                        tv_tpg->tv_tpg_vhost_count++;
-                       vs->vs_tpg[tv_tpg->tport_tpgt] = tv_tpg;
+                       vs_tpg[tv_tpg->tport_tpgt] = tv_tpg;
                        smp_mb__after_atomic_inc();
                        match = true;
                }
@@ -835,12 +872,27 @@ static int vhost_scsi_set_endpoint(
        if (match) {
                memcpy(vs->vs_vhost_wwpn, t->vhost_wwpn,
                       sizeof(vs->vs_vhost_wwpn));
-               vs->vs_endpoint = true;
+               for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
+                       vq = &vs->vqs[i];
+                       /* Flushing the vhost_work acts as synchronize_rcu */
+                       mutex_lock(&vq->mutex);
+                       rcu_assign_pointer(vq->private_data, vs_tpg);
+                       vhost_init_used(vq);
+                       mutex_unlock(&vq->mutex);
+               }
                ret = 0;
        } else {
                ret = -EEXIST;
        }
 
+       /*
+        * Act as synchronize_rcu to make sure access to
+        * old vs->vs_tpg is finished.
+        */
+       vhost_scsi_flush(vs);
+       kfree(vs->vs_tpg);
+       vs->vs_tpg = vs_tpg;
+
        mutex_unlock(&vs->dev.mutex);
        return ret;
 }
@@ -851,6 +903,8 @@ static int vhost_scsi_clear_endpoint(
 {
        struct tcm_vhost_tport *tv_tport;
        struct tcm_vhost_tpg *tv_tpg;
+       struct vhost_virtqueue *vq;
+       bool match = false;
        int index, ret, i;
        u8 target;
 
@@ -862,9 +916,14 @@ static int vhost_scsi_clear_endpoint(
                        goto err_dev;
                }
        }
+
+       if (!vs->vs_tpg) {
+               mutex_unlock(&vs->dev.mutex);
+               return 0;
+       }
+
        for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) {
                target = i;
-
                tv_tpg = vs->vs_tpg[target];
                if (!tv_tpg)
                        continue;
@@ -886,10 +945,27 @@ static int vhost_scsi_clear_endpoint(
                }
                tv_tpg->tv_tpg_vhost_count--;
                vs->vs_tpg[target] = NULL;
-               vs->vs_endpoint = false;
+               match = true;
                mutex_unlock(&tv_tpg->tv_tpg_mutex);
        }
+       if (match) {
+               for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
+                       vq = &vs->vqs[i];
+                       /* Flushing the vhost_work acts as synchronize_rcu */
+                       mutex_lock(&vq->mutex);
+                       rcu_assign_pointer(vq->private_data, NULL);
+                       mutex_unlock(&vq->mutex);
+               }
+       }
+       /*
+        * Act as synchronize_rcu to make sure access to
+        * old vs->vs_tpg is finished.
+        */
+       vhost_scsi_flush(vs);
+       kfree(vs->vs_tpg);
+       vs->vs_tpg = NULL;
        mutex_unlock(&vs->dev.mutex);
+
        return 0;
 
 err_tpg:
@@ -899,6 +975,24 @@ err_dev:
        return ret;
 }
 
+static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
+{
+       if (features & ~VHOST_SCSI_FEATURES)
+               return -EOPNOTSUPP;
+
+       mutex_lock(&vs->dev.mutex);
+       if ((features & (1 << VHOST_F_LOG_ALL)) &&
+           !vhost_log_access_ok(&vs->dev)) {
+               mutex_unlock(&vs->dev.mutex);
+               return -EFAULT;
+       }
+       vs->dev.acked_features = features;
+       smp_wmb();
+       vhost_scsi_flush(vs);
+       mutex_unlock(&vs->dev.mutex);
+       return 0;
+}
+
 static int vhost_scsi_open(struct inode *inode, struct file *f)
 {
        struct vhost_scsi *s;
@@ -939,38 +1033,6 @@ static int vhost_scsi_release(struct inode *inode, struct file *f)
        return 0;
 }
 
-static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index)
-{
-       vhost_poll_flush(&vs->dev.vqs[index].poll);
-}
-
-static void vhost_scsi_flush(struct vhost_scsi *vs)
-{
-       int i;
-
-       for (i = 0; i < VHOST_SCSI_MAX_VQ; i++)
-               vhost_scsi_flush_vq(vs, i);
-       vhost_work_flush(&vs->dev, &vs->vs_completion_work);
-}
-
-static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
-{
-       if (features & ~VHOST_SCSI_FEATURES)
-               return -EOPNOTSUPP;
-
-       mutex_lock(&vs->dev.mutex);
-       if ((features & (1 << VHOST_F_LOG_ALL)) &&
-           !vhost_log_access_ok(&vs->dev)) {
-               mutex_unlock(&vs->dev.mutex);
-               return -EFAULT;
-       }
-       vs->dev.acked_features = features;
-       smp_wmb();
-       vhost_scsi_flush(vs);
-       mutex_unlock(&vs->dev.mutex);
-       return 0;
-}
-
 static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
                                unsigned long arg)
 {
index 4c1546f71d56a2be51785f3bf02ab50437ac94d6..981c1c08c7278274411796139900df434cf5edbd 100644 (file)
@@ -31,26 +31,8 @@ config VIDEO_OUTPUT_CONTROL
          This framework adds support for low-level control of the video 
          output switch.
 
-config DISPLAY_TIMING
-       bool
-
-config VIDEOMODE
-       bool
-
-config OF_DISPLAY_TIMING
-       bool "Enable device tree display timing support"
-       depends on OF
-       select DISPLAY_TIMING
-       help
-         helper to parse display timings from the devicetree
-
-config OF_VIDEOMODE
-       bool "Enable device tree videomode support"
-       depends on OF
-       select VIDEOMODE
-       select OF_DISPLAY_TIMING
-       help
-         helper to get videomodes from the devicetree
+config VIDEOMODE_HELPERS
+       bool
 
 config HDMI
        bool
@@ -212,14 +194,6 @@ config FB_SYS_FOPS
        depends on FB
        default n
 
-config FB_WMT_GE_ROPS
-       tristate
-       depends on FB
-       default n
-       ---help---
-         Include functions for accelerated rectangle filling and area
-         copying using WonderMedia Graphics Engine operations.
-
 config FB_DEFERRED_IO
        bool
        depends on FB
@@ -1797,22 +1771,37 @@ config FB_AU1200
          option au1200fb:panel=<name>.
 
 config FB_VT8500
-       bool "VT8500 LCD Driver"
+       bool "VIA VT8500 framebuffer support"
        depends on (FB = y) && ARM && ARCH_VT8500
-       select FB_WMT_GE_ROPS
+       select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
+       select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
        select FB_SYS_IMAGEBLIT
+       select FB_MODE_HELPERS
+       select VIDEOMODE_HELPERS
        help
          This is the framebuffer driver for VIA VT8500 integrated LCD
          controller.
 
 config FB_WM8505
-       bool "WM8505 frame buffer support"
+       bool "Wondermedia WM8xxx-series frame buffer support"
        depends on (FB = y) && ARM && ARCH_VT8500
-       select FB_WMT_GE_ROPS
+       select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
+       select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
        select FB_SYS_IMAGEBLIT
+       select FB_MODE_HELPERS
+       select VIDEOMODE_HELPERS
+       help
+         This is the framebuffer driver for WonderMedia WM8xxx-series
+         integrated LCD controller. This driver covers the WM8505, WM8650
+         and WM8850 SoCs.
+
+config FB_WMT_GE_ROPS
+       bool "VT8500/WM8xxx accelerated raster ops support"
+       depends on (FB = y) && (FB_VT8500 || FB_WM8505)
+       default n
        help
-         This is the framebuffer driver for WonderMedia WM8505/WM8650
-         integrated LCD controller.
+         This adds support for accelerated raster operations on the
+         VIA VT8500 and Wondermedia 85xx series SoCs.
 
 source "drivers/video/geode/Kconfig"
 
@@ -2277,7 +2266,7 @@ config XEN_FBDEV_FRONTEND
        select FB_SYS_IMAGEBLIT
        select FB_SYS_FOPS
        select FB_DEFERRED_IO
-       select INPUT_XEN_KBDDEV_FRONTEND
+       select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC
        select XEN_XENBUS_FRONTEND
        default y
        help
index 9df387334cb7f8ed341b8728267fae3a5afd4dcc..e414378d6a5199bd5509c587002e03510a378a28 100644 (file)
@@ -171,7 +171,7 @@ obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
 
 #video output switch sysfs driver
 obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
-obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o
-obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o
-obj-$(CONFIG_VIDEOMODE) += videomode.o
-obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o
+obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o
+ifeq ($(CONFIG_OF),y)
+obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o
+endif
index 7fa1bf823729205450d0347a017ef62f9b19cd20..77cb4ffa1fe4f9d04a4b7314e653991b6e88fe57 100644 (file)
@@ -3788,19 +3788,7 @@ static struct platform_driver amifb_driver = {
        },
 };
 
-static int __init amifb_init(void)
-{
-       return platform_driver_probe(&amifb_driver, amifb_probe);
-}
-
-module_init(amifb_init);
-
-static void __exit amifb_exit(void)
-{
-       platform_driver_unregister(&amifb_driver);
-}
-
-module_exit(amifb_exit);
+module_platform_driver_probe(amifb_driver, amifb_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:amiga-video");
index 025428e04c33c7bb99a80f2310b5dfdf8c936c2b..98348ec0b3ce1f9ad342ceb7feadd0a0c6fdc3ba 100644 (file)
@@ -1158,18 +1158,7 @@ static struct platform_driver atmel_lcdfb_driver = {
        },
 };
 
-static int __init atmel_lcdfb_init(void)
-{
-       return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe);
-}
-
-static void __exit atmel_lcdfb_exit(void)
-{
-       platform_driver_unregister(&atmel_lcdfb_driver);
-}
-
-module_init(atmel_lcdfb_init);
-module_exit(atmel_lcdfb_exit);
+module_platform_driver_probe(atmel_lcdfb_driver, atmel_lcdfb_probe);
 
 MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
 MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
index 1a9ac6e1f4b3657101834736ca24c80543a067fb..f5b668e77af32e8b4c7306f64032938da453dd33 100644 (file)
 
 static void auok1900_init(struct auok190xfb_par *par)
 {
+       struct device *dev = par->info->device;
        struct auok190x_board *board = par->board;
        u16 init_param = 0;
 
+       pm_runtime_get_sync(dev);
+
        init_param |= AUOK1900_INIT_TEMP_AVERAGE;
        init_param |= AUOK1900_INIT_ROTATE(par->rotation);
        init_param |= AUOK190X_INIT_INVERSE_WHITE;
@@ -74,6 +77,9 @@ static void auok1900_init(struct auok190xfb_par *par)
 
        /* let the controller finish */
        board->wait_for_rdy(par);
+
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
 }
 
 static void auok1900_update_region(struct auok190xfb_par *par, int mode,
@@ -82,6 +88,7 @@ static void auok1900_update_region(struct auok190xfb_par *par, int mode,
        struct device *dev = par->info->device;
        unsigned char *buf = (unsigned char *)par->info->screen_base;
        int xres = par->info->var.xres;
+       int line_length = par->info->fix.line_length;
        u16 args[4];
 
        pm_runtime_get_sync(dev);
@@ -100,9 +107,9 @@ static void auok1900_update_region(struct auok190xfb_par *par, int mode,
        args[1] = y1 + 1;
        args[2] = xres;
        args[3] = y2 - y1;
-       buf += y1 * xres;
+       buf += y1 * line_length;
        auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args,
-                                    ((y2 - y1) * xres)/2, (u16 *) buf);
+                                    ((y2 - y1) * line_length)/2, (u16 *) buf);
        auok190x_send_command(par, AUOK190X_CMD_DATA_STOP);
 
        par->update_cnt++;
index d1db1653cd88546bb0855786093c367ad3887c37..12b9adcb75c54757155509ed2734ced2a6218c00 100644 (file)
 
 static void auok1901_init(struct auok190xfb_par *par)
 {
+       struct device *dev = par->info->device;
        struct auok190x_board *board = par->board;
        u16 init_param = 0;
 
+       pm_runtime_get_sync(dev);
+
        init_param |= AUOK190X_INIT_INVERSE_WHITE;
        init_param |= AUOK190X_INIT_FORMAT0;
        init_param |= AUOK1901_INIT_RESOLUTION(par->resolution);
@@ -113,6 +116,9 @@ static void auok1901_init(struct auok190xfb_par *par)
 
        /* let the controller finish */
        board->wait_for_rdy(par);
+
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
 }
 
 static void auok1901_update_region(struct auok190xfb_par *par, int mode,
@@ -121,6 +127,7 @@ static void auok1901_update_region(struct auok190xfb_par *par, int mode,
        struct device *dev = par->info->device;
        unsigned char *buf = (unsigned char *)par->info->screen_base;
        int xres = par->info->var.xres;
+       int line_length = par->info->fix.line_length;
        u16 args[5];
 
        pm_runtime_get_sync(dev);
@@ -139,9 +146,9 @@ static void auok1901_update_region(struct auok190xfb_par *par, int mode,
        args[1] = y1 + 1;
        args[2] = xres;
        args[3] = y2 - y1;
-       buf += y1 * xres;
+       buf += y1 * line_length;
        auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4,
-                                           args, ((y2 - y1) * xres)/2,
+                                           args, ((y2 - y1) * line_length)/2,
                                            (u16 *) buf);
        auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP);
 
index 53846cb534d40c35a6debb010c3d12e55a6bcc20..b1f19b266da70d291ffce72e51a275a82f0536fb 100644 (file)
@@ -40,6 +40,14 @@ static struct panel_info panel_table[] = {
                .w = 1024,
                .h = 768,
        },
+       [AUOK190X_RESOLUTION_600_800] = {
+               .w = 600,
+               .h = 800,
+       },
+       [AUOK190X_RESOLUTION_768_1024] = {
+               .w = 768,
+               .h = 1024,
+       },
 };
 
 /*
@@ -60,8 +68,48 @@ static void auok190x_issue_cmd(struct auok190xfb_par *par, u16 data)
        par->board->set_ctl(par, AUOK190X_I80_DC, 1);
 }
 
-static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
-                                u16 *data)
+/**
+ * Conversion of 16bit color to 4bit grayscale
+ * does roughly (0.3 * R + 0.6 G + 0.1 B) / 2
+ */
+static inline int rgb565_to_gray4(u16 data, struct fb_var_screeninfo *var)
+{
+       return ((((data & 0xF800) >> var->red.offset) * 77 +
+                ((data & 0x07E0) >> (var->green.offset + 1)) * 151 +
+                ((data & 0x1F) >> var->blue.offset) * 28) >> 8 >> 1);
+}
+
+static int auok190x_issue_pixels_rgb565(struct auok190xfb_par *par, int size,
+                                       u16 *data)
+{
+       struct fb_var_screeninfo *var = &par->info->var;
+       struct device *dev = par->info->device;
+       int i;
+       u16 tmp;
+
+       if (size & 7) {
+               dev_err(dev, "issue_pixels: size %d must be a multiple of 8\n",
+                       size);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < (size >> 2); i++) {
+               par->board->set_ctl(par, AUOK190X_I80_WR, 0);
+
+               tmp  = (rgb565_to_gray4(data[4*i], var) & 0x000F);
+               tmp |= (rgb565_to_gray4(data[4*i+1], var) << 4) & 0x00F0;
+               tmp |= (rgb565_to_gray4(data[4*i+2], var) << 8) & 0x0F00;
+               tmp |= (rgb565_to_gray4(data[4*i+3], var) << 12) & 0xF000;
+
+               par->board->set_hdb(par, tmp);
+               par->board->set_ctl(par, AUOK190X_I80_WR, 1);
+       }
+
+       return 0;
+}
+
+static int auok190x_issue_pixels_gray8(struct auok190xfb_par *par, int size,
+                                      u16 *data)
 {
        struct device *dev = par->info->device;
        int i;
@@ -91,6 +139,23 @@ static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
        return 0;
 }
 
+static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
+                                u16 *data)
+{
+       struct fb_info *info = par->info;
+       struct device *dev = par->info->device;
+
+       if (info->var.bits_per_pixel == 8 && info->var.grayscale)
+               auok190x_issue_pixels_gray8(par, size, data);
+       else if (info->var.bits_per_pixel == 16)
+               auok190x_issue_pixels_rgb565(par, size, data);
+       else
+               dev_err(dev, "unsupported color mode (bits: %d, gray: %d)\n",
+                       info->var.bits_per_pixel, info->var.grayscale);
+
+       return 0;
+}
+
 static u16 auok190x_read_data(struct auok190xfb_par *par)
 {
        u16 data;
@@ -224,8 +289,8 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
 {
        struct fb_deferred_io *fbdefio = info->fbdefio;
        struct auok190xfb_par *par = info->par;
+       u16 line_length = info->fix.line_length;
        u16 yres = info->var.yres;
-       u16 xres = info->var.xres;
        u16 y1 = 0, h = 0;
        int prev_index = -1;
        struct page *cur;
@@ -254,7 +319,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
        }
 
        /* height increment is fixed per page */
-       h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
+       h_inc = DIV_ROUND_UP(PAGE_SIZE , line_length);
 
        /* calculate number of pages from pixel height */
        threshold = par->consecutive_threshold / h_inc;
@@ -265,7 +330,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
        list_for_each_entry(cur, &fbdefio->pagelist, lru) {
                if (prev_index < 0) {
                        /* just starting so assign first page */
-                       y1 = (cur->index << PAGE_SHIFT) / xres;
+                       y1 = (cur->index << PAGE_SHIFT) / line_length;
                        h = h_inc;
                } else if ((cur->index - prev_index) <= threshold) {
                        /* page is within our threshold for single updates */
@@ -275,7 +340,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
                        par->update_partial(par, y1, y1 + h);
 
                        /* start over with our non consecutive page */
-                       y1 = (cur->index << PAGE_SHIFT) / xres;
+                       y1 = (cur->index << PAGE_SHIFT) / line_length;
                        h = h_inc;
                }
                prev_index = cur->index;
@@ -376,27 +441,127 @@ static void auok190xfb_imageblit(struct fb_info *info,
 static int auok190xfb_check_var(struct fb_var_screeninfo *var,
                                   struct fb_info *info)
 {
-       if (info->var.xres != var->xres || info->var.yres != var->yres ||
-           info->var.xres_virtual != var->xres_virtual ||
-           info->var.yres_virtual != var->yres_virtual) {
-               pr_info("%s: Resolution not supported: X%u x Y%u\n",
-                        __func__, var->xres, var->yres);
+       struct device *dev = info->device;
+       struct auok190xfb_par *par = info->par;
+       struct panel_info *panel = &panel_table[par->resolution];
+       int size;
+
+       /*
+        * Color depth
+        */
+
+       if (var->bits_per_pixel == 8 && var->grayscale == 1) {
+               /*
+                * For 8-bit grayscale, R, G, and B offset are equal.
+                */
+               var->red.length = 8;
+               var->red.offset = 0;
+               var->red.msb_right = 0;
+
+               var->green.length = 8;
+               var->green.offset = 0;
+               var->green.msb_right = 0;
+
+               var->blue.length = 8;
+               var->blue.offset = 0;
+               var->blue.msb_right = 0;
+
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               var->transp.msb_right = 0;
+       } else if (var->bits_per_pixel == 16) {
+               var->red.length = 5;
+               var->red.offset = 11;
+               var->red.msb_right = 0;
+
+               var->green.length = 6;
+               var->green.offset = 5;
+               var->green.msb_right = 0;
+
+               var->blue.length = 5;
+               var->blue.offset = 0;
+               var->blue.msb_right = 0;
+
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               var->transp.msb_right = 0;
+       } else {
+               dev_warn(dev, "unsupported color mode (bits: %d, grayscale: %d)\n",
+                       info->var.bits_per_pixel, info->var.grayscale);
                return -EINVAL;
        }
 
+       /*
+        * Dimensions
+        */
+
+       switch (var->rotate) {
+       case FB_ROTATE_UR:
+       case FB_ROTATE_UD:
+               var->xres = panel->w;
+               var->yres = panel->h;
+               break;
+       case FB_ROTATE_CW:
+       case FB_ROTATE_CCW:
+               var->xres = panel->h;
+               var->yres = panel->w;
+               break;
+       default:
+               dev_dbg(dev, "Invalid rotation request\n");
+               return -EINVAL;
+       }
+
+       var->xres_virtual = var->xres;
+       var->yres_virtual = var->yres;
+
        /*
         *  Memory limit
         */
 
-       if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
-               pr_info("%s: Memory Limit requested yres_virtual = %u\n",
-                        __func__, var->yres_virtual);
+       size = var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8;
+       if (size > info->fix.smem_len) {
+               dev_err(dev, "Memory limit exceeded, requested %dK\n",
+                       size >> 10);
                return -ENOMEM;
        }
 
        return 0;
 }
 
+static int auok190xfb_set_fix(struct fb_info *info)
+{
+       struct fb_fix_screeninfo *fix = &info->fix;
+       struct fb_var_screeninfo *var = &info->var;
+
+       fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+       fix->type = FB_TYPE_PACKED_PIXELS;
+       fix->accel = FB_ACCEL_NONE;
+       fix->visual = (var->grayscale) ? FB_VISUAL_STATIC_PSEUDOCOLOR
+                                      : FB_VISUAL_TRUECOLOR;
+       fix->xpanstep = 0;
+       fix->ypanstep = 0;
+       fix->ywrapstep = 0;
+
+       return 0;
+}
+
+static int auok190xfb_set_par(struct fb_info *info)
+{
+       struct auok190xfb_par *par = info->par;
+
+       par->rotation = info->var.rotate;
+       auok190xfb_set_fix(info);
+
+       /* reinit the controller to honor the rotation */
+       par->init(par);
+
+       /* wait for init to complete */
+       par->board->wait_for_rdy(par);
+
+       return 0;
+}
+
 static struct fb_ops auok190xfb_ops = {
        .owner          = THIS_MODULE,
        .fb_read        = fb_sys_read,
@@ -405,6 +570,7 @@ static struct fb_ops auok190xfb_ops = {
        .fb_copyarea    = auok190xfb_copyarea,
        .fb_imageblit   = auok190xfb_imageblit,
        .fb_check_var   = auok190xfb_check_var,
+       .fb_set_par     = auok190xfb_set_par,
 };
 
 /*
@@ -588,10 +754,16 @@ static int auok190x_power(struct auok190xfb_par *par, bool on)
 
 static void auok190x_recover(struct auok190xfb_par *par)
 {
+       struct device *dev = par->info->device;
+
        auok190x_power(par, 0);
        msleep(100);
        auok190x_power(par, 1);
 
+       /* after powercycling the device, it's always active */
+       pm_runtime_set_active(dev);
+       par->standby = 0;
+
        par->init(par);
 
        /* wait for init to complete */
@@ -875,42 +1047,17 @@ int auok190x_common_probe(struct platform_device *pdev,
        /* initialise fix, var, resolution and rotation */
 
        strlcpy(info->fix.id, init->id, 16);
-       info->fix.type = FB_TYPE_PACKED_PIXELS;
-       info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-       info->fix.xpanstep = 0;
-       info->fix.ypanstep = 0;
-       info->fix.ywrapstep = 0;
-       info->fix.accel = FB_ACCEL_NONE;
-
        info->var.bits_per_pixel = 8;
        info->var.grayscale = 1;
-       info->var.red.length = 8;
-       info->var.green.length = 8;
-       info->var.blue.length = 8;
 
        panel = &panel_table[board->resolution];
 
-       /* if 90 degree rotation, switch width and height */
-       if (board->rotation & 1) {
-               info->var.xres = panel->h;
-               info->var.yres = panel->w;
-               info->var.xres_virtual = panel->h;
-               info->var.yres_virtual = panel->w;
-               info->fix.line_length = panel->h;
-       } else {
-               info->var.xres = panel->w;
-               info->var.yres = panel->h;
-               info->var.xres_virtual = panel->w;
-               info->var.yres_virtual = panel->h;
-               info->fix.line_length = panel->w;
-       }
-
        par->resolution = board->resolution;
-       par->rotation = board->rotation;
+       par->rotation = 0;
 
        /* videomemory handling */
 
-       videomemorysize = roundup((panel->w * panel->h), PAGE_SIZE);
+       videomemorysize = roundup((panel->w * panel->h) * 2, PAGE_SIZE);
        videomemory = vmalloc(videomemorysize);
        if (!videomemory) {
                ret = -ENOMEM;
@@ -924,6 +1071,12 @@ int auok190x_common_probe(struct platform_device *pdev,
        info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
        info->fbops = &auok190xfb_ops;
 
+       ret = auok190xfb_check_var(&info->var, info);
+       if (ret)
+               goto err_defio;
+
+       auok190xfb_set_fix(info);
+
        /* deferred io init */
 
        info->fbdefio = devm_kzalloc(info->device,
index 0c189b32a4c5429f632bb812a784b9a4f8868607..67b77b40aa7f16bbcabe29fd4ad4fc4d1085b443 100644 (file)
@@ -285,36 +285,26 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
 static int controlfb_mmap(struct fb_info *info,
                        struct vm_area_struct *vma)
 {
-       unsigned long off, start;
-       u32 len;
-
-       off = vma->vm_pgoff << PAGE_SHIFT;
-
-       /* frame buffer memory */
-       start = info->fix.smem_start;
-       len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.smem_len);
-       if (off >= len) {
-               /* memory mapped io */
-               off -= len;
-               if (info->var.accel_flags)
-                       return -EINVAL;
-               start = info->fix.mmio_start;
-               len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.mmio_len);
-              vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       } else {
-               /* framebuffer */
-              vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot);
-       }
-       start &= PAGE_MASK;
-       if ((vma->vm_end - vma->vm_start + off) > len)
-                       return -EINVAL;
-       off += start;
-       vma->vm_pgoff = off >> PAGE_SHIFT;
-       if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-           vma->vm_end - vma->vm_start, vma->vm_page_prot))
-               return -EAGAIN;
-
-       return 0;
+       unsigned long mmio_pgoff;
+       unsigned long start;
+       u32 len;
+
+       start = info->fix.smem_start;
+       len = info->fix.smem_len;
+       mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
+       if (vma->vm_pgoff >= mmio_pgoff) {
+               if (info->var.accel_flags)
+                       return -EINVAL;
+               vma->vm_pgoff -= mmio_pgoff;
+               start = info->fix.mmio_start;
+               len = info->fix.mmio_len;
+               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       } else {
+               /* framebuffer */
+               vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot);
+       }
+
+       return vm_iomap_memory(vma, start, len);
 }
 
 static int controlfb_blank(int blank_mode, struct fb_info *info)
index fac7df6d1abacb7df7967a7cf0aadc159281dff0..3dd43ca2b95f1db5c59c0e20acb1525df6a37e3b 100644 (file)
@@ -35,8 +35,6 @@
 
 #include <video/exynos_mipi_dsim.h>
 
-#include <plat/fb.h>
-
 #include "exynos_mipi_dsi_common.h"
 #include "exynos_mipi_dsi_lowlevel.h"
 
index c70cb8926df6e8ee23796f231318e9242f83751a..520fc9bd887b46356f8819ff3c215a674675a93d 100644 (file)
@@ -31,8 +31,6 @@
 #include <video/mipi_display.h>
 #include <video/exynos_mipi_dsim.h>
 
-#include <mach/map.h>
-
 #include "exynos_mipi_dsi_regs.h"
 #include "exynos_mipi_dsi_lowlevel.h"
 #include "exynos_mipi_dsi_common.h"
index 95cb99a1fe2ddfd9e0b01349c652588abddb84ca..15c5abd408dc8c5615af5d15a6e0b28b222441c4 100644 (file)
@@ -26,8 +26,6 @@
 
 #include <video/exynos_mipi_dsim.h>
 
-#include <mach/map.h>
-
 #include "exynos_mipi_dsi_regs.h"
 
 void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim)
index 7d106f1f49069f78a43feb0dd2bdaee3befa43ca..27fc956166fa5693f03321196b54e3a4744e4bbf 100644 (file)
@@ -640,21 +640,9 @@ static int unifb_pan_display(struct fb_var_screeninfo *var,
 int unifb_mmap(struct fb_info *info,
                    struct vm_area_struct *vma)
 {
-       unsigned long size = vma->vm_end - vma->vm_start;
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       unsigned long pos = info->fix.smem_start + offset;
-
-       if (offset + size > info->fix.smem_len)
-               return -EINVAL;
-
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
-       if (io_remap_pfn_range(vma, vma->vm_start, pos >> PAGE_SHIFT, size,
-                               vma->vm_page_prot))
-               return -EAGAIN;
-
-       /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
-       return 0;
+       return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
 }
 
 static struct fb_ops unifb_ops = {
index 7c254084b6a044da4658071a864e9dabbfdd16dc..dcb669eb453299d0c7004e2353ae0e266bd368eb 100644 (file)
@@ -1373,15 +1373,12 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
 {
        struct fb_info *info = file_fb_info(file);
        struct fb_ops *fb;
-       unsigned long off;
+       unsigned long mmio_pgoff;
        unsigned long start;
        u32 len;
 
        if (!info)
                return -ENODEV;
-       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-               return -EINVAL;
-       off = vma->vm_pgoff << PAGE_SHIFT;
        fb = info->fbops;
        if (!fb)
                return -ENODEV;
@@ -1393,32 +1390,29 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
                return res;
        }
 
-       /* frame buffer memory */
+       /*
+        * Ugh. This can be either the frame buffer mapping, or
+        * if pgoff points past it, the mmio mapping.
+        */
        start = info->fix.smem_start;
-       len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
-       if (off >= len) {
-               /* memory mapped io */
-               off -= len;
+       len = info->fix.smem_len;
+       mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
+       if (vma->vm_pgoff >= mmio_pgoff) {
                if (info->var.accel_flags) {
                        mutex_unlock(&info->mm_lock);
                        return -EINVAL;
                }
+
+               vma->vm_pgoff -= mmio_pgoff;
                start = info->fix.mmio_start;
-               len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+               len = info->fix.mmio_len;
        }
        mutex_unlock(&info->mm_lock);
-       start &= PAGE_MASK;
-       if ((vma->vm_end - vma->vm_start + off) > len)
-               return -EINVAL;
-       off += start;
-       vma->vm_pgoff = off >> PAGE_SHIFT;
-       /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by io_remap_pfn_range()*/
+
        vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-       fb_pgprotect(file, vma, off);
-       if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-                            vma->vm_end - vma->vm_start, vma->vm_page_prot))
-               return -EAGAIN;
-       return 0;
+       fb_pgprotect(file, vma, start);
+
+       return vm_iomap_memory(vma, start, len);
 }
 
 static int
index 94ad0f71383c7fa71563332b3ab0fad9276dd2ab..6103fa6fb54f08137f0b36a7ecb54f3e7b0ebf77 100644 (file)
@@ -1376,7 +1376,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
        return err;
 }
 
-#if IS_ENABLED(CONFIG_VIDEOMODE)
+#ifdef CONFIG_VIDEOMODE_HELPERS
 int fb_videomode_from_videomode(const struct videomode *vm,
                                struct fb_videomode *fbmode)
 {
@@ -1398,13 +1398,13 @@ int fb_videomode_from_videomode(const struct videomode *vm,
 
        fbmode->sync = 0;
        fbmode->vmode = 0;
-       if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
+       if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
                fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
-       if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
+       if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
                fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
-       if (vm->data_flags & DISPLAY_FLAGS_INTERLACED)
+       if (vm->flags & DISPLAY_FLAGS_INTERLACED)
                fbmode->vmode |= FB_VMODE_INTERLACED;
-       if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN)
+       if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
                fbmode->vmode |= FB_VMODE_DOUBLE;
        fbmode->flag = 0;
 
@@ -1424,9 +1424,8 @@ int fb_videomode_from_videomode(const struct videomode *vm,
        return 0;
 }
 EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
-#endif
 
-#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+#ifdef CONFIG_OF
 static inline void dump_fb_videomode(const struct fb_videomode *m)
 {
        pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
@@ -1465,7 +1464,8 @@ int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb,
        return 0;
 }
 EXPORT_SYMBOL_GPL(of_get_fb_videomode);
-#endif
+#endif /* CONFIG_OF */
+#endif /* CONFIG_VIDEOMODE_HELPERS */
 
 #else
 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
index 41fbd9453c5fa5611406b25477073174efd0b2d5..6c278056fc60c858209b987f97163b1901f4d61f 100644 (file)
@@ -375,7 +375,10 @@ struct fsl_diu_data {
        struct diu_ad dummy_ad __aligned(8);
        struct diu_ad ad[NUM_AOIS] __aligned(8);
        u8 gamma[256 * 3] __aligned(32);
-       u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
+       /* It's easier to parse the cursor data as little-endian */
+       __le16 cursor[MAX_CURS * MAX_CURS] __aligned(32);
+       /* Blank cursor data -- used to hide the cursor */
+       __le16 blank_cursor[MAX_CURS * MAX_CURS] __aligned(32);
        uint8_t edid_data[EDID_LENGTH];
        bool has_edid;
 } __aligned(32);
@@ -824,7 +827,6 @@ static void update_lcdc(struct fb_info *info)
        /* Program DIU registers */
 
        out_be32(&hw->gamma, DMA_ADDR(data, gamma));
-       out_be32(&hw->cursor, DMA_ADDR(data, cursor));
 
        out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
        out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
@@ -967,6 +969,156 @@ static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel)
        }
 }
 
+/*
+ * Copies a cursor image from user space to the proper place in driver
+ * memory so that the hardware can display the cursor image.
+ *
+ * Cursor data is represented as a sequence of 'width' bits packed into bytes.
+ * That is, the first 8 bits are in the first byte, the second 8 bits in the
+ * second byte, and so on.  Therefore, the each row of the cursor is (width +
+ * 7) / 8 bytes of 'data'
+ *
+ * The DIU only supports cursors up to 32x32 (MAX_CURS).  We reject cursors
+ * larger than this, so we already know that 'width' <= 32.  Therefore, we can
+ * simplify our code by using a 32-bit big-endian integer ("line") to read in
+ * a single line of pixels, and only look at the top 'width' bits of that
+ * integer.
+ *
+ * This could result in an unaligned 32-bit read.  For example, if the cursor
+ * is 24x24, then the first three bytes of 'image' contain the pixel data for
+ * the top line of the cursor.  We do a 32-bit read of 'image', but we look
+ * only at the top 24 bits.  Then we increment 'image' by 3 bytes.  The next
+ * read is unaligned.  The only problem is that we might read past the end of
+ * 'image' by 1-3 bytes, but that should not cause any problems.
+ */
+static void fsl_diu_load_cursor_image(struct fb_info *info,
+       const void *image, uint16_t bg, uint16_t fg,
+       unsigned int width, unsigned int height)
+{
+       struct mfb_info *mfbi = info->par;
+       struct fsl_diu_data *data = mfbi->parent;
+       __le16 *cursor = data->cursor;
+       __le16 _fg = cpu_to_le16(fg);
+       __le16 _bg = cpu_to_le16(bg);
+       unsigned int h, w;
+
+       for (h = 0; h < height; h++) {
+               uint32_t mask = 1 << 31;
+               uint32_t line = be32_to_cpup(image);
+
+               for (w = 0; w < width; w++) {
+                       cursor[w] = (line & mask) ? _fg : _bg;
+                       mask >>= 1;
+               }
+
+               cursor += MAX_CURS;
+               image += DIV_ROUND_UP(width, 8);
+       }
+}
+
+/*
+ * Set a hardware cursor.  The image data for the cursor is passed via the
+ * fb_cursor object.
+ */
+static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+       struct mfb_info *mfbi = info->par;
+       struct fsl_diu_data *data = mfbi->parent;
+       struct diu __iomem *hw = data->diu_reg;
+
+       if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+               return -EINVAL;
+
+       /* The cursor size has changed */
+       if (cursor->set & FB_CUR_SETSIZE) {
+               /*
+                * The DIU cursor is a fixed size, so when we get this
+                * message, instead of resizing the cursor, we just clear
+                * all the image data, in expectation of new data.  However,
+                * in tests this control does not appear to be normally
+                * called.
+                */
+               memset(data->cursor, 0, sizeof(data->cursor));
+       }
+
+       /* The cursor position has changed (cursor->image.dx|dy) */
+       if (cursor->set & FB_CUR_SETPOS) {
+               uint32_t xx, yy;
+
+               yy = (cursor->image.dy - info->var.yoffset) & 0x7ff;
+               xx = (cursor->image.dx - info->var.xoffset) & 0x7ff;
+
+               out_be32(&hw->curs_pos, yy << 16 | xx);
+       }
+
+       /*
+        * FB_CUR_SETIMAGE - the cursor image has changed
+        * FB_CUR_SETCMAP  - the cursor colors has changed
+        * FB_CUR_SETSHAPE - the cursor bitmask has changed
+        */
+       if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+               unsigned int image_size =
+                       DIV_ROUND_UP(cursor->image.width, 8) * cursor->image.height;
+               unsigned int image_words =
+                       DIV_ROUND_UP(image_size, sizeof(uint32_t));
+               unsigned int bg_idx = cursor->image.bg_color;
+               unsigned int fg_idx = cursor->image.fg_color;
+               uint8_t buffer[image_size];
+               uint32_t *image, *source, *mask;
+               uint16_t fg, bg;
+               unsigned int i;
+
+               if (info->state != FBINFO_STATE_RUNNING)
+                       return 0;
+
+               /*
+                * Determine the size of the cursor image data.  Normally,
+                * it's 8x16.
+                */
+               image_size = DIV_ROUND_UP(cursor->image.width, 8) *
+                       cursor->image.height;
+
+               bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
+                    ((info->cmap.green[bg_idx] & 0xf8) << 2) |
+                    ((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
+                    1 << 15;
+
+               fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
+                    ((info->cmap.green[fg_idx] & 0xf8) << 2) |
+                    ((info->cmap.blue[fg_idx] & 0xf8) >> 3) |
+                    1 << 15;
+
+               /* Use 32-bit operations on the data to improve performance */
+               image = (uint32_t *)buffer;
+               source = (uint32_t *)cursor->image.data;
+               mask = (uint32_t *)cursor->mask;
+
+               if (cursor->rop == ROP_XOR)
+                       for (i = 0; i < image_words; i++)
+                               image[i] = source[i] ^ mask[i];
+               else
+                       for (i = 0; i < image_words; i++)
+                               image[i] = source[i] & mask[i];
+
+               fsl_diu_load_cursor_image(info, image, bg, fg,
+                       cursor->image.width, cursor->image.height);
+       };
+
+       /*
+        * Show or hide the cursor.  The cursor data is always stored in the
+        * 'cursor' memory block, and the actual cursor position is always in
+        * the DIU's CURS_POS register.  To hide the cursor, we redirect the
+        * CURSOR register to a blank cursor.  The show the cursor, we
+        * redirect the CURSOR register to the real cursor data.
+        */
+       if (cursor->enable)
+               out_be32(&hw->cursor, DMA_ADDR(data, cursor));
+       else
+               out_be32(&hw->cursor, DMA_ADDR(data, blank_cursor));
+
+       return 0;
+}
+
 /*
  * Using the fb_var_screeninfo in fb_info we set the resolution of this
  * particular framebuffer. This function alters the fb_fix_screeninfo stored
@@ -1312,6 +1464,7 @@ static struct fb_ops fsl_diu_ops = {
        .fb_ioctl = fsl_diu_ioctl,
        .fb_open = fsl_diu_open,
        .fb_release = fsl_diu_release,
+       .fb_cursor = fsl_diu_cursor,
 };
 
 static int install_fb(struct fb_info *info)
index bda5e3941510fa1c415667a873fc684b928a91e8..ceab37020fff17935596ba435f1c30e00ce94204 100644 (file)
@@ -1016,7 +1016,9 @@ static int gbefb_mmap(struct fb_info *info,
        /* check range */
        if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
                return -EINVAL;
-       if (offset + size > gbe_mem_size)
+       if (size > gbe_mem_size)
+               return -EINVAL;
+       if (offset > gbe_mem_size - size)
                return -EINVAL;
 
        /* remap using the fastest write-through mode on architecture */
index 9ed83419038bbdd94da43f0d988732fcaefec188..84de2632857a335086b829597392e2a7e456cc54 100644 (file)
@@ -252,7 +252,5 @@ void mmp_unregister_path(struct mmp_path *path)
 
        kfree(path);
        mutex_unlock(&disp_lock);
-
-       dev_info(path->dev, "de-register %s\n", path->name);
 }
 EXPORT_SYMBOL_GPL(mmp_unregister_path);
index 13ecd9897010f986e04a43afdeeaee5ae2d1909b..56009bc02b02475b525966ee9b8239d4a779b56d 100644 (file)
@@ -79,25 +79,24 @@ static struct display_timing *of_get_display_timing(struct device_node *np)
        ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
        ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
 
-       dt->dmt_flags = 0;
-       dt->data_flags = 0;
+       dt->flags = 0;
        if (!of_property_read_u32(np, "vsync-active", &val))
-               dt->dmt_flags |= val ? VESA_DMT_VSYNC_HIGH :
-                               VESA_DMT_VSYNC_LOW;
+               dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
+                               DISPLAY_FLAGS_VSYNC_LOW;
        if (!of_property_read_u32(np, "hsync-active", &val))
-               dt->dmt_flags |= val ? VESA_DMT_HSYNC_HIGH :
-                               VESA_DMT_HSYNC_LOW;
+               dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
+                               DISPLAY_FLAGS_HSYNC_LOW;
        if (!of_property_read_u32(np, "de-active", &val))
-               dt->data_flags |= val ? DISPLAY_FLAGS_DE_HIGH :
+               dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
                                DISPLAY_FLAGS_DE_LOW;
        if (!of_property_read_u32(np, "pixelclk-active", &val))
-               dt->data_flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
+               dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
                                DISPLAY_FLAGS_PIXDATA_NEGEDGE;
 
        if (of_property_read_bool(np, "interlaced"))
-               dt->data_flags |= DISPLAY_FLAGS_INTERLACED;
+               dt->flags |= DISPLAY_FLAGS_INTERLACED;
        if (of_property_read_bool(np, "doublescan"))
-               dt->data_flags |= DISPLAY_FLAGS_DOUBLESCAN;
+               dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
 
        if (ret) {
                pr_err("%s: error reading timing properties\n",
index 5b8066cd397ff1edcd7b35e63e77c0e7d72e639b..111c2d1911d32ea38e86b11c0af753133ccfab05 100644 (file)
@@ -43,7 +43,7 @@ int of_get_videomode(struct device_node *np, struct videomode *vm,
        if (index == OF_USE_NATIVE_MODE)
                index = disp->native_mode;
 
-       ret = videomode_from_timing(disp, vm, index);
+       ret = videomode_from_timings(disp, vm, index);
        if (ret)
                return ret;
 
index e512581300fc12c74ac31384558d3335ce3946eb..0bc3a936ce2be055617c64718be70da87061dc79 100644 (file)
@@ -39,17 +39,6 @@ config FB_OMAP_LCD_MIPID
          the Mobile Industry Processor Interface DBI-C/DCS
          specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3)
 
-config FB_OMAP_CONSISTENT_DMA_SIZE
-       int "Consistent DMA memory size (MB)"
-       depends on FB_OMAP
-       range 1 14
-       default 2
-       help
-         Increase the DMA consistent memory size according to your video
-         memory needs, for example if you want to use multiple planes.
-         The size must be 2MB aligned.
-         If unsure say 1.
-
 config FB_OMAP_DMA_TUNE
         bool "Set DMA SDRAM access priority high"
         depends on FB_OMAP
index ca585ef37f2528d36d0534200a911db95b07baff..717f13a9335174f502a7fbc7599fcd060ae9d583 100644 (file)
@@ -1101,41 +1101,25 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
        struct omapfb_info *ofbi = FB2OFB(fbi);
        struct fb_fix_screeninfo *fix = &fbi->fix;
        struct omapfb2_mem_region *rg;
-       unsigned long off;
        unsigned long start;
        u32 len;
-       int r = -EINVAL;
-
-       if (vma->vm_end - vma->vm_start == 0)
-               return 0;
-       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-               return -EINVAL;
-       off = vma->vm_pgoff << PAGE_SHIFT;
+       int r;
 
        rg = omapfb_get_mem_region(ofbi->region);
 
        start = omapfb_get_region_paddr(ofbi);
        len = fix->smem_len;
-       if (off >= len)
-               goto error;
-       if ((vma->vm_end - vma->vm_start + off) > len)
-               goto error;
-
-       off += start;
 
-       DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
+       DBG("user mmap region start %lx, len %d, off %lx\n", start, len,
+                       vma->vm_pgoff << PAGE_SHIFT);
 
-       vma->vm_pgoff = off >> PAGE_SHIFT;
-       /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
        vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
        vma->vm_ops = &mmap_user_ops;
        vma->vm_private_data = rg;
-       if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-                              vma->vm_end - vma->vm_start,
-                              vma->vm_page_prot)) {
-               r = -EAGAIN;
+
+       r = vm_iomap_memory(vma, start, len);
+       if (r)
                goto error;
-       }
 
        /* vm_ops.open won't be called for mmap itself. */
        atomic_inc(&rg->map_count);
@@ -1144,7 +1128,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 
        return 0;
 
- error:
+error:
        omapfb_put_mem_region(ofbi->region);
 
        return r;
index 10560efeb35ac24ae87d5a862b526c63b90e2375..5261229c79afbef8afa4e80f24936f6dbb6e6f4e 100644 (file)
@@ -397,18 +397,7 @@ static struct platform_driver vrfb_driver = {
        .remove         = __exit_p(vrfb_remove),
 };
 
-static int __init vrfb_init(void)
-{
-       return platform_driver_probe(&vrfb_driver, &vrfb_probe);
-}
-
-static void __exit vrfb_exit(void)
-{
-       platform_driver_unregister(&vrfb_driver);
-}
-
-module_init(vrfb_init);
-module_exit(vrfb_exit);
+module_platform_driver_probe(vrfb_driver, vrfb_probe);
 
 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
 MODULE_DESCRIPTION("OMAP VRFB");
index 920c27bf3947edeb05540bcce3ac11b8c2bddbf4..d9f08c653d6275ebce317cd8679d92cafdbac5bc 100644 (file)
@@ -705,21 +705,15 @@ static int ps3fb_pan_display(struct fb_var_screeninfo *var,
 
 static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
-       unsigned long size, offset;
+       int r;
 
-       size = vma->vm_end - vma->vm_start;
-       offset = vma->vm_pgoff << PAGE_SHIFT;
-       if (offset + size > info->fix.smem_len)
-               return -EINVAL;
-
-       offset += info->fix.smem_start;
-       if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
-                           size, vma->vm_page_prot))
-               return -EAGAIN;
+       r = vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
 
        dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n",
-               offset, vma->vm_start);
-       return 0;
+               info->fix.smem_start + vma->vm_pgoff << PAGE_SHIFT,
+               vma->vm_start);
+
+       return r;
 }
 
     /*
index 968a62571df733e04fd1073c64cb30f6ad04807c..2e7991c7ca088dca9688dd7a8ec13d715c25435f 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
+#include <linux/platform_data/video_s3c.h>
 
 #include <video/samsung_fimd.h>
-#include <mach/map.h>
-#include <plat/fb.h>
 
 /* This driver will export a number of framebuffer interfaces depending
  * on the configuration passed in via the platform data. Each fb instance
index cfbde5e85cbf9a77495e09f1be14fc4c90e1101f..f34c858642e8713440f64cfd7ea9df6f40ec4bae 100644 (file)
@@ -556,7 +556,7 @@ static int sa1100fb_mmap(struct fb_info *info,
                         struct vm_area_struct *vma)
 {
        struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
-       unsigned long start, len, off = vma->vm_pgoff << PAGE_SHIFT;
+       unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
 
        if (off < info->fix.smem_len) {
                vma->vm_pgoff += 1; /* skip over the palette */
@@ -564,19 +564,9 @@ static int sa1100fb_mmap(struct fb_info *info,
                                             fbi->map_dma, fbi->map_size);
        }
 
-       start = info->fix.mmio_start;
-       len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
-
-       if ((vma->vm_end - vma->vm_start + off) > len)
-               return -EINVAL;
-
-       off += start & PAGE_MASK;
-       vma->vm_pgoff = off >> PAGE_SHIFT;
-       vma->vm_flags |= VM_IO;
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-                                  vma->vm_end - vma->vm_start,
-                                  vma->vm_page_prot);
+
+       return vm_iomap_memory(vma, info->fix.mmio_start, info->fix.mmio_len);
 }
 
 static struct fb_ops sa1100fb_ops = {
index 2331fadc272bee53d265f1338c9bcbe648e3e685..b2a8912f6435ac504e4b09361c12dbe8b7d01bc6 100644 (file)
@@ -705,23 +705,17 @@ static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
 static int sgivwfb_mmap(struct fb_info *info,
                        struct vm_area_struct *vma)
 {
-       unsigned long size = vma->vm_end - vma->vm_start;
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       int r;
 
-       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-               return -EINVAL;
-       if (offset + size > sgivwfb_mem_size)
-               return -EINVAL;
-       offset += sgivwfb_mem_phys;
        pgprot_val(vma->vm_page_prot) =
-           pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
-       vma->vm_flags |= VM_IO;
-       if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
-                                               size, vma->vm_page_prot))
-               return -EAGAIN;
+               pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
+
+       r = vm_iomap_memory(vma, sgivwfb_mem_phys, sgivwfb_mem_size);
+
        printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
               offset, vma->vm_start);
-       return 0;
+
+       return r;
 }
 
 int __init sgivwfb_setup(char *options)
index 701b461cf8a953b602c676bd50d1e164267deb98..6cad53075e99321ae07696bab203088df1b5bc6e 100644 (file)
@@ -581,17 +581,7 @@ static struct platform_driver sh_mipi_driver = {
        },
 };
 
-static int __init sh_mipi_init(void)
-{
-       return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe);
-}
-module_init(sh_mipi_init);
-
-static void __exit sh_mipi_exit(void)
-{
-       platform_driver_unregister(&sh_mipi_driver);
-}
-module_exit(sh_mipi_exit);
+module_platform_driver_probe(sh_mipi_driver, sh_mipi_probe);
 
 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
 MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
index 930e550e752ac5712b99dc4909de57d0ccd7fafd..bfe4728480fd9fb7909d1845dd50b3b753390a53 100644 (file)
@@ -1445,17 +1445,7 @@ static struct platform_driver sh_hdmi_driver = {
        },
 };
 
-static int __init sh_hdmi_init(void)
-{
-       return platform_driver_probe(&sh_hdmi_driver, sh_hdmi_probe);
-}
-module_init(sh_hdmi_init);
-
-static void __exit sh_hdmi_exit(void)
-{
-       platform_driver_unregister(&sh_hdmi_driver);
-}
-module_exit(sh_hdmi_exit);
+module_platform_driver_probe(sh_hdmi_driver, sh_hdmi_probe);
 
 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
 MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver");
index 63203acef812211cb17788454116fcbe77debdd7..0264704a52be3d9e02b23178e489b2e567ec4c56 100644 (file)
@@ -858,6 +858,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
        tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16)
            | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7);
        lcdc_write_chan(ch, LDHAJR, tmp);
+       lcdc_write_chan_mirror(ch, LDHAJR, tmp);
 }
 
 static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
index 97bd6620c36494d993b0d77877a2531be80250c3..b2b33fc1ac3faa9953cab079bc094e1f04041646 100644 (file)
@@ -782,7 +782,11 @@ static int ufx_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
        unsigned long page, pos;
 
-       if (offset + size > info->fix.smem_len)
+       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+               return -EINVAL;
+       if (size > info->fix.smem_len)
+               return -EINVAL;
+       if (offset > info->fix.smem_len - size)
                return -EINVAL;
 
        pos = (unsigned long)info->fix.smem_start + offset;
index 86d449ea31699db3c7e7c5f1a7bfc1a41c2b5d83..ec03e726c94008791481bfade233e5b384bb2ddb 100644 (file)
@@ -324,7 +324,11 @@ static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
        unsigned long page, pos;
 
-       if (offset + size > info->fix.smem_len)
+       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+               return -EINVAL;
+       if (size > info->fix.smem_len)
+               return -EINVAL;
+       if (offset > info->fix.smem_len - size)
                return -EINVAL;
 
        pos = (unsigned long)info->fix.smem_start + offset;
index b75db01864883e5fea61f63cc95e3df35e749ea2..d4284458377e80103d230524d573e10e63b2ac14 100644 (file)
@@ -1973,7 +1973,8 @@ static int uvesafb_init(void)
                        err = -ENOMEM;
 
                if (err) {
-                       platform_device_put(uvesafb_device);
+                       if (uvesafb_device)
+                               platform_device_put(uvesafb_device);
                        platform_driver_unregister(&uvesafb_driver);
                        cn_del_callback(&uvesafb_cn_id);
                        return err;
index 0aa516fc59cde498343bedf801b0d07c022b28e1..09a136633f355673e935cf68be459d3521aa1ae9 100644 (file)
@@ -1003,24 +1003,18 @@ static int vmlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 static int vmlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
        struct vml_info *vinfo = container_of(info, struct vml_info, info);
-       unsigned long size = vma->vm_end - vma->vm_start;
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
        int ret;
 
-       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-               return -EINVAL;
-       if (offset + size > vinfo->vram_contig_size)
-               return -EINVAL;
        ret = vmlfb_vram_offset(vinfo, offset);
        if (ret)
                return -EINVAL;
-       offset += vinfo->vram_start;
+
        pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
        pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
-       if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
-                                               size, vma->vm_page_prot))
-               return -EAGAIN;
-       return 0;
+
+       return vm_iomap_memory(vma, vinfo->vram_start,
+                       vinfo->vram_contig_size);
 }
 
 static int vmlfb_sync(struct fb_info *info)
index 8bc1f9398945a2c99b9e45286064499d4dfd88fe..ee5985efa15c83c64d7e22718c22c594e0338f0e 100644 (file)
@@ -420,9 +420,12 @@ static int vfb_mmap(struct fb_info *info,
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
        unsigned long page, pos;
 
-       if (offset + size > info->fix.smem_len) {
+       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+               return -EINVAL;
+       if (size > info->fix.smem_len)
+               return -EINVAL;
+       if (offset > info->fix.smem_len - size)
                return -EINVAL;
-       }
 
        pos = (unsigned long)info->fix.smem_start + offset;
 
index 21c47a202afa54c583c9a42bc4ac2f3bea751647..df375c96c5d323a71767ea8794f8695ff9fbad1c 100644 (file)
 #include <video/display_timing.h>
 #include <video/videomode.h>
 
-int videomode_from_timing(const struct display_timings *disp,
+void videomode_from_timing(const struct display_timing *dt,
+                         struct videomode *vm)
+{
+       vm->pixelclock = dt->pixelclock.typ;
+       vm->hactive = dt->hactive.typ;
+       vm->hfront_porch = dt->hfront_porch.typ;
+       vm->hback_porch = dt->hback_porch.typ;
+       vm->hsync_len = dt->hsync_len.typ;
+
+       vm->vactive = dt->vactive.typ;
+       vm->vfront_porch = dt->vfront_porch.typ;
+       vm->vback_porch = dt->vback_porch.typ;
+       vm->vsync_len = dt->vsync_len.typ;
+
+       vm->flags = dt->flags;
+}
+EXPORT_SYMBOL_GPL(videomode_from_timing);
+
+int videomode_from_timings(const struct display_timings *disp,
                          struct videomode *vm, unsigned int index)
 {
        struct display_timing *dt;
@@ -20,20 +38,8 @@ int videomode_from_timing(const struct display_timings *disp,
        if (!dt)
                return -EINVAL;
 
-       vm->pixelclock = display_timing_get_value(&dt->pixelclock, TE_TYP);
-       vm->hactive = display_timing_get_value(&dt->hactive, TE_TYP);
-       vm->hfront_porch = display_timing_get_value(&dt->hfront_porch, TE_TYP);
-       vm->hback_porch = display_timing_get_value(&dt->hback_porch, TE_TYP);
-       vm->hsync_len = display_timing_get_value(&dt->hsync_len, TE_TYP);
-
-       vm->vactive = display_timing_get_value(&dt->vactive, TE_TYP);
-       vm->vfront_porch = display_timing_get_value(&dt->vfront_porch, TE_TYP);
-       vm->vback_porch = display_timing_get_value(&dt->vback_porch, TE_TYP);
-       vm->vsync_len = display_timing_get_value(&dt->vsync_len, TE_TYP);
-
-       vm->dmt_flags = dt->dmt_flags;
-       vm->data_flags = dt->data_flags;
+       videomode_from_timing(dt, vm);
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(videomode_from_timing);
+EXPORT_SYMBOL_GPL(videomode_from_timings);
index aa2579c2364a53ea07573d019605620184591daf..9547e1831e0310da3ed9be93c4f3d291f9062458 100644 (file)
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/wait.h>
-
-#include <linux/platform_data/video-vt8500lcdfb.h>
+#include <video/of_display_timing.h>
 
 #include "vt8500lcdfb.h"
 #include "wmt_ge_rops.h"
@@ -277,11 +276,11 @@ static int vt8500lcd_probe(struct platform_device *pdev)
 {
        struct vt8500lcd_info *fbi;
        struct resource *res;
+       struct display_timings *disp_timing;
        void *addr;
        int irq, ret;
 
        struct fb_videomode     of_mode;
-       struct device_node      *np;
        u32                     bpp;
        dma_addr_t fb_mem_phys;
        unsigned long fb_mem_len;
@@ -346,32 +345,18 @@ static int vt8500lcd_probe(struct platform_device *pdev)
                goto failed_free_res;
        }
 
-       np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0);
-       if (!np) {
-               pr_err("%s: No display description in Device Tree\n", __func__);
-               ret = -EINVAL;
-               goto failed_free_res;
-       }
+       disp_timing = of_get_display_timings(pdev->dev.of_node);
+       if (!disp_timing)
+               return -EINVAL;
 
-       /*
-        * This code is copied from Sascha Hauer's of_videomode helper
-        * and can be replaced with a call to the helper once mainlined
-        */
-       ret = 0;
-       ret |= of_property_read_u32(np, "hactive", &of_mode.xres);
-       ret |= of_property_read_u32(np, "vactive", &of_mode.yres);
-       ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin);
-       ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin);
-       ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len);
-       ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin);
-       ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin);
-       ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len);
-       ret |= of_property_read_u32(np, "bpp", &bpp);
-       if (ret) {
-               pr_err("%s: Unable to read display properties\n", __func__);
-               goto failed_free_res;
-       }
-       of_mode.vmode = FB_VMODE_NONINTERLACED;
+       ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode,
+                                                       OF_USE_NATIVE_MODE);
+       if (ret)
+               return ret;
+
+       ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
+       if (ret)
+               return ret;
 
        /* try allocating the framebuffer */
        fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
index 4dd0580f96fd65c32f5c717c5ffdf332626b2a48..01f9ace068e20e6de2979fb8740a454b699ef73c 100644 (file)
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/fb.h>
+#include <linux/errno.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/wait.h>
+#include <linux/kernel.h>
+#include <linux/memblock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <linux/memblock.h>
-
-#include <linux/platform_data/video-vt8500lcdfb.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <video/of_display_timing.h>
 
 #include "wm8505fb_regs.h"
 #include "wmt_ge_rops.h"
@@ -263,26 +263,22 @@ static struct fb_ops wm8505fb_ops = {
 static int wm8505fb_probe(struct platform_device *pdev)
 {
        struct wm8505fb_info    *fbi;
-       struct resource         *res;
+       struct resource *res;
+       struct display_timings *disp_timing;
        void                    *addr;
        int ret;
 
-       struct fb_videomode     of_mode;
-       struct device_node      *np;
+       struct fb_videomode     mode;
        u32                     bpp;
        dma_addr_t fb_mem_phys;
        unsigned long fb_mem_len;
        void *fb_mem_virt;
 
-       ret = -ENOMEM;
-       fbi = NULL;
-
        fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) +
                        sizeof(u32) * 16, GFP_KERNEL);
        if (!fbi) {
                dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
-               ret = -ENOMEM;
-               goto failed;
+               return -ENOMEM;
        }
 
        strcpy(fbi->fb.fix.id, DRIVER_NAME);
@@ -308,54 +304,23 @@ static int wm8505fb_probe(struct platform_device *pdev)
        fbi->fb.pseudo_palette  = addr;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "no I/O memory resource defined\n");
-               ret = -ENODEV;
-               goto failed_fbi;
-       }
+       fbi->regbase = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(fbi->regbase))
+               return PTR_ERR(fbi->regbase);
 
-       res = request_mem_region(res->start, resource_size(res), DRIVER_NAME);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to request I/O memory\n");
-               ret = -EBUSY;
-               goto failed_fbi;
-       }
-
-       fbi->regbase = ioremap(res->start, resource_size(res));
-       if (fbi->regbase == NULL) {
-               dev_err(&pdev->dev, "failed to map I/O memory\n");
-               ret = -EBUSY;
-               goto failed_free_res;
-       }
+       disp_timing = of_get_display_timings(pdev->dev.of_node);
+       if (!disp_timing)
+               return -EINVAL;
 
-       np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0);
-       if (!np) {
-               pr_err("%s: No display description in Device Tree\n", __func__);
-               ret = -EINVAL;
-               goto failed_free_res;
-       }
+       ret = of_get_fb_videomode(pdev->dev.of_node, &mode, OF_USE_NATIVE_MODE);
+       if (ret)
+               return ret;
 
-       /*
-        * This code is copied from Sascha Hauer's of_videomode helper
-        * and can be replaced with a call to the helper once mainlined
-        */
-       ret = 0;
-       ret |= of_property_read_u32(np, "hactive", &of_mode.xres);
-       ret |= of_property_read_u32(np, "vactive", &of_mode.yres);
-       ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin);
-       ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin);
-       ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len);
-       ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin);
-       ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin);
-       ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len);
-       ret |= of_property_read_u32(np, "bpp", &bpp);
-       if (ret) {
-               pr_err("%s: Unable to read display properties\n", __func__);
-               goto failed_free_res;
-       }
+       ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
+       if (ret)
+               return ret;
 
-       of_mode.vmode = FB_VMODE_NONINTERLACED;
-       fb_videomode_to_var(&fbi->fb.var, &of_mode);
+       fb_videomode_to_var(&fbi->fb.var, &mode);
 
        fbi->fb.var.nonstd              = 0;
        fbi->fb.var.activate            = FB_ACTIVATE_NOW;
@@ -364,16 +329,16 @@ static int wm8505fb_probe(struct platform_device *pdev)
        fbi->fb.var.width               = -1;
 
        /* try allocating the framebuffer */
-       fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
-       fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
+       fb_mem_len = mode.xres * mode.yres * 2 * (bpp / 8);
+       fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
                                GFP_KERNEL);
        if (!fb_mem_virt) {
                pr_err("%s: Failed to allocate framebuffer\n", __func__);
                return -ENOMEM;
-       };
+       }
 
-       fbi->fb.var.xres_virtual        = of_mode.xres;
-       fbi->fb.var.yres_virtual        = of_mode.yres * 2;
+       fbi->fb.var.xres_virtual        = mode.xres;
+       fbi->fb.var.yres_virtual        = mode.yres * 2;
        fbi->fb.var.bits_per_pixel      = bpp;
 
        fbi->fb.fix.smem_start          = fb_mem_phys;
@@ -381,28 +346,29 @@ static int wm8505fb_probe(struct platform_device *pdev)
        fbi->fb.screen_base             = fb_mem_virt;
        fbi->fb.screen_size             = fb_mem_len;
 
+       fbi->contrast = 0x10;
+       ret = wm8505fb_set_par(&fbi->fb);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to set parameters\n");
+               return ret;
+       }
+
        if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
                dev_err(&pdev->dev, "Failed to allocate color map\n");
-               ret = -ENOMEM;
-               goto failed_free_io;
+               return -ENOMEM;
        }
 
        wm8505fb_init_hw(&fbi->fb);
 
-       fbi->contrast = 0x80;
-       ret = wm8505fb_set_par(&fbi->fb);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to set parameters\n");
-               goto failed_free_cmap;
-       }
-
        platform_set_drvdata(pdev, fbi);
 
        ret = register_framebuffer(&fbi->fb);
        if (ret < 0) {
                dev_err(&pdev->dev,
                        "Failed to register framebuffer device: %d\n", ret);
-               goto failed_free_cmap;
+               if (fbi->fb.cmap.len)
+                       fb_dealloc_cmap(&fbi->fb.cmap);
+               return ret;
        }
 
        ret = device_create_file(&pdev->dev, &dev_attr_contrast);
@@ -416,25 +382,11 @@ static int wm8505fb_probe(struct platform_device *pdev)
               fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
 
        return 0;
-
-failed_free_cmap:
-       if (fbi->fb.cmap.len)
-               fb_dealloc_cmap(&fbi->fb.cmap);
-failed_free_io:
-       iounmap(fbi->regbase);
-failed_free_res:
-       release_mem_region(res->start, resource_size(res));
-failed_fbi:
-       platform_set_drvdata(pdev, NULL);
-       kfree(fbi);
-failed:
-       return ret;
 }
 
 static int wm8505fb_remove(struct platform_device *pdev)
 {
        struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
-       struct resource *res;
 
        device_remove_file(&pdev->dev, &dev_attr_contrast);
 
@@ -445,13 +397,6 @@ static int wm8505fb_remove(struct platform_device *pdev)
        if (fbi->fb.cmap.len)
                fb_dealloc_cmap(&fbi->fb.cmap);
 
-       iounmap(fbi->regbase);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
-       kfree(fbi);
-
        return 0;
 }
 
index 87380751a4437d85d537c2f7dcc4f1d47a5deae6..f73ec6377a46cde2f19151c54b9d3743900d2d86 100644 (file)
@@ -1,5 +1,28 @@
+#ifdef CONFIG_FB_WMT_GE_ROPS
+
 extern void wmt_ge_fillrect(struct fb_info *info,
                            const struct fb_fillrect *rect);
 extern void wmt_ge_copyarea(struct fb_info *info,
                            const struct fb_copyarea *area);
 extern int wmt_ge_sync(struct fb_info *info);
+
+#else
+
+static inline int wmt_ge_sync(struct fb_info *p)
+{
+       return 0;
+}
+
+static inline void wmt_ge_fillrect(struct fb_info *p,
+                                   const struct fb_fillrect *rect)
+{
+       sys_fillrect(p, rect);
+}
+
+static inline void wmt_ge_copyarea(struct fb_info *p,
+                                    const struct fb_copyarea *area)
+{
+       sys_copyarea(p, area);
+}
+
+#endif
index 9fcc70c11ceae14b78052dbab2b4eaafdee553db..e89fc313397233bf80a7d210d8b0db2a36492314 100644 (file)
@@ -117,7 +117,7 @@ config ARM_SP805_WATCHDOG
 
 config AT91RM9200_WATCHDOG
        tristate "AT91RM9200 watchdog"
-       depends on ARCH_AT91
+       depends on ARCH_AT91RM9200
        help
          Watchdog timer embedded into AT91RM9200 chips. This will reboot your
          system when the timeout is reached.
index aa85881d17b23f7ff6425be0140b6aed0c63c942..d8cc8127f19c18f9b6a4ea9f937015363b912bd8 100644 (file)
@@ -85,8 +85,7 @@ enum xen_irq_type {
  * event channel - irq->event channel mapping
  * cpu - cpu this event channel is bound to
  * index - type-specific information:
- *    PIRQ - vector, with MSB being "needs EIO", or physical IRQ of the HVM
- *           guest, or GSI (real passthrough IRQ) of the device.
+ *    PIRQ - physical IRQ, GSI, flags, and owner domain
  *    VIRQ - virq number
  *    IPI - IPI vector
  *    EVTCHN -
@@ -105,7 +104,6 @@ struct irq_info {
                struct {
                        unsigned short pirq;
                        unsigned short gsi;
-                       unsigned char vector;
                        unsigned char flags;
                        uint16_t domid;
                } pirq;
@@ -211,7 +209,6 @@ static void xen_irq_info_pirq_init(unsigned irq,
                                   unsigned short evtchn,
                                   unsigned short pirq,
                                   unsigned short gsi,
-                                  unsigned short vector,
                                   uint16_t domid,
                                   unsigned char flags)
 {
@@ -221,7 +218,6 @@ static void xen_irq_info_pirq_init(unsigned irq,
 
        info->u.pirq.pirq = pirq;
        info->u.pirq.gsi = gsi;
-       info->u.pirq.vector = vector;
        info->u.pirq.domid = domid;
        info->u.pirq.flags = flags;
 }
@@ -519,6 +515,9 @@ static void xen_free_irq(unsigned irq)
 {
        struct irq_info *info = irq_get_handler_data(irq);
 
+       if (WARN_ON(!info))
+               return;
+
        list_del(&info->list);
 
        irq_set_handler_data(irq, NULL);
@@ -714,7 +713,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
                goto out;
        }
 
-       xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, DOMID_SELF,
+       xen_irq_info_pirq_init(irq, 0, pirq, gsi, DOMID_SELF,
                               shareable ? PIRQ_SHAREABLE : 0);
 
        pirq_query_unmask(irq);
@@ -762,8 +761,7 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc)
 }
 
 int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
-                            int pirq, int vector, const char *name,
-                            domid_t domid)
+                            int pirq, const char *name, domid_t domid)
 {
        int irq, ret;
 
@@ -776,7 +774,7 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
        irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq,
                        name);
 
-       xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, domid, 0);
+       xen_irq_info_pirq_init(irq, 0, pirq, 0, domid, 0);
        ret = irq_set_msi_desc(irq, msidesc);
        if (ret < 0)
                goto error_irq;
@@ -1008,6 +1006,9 @@ static void unbind_from_irq(unsigned int irq)
        int evtchn = evtchn_from_irq(irq);
        struct irq_info *info = irq_get_handler_data(irq);
 
+       if (WARN_ON(!info))
+               return;
+
        mutex_lock(&irq_mapping_update_lock);
 
        if (info->refcnt > 0) {
@@ -1135,6 +1136,10 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
 
 void unbind_from_irqhandler(unsigned int irq, void *dev_id)
 {
+       struct irq_info *info = irq_get_handler_data(irq);
+
+       if (WARN_ON(!info))
+               return;
        free_irq(irq, dev_id);
        unbind_from_irq(irq);
 }
@@ -1316,7 +1321,7 @@ static void __xen_evtchn_do_upcall(void)
 {
        int start_word_idx, start_bit_idx;
        int word_idx, bit_idx;
-       int i;
+       int i, irq;
        int cpu = get_cpu();
        struct shared_info *s = HYPERVISOR_shared_info;
        struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
@@ -1324,6 +1329,8 @@ static void __xen_evtchn_do_upcall(void)
 
        do {
                xen_ulong_t pending_words;
+               xen_ulong_t pending_bits;
+               struct irq_desc *desc;
 
                vcpu_info->evtchn_upcall_pending = 0;
 
@@ -1335,6 +1342,17 @@ static void __xen_evtchn_do_upcall(void)
                 * selector flag. xchg_xen_ulong must contain an
                 * appropriate barrier.
                 */
+               if ((irq = per_cpu(virq_to_irq, cpu)[VIRQ_TIMER]) != -1) {
+                       int evtchn = evtchn_from_irq(irq);
+                       word_idx = evtchn / BITS_PER_LONG;
+                       pending_bits = evtchn % BITS_PER_LONG;
+                       if (active_evtchns(cpu, s, word_idx) & (1ULL << pending_bits)) {
+                               desc = irq_to_desc(irq);
+                               if (desc)
+                                       generic_handle_irq_desc(irq, desc);
+                       }
+               }
+
                pending_words = xchg_xen_ulong(&vcpu_info->evtchn_pending_sel, 0);
 
                start_word_idx = __this_cpu_read(current_word_idx);
@@ -1343,7 +1361,6 @@ static void __xen_evtchn_do_upcall(void)
                word_idx = start_word_idx;
 
                for (i = 0; pending_words != 0; i++) {
-                       xen_ulong_t pending_bits;
                        xen_ulong_t words;
 
                        words = MASK_LSBS(pending_words, word_idx);
@@ -1372,8 +1389,7 @@ static void __xen_evtchn_do_upcall(void)
 
                        do {
                                xen_ulong_t bits;
-                               int port, irq;
-                               struct irq_desc *desc;
+                               int port;
 
                                bits = MASK_LSBS(pending_bits, bit_idx);
 
@@ -1446,6 +1462,9 @@ void rebind_evtchn_irq(int evtchn, int irq)
 {
        struct irq_info *info = info_for_irq(irq);
 
+       if (WARN_ON(!info))
+               return;
+
        /* Make sure the irq is masked, since the new event channel
           will also be masked. */
        disable_irq(irq);
@@ -1719,7 +1738,12 @@ void xen_poll_irq(int irq)
 int xen_test_irq_shared(int irq)
 {
        struct irq_info *info = info_for_irq(irq);
-       struct physdev_irq_status_query irq_status = { .irq = info->u.pirq.pirq };
+       struct physdev_irq_status_query irq_status;
+
+       if (WARN_ON(!info))
+               return -ENOENT;
+
+       irq_status.irq = info->u.pirq.pirq;
 
        if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
                return 0;
index 90e34ac7e522dfcf2c5af269639f5f877d95ac3b..8abd7d57903742c54538819fa70fdfa3d0c36f95 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/syscore_ops.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/processor.h>
@@ -51,9 +52,9 @@ static DEFINE_MUTEX(acpi_ids_mutex);
 /* Which ACPI ID we have processed from 'struct acpi_processor'. */
 static unsigned long *acpi_ids_done;
 /* Which ACPI ID exist in the SSDT/DSDT processor definitions. */
-static unsigned long __initdata *acpi_id_present;
+static unsigned long *acpi_id_present;
 /* And if there is an _CST definition (or a PBLK) for the ACPI IDs */
-static unsigned long __initdata *acpi_id_cst_present;
+static unsigned long *acpi_id_cst_present;
 
 static int push_cxx_to_hypervisor(struct acpi_processor *_pr)
 {
@@ -329,7 +330,7 @@ static unsigned int __init get_max_acpi_id(void)
  * for_each_[present|online]_cpu macros which are banded to the virtual
  * CPU amount.
  */
-static acpi_status __init
+static acpi_status
 read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
        u32 acpi_id;
@@ -384,12 +385,16 @@ read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
 
        return AE_OK;
 }
-static int __init check_acpi_ids(struct acpi_processor *pr_backup)
+static int check_acpi_ids(struct acpi_processor *pr_backup)
 {
 
        if (!pr_backup)
                return -ENODEV;
 
+       if (acpi_id_present && acpi_id_cst_present)
+               /* OK, done this once .. skip to uploading */
+               goto upload;
+
        /* All online CPUs have been processed at this stage. Now verify
         * whether in fact "online CPUs" == physical CPUs.
         */
@@ -408,6 +413,7 @@ static int __init check_acpi_ids(struct acpi_processor *pr_backup)
                            read_acpi_id, NULL, NULL, NULL);
        acpi_get_devices("ACPI0007", read_acpi_id, NULL, NULL);
 
+upload:
        if (!bitmap_equal(acpi_id_present, acpi_ids_done, nr_acpi_bits)) {
                unsigned int i;
                for_each_set_bit(i, acpi_id_present, nr_acpi_bits) {
@@ -417,10 +423,7 @@ static int __init check_acpi_ids(struct acpi_processor *pr_backup)
                        (void)upload_pm_data(pr_backup);
                }
        }
-       kfree(acpi_id_present);
-       acpi_id_present = NULL;
-       kfree(acpi_id_cst_present);
-       acpi_id_cst_present = NULL;
+
        return 0;
 }
 static int __init check_prereq(void)
@@ -467,9 +470,46 @@ static void free_acpi_perf_data(void)
        free_percpu(acpi_perf_data);
 }
 
-static int __init xen_acpi_processor_init(void)
+static int xen_upload_processor_pm_data(void)
 {
        struct acpi_processor *pr_backup = NULL;
+       unsigned int i;
+       int rc = 0;
+
+       pr_info(DRV_NAME "Uploading Xen processor PM info\n");
+
+       for_each_possible_cpu(i) {
+               struct acpi_processor *_pr;
+               _pr = per_cpu(processors, i /* APIC ID */);
+               if (!_pr)
+                       continue;
+
+               if (!pr_backup) {
+                       pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
+                       if (pr_backup)
+                               memcpy(pr_backup, _pr, sizeof(struct acpi_processor));
+               }
+               (void)upload_pm_data(_pr);
+       }
+
+       rc = check_acpi_ids(pr_backup);
+       kfree(pr_backup);
+
+       return rc;
+}
+
+static void xen_acpi_processor_resume(void)
+{
+       bitmap_zero(acpi_ids_done, nr_acpi_bits);
+       xen_upload_processor_pm_data();
+}
+
+static struct syscore_ops xap_syscore_ops = {
+       .resume = xen_acpi_processor_resume,
+};
+
+static int __init xen_acpi_processor_init(void)
+{
        unsigned int i;
        int rc = check_prereq();
 
@@ -514,27 +554,12 @@ static int __init xen_acpi_processor_init(void)
                        goto err_out;
        }
 
-       for_each_possible_cpu(i) {
-               struct acpi_processor *_pr;
-               _pr = per_cpu(processors, i /* APIC ID */);
-               if (!_pr)
-                       continue;
-
-               if (!pr_backup) {
-                       pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
-                       if (pr_backup)
-                               memcpy(pr_backup, _pr, sizeof(struct acpi_processor));
-               }
-               (void)upload_pm_data(_pr);
-       }
-       rc = check_acpi_ids(pr_backup);
-
-       kfree(pr_backup);
-       pr_backup = NULL;
-
+       rc = xen_upload_processor_pm_data();
        if (rc)
                goto err_unregister;
 
+       register_syscore_ops(&xap_syscore_ops);
+
        return 0;
 err_unregister:
        for_each_possible_cpu(i) {
@@ -552,7 +577,10 @@ static void __exit xen_acpi_processor_exit(void)
 {
        int i;
 
+       unregister_syscore_ops(&xap_syscore_ops);
        kfree(acpi_ids_done);
+       kfree(acpi_id_present);
+       kfree(acpi_id_cst_present);
        for_each_possible_cpu(i) {
                struct acpi_processor_performance *perf;
                perf = per_cpu_ptr(acpi_perf_data, i);
index 5d8ee1319b5c1878c5b82f82bb150dfece7b2cf8..cbb09ce9730ac0494dc43fbef5d7d6f2ddd05b0b 100644 (file)
@@ -82,7 +82,7 @@ fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \
 fw-shipped-$(CONFIG_SCSI_QLOGIC_1280) += qlogic/1040.bin qlogic/1280.bin \
                                         qlogic/12160.bin
 fw-shipped-$(CONFIG_SCSI_QLOGICPTI) += qlogic/isp1000.bin
-fw-shipped-$(CONFIG_INFINIBAND_QIB) += intel/sd7220.fw
+fw-shipped-$(CONFIG_INFINIBAND_QIB) += qlogic/sd7220.fw
 fw-shipped-$(CONFIG_SND_KORG1212) += korg/k1212.dsp
 fw-shipped-$(CONFIG_SND_MAESTRO3) += ess/maestro3_assp_kernel.fw \
                                     ess/maestro3_assp_minisrc.fw
diff --git a/firmware/intel/sd7220.fw.ihex b/firmware/intel/sd7220.fw.ihex
deleted file mode 100644 (file)
index a336363..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-:10000000020A29020A87E5E630E6047F0180027FC2
-:1000100000E5E230E4047E0180027E00EE5F6008CD
-:1000200053F9F7E4F5FE80087F0A121731120EA289
-:1000300075FC08E4F5FDE5E720E70343F908220035
-:1000400001201100042000755101E4F552F553F52B
-:1000500052F57E7F04020438C2360552E552D3942D
-:100060000C4005755201D23690070C7407F0A3744A
-:10007000FFF0E4F50CA3F0900714F0A3F0750B204B
-:10008000F509E4F508E508D39430400302040412AE
-:100090000006150BE50870047F0180027F00E5096A
-:1000A00070047E0180027E00EE5F6005121871D23E
-:1000B0003553E1F7E5084509FFE50B25E025E02488
-:1000C00083F582E43407F583EFF085E220E552D32F
-:1000D0009401400D1219F3E054A064407003020330
-:1000E000FB53F9F8909470E4F0E0F510AF09121E9C
-:1000F000B3AF08EF4408F582758380E0F529EF443B
-:1001000007121A3CF5225440D39400401EE52954AE
-:10011000F070211219F3E04480F0E52254306508B4
-:1001200070091219F3E054BFF080091219F37440FA
-:10013000F00203FB121A127583AE74FFF0AF087E53
-:1001400000EF4407F582E0FDE50B25E025E0248182
-:10015000F582E43407F583EDF090070EE004F0EF4C
-:100160004407F582758398E0F528121A23400C1293
-:1001700019F3E04401121A320203F6AF087E00744C
-:1001800080CDEFCD8D82F583E030E00A1219F3E0E7
-:100190004420F00203FB1219F3E054DFF0EE44AE0A
-:1001A000121A4330E4030203FB749E121A0520E086
-:1001B000030203FB8F828E83E020E0030203FB1225
-:1001C00019F3E04410F0E5E320E708E508121A3AD5
-:1001D0004404F0AF087E00EF121A3A20E2341219FC
-:1001E000F3E04408F0E5E430E6047D0180027D00A0
-:1001F000E57EC3940450047C0180027C00EC4D60D9
-:1002000005C2350203FBEE44D2121A434440F00209
-:1002100003FB1219F3E054F7F0121A127583D2E0BF
-:1002200054BFF0900714E004F0E57E7003757E0182
-:10023000AF087E00121A2340121219F3E044011293
-:1002400019F2E05402121A320203FB1219F3E044CD
-:10025000021219F2E054FEF0C235EE448A8F82F5A4
-:1002600083E0F517548F4440F07490FCE508440790
-:10027000FDF5828C83E0543F900702F0E054C08D7E
-:10028000828C83F07492121A05900703121A197463
-:1002900082121A05900704121A1974B4121A0590E2
-:1002A0000705121A197494FEE5084406121A0AF595
-:1002B0001030E004D2378002C237E510547F8F82BD
-:1002C0008E83F0304430121A035480D394004004DB
-:1002D000D2398002C2398F828E83E04480F0121AB4
-:1002E000035440D394004004D23A8002C23A8F8231
-:1002F0008E83E04440F07492FEE5084406121A0A28
-:1003000030E704D2388002C2388F828E83E0547F77
-:10031000F0121E46E4F50A20030280033043031264
-:1003200019952002028003304203120C8F303006F0
-:10033000121995120C8F120D471219F3E054FBF0AD
-:10034000E50AC39401404643E1081219F3E044046E
-:10035000F0E5E420E72A121A127583D2E05408D39C
-:10036000940040047F0180027F00E50AC3940140AD
-:10037000047E0180027E00EF5E6005121DD78017AB
-:10038000121A127583D2E04408F00203FB121A120B
-:100390007583D2E054F7F0121E467F0812173174AD
-:1003A0008EFE121A128E83E0F51054FEF0E5104412
-:1003B00001FFE508FDED4407F582EFF0E51054FE7E
-:1003C000FFED4407F582EF121A11758386E04410A1
-:1003D000121A11E04410F01219F3E054FD4401FF29
-:1003E0001219F3EF121A3230320CE5084408F58284
-:1003F0007583827405F0AF0B1218D774102508F5B9
-:10040000080200850509E509D3940750030200821C
-:10041000E57ED3940040047F0180027F00E57EC327
-:1004200094FA50047E0180027E00EE5F6002057E39
-:1004300030350B43E1017F0912173102005853E1B7
-:10044000FE0200588E6A8F6B8C6C8D6D756E017517
-:100450006F01757001E4F573F574F57590072FF071
-:10046000F53CF53EF546F547F53DF53FF56FE56F93
-:10047000700FE56B456A12072A758380743AF08025
-:100480000912072A758380741AF0E4F56EC3743F6D
-:10049000956EFF120865758382EFF0121A4D1208EF
-:1004A000C6E533F01208FA1208B140E1E56F700BAF
-:1004B00012072A7583807436F0800912072A758323
-:1004C000807416F0756E0112072A7583B4E56EF01C
-:1004D000121A4D743F256EF582E43400F583E5333E
-:1004E000F074BF256EF582E434001208B140D8E400
-:1004F000F570F546F547F56E1208FAF583E0FE1241
-:1005000008C6E07C002400FFEC3EFEAD3BD3EF9D2F
-:10051000EE9C50047B0180027B00E57070047A0140
-:1005200080027A00EB5A6006856E46757001D3EF43
-:100530009DEE9C50047F0180027F00E570B40104B1
-:100540007E0180027E00EF5E6003856E47056EE5EA
-:100550006E647F70A3E5466005E547B47E0385467B
-:1005600047E56F7008854676854777800EC3747FB0
-:100570009546F578C3747F9547F579E56F7037E553
-:10058000466547700C757301757401F53CF53D8047
-:1005900035E4F54EC3E5479546F53CC313F57125A3
-:1005A00046F572C3943F4005E4F53D8040C3743F77
-:1005B0009572F53D8037E5466547700F7573017597
-:1005C0007501F53EF53F754E018022E4F54EC3E519
-:1005D000479546F53EC313F5712546F572D3943F12
-:1005E0005005E4F53F8006E57224C1F53F056FE54F
-:1005F0006FC39402500302046EE56D456C70028077
-:1006000004E574457590072FF07F01E53E6004E531
-:100610003C7014E4F53CF53DF53EF53F1208D27010
-:1006200004F00206A4807AE53CC3953E4007E53C11
-:10063000953EFF8006C3E53E953CFFE576D3957970
-:10064000400585767A800385797AE577C395785079
-:100650000585777B800385787BE57BD3957A403071
-:10066000E57B957AF53CF53EC3E57B957A900719D5
-:10067000F0E53CC313F571257AF572C3943F40054C
-:10068000E4F53D801FC3743F9572F53DF53F80143E
-:10069000E4F53CF53E900719F01208D27003F080A3
-:1006A000037401F01208657583D0E0540FFEAD3C71
-:1006B00070027E07BE0F027E80EEFBEFD39B74803C
-:1006C000F898401FE4F53CF53E1208D27003F08024
-:1006D000127401F0E508FBEB4407F5827583D2E064
-:1006E0004410F0E508FBEB4409F58275839EEDF0BC
-:1006F000EB4407F5827583CAEDF01208657583CC6B
-:10070000EFF022E5084407F5827583BCE054F0F071
-:10071000E5084407F5827583BEE054F0F0E508442F
-:1007200007F5827583C0E054F0F0E5084407F582D0
-:1007300022F0900728E0FEA3E0F5828E8322854216
-:100740004285414185404074C02FF58274023EF5D8
-:1007500083E542F074E02FF58274023EF58322E5D2
-:100760004229FDE433FCE53CC39DEC6480F87480D1
-:100770009822F583E0900722541FFDE0FAA3E0F5EC
-:10078000828A83EDF022900722E0FCA3E0F5828CC0
-:100790008322900724FFED4407CFF0A3EFF02285DA
-:1007A0003838853939853A3A74C02FF58274023E5B
-:1007B000F58322900726FFED4407CFF0A3EFF02248
-:1007C000F074A02FF58274023EF5832274C02511C7
-:1007D000F582E43401F5832274002511F582E434B6
-:1007E00002F5832274602511F582E43403F5832237
-:1007F00074802511F582E43403F5832274E0251119
-:10080000F582E43403F5832274402511F582E43443
-:1008100006F5832274802FF58274023EF58322AFA1
-:10082000087E00EF4407F58222F583E5824407F550
-:1008300082E540F02274402511F582E43402F5830C
-:100840002274C02511F582E43403F5832274002557
-:1008500011F582E43406F5832274202511F582E433
-:100860003406F58322E508FDED4407F58222E541D3
-:10087000F0E56564014564227E00FB7A00FD7C00A2
-:100880002274202511F582E434022274A02511F58A
-:1008900082E4340322853E42853F418F4022853CDD
-:1008A00042853D418F402275453F900720E4F0A3EB
-:1008B00022F583E532F0056EE56EC3944022F0E543
-:1008C000084406F582227400256EF582E43400F5B2
-:1008D0008322E56D456C90072F22E4F9E53CD39522
-:1008E0003E2274802EF582E43402F583E02274A067
-:1008F0002EF582E43402F583E0227480256EF582C1
-:10090000E43400222542FDE433FC22854242854145
-:100910004185404022ED4C60030209E5EF4E7037FF
-:10092000900726120789E0FD1207CCEDF09007280A
-:10093000120789E0FD1207D8EDF0120786E0541F78
-:10094000FD120881F583EDF0900724120789E05429
-:100950001FFD120835EDF0EF64044E703790072646
-:10096000120789E0FD1207E4EDF0900728120789CD
-:10097000E0FD1207F0EDF0120786E0541FFD1208AB
-:100980008BF583EDF0900724120789E0541FFD12C8
-:100990000841EDF0EF64014E70047D0180027D009E
-:1009A000EF64024E70047F0180027F00EF4D60789B
-:1009B000900726120735E0FF1207FCEF120731E01F
-:1009C000FF120808EFF0900722120735E0541FFFCE
-:1009D00012084DEFF0900724120735E0541FFF1264
-:1009E0000859EFF0221207CCE4F01207D8E4F01215
-:1009F0000881F583E4F01208357414F01207E4E47A
-:100A0000F01207F0E4F012088BF583E4F0120841CD
-:100A10007414F01207FCE4F0120808E4F012084D18
-:100A2000E4F01208597414F02253F9F775FC10E43D
-:100A3000F5FD75FE30F5FFE5E720E70343F908E52E
-:100A4000E620E70B78FFE4F6D8FD53E6FE80097850
-:100A500008E4F6D8FD53E6FE758180E4F5A8D2A837
-:100A6000C2A9D2AFE5E220E50520E602800343E11A
-:100A700002E5E220E00E9000007F007E08E4F0A393
-:100A8000DFFCDEFA020ADB43FA01C0E0C0F0C083FB
-:100A9000C082C0D0121CE7D0D0D082D083D0F0D09A
-:100AA000E053FAFE32021B55E493A3F8E493A3F655
-:100AB00008DFF98029E493A3F85407240CC8C33352
-:100AC000C4540F4420C8834004F456800146F6DF26
-:100AD000E4800B010204081020408090003FE47E77
-:100AE000019360C1A3FF543F30E509541FFEE49316
-:100AF000A360010ECF54C025E060AD40B880FE8CED
-:100B0000648D658A668B67E4F569EF4E7003021D9C
-:100B100055E4F568E5674566703212072A758390DB
-:100B2000E41207297583C2E41207297583C4E4120D
-:100B30000870702912072A758392E41207297583B9
-:100B4000C6E41207297583C8E4F0801190072612C5
-:100B50000735E41208707005120732E4F0121D55D3
-:100B6000121EBFE5674566703312072A758390E54C
-:100B7000411207297583C2E5411207297583C41202
-:100B8000086E702912072A758392E54012072975AD
-:100B900083C6E5401207297583C8800E9007261288
-:100BA000073512086E7006120732E540F0AF697E15
-:100BB00000AD67AC6612044412072A7583CAE0D3FD
-:100BC0009400500C0568E568C394055003020B14AB
-:100BD000228C608D611208DA7420400D2FF582742A
-:100BE000033EF583E53EF0800B2FF58274033EF55E
-:100BF00083E53CF0E53CD3953E403CE561456070C3
-:100C000010E9120904E53E120768403B120895807E
-:100C100018E53EC39538401D853E38E53E600585A4
-:100C20003F3980038539398F3A120814E53E12079F
-:100C3000C0E53FF0228043E5614560701912075F0F
-:100C4000400512089E802712090B120814E5421273
-:100C500007C0E541F022E53CC39538401D853C388E
-:100C6000E53C6005853D3980038539398F3A1208A6
-:100C700014E53C1207C0E53DF02285383885393946
-:100C8000853A3A120814E5381207C0E539F0227F98
-:100C900006121731121D23120E04120E33E0440AFD
-:100CA000F0748EFE120E04120E0BEFF0E52830E504
-:100CB00003D38001C3400575142080037514081206
-:100CC0000E0475838AE514F0B4FF05751280800662
-:100CD000E514C313F512E4F516F57F121936121355
-:100CE000A3E50AC3940150090516E516C394144000
-:100CF000EAE5E420E728120E047583D2E05408D315
-:100D0000940040047F0180027F00E50AC394014003
-:100D1000047E0180027E00EF5E6003121DD7E57F36
-:100D2000C394114014120E047583D2E04480F0E5A0
-:100D3000E420E70F121DD7800A120E047583D2E05B
-:100D4000547FF0121D2322748A850882F583E517EB
-:100D5000F0120E3AE4F0900702E0120E177583903D
-:100D6000EFF07492FEE5084407FFF5828E83E054AD
-:100D7000C0FD900703E0543F4D8F828E83F09007B3
-:100D800004E0120E17758382EFF0900705E0FFED87
-:100D90004407F5827583B4EF120E03758380E05427
-:100DA000BFF030370A120E91758394E04480F03022
-:100DB000380A120E91758392E04480F0E52830E401
-:100DC0001A20390A120E04758388E0547FF0203A05
-:100DD0000A120E04758388E054BFF0748CFE120E64
-:100DE000048E83E0540F120E03758386E054BFF027
-:100DF000E5084406120DFD75838AE4F022F582753C
-:100E00008382E4F0E5084407F582228E83E0F51042
-:100E100054FEF0E5104401FFE508FDED4407F582BE
-:100E200022E515C45407FFE508FDED4408F5827579
-:100E3000838222758380E04440F0E5084408F5820F
-:100E400075838A22E51625E025E024AFF582E43497
-:100E50001AF583E493F50D2243E11043E18053E159
-:100E6000FD85E11022E51625E025E024B2F582E4B7
-:100E7000341AF583E49322855582855483E515F071
-:100E800022E5E25420D3940022E5E25440D39400BA
-:100E900022E5084406F58222FDE508FBEB4407F550
-:100EA000822253F9F775FE3022EF4E70261207CCDE
-:100EB000E0FD90072612077B1207D8E0FD90072877
-:100EC00012077B120881120772120835E09007247E
-:100ED000120778EF64044E70291207E4E0FD9007D2
-:100EE0002612077B1207F0E0FD90072812077B12FD
-:100EF000088B120772120841E0541FFD900724125C
-:100F0000077BEF64014E70047D0180027D00EF6479
-:100F1000024E70047F0180027F00EF4D60351207A2
-:100F2000FCE0FF900726120789EFF0120808E0FFA7
-:100F3000900728120789EFF012084DE0541FFF12A6
-:100F40000786EFF0120859E0541FFF90072412079C
-:100F500089EFF022E4F553120E8140047F018002F4
-:100F60007F00120E8940047E0180027E00EE4F70E9
-:100F700003020FF685E11043E10253E10F85E11012
-:100F8000E4F551E5E3543FF552120E89401DAD5290
-:100F9000AF51121118EF600885E11043E140800B5A
-:100FA00053E1BF120E5812000680FBE5E3543FF5F3
-:100FB00051E5E4543FF552120E81401DAD52AF5140
-:100FC000121118EF600885E11043E120800B53E116
-:100FD000DF120E5812000680FB120E8140047F01C2
-:100FE00080027F00120E8940047E0180027E00EEA6
-:100FF0004F6003120E5B22120E21EFF012109122AD
-:1010000002110002104002109000000000000000D9
-:1010100001200120E4F5571216BD121644E4121007
-:10102000561214B7900726120735E4120731E4F080
-:101030001210561214B7900726120735E541120711
-:1010400031E540F0AF577E00AD567C00120444AF4E
-:10105000567E000211EEFF900720A3E0FDE4F55656
-:10106000F540FEFCAB56FA1211517F0F7D18E4F5E6
-:1010700056F540FEFCAB56FA121541AF567E0012F3
-:101080001AFFE4FFF5567D1FF540FEFCAB56FA2231
-:1010900022E4F555E508FD74A0F556ED4407F55733
-:1010A000E52830E503D38001C340057F28EF8004A5
-:1010B0007F14EFC313F554E4F9120E1875838EE014
-:1010C000F510CEEFCEEED394004026E51054FE127C
-:1010D0000E9875838EEDF0E5104401FDEB4407F5A5
-:1010E00082EDF0855782855683E030E301091E804A
-:1010F000D4C234E9C395544002D2342202000622FD
-:10110000303011901000E493F510901010E493F536
-:101110001012109012115022E4FCC3ED9FFAEFF56B
-:101120008375820079FFE493CC6CCCA3D9F8DAF60E
-:10113000E5E230E4028CE5ED24FFFFEF7582FFF578
-:1011400083E4936C70037F01227F00222211000050
-:10115000228E588F598C5A8D5B8A5C8B5D755E012F
-:10116000E4F55FF560F56212072A7583D0E0FFC4ED
-:10117000540FF561121EA585595ED3E55E955BE5BA
-:101180005A12076B504B1207037583BCE0455E1281
-:1011900007297583BEE0455E1207297583C0E045C7
-:1011A0005EF0AF5FE560120878120AFFAF627E0062
-:1011B000AD5DAC5C120444E561AF5E7E00B4030536
-:1011C000121E218007AD5DAC5C121317055E021183
-:1011D0007A1207037583BCE045401207297583BE68
-:1011E000E045401207297583C0E04540F0228E5843
-:1011F0008F59755A017901755B01E4FB12072A7555
-:1012000083AEE0541AFF120865E0C4135407FEEFE2
-:10121000700CEE6535700790072FE0B4010DAF3507
-:101220007E00120EA9CFEBCF021E60E55964024585
-:101230005870047F0180027F00E559455870047E94
-:101240000180027E00EE4F602385414985404BE5D9
-:10125000594558702CAF5AFECDE9CDFCAB59AA5870
-:10126000120AFFAF5B7E00121E608015AF5B7E002E
-:10127000121E60900726120735E549120731E54B2B
-:10128000F0E4FDAF35FEFC120915228C648D651269
-:1012900008DA403CE56545647010120904C3E53E78
-:1012A000120769403B1208958018E53EC395384007
-:1012B0001D853E38E53E6005853F39800385393917
-:1012C0008F3A1207A8E53E120753E53FF022803B14
-:1012D000E5654564701112075F400512089E801F86
-:1012E00012073EE541F022E53CC39538401D853CA0
-:1012F00038E53C6005853D3980038539398F3A12E0
-:1013000007A8E53C120753E53DF02212079FE53898
-:10131000120753E539F0228C638D641208DA403CE1
-:10132000E56445637010120904C3E53E1207694085
-:101330003B1208958018E53EC39538401D853E3820
-:10134000E53E6005853F3980038539398F3A1207BC
-:10135000A8E53E120753E53FF022803BE564456374
-:10136000701112075F400512089E801F12073EE5AC
-:1013700041F022E53CC39538401D853C38E53C6092
-:1013800005853D3980038539398F3A1207A8E53C38
-:10139000120753E53DF02212079FE538120753E587
-:1013A00039F022E50DFEE5088E544405F555751516
-:1013B0000FF582120E7A1217A320310575150380DE
-:1013C0000375150BE50AC39401503812142020311F
-:1013D0000605150515800415151515E50AC39401B4
-:1013E0005021121420203104051580021515E50A3C
-:1013F000C39401500E120E771217A3203105051564
-:10140000120E77E515B408047F0180027F00E51510
-:10141000B407047E0180027E00EE4F6002057F2249
-:10142000855582855483E515F01217A32212072AE9
-:101430007583AE74FF120729E0541AF534E0C41323
-:101440005407F53524FE602424FE603C24047063B8
-:1014500075312DE508FD74B612079274BC90072211
-:1014600012079574901207B37492803C75313AE577
-:1014700008FD74BA12079274C09007221207B6745E
-:10148000C41207B374C88020753135E508FD74B8FF
-:1014900012079274BEFFED4407900722CFF0A3EF2E
-:1014A000F074C21207B374C6FFED4407A3CFF0A3D4
-:1014B000EFF022753401228E588F598C5A8D5B8A39
-:1014C0005C8B5D755E01E4F55F121EA585595ED3E8
-:1014D000E55E955BE55A12076B5057E55D455C701C
-:1014E0003012072A758392E55E1207297583C6E5D7
-:1014F0005E1207297583C8E55E120729758390E59A
-:101500005E1207297583C2E55E1207297583C480C0
-:1015100003120732E55EF0AF5F7E00AD5DAC5C129A
-:101520000444AF5E7E00AD5DAC5C120BD1055E0283
-:1015300014CFAB5DAA5CAD5BAC5AAF59AE58021B81
-:10154000FB8C5C8D5D8A5E8B5F756001E4F561F5F7
-:1015500062F563121EA58F60D3E560955DE55C12B0
-:10156000076B5061E55F455E702712072A7583B6E9
-:10157000E5601207297583B8E5601207297583BAFB
-:10158000E560F0AF617E00E56212087A120AFF8022
-:1015900019900724120735E56012072975838EE438
-:1015A0001207297401120729E4F0AF637E00AD5FD2
-:1015B000AC5E120444AF607E00AD5FAC5E12128B75
-:1015C00005600215582290114DE49390072EF012F9
-:1015D000081F7583AEE0541AF5347067EF4407F5C1
-:1015E000827583CEE0FF1313135407F536540FD3DF
-:1015F0009400400612142D121BA9E536540F24FE48
-:10160000600C14600C146019240370378010021EE3
-:1016100091121E9112072A7583CEE054EFF0021D3D
-:10162000AE121014E4F555121D850555E555C39409
-:101630000540F412072A7583CEE054C7120729E04B
-:101640004408F022E4F558F559AF08EF4407F58255
-:101650007583D0E0FDC4540FF55AEF4407F5827549
-:1016600083807401F0120821758382E545F0EF4410
-:1016700007F58275838A74FFF0121A4D12072A75D6
-:1016800083BCE054EF1207297583BEE054EF1207C4
-:10169000297583C0E054EF1207297583BCE044101C
-:1016A0001207297583BEE044101207297583C0E034
-:1016B0004410F0AF58E559120878020AFFE4F558D3
-:1016C0007D01F559AF35FEFC12091512072A758305
-:1016D000B674101207297583B87410120729758320
-:1016E000BA74101207297583BC7410120729758308
-:1016F000BE74101207297583C074101207297583F0
-:1017000090E41207297583C2E41207297583C4E4A3
-:10171000120729758392E41207297583C6E412071C
-:10172000297583C8E4F0AF58FEE55912087A020A19
-:10173000FFE5E230E46CE5E754C064407064E5091D
-:10174000C45430FEE50825E025E054C04EFEEF54B9
-:101750003F4EFDE52BAE2A7802C333CE33CED8F907
-:10176000F5828E83EDF0E52BAE2A7802C333CE33BB
-:10177000CED8F9FFF5828E83A3E5FEF08F828E83AB
-:10178000A3A3E5FDF08F828E83A3A3A3E5FCF0C3A2
-:10179000E52B94FAE52A94005008052BE52B7002FE
-:1017A000052A22E4FFE4F558F556F5577482FC1239
-:1017B0000E048C83E0F510547FF0E5104480120E87
-:1017C00098EDF07E0A120E047583A0E020E026DE7C
-:1017D000F40557E55770020556E5142401FDE4337E
-:1017E000FCD3E5579DE5569C40D9E50A942050026C
-:1017F000050A43E108C231120E047583A6E05512B2
-:1018000065127003D23122C23122900726E0FAA37A
-:10181000E0F5828A83E0F541E539C395414026E54C
-:10182000399541C39FEE12076B40047C0180027C16
-:1018300000E541643F60047B0180027B00EC5B605B
-:101840002905418028C3E5419539C39FEE12076BF6
-:1018500040047F0180027F00E54160047E01800238
-:101860007E00EF5E600415418003853941853A4072
-:1018700022E5E230E460E5E130E25BE50970047FF7
-:101880000180027F00E50870047E0180027E00EE88
-:101890005F604353F9F8E5E230E43BE5E130E22EE6
-:1018A00043FA0253FAFBE4F510909470E510F0E56A
-:1018B000E130E2E7909470E06510600343FA0405BC
-:1018C00010909470E510F070E612000680E153FA73
-:1018D000FD53FAFB80C0228F54120006E5E130E090
-:1018E000047F0180027F00E57ED3940540047E01E1
-:1018F00080027E00EE4F603D855411E5E220E1322A
-:1019000074CE121A0530E7047D0180027D008F82BB
-:101910008E83E030E6047F0180027F00EF5D70156A
-:101920001215C674CE121A0530E607E04480F04363
-:10193000F98012187122120E44E51625E025E024E4
-:10194000B0F582E4341AF583E493F50FE51625E04B
-:1019500025E024B1F582E4341AF583E493F50E1200
-:101960000E65F510E50F54F0120E1775838CEFF02D
-:10197000E50F30E00C120E04758386E04440F080E1
-:101980000A120E04758386E054BFF0120E9175831F
-:1019900082E50EF0227F05121731120E04120E336B
-:1019A0007402F0748EFE120E04120E0BEFF0751519
-:1019B00070120FF72034057515108003751550123D
-:1019C0000FF72034047410800274F02515F51512F9
-:1019D0000E21EFF0121091203417E5156430600CE1
-:1019E00074102515F515B48003E4F515120E21EFDA
-:1019F000F022F0E50B25E025E02482F582E43407AF
-:101A0000F583227488FEE5084407FFF5828E83E0A3
-:101A100022F0E5084407F58222F0E054C08F828E60
-:101A200083F022EF4407F582758386E05410D39447
-:101A30000022F0900715E004F0224406F582758339
-:101A40009EE022FEEF4407F5828E83E022E49007B9
-:101A50002AF0A3F012072A758382E0547F12072927
-:101A6000E04480F01210FC12081F7583A0E020E013
-:101A70001A90072BE004F0700690072AE004F0901B
-:101A8000072AE0B410E1A3E0B400DCEE44A6FCEFCA
-:101A90004407F5828C83E0F532EE44A8FEEF44075C
-:101AA000F5828E83E0F5332201201100042000909E
-:101AB00000200F9200210F9400220F9600230F9810
-:101AC00000240F9A00250F9C00260F9E00270FA0D0
-:101AD000012001A2012101A4012201A6012301A8E4
-:101AE000012401AA012501AC012601AE012701B0A4
-:101AF000012801B400280FB640280FB8612801CB97
-:101B0000EFCBCAEECA7F01E4FDEB4A7024E508F58D
-:101B10008274B6120829E508F58274B8120829E51E
-:101B200008F58274BA1208297E007C00120AFF8030
-:101B300012900726120735E541F090072412073569
-:101B4000E540F012072A75838EE41207297401120A
-:101B50000729E4F022E4F526F52753E1FEF52A757E
-:101B60002B01F5087F0112173130301C901AA9E4BF
-:101B700093F510901FF9E493F510900041E493F56C
-:101B800010901ECAE493F5107F02121731120F5401
-:101B90007F03121731120006E5E230E70912100048
-:101BA00030300312110002004712081F7583D0E085
-:101BB000C4540FFD7543017544FF1208AA7404F064
-:101BC000753B01ED14600C14600B14600F2403705E
-:101BD0000B800980001208A704F080061208A77481
-:101BE00004F0EE4482FEEF4407F5828E83E5451251
-:101BF00008BE758382E531F002114C8E608F611250
-:101C00001EA5E4FFCEEDCEEED39561E56012076B25
-:101C1000403974202EF582E43403F583E07003FF2D
-:101C200080261208E2FDC39F401ECFEDCFEB4A7025
-:101C30000B8D421208EEF5418E40800C1208E2F541
-:101C4000381208EEF5398E3A1E80BC22755801E52F
-:101C500035700C1207CCE0F54A1207D8E0F54CE5D8
-:101C600035B4040C1207E4E0F54A1207F0E0F54C35
-:101C7000E535B401047F0180027F00E535B402043C
-:101C80007E0180027E00EE4F600C1207FCE0F54AF8
-:101C9000120808E0F54C85414985404B22755B01EF
-:101CA000900724120735E0541FFFD3940250048F8D
-:101CB000588005EF24FEF558EFC394184005755978
-:101CC000188004EF04F55985435AAF587E00AD598A
-:101CD0007C00AB5B7A00121541AF5A7E0012180AE5
-:101CE000AF5B7E00021AFFE5E230E70E121003C27E
-:101CF000303030031210FF203328E5E730E70512BB
-:101D00000EA2800DE5FEC394205006120EA243F9E8
-:101D100008E5F230E70353F97FE5F15470D39400FE
-:101D200050D822120E04758380E4F0E508440712AF
-:101D30000DFD758384120E02758386120E02758363
-:101D40008CE054F3120E0375838E120E0275839489
-:101D5000E054FBF02212072A75838EE412072974DF
-:101D600001120729E41208BE75838CE04420120892
-:101D7000BEE054DFF07484850882F583E0547FF080
-:101D8000E04480F022755601E4FDF557AF35FEFCC6
-:101D9000120915121C9D121E7A121C4CAF577E00A0
-:101DA000AD567C00120444AF567E000211EE75560B
-:101DB00001E4FDF557AF35FEFC120915121C9D120A
-:101DC0001E7A121C4CAF577E00AD567C00120444A4
-:101DD000AF567E000211EEE4F516120E44FEE50841
-:101DE0004405FF120E658F828E83F00516E516C33B
-:101DF000941440E6E508120E2BE4F022E4F558F5C1
-:101E000059F55AFFFEAD58FC1209157F047E00AD4E
-:101E1000587C001209157F027E00AD587C00020933
-:101E200015E53C253EFCE5422400FBE433FAECC317
-:101E30009BEA12076B400B8C42E53D253FF5418F35
-:101E4000402212090B227484F5188508198519821D
-:101E5000851883E0547FF0E04480F0E04480F02275
-:101E6000EF4E700B12072A7583D2E054DFF0221276
-:101E7000072A7583D2E04420F02275580190072686
-:101E8000120735E0543FF541120732E0543FF54068
-:101E900022755602E4F557121DFCAF577E00AD5671
-:101EA0007C00020444E4F542F541F540F538F5398B
-:101EB000F53A22EF5407FFE5F954F84FF5F9227F80
-:101EC00001E4FE0F0EBEFFFB2201200001042000F2
-:101ED0000000000000000000000000000000000002
-:101EE00000000000000000000000000000000000F2
-:101EF00000000000000000000000000000000000E2
-:101F000000000000000000000000000000000000D1
-:101F100000000000000000000000000000000000C1
-:101F200000000000000000000000000000000000B1
-:101F300000000000000000000000000000000000A1
-:101F40000000000000000000000000000000000091
-:101F50000000000000000000000000000000000081
-:101F60000000000000000000000000000000000071
-:101F70000000000000000000000000000000000061
-:101F80000000000000000000000000000000000051
-:101F90000000000000000000000000000000000041
-:101FA0000000000000000000000000000000000031
-:101FB0000000000000000000000000000000000021
-:101FC0000000000000000000000000000000000011
-:101FD0000000000000000000000000000000000001
-:101FE00000000000000000000000000000000000F1
-:101FF000000000000000000001201100042000810A
-:00000001FF
diff --git a/firmware/qlogic/sd7220.fw.ihex b/firmware/qlogic/sd7220.fw.ihex
new file mode 100644 (file)
index 0000000..a336363
--- /dev/null
@@ -0,0 +1,513 @@
+:10000000020A29020A87E5E630E6047F0180027FC2
+:1000100000E5E230E4047E0180027E00EE5F6008CD
+:1000200053F9F7E4F5FE80087F0A121731120EA289
+:1000300075FC08E4F5FDE5E720E70343F908220035
+:1000400001201100042000755101E4F552F553F52B
+:1000500052F57E7F04020438C2360552E552D3942D
+:100060000C4005755201D23690070C7407F0A3744A
+:10007000FFF0E4F50CA3F0900714F0A3F0750B204B
+:10008000F509E4F508E508D39430400302040412AE
+:100090000006150BE50870047F0180027F00E5096A
+:1000A00070047E0180027E00EE5F6005121871D23E
+:1000B0003553E1F7E5084509FFE50B25E025E02488
+:1000C00083F582E43407F583EFF085E220E552D32F
+:1000D0009401400D1219F3E054A064407003020330
+:1000E000FB53F9F8909470E4F0E0F510AF09121E9C
+:1000F000B3AF08EF4408F582758380E0F529EF443B
+:1001000007121A3CF5225440D39400401EE52954AE
+:10011000F070211219F3E04480F0E52254306508B4
+:1001200070091219F3E054BFF080091219F37440FA
+:10013000F00203FB121A127583AE74FFF0AF087E53
+:1001400000EF4407F582E0FDE50B25E025E0248182
+:10015000F582E43407F583EDF090070EE004F0EF4C
+:100160004407F582758398E0F528121A23400C1293
+:1001700019F3E04401121A320203F6AF087E00744C
+:1001800080CDEFCD8D82F583E030E00A1219F3E0E7
+:100190004420F00203FB1219F3E054DFF0EE44AE0A
+:1001A000121A4330E4030203FB749E121A0520E086
+:1001B000030203FB8F828E83E020E0030203FB1225
+:1001C00019F3E04410F0E5E320E708E508121A3AD5
+:1001D0004404F0AF087E00EF121A3A20E2341219FC
+:1001E000F3E04408F0E5E430E6047D0180027D00A0
+:1001F000E57EC3940450047C0180027C00EC4D60D9
+:1002000005C2350203FBEE44D2121A434440F00209
+:1002100003FB1219F3E054F7F0121A127583D2E0BF
+:1002200054BFF0900714E004F0E57E7003757E0182
+:10023000AF087E00121A2340121219F3E044011293
+:1002400019F2E05402121A320203FB1219F3E044CD
+:10025000021219F2E054FEF0C235EE448A8F82F5A4
+:1002600083E0F517548F4440F07490FCE508440790
+:10027000FDF5828C83E0543F900702F0E054C08D7E
+:10028000828C83F07492121A05900703121A197463
+:1002900082121A05900704121A1974B4121A0590E2
+:1002A0000705121A197494FEE5084406121A0AF595
+:1002B0001030E004D2378002C237E510547F8F82BD
+:1002C0008E83F0304430121A035480D394004004DB
+:1002D000D2398002C2398F828E83E04480F0121AB4
+:1002E000035440D394004004D23A8002C23A8F8231
+:1002F0008E83E04440F07492FEE5084406121A0A28
+:1003000030E704D2388002C2388F828E83E0547F77
+:10031000F0121E46E4F50A20030280033043031264
+:1003200019952002028003304203120C8F303006F0
+:10033000121995120C8F120D471219F3E054FBF0AD
+:10034000E50AC39401404643E1081219F3E044046E
+:10035000F0E5E420E72A121A127583D2E05408D39C
+:10036000940040047F0180027F00E50AC3940140AD
+:10037000047E0180027E00EF5E6005121DD78017AB
+:10038000121A127583D2E04408F00203FB121A120B
+:100390007583D2E054F7F0121E467F0812173174AD
+:1003A0008EFE121A128E83E0F51054FEF0E5104412
+:1003B00001FFE508FDED4407F582EFF0E51054FE7E
+:1003C000FFED4407F582EF121A11758386E04410A1
+:1003D000121A11E04410F01219F3E054FD4401FF29
+:1003E0001219F3EF121A3230320CE5084408F58284
+:1003F0007583827405F0AF0B1218D774102508F5B9
+:10040000080200850509E509D3940750030200821C
+:10041000E57ED3940040047F0180027F00E57EC327
+:1004200094FA50047E0180027E00EE5F6002057E39
+:1004300030350B43E1017F0912173102005853E1B7
+:10044000FE0200588E6A8F6B8C6C8D6D756E017517
+:100450006F01757001E4F573F574F57590072FF071
+:10046000F53CF53EF546F547F53DF53FF56FE56F93
+:10047000700FE56B456A12072A758380743AF08025
+:100480000912072A758380741AF0E4F56EC3743F6D
+:10049000956EFF120865758382EFF0121A4D1208EF
+:1004A000C6E533F01208FA1208B140E1E56F700BAF
+:1004B00012072A7583807436F0800912072A758323
+:1004C000807416F0756E0112072A7583B4E56EF01C
+:1004D000121A4D743F256EF582E43400F583E5333E
+:1004E000F074BF256EF582E434001208B140D8E400
+:1004F000F570F546F547F56E1208FAF583E0FE1241
+:1005000008C6E07C002400FFEC3EFEAD3BD3EF9D2F
+:10051000EE9C50047B0180027B00E57070047A0140
+:1005200080027A00EB5A6006856E46757001D3EF43
+:100530009DEE9C50047F0180027F00E570B40104B1
+:100540007E0180027E00EF5E6003856E47056EE5EA
+:100550006E647F70A3E5466005E547B47E0385467B
+:1005600047E56F7008854676854777800EC3747FB0
+:100570009546F578C3747F9547F579E56F7037E553
+:10058000466547700C757301757401F53CF53D8047
+:1005900035E4F54EC3E5479546F53CC313F57125A3
+:1005A00046F572C3943F4005E4F53D8040C3743F77
+:1005B0009572F53D8037E5466547700F7573017597
+:1005C0007501F53EF53F754E018022E4F54EC3E519
+:1005D000479546F53EC313F5712546F572D3943F12
+:1005E0005005E4F53F8006E57224C1F53F056FE54F
+:1005F0006FC39402500302046EE56D456C70028077
+:1006000004E574457590072FF07F01E53E6004E531
+:100610003C7014E4F53CF53DF53EF53F1208D27010
+:1006200004F00206A4807AE53CC3953E4007E53C11
+:10063000953EFF8006C3E53E953CFFE576D3957970
+:10064000400585767A800385797AE577C395785079
+:100650000585777B800385787BE57BD3957A403071
+:10066000E57B957AF53CF53EC3E57B957A900719D5
+:10067000F0E53CC313F571257AF572C3943F40054C
+:10068000E4F53D801FC3743F9572F53DF53F80143E
+:10069000E4F53CF53E900719F01208D27003F080A3
+:1006A000037401F01208657583D0E0540FFEAD3C71
+:1006B00070027E07BE0F027E80EEFBEFD39B74803C
+:1006C000F898401FE4F53CF53E1208D27003F08024
+:1006D000127401F0E508FBEB4407F5827583D2E064
+:1006E0004410F0E508FBEB4409F58275839EEDF0BC
+:1006F000EB4407F5827583CAEDF01208657583CC6B
+:10070000EFF022E5084407F5827583BCE054F0F071
+:10071000E5084407F5827583BEE054F0F0E508442F
+:1007200007F5827583C0E054F0F0E5084407F582D0
+:1007300022F0900728E0FEA3E0F5828E8322854216
+:100740004285414185404074C02FF58274023EF5D8
+:1007500083E542F074E02FF58274023EF58322E5D2
+:100760004229FDE433FCE53CC39DEC6480F87480D1
+:100770009822F583E0900722541FFDE0FAA3E0F5EC
+:10078000828A83EDF022900722E0FCA3E0F5828CC0
+:100790008322900724FFED4407CFF0A3EFF02285DA
+:1007A0003838853939853A3A74C02FF58274023E5B
+:1007B000F58322900726FFED4407CFF0A3EFF02248
+:1007C000F074A02FF58274023EF5832274C02511C7
+:1007D000F582E43401F5832274002511F582E434B6
+:1007E00002F5832274602511F582E43403F5832237
+:1007F00074802511F582E43403F5832274E0251119
+:10080000F582E43403F5832274402511F582E43443
+:1008100006F5832274802FF58274023EF58322AFA1
+:10082000087E00EF4407F58222F583E5824407F550
+:1008300082E540F02274402511F582E43402F5830C
+:100840002274C02511F582E43403F5832274002557
+:1008500011F582E43406F5832274202511F582E433
+:100860003406F58322E508FDED4407F58222E541D3
+:10087000F0E56564014564227E00FB7A00FD7C00A2
+:100880002274202511F582E434022274A02511F58A
+:1008900082E4340322853E42853F418F4022853CDD
+:1008A00042853D418F402275453F900720E4F0A3EB
+:1008B00022F583E532F0056EE56EC3944022F0E543
+:1008C000084406F582227400256EF582E43400F5B2
+:1008D0008322E56D456C90072F22E4F9E53CD39522
+:1008E0003E2274802EF582E43402F583E02274A067
+:1008F0002EF582E43402F583E0227480256EF582C1
+:10090000E43400222542FDE433FC22854242854145
+:100910004185404022ED4C60030209E5EF4E7037FF
+:10092000900726120789E0FD1207CCEDF09007280A
+:10093000120789E0FD1207D8EDF0120786E0541F78
+:10094000FD120881F583EDF0900724120789E05429
+:100950001FFD120835EDF0EF64044E703790072646
+:10096000120789E0FD1207E4EDF0900728120789CD
+:10097000E0FD1207F0EDF0120786E0541FFD1208AB
+:100980008BF583EDF0900724120789E0541FFD12C8
+:100990000841EDF0EF64014E70047D0180027D009E
+:1009A000EF64024E70047F0180027F00EF4D60789B
+:1009B000900726120735E0FF1207FCEF120731E01F
+:1009C000FF120808EFF0900722120735E0541FFFCE
+:1009D00012084DEFF0900724120735E0541FFF1264
+:1009E0000859EFF0221207CCE4F01207D8E4F01215
+:1009F0000881F583E4F01208357414F01207E4E47A
+:100A0000F01207F0E4F012088BF583E4F0120841CD
+:100A10007414F01207FCE4F0120808E4F012084D18
+:100A2000E4F01208597414F02253F9F775FC10E43D
+:100A3000F5FD75FE30F5FFE5E720E70343F908E52E
+:100A4000E620E70B78FFE4F6D8FD53E6FE80097850
+:100A500008E4F6D8FD53E6FE758180E4F5A8D2A837
+:100A6000C2A9D2AFE5E220E50520E602800343E11A
+:100A700002E5E220E00E9000007F007E08E4F0A393
+:100A8000DFFCDEFA020ADB43FA01C0E0C0F0C083FB
+:100A9000C082C0D0121CE7D0D0D082D083D0F0D09A
+:100AA000E053FAFE32021B55E493A3F8E493A3F655
+:100AB00008DFF98029E493A3F85407240CC8C33352
+:100AC000C4540F4420C8834004F456800146F6DF26
+:100AD000E4800B010204081020408090003FE47E77
+:100AE000019360C1A3FF543F30E509541FFEE49316
+:100AF000A360010ECF54C025E060AD40B880FE8CED
+:100B0000648D658A668B67E4F569EF4E7003021D9C
+:100B100055E4F568E5674566703212072A758390DB
+:100B2000E41207297583C2E41207297583C4E4120D
+:100B30000870702912072A758392E41207297583B9
+:100B4000C6E41207297583C8E4F0801190072612C5
+:100B50000735E41208707005120732E4F0121D55D3
+:100B6000121EBFE5674566703312072A758390E54C
+:100B7000411207297583C2E5411207297583C41202
+:100B8000086E702912072A758392E54012072975AD
+:100B900083C6E5401207297583C8800E9007261288
+:100BA000073512086E7006120732E540F0AF697E15
+:100BB00000AD67AC6612044412072A7583CAE0D3FD
+:100BC0009400500C0568E568C394055003020B14AB
+:100BD000228C608D611208DA7420400D2FF582742A
+:100BE000033EF583E53EF0800B2FF58274033EF55E
+:100BF00083E53CF0E53CD3953E403CE561456070C3
+:100C000010E9120904E53E120768403B120895807E
+:100C100018E53EC39538401D853E38E53E600585A4
+:100C20003F3980038539398F3A120814E53E12079F
+:100C3000C0E53FF0228043E5614560701912075F0F
+:100C4000400512089E802712090B120814E5421273
+:100C500007C0E541F022E53CC39538401D853C388E
+:100C6000E53C6005853D3980038539398F3A1208A6
+:100C700014E53C1207C0E53DF02285383885393946
+:100C8000853A3A120814E5381207C0E539F0227F98
+:100C900006121731121D23120E04120E33E0440AFD
+:100CA000F0748EFE120E04120E0BEFF0E52830E504
+:100CB00003D38001C3400575142080037514081206
+:100CC0000E0475838AE514F0B4FF05751280800662
+:100CD000E514C313F512E4F516F57F121936121355
+:100CE000A3E50AC3940150090516E516C394144000
+:100CF000EAE5E420E728120E047583D2E05408D315
+:100D0000940040047F0180027F00E50AC394014003
+:100D1000047E0180027E00EF5E6003121DD7E57F36
+:100D2000C394114014120E047583D2E04480F0E5A0
+:100D3000E420E70F121DD7800A120E047583D2E05B
+:100D4000547FF0121D2322748A850882F583E517EB
+:100D5000F0120E3AE4F0900702E0120E177583903D
+:100D6000EFF07492FEE5084407FFF5828E83E054AD
+:100D7000C0FD900703E0543F4D8F828E83F09007B3
+:100D800004E0120E17758382EFF0900705E0FFED87
+:100D90004407F5827583B4EF120E03758380E05427
+:100DA000BFF030370A120E91758394E04480F03022
+:100DB000380A120E91758392E04480F0E52830E401
+:100DC0001A20390A120E04758388E0547FF0203A05
+:100DD0000A120E04758388E054BFF0748CFE120E64
+:100DE000048E83E0540F120E03758386E054BFF027
+:100DF000E5084406120DFD75838AE4F022F582753C
+:100E00008382E4F0E5084407F582228E83E0F51042
+:100E100054FEF0E5104401FFE508FDED4407F582BE
+:100E200022E515C45407FFE508FDED4408F5827579
+:100E3000838222758380E04440F0E5084408F5820F
+:100E400075838A22E51625E025E024AFF582E43497
+:100E50001AF583E493F50D2243E11043E18053E159
+:100E6000FD85E11022E51625E025E024B2F582E4B7
+:100E7000341AF583E49322855582855483E515F071
+:100E800022E5E25420D3940022E5E25440D39400BA
+:100E900022E5084406F58222FDE508FBEB4407F550
+:100EA000822253F9F775FE3022EF4E70261207CCDE
+:100EB000E0FD90072612077B1207D8E0FD90072877
+:100EC00012077B120881120772120835E09007247E
+:100ED000120778EF64044E70291207E4E0FD9007D2
+:100EE0002612077B1207F0E0FD90072812077B12FD
+:100EF000088B120772120841E0541FFD900724125C
+:100F0000077BEF64014E70047D0180027D00EF6479
+:100F1000024E70047F0180027F00EF4D60351207A2
+:100F2000FCE0FF900726120789EFF0120808E0FFA7
+:100F3000900728120789EFF012084DE0541FFF12A6
+:100F40000786EFF0120859E0541FFF90072412079C
+:100F500089EFF022E4F553120E8140047F018002F4
+:100F60007F00120E8940047E0180027E00EE4F70E9
+:100F700003020FF685E11043E10253E10F85E11012
+:100F8000E4F551E5E3543FF552120E89401DAD5290
+:100F9000AF51121118EF600885E11043E140800B5A
+:100FA00053E1BF120E5812000680FBE5E3543FF5F3
+:100FB00051E5E4543FF552120E81401DAD52AF5140
+:100FC000121118EF600885E11043E120800B53E116
+:100FD000DF120E5812000680FB120E8140047F01C2
+:100FE00080027F00120E8940047E0180027E00EEA6
+:100FF0004F6003120E5B22120E21EFF012109122AD
+:1010000002110002104002109000000000000000D9
+:1010100001200120E4F5571216BD121644E4121007
+:10102000561214B7900726120735E4120731E4F080
+:101030001210561214B7900726120735E541120711
+:1010400031E540F0AF577E00AD567C00120444AF4E
+:10105000567E000211EEFF900720A3E0FDE4F55656
+:10106000F540FEFCAB56FA1211517F0F7D18E4F5E6
+:1010700056F540FEFCAB56FA121541AF567E0012F3
+:101080001AFFE4FFF5567D1FF540FEFCAB56FA2231
+:1010900022E4F555E508FD74A0F556ED4407F55733
+:1010A000E52830E503D38001C340057F28EF8004A5
+:1010B0007F14EFC313F554E4F9120E1875838EE014
+:1010C000F510CEEFCEEED394004026E51054FE127C
+:1010D0000E9875838EEDF0E5104401FDEB4407F5A5
+:1010E00082EDF0855782855683E030E301091E804A
+:1010F000D4C234E9C395544002D2342202000622FD
+:10110000303011901000E493F510901010E493F536
+:101110001012109012115022E4FCC3ED9FFAEFF56B
+:101120008375820079FFE493CC6CCCA3D9F8DAF60E
+:10113000E5E230E4028CE5ED24FFFFEF7582FFF578
+:1011400083E4936C70037F01227F00222211000050
+:10115000228E588F598C5A8D5B8A5C8B5D755E012F
+:10116000E4F55FF560F56212072A7583D0E0FFC4ED
+:10117000540FF561121EA585595ED3E55E955BE5BA
+:101180005A12076B504B1207037583BCE0455E1281
+:1011900007297583BEE0455E1207297583C0E045C7
+:1011A0005EF0AF5FE560120878120AFFAF627E0062
+:1011B000AD5DAC5C120444E561AF5E7E00B4030536
+:1011C000121E218007AD5DAC5C121317055E021183
+:1011D0007A1207037583BCE045401207297583BE68
+:1011E000E045401207297583C0E04540F0228E5843
+:1011F0008F59755A017901755B01E4FB12072A7555
+:1012000083AEE0541AFF120865E0C4135407FEEFE2
+:10121000700CEE6535700790072FE0B4010DAF3507
+:101220007E00120EA9CFEBCF021E60E55964024585
+:101230005870047F0180027F00E559455870047E94
+:101240000180027E00EE4F602385414985404BE5D9
+:10125000594558702CAF5AFECDE9CDFCAB59AA5870
+:10126000120AFFAF5B7E00121E608015AF5B7E002E
+:10127000121E60900726120735E549120731E54B2B
+:10128000F0E4FDAF35FEFC120915228C648D651269
+:1012900008DA403CE56545647010120904C3E53E78
+:1012A000120769403B1208958018E53EC395384007
+:1012B0001D853E38E53E6005853F39800385393917
+:1012C0008F3A1207A8E53E120753E53FF022803B14
+:1012D000E5654564701112075F400512089E801F86
+:1012E00012073EE541F022E53CC39538401D853CA0
+:1012F00038E53C6005853D3980038539398F3A12E0
+:1013000007A8E53C120753E53DF02212079FE53898
+:10131000120753E539F0228C638D641208DA403CE1
+:10132000E56445637010120904C3E53E1207694085
+:101330003B1208958018E53EC39538401D853E3820
+:10134000E53E6005853F3980038539398F3A1207BC
+:10135000A8E53E120753E53FF022803BE564456374
+:10136000701112075F400512089E801F12073EE5AC
+:1013700041F022E53CC39538401D853C38E53C6092
+:1013800005853D3980038539398F3A1207A8E53C38
+:10139000120753E53DF02212079FE538120753E587
+:1013A00039F022E50DFEE5088E544405F555751516
+:1013B0000FF582120E7A1217A320310575150380DE
+:1013C0000375150BE50AC39401503812142020311F
+:1013D0000605150515800415151515E50AC39401B4
+:1013E0005021121420203104051580021515E50A3C
+:1013F000C39401500E120E771217A3203105051564
+:10140000120E77E515B408047F0180027F00E51510
+:10141000B407047E0180027E00EE4F6002057F2249
+:10142000855582855483E515F01217A32212072AE9
+:101430007583AE74FF120729E0541AF534E0C41323
+:101440005407F53524FE602424FE603C24047063B8
+:1014500075312DE508FD74B612079274BC90072211
+:1014600012079574901207B37492803C75313AE577
+:1014700008FD74BA12079274C09007221207B6745E
+:10148000C41207B374C88020753135E508FD74B8FF
+:1014900012079274BEFFED4407900722CFF0A3EF2E
+:1014A000F074C21207B374C6FFED4407A3CFF0A3D4
+:1014B000EFF022753401228E588F598C5A8D5B8A39
+:1014C0005C8B5D755E01E4F55F121EA585595ED3E8
+:1014D000E55E955BE55A12076B5057E55D455C701C
+:1014E0003012072A758392E55E1207297583C6E5D7
+:1014F0005E1207297583C8E55E120729758390E59A
+:101500005E1207297583C2E55E1207297583C480C0
+:1015100003120732E55EF0AF5F7E00AD5DAC5C129A
+:101520000444AF5E7E00AD5DAC5C120BD1055E0283
+:1015300014CFAB5DAA5CAD5BAC5AAF59AE58021B81
+:10154000FB8C5C8D5D8A5E8B5F756001E4F561F5F7
+:1015500062F563121EA58F60D3E560955DE55C12B0
+:10156000076B5061E55F455E702712072A7583B6E9
+:10157000E5601207297583B8E5601207297583BAFB
+:10158000E560F0AF617E00E56212087A120AFF8022
+:1015900019900724120735E56012072975838EE438
+:1015A0001207297401120729E4F0AF637E00AD5FD2
+:1015B000AC5E120444AF607E00AD5FAC5E12128B75
+:1015C00005600215582290114DE49390072EF012F9
+:1015D000081F7583AEE0541AF5347067EF4407F5C1
+:1015E000827583CEE0FF1313135407F536540FD3DF
+:1015F0009400400612142D121BA9E536540F24FE48
+:10160000600C14600C146019240370378010021EE3
+:1016100091121E9112072A7583CEE054EFF0021D3D
+:10162000AE121014E4F555121D850555E555C39409
+:101630000540F412072A7583CEE054C7120729E04B
+:101640004408F022E4F558F559AF08EF4407F58255
+:101650007583D0E0FDC4540FF55AEF4407F5827549
+:1016600083807401F0120821758382E545F0EF4410
+:1016700007F58275838A74FFF0121A4D12072A75D6
+:1016800083BCE054EF1207297583BEE054EF1207C4
+:10169000297583C0E054EF1207297583BCE044101C
+:1016A0001207297583BEE044101207297583C0E034
+:1016B0004410F0AF58E559120878020AFFE4F558D3
+:1016C0007D01F559AF35FEFC12091512072A758305
+:1016D000B674101207297583B87410120729758320
+:1016E000BA74101207297583BC7410120729758308
+:1016F000BE74101207297583C074101207297583F0
+:1017000090E41207297583C2E41207297583C4E4A3
+:10171000120729758392E41207297583C6E412071C
+:10172000297583C8E4F0AF58FEE55912087A020A19
+:10173000FFE5E230E46CE5E754C064407064E5091D
+:10174000C45430FEE50825E025E054C04EFEEF54B9
+:101750003F4EFDE52BAE2A7802C333CE33CED8F907
+:10176000F5828E83EDF0E52BAE2A7802C333CE33BB
+:10177000CED8F9FFF5828E83A3E5FEF08F828E83AB
+:10178000A3A3E5FDF08F828E83A3A3A3E5FCF0C3A2
+:10179000E52B94FAE52A94005008052BE52B7002FE
+:1017A000052A22E4FFE4F558F556F5577482FC1239
+:1017B0000E048C83E0F510547FF0E5104480120E87
+:1017C00098EDF07E0A120E047583A0E020E026DE7C
+:1017D000F40557E55770020556E5142401FDE4337E
+:1017E000FCD3E5579DE5569C40D9E50A942050026C
+:1017F000050A43E108C231120E047583A6E05512B2
+:1018000065127003D23122C23122900726E0FAA37A
+:10181000E0F5828A83E0F541E539C395414026E54C
+:10182000399541C39FEE12076B40047C0180027C16
+:1018300000E541643F60047B0180027B00EC5B605B
+:101840002905418028C3E5419539C39FEE12076BF6
+:1018500040047F0180027F00E54160047E01800238
+:101860007E00EF5E600415418003853941853A4072
+:1018700022E5E230E460E5E130E25BE50970047FF7
+:101880000180027F00E50870047E0180027E00EE88
+:101890005F604353F9F8E5E230E43BE5E130E22EE6
+:1018A00043FA0253FAFBE4F510909470E510F0E56A
+:1018B000E130E2E7909470E06510600343FA0405BC
+:1018C00010909470E510F070E612000680E153FA73
+:1018D000FD53FAFB80C0228F54120006E5E130E090
+:1018E000047F0180027F00E57ED3940540047E01E1
+:1018F00080027E00EE4F603D855411E5E220E1322A
+:1019000074CE121A0530E7047D0180027D008F82BB
+:101910008E83E030E6047F0180027F00EF5D70156A
+:101920001215C674CE121A0530E607E04480F04363
+:10193000F98012187122120E44E51625E025E024E4
+:10194000B0F582E4341AF583E493F50FE51625E04B
+:1019500025E024B1F582E4341AF583E493F50E1200
+:101960000E65F510E50F54F0120E1775838CEFF02D
+:10197000E50F30E00C120E04758386E04440F080E1
+:101980000A120E04758386E054BFF0120E9175831F
+:1019900082E50EF0227F05121731120E04120E336B
+:1019A0007402F0748EFE120E04120E0BEFF0751519
+:1019B00070120FF72034057515108003751550123D
+:1019C0000FF72034047410800274F02515F51512F9
+:1019D0000E21EFF0121091203417E5156430600CE1
+:1019E00074102515F515B48003E4F515120E21EFDA
+:1019F000F022F0E50B25E025E02482F582E43407AF
+:101A0000F583227488FEE5084407FFF5828E83E0A3
+:101A100022F0E5084407F58222F0E054C08F828E60
+:101A200083F022EF4407F582758386E05410D39447
+:101A30000022F0900715E004F0224406F582758339
+:101A40009EE022FEEF4407F5828E83E022E49007B9
+:101A50002AF0A3F012072A758382E0547F12072927
+:101A6000E04480F01210FC12081F7583A0E020E013
+:101A70001A90072BE004F0700690072AE004F0901B
+:101A8000072AE0B410E1A3E0B400DCEE44A6FCEFCA
+:101A90004407F5828C83E0F532EE44A8FEEF44075C
+:101AA000F5828E83E0F5332201201100042000909E
+:101AB00000200F9200210F9400220F9600230F9810
+:101AC00000240F9A00250F9C00260F9E00270FA0D0
+:101AD000012001A2012101A4012201A6012301A8E4
+:101AE000012401AA012501AC012601AE012701B0A4
+:101AF000012801B400280FB640280FB8612801CB97
+:101B0000EFCBCAEECA7F01E4FDEB4A7024E508F58D
+:101B10008274B6120829E508F58274B8120829E51E
+:101B200008F58274BA1208297E007C00120AFF8030
+:101B300012900726120735E541F090072412073569
+:101B4000E540F012072A75838EE41207297401120A
+:101B50000729E4F022E4F526F52753E1FEF52A757E
+:101B60002B01F5087F0112173130301C901AA9E4BF
+:101B700093F510901FF9E493F510900041E493F56C
+:101B800010901ECAE493F5107F02121731120F5401
+:101B90007F03121731120006E5E230E70912100048
+:101BA00030300312110002004712081F7583D0E085
+:101BB000C4540FFD7543017544FF1208AA7404F064
+:101BC000753B01ED14600C14600B14600F2403705E
+:101BD0000B800980001208A704F080061208A77481
+:101BE00004F0EE4482FEEF4407F5828E83E5451251
+:101BF00008BE758382E531F002114C8E608F611250
+:101C00001EA5E4FFCEEDCEEED39561E56012076B25
+:101C1000403974202EF582E43403F583E07003FF2D
+:101C200080261208E2FDC39F401ECFEDCFEB4A7025
+:101C30000B8D421208EEF5418E40800C1208E2F541
+:101C4000381208EEF5398E3A1E80BC22755801E52F
+:101C500035700C1207CCE0F54A1207D8E0F54CE5D8
+:101C600035B4040C1207E4E0F54A1207F0E0F54C35
+:101C7000E535B401047F0180027F00E535B402043C
+:101C80007E0180027E00EE4F600C1207FCE0F54AF8
+:101C9000120808E0F54C85414985404B22755B01EF
+:101CA000900724120735E0541FFFD3940250048F8D
+:101CB000588005EF24FEF558EFC394184005755978
+:101CC000188004EF04F55985435AAF587E00AD598A
+:101CD0007C00AB5B7A00121541AF5A7E0012180AE5
+:101CE000AF5B7E00021AFFE5E230E70E121003C27E
+:101CF000303030031210FF203328E5E730E70512BB
+:101D00000EA2800DE5FEC394205006120EA243F9E8
+:101D100008E5F230E70353F97FE5F15470D39400FE
+:101D200050D822120E04758380E4F0E508440712AF
+:101D30000DFD758384120E02758386120E02758363
+:101D40008CE054F3120E0375838E120E0275839489
+:101D5000E054FBF02212072A75838EE412072974DF
+:101D600001120729E41208BE75838CE04420120892
+:101D7000BEE054DFF07484850882F583E0547FF080
+:101D8000E04480F022755601E4FDF557AF35FEFCC6
+:101D9000120915121C9D121E7A121C4CAF577E00A0
+:101DA000AD567C00120444AF567E000211EE75560B
+:101DB00001E4FDF557AF35FEFC120915121C9D120A
+:101DC0001E7A121C4CAF577E00AD567C00120444A4
+:101DD000AF567E000211EEE4F516120E44FEE50841
+:101DE0004405FF120E658F828E83F00516E516C33B
+:101DF000941440E6E508120E2BE4F022E4F558F5C1
+:101E000059F55AFFFEAD58FC1209157F047E00AD4E
+:101E1000587C001209157F027E00AD587C00020933
+:101E200015E53C253EFCE5422400FBE433FAECC317
+:101E30009BEA12076B400B8C42E53D253FF5418F35
+:101E4000402212090B227484F5188508198519821D
+:101E5000851883E0547FF0E04480F0E04480F02275
+:101E6000EF4E700B12072A7583D2E054DFF0221276
+:101E7000072A7583D2E04420F02275580190072686
+:101E8000120735E0543FF541120732E0543FF54068
+:101E900022755602E4F557121DFCAF577E00AD5671
+:101EA0007C00020444E4F542F541F540F538F5398B
+:101EB000F53A22EF5407FFE5F954F84FF5F9227F80
+:101EC00001E4FE0F0EBEFFFB2201200001042000F2
+:101ED0000000000000000000000000000000000002
+:101EE00000000000000000000000000000000000F2
+:101EF00000000000000000000000000000000000E2
+:101F000000000000000000000000000000000000D1
+:101F100000000000000000000000000000000000C1
+:101F200000000000000000000000000000000000B1
+:101F300000000000000000000000000000000000A1
+:101F40000000000000000000000000000000000091
+:101F50000000000000000000000000000000000081
+:101F60000000000000000000000000000000000071
+:101F70000000000000000000000000000000000061
+:101F80000000000000000000000000000000000051
+:101F90000000000000000000000000000000000041
+:101FA0000000000000000000000000000000000031
+:101FB0000000000000000000000000000000000021
+:101FC0000000000000000000000000000000000011
+:101FD0000000000000000000000000000000000001
+:101FE00000000000000000000000000000000000F1
+:101FF000000000000000000001201100042000810A
+:00000001FF
index 3f941f2a305949f31ba9dce2a4e87f6849e8ab71..1dc8786f4588355245a90063e02464ff35e07760 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1029,9 +1029,9 @@ static int aio_read_evt(struct kioctx *ioctx, struct io_event *ent)
        spin_unlock(&info->ring_lock);
 
 out:
-       kunmap_atomic(ring);
        dprintk("leaving aio_read_evt: %d  h%lu t%lu\n", ret,
                 (unsigned long)ring->head, (unsigned long)ring->tail);
+       kunmap_atomic(ring);
        return ret;
 }
 
index 3939829f6c5cc67e7d0ca1e9518f1df834be5088..86af964c2425d7077467bf54eaecde3d2d4c4911 100644 (file)
@@ -1137,6 +1137,7 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
                        goto whole;
                if (!(vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_PRIVATE))
                        goto whole;
+               return 0;
        }
 
        /* Do not dump I/O mapped devices or special mappings */
index bb5768f59b32e22fdcde250f0ae8b01eb6b69b48..b96fc6ce485595f0179bc909c807ae197258e671 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1428,8 +1428,6 @@ void bio_endio(struct bio *bio, int error)
        else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
                error = -EIO;
 
-       trace_block_bio_complete(bio, error);
-
        if (bio->bi_end_io)
                bio->bi_end_io(bio, error);
 }
index aea605c98ba6b4eb920a022acaf6c4587ed653f9..aae187a7f94a661edb82189496242fdac4c33fcf 100644 (file)
@@ -551,6 +551,7 @@ struct block_device *bdgrab(struct block_device *bdev)
        ihold(bdev->bd_inode);
        return bdev;
 }
+EXPORT_SYMBOL(bdgrab);
 
 long nr_blockdev_pages(void)
 {
index 451fad96ecd115393207e69433162b7328f74923..ef96381569a4a1229b95f6b3470f232b3ebe8b0e 100644 (file)
@@ -317,6 +317,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
        unsigned long src_ptr;
        unsigned long dst_ptr;
        int overwrite_root = 0;
+       bool inode_item = key->type == BTRFS_INODE_ITEM_KEY;
 
        if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
                overwrite_root = 1;
@@ -326,6 +327,9 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
 
        /* look for the key in the destination tree */
        ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
+       if (ret < 0)
+               return ret;
+
        if (ret == 0) {
                char *src_copy;
                char *dst_copy;
@@ -367,6 +371,30 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
                        return 0;
                }
 
+               /*
+                * We need to load the old nbytes into the inode so when we
+                * replay the extents we've logged we get the right nbytes.
+                */
+               if (inode_item) {
+                       struct btrfs_inode_item *item;
+                       u64 nbytes;
+
+                       item = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                             struct btrfs_inode_item);
+                       nbytes = btrfs_inode_nbytes(path->nodes[0], item);
+                       item = btrfs_item_ptr(eb, slot,
+                                             struct btrfs_inode_item);
+                       btrfs_set_inode_nbytes(eb, item, nbytes);
+               }
+       } else if (inode_item) {
+               struct btrfs_inode_item *item;
+
+               /*
+                * New inode, set nbytes to 0 so that the nbytes comes out
+                * properly when we replay the extents.
+                */
+               item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item);
+               btrfs_set_inode_nbytes(eb, item, 0);
        }
 insert:
        btrfs_release_path(path);
@@ -486,7 +514,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
        int found_type;
        u64 extent_end;
        u64 start = key->offset;
-       u64 saved_nbytes;
+       u64 nbytes = 0;
        struct btrfs_file_extent_item *item;
        struct inode *inode = NULL;
        unsigned long size;
@@ -496,10 +524,19 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
        found_type = btrfs_file_extent_type(eb, item);
 
        if (found_type == BTRFS_FILE_EXTENT_REG ||
-           found_type == BTRFS_FILE_EXTENT_PREALLOC)
-               extent_end = start + btrfs_file_extent_num_bytes(eb, item);
-       else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
+           found_type == BTRFS_FILE_EXTENT_PREALLOC) {
+               nbytes = btrfs_file_extent_num_bytes(eb, item);
+               extent_end = start + nbytes;
+
+               /*
+                * We don't add to the inodes nbytes if we are prealloc or a
+                * hole.
+                */
+               if (btrfs_file_extent_disk_bytenr(eb, item) == 0)
+                       nbytes = 0;
+       } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
                size = btrfs_file_extent_inline_len(eb, item);
+               nbytes = btrfs_file_extent_ram_bytes(eb, item);
                extent_end = ALIGN(start + size, root->sectorsize);
        } else {
                ret = 0;
@@ -548,7 +585,6 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
        }
        btrfs_release_path(path);
 
-       saved_nbytes = inode_get_bytes(inode);
        /* drop any overlapping extents */
        ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1);
        BUG_ON(ret);
@@ -635,7 +671,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
                BUG_ON(ret);
        }
 
-       inode_set_bytes(inode, saved_nbytes);
+       inode_add_bytes(inode, nbytes);
        ret = btrfs_update_inode(trans, root, inode);
 out:
        if (inode)
index 991c63c6bdd053189082c6208407a5df55b29053..21b3a291c327c1e3871d110725ed972ce8ab21ba 100644 (file)
@@ -1575,14 +1575,24 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        }
                        break;
                case Opt_blank_pass:
-                       vol->password = NULL;
-                       break;
-               case Opt_pass:
                        /* passwords have to be handled differently
                         * to allow the character used for deliminator
                         * to be passed within them
                         */
 
+                       /*
+                        * Check if this is a case where the  password
+                        * starts with a delimiter
+                        */
+                       tmp_end = strchr(data, '=');
+                       tmp_end++;
+                       if (!(tmp_end < end && tmp_end[1] == delim)) {
+                               /* No it is not. Set the password to NULL */
+                               vol->password = NULL;
+                               break;
+                       }
+                       /* Yes it is. Drop down to Opt_pass below.*/
+               case Opt_pass:
                        /* Obtain the value string */
                        value = strchr(data, '=');
                        value++;
index 412e6eda25f813e037f3d18936e7ed860793a443..e4141f2574953893377939f2362a673a62a609b9 100644 (file)
@@ -80,13 +80,6 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
        int rc;
 
        mutex_lock(&ecryptfs_daemon_hash_mux);
-       rc = try_module_get(THIS_MODULE);
-       if (rc == 0) {
-               rc = -EIO;
-               printk(KERN_ERR "%s: Error attempting to increment module use "
-                      "count; rc = [%d]\n", __func__, rc);
-               goto out_unlock_daemon_list;
-       }
        rc = ecryptfs_find_daemon_by_euid(&daemon);
        if (!rc) {
                rc = -EINVAL;
@@ -96,7 +89,7 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to spawn daemon; "
                       "rc = [%d]\n", __func__, rc);
-               goto out_module_put_unlock_daemon_list;
+               goto out_unlock_daemon_list;
        }
        mutex_lock(&daemon->mux);
        if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) {
@@ -108,9 +101,6 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
        atomic_inc(&ecryptfs_num_miscdev_opens);
 out_unlock_daemon:
        mutex_unlock(&daemon->mux);
-out_module_put_unlock_daemon_list:
-       if (rc)
-               module_put(THIS_MODULE);
 out_unlock_daemon_list:
        mutex_unlock(&ecryptfs_daemon_hash_mux);
        return rc;
@@ -147,7 +137,6 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file)
                       "bug.\n", __func__, rc);
                BUG();
        }
-       module_put(THIS_MODULE);
        return rc;
 }
 
@@ -471,6 +460,7 @@ out_free:
 
 
 static const struct file_operations ecryptfs_miscdev_fops = {
+       .owner   = THIS_MODULE,
        .open    = ecryptfs_miscdev_open,
        .poll    = ecryptfs_miscdev_poll,
        .read    = ecryptfs_miscdev_read,
index 56efcaadf8485a5887ae04493b9cacf28b5c73ef..9c6d06dcef8bf1f997c0f05bfe443fcde993d72b 100644 (file)
@@ -2999,20 +2999,23 @@ static int ext4_split_extent_at(handle_t *handle,
                        if (split_flag & EXT4_EXT_DATA_VALID1) {
                                err = ext4_ext_zeroout(inode, ex2);
                                zero_ex.ee_block = ex2->ee_block;
-                               zero_ex.ee_len = ext4_ext_get_actual_len(ex2);
+                               zero_ex.ee_len = cpu_to_le16(
+                                               ext4_ext_get_actual_len(ex2));
                                ext4_ext_store_pblock(&zero_ex,
                                                      ext4_ext_pblock(ex2));
                        } else {
                                err = ext4_ext_zeroout(inode, ex);
                                zero_ex.ee_block = ex->ee_block;
-                               zero_ex.ee_len = ext4_ext_get_actual_len(ex);
+                               zero_ex.ee_len = cpu_to_le16(
+                                               ext4_ext_get_actual_len(ex));
                                ext4_ext_store_pblock(&zero_ex,
                                                      ext4_ext_pblock(ex));
                        }
                } else {
                        err = ext4_ext_zeroout(inode, &orig_ex);
                        zero_ex.ee_block = orig_ex.ee_block;
-                       zero_ex.ee_len = ext4_ext_get_actual_len(&orig_ex);
+                       zero_ex.ee_len = cpu_to_le16(
+                                               ext4_ext_get_actual_len(&orig_ex));
                        ext4_ext_store_pblock(&zero_ex,
                                              ext4_ext_pblock(&orig_ex));
                }
@@ -3272,7 +3275,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
                if (err)
                        goto out;
                zero_ex.ee_block = ex->ee_block;
-               zero_ex.ee_len = ext4_ext_get_actual_len(ex);
+               zero_ex.ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex));
                ext4_ext_store_pblock(&zero_ex, ext4_ext_pblock(ex));
 
                err = ext4_ext_get_access(handle, inode, path + depth);
index b505a145a5937a426184d5c289b6825ee62d0e17..a04183127ef049190ad96c0b7052ea4495fd33e9 100644 (file)
@@ -1539,9 +1539,9 @@ static int free_hole_blocks(handle_t *handle, struct inode *inode,
                blk = *i_data;
                if (level > 0) {
                        ext4_lblk_t first2;
-                       bh = sb_bread(inode->i_sb, blk);
+                       bh = sb_bread(inode->i_sb, le32_to_cpu(blk));
                        if (!bh) {
-                               EXT4_ERROR_INODE_BLOCK(inode, blk,
+                               EXT4_ERROR_INODE_BLOCK(inode, le32_to_cpu(blk),
                                                       "Read failure");
                                return -EIO;
                        }
index 019f45e450971341f9cfba1c50a0116295b2dfd3..d79c2dadc536662370c3c084b100f1cecd303855 100644 (file)
@@ -923,8 +923,11 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
                cmd = F_SETLK;
                fl->fl_type = F_UNLCK;
        }
-       if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+       if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
+               if (fl->fl_type == F_UNLCK)
+                       posix_lock_file_wait(file, fl);
                return -EIO;
+       }
        if (IS_GETLK(cmd))
                return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
        else if (fl->fl_type == F_UNLCK)
index 156e42ec84ea488c9c223400284c9040b5c86f69..5c29216e9cc1d000053aa4f34a5dd1a6d936cb2f 100644 (file)
@@ -588,6 +588,7 @@ struct lm_lockstruct {
        struct dlm_lksb ls_control_lksb; /* control_lock */
        char ls_control_lvb[GDLM_LVB_SIZE]; /* control_lock lvb */
        struct completion ls_sync_wait; /* {control,mounted}_{lock,unlock} */
+       char *ls_lvb_bits;
 
        spinlock_t ls_recover_spin; /* protects following fields */
        unsigned long ls_recover_flags; /* DFL_ */
index 9802de0f85e61fe061ea150d15177c39b4128ca3..c8423d6de6c3ee54341d5ea5c4eb7e20ca7255de 100644 (file)
@@ -483,12 +483,8 @@ static void control_lvb_write(struct lm_lockstruct *ls, uint32_t lvb_gen,
 
 static int all_jid_bits_clear(char *lvb)
 {
-       int i;
-       for (i = JID_BITMAP_OFFSET; i < GDLM_LVB_SIZE; i++) {
-               if (lvb[i])
-                       return 0;
-       }
-       return 1;
+       return !memchr_inv(lvb + JID_BITMAP_OFFSET, 0,
+                       GDLM_LVB_SIZE - JID_BITMAP_OFFSET);
 }
 
 static void sync_wait_cb(void *arg)
@@ -580,7 +576,6 @@ static void gfs2_control_func(struct work_struct *work)
 {
        struct gfs2_sbd *sdp = container_of(work, struct gfs2_sbd, sd_control_work.work);
        struct lm_lockstruct *ls = &sdp->sd_lockstruct;
-       char lvb_bits[GDLM_LVB_SIZE];
        uint32_t block_gen, start_gen, lvb_gen, flags;
        int recover_set = 0;
        int write_lvb = 0;
@@ -634,7 +629,7 @@ static void gfs2_control_func(struct work_struct *work)
                return;
        }
 
-       control_lvb_read(ls, &lvb_gen, lvb_bits);
+       control_lvb_read(ls, &lvb_gen, ls->ls_lvb_bits);
 
        spin_lock(&ls->ls_recover_spin);
        if (block_gen != ls->ls_recover_block ||
@@ -664,10 +659,10 @@ static void gfs2_control_func(struct work_struct *work)
 
                        ls->ls_recover_result[i] = 0;
 
-                       if (!test_bit_le(i, lvb_bits + JID_BITMAP_OFFSET))
+                       if (!test_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET))
                                continue;
 
-                       __clear_bit_le(i, lvb_bits + JID_BITMAP_OFFSET);
+                       __clear_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET);
                        write_lvb = 1;
                }
        }
@@ -691,7 +686,7 @@ static void gfs2_control_func(struct work_struct *work)
                                continue;
                        if (ls->ls_recover_submit[i] < start_gen) {
                                ls->ls_recover_submit[i] = 0;
-                               __set_bit_le(i, lvb_bits + JID_BITMAP_OFFSET);
+                               __set_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET);
                        }
                }
                /* even if there are no bits to set, we need to write the
@@ -705,7 +700,7 @@ static void gfs2_control_func(struct work_struct *work)
        spin_unlock(&ls->ls_recover_spin);
 
        if (write_lvb) {
-               control_lvb_write(ls, start_gen, lvb_bits);
+               control_lvb_write(ls, start_gen, ls->ls_lvb_bits);
                flags = DLM_LKF_CONVERT | DLM_LKF_VALBLK;
        } else {
                flags = DLM_LKF_CONVERT;
@@ -725,7 +720,7 @@ static void gfs2_control_func(struct work_struct *work)
         */
 
        for (i = 0; i < recover_size; i++) {
-               if (test_bit_le(i, lvb_bits + JID_BITMAP_OFFSET)) {
+               if (test_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET)) {
                        fs_info(sdp, "recover generation %u jid %d\n",
                                start_gen, i);
                        gfs2_recover_set(sdp, i);
@@ -758,7 +753,6 @@ static void gfs2_control_func(struct work_struct *work)
 static int control_mount(struct gfs2_sbd *sdp)
 {
        struct lm_lockstruct *ls = &sdp->sd_lockstruct;
-       char lvb_bits[GDLM_LVB_SIZE];
        uint32_t start_gen, block_gen, mount_gen, lvb_gen;
        int mounted_mode;
        int retries = 0;
@@ -857,7 +851,7 @@ locks_done:
         * lvb_gen will be non-zero.
         */
 
-       control_lvb_read(ls, &lvb_gen, lvb_bits);
+       control_lvb_read(ls, &lvb_gen, ls->ls_lvb_bits);
 
        if (lvb_gen == 0xFFFFFFFF) {
                /* special value to force mount attempts to fail */
@@ -887,7 +881,7 @@ locks_done:
         * and all lvb bits to be clear (no pending journal recoveries.)
         */
 
-       if (!all_jid_bits_clear(lvb_bits)) {
+       if (!all_jid_bits_clear(ls->ls_lvb_bits)) {
                /* journals need recovery, wait until all are clear */
                fs_info(sdp, "control_mount wait for journal recovery\n");
                goto restart;
@@ -949,7 +943,6 @@ static int dlm_recovery_wait(void *word)
 static int control_first_done(struct gfs2_sbd *sdp)
 {
        struct lm_lockstruct *ls = &sdp->sd_lockstruct;
-       char lvb_bits[GDLM_LVB_SIZE];
        uint32_t start_gen, block_gen;
        int error;
 
@@ -991,8 +984,8 @@ restart:
        memset(ls->ls_recover_result, 0, ls->ls_recover_size*sizeof(uint32_t));
        spin_unlock(&ls->ls_recover_spin);
 
-       memset(lvb_bits, 0, sizeof(lvb_bits));
-       control_lvb_write(ls, start_gen, lvb_bits);
+       memset(ls->ls_lvb_bits, 0, GDLM_LVB_SIZE);
+       control_lvb_write(ls, start_gen, ls->ls_lvb_bits);
 
        error = mounted_lock(sdp, DLM_LOCK_PR, DLM_LKF_CONVERT);
        if (error)
@@ -1022,6 +1015,12 @@ static int set_recover_size(struct gfs2_sbd *sdp, struct dlm_slot *slots,
        uint32_t old_size, new_size;
        int i, max_jid;
 
+       if (!ls->ls_lvb_bits) {
+               ls->ls_lvb_bits = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
+               if (!ls->ls_lvb_bits)
+                       return -ENOMEM;
+       }
+
        max_jid = 0;
        for (i = 0; i < num_slots; i++) {
                if (max_jid < slots[i].slot - 1)
@@ -1057,6 +1056,7 @@ static int set_recover_size(struct gfs2_sbd *sdp, struct dlm_slot *slots,
 
 static void free_recover_size(struct lm_lockstruct *ls)
 {
+       kfree(ls->ls_lvb_bits);
        kfree(ls->ls_recover_submit);
        kfree(ls->ls_recover_result);
        ls->ls_recover_submit = NULL;
@@ -1205,6 +1205,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
        ls->ls_recover_size = 0;
        ls->ls_recover_submit = NULL;
        ls->ls_recover_result = NULL;
+       ls->ls_lvb_bits = NULL;
 
        error = set_recover_size(sdp, NULL, 0);
        if (error)
index d1f51fd73f86eeb6fc136e176a8cd5cbdcac2af8..5a51265a4341df35fe0855db5f530a1e8e55771f 100644 (file)
@@ -576,7 +576,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
        RB_CLEAR_NODE(&ip->i_res->rs_node);
 out:
        up_write(&ip->i_rw_mutex);
-       return 0;
+       return error;
 }
 
 static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs)
@@ -1181,12 +1181,9 @@ int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
                             const struct gfs2_bitmap *bi, unsigned minlen, u64 *ptrimmed)
 {
        struct super_block *sb = sdp->sd_vfs;
-       struct block_device *bdev = sb->s_bdev;
-       const unsigned int sects_per_blk = sdp->sd_sb.sb_bsize /
-                                          bdev_logical_block_size(sb->s_bdev);
        u64 blk;
        sector_t start = 0;
-       sector_t nr_sects = 0;
+       sector_t nr_blks = 0;
        int rv;
        unsigned int x;
        u32 trimmed = 0;
@@ -1206,35 +1203,34 @@ int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
                if (diff == 0)
                        continue;
                blk = offset + ((bi->bi_start + x) * GFS2_NBBY);
-               blk *= sects_per_blk; /* convert to sectors */
                while(diff) {
                        if (diff & 1) {
-                               if (nr_sects == 0)
+                               if (nr_blks == 0)
                                        goto start_new_extent;
-                               if ((start + nr_sects) != blk) {
-                                       if (nr_sects >= minlen) {
-                                               rv = blkdev_issue_discard(bdev,
-                                                       start, nr_sects,
+                               if ((start + nr_blks) != blk) {
+                                       if (nr_blks >= minlen) {
+                                               rv = sb_issue_discard(sb,
+                                                       start, nr_blks,
                                                        GFP_NOFS, 0);
                                                if (rv)
                                                        goto fail;
-                                               trimmed += nr_sects;
+                                               trimmed += nr_blks;
                                        }
-                                       nr_sects = 0;
+                                       nr_blks = 0;
 start_new_extent:
                                        start = blk;
                                }
-                               nr_sects += sects_per_blk;
+                               nr_blks++;
                        }
                        diff >>= 2;
-                       blk += sects_per_blk;
+                       blk++;
                }
        }
-       if (nr_sects >= minlen) {
-               rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS, 0);
+       if (nr_blks >= minlen) {
+               rv = sb_issue_discard(sb, start, nr_blks, GFP_NOFS, 0);
                if (rv)
                        goto fail;
-               trimmed += nr_sects;
+               trimmed += nr_blks;
        }
        if (ptrimmed)
                *ptrimmed = trimmed;
index a94f0f779d5e3338281e3a1f5a0aaee6b16a01bc..fe0a76213d9eb6b39e291c415ccc4bf7af3a06e8 100644 (file)
@@ -533,7 +533,7 @@ void hfsplus_file_truncate(struct inode *inode)
                struct address_space *mapping = inode->i_mapping;
                struct page *page;
                void *fsdata;
-               u32 size = inode->i_size;
+               loff_t size = inode->i_size;
 
                res = pagecache_write_begin(NULL, mapping, size, 0,
                                                AOP_FLAG_UNINTERRUPTIBLE,
index 84e3d856e91d05c27aa182be0d28dead99128c93..523464e62849ccea755104d19e7ce39c2ca5fbfd 100644 (file)
@@ -110,7 +110,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
         * way when do_mmap_pgoff unwinds (may be important on powerpc
         * and ia64).
         */
-       vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND | VM_DONTDUMP;
+       vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND;
        vma->vm_ops = &hugetlb_vm_ops;
 
        if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT))
index f5f7c06c36fb159f89a793510c62f3f9170c3e4d..a898b3d43ccf3990986d51be3305bdc3e6d665ef 100644 (file)
@@ -725,7 +725,7 @@ void prune_icache_sb(struct super_block *sb, int nr_to_scan)
                 * inode to the back of the list so we don't spin on it.
                 */
                if (!spin_trylock(&inode->i_lock)) {
-                       list_move_tail(&inode->i_lru, &sb->s_inode_lru);
+                       list_move(&inode->i_lru, &sb->s_inode_lru);
                        continue;
                }
 
index d581e45c0a9fd6ada94edd2bb6ea4fe4c7fc9e23..341d3f564082f2367a7f1538255e90bdfbfd8cd2 100644 (file)
@@ -1690,7 +1690,7 @@ static int do_loopback(struct path *path, const char *old_name,
 
        if (IS_ERR(mnt)) {
                err = PTR_ERR(mnt);
-               goto out;
+               goto out2;
        }
 
        err = graft_tree(mnt, path);
index ac4fc9a8fdbc6c6133b186ddd5de476db9f03930..66b6664dcd4c4c9cd209d9420eb9de895cd1e344 100644 (file)
@@ -300,7 +300,7 @@ int nfs40_walk_client_list(struct nfs_client *new,
                           struct rpc_cred *cred)
 {
        struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
-       struct nfs_client *pos, *n, *prev = NULL;
+       struct nfs_client *pos, *prev = NULL;
        struct nfs4_setclientid_res clid = {
                .clientid       = new->cl_clientid,
                .confirm        = new->cl_confirm,
@@ -308,10 +308,23 @@ int nfs40_walk_client_list(struct nfs_client *new,
        int status = -NFS4ERR_STALE_CLIENTID;
 
        spin_lock(&nn->nfs_client_lock);
-       list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
+       list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
                /* If "pos" isn't marked ready, we can't trust the
                 * remaining fields in "pos" */
-               if (pos->cl_cons_state < NFS_CS_READY)
+               if (pos->cl_cons_state > NFS_CS_READY) {
+                       atomic_inc(&pos->cl_count);
+                       spin_unlock(&nn->nfs_client_lock);
+
+                       if (prev)
+                               nfs_put_client(prev);
+                       prev = pos;
+
+                       status = nfs_wait_client_init_complete(pos);
+                       spin_lock(&nn->nfs_client_lock);
+                       if (status < 0)
+                               continue;
+               }
+               if (pos->cl_cons_state != NFS_CS_READY)
                        continue;
 
                if (pos->rpc_ops != new->rpc_ops)
@@ -423,16 +436,16 @@ int nfs41_walk_client_list(struct nfs_client *new,
                           struct rpc_cred *cred)
 {
        struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
-       struct nfs_client *pos, *n, *prev = NULL;
+       struct nfs_client *pos, *prev = NULL;
        int status = -NFS4ERR_STALE_CLIENTID;
 
        spin_lock(&nn->nfs_client_lock);
-       list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
+       list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
                /* If "pos" isn't marked ready, we can't trust the
                 * remaining fields in "pos", especially the client
                 * ID and serverowner fields.  Wait for CREATE_SESSION
                 * to finish. */
-               if (pos->cl_cons_state < NFS_CS_READY) {
+               if (pos->cl_cons_state > NFS_CS_READY) {
                        atomic_inc(&pos->cl_count);
                        spin_unlock(&nn->nfs_client_lock);
 
@@ -440,18 +453,17 @@ int nfs41_walk_client_list(struct nfs_client *new,
                                nfs_put_client(prev);
                        prev = pos;
 
-                       nfs4_schedule_lease_recovery(pos);
                        status = nfs_wait_client_init_complete(pos);
-                       if (status < 0) {
-                               nfs_put_client(pos);
-                               spin_lock(&nn->nfs_client_lock);
-                               continue;
+                       if (status == 0) {
+                               nfs4_schedule_lease_recovery(pos);
+                               status = nfs4_wait_clnt_recover(pos);
                        }
-                       status = pos->cl_cons_state;
                        spin_lock(&nn->nfs_client_lock);
                        if (status < 0)
                                continue;
                }
+               if (pos->cl_cons_state != NFS_CS_READY)
+                       continue;
 
                if (pos->rpc_ops != new->rpc_ops)
                        continue;
@@ -469,17 +481,18 @@ int nfs41_walk_client_list(struct nfs_client *new,
                        continue;
 
                atomic_inc(&pos->cl_count);
-               spin_unlock(&nn->nfs_client_lock);
+               *result = pos;
+               status = 0;
                dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
                        __func__, pos, atomic_read(&pos->cl_count));
-
-               *result = pos;
-               return 0;
+               break;
        }
 
        /* No matching nfs_client found. */
        spin_unlock(&nn->nfs_client_lock);
        dprintk("NFS: <-- %s status = %d\n", __func__, status);
+       if (prev)
+               nfs_put_client(prev);
        return status;
 }
 #endif /* CONFIG_NFS_V4_1 */
index 26431cf62ddbc393fd5fe1e432742be37d06e12e..0ad025eb523bc6b651d82497c29a0d27ebdf3dac 100644 (file)
@@ -1046,6 +1046,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
                /* Save the delegation */
                nfs4_stateid_copy(&stateid, &delegation->stateid);
                rcu_read_unlock();
+               nfs_release_seqid(opendata->o_arg.seqid);
                ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode);
                if (ret != 0)
                        goto out;
index 6ace365c6334db844af0c2c3f221cd871ef3658c..d41a3518509fa5a0cf1dbbdcbed87f39fa3eff45 100644 (file)
@@ -1886,7 +1886,13 @@ again:
                        status = PTR_ERR(clnt);
                        break;
                }
-               clp->cl_rpcclient = clnt;
+               /* Note: this is safe because we haven't yet marked the
+                * client as ready, so we are the only user of
+                * clp->cl_rpcclient
+                */
+               clnt = xchg(&clp->cl_rpcclient, clnt);
+               rpc_shutdown_client(clnt);
+               clnt = clp->cl_rpcclient;
                goto again;
 
        case -NFS4ERR_MINOR_VERS_MISMATCH:
index 01168865dd37395a047cbeeb0175d7c8a5b80f88..a2720071f282f7607f13d63af8d6e9d6cf18bce6 100644 (file)
@@ -264,7 +264,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
                iattr->ia_valid |= ATTR_SIZE;
        }
        if (bmval[0] & FATTR4_WORD0_ACL) {
-               int nace;
+               u32 nace;
                struct nfs4_ace *ace;
 
                READ_BUF(4); len += 4;
index f7ed9ee46eb9d3818d2210c100731e5eda6ee35e..cbd0f1b324b972b96f036139fcd96bf53a03fb01 100644 (file)
@@ -143,6 +143,7 @@ static const char * const task_state_array[] = {
        "x (dead)",             /*  64 */
        "K (wakekill)",         /* 128 */
        "W (waking)",           /* 256 */
+       "P (parked)",           /* 512 */
 };
 
 static inline const char *get_task_state(struct task_struct *tsk)
index 4b3b3ffb52f14e234aa3ec99abde281ca41e1817..21e1a8f1659d097f455e196d0b775771d3904b2b 100644 (file)
@@ -755,37 +755,8 @@ void pde_put(struct proc_dir_entry *pde)
                free_proc_entry(pde);
 }
 
-/*
- * Remove a /proc entry and free it if it's not currently in use.
- */
-void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
+static void entry_rundown(struct proc_dir_entry *de)
 {
-       struct proc_dir_entry **p;
-       struct proc_dir_entry *de = NULL;
-       const char *fn = name;
-       unsigned int len;
-
-       spin_lock(&proc_subdir_lock);
-       if (__xlate_proc_name(name, &parent, &fn) != 0) {
-               spin_unlock(&proc_subdir_lock);
-               return;
-       }
-       len = strlen(fn);
-
-       for (p = &parent->subdir; *p; p=&(*p)->next ) {
-               if (proc_match(len, fn, *p)) {
-                       de = *p;
-                       *p = de->next;
-                       de->next = NULL;
-                       break;
-               }
-       }
-       spin_unlock(&proc_subdir_lock);
-       if (!de) {
-               WARN(1, "name '%s'\n", name);
-               return;
-       }
-
        spin_lock(&de->pde_unload_lock);
        /*
         * Stop accepting new callers into module. If you're
@@ -817,6 +788,40 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
                spin_lock(&de->pde_unload_lock);
        }
        spin_unlock(&de->pde_unload_lock);
+}
+
+/*
+ * Remove a /proc entry and free it if it's not currently in use.
+ */
+void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
+{
+       struct proc_dir_entry **p;
+       struct proc_dir_entry *de = NULL;
+       const char *fn = name;
+       unsigned int len;
+
+       spin_lock(&proc_subdir_lock);
+       if (__xlate_proc_name(name, &parent, &fn) != 0) {
+               spin_unlock(&proc_subdir_lock);
+               return;
+       }
+       len = strlen(fn);
+
+       for (p = &parent->subdir; *p; p=&(*p)->next ) {
+               if (proc_match(len, fn, *p)) {
+                       de = *p;
+                       *p = de->next;
+                       de->next = NULL;
+                       break;
+               }
+       }
+       spin_unlock(&proc_subdir_lock);
+       if (!de) {
+               WARN(1, "name '%s'\n", name);
+               return;
+       }
+
+       entry_rundown(de);
 
        if (S_ISDIR(de->mode))
                parent->nlink--;
@@ -827,3 +832,57 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
        pde_put(de);
 }
 EXPORT_SYMBOL(remove_proc_entry);
+
+int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
+{
+       struct proc_dir_entry **p;
+       struct proc_dir_entry *root = NULL, *de, *next;
+       const char *fn = name;
+       unsigned int len;
+
+       spin_lock(&proc_subdir_lock);
+       if (__xlate_proc_name(name, &parent, &fn) != 0) {
+               spin_unlock(&proc_subdir_lock);
+               return -ENOENT;
+       }
+       len = strlen(fn);
+
+       for (p = &parent->subdir; *p; p=&(*p)->next ) {
+               if (proc_match(len, fn, *p)) {
+                       root = *p;
+                       *p = root->next;
+                       root->next = NULL;
+                       break;
+               }
+       }
+       if (!root) {
+               spin_unlock(&proc_subdir_lock);
+               return -ENOENT;
+       }
+       de = root;
+       while (1) {
+               next = de->subdir;
+               if (next) {
+                       de->subdir = next->next;
+                       next->next = NULL;
+                       de = next;
+                       continue;
+               }
+               spin_unlock(&proc_subdir_lock);
+
+               entry_rundown(de);
+               next = de->parent;
+               if (S_ISDIR(de->mode))
+                       next->nlink--;
+               de->nlink = 0;
+               if (de == root)
+                       break;
+               pde_put(de);
+
+               spin_lock(&proc_subdir_lock);
+               de = next;
+       }
+       pde_put(root);
+       return 0;
+}
+EXPORT_SYMBOL(remove_proc_subtree);
index c196369fe4083128163ed66707d85cde1c0367fb..4cce1d9552fbbcd5f23447245a8b6f942c6fe89c 100644 (file)
@@ -187,8 +187,8 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset,
        if (dbuf->count == ARRAY_SIZE(dbuf->dentries))
                return -ENOSPC;
 
-       if (name[0] == '.' && (name[1] == '\0' ||
-                              (name[1] == '.' && name[2] == '\0')))
+       if (name[0] == '.' && (namelen < 2 ||
+                              (namelen == 2 && name[1] == '.')))
                return 0;
 
        dentry = lookup_one_len(name, dbuf->xadir, namelen);
index ac838b844936cdc29be5f3eff7192e9cb9a15582..f21acf0ef01f9535b7d3a576361c387593414747 100644 (file)
@@ -1568,6 +1568,12 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        c->remounting_rw = 1;
        c->ro_mount = 0;
 
+       if (c->space_fixup) {
+               err = ubifs_fixup_free_space(c);
+               if (err)
+                       return err;
+       }
+
        err = check_free_space(c);
        if (err)
                goto out;
@@ -1684,12 +1690,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
                err = dbg_check_space_info(c);
        }
 
-       if (c->space_fixup) {
-               err = ubifs_fixup_free_space(c);
-               if (err)
-                       goto out;
-       }
-
        mutex_unlock(&c->umount_mutex);
        return err;
 
index 25f01d0bc149cc388ce5a8e66d556669809e2b34..b1b1fa6ffffecce461a44945524d60d9b46dd54c 100644 (file)
@@ -99,7 +99,12 @@ struct mmu_gather {
        unsigned int            need_flush : 1, /* Did free PTEs */
                                fast_mode  : 1; /* No batching   */
 
-       unsigned int            fullmm;
+       /* we are in the middle of an operation to clear
+        * a full mm and can make some optimizations */
+       unsigned int            fullmm : 1,
+       /* we have performed an operation which
+        * requires a complete flush of the tlb */
+                               need_flush_all : 1;
 
        struct mmu_gather_batch *active;
        struct mmu_gather_batch local;
index bcbdd7484e581404d54be807c034fced32ba45c2..03053aca5b326c07d56f0022336fc9fc49927653 100644 (file)
@@ -152,15 +152,6 @@ void acpi_penalize_isa_irq(int irq, int active);
 
 void acpi_pci_irq_disable (struct pci_dev *dev);
 
-struct acpi_pci_driver {
-       struct list_head node;
-       int (*add)(struct acpi_pci_root *root);
-       void (*remove)(struct acpi_pci_root *root);
-};
-
-int acpi_pci_register_driver(struct acpi_pci_driver *driver);
-void acpi_pci_unregister_driver(struct acpi_pci_driver *driver);
-
 extern int ec_read(u8 addr, u8 *val);
 extern int ec_write(u8 addr, u8 val);
 extern int ec_transaction(u8 command,
index 8f7a3d68371a37314ab8263c078674fd79a8c5b5..ee0bd95240553576bf51672015c756aa0dea3b94 100644 (file)
@@ -954,7 +954,7 @@ static inline int atapi_cdb_len(const u16 *dev_id)
        }
 }
 
-static inline bool atapi_command_packet_set(const u16 *dev_id)
+static inline int atapi_command_packet_set(const u16 *dev_id)
 {
        return (dev_id[ATA_ID_CONFIG] >> 8) & 0x1f;
 }
index 0ea61e07a91c03053833faf3a4250e1f6023a10d..7c2e030e72f10542612ba34ce79b18f6b1b8ad06 100644 (file)
@@ -12,7 +12,6 @@
 
 struct blk_trace {
        int trace_state;
-       bool rq_based;
        struct rchan *rchan;
        unsigned long __percpu *sequence;
        unsigned char __percpu *msg_data;
index 98503b7923698e3b527dc278aa32d5db1da1dfe1..d9a4f7f40f329b22c81f86e31c72b259d4acb4bf 100644 (file)
@@ -35,6 +35,7 @@ struct cpu_vfs_cap_data {
 #define _KERNEL_CAP_T_SIZE     (sizeof(kernel_cap_t))
 
 
+struct file;
 struct inode;
 struct dentry;
 struct user_namespace;
@@ -211,6 +212,7 @@ extern bool capable(int cap);
 extern bool ns_capable(struct user_namespace *ns, int cap);
 extern bool nsown_capable(int cap);
 extern bool inode_capable(const struct inode *inode, int cap);
+extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
 
 /* audit system wants to get cap info from files as well */
 extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
index 76a87fb57ac258c4f004cee14737d8570da048f0..377cd8c3395eed02ac9f4dbadf7cac96dcf09de9 100644 (file)
@@ -141,11 +141,11 @@ typedef struct {
 } compat_sigset_t;
 
 struct compat_sigaction {
-#ifndef __ARCH_HAS_ODD_SIGACTION
+#ifndef __ARCH_HAS_IRIX_SIGACTION
        compat_uptr_t                   sa_handler;
        compat_ulong_t                  sa_flags;
 #else
-       compat_ulong_t                  sa_flags;
+       compat_uint_t                   sa_flags;
        compat_uptr_t                   sa_handler;
 #endif
 #ifdef __ARCH_HAS_SA_RESTORER
index e83ef39b3bea7359475d328aeed2e81d6b8926af..fe8c4476f7e4b36f4f7b4a778c73b8cfd77c2336 100644 (file)
@@ -213,7 +213,7 @@ struct devfreq_simple_ondemand_data {
 #endif
 
 #else /* !CONFIG_PM_DEVFREQ */
-static struct devfreq *devfreq_add_device(struct device *dev,
+static inline struct devfreq *devfreq_add_device(struct device *dev,
                                          struct devfreq_dev_profile *profile,
                                          const char *governor_name,
                                          void *data)
@@ -221,34 +221,34 @@ static struct devfreq *devfreq_add_device(struct device *dev,
        return NULL;
 }
 
-static int devfreq_remove_device(struct devfreq *devfreq)
+static inline int devfreq_remove_device(struct devfreq *devfreq)
 {
        return 0;
 }
 
-static int devfreq_suspend_device(struct devfreq *devfreq)
+static inline int devfreq_suspend_device(struct devfreq *devfreq)
 {
        return 0;
 }
 
-static int devfreq_resume_device(struct devfreq *devfreq)
+static inline int devfreq_resume_device(struct devfreq *devfreq)
 {
        return 0;
 }
 
-static struct opp *devfreq_recommended_opp(struct device *dev,
+static inline struct opp *devfreq_recommended_opp(struct device *dev,
                                           unsigned long *freq, u32 flags)
 {
-       return -EINVAL;
+       return ERR_PTR(-EINVAL);
 }
 
-static int devfreq_register_opp_notifier(struct device *dev,
+static inline int devfreq_register_opp_notifier(struct device *dev,
                                         struct devfreq *devfreq)
 {
        return -EINVAL;
 }
 
-static int devfreq_unregister_opp_notifier(struct device *dev,
+static inline int devfreq_unregister_opp_notifier(struct device *dev,
                                           struct devfreq *devfreq)
 {
        return -EINVAL;
index 9bf2f1fcae27789e54336f053fecabe4655b1fbd..3d7df3d32c662f20a2a7c1b661c9d89f5f4b9dd3 100644 (file)
@@ -333,6 +333,7 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
                                              unsigned long count,
                                              u64 *max_size,
                                              int *reset_type);
+typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long size);
 
 /*
  *  EFI Configuration Table and GUID definitions
@@ -575,9 +576,15 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos
 #ifdef CONFIG_X86
 extern void efi_late_init(void);
 extern void efi_free_boot_services(void);
+extern efi_status_t efi_query_variable_store(u32 attributes, unsigned long size);
 #else
 static inline void efi_late_init(void) {}
 static inline void efi_free_boot_services(void) {}
+
+static inline efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
+{
+       return EFI_SUCCESS;
+}
 #endif
 extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
 extern u64 efi_get_iobase (void);
@@ -731,7 +738,7 @@ struct efivar_operations {
        efi_get_variable_t *get_variable;
        efi_get_next_variable_t *get_next_variable;
        efi_set_variable_t *set_variable;
-       efi_query_variable_info_t *query_variable_info;
+       efi_query_variable_store_t *query_variable_store;
 };
 
 struct efivars {
index e5ca8ef50e9bf674e46fa58d7fff5f0424ab5bad..52da2a250795f3aefc3d2acc927a229f8a662d59 100644 (file)
@@ -89,6 +89,7 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip,
  *            that the call back has its own recursion protection. If it does
  *            not set this, then the ftrace infrastructure will add recursion
  *            protection for the caller.
+ * STUB   - The ftrace_ops is just a place holder.
  */
 enum {
        FTRACE_OPS_FL_ENABLED                   = 1 << 0,
@@ -98,6 +99,7 @@ enum {
        FTRACE_OPS_FL_SAVE_REGS                 = 1 << 4,
        FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED    = 1 << 5,
        FTRACE_OPS_FL_RECURSION_SAFE            = 1 << 6,
+       FTRACE_OPS_FL_STUB                      = 1 << 7,
 };
 
 struct ftrace_ops {
@@ -394,7 +396,6 @@ ssize_t ftrace_filter_write(struct file *file, const char __user *ubuf,
                            size_t cnt, loff_t *ppos);
 ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf,
                             size_t cnt, loff_t *ppos);
-loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int whence);
 int ftrace_regex_release(struct inode *inode, struct file *file);
 
 void __init
@@ -567,6 +568,8 @@ static inline int
 ftrace_regex_release(struct inode *inode, struct file *file) { return -ENODEV; }
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
+loff_t ftrace_filter_lseek(struct file *file, loff_t offset, int whence);
+
 /* totally disable ftrace - can not re-enable after this */
 void ftrace_kill(void);
 
index d2e6927bbaae1eb65b5b1dd2575643a5562e329a..d78d28a733b15afdc25a620ca5925f6619f82a2c 100644 (file)
@@ -200,6 +200,8 @@ extern size_t vmcoreinfo_max_size;
 
 int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
                unsigned long long *crash_size, unsigned long long *crash_base);
+int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
+               unsigned long long *crash_size, unsigned long long *crash_base);
 int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
                unsigned long long *crash_size, unsigned long long *crash_base);
 int crash_shrink_memory(unsigned long new_size);
index cad77fe09d770e47a03f8a802bd09fd30b3d136b..c13958251927d6c122c32795c712e8f994c29109 100644 (file)
@@ -518,7 +518,7 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data,
 int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
                           void *data, unsigned long len);
 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
-                             gpa_t gpa);
+                             gpa_t gpa, unsigned long len);
 int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
 int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len);
 struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
index fa7cc7244cbdbf019591f644e42622145c8dd28b..b0bcce0ddc95a531dd30c30e91a89c92e961b8d4 100644 (file)
@@ -71,6 +71,7 @@ struct gfn_to_hva_cache {
        u64 generation;
        gpa_t gpa;
        unsigned long hva;
+       unsigned long len;
        struct kvm_memory_slot *memslot;
 };
 
index 91c9d109e5f17bf39c88904cfaa635e132999c9e..eae7a053dc5141d062a80bb4055449520bac61cf 100644 (file)
@@ -398,6 +398,7 @@ enum {
        ATA_HORKAGE_NOSETXFER   = (1 << 14),    /* skip SETXFER, SATA only */
        ATA_HORKAGE_BROKEN_FPDMA_AA     = (1 << 15),    /* skip AA */
        ATA_HORKAGE_DUMP_ID     = (1 << 16),    /* dump IDENTIFY data */
+       ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17),  /* Set max sects to 65535 */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
index e19ff30ad0a21453cece0df7524d0b336a69078f..e2091b88d24c972be51d80e1f110ad03c50d8902 100644 (file)
@@ -1611,6 +1611,8 @@ int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
                        unsigned long pfn);
 int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
                        unsigned long pfn);
+int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len);
+
 
 struct page *follow_page_mask(struct vm_area_struct *vma,
                              unsigned long address, unsigned int foll_flags,
index ce93a341337d48a78b5449ea249aac04c3f8284d..20c2d6dd5d259f6467baf0939e6837ed85e936b3 100644 (file)
@@ -13,14 +13,14 @@ struct msi_msg {
 /* Helper functions */
 struct irq_data;
 struct msi_desc;
-extern void mask_msi_irq(struct irq_data *data);
-extern void unmask_msi_irq(struct irq_data *data);
-extern void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
-extern void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
-extern void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
-extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
-extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
-extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
+void mask_msi_irq(struct irq_data *data);
+void unmask_msi_irq(struct irq_data *data);
+void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+void read_msi_msg(unsigned int irq, struct msi_msg *msg);
+void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
+void write_msi_msg(unsigned int irq, struct msi_msg *msg);
 
 struct msi_desc {
        struct {
@@ -54,9 +54,8 @@ struct msi_desc {
  */
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
 void arch_teardown_msi_irq(unsigned int irq);
-extern int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
-extern void arch_teardown_msi_irqs(struct pci_dev *dev);
-extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
-
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
+void arch_teardown_msi_irqs(struct pci_dev *dev);
+int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
 
 #endif /* LINUX_MSI_H */
index 9121595a8ebfe14a1d2330c79454f4b53a088669..433da8a1a42642ce33596b536f2dcaad4427b3ac 100644 (file)
@@ -53,6 +53,9 @@ struct mutex {
 #if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
        struct task_struct      *owner;
 #endif
+#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
+       void                    *spin_mlock;    /* Spinner MCS lock */
+#endif
 #ifdef CONFIG_DEBUG_MUTEXES
        const char              *name;
        void                    *magic;
index b3d00fa4b3149b614365dd215a611ed638fdb924..6151e903eef0a4a380ca03cb24f26e5121543758 100644 (file)
@@ -210,9 +210,9 @@ struct netdev_hw_addr {
 #define NETDEV_HW_ADDR_T_SLAVE         3
 #define NETDEV_HW_ADDR_T_UNICAST       4
 #define NETDEV_HW_ADDR_T_MULTICAST     5
-       bool                    synced;
        bool                    global_use;
        int                     refcount;
+       int                     synced;
        struct rcu_head         rcu_head;
 };
 
@@ -895,7 +895,7 @@ struct netdev_fcoe_hbainfo {
  *
  * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh)
  * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
- *                          struct net_device *dev)
+ *                          struct net_device *dev, u32 filter_mask)
  *
  * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier);
  *     Called to change device carrier. Soft-devices (like dummy, team, etc)
index 01d25e6fc792472692f6e601de77a7b83fe69734..0214c4c146faab0dad0a339dcd098124245dbe37 100644 (file)
@@ -291,6 +291,7 @@ ip_set_hash_destroy(struct ip_set *set)
 #define type_pf_data_tlist     TOKEN(TYPE, PF, _data_tlist)
 #define type_pf_data_next      TOKEN(TYPE, PF, _data_next)
 #define type_pf_data_flags     TOKEN(TYPE, PF, _data_flags)
+#define type_pf_data_reset_flags TOKEN(TYPE, PF, _data_reset_flags)
 #ifdef IP_SET_HASH_WITH_NETS
 #define type_pf_data_match     TOKEN(TYPE, PF, _data_match)
 #else
@@ -385,9 +386,9 @@ type_pf_resize(struct ip_set *set, bool retried)
        struct ip_set_hash *h = set->data;
        struct htable *t, *orig = h->table;
        u8 htable_bits = orig->htable_bits;
-       const struct type_pf_elem *data;
+       struct type_pf_elem *data;
        struct hbucket *n, *m;
-       u32 i, j;
+       u32 i, j, flags = 0;
        int ret;
 
 retry:
@@ -412,9 +413,16 @@ retry:
                n = hbucket(orig, i);
                for (j = 0; j < n->pos; j++) {
                        data = ahash_data(n, j);
+#ifdef IP_SET_HASH_WITH_NETS
+                       flags = 0;
+                       type_pf_data_reset_flags(data, &flags);
+#endif
                        m = hbucket(t, HKEY(data, h->initval, htable_bits));
-                       ret = type_pf_elem_add(m, data, AHASH_MAX(h), 0);
+                       ret = type_pf_elem_add(m, data, AHASH_MAX(h), flags);
                        if (ret < 0) {
+#ifdef IP_SET_HASH_WITH_NETS
+                               type_pf_data_flags(data, flags);
+#endif
                                read_unlock_bh(&set->lock);
                                ahash_destroy(t);
                                if (ret == -EAGAIN)
@@ -836,9 +844,9 @@ type_pf_tresize(struct ip_set *set, bool retried)
        struct ip_set_hash *h = set->data;
        struct htable *t, *orig = h->table;
        u8 htable_bits = orig->htable_bits;
-       const struct type_pf_elem *data;
+       struct type_pf_elem *data;
        struct hbucket *n, *m;
-       u32 i, j;
+       u32 i, j, flags = 0;
        int ret;
 
        /* Try to cleanup once */
@@ -873,10 +881,17 @@ retry:
                n = hbucket(orig, i);
                for (j = 0; j < n->pos; j++) {
                        data = ahash_tdata(n, j);
+#ifdef IP_SET_HASH_WITH_NETS
+                       flags = 0;
+                       type_pf_data_reset_flags(data, &flags);
+#endif
                        m = hbucket(t, HKEY(data, h->initval, htable_bits));
-                       ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 0,
-                                               ip_set_timeout_get(type_pf_data_timeout(data)));
+                       ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), flags,
+                               ip_set_timeout_get(type_pf_data_timeout(data)));
                        if (ret < 0) {
+#ifdef IP_SET_HASH_WITH_NETS
+                               type_pf_data_flags(data, flags);
+#endif
                                read_unlock_bh(&set->lock);
                                ahash_destroy(t);
                                if (ret == -EAGAIN)
@@ -1187,6 +1202,7 @@ type_pf_gc_init(struct ip_set *set)
 #undef type_pf_data_tlist
 #undef type_pf_data_next
 #undef type_pf_data_flags
+#undef type_pf_data_reset_flags
 #undef type_pf_data_match
 
 #undef type_pf_elem
index 9a22b5efb384a5247e57319222ba05f883fed25a..81b31613eb252b3a46052d2375e333affc91c77f 100644 (file)
@@ -41,8 +41,37 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
 
        return DEVICE_ACPI_HANDLE(dev);
 }
+
+void acpi_pci_add_bus(struct pci_bus *bus);
+void acpi_pci_remove_bus(struct pci_bus *bus);
+
+#ifdef CONFIG_ACPI_PCI_SLOT
+void acpi_pci_slot_init(void);
+void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle);
+void acpi_pci_slot_remove(struct pci_bus *bus);
+#else
+static inline void acpi_pci_slot_init(void) { }
+static inline void acpi_pci_slot_enumerate(struct pci_bus *bus,
+                                          acpi_handle handle) { }
+static inline void acpi_pci_slot_remove(struct pci_bus *bus) { }
 #endif
 
+#ifdef CONFIG_HOTPLUG_PCI_ACPI
+void acpiphp_init(void);
+void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle);
+void acpiphp_remove_slots(struct pci_bus *bus);
+#else
+static inline void acpiphp_init(void) { }
+static inline void acpiphp_enumerate_slots(struct pci_bus *bus,
+                                          acpi_handle handle) { }
+static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
+#endif
+
+#else  /* CONFIG_ACPI */
+static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
+static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
+#endif /* CONFIG_ACPI */
+
 #ifdef CONFIG_ACPI_APEI
 extern bool aer_acpi_firmware_first(void);
 #else
index c8320144fe790cc3fb8dc5fe593092412a838bae..8af4610c2e414963a62e4522b482afa700ec4532 100644 (file)
 #define PCIE_LINK_STATE_CLKPM  4
 
 #ifdef CONFIG_PCIEASPM
-extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
-extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
-extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
-extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
-extern void pci_disable_link_state(struct pci_dev *pdev, int state);
-extern void pci_disable_link_state_locked(struct pci_dev *pdev, int state);
-extern void pcie_clear_aspm(struct pci_bus *bus);
-extern void pcie_no_aspm(void);
+void pcie_aspm_init_link_state(struct pci_dev *pdev);
+void pcie_aspm_exit_link_state(struct pci_dev *pdev);
+void pcie_aspm_pm_state_change(struct pci_dev *pdev);
+void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
+void pci_disable_link_state(struct pci_dev *pdev, int state);
+void pci_disable_link_state_locked(struct pci_dev *pdev, int state);
+void pcie_clear_aspm(struct pci_bus *bus);
+void pcie_no_aspm(void);
 #else
 static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
 {
@@ -56,8 +56,8 @@ static inline void pcie_no_aspm(void)
 #endif
 
 #ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
-extern void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
-extern void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
+void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
+void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
 #else
 static inline void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
 {
index 7ef68724f0f054f88427d2dbc18c63b962a16394..68bcefd7fca002a89446603d4fc894e6de2b24b0 100644 (file)
@@ -14,9 +14,9 @@ struct pci_ats {
 
 #ifdef CONFIG_PCI_ATS
 
-extern int pci_enable_ats(struct pci_dev *dev, int ps);
-extern void pci_disable_ats(struct pci_dev *dev);
-extern int pci_ats_queue_depth(struct pci_dev *dev);
+int pci_enable_ats(struct pci_dev *dev, int ps);
+void pci_disable_ats(struct pci_dev *dev);
+int pci_ats_queue_depth(struct pci_dev *dev);
 
 /**
  * pci_ats_enabled - query the ATS status
@@ -54,12 +54,12 @@ static inline int pci_ats_enabled(struct pci_dev *dev)
 
 #ifdef CONFIG_PCI_PRI
 
-extern int  pci_enable_pri(struct pci_dev *pdev, u32 reqs);
-extern void pci_disable_pri(struct pci_dev *pdev);
-extern bool pci_pri_enabled(struct pci_dev *pdev);
-extern int  pci_reset_pri(struct pci_dev *pdev);
-extern bool pci_pri_stopped(struct pci_dev *pdev);
-extern int  pci_pri_status(struct pci_dev *pdev);
+int pci_enable_pri(struct pci_dev *pdev, u32 reqs);
+void pci_disable_pri(struct pci_dev *pdev);
+bool pci_pri_enabled(struct pci_dev *pdev);
+int pci_reset_pri(struct pci_dev *pdev);
+bool pci_pri_stopped(struct pci_dev *pdev);
+int pci_pri_status(struct pci_dev *pdev);
 
 #else /* CONFIG_PCI_PRI */
 
@@ -95,10 +95,10 @@ static inline int pci_pri_status(struct pci_dev *pdev)
 
 #ifdef CONFIG_PCI_PASID
 
-extern int pci_enable_pasid(struct pci_dev *pdev, int features);
-extern void pci_disable_pasid(struct pci_dev *pdev);
-extern int pci_pasid_features(struct pci_dev *pdev);
-extern int pci_max_pasids(struct pci_dev *pdev);
+int pci_enable_pasid(struct pci_dev *pdev, int features);
+void pci_disable_pasid(struct pci_dev *pdev);
+int pci_pasid_features(struct pci_dev *pdev);
+int pci_max_pasids(struct pci_dev *pdev);
 
 #else  /* CONFIG_PCI_PASID */
 
index 2461033a798728203f456eff4d6a0099816a7072..e73dfa308b876ca30246d984669c675f93bdd9b4 100644 (file)
 /* Include the ID list */
 #include <linux/pci_ids.h>
 
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices.  The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ *     7:3 = slot
+ *     2:0 = function
+ * PCI_DEVFN(), PCI_SLOT(), and PCI_FUNC() are defined uapi/linux/pci.h
+ * In the interest of not exposing interfaces to user-space unnecessarily,
+ * the following kernel only defines are being added here.
+ */
+#define PCI_DEVID(bus, devfn)  ((((u16)bus) << 8) | devfn)
+/* return bus from PCI devid = ((u16)bus_number) << 8) | devfn */
+#define PCI_BUS_NUM(x) (((x) >> 8) & 0xff)
+
 /* pci_slot represents a physical slot */
 struct pci_slot {
        struct pci_bus *bus;            /* The bus this slot is on */
@@ -232,6 +247,8 @@ struct pci_dev {
        u8              revision;       /* PCI revision, low byte of class word */
        u8              hdr_type;       /* PCI header type (`multi' flag masked out) */
        u8              pcie_cap;       /* PCI-E capability offset */
+       u8              msi_cap;        /* MSI capability offset */
+       u8              msix_cap;       /* MSI-X capability offset */
        u8              pcie_mpss:3;    /* PCI-E Max Payload Size Supported */
        u8              rom_base_reg;   /* which config register controls the ROM */
        u8              pin;            /* which interrupt pin this device uses */
@@ -249,8 +266,7 @@ struct pci_dev {
        pci_power_t     current_state;  /* Current operating state. In ACPI-speak,
                                           this is D0-D3, D0 being fully functional,
                                           and D3 being off. */
-       int             pm_cap;         /* PM capability offset in the
-                                          configuration space */
+       u8              pm_cap;         /* PM capability offset */
        unsigned int    pme_support:5;  /* Bitmask of states from which PME#
                                           can be generated */
        unsigned int    pme_interrupt:1;
@@ -348,7 +364,7 @@ static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
        return dev;
 }
 
-extern struct pci_dev *alloc_pci_dev(void);
+struct pci_dev *alloc_pci_dev(void);
 
 #define        to_pci_dev(n) container_of(n, struct pci_dev, dev)
 #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
@@ -504,10 +520,10 @@ struct pci_ops {
  * ACPI needs to be able to access PCI config space before we've done a
  * PCI bus scan and created pci_bus structures.
  */
-extern int raw_pci_read(unsigned int domain, unsigned int bus,
-                       unsigned int devfn, int reg, int len, u32 *val);
-extern int raw_pci_write(unsigned int domain, unsigned int bus,
-                       unsigned int devfn, int reg, int len, u32 val);
+int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
+                int reg, int len, u32 *val);
+int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
+                 int reg, int len, u32 val);
 
 struct pci_bus_region {
        resource_size_t start;
@@ -658,7 +674,7 @@ struct pci_driver {
 /* these external functions are only available when PCI support is enabled */
 #ifdef CONFIG_PCI
 
-extern void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss);
+void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss);
 
 enum pcie_bus_config_types {
        PCIE_BUS_TUNE_OFF,
@@ -675,9 +691,11 @@ extern struct bus_type pci_bus_type;
  * code, or pci core code. */
 extern struct list_head pci_root_buses;        /* list of all known PCI buses */
 /* Some device drivers need know if pci is initiated */
-extern int no_pci_devices(void);
+int no_pci_devices(void);
 
 void pcibios_resource_survey_bus(struct pci_bus *bus);
+void pcibios_add_bus(struct pci_bus *bus);
+void pcibios_remove_bus(struct pci_bus *bus);
 void pcibios_fixup_bus(struct pci_bus *);
 int __must_check pcibios_enable_device(struct pci_dev *, int mask);
 /* Architecture specific versions may override this (weak) */
@@ -699,7 +717,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
 void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
                             struct pci_bus_region *region);
 void pcibios_scan_specific_bus(int busn);
-extern struct pci_bus *pci_find_bus(int domain, int busnr);
+struct pci_bus *pci_find_bus(int domain, int busnr);
 void pci_bus_add_devices(const struct pci_bus *bus);
 struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
                                      struct pci_ops *ops, void *sysdata);
@@ -732,14 +750,14 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev,
 u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin);
 int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
 u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp);
-extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
-extern void pci_dev_put(struct pci_dev *dev);
-extern void pci_remove_bus(struct pci_bus *b);
-extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
+struct pci_dev *pci_dev_get(struct pci_dev *dev);
+void pci_dev_put(struct pci_dev *dev);
+void pci_remove_bus(struct pci_bus *b);
+void pci_stop_and_remove_bus_device(struct pci_dev *dev);
 void pci_stop_root_bus(struct pci_bus *bus);
 void pci_remove_root_bus(struct pci_bus *bus);
 void pci_setup_cardbus(struct pci_bus *bus);
-extern void pci_sort_breadthfirst(void);
+void pci_sort_breadthfirst(void);
 #define dev_is_pci(d) ((d)->bus == &pci_bus_type)
 #define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)->is_physfn : false))
 #define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf(to_pci_dev(d)) : 0))
@@ -916,6 +934,7 @@ void pci_disable_rom(struct pci_dev *pdev);
 void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
 void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
 size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size);
+void __iomem __must_check *pci_platform_rom(struct pci_dev *pdev, size_t *size);
 
 /* Power management related routines */
 int pci_save_state(struct pci_dev *dev);
@@ -1141,18 +1160,17 @@ static inline int pci_msi_enabled(void)
        return 0;
 }
 #else
-extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
-extern int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec);
-extern void pci_msi_shutdown(struct pci_dev *dev);
-extern void pci_disable_msi(struct pci_dev *dev);
-extern int pci_msix_table_size(struct pci_dev *dev);
-extern int pci_enable_msix(struct pci_dev *dev,
-       struct msix_entry *entries, int nvec);
-extern void pci_msix_shutdown(struct pci_dev *dev);
-extern void pci_disable_msix(struct pci_dev *dev);
-extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
-extern void pci_restore_msi_state(struct pci_dev *dev);
-extern int pci_msi_enabled(void);
+int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
+int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec);
+void pci_msi_shutdown(struct pci_dev *dev);
+void pci_disable_msi(struct pci_dev *dev);
+int pci_msix_table_size(struct pci_dev *dev);
+int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec);
+void pci_msix_shutdown(struct pci_dev *dev);
+void pci_disable_msix(struct pci_dev *dev);
+void msi_remove_pci_irq_vectors(struct pci_dev *dev);
+void pci_restore_msi_state(struct pci_dev *dev);
+int pci_msi_enabled(void);
 #endif
 
 #ifdef CONFIG_PCIEPORTBUS
@@ -1167,8 +1185,8 @@ extern bool pcie_ports_auto;
 static inline int pcie_aspm_enabled(void) { return 0; }
 static inline bool pcie_aspm_support_enabled(void) { return false; }
 #else
-extern int pcie_aspm_enabled(void);
-extern bool pcie_aspm_support_enabled(void);
+int pcie_aspm_enabled(void);
+bool pcie_aspm_support_enabled(void);
 #endif
 
 #ifdef CONFIG_PCIEAER
@@ -1186,8 +1204,8 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev)
 }
 static inline void pcie_ecrc_get_policy(char *str) {};
 #else
-extern void pcie_set_ecrc_checking(struct pci_dev *dev);
-extern void pcie_ecrc_get_policy(char *str);
+void pcie_set_ecrc_checking(struct pci_dev *dev);
+void pcie_ecrc_get_policy(char *str);
 #endif
 
 #define pci_enable_msi(pdev)   pci_enable_msi_block(pdev, 1)
@@ -1198,9 +1216,9 @@ int  ht_create_irq(struct pci_dev *dev, int idx);
 void ht_destroy_irq(unsigned int irq);
 #endif /* CONFIG_HT_IRQ */
 
-extern void pci_cfg_access_lock(struct pci_dev *dev);
-extern bool pci_cfg_access_trylock(struct pci_dev *dev);
-extern void pci_cfg_access_unlock(struct pci_dev *dev);
+void pci_cfg_access_lock(struct pci_dev *dev);
+bool pci_cfg_access_trylock(struct pci_dev *dev);
+void pci_cfg_access_unlock(struct pci_dev *dev);
 
 /*
  * PCI domain support.  Sometimes called PCI segment (eg by ACPI),
@@ -1225,7 +1243,7 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 /* some architectures require additional setup to direct VGA traffic */
 typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
                      unsigned int command_bits, u32 flags);
-extern void pci_register_set_vga_state(arch_set_vga_state_t func);
+void pci_register_set_vga_state(arch_set_vga_state_t func);
 
 #else /* CONFIG_PCI is not enabled */
 
@@ -1627,8 +1645,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev,
 int pcibios_add_device(struct pci_dev *dev);
 
 #ifdef CONFIG_PCI_MMCONFIG
-extern void __init pci_mmcfg_early_init(void);
-extern void __init pci_mmcfg_late_init(void);
+void __init pci_mmcfg_early_init(void);
+void __init pci_mmcfg_late_init(void);
 #else
 static inline void pci_mmcfg_early_init(void) { }
 static inline void pci_mmcfg_late_init(void) { }
@@ -1639,12 +1657,12 @@ int pci_ext_cfg_avail(void);
 void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
 
 #ifdef CONFIG_PCI_IOV
-extern int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
-extern void pci_disable_sriov(struct pci_dev *dev);
-extern irqreturn_t pci_sriov_migration(struct pci_dev *dev);
-extern int pci_num_vf(struct pci_dev *dev);
-extern int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
-extern int pci_sriov_get_totalvfs(struct pci_dev *dev);
+int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
+void pci_disable_sriov(struct pci_dev *dev);
+irqreturn_t pci_sriov_migration(struct pci_dev *dev);
+int pci_num_vf(struct pci_dev *dev);
+int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
+int pci_sriov_get_totalvfs(struct pci_dev *dev);
 #else
 static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
 {
@@ -1672,8 +1690,8 @@ static inline int pci_sriov_get_totalvfs(struct pci_dev *dev)
 #endif
 
 #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
-extern void pci_hp_create_module_link(struct pci_slot *pci_slot);
-extern void pci_hp_remove_module_link(struct pci_slot *pci_slot);
+void pci_hp_create_module_link(struct pci_slot *pci_slot);
+void pci_hp_remove_module_link(struct pci_slot *pci_slot);
 #endif
 
 /**
@@ -1817,13 +1835,13 @@ int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
 /* PCI <-> OF binding helpers */
 #ifdef CONFIG_OF
 struct device_node;
-extern void pci_set_of_node(struct pci_dev *dev);
-extern void pci_release_of_node(struct pci_dev *dev);
-extern void pci_set_bus_of_node(struct pci_bus *bus);
-extern void pci_release_bus_of_node(struct pci_bus *bus);
+void pci_set_of_node(struct pci_dev *dev);
+void pci_release_of_node(struct pci_dev *dev);
+void pci_set_bus_of_node(struct pci_bus *bus);
+void pci_release_bus_of_node(struct pci_bus *bus);
 
 /* Arch may override this (weak) */
-extern struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus);
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
 
 static inline struct device_node *
 pci_device_to_OF_node(const struct pci_dev *pdev)
index 45fc162cbdc06b0d3d0320c50575b14b5a8b5828..8db71dcd633740a8a7290aff4a99f6a23ee8e366 100644 (file)
@@ -125,12 +125,12 @@ static inline const char *hotplug_slot_name(const struct hotplug_slot *slot)
        return pci_slot_name(slot->pci_slot);
 }
 
-extern int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus,
-                            int nr, const char *name,
-                            struct module *owner, const char *mod_name);
-extern int pci_hp_deregister(struct hotplug_slot *slot);
-extern int __must_check pci_hp_change_slot_info        (struct hotplug_slot *slot,
-                                                struct hotplug_slot_info *info);
+int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus, int nr,
+                     const char *name, struct module *owner,
+                     const char *mod_name);
+int pci_hp_deregister(struct hotplug_slot *slot);
+int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
+                                        struct hotplug_slot_info *info);
 
 /* use a define to avoid include chaining to get THIS_MODULE & friends */
 #define pci_hp_register(slot, pbus, devnr, name) \
index f11c1c2609d53ded1135b6289845f2ddd5e701da..a80f9e6ce9e54dac2c3a49d1f896453c5a0fb271 100644 (file)
 #define PCI_SUBDEVICE_ID_KEYSPAN_SX2   0x5334
 
 #define PCI_VENDOR_ID_MARVELL          0x11ab
+#define PCI_VENDOR_ID_MARVELL_EXT      0x1b4b
 #define PCI_DEVICE_ID_MARVELL_GT64111  0x4146
 #define PCI_DEVICE_ID_MARVELL_GT64260  0x6430
 #define PCI_DEVICE_ID_MARVELL_MV64360  0x6460
index e6f91b1406d8e323a600baac1e11c27108103520..9572669eea9758003fba426128def92d6d211ef0 100644 (file)
@@ -62,7 +62,7 @@ struct pcie_port_service_driver {
 #define to_service_driver(d) \
        container_of(d, struct pcie_port_service_driver, driver)
 
-extern int pcie_port_service_register(struct pcie_port_service_driver *new);
-extern void pcie_port_service_unregister(struct pcie_port_service_driver *new);
+int pcie_port_service_register(struct pcie_port_service_driver *new);
+void pcie_port_service_unregister(struct pcie_port_service_driver *new);
 
 #endif /* _PCIEPORT_IF_H_ */
diff --git a/include/linux/platform_data/video-vt8500lcdfb.h b/include/linux/platform_data/video-vt8500lcdfb.h
deleted file mode 100644 (file)
index 7f399c3..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  VT8500/WM8505 Frame Buffer platform data definitions
- *
- *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _VT8500FB_H
-#define _VT8500FB_H
-
-#include <linux/fb.h>
-
-struct vt8500fb_platform_data {
-       struct fb_videomode     mode;
-       u32                     xres_virtual;
-       u32                     yres_virtual;
-       u32                     bpp;
-       unsigned long           video_mem_phys;
-       void                    *video_mem_virt;
-       unsigned long           video_mem_len;
-};
-
-#endif /* _VT8500FB_H */
diff --git a/include/linux/platform_data/video_s3c.h b/include/linux/platform_data/video_s3c.h
new file mode 100644 (file)
index 0000000..4888399
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __PLATFORM_DATA_VIDEO_S3C
+#define __PLATFORM_DATA_VIDEO_S3C
+
+/* S3C_FB_MAX_WIN
+ * Set to the maximum number of windows that any of the supported hardware
+ * can use. Since the platform data uses this for an array size, having it
+ * set to the maximum of any version of the hardware can do is safe.
+ */
+#define S3C_FB_MAX_WIN (5)
+
+/**
+ * struct s3c_fb_pd_win - per window setup data
+ * @xres     : The window X size.
+ * @yres     : The window Y size.
+ * @virtual_x: The virtual X size.
+ * @virtual_y: The virtual Y size.
+ */
+struct s3c_fb_pd_win {
+       unsigned short          default_bpp;
+       unsigned short          max_bpp;
+       unsigned short          xres;
+       unsigned short          yres;
+       unsigned short          virtual_x;
+       unsigned short          virtual_y;
+};
+
+/**
+ * struct s3c_fb_platdata -  S3C driver platform specific information
+ * @setup_gpio: Setup the external GPIO pins to the right state to transfer
+ *             the data from the display system to the connected display
+ *             device.
+ * @vidcon0: The base vidcon0 values to control the panel data format.
+ * @vidcon1: The base vidcon1 values to control the panel data output.
+ * @vtiming: Video timing when connected to a RGB type panel.
+ * @win: The setup data for each hardware window, or NULL for unused.
+ * @display_mode: The LCD output display mode.
+ *
+ * The platform data supplies the video driver with all the information
+ * it requires to work with the display(s) attached to the machine. It
+ * controls the initial mode, the number of display windows (0 is always
+ * the base framebuffer) that are initialised etc.
+ *
+ */
+struct s3c_fb_platdata {
+       void    (*setup_gpio)(void);
+
+       struct s3c_fb_pd_win    *win[S3C_FB_MAX_WIN];
+       struct fb_videomode     *vtiming;
+
+       u32                      vidcon0;
+       u32                      vidcon1;
+};
+
+#endif
index 5a710b9c578e2881478872d505e8b649e8bdb55f..87a03c746f177be0b4ddc0dee6a61860d596ff3d 100644 (file)
@@ -93,14 +93,20 @@ do { \
 
 #else /* !CONFIG_PREEMPT_COUNT */
 
-#define preempt_disable()              do { } while (0)
-#define sched_preempt_enable_no_resched()      do { } while (0)
-#define preempt_enable_no_resched()    do { } while (0)
-#define preempt_enable()               do { } while (0)
-
-#define preempt_disable_notrace()              do { } while (0)
-#define preempt_enable_no_resched_notrace()    do { } while (0)
-#define preempt_enable_notrace()               do { } while (0)
+/*
+ * Even if we don't have any preemption, we need preempt disable/enable
+ * to be barriers, so that we don't have things like get_user/put_user
+ * that can cause faults and scheduling migrate into our preempt-protected
+ * region.
+ */
+#define preempt_disable()              barrier()
+#define sched_preempt_enable_no_resched()      barrier()
+#define preempt_enable_no_resched()    barrier()
+#define preempt_enable()               barrier()
+
+#define preempt_disable_notrace()              barrier()
+#define preempt_enable_no_resched_notrace()    barrier()
+#define preempt_enable_notrace()               barrier()
 
 #endif /* CONFIG_PREEMPT_COUNT */
 
index 8307f2f94d860f46139b6a20d6795a9186704c19..94dfb2aa5533c3c6a2a661358a6da4c6555310d3 100644 (file)
@@ -117,6 +117,7 @@ struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
                                const struct file_operations *proc_fops,
                                void *data);
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
+extern int remove_proc_subtree(const char *name, struct proc_dir_entry *parent);
 
 struct pid_namespace;
 
@@ -202,6 +203,7 @@ static inline struct proc_dir_entry *proc_create_data(const char *name,
        return NULL;
 }
 #define remove_proc_entry(name, parent) do {} while (0)
+#define remove_proc_subtree(name, parent) do {} while (0)
 
 static inline struct proc_dir_entry *proc_symlink(const char *name,
                struct proc_dir_entry *parent,const char *dest) {return NULL;}
index d35d2b6ddbfb69f098b1660fe280b4d2da8a5ffe..2d02c76a01becadace5eea683910cb7afcac53c1 100644 (file)
@@ -163,9 +163,10 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
 #define TASK_DEAD              64
 #define TASK_WAKEKILL          128
 #define TASK_WAKING            256
-#define TASK_STATE_MAX         512
+#define TASK_PARKED            512
+#define TASK_STATE_MAX         1024
 
-#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW"
+#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP"
 
 extern char ___assert_task_state[1 - 2*!!(
                sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)];
@@ -320,7 +321,6 @@ extern signed long schedule_timeout_killable(signed long timeout);
 extern signed long schedule_timeout_uninterruptible(signed long timeout);
 asmlinkage void schedule(void);
 extern void schedule_preempt_disabled(void);
-extern int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner);
 
 struct nsproxy;
 struct user_namespace;
index eee7478cda701ddeabc00150f607f368a4239350..032c366ef1c62b203134e386ad1bc8a92a6c31fe 100644 (file)
@@ -1012,6 +1012,10 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     This hook can be used by the module to update any security state
  *     associated with the TUN device's security structure.
  *     @security pointer to the TUN devices's security structure.
+ * @skb_owned_by:
+ *     This hook sets the packet's owning sock.
+ *     @skb is the packet.
+ *     @sk the sock which owns the packet.
  *
  * Security hooks for XFRM operations.
  *
@@ -1638,6 +1642,7 @@ struct security_operations {
        int (*tun_dev_attach_queue) (void *security);
        int (*tun_dev_attach) (struct sock *sk, void *security);
        int (*tun_dev_open) (void *security);
+       void (*skb_owned_by) (struct sk_buff *skb, struct sock *sk);
 #endif /* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2588,6 +2593,8 @@ int security_tun_dev_attach_queue(void *security);
 int security_tun_dev_attach(struct sock *sk, void *security);
 int security_tun_dev_open(void *security);
 
+void security_skb_owned_by(struct sk_buff *skb, struct sock *sk);
+
 #else  /* CONFIG_SECURITY_NETWORK */
 static inline int security_unix_stream_connect(struct sock *sock,
                                               struct sock *other,
@@ -2779,6 +2786,11 @@ static inline int security_tun_dev_open(void *security)
 {
        return 0;
 }
+
+static inline void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
+{
+}
+
 #endif /* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
index a2dcb94ea49de76e81bc6c9d200b555d4cbbba04..9475c5cb28bcc82827e9ed8c540fa59acd5067e9 100644 (file)
@@ -250,11 +250,11 @@ extern int show_unhandled_signals;
 extern int sigsuspend(sigset_t *);
 
 struct sigaction {
-#ifndef __ARCH_HAS_ODD_SIGACTION
+#ifndef __ARCH_HAS_IRIX_SIGACTION
        __sighandler_t  sa_handler;
        unsigned long   sa_flags;
 #else
-       unsigned long   sa_flags;
+       unsigned int    sa_flags;
        __sighandler_t  sa_handler;
 #endif
 #ifdef __ARCH_HAS_SA_RESTORER
index 441f5bfdab8ea476749bb512d2c7deeed7399a83..b8292d8cc9fa6238ed0691194f714f827cabd058 100644 (file)
@@ -2643,6 +2643,13 @@ static inline void nf_reset(struct sk_buff *skb)
 #endif
 }
 
+static inline void nf_reset_trace(struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
+       skb->nf_trace = 0;
+#endif
+}
+
 /* Note: This doesn't put any conntrack and bridge info in dst. */
 static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
 {
index a26e2fb604e6e5f004e93da22d4f5355bf9a7358..e2369c167dbd9e7300ecbf617cbc9d8f291c8dc0 100644 (file)
  * In the debug case, 1 means unlocked, 0 means locked. (the values
  * are inverted, to catch initialization bugs)
  *
- * No atomicity anywhere, we are on UP.
+ * No atomicity anywhere, we are on UP. However, we still need
+ * the compiler barriers, because we do not want the compiler to
+ * move potentially faulting instructions (notably user accesses)
+ * into the locked sequence, resulting in non-atomic execution.
  */
 
 #ifdef CONFIG_DEBUG_SPINLOCK
@@ -25,6 +28,7 @@
 static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
        lock->slock = 0;
+       barrier();
 }
 
 static inline void
@@ -32,6 +36,7 @@ arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags)
 {
        local_irq_save(flags);
        lock->slock = 0;
+       barrier();
 }
 
 static inline int arch_spin_trylock(arch_spinlock_t *lock)
@@ -39,32 +44,34 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
        char oldval = lock->slock;
 
        lock->slock = 0;
+       barrier();
 
        return oldval > 0;
 }
 
 static inline void arch_spin_unlock(arch_spinlock_t *lock)
 {
+       barrier();
        lock->slock = 1;
 }
 
 /*
  * Read-write spinlocks. No debug version.
  */
-#define arch_read_lock(lock)           do { (void)(lock); } while (0)
-#define arch_write_lock(lock)          do { (void)(lock); } while (0)
-#define arch_read_trylock(lock)        ({ (void)(lock); 1; })
-#define arch_write_trylock(lock)       ({ (void)(lock); 1; })
-#define arch_read_unlock(lock)         do { (void)(lock); } while (0)
-#define arch_write_unlock(lock)        do { (void)(lock); } while (0)
+#define arch_read_lock(lock)           do { barrier(); (void)(lock); } while (0)
+#define arch_write_lock(lock)          do { barrier(); (void)(lock); } while (0)
+#define arch_read_trylock(lock)        ({ barrier(); (void)(lock); 1; })
+#define arch_write_trylock(lock)       ({ barrier(); (void)(lock); 1; })
+#define arch_read_unlock(lock)         do { barrier(); (void)(lock); } while (0)
+#define arch_write_unlock(lock)        do { barrier(); (void)(lock); } while (0)
 
 #else /* DEBUG_SPINLOCK */
 #define arch_spin_is_locked(lock)      ((void)(lock), 0)
 /* for sched.c and kernel_lock.c: */
-# define arch_spin_lock(lock)          do { (void)(lock); } while (0)
-# define arch_spin_lock_flags(lock, flags)     do { (void)(lock); } while (0)
-# define arch_spin_unlock(lock)        do { (void)(lock); } while (0)
-# define arch_spin_trylock(lock)       ({ (void)(lock); 1; })
+# define arch_spin_lock(lock)          do { barrier(); (void)(lock); } while (0)
+# define arch_spin_lock_flags(lock, flags)     do { barrier(); (void)(lock); } while (0)
+# define arch_spin_unlock(lock)        do { barrier(); (void)(lock); } while (0)
+# define arch_spin_trylock(lock)       ({ barrier(); (void)(lock); 1; })
 #endif /* DEBUG_SPINLOCK */
 
 #define arch_spin_is_contended(lock)   (((void)(lock), 0))
index 9e492be5244b40d8ead3340aa7ac475cb51e56ff..6fcfe99bd999d295e0eb8efb967d0b2892335afc 100644 (file)
 #define SSB_CHIPCO_PMU_CTL                     0x0600 /* PMU control */
 #define  SSB_CHIPCO_PMU_CTL_ILP_DIV            0xFFFF0000 /* ILP div mask */
 #define  SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT      16
+#define  SSB_CHIPCO_PMU_CTL_PLL_UPD            0x00000400
 #define  SSB_CHIPCO_PMU_CTL_NOILPONW           0x00000200 /* No ILP on wait */
 #define  SSB_CHIPCO_PMU_CTL_HTREQEN            0x00000100 /* HT req enable */
 #define  SSB_CHIPCO_PMU_CTL_ALPREQEN           0x00000080 /* ALP req enable */
@@ -667,5 +668,6 @@ enum ssb_pmu_ldo_volt_id {
 void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
                             enum ssb_pmu_ldo_volt_id id, u32 voltage);
 void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on);
+void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid);
 
 #endif /* LINUX_SSB_CHIPCO_H_ */
index 2de42f9401d2599d4309028297c29a3bff9222c8..a5ffd32642fd6d46a8bad7e64eb2b791b9c4cdab 100644 (file)
@@ -25,6 +25,7 @@ extern int swiotlb_force;
 extern void swiotlb_init(int verbose);
 int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
 extern unsigned long swiotlb_nr_tbl(void);
+unsigned long swiotlb_size_or_default(void);
 extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
 
 /*
diff --git a/include/linux/ucs2_string.h b/include/linux/ucs2_string.h
new file mode 100644 (file)
index 0000000..cbb20af
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _LINUX_UCS2_STRING_H_
+#define _LINUX_UCS2_STRING_H_
+
+#include <linux/types.h>       /* for size_t */
+#include <linux/stddef.h>      /* for NULL */
+
+typedef u16 ucs2_char_t;
+
+unsigned long ucs2_strnlen(const ucs2_char_t *s, size_t maxlength);
+unsigned long ucs2_strlen(const ucs2_char_t *s);
+unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
+int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);
+
+#endif /* _LINUX_UCS2_STRING_H_ */
index 40be2a0d8ae1bef7270b06a8a04cc9b9ab30b630..84a6440f1f19ee698dba94a7f899d77fc527e432 100644 (file)
@@ -199,6 +199,7 @@ extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
 /* Device notifier */
 extern int register_inet6addr_notifier(struct notifier_block *nb);
 extern int unregister_inet6addr_notifier(struct notifier_block *nb);
+extern int inet6addr_notifier_call_chain(unsigned long val, void *v);
 
 extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
                                         struct ipv6_devconf *devconf);
index f74109144d3fe544da2ff7ccf29f99884c22b32f..f132924cc9daec92b50427f705b88c3c350e70a3 100644 (file)
@@ -256,7 +256,8 @@ static inline __u32 irlmp_get_daddr(const struct lsap_cb *self)
        return (self && self->lap) ? self->lap->daddr : 0;
 }
 
-extern const char *irlmp_reasons[];
+const char *irlmp_reason_str(LM_REASON reason);
+
 extern int sysctl_discovery_timeout;
 extern int sysctl_discovery_slots;
 extern int sysctl_discovery;
index cc7c19732389dba327a92742de4cfeba96b5903e..714cc9a54a4c38575f15581cb379a20f6615b3e2 100644 (file)
@@ -130,6 +130,14 @@ struct iucv_sock {
                                               enum iucv_tx_notify n);
 };
 
+struct iucv_skb_cb {
+       u32     class;          /* target class of message */
+       u32     tag;            /* tag associated with message */
+       u32     offset;         /* offset for skb receival */
+};
+
+#define IUCV_SKB_CB(__skb)     ((struct iucv_skb_cb *)&((__skb)->cb[0]))
+
 /* iucv socket options (SOL_IUCV) */
 #define SO_IPRMDATA_MSG        0x0080          /* send/recv IPRM_DATA msgs */
 #define SO_MSGLIMIT    0x1000          /* get/set IUCV MSGLIMIT */
index 975cca01048bee3b7da9017725654053921250ae..b11708105681e04f5c24f7ed206f732e2c37dc02 100644 (file)
@@ -56,8 +56,8 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm,
        scm->pid  = get_pid(pid);
        scm->cred = cred ? get_cred(cred) : NULL;
        scm->creds.pid = pid_vnr(pid);
-       scm->creds.uid = cred ? cred->euid : INVALID_UID;
-       scm->creds.gid = cred ? cred->egid : INVALID_GID;
+       scm->creds.uid = cred ? cred->uid : INVALID_UID;
+       scm->creds.gid = cred ? cred->gid : INVALID_GID;
 }
 
 static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
index 399162b50a8d3479e68183f63f8e227f8db5f6c5..e1379b4e8faf569c6f95131577bba6c4c392e2b0 100644 (file)
@@ -1074,7 +1074,8 @@ void fc_rport_terminate_io(struct fc_rport *);
 /*
  * DISCOVERY LAYER
  *****************************/
-int fc_disc_init(struct fc_lport *);
+void fc_disc_init(struct fc_lport *);
+void fc_disc_config(struct fc_lport *, void *);
 
 static inline struct fc_lport *fc_disc_lport(struct fc_disc *disc)
 {
old mode 100755 (executable)
new mode 100644 (file)
index e1ef63d4a5c453b17630b279d5780b32f1e722c3..44a30b1086835d1d1fcc2840bb5328d5a2ce19b2 100644 (file)
@@ -488,6 +488,7 @@ struct snd_soc_dapm_path {
        /* status */
        u32 connect:1;  /* source and sink widgets are connected */
        u32 walked:1;   /* path has been walked */
+       u32 walking:1;  /* path is in the process of being walked */
        u32 weak:1;     /* path ignored for power management */
 
        int (*connected)(struct snd_soc_dapm_widget *source,
index 9961726523d01251957b2f8c661422c31d1ac78c..9c1467357b03c616967cd193efab6506e3e5adff 100644 (file)
@@ -257,6 +257,7 @@ TRACE_EVENT(block_bio_bounce,
 
 /**
  * block_bio_complete - completed all work on the block operation
+ * @q: queue holding the block operation
  * @bio: block operation completed
  * @error: io error value
  *
@@ -265,9 +266,9 @@ TRACE_EVENT(block_bio_bounce,
  */
 TRACE_EVENT(block_bio_complete,
 
-       TP_PROTO(struct bio *bio, int error),
+       TP_PROTO(struct request_queue *q, struct bio *bio, int error),
 
-       TP_ARGS(bio, error),
+       TP_ARGS(q, bio, error),
 
        TP_STRUCT__entry(
                __field( dev_t,         dev             )
@@ -278,8 +279,7 @@ TRACE_EVENT(block_bio_complete,
        ),
 
        TP_fast_assign(
-               __entry->dev            = bio->bi_bdev ?
-                                         bio->bi_bdev->bd_dev : 0;
+               __entry->dev            = bio->bi_bdev->bd_dev;
                __entry->sector         = bio->bi_sector;
                __entry->nr_sector      = bio->bi_size >> 9;
                __entry->error          = error;
index 5a8671e8a67ff8fa8f715311300901181555d78e..e5586caff67a973c962a3ed6bf43d4cc01664083 100644 (file)
@@ -147,7 +147,7 @@ TRACE_EVENT(sched_switch,
                  __print_flags(__entry->prev_state & (TASK_STATE_MAX-1), "|",
                                { 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" },
                                { 16, "Z" }, { 32, "X" }, { 64, "x" },
-                               { 128, "W" }) : "R",
+                               { 128, "K" }, { 256, "W" }, { 512, "P" }) : "R",
                __entry->prev_state & TASK_STATE_MAX ? "+" : "",
                __entry->next_comm, __entry->next_pid, __entry->next_prio)
 );
index 4c43b44487922301a3c7949ee6c07020e50e248e..706d035fa7488df73b142b1812c2c3feaa8708d3 100644 (file)
 #ifndef _LINUX_FUSE_H
 #define _LINUX_FUSE_H
 
-#ifdef __linux__
+#ifdef __KERNEL__
 #include <linux/types.h>
 #else
 #include <stdint.h>
-#define __u64 uint64_t
-#define __s64 int64_t
-#define __u32 uint32_t
-#define __s32 int32_t
-#define __u16 uint16_t
 #endif
 
 /*
    userspace works under 64bit kernels */
 
 struct fuse_attr {
-       __u64   ino;
-       __u64   size;
-       __u64   blocks;
-       __u64   atime;
-       __u64   mtime;
-       __u64   ctime;
-       __u32   atimensec;
-       __u32   mtimensec;
-       __u32   ctimensec;
-       __u32   mode;
-       __u32   nlink;
-       __u32   uid;
-       __u32   gid;
-       __u32   rdev;
-       __u32   blksize;
-       __u32   padding;
+       uint64_t        ino;
+       uint64_t        size;
+       uint64_t        blocks;
+       uint64_t        atime;
+       uint64_t        mtime;
+       uint64_t        ctime;
+       uint32_t        atimensec;
+       uint32_t        mtimensec;
+       uint32_t        ctimensec;
+       uint32_t        mode;
+       uint32_t        nlink;
+       uint32_t        uid;
+       uint32_t        gid;
+       uint32_t        rdev;
+       uint32_t        blksize;
+       uint32_t        padding;
 };
 
 struct fuse_kstatfs {
-       __u64   blocks;
-       __u64   bfree;
-       __u64   bavail;
-       __u64   files;
-       __u64   ffree;
-       __u32   bsize;
-       __u32   namelen;
-       __u32   frsize;
-       __u32   padding;
-       __u32   spare[6];
+       uint64_t        blocks;
+       uint64_t        bfree;
+       uint64_t        bavail;
+       uint64_t        files;
+       uint64_t        ffree;
+       uint32_t        bsize;
+       uint32_t        namelen;
+       uint32_t        frsize;
+       uint32_t        padding;
+       uint32_t        spare[6];
 };
 
 struct fuse_file_lock {
-       __u64   start;
-       __u64   end;
-       __u32   type;
-       __u32   pid; /* tgid */
+       uint64_t        start;
+       uint64_t        end;
+       uint32_t        type;
+       uint32_t        pid; /* tgid */
 };
 
 /**
@@ -364,143 +359,143 @@ enum fuse_notify_code {
 #define FUSE_COMPAT_ENTRY_OUT_SIZE 120
 
 struct fuse_entry_out {
-       __u64   nodeid;         /* Inode ID */
-       __u64   generation;     /* Inode generation: nodeid:gen must
-                                  be unique for the fs's lifetime */
-       __u64   entry_valid;    /* Cache timeout for the name */
-       __u64   attr_valid;     /* Cache timeout for the attributes */
-       __u32   entry_valid_nsec;
-       __u32   attr_valid_nsec;
+       uint64_t        nodeid;         /* Inode ID */
+       uint64_t        generation;     /* Inode generation: nodeid:gen must
+                                          be unique for the fs's lifetime */
+       uint64_t        entry_valid;    /* Cache timeout for the name */
+       uint64_t        attr_valid;     /* Cache timeout for the attributes */
+       uint32_t        entry_valid_nsec;
+       uint32_t        attr_valid_nsec;
        struct fuse_attr attr;
 };
 
 struct fuse_forget_in {
-       __u64   nlookup;
+       uint64_t        nlookup;
 };
 
 struct fuse_forget_one {
-       __u64   nodeid;
-       __u64   nlookup;
+       uint64_t        nodeid;
+       uint64_t        nlookup;
 };
 
 struct fuse_batch_forget_in {
-       __u32   count;
-       __u32   dummy;
+       uint32_t        count;
+       uint32_t        dummy;
 };
 
 struct fuse_getattr_in {
-       __u32   getattr_flags;
-       __u32   dummy;
-       __u64   fh;
+       uint32_t        getattr_flags;
+       uint32_t        dummy;
+       uint64_t        fh;
 };
 
 #define FUSE_COMPAT_ATTR_OUT_SIZE 96
 
 struct fuse_attr_out {
-       __u64   attr_valid;     /* Cache timeout for the attributes */
-       __u32   attr_valid_nsec;
-       __u32   dummy;
+       uint64_t        attr_valid;     /* Cache timeout for the attributes */
+       uint32_t        attr_valid_nsec;
+       uint32_t        dummy;
        struct fuse_attr attr;
 };
 
 #define FUSE_COMPAT_MKNOD_IN_SIZE 8
 
 struct fuse_mknod_in {
-       __u32   mode;
-       __u32   rdev;
-       __u32   umask;
-       __u32   padding;
+       uint32_t        mode;
+       uint32_t        rdev;
+       uint32_t        umask;
+       uint32_t        padding;
 };
 
 struct fuse_mkdir_in {
-       __u32   mode;
-       __u32   umask;
+       uint32_t        mode;
+       uint32_t        umask;
 };
 
 struct fuse_rename_in {
-       __u64   newdir;
+       uint64_t        newdir;
 };
 
 struct fuse_link_in {
-       __u64   oldnodeid;
+       uint64_t        oldnodeid;
 };
 
 struct fuse_setattr_in {
-       __u32   valid;
-       __u32   padding;
-       __u64   fh;
-       __u64   size;
-       __u64   lock_owner;
-       __u64   atime;
-       __u64   mtime;
-       __u64   unused2;
-       __u32   atimensec;
-       __u32   mtimensec;
-       __u32   unused3;
-       __u32   mode;
-       __u32   unused4;
-       __u32   uid;
-       __u32   gid;
-       __u32   unused5;
+       uint32_t        valid;
+       uint32_t        padding;
+       uint64_t        fh;
+       uint64_t        size;
+       uint64_t        lock_owner;
+       uint64_t        atime;
+       uint64_t        mtime;
+       uint64_t        unused2;
+       uint32_t        atimensec;
+       uint32_t        mtimensec;
+       uint32_t        unused3;
+       uint32_t        mode;
+       uint32_t        unused4;
+       uint32_t        uid;
+       uint32_t        gid;
+       uint32_t        unused5;
 };
 
 struct fuse_open_in {
-       __u32   flags;
-       __u32   unused;
+       uint32_t        flags;
+       uint32_t        unused;
 };
 
 struct fuse_create_in {
-       __u32   flags;
-       __u32   mode;
-       __u32   umask;
-       __u32   padding;
+       uint32_t        flags;
+       uint32_t        mode;
+       uint32_t        umask;
+       uint32_t        padding;
 };
 
 struct fuse_open_out {
-       __u64   fh;
-       __u32   open_flags;
-       __u32   padding;
+       uint64_t        fh;
+       uint32_t        open_flags;
+       uint32_t        padding;
 };
 
 struct fuse_release_in {
-       __u64   fh;
-       __u32   flags;
-       __u32   release_flags;
-       __u64   lock_owner;
+       uint64_t        fh;
+       uint32_t        flags;
+       uint32_t        release_flags;
+       uint64_t        lock_owner;
 };
 
 struct fuse_flush_in {
-       __u64   fh;
-       __u32   unused;
-       __u32   padding;
-       __u64   lock_owner;
+       uint64_t        fh;
+       uint32_t        unused;
+       uint32_t        padding;
+       uint64_t        lock_owner;
 };
 
 struct fuse_read_in {
-       __u64   fh;
-       __u64   offset;
-       __u32   size;
-       __u32   read_flags;
-       __u64   lock_owner;
-       __u32   flags;
-       __u32   padding;
+       uint64_t        fh;
+       uint64_t        offset;
+       uint32_t        size;
+       uint32_t        read_flags;
+       uint64_t        lock_owner;
+       uint32_t        flags;
+       uint32_t        padding;
 };
 
 #define FUSE_COMPAT_WRITE_IN_SIZE 24
 
 struct fuse_write_in {
-       __u64   fh;
-       __u64   offset;
-       __u32   size;
-       __u32   write_flags;
-       __u64   lock_owner;
-       __u32   flags;
-       __u32   padding;
+       uint64_t        fh;
+       uint64_t        offset;
+       uint32_t        size;
+       uint32_t        write_flags;
+       uint64_t        lock_owner;
+       uint32_t        flags;
+       uint32_t        padding;
 };
 
 struct fuse_write_out {
-       __u32   size;
-       __u32   padding;
+       uint32_t        size;
+       uint32_t        padding;
 };
 
 #define FUSE_COMPAT_STATFS_SIZE 48
@@ -510,32 +505,32 @@ struct fuse_statfs_out {
 };
 
 struct fuse_fsync_in {
-       __u64   fh;
-       __u32   fsync_flags;
-       __u32   padding;
+       uint64_t        fh;
+       uint32_t        fsync_flags;
+       uint32_t        padding;
 };
 
 struct fuse_setxattr_in {
-       __u32   size;
-       __u32   flags;
+       uint32_t        size;
+       uint32_t        flags;
 };
 
 struct fuse_getxattr_in {
-       __u32   size;
-       __u32   padding;
+       uint32_t        size;
+       uint32_t        padding;
 };
 
 struct fuse_getxattr_out {
-       __u32   size;
-       __u32   padding;
+       uint32_t        size;
+       uint32_t        padding;
 };
 
 struct fuse_lk_in {
-       __u64   fh;
-       __u64   owner;
+       uint64_t        fh;
+       uint64_t        owner;
        struct fuse_file_lock lk;
-       __u32   lk_flags;
-       __u32   padding;
+       uint32_t        lk_flags;
+       uint32_t        padding;
 };
 
 struct fuse_lk_out {
@@ -543,134 +538,135 @@ struct fuse_lk_out {
 };
 
 struct fuse_access_in {
-       __u32   mask;
-       __u32   padding;
+       uint32_t        mask;
+       uint32_t        padding;
 };
 
 struct fuse_init_in {
-       __u32   major;
-       __u32   minor;
-       __u32   max_readahead;
-       __u32   flags;
+       uint32_t        major;
+       uint32_t        minor;
+       uint32_t        max_readahead;
+       uint32_t        flags;
 };
 
 struct fuse_init_out {
-       __u32   major;
-       __u32   minor;
-       __u32   max_readahead;
-       __u32   flags;
-       __u16   max_background;
-       __u16   congestion_threshold;
-       __u32   max_write;
+       uint32_t        major;
+       uint32_t        minor;
+       uint32_t        max_readahead;
+       uint32_t        flags;
+       uint16_t        max_background;
+       uint16_t        congestion_threshold;
+       uint32_t        max_write;
 };
 
 #define CUSE_INIT_INFO_MAX 4096
 
 struct cuse_init_in {
-       __u32   major;
-       __u32   minor;
-       __u32   unused;
-       __u32   flags;
+       uint32_t        major;
+       uint32_t        minor;
+       uint32_t        unused;
+       uint32_t        flags;
 };
 
 struct cuse_init_out {
-       __u32   major;
-       __u32   minor;
-       __u32   unused;
-       __u32   flags;
-       __u32   max_read;
-       __u32   max_write;
-       __u32   dev_major;              /* chardev major */
-       __u32   dev_minor;              /* chardev minor */
-       __u32   spare[10];
+       uint32_t        major;
+       uint32_t        minor;
+       uint32_t        unused;
+       uint32_t        flags;
+       uint32_t        max_read;
+       uint32_t        max_write;
+       uint32_t        dev_major;              /* chardev major */
+       uint32_t        dev_minor;              /* chardev minor */
+       uint32_t        spare[10];
 };
 
 struct fuse_interrupt_in {
-       __u64   unique;
+       uint64_t        unique;
 };
 
 struct fuse_bmap_in {
-       __u64   block;
-       __u32   blocksize;
-       __u32   padding;
+       uint64_t        block;
+       uint32_t        blocksize;
+       uint32_t        padding;
 };
 
 struct fuse_bmap_out {
-       __u64   block;
+       uint64_t        block;
 };
 
 struct fuse_ioctl_in {
-       __u64   fh;
-       __u32   flags;
-       __u32   cmd;
-       __u64   arg;
-       __u32   in_size;
-       __u32   out_size;
+       uint64_t        fh;
+       uint32_t        flags;
+       uint32_t        cmd;
+       uint64_t        arg;
+       uint32_t        in_size;
+       uint32_t        out_size;
 };
 
 struct fuse_ioctl_iovec {
-       __u64   base;
-       __u64   len;
+       uint64_t        base;
+       uint64_t        len;
 };
 
 struct fuse_ioctl_out {
-       __s32   result;
-       __u32   flags;
-       __u32   in_iovs;
-       __u32   out_iovs;
+       int32_t         result;
+       uint32_t        flags;
+       uint32_t        in_iovs;
+       uint32_t        out_iovs;
 };
 
 struct fuse_poll_in {
-       __u64   fh;
-       __u64   kh;
-       __u32   flags;
-       __u32   events;
+       uint64_t        fh;
+       uint64_t        kh;
+       uint32_t        flags;
+       uint32_t        events;
 };
 
 struct fuse_poll_out {
-       __u32   revents;
-       __u32   padding;
+       uint32_t        revents;
+       uint32_t        padding;
 };
 
 struct fuse_notify_poll_wakeup_out {
-       __u64   kh;
+       uint64_t        kh;
 };
 
 struct fuse_fallocate_in {
-       __u64   fh;
-       __u64   offset;
-       __u64   length;
-       __u32   mode;
-       __u32   padding;
+       uint64_t        fh;
+       uint64_t        offset;
+       uint64_t        length;
+       uint32_t        mode;
+       uint32_t        padding;
 };
 
 struct fuse_in_header {
-       __u32   len;
-       __u32   opcode;
-       __u64   unique;
-       __u64   nodeid;
-       __u32   uid;
-       __u32   gid;
-       __u32   pid;
-       __u32   padding;
+       uint32_t        len;
+       uint32_t        opcode;
+       uint64_t        unique;
+       uint64_t        nodeid;
+       uint32_t        uid;
+       uint32_t        gid;
+       uint32_t        pid;
+       uint32_t        padding;
 };
 
 struct fuse_out_header {
-       __u32   len;
-       __s32   error;
-       __u64   unique;
+       uint32_t        len;
+       int32_t         error;
+       uint64_t        unique;
 };
 
 struct fuse_dirent {
-       __u64   ino;
-       __u64   off;
-       __u32   namelen;
-       __u32   type;
+       uint64_t        ino;
+       uint64_t        off;
+       uint32_t        namelen;
+       uint32_t        type;
        char name[];
 };
 
 #define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
-#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
+#define FUSE_DIRENT_ALIGN(x) \
+       (((x) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1))
 #define FUSE_DIRENT_SIZE(d) \
        FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
 
@@ -685,47 +681,47 @@ struct fuse_direntplus {
        FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen)
 
 struct fuse_notify_inval_inode_out {
-       __u64   ino;
-       __s64   off;
-       __s64   len;
+       uint64_t        ino;
+       int64_t         off;
+       int64_t         len;
 };
 
 struct fuse_notify_inval_entry_out {
-       __u64   parent;
-       __u32   namelen;
-       __u32   padding;
+       uint64_t        parent;
+       uint32_t        namelen;
+       uint32_t        padding;
 };
 
 struct fuse_notify_delete_out {
-       __u64   parent;
-       __u64   child;
-       __u32   namelen;
-       __u32   padding;
+       uint64_t        parent;
+       uint64_t        child;
+       uint32_t        namelen;
+       uint32_t        padding;
 };
 
 struct fuse_notify_store_out {
-       __u64   nodeid;
-       __u64   offset;
-       __u32   size;
-       __u32   padding;
+       uint64_t        nodeid;
+       uint64_t        offset;
+       uint32_t        size;
+       uint32_t        padding;
 };
 
 struct fuse_notify_retrieve_out {
-       __u64   notify_unique;
-       __u64   nodeid;
-       __u64   offset;
-       __u32   size;
-       __u32   padding;
+       uint64_t        notify_unique;
+       uint64_t        nodeid;
+       uint64_t        offset;
+       uint32_t        size;
+       uint32_t        padding;
 };
 
 /* Matches the size of fuse_write_in */
 struct fuse_notify_retrieve_in {
-       __u64   dummy1;
-       __u64   offset;
-       __u32   size;
-       __u32   dummy2;
-       __u64   dummy3;
-       __u64   dummy4;
+       uint64_t        dummy1;
+       uint64_t        offset;
+       uint32_t        size;
+       uint32_t        dummy2;
+       uint64_t        dummy3;
+       uint64_t        dummy4;
 };
 
 #endif /* _LINUX_FUSE_H */
index ebfadc56d1b43526c439086eb294124d20bec524..864e324da80d73aad07778f38bba7f7be8e4d55d 100644 (file)
 
 /* Message Signalled Interrupts registers */
 
-#define PCI_MSI_FLAGS          2       /* Various flags */
-#define  PCI_MSI_FLAGS_64BIT   0x80    /* 64-bit addresses allowed */
-#define  PCI_MSI_FLAGS_QSIZE   0x70    /* Message queue size configured */
-#define  PCI_MSI_FLAGS_QMASK   0x0e    /* Maximum queue size available */
-#define  PCI_MSI_FLAGS_ENABLE  0x01    /* MSI feature enabled */
-#define  PCI_MSI_FLAGS_MASKBIT 0x100   /* 64-bit mask bits allowed */
+#define PCI_MSI_FLAGS          2       /* Message Control */
+#define  PCI_MSI_FLAGS_ENABLE  0x0001  /* MSI feature enabled */
+#define  PCI_MSI_FLAGS_QMASK   0x000e  /* Maximum queue size available */
+#define  PCI_MSI_FLAGS_QSIZE   0x0070  /* Message queue size configured */
+#define  PCI_MSI_FLAGS_64BIT   0x0080  /* 64-bit addresses allowed */
+#define  PCI_MSI_FLAGS_MASKBIT 0x0100  /* Per-vector masking capable */
 #define PCI_MSI_RFU            3       /* Rest of capability flags */
 #define PCI_MSI_ADDRESS_LO     4       /* Lower 32 bits */
 #define PCI_MSI_ADDRESS_HI     8       /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
 #define PCI_MSI_PENDING_64     20      /* Pending intrs for 64-bit devices */
 
 /* MSI-X registers */
-#define PCI_MSIX_FLAGS         2
-#define  PCI_MSIX_FLAGS_QSIZE  0x7FF
-#define  PCI_MSIX_FLAGS_ENABLE (1 << 15)
-#define  PCI_MSIX_FLAGS_MASKALL        (1 << 14)
-#define PCI_MSIX_TABLE         4
-#define PCI_MSIX_PBA           8
-#define  PCI_MSIX_FLAGS_BIRMASK        (7 << 0)
+#define PCI_MSIX_FLAGS         2       /* Message Control */
+#define  PCI_MSIX_FLAGS_QSIZE  0x07FF  /* Table size */
+#define  PCI_MSIX_FLAGS_MASKALL        0x4000  /* Mask all vectors for this function */
+#define  PCI_MSIX_FLAGS_ENABLE 0x8000  /* MSI-X enable */
+#define PCI_MSIX_TABLE         4       /* Table offset */
+#define  PCI_MSIX_TABLE_BIR    0x00000007 /* BAR index */
+#define  PCI_MSIX_TABLE_OFFSET 0xfffffff8 /* Offset into specified BAR */
+#define PCI_MSIX_PBA           8       /* Pending Bit Array offset */
+#define  PCI_MSIX_PBA_BIR      0x00000007 /* BAR index */
+#define  PCI_MSIX_PBA_OFFSET   0xfffffff8 /* Offset into specified BAR */
+#define  PCI_MSIX_FLAGS_BIRMASK        (7 << 0)   /* deprecated */
 #define PCI_CAP_MSIX_SIZEOF    12      /* size of MSIX registers */
 
 /* MSI-X entry's format */
index 609efe8c686e63c9cc591bc4682b9a535b0b9a97..ac329ee1d753f894e006ead445407c685fd68268 100644 (file)
@@ -22,6 +22,8 @@
  */
 #define AUOK190X_RESOLUTION_800_600            0
 #define AUOK190X_RESOLUTION_1024_768           1
+#define AUOK190X_RESOLUTION_600_800            4
+#define AUOK190X_RESOLUTION_768_1024           5
 
 /*
  * struct used by auok190x. board specific stuff comes from *board
@@ -98,7 +100,6 @@ struct auok190x_board {
        int gpio_nbusy;
 
        int resolution;
-       int rotation;
        int quirks;
        int fps;
 };
index 71e9a383a98156c4a67a9b0ef69f91db827505bd..5d0259b08e015ae0e3d288de561446cc995aecdb 100644 (file)
 #include <linux/bitops.h>
 #include <linux/types.h>
 
-/* VESA display monitor timing parameters */
-#define VESA_DMT_HSYNC_LOW             BIT(0)
-#define VESA_DMT_HSYNC_HIGH            BIT(1)
-#define VESA_DMT_VSYNC_LOW             BIT(2)
-#define VESA_DMT_VSYNC_HIGH            BIT(3)
-
-/* display specific flags */
-#define DISPLAY_FLAGS_DE_LOW           BIT(0)  /* data enable flag */
-#define DISPLAY_FLAGS_DE_HIGH          BIT(1)
-#define DISPLAY_FLAGS_PIXDATA_POSEDGE  BIT(2)  /* drive data on pos. edge */
-#define DISPLAY_FLAGS_PIXDATA_NEGEDGE  BIT(3)  /* drive data on neg. edge */
-#define DISPLAY_FLAGS_INTERLACED       BIT(4)
-#define DISPLAY_FLAGS_DOUBLESCAN       BIT(5)
+enum display_flags {
+       DISPLAY_FLAGS_HSYNC_LOW         = BIT(0),
+       DISPLAY_FLAGS_HSYNC_HIGH        = BIT(1),
+       DISPLAY_FLAGS_VSYNC_LOW         = BIT(2),
+       DISPLAY_FLAGS_VSYNC_HIGH        = BIT(3),
+
+       /* data enable flag */
+       DISPLAY_FLAGS_DE_LOW            = BIT(4),
+       DISPLAY_FLAGS_DE_HIGH           = BIT(5),
+       /* drive data on pos. edge */
+       DISPLAY_FLAGS_PIXDATA_POSEDGE   = BIT(6),
+       /* drive data on neg. edge */
+       DISPLAY_FLAGS_PIXDATA_NEGEDGE   = BIT(7),
+       DISPLAY_FLAGS_INTERLACED        = BIT(8),
+       DISPLAY_FLAGS_DOUBLESCAN        = BIT(9),
+};
 
 /*
  * A single signal can be specified via a range of minimal and maximal values
@@ -36,12 +39,6 @@ struct timing_entry {
        u32 max;
 };
 
-enum timing_entry_index {
-       TE_MIN = 0,
-       TE_TYP = 1,
-       TE_MAX = 2,
-};
-
 /*
  * Single "mode" entry. This describes one set of signal timings a display can
  * have in one setting. This struct can later be converted to struct videomode
@@ -72,8 +69,7 @@ struct display_timing {
        struct timing_entry vback_porch;        /* ver. back porch */
        struct timing_entry vsync_len;          /* ver. sync len */
 
-       unsigned int dmt_flags;                 /* VESA DMT flags */
-       unsigned int data_flags;                /* video data flags */
+       enum display_flags flags;               /* display flags */
 };
 
 /*
@@ -89,25 +85,6 @@ struct display_timings {
        struct display_timing **timings;
 };
 
-/* get value specified by index from struct timing_entry */
-static inline u32 display_timing_get_value(const struct timing_entry *te,
-                                          enum timing_entry_index index)
-{
-       switch (index) {
-       case TE_MIN:
-               return te->min;
-               break;
-       case TE_TYP:
-               return te->typ;
-               break;
-       case TE_MAX:
-               return te->max;
-               break;
-       default:
-               return te->typ;
-       }
-}
-
 /* get one entry from struct display_timings */
 static inline struct display_timing *display_timings_get(const struct
                                                         display_timings *disp,
index a42156234dd4e2f8a6563c39f60c31546ddc893a..3f1049d870d5d4223ee47df2c8a5c05e445762a8 100644 (file)
@@ -29,20 +29,30 @@ struct videomode {
        u32 vback_porch;
        u32 vsync_len;
 
-       unsigned int dmt_flags; /* VESA DMT flags */
-       unsigned int data_flags; /* video data flags */
+       enum display_flags flags; /* display flags */
 };
 
 /**
  * videomode_from_timing - convert display timing to videomode
+ * @dt: display_timing structure
+ * @vm: return value
+ *
+ * DESCRIPTION:
+ * This function converts a struct display_timing to a struct videomode.
+ */
+void videomode_from_timing(const struct display_timing *dt,
+                         struct videomode *vm);
+
+/**
+ * videomode_from_timings - convert one display timings entry to videomode
  * @disp: structure with all possible timing entries
  * @vm: return value
  * @index: index into the list of display timings in devicetree
  *
  * DESCRIPTION:
- * This function converts a struct display_timing to a struct videomode.
+ * This function converts one struct display_timing entry to a struct videomode.
  */
-int videomode_from_timing(const struct display_timings *disp,
+int videomode_from_timings(const struct display_timings *disp,
                          struct videomode *vm, unsigned int index);
 
 #endif
index c6bfe01acf6b4f4952f42ea171b68947c87ff16f..b2b27c6a0f7bed4d17e85a57434cae2120cd4ec8 100644 (file)
@@ -90,8 +90,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
 int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc);
 /* Bind an PSI pirq to an irq. */
 int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
-                            int pirq, int vector, const char *name,
-                            domid_t domid);
+                            int pirq, const char *name, domid_t domid);
 #endif
 
 /* De-allocates the above mentioned physical interrupt. */
index 31cd1bf6af271771e67bdf6e29eb306371d3d130..fede1d06ef305cc59386bb4490c7e2e020b9f25d 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -872,6 +872,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
                                                        goto out_unlock;
                                                break;
                                        }
+                                       msg = ERR_PTR(-EAGAIN);
                                } else
                                        break;
                                msg_counter++;
index ab4f1090f437e0aaa0395e110169cdc6d37b50d9..b3097bde4e9cbc999e5d09205db8014e0da27632 100644 (file)
@@ -4,3 +4,4 @@
 config_data.h
 config_data.gz
 timeconst.h
+hz.bc
index 493d97259484cfef006c59b934be4fcf9663d1ac..f6c2ce5701e1c3c723d03e3d917c62f584c3a074 100644 (file)
@@ -392,6 +392,30 @@ bool ns_capable(struct user_namespace *ns, int cap)
 }
 EXPORT_SYMBOL(ns_capable);
 
+/**
+ * file_ns_capable - Determine if the file's opener had a capability in effect
+ * @file:  The file we want to check
+ * @ns:  The usernamespace we want the capability in
+ * @cap: The capability to be tested for
+ *
+ * Return true if task that opened the file had a capability in effect
+ * when the file was opened.
+ *
+ * This does not set PF_SUPERPRIV because the caller may not
+ * actually be privileged.
+ */
+bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap)
+{
+       if (WARN_ON_ONCE(!cap_valid(cap)))
+               return false;
+
+       if (security_capable(file->f_cred, ns, cap) == 0)
+               return true;
+
+       return false;
+}
+EXPORT_SYMBOL(file_ns_capable);
+
 /**
  * capable - Determine if the current task has a superior capability in effect
  * @cap: The capability to be tested for
index 59412d037eed2a81163483b89fb38d9feb30623a..9fcb0944f0718597fab6f6723e70e701be55b075 100644 (file)
@@ -4596,6 +4596,7 @@ void perf_event_comm(struct task_struct *task)
        struct perf_event_context *ctx;
        int ctxn;
 
+       rcu_read_lock();
        for_each_task_context_nr(ctxn) {
                ctx = task->perf_event_ctxp[ctxn];
                if (!ctx)
@@ -4603,6 +4604,7 @@ void perf_event_comm(struct task_struct *task)
 
                perf_event_enable_on_exec(ctx);
        }
+       rcu_read_unlock();
 
        if (!atomic_read(&nr_comm_events))
                return;
@@ -4737,7 +4739,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
        } else {
                if (arch_vma_name(mmap_event->vma)) {
                        name = strncpy(tmp, arch_vma_name(mmap_event->vma),
-                                      sizeof(tmp));
+                                      sizeof(tmp) - 1);
+                       tmp[sizeof(tmp) - 1] = '\0';
                        goto got_name;
                }
 
@@ -5330,7 +5333,7 @@ static void sw_perf_event_destroy(struct perf_event *event)
 
 static int perf_swevent_init(struct perf_event *event)
 {
-       int event_id = event->attr.config;
+       u64 event_id = event->attr.config;
 
        if (event->attr.type != PERF_TYPE_SOFTWARE)
                return -ENOENT;
@@ -5986,6 +5989,7 @@ skip_type:
        if (pmu->pmu_cpu_context)
                goto got_cpu_context;
 
+       ret = -ENOMEM;
        pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);
        if (!pmu->pmu_cpu_context)
                goto free_dev;
index d56a64c99a8b1ccf07d3ee252d73048181dcdfd9..eb675c4d59dfd440b9f93d92226ee2dc5ffe8290 100644 (file)
@@ -16,7 +16,7 @@ struct ring_buffer {
        int                             page_order;     /* allocation order  */
 #endif
        int                             nr_pages;       /* nr of data pages  */
-       int                             writable;       /* are we writable   */
+       int                             overwrite;      /* can overwrite itself */
 
        atomic_t                        poll;           /* POLL_ for wakeups */
 
index 23cb34ff3973c2dc7e4ce9cf41f744f93a36f83a..97fddb09762b0dc815af7d1f674993d87cd45574 100644 (file)
 static bool perf_output_space(struct ring_buffer *rb, unsigned long tail,
                              unsigned long offset, unsigned long head)
 {
-       unsigned long mask;
+       unsigned long sz = perf_data_size(rb);
+       unsigned long mask = sz - 1;
 
-       if (!rb->writable)
+       /*
+        * check if user-writable
+        * overwrite : over-write its own tail
+        * !overwrite: buffer possibly drops events.
+        */
+       if (rb->overwrite)
                return true;
 
-       mask = perf_data_size(rb) - 1;
+       /*
+        * verify that payload is not bigger than buffer
+        * otherwise masking logic may fail to detect
+        * the "not enough space" condition
+        */
+       if ((head - offset) > sz)
+               return false;
 
        offset = (offset - tail) & mask;
        head   = (head   - tail) & mask;
@@ -212,7 +224,9 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
                rb->watermark = max_size / 2;
 
        if (flags & RING_BUFFER_WRITABLE)
-               rb->writable = 1;
+               rb->overwrite = 0;
+       else
+               rb->overwrite = 1;
 
        atomic_set(&rb->refcount, 1);
 
index cc47812d3feb0c86cbcf8f03e6ee81340ef7c57c..14be27feda491da1c3dc9990a5ae80ce649570aa 100644 (file)
@@ -63,6 +63,7 @@
 DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
 {
 
+       .lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),
        .clock_base =
        {
                {
@@ -1642,8 +1643,6 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
        struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
        int i;
 
-       raw_spin_lock_init(&cpu_base->lock);
-
        for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
                cpu_base->clock_base[i].cpu_base = cpu_base;
                timerqueue_init_head(&cpu_base->clock_base[i].active);
index bddd3d7a74b688a1c9c2e68481b77363558124c7..ffd4e111fd67e7d7b29199b6206957f6c458a350 100644 (file)
@@ -55,7 +55,7 @@ struct resource crashk_res = {
        .flags = IORESOURCE_BUSY | IORESOURCE_MEM
 };
 struct resource crashk_low_res = {
-       .name  = "Crash kernel low",
+       .name  = "Crash kernel",
        .start = 0,
        .end   = 0,
        .flags = IORESOURCE_BUSY | IORESOURCE_MEM
@@ -1368,35 +1368,114 @@ static int __init parse_crashkernel_simple(char                *cmdline,
        return 0;
 }
 
+#define SUFFIX_HIGH 0
+#define SUFFIX_LOW  1
+#define SUFFIX_NULL 2
+static __initdata char *suffix_tbl[] = {
+       [SUFFIX_HIGH] = ",high",
+       [SUFFIX_LOW]  = ",low",
+       [SUFFIX_NULL] = NULL,
+};
+
 /*
- * That function is the entry point for command line parsing and should be
- * called from the arch-specific code.
+ * That function parses "suffix"  crashkernel command lines like
+ *
+ *     crashkernel=size,[high|low]
+ *
+ * It returns 0 on success and -EINVAL on failure.
  */
+static int __init parse_crashkernel_suffix(char *cmdline,
+                                          unsigned long long   *crash_size,
+                                          unsigned long long   *crash_base,
+                                          const char *suffix)
+{
+       char *cur = cmdline;
+
+       *crash_size = memparse(cmdline, &cur);
+       if (cmdline == cur) {
+               pr_warn("crashkernel: memory value expected\n");
+               return -EINVAL;
+       }
+
+       /* check with suffix */
+       if (strncmp(cur, suffix, strlen(suffix))) {
+               pr_warn("crashkernel: unrecognized char\n");
+               return -EINVAL;
+       }
+       cur += strlen(suffix);
+       if (*cur != ' ' && *cur != '\0') {
+               pr_warn("crashkernel: unrecognized char\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static __init char *get_last_crashkernel(char *cmdline,
+                            const char *name,
+                            const char *suffix)
+{
+       char *p = cmdline, *ck_cmdline = NULL;
+
+       /* find crashkernel and use the last one if there are more */
+       p = strstr(p, name);
+       while (p) {
+               char *end_p = strchr(p, ' ');
+               char *q;
+
+               if (!end_p)
+                       end_p = p + strlen(p);
+
+               if (!suffix) {
+                       int i;
+
+                       /* skip the one with any known suffix */
+                       for (i = 0; suffix_tbl[i]; i++) {
+                               q = end_p - strlen(suffix_tbl[i]);
+                               if (!strncmp(q, suffix_tbl[i],
+                                            strlen(suffix_tbl[i])))
+                                       goto next;
+                       }
+                       ck_cmdline = p;
+               } else {
+                       q = end_p - strlen(suffix);
+                       if (!strncmp(q, suffix, strlen(suffix)))
+                               ck_cmdline = p;
+               }
+next:
+               p = strstr(p+1, name);
+       }
+
+       if (!ck_cmdline)
+               return NULL;
+
+       return ck_cmdline;
+}
+
 static int __init __parse_crashkernel(char *cmdline,
                             unsigned long long system_ram,
                             unsigned long long *crash_size,
                             unsigned long long *crash_base,
-                               const char *name)
+                            const char *name,
+                            const char *suffix)
 {
-       char    *p = cmdline, *ck_cmdline = NULL;
        char    *first_colon, *first_space;
+       char    *ck_cmdline;
 
        BUG_ON(!crash_size || !crash_base);
        *crash_size = 0;
        *crash_base = 0;
 
-       /* find crashkernel and use the last one if there are more */
-       p = strstr(p, name);
-       while (p) {
-               ck_cmdline = p;
-               p = strstr(p+1, name);
-       }
+       ck_cmdline = get_last_crashkernel(cmdline, name, suffix);
 
        if (!ck_cmdline)
                return -EINVAL;
 
        ck_cmdline += strlen(name);
 
+       if (suffix)
+               return parse_crashkernel_suffix(ck_cmdline, crash_size,
+                               crash_base, suffix);
        /*
         * if the commandline contains a ':', then that's the extended
         * syntax -- if not, it must be the classic syntax
@@ -1413,13 +1492,26 @@ static int __init __parse_crashkernel(char *cmdline,
        return 0;
 }
 
+/*
+ * That function is the entry point for command line parsing and should be
+ * called from the arch-specific code.
+ */
 int __init parse_crashkernel(char *cmdline,
                             unsigned long long system_ram,
                             unsigned long long *crash_size,
                             unsigned long long *crash_base)
 {
        return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
-                                       "crashkernel=");
+                                       "crashkernel=", NULL);
+}
+
+int __init parse_crashkernel_high(char *cmdline,
+                            unsigned long long system_ram,
+                            unsigned long long *crash_size,
+                            unsigned long long *crash_base)
+{
+       return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
+                               "crashkernel=", suffix_tbl[SUFFIX_HIGH]);
 }
 
 int __init parse_crashkernel_low(char *cmdline,
@@ -1428,7 +1520,7 @@ int __init parse_crashkernel_low(char *cmdline,
                             unsigned long long *crash_base)
 {
        return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
-                                       "crashkernel_low=");
+                               "crashkernel=", suffix_tbl[SUFFIX_LOW]);
 }
 
 static void update_vmcoreinfo_note(void)
index e35be53f6613c4fd08c093b6865cd6f43e0b9a89..3fed7f0cbcdfe3d2149dd903e6912628ba58da95 100644 (file)
@@ -794,16 +794,16 @@ out:
 }
 
 #ifdef CONFIG_SYSCTL
-/* This should be called with kprobe_mutex locked */
 static void __kprobes optimize_all_kprobes(void)
 {
        struct hlist_head *head;
        struct kprobe *p;
        unsigned int i;
 
+       mutex_lock(&kprobe_mutex);
        /* If optimization is already allowed, just return */
        if (kprobes_allow_optimization)
-               return;
+               goto out;
 
        kprobes_allow_optimization = true;
        for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
@@ -813,18 +813,22 @@ static void __kprobes optimize_all_kprobes(void)
                                optimize_kprobe(p);
        }
        printk(KERN_INFO "Kprobes globally optimized\n");
+out:
+       mutex_unlock(&kprobe_mutex);
 }
 
-/* This should be called with kprobe_mutex locked */
 static void __kprobes unoptimize_all_kprobes(void)
 {
        struct hlist_head *head;
        struct kprobe *p;
        unsigned int i;
 
+       mutex_lock(&kprobe_mutex);
        /* If optimization is already prohibited, just return */
-       if (!kprobes_allow_optimization)
+       if (!kprobes_allow_optimization) {
+               mutex_unlock(&kprobe_mutex);
                return;
+       }
 
        kprobes_allow_optimization = false;
        for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
@@ -834,11 +838,14 @@ static void __kprobes unoptimize_all_kprobes(void)
                                unoptimize_kprobe(p, false);
                }
        }
+       mutex_unlock(&kprobe_mutex);
+
        /* Wait for unoptimizing completion */
        wait_for_kprobe_optimizer();
        printk(KERN_INFO "Kprobes globally unoptimized\n");
 }
 
+static DEFINE_MUTEX(kprobe_sysctl_mutex);
 int sysctl_kprobes_optimization;
 int proc_kprobes_optimization_handler(struct ctl_table *table, int write,
                                      void __user *buffer, size_t *length,
@@ -846,7 +853,7 @@ int proc_kprobes_optimization_handler(struct ctl_table *table, int write,
 {
        int ret;
 
-       mutex_lock(&kprobe_mutex);
+       mutex_lock(&kprobe_sysctl_mutex);
        sysctl_kprobes_optimization = kprobes_allow_optimization ? 1 : 0;
        ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
 
@@ -854,7 +861,7 @@ int proc_kprobes_optimization_handler(struct ctl_table *table, int write,
                optimize_all_kprobes();
        else
                unoptimize_all_kprobes();
-       mutex_unlock(&kprobe_mutex);
+       mutex_unlock(&kprobe_sysctl_mutex);
 
        return ret;
 }
index 691dc2ef9baf241c121144799360a7e1237afcb5..9eb7fed0bbaa9895973a14e551c76de31fffe533 100644 (file)
@@ -124,12 +124,12 @@ void *kthread_data(struct task_struct *task)
 
 static void __kthread_parkme(struct kthread *self)
 {
-       __set_current_state(TASK_INTERRUPTIBLE);
+       __set_current_state(TASK_PARKED);
        while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) {
                if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags))
                        complete(&self->parked);
                schedule();
-               __set_current_state(TASK_INTERRUPTIBLE);
+               __set_current_state(TASK_PARKED);
        }
        clear_bit(KTHREAD_IS_PARKED, &self->flags);
        __set_current_state(TASK_RUNNING);
@@ -256,8 +256,13 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
 }
 EXPORT_SYMBOL(kthread_create_on_node);
 
-static void __kthread_bind(struct task_struct *p, unsigned int cpu)
+static void __kthread_bind(struct task_struct *p, unsigned int cpu, long state)
 {
+       /* Must have done schedule() in kthread() before we set_task_cpu */
+       if (!wait_task_inactive(p, state)) {
+               WARN_ON(1);
+               return;
+       }
        /* It's safe because the task is inactive. */
        do_set_cpus_allowed(p, cpumask_of(cpu));
        p->flags |= PF_THREAD_BOUND;
@@ -274,12 +279,7 @@ static void __kthread_bind(struct task_struct *p, unsigned int cpu)
  */
 void kthread_bind(struct task_struct *p, unsigned int cpu)
 {
-       /* Must have done schedule() in kthread() before we set_task_cpu */
-       if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE)) {
-               WARN_ON(1);
-               return;
-       }
-       __kthread_bind(p, cpu);
+       __kthread_bind(p, cpu, TASK_UNINTERRUPTIBLE);
 }
 EXPORT_SYMBOL(kthread_bind);
 
@@ -324,6 +324,22 @@ static struct kthread *task_get_live_kthread(struct task_struct *k)
        return NULL;
 }
 
+static void __kthread_unpark(struct task_struct *k, struct kthread *kthread)
+{
+       clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
+       /*
+        * We clear the IS_PARKED bit here as we don't wait
+        * until the task has left the park code. So if we'd
+        * park before that happens we'd see the IS_PARKED bit
+        * which might be about to be cleared.
+        */
+       if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) {
+               if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags))
+                       __kthread_bind(k, kthread->cpu, TASK_PARKED);
+               wake_up_state(k, TASK_PARKED);
+       }
+}
+
 /**
  * kthread_unpark - unpark a thread created by kthread_create().
  * @k:         thread created by kthread_create().
@@ -336,20 +352,8 @@ void kthread_unpark(struct task_struct *k)
 {
        struct kthread *kthread = task_get_live_kthread(k);
 
-       if (kthread) {
-               clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
-               /*
-                * We clear the IS_PARKED bit here as we don't wait
-                * until the task has left the park code. So if we'd
-                * park before that happens we'd see the IS_PARKED bit
-                * which might be about to be cleared.
-                */
-               if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) {
-                       if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags))
-                               __kthread_bind(k, kthread->cpu);
-                       wake_up_process(k);
-               }
-       }
+       if (kthread)
+               __kthread_unpark(k, kthread);
        put_task_struct(k);
 }
 
@@ -407,7 +411,7 @@ int kthread_stop(struct task_struct *k)
        trace_sched_kthread_stop(k);
        if (kthread) {
                set_bit(KTHREAD_SHOULD_STOP, &kthread->flags);
-               clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
+               __kthread_unpark(k, kthread);
                wake_up_process(k);
                wait_for_completion(&kthread->exited);
        }
index 8a0efac4f99de7c5d0711bea6792db1f385f66eb..6a3bccba7e7df98df709c11c9284ef146eb5c00c 100644 (file)
@@ -380,6 +380,13 @@ static int verbose(struct lock_class *class)
 unsigned long nr_stack_trace_entries;
 static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES];
 
+static void print_lockdep_off(const char *bug_msg)
+{
+       printk(KERN_DEBUG "%s\n", bug_msg);
+       printk(KERN_DEBUG "turning off the locking correctness validator.\n");
+       printk(KERN_DEBUG "Please attach the output of /proc/lock_stat to the bug report\n");
+}
+
 static int save_trace(struct stack_trace *trace)
 {
        trace->nr_entries = 0;
@@ -409,8 +416,7 @@ static int save_trace(struct stack_trace *trace)
                if (!debug_locks_off_graph_unlock())
                        return 0;
 
-               printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n");
-               printk("turning off the locking correctness validator.\n");
+               print_lockdep_off("BUG: MAX_STACK_TRACE_ENTRIES too low!");
                dump_stack();
 
                return 0;
@@ -763,8 +769,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
                }
                raw_local_irq_restore(flags);
 
-               printk("BUG: MAX_LOCKDEP_KEYS too low!\n");
-               printk("turning off the locking correctness validator.\n");
+               print_lockdep_off("BUG: MAX_LOCKDEP_KEYS too low!");
                dump_stack();
                return NULL;
        }
@@ -834,8 +839,7 @@ static struct lock_list *alloc_list_entry(void)
                if (!debug_locks_off_graph_unlock())
                        return NULL;
 
-               printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n");
-               printk("turning off the locking correctness validator.\n");
+               print_lockdep_off("BUG: MAX_LOCKDEP_ENTRIES too low!");
                dump_stack();
                return NULL;
        }
@@ -2000,7 +2004,7 @@ static inline int lookup_chain_cache(struct task_struct *curr,
        struct lock_class *class = hlock_class(hlock);
        struct list_head *hash_head = chainhashentry(chain_key);
        struct lock_chain *chain;
-       struct held_lock *hlock_curr, *hlock_next;
+       struct held_lock *hlock_curr;
        int i, j;
 
        /*
@@ -2048,8 +2052,7 @@ cache_hit:
                if (!debug_locks_off_graph_unlock())
                        return 0;
 
-               printk("BUG: MAX_LOCKDEP_CHAINS too low!\n");
-               printk("turning off the locking correctness validator.\n");
+               print_lockdep_off("BUG: MAX_LOCKDEP_CHAINS too low!");
                dump_stack();
                return 0;
        }
@@ -2057,12 +2060,10 @@ cache_hit:
        chain->chain_key = chain_key;
        chain->irq_context = hlock->irq_context;
        /* Find the first held_lock of current chain */
-       hlock_next = hlock;
        for (i = curr->lockdep_depth - 1; i >= 0; i--) {
                hlock_curr = curr->held_locks + i;
-               if (hlock_curr->irq_context != hlock_next->irq_context)
+               if (hlock_curr->irq_context != hlock->irq_context)
                        break;
-               hlock_next = hlock;
        }
        i++;
        chain->depth = curr->lockdep_depth + 1 - i;
@@ -3190,9 +3191,9 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
 #endif
        if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) {
                debug_locks_off();
-               printk("BUG: MAX_LOCK_DEPTH too low, depth: %i  max: %lu!\n",
+               print_lockdep_off("BUG: MAX_LOCK_DEPTH too low!");
+               printk(KERN_DEBUG "depth: %i  max: %lu!\n",
                       curr->lockdep_depth, MAX_LOCK_DEPTH);
-               printk("turning off the locking correctness validator.\n");
 
                lockdep_print_held_locks(current);
                debug_show_all_locks();
index 52f23011b6e0f1001eeaa01a6d2f821206cf588b..ad53a664f113b7036fc9abed4d7d73f0be5b2479 100644 (file)
 # include <asm/mutex.h>
 #endif
 
+/*
+ * A negative mutex count indicates that waiters are sleeping waiting for the
+ * mutex.
+ */
+#define        MUTEX_SHOW_NO_WAITER(mutex)     (atomic_read(&(mutex)->count) >= 0)
+
 void
 __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
 {
@@ -44,6 +50,9 @@ __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
        spin_lock_init(&lock->wait_lock);
        INIT_LIST_HEAD(&lock->wait_list);
        mutex_clear_owner(lock);
+#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
+       lock->spin_mlock = NULL;
+#endif
 
        debug_mutex_init(lock, name, key);
 }
@@ -95,6 +104,124 @@ void __sched mutex_lock(struct mutex *lock)
 EXPORT_SYMBOL(mutex_lock);
 #endif
 
+#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
+/*
+ * In order to avoid a stampede of mutex spinners from acquiring the mutex
+ * more or less simultaneously, the spinners need to acquire a MCS lock
+ * first before spinning on the owner field.
+ *
+ * We don't inline mspin_lock() so that perf can correctly account for the
+ * time spent in this lock function.
+ */
+struct mspin_node {
+       struct mspin_node *next ;
+       int               locked;       /* 1 if lock acquired */
+};
+#define        MLOCK(mutex)    ((struct mspin_node **)&((mutex)->spin_mlock))
+
+static noinline
+void mspin_lock(struct mspin_node **lock, struct mspin_node *node)
+{
+       struct mspin_node *prev;
+
+       /* Init node */
+       node->locked = 0;
+       node->next   = NULL;
+
+       prev = xchg(lock, node);
+       if (likely(prev == NULL)) {
+               /* Lock acquired */
+               node->locked = 1;
+               return;
+       }
+       ACCESS_ONCE(prev->next) = node;
+       smp_wmb();
+       /* Wait until the lock holder passes the lock down */
+       while (!ACCESS_ONCE(node->locked))
+               arch_mutex_cpu_relax();
+}
+
+static void mspin_unlock(struct mspin_node **lock, struct mspin_node *node)
+{
+       struct mspin_node *next = ACCESS_ONCE(node->next);
+
+       if (likely(!next)) {
+               /*
+                * Release the lock by setting it to NULL
+                */
+               if (cmpxchg(lock, node, NULL) == node)
+                       return;
+               /* Wait until the next pointer is set */
+               while (!(next = ACCESS_ONCE(node->next)))
+                       arch_mutex_cpu_relax();
+       }
+       ACCESS_ONCE(next->locked) = 1;
+       smp_wmb();
+}
+
+/*
+ * Mutex spinning code migrated from kernel/sched/core.c
+ */
+
+static inline bool owner_running(struct mutex *lock, struct task_struct *owner)
+{
+       if (lock->owner != owner)
+               return false;
+
+       /*
+        * Ensure we emit the owner->on_cpu, dereference _after_ checking
+        * lock->owner still matches owner, if that fails, owner might
+        * point to free()d memory, if it still matches, the rcu_read_lock()
+        * ensures the memory stays valid.
+        */
+       barrier();
+
+       return owner->on_cpu;
+}
+
+/*
+ * Look out! "owner" is an entirely speculative pointer
+ * access and not reliable.
+ */
+static noinline
+int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
+{
+       rcu_read_lock();
+       while (owner_running(lock, owner)) {
+               if (need_resched())
+                       break;
+
+               arch_mutex_cpu_relax();
+       }
+       rcu_read_unlock();
+
+       /*
+        * We break out the loop above on need_resched() and when the
+        * owner changed, which is a sign for heavy contention. Return
+        * success only when lock->owner is NULL.
+        */
+       return lock->owner == NULL;
+}
+
+/*
+ * Initial check for entering the mutex spinning loop
+ */
+static inline int mutex_can_spin_on_owner(struct mutex *lock)
+{
+       int retval = 1;
+
+       rcu_read_lock();
+       if (lock->owner)
+               retval = lock->owner->on_cpu;
+       rcu_read_unlock();
+       /*
+        * if lock->owner is not set, the mutex owner may have just acquired
+        * it and not set the owner yet or the mutex has been released.
+        */
+       return retval;
+}
+#endif
+
 static __used noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
 
 /**
@@ -158,25 +285,39 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
         *
         * We can't do this for DEBUG_MUTEXES because that relies on wait_lock
         * to serialize everything.
+        *
+        * The mutex spinners are queued up using MCS lock so that only one
+        * spinner can compete for the mutex. However, if mutex spinning isn't
+        * going to happen, there is no point in going through the lock/unlock
+        * overhead.
         */
+       if (!mutex_can_spin_on_owner(lock))
+               goto slowpath;
 
        for (;;) {
                struct task_struct *owner;
+               struct mspin_node  node;
 
                /*
                 * If there's an owner, wait for it to either
                 * release the lock or go to sleep.
                 */
+               mspin_lock(MLOCK(lock), &node);
                owner = ACCESS_ONCE(lock->owner);
-               if (owner && !mutex_spin_on_owner(lock, owner))
+               if (owner && !mutex_spin_on_owner(lock, owner)) {
+                       mspin_unlock(MLOCK(lock), &node);
                        break;
+               }
 
-               if (atomic_cmpxchg(&lock->count, 1, 0) == 1) {
+               if ((atomic_read(&lock->count) == 1) &&
+                   (atomic_cmpxchg(&lock->count, 1, 0) == 1)) {
                        lock_acquired(&lock->dep_map, ip);
                        mutex_set_owner(lock);
+                       mspin_unlock(MLOCK(lock), &node);
                        preempt_enable();
                        return 0;
                }
+               mspin_unlock(MLOCK(lock), &node);
 
                /*
                 * When there's no owner, we might have preempted between the
@@ -195,6 +336,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                 */
                arch_mutex_cpu_relax();
        }
+slowpath:
 #endif
        spin_lock_mutex(&lock->wait_lock, flags);
 
@@ -205,7 +347,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
        list_add_tail(&waiter.list, &lock->wait_list);
        waiter.task = task;
 
-       if (atomic_xchg(&lock->count, -1) == 1)
+       if (MUTEX_SHOW_NO_WAITER(lock) && (atomic_xchg(&lock->count, -1) == 1))
                goto done;
 
        lock_contended(&lock->dep_map, ip);
@@ -220,7 +362,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                 * that when we release the lock, we properly wake up the
                 * other waiters:
                 */
-               if (atomic_xchg(&lock->count, -1) == 1)
+               if (MUTEX_SHOW_NO_WAITER(lock) &&
+                  (atomic_xchg(&lock->count, -1) == 1))
                        break;
 
                /*
index 7890b10084a71e4deff2a1ed652c7011358fc3b4..1d96dd0d93c1aa24eaff65f13b9df2cc22945ae2 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/freezer.h>
+#include <linux/stat.h>
 
 #include "rtmutex.h"
 
@@ -366,8 +367,8 @@ static ssize_t sysfs_test_status(struct device *dev, struct device_attribute *at
        return curr - buf;
 }
 
-static DEVICE_ATTR(status, 0600, sysfs_test_status, NULL);
-static DEVICE_ATTR(command, 0600, NULL, sysfs_test_command);
+static DEVICE_ATTR(status, S_IRUSR, sysfs_test_status, NULL);
+static DEVICE_ATTR(command, S_IWUSR, NULL, sysfs_test_command);
 
 static struct bus_type rttest_subsys = {
        .name = "rttest",
index c685e31492dfcd38ff830ffbc0aecbd77e29ee83..c3ae1446461c0ffc22f41cc03a7504a84576b48b 100644 (file)
@@ -176,10 +176,36 @@ static u64 sched_clock_remote(struct sched_clock_data *scd)
        u64 this_clock, remote_clock;
        u64 *ptr, old_val, val;
 
+#if BITS_PER_LONG != 64
+again:
+       /*
+        * Careful here: The local and the remote clock values need to
+        * be read out atomic as we need to compare the values and
+        * then update either the local or the remote side. So the
+        * cmpxchg64 below only protects one readout.
+        *
+        * We must reread via sched_clock_local() in the retry case on
+        * 32bit as an NMI could use sched_clock_local() via the
+        * tracer and hit between the readout of
+        * the low32bit and the high 32bit portion.
+        */
+       this_clock = sched_clock_local(my_scd);
+       /*
+        * We must enforce atomic readout on 32bit, otherwise the
+        * update on the remote cpu can hit inbetween the readout of
+        * the low32bit and the high 32bit portion.
+        */
+       remote_clock = cmpxchg64(&scd->clock, 0, 0);
+#else
+       /*
+        * On 64bit the read of [my]scd->clock is atomic versus the
+        * update, so we can avoid the above 32bit dance.
+        */
        sched_clock_local(my_scd);
 again:
        this_clock = my_scd->clock;
        remote_clock = scd->clock;
+#endif
 
        /*
         * Use the opportunity that we have both locks
index 7f12624a393c3100506e5a3eaf588b5f463332ee..42053547e0f5fc754d4a367814369cf476eea473 100644 (file)
@@ -1498,8 +1498,10 @@ static void try_to_wake_up_local(struct task_struct *p)
 {
        struct rq *rq = task_rq(p);
 
-       BUG_ON(rq != this_rq());
-       BUG_ON(p == current);
+       if (WARN_ON_ONCE(rq != this_rq()) ||
+           WARN_ON_ONCE(p == current))
+               return;
+
        lockdep_assert_held(&rq->lock);
 
        if (!raw_spin_trylock(&p->pi_lock)) {
@@ -2997,51 +2999,6 @@ void __sched schedule_preempt_disabled(void)
        preempt_disable();
 }
 
-#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
-
-static inline bool owner_running(struct mutex *lock, struct task_struct *owner)
-{
-       if (lock->owner != owner)
-               return false;
-
-       /*
-        * Ensure we emit the owner->on_cpu, dereference _after_ checking
-        * lock->owner still matches owner, if that fails, owner might
-        * point to free()d memory, if it still matches, the rcu_read_lock()
-        * ensures the memory stays valid.
-        */
-       barrier();
-
-       return owner->on_cpu;
-}
-
-/*
- * Look out! "owner" is an entirely speculative pointer
- * access and not reliable.
- */
-int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
-{
-       if (!sched_feat(OWNER_SPIN))
-               return 0;
-
-       rcu_read_lock();
-       while (owner_running(lock, owner)) {
-               if (need_resched())
-                       break;
-
-               arch_mutex_cpu_relax();
-       }
-       rcu_read_unlock();
-
-       /*
-        * We break out the loop above on need_resched() and when the
-        * owner changed, which is a sign for heavy contention. Return
-        * success only when lock->owner is NULL.
-        */
-       return lock->owner == NULL;
-}
-#endif
-
 #ifdef CONFIG_PREEMPT
 /*
  * this is the entry point to schedule() from in-kernel preemption
@@ -4999,7 +4956,7 @@ static void sd_free_ctl_entry(struct ctl_table **tablep)
 }
 
 static int min_load_idx = 0;
-static int max_load_idx = CPU_LOAD_IDX_MAX;
+static int max_load_idx = CPU_LOAD_IDX_MAX-1;
 
 static void
 set_table_entry(struct ctl_table *entry,
index ed12cbb135f4b8ded0d3c7be26a67d1df8d2ffc2..e93cca92f38b77cce7ce1f49491a393fb79ee346 100644 (file)
@@ -310,7 +310,7 @@ void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times)
 
        t = tsk;
        do {
-               task_cputime(tsk, &utime, &stime);
+               task_cputime(t, &utime, &stime);
                times->utime += utime;
                times->stime += stime;
                times->sum_exec_runtime += task_sched_runtime(t);
index 1ad1d2b5395fae04e413238e53d314ab6fbe2b9c..99399f8e4799b118e81486f9bc9b672947fd1ab7 100644 (file)
@@ -45,13 +45,6 @@ SCHED_FEAT(HRTICK, false)
 SCHED_FEAT(DOUBLE_TICK, false)
 SCHED_FEAT(LB_BIAS, true)
 
-/*
- * Spin-wait on mutex acquisition when the mutex owner is running on
- * another cpu -- assumes that when the owner is running, it will soon
- * release the lock. Decreases scheduling overhead.
- */
-SCHED_FEAT(OWNER_SPIN, true)
-
 /*
  * Decrement CPU power based on time not spent running tasks
  */
index dd72567767d963ccb8ac2f3cfa4a824fa5f81b4e..598dc06be4214c7a11fbf128baff984fa9c1c4b5 100644 (file)
@@ -2948,7 +2948,7 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
 
 static int do_tkill(pid_t tgid, pid_t pid, int sig)
 {
-       struct siginfo info;
+       struct siginfo info = {};
 
        info.si_signo = sig;
        info.si_errno = 0;
index 8eaed9aa9cf0c1995520605af1de8ef3b9e95485..02fc5c9336735a834378dbbb6fff8e57b919b0fa 100644 (file)
@@ -185,8 +185,18 @@ __smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu)
        }
        get_task_struct(tsk);
        *per_cpu_ptr(ht->store, cpu) = tsk;
-       if (ht->create)
-               ht->create(cpu);
+       if (ht->create) {
+               /*
+                * Make sure that the task has actually scheduled out
+                * into park position, before calling the create
+                * callback. At least the migration thread callback
+                * requires that the task is off the runqueue.
+                */
+               if (!wait_task_inactive(tsk, TASK_PARKED))
+                       WARN_ON(1);
+               else
+                       ht->create(cpu);
+       }
        return 0;
 }
 
index 39c9c4a2949f3166b114f11534957ff2f6060565..0da73cf73e60937ba8eb65a77f20febcb8264c45 100644 (file)
@@ -324,7 +324,6 @@ void kernel_restart_prepare(char *cmd)
        system_state = SYSTEM_RESTART;
        usermodehelper_disable();
        device_shutdown();
-       syscore_shutdown();
 }
 
 /**
@@ -370,6 +369,7 @@ void kernel_restart(char *cmd)
 {
        kernel_restart_prepare(cmd);
        disable_nonboot_cpus();
+       syscore_shutdown();
        if (!cmd)
                printk(KERN_EMERG "Restarting system.\n");
        else
@@ -395,6 +395,7 @@ static void kernel_shutdown_prepare(enum system_states state)
 void kernel_halt(void)
 {
        kernel_shutdown_prepare(SYSTEM_HALT);
+       disable_nonboot_cpus();
        syscore_shutdown();
        printk(KERN_EMERG "System halted.\n");
        kmsg_dump(KMSG_DUMP_HALT);
index 9e5b8c272eecc9121e8d3e064f30220c71c7e957..5a0f781cd729870892d105f24cc552a9d28b23e6 100644 (file)
@@ -739,12 +739,6 @@ static void blk_add_trace_rq_complete(void *ignore,
                                      struct request_queue *q,
                                      struct request *rq)
 {
-       struct blk_trace *bt = q->blk_trace;
-
-       /* if control ever passes through here, it's a request based driver */
-       if (unlikely(bt && !bt->rq_based))
-               bt->rq_based = true;
-
        blk_add_trace_rq(q, rq, BLK_TA_COMPLETE);
 }
 
@@ -780,24 +774,10 @@ static void blk_add_trace_bio_bounce(void *ignore,
        blk_add_trace_bio(q, bio, BLK_TA_BOUNCE, 0);
 }
 
-static void blk_add_trace_bio_complete(void *ignore, struct bio *bio, int error)
+static void blk_add_trace_bio_complete(void *ignore,
+                                      struct request_queue *q, struct bio *bio,
+                                      int error)
 {
-       struct request_queue *q;
-       struct blk_trace *bt;
-
-       if (!bio->bi_bdev)
-               return;
-
-       q = bdev_get_queue(bio->bi_bdev);
-       bt = q->blk_trace;
-
-       /*
-        * Request based drivers will generate both rq and bio completions.
-        * Ignore bio ones.
-        */
-       if (likely(!bt) || bt->rq_based)
-               return;
-
        blk_add_trace_bio(q, bio, BLK_TA_COMPLETE, error);
 }
 
index 6893d5a2bf086014f2919496ca7062c246935dad..b3fde6d7b7fc47683244a5a432ab35a543551499 100644 (file)
@@ -66,7 +66,7 @@
 
 static struct ftrace_ops ftrace_list_end __read_mostly = {
        .func           = ftrace_stub,
-       .flags          = FTRACE_OPS_FL_RECURSION_SAFE,
+       .flags          = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB,
 };
 
 /* ftrace_enabled is a method to turn ftrace on or off */
@@ -694,7 +694,6 @@ int ftrace_profile_pages_init(struct ftrace_profile_stat *stat)
                free_page(tmp);
        }
 
-       free_page((unsigned long)stat->pages);
        stat->pages = NULL;
        stat->start = NULL;
 
@@ -1053,6 +1052,19 @@ static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
 
 static struct pid * const ftrace_swapper_pid = &init_struct_pid;
 
+loff_t
+ftrace_filter_lseek(struct file *file, loff_t offset, int whence)
+{
+       loff_t ret;
+
+       if (file->f_mode & FMODE_READ)
+               ret = seq_lseek(file, offset, whence);
+       else
+               file->f_pos = ret = 1;
+
+       return ret;
+}
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 #ifndef CONFIG_FTRACE_MCOUNT_RECORD
@@ -2613,7 +2625,7 @@ static void ftrace_filter_reset(struct ftrace_hash *hash)
  * routine, you can use ftrace_filter_write() for the write
  * routine if @flag has FTRACE_ITER_FILTER set, or
  * ftrace_notrace_write() if @flag has FTRACE_ITER_NOTRACE set.
- * ftrace_regex_lseek() should be used as the lseek routine, and
+ * ftrace_filter_lseek() should be used as the lseek routine, and
  * release must call ftrace_regex_release().
  */
 int
@@ -2697,19 +2709,6 @@ ftrace_notrace_open(struct inode *inode, struct file *file)
                                 inode, file);
 }
 
-loff_t
-ftrace_regex_lseek(struct file *file, loff_t offset, int whence)
-{
-       loff_t ret;
-
-       if (file->f_mode & FMODE_READ)
-               ret = seq_lseek(file, offset, whence);
-       else
-               file->f_pos = ret = 1;
-
-       return ret;
-}
-
 static int ftrace_match(char *str, char *regex, int len, int type)
 {
        int matched = 0;
@@ -3441,14 +3440,14 @@ static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata;
 
 static int __init set_ftrace_notrace(char *str)
 {
-       strncpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
+       strlcpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
        return 1;
 }
 __setup("ftrace_notrace=", set_ftrace_notrace);
 
 static int __init set_ftrace_filter(char *str)
 {
-       strncpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
+       strlcpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
        return 1;
 }
 __setup("ftrace_filter=", set_ftrace_filter);
@@ -3571,7 +3570,7 @@ static const struct file_operations ftrace_filter_fops = {
        .open = ftrace_filter_open,
        .read = seq_read,
        .write = ftrace_filter_write,
-       .llseek = ftrace_regex_lseek,
+       .llseek = ftrace_filter_lseek,
        .release = ftrace_regex_release,
 };
 
@@ -3579,7 +3578,7 @@ static const struct file_operations ftrace_notrace_fops = {
        .open = ftrace_notrace_open,
        .read = seq_read,
        .write = ftrace_notrace_write,
-       .llseek = ftrace_regex_lseek,
+       .llseek = ftrace_filter_lseek,
        .release = ftrace_regex_release,
 };
 
@@ -3784,8 +3783,8 @@ static const struct file_operations ftrace_graph_fops = {
        .open           = ftrace_graph_open,
        .read           = seq_read,
        .write          = ftrace_graph_write,
+       .llseek         = ftrace_filter_lseek,
        .release        = ftrace_graph_release,
-       .llseek         = seq_lseek,
 };
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
@@ -4131,7 +4130,8 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
        preempt_disable_notrace();
        trace_recursion_set(TRACE_CONTROL_BIT);
        do_for_each_ftrace_op(op, ftrace_control_list) {
-               if (!ftrace_function_local_disabled(op) &&
+               if (!(op->flags & FTRACE_OPS_FL_STUB) &&
+                   !ftrace_function_local_disabled(op) &&
                    ftrace_ops_test(op, ip))
                        op->func(ip, parent_ip, op, regs);
        } while_for_each_ftrace_op(op);
@@ -4439,7 +4439,7 @@ static const struct file_operations ftrace_pid_fops = {
        .open           = ftrace_pid_open,
        .write          = ftrace_pid_write,
        .read           = seq_read,
-       .llseek         = seq_lseek,
+       .llseek         = ftrace_filter_lseek,
        .release        = ftrace_pid_release,
 };
 
@@ -4555,12 +4555,8 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
                ftrace_startup_sysctl();
 
                /* we are starting ftrace again */
-               if (ftrace_ops_list != &ftrace_list_end) {
-                       if (ftrace_ops_list->next == &ftrace_list_end)
-                               ftrace_trace_function = ftrace_ops_list->func;
-                       else
-                               ftrace_trace_function = ftrace_ops_list_func;
-               }
+               if (ftrace_ops_list != &ftrace_list_end)
+                       update_ftrace_function();
 
        } else {
                /* stopping ftrace calls (just send to ftrace_stub) */
index 4f1dade56981d6fe5d880e9f6caaf609ab1e9c02..66338c4f7f4bdb6142c2b21a99f14292c708d050 100644 (file)
@@ -132,7 +132,7 @@ static char *default_bootup_tracer;
 
 static int __init set_cmdline_ftrace(char *str)
 {
-       strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
+       strlcpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
        default_bootup_tracer = bootup_tracer_buf;
        /* We are using ftrace early, expand it */
        ring_buffer_expanded = 1;
@@ -162,7 +162,7 @@ static char *trace_boot_options __initdata;
 
 static int __init set_trace_boot_options(char *str)
 {
-       strncpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);
+       strlcpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);
        trace_boot_options = trace_boot_options_buf;
        return 0;
 }
@@ -744,8 +744,11 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
                return;
 
        WARN_ON_ONCE(!irqs_disabled());
-       if (WARN_ON_ONCE(!current_trace->allocated_snapshot))
+       if (!current_trace->allocated_snapshot) {
+               /* Only the nop tracer should hit this when disabling */
+               WARN_ON_ONCE(current_trace != &nop_trace);
                return;
+       }
 
        arch_spin_lock(&ftrace_max_lock);
 
index 42ca822fc7019670d8bea7291caea4110477749b..83a8b5b7bd35fa01a5e0302d83bf3d33d81f9557 100644 (file)
@@ -322,7 +322,7 @@ static const struct file_operations stack_trace_filter_fops = {
        .open = stack_trace_filter_open,
        .read = seq_read,
        .write = ftrace_filter_write,
-       .llseek = ftrace_regex_lseek,
+       .llseek = ftrace_filter_lseek,
        .release = ftrace_regex_release,
 };
 
index a54f26f82eb250a60c7f24ecc651c6c1bbf8cc88..e134d8f365ddea425ac6a8df541875038928298d 100644 (file)
@@ -25,7 +25,8 @@
 
 static struct kmem_cache *user_ns_cachep __read_mostly;
 
-static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
+static bool new_idmap_permitted(const struct file *file,
+                               struct user_namespace *ns, int cap_setid,
                                struct uid_gid_map *map);
 
 static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
@@ -612,10 +613,10 @@ static ssize_t map_write(struct file *file, const char __user *buf,
        if (map->nr_extents != 0)
                goto out;
 
-       /* Require the appropriate privilege CAP_SETUID or CAP_SETGID
-        * over the user namespace in order to set the id mapping.
+       /*
+        * Adjusting namespace settings requires capabilities on the target.
         */
-       if (cap_valid(cap_setid) && !ns_capable(ns, cap_setid))
+       if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN))
                goto out;
 
        /* Get a buffer */
@@ -700,7 +701,7 @@ static ssize_t map_write(struct file *file, const char __user *buf,
 
        ret = -EPERM;
        /* Validate the user is allowed to use user id's mapped to. */
-       if (!new_idmap_permitted(ns, cap_setid, &new_map))
+       if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
                goto out;
 
        /* Map the lower ids from the parent user namespace to the
@@ -787,7 +788,8 @@ ssize_t proc_projid_map_write(struct file *file, const char __user *buf, size_t
                         &ns->projid_map, &ns->parent->projid_map);
 }
 
-static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
+static bool new_idmap_permitted(const struct file *file, 
+                               struct user_namespace *ns, int cap_setid,
                                struct uid_gid_map *new_map)
 {
        /* Allow mapping to your own filesystem ids */
@@ -795,12 +797,12 @@ static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
                u32 id = new_map->extent[0].lower_first;
                if (cap_setid == CAP_SETUID) {
                        kuid_t uid = make_kuid(ns->parent, id);
-                       if (uid_eq(uid, current_fsuid()))
+                       if (uid_eq(uid, file->f_cred->fsuid))
                                return true;
                }
                else if (cap_setid == CAP_SETGID) {
                        kgid_t gid = make_kgid(ns->parent, id);
-                       if (gid_eq(gid, current_fsgid()))
+                       if (gid_eq(gid, file->f_cred->fsgid))
                                return true;
                }
        }
@@ -811,8 +813,10 @@ static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
 
        /* Allow the specified ids if we have the appropriate capability
         * (CAP_SETUID or CAP_SETGID) over the parent user namespace.
+        * And the opener of the id file also had the approprpiate capability.
         */
-       if (ns_capable(ns->parent, cap_setid))
+       if (ns_capable(ns->parent, cap_setid) &&
+           file_ns_capable(file, ns->parent, cap_setid))
                return true;
 
        return false;
index 3958dc4389f993cc204670706e834c42be80165b..fe01d418b09ae4d13a15b59039ef27602d1ad0f3 100644 (file)
@@ -404,4 +404,7 @@ config OID_REGISTRY
        help
          Enable fast lookup object identifier registry.
 
+config UCS2_STRING
+        tristate
+
 endmenu
index d7946ff75b2ea0f4baca2716aba3f41577f9b904..6e2cc561f761af79f2d555ca688bbcfe676de602 100644 (file)
@@ -174,3 +174,5 @@ quiet_cmd_build_OID_registry = GEN     $@
       cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@
 
 clean-files    += oid_registry_data.c
+
+obj-$(CONFIG_UCS2_STRING) += ucs2_string.o
index e07ee1fcd6f19da086439ffbeacd8376e4b3e533..a65486613d79775bf87918b390d8edd608d55cef 100644 (file)
@@ -529,6 +529,13 @@ struct kobject *kobject_get(struct kobject *kobj)
        return kobj;
 }
 
+static struct kobject *kobject_get_unless_zero(struct kobject *kobj)
+{
+       if (!kref_get_unless_zero(&kobj->kref))
+               kobj = NULL;
+       return kobj;
+}
+
 /*
  * kobject_cleanup - free kobject resources.
  * @kobj: object to cleanup
@@ -751,7 +758,7 @@ struct kobject *kset_find_obj(struct kset *kset, const char *name)
 
        list_for_each_entry(k, &kset->list, entry) {
                if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
-                       ret = kobject_get(k);
+                       ret = kobject_get_unless_zero(k);
                        break;
                }
        }
index bfe02b8fc55b3d1c383832148e4e5aa44e0ef87c..d23762e6652c1e02bf87f070d3164afa93dc91a8 100644 (file)
@@ -105,9 +105,9 @@ setup_io_tlb_npages(char *str)
        if (!strcmp(str, "force"))
                swiotlb_force = 1;
 
-       return 1;
+       return 0;
 }
-__setup("swiotlb=", setup_io_tlb_npages);
+early_param("swiotlb", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
 unsigned long swiotlb_nr_tbl(void)
@@ -115,6 +115,18 @@ unsigned long swiotlb_nr_tbl(void)
        return io_tlb_nslabs;
 }
 EXPORT_SYMBOL_GPL(swiotlb_nr_tbl);
+
+/* default to 64MB */
+#define IO_TLB_DEFAULT_SIZE (64UL<<20)
+unsigned long swiotlb_size_or_default(void)
+{
+       unsigned long size;
+
+       size = io_tlb_nslabs << IO_TLB_SHIFT;
+
+       return size ? size : (IO_TLB_DEFAULT_SIZE);
+}
+
 /* Note that this doesn't work with highmem page */
 static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
                                      volatile void *address)
@@ -188,8 +200,7 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 void  __init
 swiotlb_init(int verbose)
 {
-       /* default to 64MB */
-       size_t default_size = 64UL<<20;
+       size_t default_size = IO_TLB_DEFAULT_SIZE;
        unsigned char *vstart;
        unsigned long bytes;
 
diff --git a/lib/ucs2_string.c b/lib/ucs2_string.c
new file mode 100644 (file)
index 0000000..6f500ef
--- /dev/null
@@ -0,0 +1,51 @@
+#include <linux/ucs2_string.h>
+#include <linux/module.h>
+
+/* Return the number of unicode characters in data */
+unsigned long
+ucs2_strnlen(const ucs2_char_t *s, size_t maxlength)
+{
+        unsigned long length = 0;
+
+        while (*s++ != 0 && length < maxlength)
+                length++;
+        return length;
+}
+EXPORT_SYMBOL(ucs2_strnlen);
+
+unsigned long
+ucs2_strlen(const ucs2_char_t *s)
+{
+        return ucs2_strnlen(s, ~0UL);
+}
+EXPORT_SYMBOL(ucs2_strlen);
+
+/*
+ * Return the number of bytes is the length of this string
+ * Note: this is NOT the same as the number of unicode characters
+ */
+unsigned long
+ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength)
+{
+        return ucs2_strnlen(data, maxlength/sizeof(ucs2_char_t)) * sizeof(ucs2_char_t);
+}
+EXPORT_SYMBOL(ucs2_strsize);
+
+int
+ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len)
+{
+        while (1) {
+                if (len == 0)
+                        return 0;
+                if (*a < *b)
+                        return -1;
+                if (*a > *b)
+                        return 1;
+                if (*a == 0) /* implies *b == 0 */
+                        return 0;
+                a++;
+                b++;
+                len--;
+        }
+}
+EXPORT_SYMBOL(ucs2_strncmp);
index ca9a7c6d7e973c5db4bbecd7e72139d5c9529b72..1a12f5b9a0aba45396fccc46d14d2b6534c30263 100644 (file)
@@ -2961,7 +2961,17 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        break;
                }
 
-               if (absent ||
+               /*
+                * We need call hugetlb_fault for both hugepages under migration
+                * (in which case hugetlb_fault waits for the migration,) and
+                * hwpoisoned hugepages (in which case we need to prevent the
+                * caller from accessing to them.) In order to do this, we use
+                * here is_swap_pte instead of is_hugetlb_entry_migration and
+                * is_hugetlb_entry_hwpoisoned. This is because it simply covers
+                * both cases, and because we can't follow correct pages
+                * directly from any kind of swap entries.
+                */
+               if (absent || is_swap_pte(huge_ptep_get(pte)) ||
                    ((flags & FOLL_WRITE) && !pte_write(huge_ptep_get(pte)))) {
                        int ret;
 
index 494526ae024a3173fc200d47e36087f6252852c2..ba94dec5b25900e47093544e11f8c765bf243f9d 100644 (file)
@@ -216,6 +216,7 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm)
        tlb->mm = mm;
 
        tlb->fullmm     = fullmm;
+       tlb->need_flush_all = 0;
        tlb->start      = -1UL;
        tlb->end        = 0;
        tlb->need_flush = 0;
@@ -2392,6 +2393,53 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
 }
 EXPORT_SYMBOL(remap_pfn_range);
 
+/**
+ * vm_iomap_memory - remap memory to userspace
+ * @vma: user vma to map to
+ * @start: start of area
+ * @len: size of area
+ *
+ * This is a simplified io_remap_pfn_range() for common driver use. The
+ * driver just needs to give us the physical memory range to be mapped,
+ * we'll figure out the rest from the vma information.
+ *
+ * NOTE! Some drivers might want to tweak vma->vm_page_prot first to get
+ * whatever write-combining details or similar.
+ */
+int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len)
+{
+       unsigned long vm_len, pfn, pages;
+
+       /* Check that the physical memory area passed in looks valid */
+       if (start + len < start)
+               return -EINVAL;
+       /*
+        * You *really* shouldn't map things that aren't page-aligned,
+        * but we've historically allowed it because IO memory might
+        * just have smaller alignment.
+        */
+       len += start & ~PAGE_MASK;
+       pfn = start >> PAGE_SHIFT;
+       pages = (len + ~PAGE_MASK) >> PAGE_SHIFT;
+       if (pfn + pages < pfn)
+               return -EINVAL;
+
+       /* We start the mapping 'vm_pgoff' pages into the area */
+       if (vma->vm_pgoff > pages)
+               return -EINVAL;
+       pfn += vma->vm_pgoff;
+       pages -= vma->vm_pgoff;
+
+       /* Can we fit all of the mapping? */
+       vm_len = vma->vm_end - vma->vm_start;
+       if (vm_len >> PAGE_SHIFT > pages)
+               return -EINVAL;
+
+       /* Ok, let it rip */
+       return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot);
+}
+EXPORT_SYMBOL(vm_iomap_memory);
+
 static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
                                     unsigned long addr, unsigned long end,
                                     pte_fn_t fn, void *data)
index 6466699b16cbca1a26c8792f9d484925a23df005..0db0de1c2fbee21e0e9919af66021b190d789731 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1940,7 +1940,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
 
        /* Check the cache first. */
        /* (Cache hit rate is typically around 35%.) */
-       vma = mm->mmap_cache;
+       vma = ACCESS_ONCE(mm->mmap_cache);
        if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) {
                struct rb_node *rb_node;
 
index e19328087534af9f77371866c9afe30c70e3ff89..e001768b14e810029d65f1dce09cc5a391f56985 100644 (file)
@@ -821,7 +821,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
        struct vm_area_struct *vma;
 
        /* check the cache first */
-       vma = mm->mmap_cache;
+       vma = ACCESS_ONCE(mm->mmap_cache);
        if (vma && vma->vm_start <= addr && vma->vm_end > addr)
                return vma;
 
@@ -1838,6 +1838,16 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
 }
 EXPORT_SYMBOL(remap_pfn_range);
 
+int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len)
+{
+       unsigned long pfn = start >> PAGE_SHIFT;
+       unsigned long vm_len = vma->vm_end - vma->vm_start;
+
+       pfn += vma->vm_pgoff;
+       return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot);
+}
+EXPORT_SYMBOL(vm_iomap_memory);
+
 int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
                        unsigned long pgoff)
 {
index 88c5fed8b9a4bd9a54021810cf05710cff4fcbfc..669fba39be1aa41bb9adfd040c709e43b194cfe2 100644 (file)
@@ -3188,9 +3188,9 @@ int kswapd_run(int nid)
        if (IS_ERR(pgdat->kswapd)) {
                /* failure at boot is fatal */
                BUG_ON(system_state == SYSTEM_BOOTING);
-               pgdat->kswapd = NULL;
                pr_err("Failed to start kswapd on node %d\n", nid);
                ret = PTR_ERR(pgdat->kswapd);
+               pgdat->kswapd = NULL;
        }
        return ret;
 }
index a4cc3229952a17d387411cded9bc66d940b9929f..e085bcc754f602e4401e51c8c29442a1bd143de8 100644 (file)
@@ -870,8 +870,12 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl)
         * all pending messages before the applicant is gone.
         */
        del_timer_sync(&app->join_timer);
+
+       spin_lock(&app->lock);
        mrp_mad_event(app, MRP_EVENT_TX);
        mrp_pdu_queue(app);
+       spin_unlock(&app->lock);
+
        mrp_queue_xmit(app);
 
        dev_mc_del(dev, appl->group_address);
index 7b491006eaf4000424282979b0c4709325102152..737bef59ce899adc0a3e0ba67ea3d56536e5b7e5 100644 (file)
@@ -531,6 +531,8 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
        struct sk_buff *skb;
        int copied, error = -EINVAL;
 
+       msg->msg_namelen = 0;
+
        if (sock->state != SS_CONNECTED)
                return -ENOTCONN;
 
index 7b11f8bc5071cba0de51054913fa5f3e8bb3f063..e277e38f736b93a133a6cd43cc7b264acfbad641 100644 (file)
@@ -1642,6 +1642,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
                ax25_address src;
                const unsigned char *mac = skb_mac_header(skb);
 
+               memset(sax, 0, sizeof(struct full_sockaddr_ax25));
                ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL,
                                &digi, NULL, NULL);
                sax->sax25_family = AF_AX25;
index 0488d70c8c3512bef0311f1611d0a4a362b9057e..fa563e497c4861a3fd1656a91887eed47e81ec81 100644 (file)
@@ -169,7 +169,7 @@ void batadv_mesh_free(struct net_device *soft_iface)
        atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
 }
 
-int batadv_is_my_mac(const uint8_t *addr)
+int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr)
 {
        const struct batadv_hard_iface *hard_iface;
 
@@ -178,6 +178,9 @@ int batadv_is_my_mac(const uint8_t *addr)
                if (hard_iface->if_status != BATADV_IF_ACTIVE)
                        continue;
 
+               if (hard_iface->soft_iface != bat_priv->soft_iface)
+                       continue;
+
                if (batadv_compare_eth(hard_iface->net_dev->dev_addr, addr)) {
                        rcu_read_unlock();
                        return 1;
index ced08b936a9690a6f7d01af7f7eb8a31f3e1f29d..d40910dfc8ea5a20fbe2c839f59bd65018bf1c28 100644 (file)
@@ -162,7 +162,7 @@ extern struct workqueue_struct *batadv_event_workqueue;
 
 int batadv_mesh_init(struct net_device *soft_iface);
 void batadv_mesh_free(struct net_device *soft_iface);
-int batadv_is_my_mac(const uint8_t *addr);
+int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr);
 struct batadv_hard_iface *
 batadv_seq_print_text_primary_if_get(struct seq_file *seq);
 int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
index 5ee21cebbbb0953fd7708b84761f379d8a1423e5..319f2906c71a2146328c1e6ad1c4e9cbedee1e53 100644 (file)
@@ -402,7 +402,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
                goto out;
 
        /* not for me */
-       if (!batadv_is_my_mac(ethhdr->h_dest))
+       if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
                goto out;
 
        icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
@@ -416,7 +416,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        }
 
        /* packet for me */
-       if (batadv_is_my_mac(icmp_packet->dst))
+       if (batadv_is_my_mac(bat_priv, icmp_packet->dst))
                return batadv_recv_my_icmp_packet(bat_priv, skb, hdr_size);
 
        /* TTL exceeded */
@@ -548,7 +548,8 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig,
        return router;
 }
 
-static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size)
+static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
+                                      struct sk_buff *skb, int hdr_size)
 {
        struct ethhdr *ethhdr;
 
@@ -567,7 +568,7 @@ static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size)
                return -1;
 
        /* not for me */
-       if (!batadv_is_my_mac(ethhdr->h_dest))
+       if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
                return -1;
 
        return 0;
@@ -582,7 +583,7 @@ int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
        char tt_flag;
        size_t packet_size;
 
-       if (batadv_check_unicast_packet(skb, hdr_size) < 0)
+       if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
                return NET_RX_DROP;
 
        /* I could need to modify it */
@@ -614,7 +615,7 @@ int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
        case BATADV_TT_RESPONSE:
                batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
 
-               if (batadv_is_my_mac(tt_query->dst)) {
+               if (batadv_is_my_mac(bat_priv, tt_query->dst)) {
                        /* packet needs to be linearized to access the TT
                         * changes
                         */
@@ -657,14 +658,15 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
        struct batadv_roam_adv_packet *roam_adv_packet;
        struct batadv_orig_node *orig_node;
 
-       if (batadv_check_unicast_packet(skb, sizeof(*roam_adv_packet)) < 0)
+       if (batadv_check_unicast_packet(bat_priv, skb,
+                                       sizeof(*roam_adv_packet)) < 0)
                goto out;
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
 
        roam_adv_packet = (struct batadv_roam_adv_packet *)skb->data;
 
-       if (!batadv_is_my_mac(roam_adv_packet->dst))
+       if (!batadv_is_my_mac(bat_priv, roam_adv_packet->dst))
                return batadv_route_unicast_packet(skb, recv_if);
 
        /* check if it is a backbone gateway. we don't accept
@@ -967,7 +969,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
         * last time) the packet had an updated information or not
         */
        curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
-       if (!batadv_is_my_mac(unicast_packet->dest)) {
+       if (!batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
                orig_node = batadv_orig_hash_find(bat_priv,
                                                  unicast_packet->dest);
                /* if it is not possible to find the orig_node representing the
@@ -1044,14 +1046,14 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
        if (is4addr)
                hdr_size = sizeof(*unicast_4addr_packet);
 
-       if (batadv_check_unicast_packet(skb, hdr_size) < 0)
+       if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
                return NET_RX_DROP;
 
        if (!batadv_check_unicast_ttvn(bat_priv, skb))
                return NET_RX_DROP;
 
        /* packet for me */
-       if (batadv_is_my_mac(unicast_packet->dest)) {
+       if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
                if (is4addr) {
                        batadv_dat_inc_counter(bat_priv,
                                               unicast_4addr_packet->subtype);
@@ -1088,7 +1090,7 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
        struct sk_buff *new_skb = NULL;
        int ret;
 
-       if (batadv_check_unicast_packet(skb, hdr_size) < 0)
+       if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
                return NET_RX_DROP;
 
        if (!batadv_check_unicast_ttvn(bat_priv, skb))
@@ -1097,7 +1099,7 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
 
        /* packet for me */
-       if (batadv_is_my_mac(unicast_packet->dest)) {
+       if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
                ret = batadv_frag_reassemble_skb(skb, bat_priv, &new_skb);
 
                if (ret == NET_RX_DROP)
@@ -1151,13 +1153,13 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
                goto out;
 
        /* ignore broadcasts sent by myself */
-       if (batadv_is_my_mac(ethhdr->h_source))
+       if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
                goto out;
 
        bcast_packet = (struct batadv_bcast_packet *)skb->data;
 
        /* ignore broadcasts originated by myself */
-       if (batadv_is_my_mac(bcast_packet->orig))
+       if (batadv_is_my_mac(bat_priv, bcast_packet->orig))
                goto out;
 
        if (bcast_packet->header.ttl < 2)
@@ -1243,14 +1245,14 @@ int batadv_recv_vis_packet(struct sk_buff *skb,
        ethhdr = (struct ethhdr *)skb_mac_header(skb);
 
        /* not for me */
-       if (!batadv_is_my_mac(ethhdr->h_dest))
+       if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
                return NET_RX_DROP;
 
        /* ignore own packets */
-       if (batadv_is_my_mac(vis_packet->vis_orig))
+       if (batadv_is_my_mac(bat_priv, vis_packet->vis_orig))
                return NET_RX_DROP;
 
-       if (batadv_is_my_mac(vis_packet->sender_orig))
+       if (batadv_is_my_mac(bat_priv, vis_packet->sender_orig))
                return NET_RX_DROP;
 
        switch (vis_packet->vis_type) {
index 98a66a021a602678d515df58199895bceef31a92..7abee19567e9e0f84ecb224e666f2e6c1094333c 100644 (file)
@@ -1953,7 +1953,7 @@ out:
 bool batadv_send_tt_response(struct batadv_priv *bat_priv,
                             struct batadv_tt_query_packet *tt_request)
 {
-       if (batadv_is_my_mac(tt_request->dst)) {
+       if (batadv_is_my_mac(bat_priv, tt_request->dst)) {
                /* don't answer backbone gws! */
                if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_request->src))
                        return true;
index c053244b97bd38e03a588c1c629e6081d06b2154..6a1e646be96d45b21e21127a056a9aad3af91bb1 100644 (file)
@@ -477,7 +477,7 @@ void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
 
        /* Are we the target for this VIS packet? */
        if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC   &&
-           batadv_is_my_mac(vis_packet->target_orig))
+           batadv_is_my_mac(bat_priv, vis_packet->target_orig))
                are_target = 1;
 
        spin_lock_bh(&bat_priv->vis.hash_lock);
@@ -496,7 +496,7 @@ void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
                batadv_send_list_add(bat_priv, info);
 
                /* ... we're not the recipient (and thus need to forward). */
-       } else if (!batadv_is_my_mac(packet->target_orig)) {
+       } else if (!batadv_is_my_mac(bat_priv, packet->target_orig)) {
                batadv_send_list_add(bat_priv, info);
        }
 
index d3ee69b35a78267f35b8ea4a9b32d367160eea21..0d1b08cc76e1d73acba966e4c22f64c0285cce05 100644 (file)
@@ -230,6 +230,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
        if (flags & (MSG_OOB))
                return -EOPNOTSUPP;
 
+       msg->msg_namelen = 0;
+
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb) {
                if (sk->sk_shutdown & RCV_SHUTDOWN)
@@ -237,8 +239,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                return err;
        }
 
-       msg->msg_namelen = 0;
-
        copied = skb->len;
        if (len < copied) {
                msg->msg_flags |= MSG_TRUNC;
index c23bae86263b6e98a21a8f69ae45190b827b2376..7c9224bcce178c493ce0a19f3f8250b1828d39b8 100644 (file)
@@ -608,6 +608,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
                rfcomm_dlc_accept(d);
+               msg->msg_namelen = 0;
                return 0;
        }
 
index fad0302bdb325e5df700edf4fe323c6226216599..fb6192c9812e81bcac3d8dea31f60095aa40ffda 100644 (file)
@@ -665,6 +665,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
            test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
                hci_conn_accept(pi->conn->hcon, 0);
                sk->sk_state = BT_CONFIG;
+               msg->msg_namelen = 0;
 
                release_sock(sk);
                return 0;
index ef1b91431c6bb1e0627119f877eca0d2339a899c..459dab22b3f6009dc027c01e29fe587270291053 100644 (file)
@@ -67,7 +67,8 @@ void br_port_carrier_check(struct net_bridge_port *p)
        struct net_device *dev = p->dev;
        struct net_bridge *br = p->br;
 
-       if (netif_running(dev) && netif_oper_up(dev))
+       if (!(p->flags & BR_ADMIN_COST) &&
+           netif_running(dev) && netif_oper_up(dev))
                p->path_cost = port_cost(dev);
 
        if (!netif_running(br->dev))
index 3cbf5beb3d4be267fbea19a2fd81b7b09d3d6a0c..d2c043a857b6a0fd3bfd208f018179b96c42dacd 100644 (file)
@@ -156,6 +156,7 @@ struct net_bridge_port
 #define BR_BPDU_GUARD           0x00000002
 #define BR_ROOT_BLOCK          0x00000004
 #define BR_MULTICAST_FAST_LEAVE        0x00000008
+#define BR_ADMIN_COST          0x00000010
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
        u32                             multicast_startup_queries_sent;
index 0bdb4ebd362b7818229bb50f13d25f7e1181dcad..d45e760141bb81a34909b98724b2d8f3fc876136 100644 (file)
@@ -288,6 +288,7 @@ int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost)
            path_cost > BR_MAX_PATH_COST)
                return -ERANGE;
 
+       p->flags |= BR_ADMIN_COST;
        p->path_cost = path_cost;
        br_configuration_update(p->br);
        br_port_state_selection(p->br);
index 095259f839023a99a2127d1d4173bb29737471df..ff2ff3ce6965a73dcf74918cd5c5bcc1b4a7d51b 100644 (file)
@@ -286,6 +286,8 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
        if (m->msg_flags&MSG_OOB)
                goto read_error;
 
+       m->msg_namelen = 0;
+
        skb = skb_recv_datagram(sk, flags, 0 , &ret);
        if (!skb)
                goto read_error;
index 2d117dc5ebea0e027e34e844dc7685720a93c033..117814a7e73c720b20026289f4349528e8ed6f6a 100644 (file)
@@ -466,7 +466,7 @@ static int cgw_notifier(struct notifier_block *nb,
                        if (gwj->src.dev == dev || gwj->dst.dev == dev) {
                                hlist_del(&gwj->list);
                                cgw_unregister_filter(gwj);
-                               kfree(gwj);
+                               kmem_cache_free(cgw_cache, gwj);
                        }
                }
        }
@@ -864,7 +864,7 @@ static void cgw_remove_all_jobs(void)
        hlist_for_each_entry_safe(gwj, nx, &cgw_list, list) {
                hlist_del(&gwj->list);
                cgw_unregister_filter(gwj);
-               kfree(gwj);
+               kmem_cache_free(cgw_cache, gwj);
        }
 }
 
@@ -920,7 +920,7 @@ static int cgw_remove_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
 
                hlist_del(&gwj->list);
                cgw_unregister_filter(gwj);
-               kfree(gwj);
+               kmem_cache_free(cgw_cache, gwj);
                err = 0;
                break;
        }
index b13e5c766c11359507a61bb9689c9841d660951a..b24ab0e98eb4d8dd8cef2a20ef2a39b97d9ece92 100644 (file)
@@ -1624,7 +1624,6 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
        }
 
        skb_orphan(skb);
-       nf_reset(skb);
 
        if (unlikely(!is_skb_forwardable(dev, skb))) {
                atomic_long_inc(&dev->rx_dropped);
@@ -1640,6 +1639,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
        skb->mark = 0;
        secpath_reset(skb);
        nf_reset(skb);
+       nf_reset_trace(skb);
        return netif_rx(skb);
 }
 EXPORT_SYMBOL_GPL(dev_forward_skb);
@@ -2148,6 +2148,9 @@ static void skb_warn_bad_offload(const struct sk_buff *skb)
        struct net_device *dev = skb->dev;
        const char *driver = "";
 
+       if (!net_ratelimit())
+               return;
+
        if (dev && dev->dev.parent)
                driver = dev_driver_string(dev->dev.parent);
 
@@ -3314,6 +3317,7 @@ int netdev_rx_handler_register(struct net_device *dev,
        if (dev->rx_handler)
                return -EBUSY;
 
+       /* Note: rx_handler_data must be set before rx_handler */
        rcu_assign_pointer(dev->rx_handler_data, rx_handler_data);
        rcu_assign_pointer(dev->rx_handler, rx_handler);
 
@@ -3334,6 +3338,11 @@ void netdev_rx_handler_unregister(struct net_device *dev)
 
        ASSERT_RTNL();
        RCU_INIT_POINTER(dev->rx_handler, NULL);
+       /* a reader seeing a non NULL rx_handler in a rcu_read_lock()
+        * section has a guarantee to see a non NULL rx_handler_data
+        * as well.
+        */
+       synchronize_net();
        RCU_INIT_POINTER(dev->rx_handler_data, NULL);
 }
 EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
index bd2eb9d3e369c3ea0cdeac568600fd929c0b0d48..abdc9e6ef33e988ed3e2e00fada13b4ac3147143 100644 (file)
@@ -37,7 +37,7 @@ static int __hw_addr_create_ex(struct netdev_hw_addr_list *list,
        ha->type = addr_type;
        ha->refcount = 1;
        ha->global_use = global;
-       ha->synced = false;
+       ha->synced = 0;
        list_add_tail_rcu(&ha->list, &list->list);
        list->count++;
 
@@ -165,7 +165,7 @@ int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
                                            addr_len, ha->type);
                        if (err)
                                break;
-                       ha->synced = true;
+                       ha->synced++;
                        ha->refcount++;
                } else if (ha->refcount == 1) {
                        __hw_addr_del(to_list, ha->addr, addr_len, ha->type);
@@ -186,7 +186,7 @@ void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
                if (ha->synced) {
                        __hw_addr_del(to_list, ha->addr,
                                      addr_len, ha->type);
-                       ha->synced = false;
+                       ha->synced--;
                        __hw_addr_del(from_list, ha->addr,
                                      addr_len, ha->type);
                }
index c56ea6f7f6c7c88acbe602a3470c979622345713..2bfd081c59f7706cbd9d8a5ba8a5780aaaae23d1 100644 (file)
@@ -328,7 +328,7 @@ static void flow_cache_flush_per_cpu(void *data)
        struct flow_flush_info *info = data;
        struct tasklet_struct *tasklet;
 
-       tasklet = this_cpu_ptr(&info->cache->percpu->flush_tasklet);
+       tasklet = &this_cpu_ptr(info->cache->percpu)->flush_tasklet;
        tasklet->data = (unsigned long)info;
        tasklet_schedule(tasklet);
 }
index 5fb8d7e472941fede3595a3a4032cfc21fbe849b..23854b51a259cb8b65c2bb1ee4be8e32e0ca0eb8 100644 (file)
@@ -496,8 +496,10 @@ static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
        }
        if (ops->fill_info) {
                data = nla_nest_start(skb, IFLA_INFO_DATA);
-               if (data == NULL)
+               if (data == NULL) {
+                       err = -EMSGSIZE;
                        goto err_cancel_link;
+               }
                err = ops->fill_info(skb, dev);
                if (err < 0)
                        goto err_cancel_data;
@@ -1070,7 +1072,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
        rcu_read_lock();
        cb->seq = net->dev_base_seq;
 
-       if (nlmsg_parse(cb->nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
+       if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
                        ifla_policy) >= 0) {
 
                if (tb[IFLA_EXT_MASK])
@@ -1920,7 +1922,7 @@ static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh)
        u32 ext_filter_mask = 0;
        u16 min_ifinfo_dump_size = 0;
 
-       if (nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
+       if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
                        ifla_policy) >= 0) {
                if (tb[IFLA_EXT_MASK])
                        ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
index f678507bc8291f7df43108f470e41c3929af50e8..c6287cd978c2db7b40f3aa3fe06b5d43bced64d5 100644 (file)
@@ -587,13 +587,16 @@ static void check_lifetime(struct work_struct *work)
 {
        unsigned long now, next, next_sec, next_sched;
        struct in_ifaddr *ifa;
+       struct hlist_node *n;
        int i;
 
        now = jiffies;
        next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY);
 
-       rcu_read_lock();
        for (i = 0; i < IN4_ADDR_HSIZE; i++) {
+               bool change_needed = false;
+
+               rcu_read_lock();
                hlist_for_each_entry_rcu(ifa, &inet_addr_lst[i], hash) {
                        unsigned long age;
 
@@ -606,16 +609,7 @@ static void check_lifetime(struct work_struct *work)
 
                        if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME &&
                            age >= ifa->ifa_valid_lft) {
-                               struct in_ifaddr **ifap ;
-
-                               rtnl_lock();
-                               for (ifap = &ifa->ifa_dev->ifa_list;
-                                    *ifap != NULL; ifap = &ifa->ifa_next) {
-                                       if (*ifap == ifa)
-                                               inet_del_ifa(ifa->ifa_dev,
-                                                            ifap, 1);
-                               }
-                               rtnl_unlock();
+                               change_needed = true;
                        } else if (ifa->ifa_preferred_lft ==
                                   INFINITY_LIFE_TIME) {
                                continue;
@@ -625,10 +619,8 @@ static void check_lifetime(struct work_struct *work)
                                        next = ifa->ifa_tstamp +
                                               ifa->ifa_valid_lft * HZ;
 
-                               if (!(ifa->ifa_flags & IFA_F_DEPRECATED)) {
-                                       ifa->ifa_flags |= IFA_F_DEPRECATED;
-                                       rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0);
-                               }
+                               if (!(ifa->ifa_flags & IFA_F_DEPRECATED))
+                                       change_needed = true;
                        } else if (time_before(ifa->ifa_tstamp +
                                               ifa->ifa_preferred_lft * HZ,
                                               next)) {
@@ -636,8 +628,42 @@ static void check_lifetime(struct work_struct *work)
                                       ifa->ifa_preferred_lft * HZ;
                        }
                }
+               rcu_read_unlock();
+               if (!change_needed)
+                       continue;
+               rtnl_lock();
+               hlist_for_each_entry_safe(ifa, n, &inet_addr_lst[i], hash) {
+                       unsigned long age;
+
+                       if (ifa->ifa_flags & IFA_F_PERMANENT)
+                               continue;
+
+                       /* We try to batch several events at once. */
+                       age = (now - ifa->ifa_tstamp +
+                              ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
+
+                       if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME &&
+                           age >= ifa->ifa_valid_lft) {
+                               struct in_ifaddr **ifap;
+
+                               for (ifap = &ifa->ifa_dev->ifa_list;
+                                    *ifap != NULL; ifap = &(*ifap)->ifa_next) {
+                                       if (*ifap == ifa) {
+                                               inet_del_ifa(ifa->ifa_dev,
+                                                            ifap, 1);
+                                               break;
+                                       }
+                               }
+                       } else if (ifa->ifa_preferred_lft !=
+                                  INFINITY_LIFE_TIME &&
+                                  age >= ifa->ifa_preferred_lft &&
+                                  !(ifa->ifa_flags & IFA_F_DEPRECATED)) {
+                               ifa->ifa_flags |= IFA_F_DEPRECATED;
+                               rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0);
+                       }
+               }
+               rtnl_unlock();
        }
-       rcu_read_unlock();
 
        next_sec = round_jiffies_up(next);
        next_sched = next;
@@ -802,8 +828,12 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
                if (nlh->nlmsg_flags & NLM_F_EXCL ||
                    !(nlh->nlmsg_flags & NLM_F_REPLACE))
                        return -EEXIST;
-
-               set_ifa_lifetime(ifa_existing, valid_lft, prefered_lft);
+               ifa = ifa_existing;
+               set_ifa_lifetime(ifa, valid_lft, prefered_lft);
+               cancel_delayed_work(&check_lifetime_work);
+               schedule_delayed_work(&check_lifetime_work, 0);
+               rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid);
+               blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
        }
        return 0;
 }
index 3b4f0cd2e63edbd136683577873b288712a4b92a..4cfe34d4cc967a94ed15f2deef3d249d2429e846 100644 (file)
@@ -139,8 +139,6 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 
        /* skb is pure payload to encrypt */
 
-       err = -ENOMEM;
-
        esp = x->data;
        aead = esp->aead;
        alen = crypto_aead_authsize(aead);
@@ -176,8 +174,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
        }
 
        tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
-       if (!tmp)
+       if (!tmp) {
+               err = -ENOMEM;
                goto error;
+       }
 
        seqhi = esp_tmp_seqhi(tmp);
        iv = esp_tmp_iv(aead, tmp, seqhilen);
index a6445b843ef40774f2bf5014e6800e1f4fd86b3e..52c273ea05c34c902e07c00609b4f881c392c37b 100644 (file)
@@ -248,8 +248,7 @@ static void ip_expire(unsigned long arg)
                if (!head->dev)
                        goto out_rcu_unlock;
 
-               /* skb dst is stale, drop it, and perform route lookup again */
-               skb_dst_drop(head);
+               /* skb has no dst, perform route lookup again */
                iph = ip_hdr(head);
                err = ip_route_input_noref(head, iph->daddr, iph->saddr,
                                           iph->tos, head->dev);
@@ -523,9 +522,16 @@ found:
                qp->q.max_size = skb->len + ihl;
 
        if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
-           qp->q.meat == qp->q.len)
-               return ip_frag_reasm(qp, prev, dev);
+           qp->q.meat == qp->q.len) {
+               unsigned long orefdst = skb->_skb_refdst;
 
+               skb->_skb_refdst = 0UL;
+               err = ip_frag_reasm(qp, prev, dev);
+               skb->_skb_refdst = orefdst;
+               return err;
+       }
+
+       skb_dst_drop(skb);
        inet_frag_lru_move(&qp->q);
        return -EINPROGRESS;
 
index c30130062cd6515f31d7497eaa6a403d2b1d629d..c49dcd0284a06c6bb4b4e6787af5888289ba50f3 100644 (file)
@@ -66,6 +66,12 @@ static bool rpfilter_lookup_reverse(struct flowi4 *fl4,
        return dev_match;
 }
 
+static bool rpfilter_is_local(const struct sk_buff *skb)
+{
+       const struct rtable *rt = skb_rtable(skb);
+       return rt && (rt->rt_flags & RTCF_LOCAL);
+}
+
 static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
        const struct xt_rpfilter_info *info;
@@ -76,7 +82,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
        info = par->matchinfo;
        invert = info->flags & XT_RPFILTER_INVERT;
 
-       if (par->in->flags & IFF_LOOPBACK)
+       if (rpfilter_is_local(skb))
                return true ^ invert;
 
        iph = ip_hdr(skb);
index ef54377fb11cbdd3f327fa29c45c623923b8cb2f..397e0f69435fd1b1b4b3775cadc409d67ea63332 100644 (file)
@@ -349,8 +349,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
         * hasn't changed since we received the original syn, but I see
         * no easy way to do this.
         */
-       flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
-                          RT_SCOPE_UNIVERSE, IPPROTO_TCP,
+       flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark,
+                          RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
                           inet_sk_flowi_flags(sk),
                           (opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
                           ireq->loc_addr, th->source, th->dest);
index 3bd55bad230ac7f822f4ea75eb280bc8ce0c07fc..13b9c08fc1582531aa34eef92a432dc96f2a1c52 100644 (file)
@@ -113,6 +113,7 @@ int sysctl_tcp_early_retrans __read_mostly = 2;
 #define FLAG_DSACKING_ACK      0x800 /* SACK blocks contained D-SACK info */
 #define FLAG_NONHEAD_RETRANS_ACKED     0x1000 /* Non-head rexmitted data was ACKed */
 #define FLAG_SACK_RENEGING     0x2000 /* snd_una advanced to a sacked seq */
+#define FLAG_UPDATE_TS_RECENT  0x4000 /* tcp_replace_ts_recent() */
 
 #define FLAG_ACKED             (FLAG_DATA_ACKED|FLAG_SYN_ACKED)
 #define FLAG_NOT_DUP           (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
@@ -3564,6 +3565,27 @@ static void tcp_send_challenge_ack(struct sock *sk)
        }
 }
 
+static void tcp_store_ts_recent(struct tcp_sock *tp)
+{
+       tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
+       tp->rx_opt.ts_recent_stamp = get_seconds();
+}
+
+static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
+{
+       if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) {
+               /* PAWS bug workaround wrt. ACK frames, the PAWS discard
+                * extra check below makes sure this can only happen
+                * for pure ACK frames.  -DaveM
+                *
+                * Not only, also it occurs for expired timestamps.
+                */
+
+               if (tcp_paws_check(&tp->rx_opt, 0))
+                       tcp_store_ts_recent(tp);
+       }
+}
+
 /* This routine deals with incoming acks, but not outgoing ones. */
 static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 {
@@ -3607,6 +3629,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        prior_fackets = tp->fackets_out;
        prior_in_flight = tcp_packets_in_flight(tp);
 
+       /* ts_recent update must be made after we are sure that the packet
+        * is in window.
+        */
+       if (flag & FLAG_UPDATE_TS_RECENT)
+               tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
        if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
                /* Window is constant, pure forward advance.
                 * No more checks are required.
@@ -3927,27 +3955,6 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th)
 EXPORT_SYMBOL(tcp_parse_md5sig_option);
 #endif
 
-static inline void tcp_store_ts_recent(struct tcp_sock *tp)
-{
-       tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
-       tp->rx_opt.ts_recent_stamp = get_seconds();
-}
-
-static inline void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
-{
-       if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) {
-               /* PAWS bug workaround wrt. ACK frames, the PAWS discard
-                * extra check below makes sure this can only happen
-                * for pure ACK frames.  -DaveM
-                *
-                * Not only, also it occurs for expired timestamps.
-                */
-
-               if (tcp_paws_check(&tp->rx_opt, 0))
-                       tcp_store_ts_recent(tp);
-       }
-}
-
 /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM
  *
  * It is not fatal. If this ACK does _not_ change critical state (seqs, window)
@@ -5543,14 +5550,9 @@ slow_path:
                return 0;
 
 step5:
-       if (tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
+       if (tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0)
                goto discard;
 
-       /* ts_recent update must be made after we are sure that the packet
-        * is in window.
-        */
-       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
        tcp_rcv_rtt_measure_ts(sk, skb);
 
        /* Process urgent data. */
@@ -5986,7 +5988,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 
        /* step 5: check the ACK field */
        if (true) {
-               int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0;
+               int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH |
+                                                 FLAG_UPDATE_TS_RECENT) > 0;
 
                switch (sk->sk_state) {
                case TCP_SYN_RECV:
@@ -6137,11 +6140,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                }
        }
 
-       /* ts_recent update must be made after we are sure that the packet
-        * is in window.
-        */
-       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
        /* step 6: check the URG bit */
        tcp_urg(sk, skb, th);
 
index 5d0b4387cba6df401166a48f1e4cf3800d6ce6ff..509912a5ff98e73edfe9d60295de196ed16874a2 100644 (file)
@@ -2388,8 +2388,12 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
         */
        TCP_SKB_CB(skb)->when = tcp_time_stamp;
 
-       /* make sure skb->data is aligned on arches that require it */
-       if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
+       /* make sure skb->data is aligned on arches that require it
+        * and check if ack-trimming & collapsing extended the headroom
+        * beyond what csum_start can cover.
+        */
+       if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) ||
+                    skb_headroom(skb) >= 0xFFFF)) {
                struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
                                                   GFP_ATOMIC);
                return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
@@ -2709,6 +2713,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
        skb_reserve(skb, MAX_TCP_HEADER);
 
        skb_dst_set(skb, dst);
+       security_skb_owned_by(skb, sk);
 
        mss = dst_metric_advmss(dst);
        if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss)
index 26512250e095557e50fbee26cc5dcd65d12cc675..dae802c0af7c002df341d3dfe4ed94db6584118e 100644 (file)
@@ -168,8 +168,6 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
 static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
                               struct net_device *dev);
 
-static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
-
 static struct ipv6_devconf ipv6_devconf __read_mostly = {
        .forwarding             = 0,
        .hop_limit              = IPV6_DEFAULT_HOPLIMIT,
@@ -837,7 +835,7 @@ out2:
        rcu_read_unlock_bh();
 
        if (likely(err == 0))
-               atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
+               inet6addr_notifier_call_chain(NETDEV_UP, ifa);
        else {
                kfree(ifa);
                ifa = ERR_PTR(err);
@@ -927,7 +925,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
 
        ipv6_ifa_notify(RTM_DELADDR, ifp);
 
-       atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp);
+       inet6addr_notifier_call_chain(NETDEV_DOWN, ifp);
 
        /*
         * Purge or update corresponding prefix
@@ -2529,6 +2527,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
 static void init_loopback(struct net_device *dev)
 {
        struct inet6_dev  *idev;
+       struct net_device *sp_dev;
+       struct inet6_ifaddr *sp_ifa;
+       struct rt6_info *sp_rt;
 
        /* ::1 */
 
@@ -2540,6 +2541,30 @@ static void init_loopback(struct net_device *dev)
        }
 
        add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
+
+       /* Add routes to other interface's IPv6 addresses */
+       for_each_netdev(dev_net(dev), sp_dev) {
+               if (!strcmp(sp_dev->name, dev->name))
+                       continue;
+
+               idev = __in6_dev_get(sp_dev);
+               if (!idev)
+                       continue;
+
+               read_lock_bh(&idev->lock);
+               list_for_each_entry(sp_ifa, &idev->addr_list, if_list) {
+
+                       if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
+                               continue;
+
+                       sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
+
+                       /* Failure cases are ignored */
+                       if (!IS_ERR(sp_rt))
+                               ip6_ins_rt(sp_rt);
+               }
+               read_unlock_bh(&idev->lock);
+       }
 }
 
 static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr)
@@ -2961,7 +2986,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
 
                if (state != INET6_IFADDR_STATE_DEAD) {
                        __ipv6_ifa_notify(RTM_DELADDR, ifa);
-                       atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa);
+                       inet6addr_notifier_call_chain(NETDEV_DOWN, ifa);
                }
                in6_ifa_put(ifa);
 
@@ -4842,22 +4867,6 @@ static struct pernet_operations addrconf_ops = {
        .exit = addrconf_exit_net,
 };
 
-/*
- *      Device notifier
- */
-
-int register_inet6addr_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&inet6addr_chain, nb);
-}
-EXPORT_SYMBOL(register_inet6addr_notifier);
-
-int unregister_inet6addr_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
-}
-EXPORT_SYMBOL(unregister_inet6addr_notifier);
-
 static struct rtnl_af_ops inet6_ops = {
        .family           = AF_INET6,
        .fill_link_af     = inet6_fill_link_af,
index d051e5f4bf348092e8062b930b56881669974a95..72104562c86481311857359882669527359a7f6c 100644 (file)
@@ -78,3 +78,22 @@ int __ipv6_addr_type(const struct in6_addr *addr)
 }
 EXPORT_SYMBOL(__ipv6_addr_type);
 
+static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
+
+int register_inet6addr_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_register(&inet6addr_chain, nb);
+}
+EXPORT_SYMBOL(register_inet6addr_notifier);
+
+int unregister_inet6addr_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
+}
+EXPORT_SYMBOL(unregister_inet6addr_notifier);
+
+int inet6addr_notifier_call_chain(unsigned long val, void *v)
+{
+       return atomic_notifier_call_chain(&inet6addr_chain, val, v);
+}
+EXPORT_SYMBOL(inet6addr_notifier_call_chain);
index e33fe0ab2568ec5a750e846457ff52a6a3395c86..2bab2aa597450813ae4bd60d362998830a7e7e3b 100644 (file)
@@ -118,6 +118,18 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
            ipv6_addr_loopback(&hdr->daddr))
                goto err;
 
+       /* RFC4291 Errata ID: 3480
+        * Interface-Local scope spans only a single interface on a
+        * node and is useful only for loopback transmission of
+        * multicast.  Packets with interface-local scope received
+        * from another node must be discarded.
+        */
+       if (!(skb->pkt_type == PACKET_LOOPBACK ||
+             dev->flags & IFF_LOOPBACK) &&
+           ipv6_addr_is_multicast(&hdr->daddr) &&
+           IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
+               goto err;
+
        /* RFC4291 2.7
         * Nodes must not originate a packet to a multicast address whose scope
         * field contains the reserved value 0; if such a packet is received, it
index 33608c610276d87e9845b75555fadc6771765606..cb631143721c0afb13152121c74a9d49f51e99dc 100644 (file)
@@ -57,7 +57,7 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,
                if (pfx_len - i >= 32)
                        mask = 0;
                else
-                       mask = htonl(~((1 << (pfx_len - i)) - 1));
+                       mask = htonl((1 << (i - pfx_len + 32)) - 1);
 
                idx = i / 32;
                addr->s6_addr32[idx] &= mask;
index 5060d54199abbc180d7dc87ba072bace2bc167f7..e0983f3648a628410c6f6bfd9549ec339a325353 100644 (file)
@@ -71,6 +71,12 @@ static bool rpfilter_lookup_reverse6(const struct sk_buff *skb,
        return ret;
 }
 
+static bool rpfilter_is_local(const struct sk_buff *skb)
+{
+       const struct rt6_info *rt = (const void *) skb_dst(skb);
+       return rt && (rt->rt6i_flags & RTF_LOCAL);
+}
+
 static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
        const struct xt_rpfilter_info *info = par->matchinfo;
@@ -78,7 +84,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
        struct ipv6hdr *iph;
        bool invert = info->flags & XT_RPFILTER_INVERT;
 
-       if (par->in->flags & IFF_LOOPBACK)
+       if (rpfilter_is_local(skb))
                return true ^ invert;
 
        iph = ipv6_hdr(skb);
index 196ab9347ad1df2bab5a9c98720a51e81773985c..0ba10e53a6298f07cb64193681ccbfb419d40f36 100644 (file)
@@ -330,9 +330,17 @@ found:
        }
 
        if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
-           fq->q.meat == fq->q.len)
-               return ip6_frag_reasm(fq, prev, dev);
+           fq->q.meat == fq->q.len) {
+               int res;
+               unsigned long orefdst = skb->_skb_refdst;
+
+               skb->_skb_refdst = 0UL;
+               res = ip6_frag_reasm(fq, prev, dev);
+               skb->_skb_refdst = orefdst;
+               return res;
+       }
 
+       skb_dst_drop(skb);
        inet_frag_lru_move(&fq->q);
        return -1;
 
index f6d629fd6aee152aaff674a03db7a3dd0f194134..46a5be85be87ebed43ec8b01d6b63263df556279 100644 (file)
@@ -386,6 +386,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
                if (dst)
                        dst->ops->redirect(dst, sk, skb);
+               goto out;
        }
 
        if (type == ICMPV6_PKT_TOOBIG) {
index d28e7f014cc639779a4557203b4b2ba2f7e63927..e493b3397ae3337b4582d811febb932e0711a09e 100644 (file)
@@ -1386,6 +1386,8 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
 
        IRDA_DEBUG(4, "%s()\n", __func__);
 
+       msg->msg_namelen = 0;
+
        skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
                                flags & MSG_DONTWAIT, &err);
        if (!skb)
index 29340a9a6fb9937f9bc848ffda5c49c51cca47ee..e1b37f5a2691f7a79052f9b840aa0f9910182698 100644 (file)
@@ -303,7 +303,8 @@ static void iriap_disconnect_indication(void *instance, void *sap,
 {
        struct iriap_cb *self;
 
-       IRDA_DEBUG(4, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
+       IRDA_DEBUG(4, "%s(), reason=%s [%d]\n", __func__,
+                  irlmp_reason_str(reason), reason);
 
        self = instance;
 
index 6115a44c0a24f9ba1cb3248de38b8579118e5dbf..1064621da6f6c297ee7deaa439e9569d9f37cf73 100644 (file)
@@ -66,8 +66,15 @@ const char *irlmp_reasons[] = {
        "LM_LAP_RESET",
        "LM_INIT_DISCONNECT",
        "ERROR, NOT USED",
+       "UNKNOWN",
 };
 
+const char *irlmp_reason_str(LM_REASON reason)
+{
+       reason = min_t(size_t, reason, ARRAY_SIZE(irlmp_reasons) - 1);
+       return irlmp_reasons[reason];
+}
+
 /*
  * Function irlmp_init (void)
  *
@@ -747,7 +754,8 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
 {
        struct lsap_cb *lsap;
 
-       IRDA_DEBUG(1, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
+       IRDA_DEBUG(1, "%s(), reason=%s [%d]\n", __func__,
+                  irlmp_reason_str(reason), reason);
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
 
index a7d11ffe428428f25194702c5728562fd87a8e2b..206ce6db2c36a2ae44d694614f8be29317f5b74d 100644 (file)
@@ -49,12 +49,6 @@ static const u8 iprm_shutdown[8] =
 
 #define TRGCLS_SIZE    (sizeof(((struct iucv_message *)0)->class))
 
-/* macros to set/get socket control buffer at correct offset */
-#define CB_TAG(skb)    ((skb)->cb)             /* iucv message tag */
-#define CB_TAG_LEN     (sizeof(((struct iucv_message *) 0)->tag))
-#define CB_TRGCLS(skb) ((skb)->cb + CB_TAG_LEN) /* iucv msg target class */
-#define CB_TRGCLS_LEN  (TRGCLS_SIZE)
-
 #define __iucv_sock_wait(sk, condition, timeo, ret)                    \
 do {                                                                   \
        DEFINE_WAIT(__wait);                                            \
@@ -1141,7 +1135,7 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 
        /* increment and save iucv message tag for msg_completion cbk */
        txmsg.tag = iucv->send_tag++;
-       memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN);
+       IUCV_SKB_CB(skb)->tag = txmsg.tag;
 
        if (iucv->transport == AF_IUCV_TRANS_HIPER) {
                atomic_inc(&iucv->msg_sent);
@@ -1224,7 +1218,7 @@ static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len)
                        return -ENOMEM;
 
                /* copy target class to control buffer of new skb */
-               memcpy(CB_TRGCLS(nskb), CB_TRGCLS(skb), CB_TRGCLS_LEN);
+               IUCV_SKB_CB(nskb)->class = IUCV_SKB_CB(skb)->class;
 
                /* copy data fragment */
                memcpy(nskb->data, skb->data + copied, size);
@@ -1256,7 +1250,7 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
 
        /* store msg target class in the second 4 bytes of skb ctrl buffer */
        /* Note: the first 4 bytes are reserved for msg tag */
-       memcpy(CB_TRGCLS(skb), &msg->class, CB_TRGCLS_LEN);
+       IUCV_SKB_CB(skb)->class = msg->class;
 
        /* check for special IPRM messages (e.g. iucv_sock_shutdown) */
        if ((msg->flags & IUCV_IPRMDATA) && len > 7) {
@@ -1292,6 +1286,7 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
                }
        }
 
+       IUCV_SKB_CB(skb)->offset = 0;
        if (sock_queue_rcv_skb(sk, skb))
                skb_queue_head(&iucv_sk(sk)->backlog_skb_q, skb);
 }
@@ -1327,6 +1322,9 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
        unsigned int copied, rlen;
        struct sk_buff *skb, *rskb, *cskb;
        int err = 0;
+       u32 offset;
+
+       msg->msg_namelen = 0;
 
        if ((sk->sk_state == IUCV_DISCONN) &&
            skb_queue_empty(&iucv->backlog_skb_q) &&
@@ -1346,13 +1344,14 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                return err;
        }
 
-       rlen   = skb->len;              /* real length of skb */
+       offset = IUCV_SKB_CB(skb)->offset;
+       rlen   = skb->len - offset;             /* real length of skb */
        copied = min_t(unsigned int, rlen, len);
        if (!rlen)
                sk->sk_shutdown = sk->sk_shutdown | RCV_SHUTDOWN;
 
        cskb = skb;
-       if (skb_copy_datagram_iovec(cskb, 0, msg->msg_iov, copied)) {
+       if (skb_copy_datagram_iovec(cskb, offset, msg->msg_iov, copied)) {
                if (!(flags & MSG_PEEK))
                        skb_queue_head(&sk->sk_receive_queue, skb);
                return -EFAULT;
@@ -1370,7 +1369,8 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
         * get the trgcls from the control buffer of the skb due to
         * fragmentation of original iucv message. */
        err = put_cmsg(msg, SOL_IUCV, SCM_IUCV_TRGCLS,
-                       CB_TRGCLS_LEN, CB_TRGCLS(skb));
+                      sizeof(IUCV_SKB_CB(skb)->class),
+                      (void *)&IUCV_SKB_CB(skb)->class);
        if (err) {
                if (!(flags & MSG_PEEK))
                        skb_queue_head(&sk->sk_receive_queue, skb);
@@ -1382,9 +1382,8 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 
                /* SOCK_STREAM: re-queue skb if it contains unreceived data */
                if (sk->sk_type == SOCK_STREAM) {
-                       skb_pull(skb, copied);
-                       if (skb->len) {
-                               skb_queue_head(&sk->sk_receive_queue, skb);
+                       if (copied < rlen) {
+                               IUCV_SKB_CB(skb)->offset = offset + copied;
                                goto done;
                        }
                }
@@ -1403,6 +1402,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                spin_lock_bh(&iucv->message_q.lock);
                rskb = skb_dequeue(&iucv->backlog_skb_q);
                while (rskb) {
+                       IUCV_SKB_CB(rskb)->offset = 0;
                        if (sock_queue_rcv_skb(sk, rskb)) {
                                skb_queue_head(&iucv->backlog_skb_q,
                                                rskb);
@@ -1830,7 +1830,7 @@ static void iucv_callback_txdone(struct iucv_path *path,
                spin_lock_irqsave(&list->lock, flags);
 
                while (list_skb != (struct sk_buff *)list) {
-                       if (!memcmp(&msg->tag, CB_TAG(list_skb), CB_TAG_LEN)) {
+                       if (msg->tag != IUCV_SKB_CB(list_skb)->tag) {
                                this = list_skb;
                                break;
                        }
@@ -2091,6 +2091,7 @@ static int afiucv_hs_callback_rx(struct sock *sk, struct sk_buff *skb)
        skb_pull(skb, sizeof(struct af_iucv_trans_hdr));
        skb_reset_transport_header(skb);
        skb_reset_network_header(skb);
+       IUCV_SKB_CB(skb)->offset = 0;
        spin_lock(&iucv->message_q.lock);
        if (skb_queue_empty(&iucv->backlog_skb_q)) {
                if (sock_queue_rcv_skb(sk, skb)) {
@@ -2195,8 +2196,7 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
                /* fall through and receive zero length data */
        case 0:
                /* plain data frame */
-               memcpy(CB_TRGCLS(skb), &trans_hdr->iucv_hdr.class,
-                      CB_TRGCLS_LEN);
+               IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class;
                err = afiucv_hs_callback_rx(sk, skb);
                break;
        default:
index 8555f331ea60d4bca67cbe91390ed077f62a091e..5b1e5af257137e4c6a03a2c575f1adb5a949e25e 100644 (file)
@@ -2693,6 +2693,7 @@ static int key_notify_policy_flush(const struct km_event *c)
        hdr->sadb_msg_pid = c->portid;
        hdr->sadb_msg_version = PF_KEY_V2;
        hdr->sadb_msg_errno = (uint8_t) 0;
+       hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
        hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
        pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
        return 0;
index c74f5a91ff6a3213209c23ff488f0b475a552857..b8a6039314e868781d3130f06fbb78ced6c4a678 100644 (file)
@@ -690,6 +690,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
                lsa->l2tp_addr = ipv6_hdr(skb)->saddr;
                lsa->l2tp_flowinfo = 0;
                lsa->l2tp_scope_id = 0;
+               lsa->l2tp_conn_id = 0;
                if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL)
                        lsa->l2tp_scope_id = IP6CB(skb)->iif;
        }
index 88709882c4641f7d147fbeaa9f48323cfc8637eb..48aaa89253e037c9b7f2e07f3bc1d03d837266fd 100644 (file)
@@ -720,6 +720,8 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
        int target;     /* Read at least this many bytes */
        long timeo;
 
+       msg->msg_namelen = 0;
+
        lock_sock(sk);
        copied = -ENOTCONN;
        if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
index fb306814576affa7e636fa53353d29ba1e39b668..a6893602f87a753ebafeae0d0b8f449bdc7251f7 100644 (file)
@@ -2582,7 +2582,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
                        list_del(&dep->list);
                        mutex_unlock(&local->mtx);
 
-                       ieee80211_roc_notify_destroy(dep);
+                       ieee80211_roc_notify_destroy(dep, true);
                        return 0;
                }
 
@@ -2622,7 +2622,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
                        ieee80211_start_next_roc(local);
                mutex_unlock(&local->mtx);
 
-               ieee80211_roc_notify_destroy(found);
+               ieee80211_roc_notify_destroy(found, true);
        } else {
                /* work may be pending so use it all the time */
                found->abort = true;
@@ -2632,6 +2632,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
 
                /* work will clean up etc */
                flush_delayed_work(&found->work);
+               WARN_ON(!found->to_be_freed);
+               kfree(found);
        }
 
        return 0;
index 78c0d90dd641e459dcec9972be0d97634d58a5c6..931be419ab5aece83990b530afa5979b2053294c 100644 (file)
@@ -63,6 +63,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
                      enum ieee80211_chanctx_mode mode)
 {
        struct ieee80211_chanctx *ctx;
+       u32 changed;
        int err;
 
        lockdep_assert_held(&local->chanctx_mtx);
@@ -76,6 +77,13 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
        ctx->conf.rx_chains_dynamic = 1;
        ctx->mode = mode;
 
+       /* acquire mutex to prevent idle from changing */
+       mutex_lock(&local->mtx);
+       /* turn idle off *before* setting channel -- some drivers need that */
+       changed = ieee80211_idle_off(local);
+       if (changed)
+               ieee80211_hw_config(local, changed);
+
        if (!local->use_chanctx) {
                local->_oper_channel_type =
                        cfg80211_get_chandef_type(chandef);
@@ -85,14 +93,17 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
                err = drv_add_chanctx(local, ctx);
                if (err) {
                        kfree(ctx);
-                       return ERR_PTR(err);
+                       ctx = ERR_PTR(err);
+
+                       ieee80211_recalc_idle(local);
+                       goto out;
                }
        }
 
+       /* and keep the mutex held until the new chanctx is on the list */
        list_add_rcu(&ctx->list, &local->chanctx_list);
 
-       mutex_lock(&local->mtx);
-       ieee80211_recalc_idle(local);
+ out:
        mutex_unlock(&local->mtx);
 
        return ctx;
index 388580a1badad2acec84893fe6ec652f8ce24b6c..5672533a083279ddc50fe98a09bbd4363a9fc731 100644 (file)
@@ -309,6 +309,7 @@ struct ieee80211_roc_work {
        struct ieee80211_channel *chan;
 
        bool started, abort, hw_begun, notified;
+       bool to_be_freed;
 
        unsigned long hw_start_time;
 
@@ -1347,7 +1348,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local);
 void ieee80211_roc_setup(struct ieee80211_local *local);
 void ieee80211_start_next_roc(struct ieee80211_local *local);
 void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
-void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc);
+void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
 void ieee80211_sw_roc_work(struct work_struct *work);
 void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
 
@@ -1361,6 +1362,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
                             enum nl80211_iftype type);
 void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
 void ieee80211_remove_interfaces(struct ieee80211_local *local);
+u32 ieee80211_idle_off(struct ieee80211_local *local);
 void ieee80211_recalc_idle(struct ieee80211_local *local);
 void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
                                    const int offset);
index baaa8608e52de8d9d504f14a254bb7e6631b5f2e..9ed49ad0380f151fc5ad5448e953f6497d800291 100644 (file)
@@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
 }
 
-static u32 ieee80211_idle_off(struct ieee80211_local *local)
+static u32 __ieee80211_idle_off(struct ieee80211_local *local)
 {
        if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
                return 0;
@@ -87,7 +87,7 @@ static u32 ieee80211_idle_off(struct ieee80211_local *local)
        return IEEE80211_CONF_CHANGE_IDLE;
 }
 
-static u32 ieee80211_idle_on(struct ieee80211_local *local)
+static u32 __ieee80211_idle_on(struct ieee80211_local *local)
 {
        if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
                return 0;
@@ -98,16 +98,18 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local)
        return IEEE80211_CONF_CHANGE_IDLE;
 }
 
-void ieee80211_recalc_idle(struct ieee80211_local *local)
+static u32 __ieee80211_recalc_idle(struct ieee80211_local *local,
+                                  bool force_active)
 {
        bool working = false, scanning, active;
        unsigned int led_trig_start = 0, led_trig_stop = 0;
        struct ieee80211_roc_work *roc;
-       u32 change;
 
        lockdep_assert_held(&local->mtx);
 
-       active = !list_empty(&local->chanctx_list) || local->monitors;
+       active = force_active ||
+                !list_empty(&local->chanctx_list) ||
+                local->monitors;
 
        if (!local->ops->remain_on_channel) {
                list_for_each_entry(roc, &local->roc_list, list) {
@@ -132,9 +134,18 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
        ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
 
        if (working || scanning || active)
-               change = ieee80211_idle_off(local);
-       else
-               change = ieee80211_idle_on(local);
+               return __ieee80211_idle_off(local);
+       return __ieee80211_idle_on(local);
+}
+
+u32 ieee80211_idle_off(struct ieee80211_local *local)
+{
+       return __ieee80211_recalc_idle(local, true);
+}
+
+void ieee80211_recalc_idle(struct ieee80211_local *local)
+{
+       u32 change = __ieee80211_recalc_idle(local, false);
        if (change)
                ieee80211_hw_config(local, change);
 }
@@ -349,21 +360,19 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
 static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata;
-       int ret = 0;
+       int ret;
 
        if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
                return 0;
 
-       mutex_lock(&local->iflist_mtx);
+       ASSERT_RTNL();
 
        if (local->monitor_sdata)
-               goto out_unlock;
+               return 0;
 
        sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
-       if (!sdata) {
-               ret = -ENOMEM;
-               goto out_unlock;
-       }
+       if (!sdata)
+               return -ENOMEM;
 
        /* set up data */
        sdata->local = local;
@@ -377,13 +386,13 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
        if (WARN_ON(ret)) {
                /* ok .. stupid driver, it asked for this! */
                kfree(sdata);
-               goto out_unlock;
+               return ret;
        }
 
        ret = ieee80211_check_queues(sdata);
        if (ret) {
                kfree(sdata);
-               goto out_unlock;
+               return ret;
        }
 
        ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
@@ -391,13 +400,14 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
        if (ret) {
                drv_remove_interface(local, sdata);
                kfree(sdata);
-               goto out_unlock;
+               return ret;
        }
 
+       mutex_lock(&local->iflist_mtx);
        rcu_assign_pointer(local->monitor_sdata, sdata);
- out_unlock:
        mutex_unlock(&local->iflist_mtx);
-       return ret;
+
+       return 0;
 }
 
 static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
@@ -407,14 +417,20 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
        if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
                return;
 
+       ASSERT_RTNL();
+
        mutex_lock(&local->iflist_mtx);
 
        sdata = rcu_dereference_protected(local->monitor_sdata,
                                          lockdep_is_held(&local->iflist_mtx));
-       if (!sdata)
-               goto out_unlock;
+       if (!sdata) {
+               mutex_unlock(&local->iflist_mtx);
+               return;
+       }
 
        rcu_assign_pointer(local->monitor_sdata, NULL);
+       mutex_unlock(&local->iflist_mtx);
+
        synchronize_net();
 
        ieee80211_vif_release_channel(sdata);
@@ -422,8 +438,6 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
        drv_remove_interface(local, sdata);
 
        kfree(sdata);
- out_unlock:
-       mutex_unlock(&local->iflist_mtx);
 }
 
 /*
index 29ce2aa87e7b60fdd344f7fd8acb1148cbc477fd..4749b3858695e6c2aeae983146d6a055be562a28 100644 (file)
@@ -1060,7 +1060,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
 
        rcu_read_lock();
        list_for_each_entry_rcu(sdata, &local->interfaces, list)
-               if (ieee80211_vif_is_mesh(&sdata->vif))
+               if (ieee80211_vif_is_mesh(&sdata->vif) &&
+                   ieee80211_sdata_running(sdata))
                        ieee80211_queue_work(&local->hw, &sdata->work);
        rcu_read_unlock();
 }
index 141577412d8407fc8b18ad354a34ad8de105f154..346ad4cfb01323cf471758dd5a6fcbdb12b338a6 100644 (file)
@@ -3608,8 +3608,10 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
 
        /* Restart STA timers */
        rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list)
-               ieee80211_restart_sta_timer(sdata);
+       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+               if (ieee80211_sdata_running(sdata))
+                       ieee80211_restart_sta_timer(sdata);
+       }
        rcu_read_unlock();
 }
 
@@ -3962,8 +3964,16 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        /* prep auth_data so we don't go into idle on disassoc */
        ifmgd->auth_data = auth_data;
 
-       if (ifmgd->associated)
-               ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+       if (ifmgd->associated) {
+               u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+               ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+                                      WLAN_REASON_UNSPECIFIED,
+                                      false, frame_buf);
+
+               __cfg80211_send_deauth(sdata->dev, frame_buf,
+                                      sizeof(frame_buf));
+       }
 
        sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
 
@@ -4023,8 +4033,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 
        mutex_lock(&ifmgd->mtx);
 
-       if (ifmgd->associated)
-               ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+       if (ifmgd->associated) {
+               u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+               ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+                                      WLAN_REASON_UNSPECIFIED,
+                                      false, frame_buf);
+
+               __cfg80211_send_deauth(sdata->dev, frame_buf,
+                                      sizeof(frame_buf));
+       }
 
        if (ifmgd->auth_data && !ifmgd->auth_data->done) {
                err = -EBUSY;
index cc79b4a2e821c9232c41135da3f4397dbba67b8d..430bd254e49693bf7e62744843fff8c10a2acb9a 100644 (file)
@@ -297,10 +297,13 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
        }
 }
 
-void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
+void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free)
 {
        struct ieee80211_roc_work *dep, *tmp;
 
+       if (WARN_ON(roc->to_be_freed))
+               return;
+
        /* was never transmitted */
        if (roc->frame) {
                cfg80211_mgmt_tx_status(&roc->sdata->wdev,
@@ -316,9 +319,12 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
                                                   GFP_KERNEL);
 
        list_for_each_entry_safe(dep, tmp, &roc->dependents, list)
-               ieee80211_roc_notify_destroy(dep);
+               ieee80211_roc_notify_destroy(dep, true);
 
-       kfree(roc);
+       if (free)
+               kfree(roc);
+       else
+               roc->to_be_freed = true;
 }
 
 void ieee80211_sw_roc_work(struct work_struct *work)
@@ -331,6 +337,9 @@ void ieee80211_sw_roc_work(struct work_struct *work)
 
        mutex_lock(&local->mtx);
 
+       if (roc->to_be_freed)
+               goto out_unlock;
+
        if (roc->abort)
                goto finish;
 
@@ -370,7 +379,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
  finish:
                list_del(&roc->list);
                started = roc->started;
-               ieee80211_roc_notify_destroy(roc);
+               ieee80211_roc_notify_destroy(roc, !roc->abort);
 
                if (started) {
                        drv_flush(local, false);
@@ -410,7 +419,7 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
 
        list_del(&roc->list);
 
-       ieee80211_roc_notify_destroy(roc);
+       ieee80211_roc_notify_destroy(roc, true);
 
        /* if there's another roc, start it now */
        ieee80211_start_next_roc(local);
@@ -460,12 +469,14 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
        list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
                if (local->ops->remain_on_channel) {
                        list_del(&roc->list);
-                       ieee80211_roc_notify_destroy(roc);
+                       ieee80211_roc_notify_destroy(roc, true);
                } else {
                        ieee80211_queue_delayed_work(&local->hw, &roc->work, 0);
 
                        /* work will clean up etc */
                        flush_delayed_work(&roc->work);
+                       WARN_ON(!roc->to_be_freed);
+                       kfree(roc);
                }
        }
 
index bb73ed2d20b90e8ece75bdd41a331fecb9c9d7ac..c6844ad080beee0123969c3aca15b7ca349eddda 100644 (file)
@@ -2675,7 +2675,19 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
 
                memset(nskb->cb, 0, sizeof(nskb->cb));
 
-               ieee80211_tx_skb(rx->sdata, nskb);
+               if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
+                       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb);
+
+                       info->flags = IEEE80211_TX_CTL_TX_OFFCHAN |
+                                     IEEE80211_TX_INTFL_OFFCHAN_TX_OK |
+                                     IEEE80211_TX_CTL_NO_CCK_RATE;
+                       if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
+                               info->hw_queue =
+                                       local->hw.offchannel_tx_hw_queue;
+               }
+
+               __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7,
+                                           status->band);
        }
        dev_kfree_skb(rx->skb);
        return RX_QUEUED;
index a79ce820cb50cf01e5cff62a47b974332c3fe8d6..238a0cca320e621dad86cbca1830e4867459cb6d 100644 (file)
@@ -766,6 +766,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
        int ret, i;
+       bool have_key = false;
 
        might_sleep();
 
@@ -793,12 +794,19 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
        list_del_rcu(&sta->list);
 
        mutex_lock(&local->key_mtx);
-       for (i = 0; i < NUM_DEFAULT_KEYS; i++)
+       for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
                __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
-       if (sta->ptk)
+               have_key = true;
+       }
+       if (sta->ptk) {
                __ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
+               have_key = true;
+       }
        mutex_unlock(&local->key_mtx);
 
+       if (!have_key)
+               synchronize_net();
+
        sta->dead = true;
 
        local->num_sta--;
index 0f92dc24cb894bfa0674c2b3f6dca970d7615c64..d7df6ac2c6f10a1bf14be997a981f577e5364b98 100644 (file)
@@ -339,7 +339,11 @@ bitmap_ipmac_tlist(const struct ip_set *set,
 nla_put_failure:
        nla_nest_cancel(skb, nested);
        ipset_nest_end(skb, atd);
-       return -EMSGSIZE;
+       if (unlikely(id == first)) {
+               cb->args[2] = 0;
+               return -EMSGSIZE;
+       }
+       return 0;
 }
 
 static int
index f2627226a0870b22612fe17397c228ff7ef628b0..10a30b4fc7dba7af7ad858c566791e982475436a 100644 (file)
@@ -104,6 +104,15 @@ hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags)
        dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
 }
 
+static inline void
+hash_ipportnet4_data_reset_flags(struct hash_ipportnet4_elem *dst, u32 *flags)
+{
+       if (dst->nomatch) {
+               *flags = IPSET_FLAG_NOMATCH;
+               dst->nomatch = 0;
+       }
+}
+
 static inline int
 hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem)
 {
@@ -414,6 +423,15 @@ hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags)
        dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
 }
 
+static inline void
+hash_ipportnet6_data_reset_flags(struct hash_ipportnet6_elem *dst, u32 *flags)
+{
+       if (dst->nomatch) {
+               *flags = IPSET_FLAG_NOMATCH;
+               dst->nomatch = 0;
+       }
+}
+
 static inline int
 hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem)
 {
index 4b677cf6bf7d7899f7295fea5eeab54df84699c6..d6a59154d7104258d18335a39646fbf9e3b8f598 100644 (file)
@@ -87,7 +87,16 @@ hash_net4_data_copy(struct hash_net4_elem *dst,
 static inline void
 hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags)
 {
-       dst->nomatch = flags & IPSET_FLAG_NOMATCH;
+       dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
+}
+
+static inline void
+hash_net4_data_reset_flags(struct hash_net4_elem *dst, u32 *flags)
+{
+       if (dst->nomatch) {
+               *flags = IPSET_FLAG_NOMATCH;
+               dst->nomatch = 0;
+       }
 }
 
 static inline int
@@ -308,7 +317,16 @@ hash_net6_data_copy(struct hash_net6_elem *dst,
 static inline void
 hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags)
 {
-       dst->nomatch = flags & IPSET_FLAG_NOMATCH;
+       dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
+}
+
+static inline void
+hash_net6_data_reset_flags(struct hash_net6_elem *dst, u32 *flags)
+{
+       if (dst->nomatch) {
+               *flags = IPSET_FLAG_NOMATCH;
+               dst->nomatch = 0;
+       }
 }
 
 static inline int
index 6ba985f1c96ff5ef43bf0ad599e9792bd64f54ef..f2b0a3c30130ba66bc69fe24b39cb54cdbc0c77a 100644 (file)
@@ -198,7 +198,16 @@ hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
 static inline void
 hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags)
 {
-       dst->nomatch = flags & IPSET_FLAG_NOMATCH;
+       dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
+}
+
+static inline void
+hash_netiface4_data_reset_flags(struct hash_netiface4_elem *dst, u32 *flags)
+{
+       if (dst->nomatch) {
+               *flags = IPSET_FLAG_NOMATCH;
+               dst->nomatch = 0;
+       }
 }
 
 static inline int
@@ -494,7 +503,7 @@ hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
 static inline void
 hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags)
 {
-       dst->nomatch = flags & IPSET_FLAG_NOMATCH;
+       dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
 }
 
 static inline int
@@ -503,6 +512,15 @@ hash_netiface6_data_match(const struct hash_netiface6_elem *elem)
        return elem->nomatch ? -ENOTEMPTY : 1;
 }
 
+static inline void
+hash_netiface6_data_reset_flags(struct hash_netiface6_elem *dst, u32 *flags)
+{
+       if (dst->nomatch) {
+               *flags = IPSET_FLAG_NOMATCH;
+               dst->nomatch = 0;
+       }
+}
+
 static inline void
 hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
 {
index af20c0c5ced2e9204df65ddaf37424a9b589be99..349deb672a2d4fd8303ab43bdb3f0207c9124e0d 100644 (file)
@@ -104,6 +104,15 @@ hash_netport4_data_flags(struct hash_netport4_elem *dst, u32 flags)
        dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
 }
 
+static inline void
+hash_netport4_data_reset_flags(struct hash_netport4_elem *dst, u32 *flags)
+{
+       if (dst->nomatch) {
+               *flags = IPSET_FLAG_NOMATCH;
+               dst->nomatch = 0;
+       }
+}
+
 static inline int
 hash_netport4_data_match(const struct hash_netport4_elem *elem)
 {
@@ -375,6 +384,15 @@ hash_netport6_data_flags(struct hash_netport6_elem *dst, u32 flags)
        dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
 }
 
+static inline void
+hash_netport6_data_reset_flags(struct hash_netport6_elem *dst, u32 *flags)
+{
+       if (dst->nomatch) {
+               *flags = IPSET_FLAG_NOMATCH;
+               dst->nomatch = 0;
+       }
+}
+
 static inline int
 hash_netport6_data_match(const struct hash_netport6_elem *elem)
 {
index 8371c2bac2e4240eb5c4b3f6abd0faa48f6212ce..09c744aa89829cb7f99878974ef2471364135f27 100644 (file)
@@ -174,9 +174,13 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
 {
        const struct set_elem *e = list_set_elem(map, i);
 
-       if (i == map->size - 1 && e->id != IPSET_INVALID_ID)
-               /* Last element replaced: e.g. add new,before,last */
-               ip_set_put_byindex(e->id);
+       if (e->id != IPSET_INVALID_ID) {
+               const struct set_elem *x = list_set_elem(map, map->size - 1);
+
+               /* Last element replaced or pushed off */
+               if (x->id != IPSET_INVALID_ID)
+                       ip_set_put_byindex(x->id);
+       }
        if (with_timeout(map->timeout))
                list_elem_tadd(map, i, id, ip_set_timeout_set(timeout));
        else
index 0e7d423324c399b3c5012dc312fd75f470b78cb5..e0c4373b47478d4d72899d95166566db34a8bcfa 100644 (file)
@@ -1593,10 +1593,8 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
                end += strlen("\r\n\r\n") + clen;
 
                msglen = origlen = end - dptr;
-               if (msglen > datalen) {
-                       nf_ct_helper_log(skb, ct, "incomplete/bad SIP message");
-                       return NF_DROP;
-               }
+               if (msglen > datalen)
+                       return NF_ACCEPT;
 
                ret = process_sip_msg(skb, ct, protoff, dataoff,
                                      &dptr, &msglen);
index 6bcce401fd1c5ddfbc3fe00bb45ab87a72ab9fb2..fedee394366187cf35bfa242c9cd1584f0eb0108 100644 (file)
@@ -568,6 +568,7 @@ static int __init nf_conntrack_standalone_init(void)
                register_net_sysctl(&init_net, "net", nf_ct_netfilter_table);
        if (!nf_ct_netfilter_header) {
                pr_err("nf_conntrack: can't register to sysctl.\n");
+               ret = -ENOMEM;
                goto out_sysctl;
        }
 #endif
index 8d5769c6d16e505ed6239889faee03ab34d4c15d..ad24be070e53c0fe8c27e49a6e2cb93a39c32062 100644 (file)
@@ -467,33 +467,22 @@ EXPORT_SYMBOL_GPL(nf_nat_packet);
 struct nf_nat_proto_clean {
        u8      l3proto;
        u8      l4proto;
-       bool    hash;
 };
 
-/* Clear NAT section of all conntracks, in case we're loaded again. */
-static int nf_nat_proto_clean(struct nf_conn *i, void *data)
+/* kill conntracks with affected NAT section */
+static int nf_nat_proto_remove(struct nf_conn *i, void *data)
 {
        const struct nf_nat_proto_clean *clean = data;
        struct nf_conn_nat *nat = nfct_nat(i);
 
        if (!nat)
                return 0;
-       if (!(i->status & IPS_SRC_NAT_DONE))
-               return 0;
+
        if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) ||
            (clean->l4proto && nf_ct_protonum(i) != clean->l4proto))
                return 0;
 
-       if (clean->hash) {
-               spin_lock_bh(&nf_nat_lock);
-               hlist_del_rcu(&nat->bysource);
-               spin_unlock_bh(&nf_nat_lock);
-       } else {
-               memset(nat, 0, sizeof(*nat));
-               i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK |
-                              IPS_SEQ_ADJUST);
-       }
-       return 0;
+       return i->status & IPS_NAT_MASK ? 1 : 0;
 }
 
 static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto)
@@ -505,16 +494,8 @@ static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto)
        struct net *net;
 
        rtnl_lock();
-       /* Step 1 - remove from bysource hash */
-       clean.hash = true;
        for_each_net(net)
-               nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
-       synchronize_rcu();
-
-       /* Step 2 - clean NAT section */
-       clean.hash = false;
-       for_each_net(net)
-               nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
+               nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
        rtnl_unlock();
 }
 
@@ -526,16 +507,9 @@ static void nf_nat_l3proto_clean(u8 l3proto)
        struct net *net;
 
        rtnl_lock();
-       /* Step 1 - remove from bysource hash */
-       clean.hash = true;
-       for_each_net(net)
-               nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
-       synchronize_rcu();
 
-       /* Step 2 - clean NAT section */
-       clean.hash = false;
        for_each_net(net)
-               nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
+               nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
        rtnl_unlock();
 }
 
@@ -773,7 +747,7 @@ static void __net_exit nf_nat_net_exit(struct net *net)
 {
        struct nf_nat_proto_clean clean = {};
 
-       nf_ct_iterate_cleanup(net, &nf_nat_proto_clean, &clean);
+       nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean);
        synchronize_rcu();
        nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size);
 }
index 589d686f0b4cbe0f25b785790dfeba9bf1a13d98..dc3fd5d44464a3ca7cdc5ed68d52ec71256b0cc2 100644 (file)
@@ -49,6 +49,8 @@ nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb,
                return -EINVAL;
 
        acct_name = nla_data(tb[NFACCT_NAME]);
+       if (strlen(acct_name) == 0)
+               return -EINVAL;
 
        list_for_each_entry(nfacct, &nfnl_acct_list, head) {
                if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0)
index 1cb48540f86a96df1e1b26371e5d75589861562d..42680b2baa118d7d09697718077df29d994a10a3 100644 (file)
@@ -1062,8 +1062,10 @@ static int __init nfnetlink_queue_init(void)
 
 #ifdef CONFIG_PROC_FS
        if (!proc_create("nfnetlink_queue", 0440,
-                        proc_net_netfilter, &nfqnl_file_ops))
+                        proc_net_netfilter, &nfqnl_file_ops)) {
+               status = -ENOMEM;
                goto cleanup_subsys;
+       }
 #endif
 
        register_netdevice_notifier(&nfqnl_dev_notifier);
index d1fa1d9ffd2e82450d1a6c73fbfb55419cebe0c5..103bd704b5fc39e24d07714dd6831ca2d3bf036a 100644 (file)
@@ -1173,6 +1173,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
        }
 
        if (sax != NULL) {
+               memset(sax, 0, sizeof(*sax));
                sax->sax25_family = AF_NETROM;
                skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,
                              AX25_ADDR_LEN);
index b530afadd76c6168a5374d27935b7d95180f8884..ee25f25f0cd638367cc4a6668c44e907945c9469 100644 (file)
@@ -107,8 +107,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
                                accept_sk->sk_state_change(sk);
 
                                bh_unlock_sock(accept_sk);
-
-                               sock_orphan(accept_sk);
                        }
 
                        if (listen == true) {
@@ -134,8 +132,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
 
                bh_unlock_sock(sk);
 
-               sock_orphan(sk);
-
                sk_del_node_init(sk);
        }
 
@@ -164,8 +160,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
 
                bh_unlock_sock(sk);
 
-               sock_orphan(sk);
-
                sk_del_node_init(sk);
        }
 
@@ -827,7 +821,6 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local,
                skb_get(skb);
        } else {
                pr_err("Receive queue is full\n");
-               kfree_skb(skb);
        }
 
        nfc_llcp_sock_put(llcp_sock);
@@ -1028,7 +1021,6 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
                        skb_get(skb);
                } else {
                        pr_err("Receive queue is full\n");
-                       kfree_skb(skb);
                }
        }
 
index 5c7cdf3f2a83b5a6a85033744121727ecddba70d..6c94447ec414c87479581b45fbcced1071f782cb 100644 (file)
@@ -270,7 +270,9 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
                }
 
                if (sk->sk_state == LLCP_CONNECTED || !newsock) {
-                       nfc_llcp_accept_unlink(sk);
+                       list_del_init(&lsk->accept_queue);
+                       sock_put(sk);
+
                        if (newsock)
                                sock_graft(sk, newsock);
 
@@ -464,8 +466,6 @@ static int llcp_sock_release(struct socket *sock)
                        nfc_llcp_accept_unlink(accept_sk);
 
                        release_sock(accept_sk);
-
-                       sock_orphan(accept_sk);
                }
        }
 
@@ -646,6 +646,8 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        pr_debug("%p %zu\n", sk, len);
 
+       msg->msg_namelen = 0;
+
        lock_sock(sk);
 
        if (sk->sk_state == LLCP_CLOSED &&
@@ -691,6 +693,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 
                pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap);
 
+               memset(sockaddr, 0, sizeof(*sockaddr));
                sockaddr->sa_family = AF_NFC;
                sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP;
                sockaddr->dsap = ui_cb->dsap;
index a4b724708a1ab0b7d4aedffc07606b8fbfdac0a9..6980c3e6f0667b0ed22098098b66da7cf929a47e 100644 (file)
@@ -1593,10 +1593,8 @@ struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 portid,
                return ERR_PTR(-ENOMEM);
 
        retval = ovs_vport_cmd_fill_info(vport, skb, portid, seq, 0, cmd);
-       if (retval < 0) {
-               kfree_skb(skb);
-               return ERR_PTR(retval);
-       }
+       BUG_ON(retval < 0);
+
        return skb;
 }
 
@@ -1726,24 +1724,32 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
            nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type)
                err = -EINVAL;
 
+       reply = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       if (!reply) {
+               err = -ENOMEM;
+               goto exit_unlock;
+       }
+
        if (!err && a[OVS_VPORT_ATTR_OPTIONS])
                err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]);
        if (err)
-               goto exit_unlock;
+               goto exit_free;
+
        if (a[OVS_VPORT_ATTR_UPCALL_PID])
                vport->upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]);
 
-       reply = ovs_vport_cmd_build_info(vport, info->snd_portid, info->snd_seq,
-                                        OVS_VPORT_CMD_NEW);
-       if (IS_ERR(reply)) {
-               netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
-                               ovs_dp_vport_multicast_group.id, PTR_ERR(reply));
-               goto exit_unlock;
-       }
+       err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
+                                     info->snd_seq, 0, OVS_VPORT_CMD_NEW);
+       BUG_ON(err < 0);
 
        genl_notify(reply, genl_info_net(info), info->snd_portid,
                    ovs_dp_vport_multicast_group.id, info->nlhdr, GFP_KERNEL);
 
+       rtnl_unlock();
+       return 0;
+
+exit_free:
+       kfree_skb(reply);
 exit_unlock:
        rtnl_unlock();
        return err;
index fe0e4215c73d6045469ba006722ef223d43ebd66..67a2b783fe70257cb6c33542806d3f3ca17f3d76 100644 (file)
@@ -795,9 +795,9 @@ void ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow)
 
 void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
 {
+       BUG_ON(table->count == 0);
        hlist_del_rcu(&flow->hash_node[table->node_ver]);
        table->count--;
-       BUG_ON(table->count < 0);
 }
 
 /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute.  */
index cf68e6e4054a6735694b1ce5bbee30fefbb02899..9c834745159786e5e1d4338f51860be00943a0fd 100644 (file)
@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
        skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 
        if (srose != NULL) {
+               memset(srose, 0, msg->msg_namelen);
                srose->srose_family = AF_ROSE;
                srose->srose_addr   = rose->dest_addr;
                srose->srose_call   = rose->dest_call;
index 1135d8227f9bf1811a2c45c211b80e6b9a69706f..9b97172db84a7c72c31c2b6bd36141149859eb1c 100644 (file)
@@ -204,7 +204,6 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
        if (err < 0)
                return err;
 
-       err = -EINVAL;
        if (tb[TCA_FW_CLASSID]) {
                f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
                tcf_bind_filter(tp, &f->res, base);
@@ -218,6 +217,7 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
        }
 #endif /* CONFIG_NET_CLS_IND */
 
+       err = -EINVAL;
        if (tb[TCA_FW_MASK]) {
                mask = nla_get_u32(tb[TCA_FW_MASK]);
                if (mask != head->mask)
index 13aa47aa2ffb48ea25990dce3762b83e775d7bcf..1bc210ffcba2a524750b3382d444a87db2c08c2c 100644 (file)
@@ -962,8 +962,11 @@ cbq_dequeue(struct Qdisc *sch)
                cbq_update(q);
                if ((incr -= incr2) < 0)
                        incr = 0;
+               q->now += incr;
+       } else {
+               if (now > q->now)
+                       q->now = now;
        }
-       q->now += incr;
        q->now_rt = now;
 
        for (;;) {
index 4e606fcb2534929a2470e807816ac1089d81b7b2..55786283a3dfe613ee6deac5756b4726a66925ee 100644 (file)
@@ -195,7 +195,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                flow->deficit = q->quantum;
                flow->dropped = 0;
        }
-       if (++sch->q.qlen < sch->limit)
+       if (++sch->q.qlen <= sch->limit)
                return NET_XMIT_SUCCESS;
 
        q->drop_overlimit++;
index ffad48109a228c66ccbd33124525dee83f9158df..eac7e0ee23c18708354e3cef8c237d289b81235f 100644 (file)
@@ -904,7 +904,7 @@ void psched_ratecfg_precompute(struct psched_ratecfg *r, u32 rate)
        u64 mult;
        int shift;
 
-       r->rate_bps = rate << 3;
+       r->rate_bps = (u64)rate << 3;
        r->shift = 0;
        r->mult = 1;
        /*
index dcc446e7fbf6b6c0d639e2889438bc5f2aa65df2..d5f35f15af983e7a6955c576460a092ec70c0bcb 100644 (file)
@@ -304,10 +304,8 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
        err = rpciod_up();
        if (err)
                goto out_no_rpciod;
-       err = -EINVAL;
-       if (!xprt)
-               goto out_no_xprt;
 
+       err = -EINVAL;
        if (args->version >= program->nrvers)
                goto out_err;
        version = program->version[args->version];
@@ -382,10 +380,9 @@ out_no_principal:
 out_no_stats:
        kfree(clnt);
 out_err:
-       xprt_put(xprt);
-out_no_xprt:
        rpciod_down();
 out_no_rpciod:
+       xprt_put(xprt);
        return ERR_PTR(err);
 }
 
@@ -512,7 +509,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
        new = rpc_new_client(args, xprt);
        if (IS_ERR(new)) {
                err = PTR_ERR(new);
-               goto out_put;
+               goto out_err;
        }
 
        atomic_inc(&clnt->cl_count);
@@ -525,8 +522,6 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
        new->cl_chatty = clnt->cl_chatty;
        return new;
 
-out_put:
-       xprt_put(xprt);
 out_err:
        dprintk("RPC:       %s: returned error %d\n", __func__, err);
        return ERR_PTR(err);
index a9622b6cd91689ae17ae92b9226c3705067a1a8a..515ce38e4f4c7286023f32f4c8c692af2787ec80 100644 (file)
@@ -790,6 +790,7 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
        if (addr) {
                addr->family = AF_TIPC;
                addr->addrtype = TIPC_ADDR_ID;
+               memset(&addr->addr, 0, sizeof(addr->addr));
                addr->addr.id.ref = msg_origport(msg);
                addr->addr.id.node = msg_orignode(msg);
                addr->addr.name.domain = 0;     /* could leave uninitialized */
@@ -904,6 +905,9 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
                goto exit;
        }
 
+       /* will be updated in set_orig_addr() if needed */
+       m->msg_namelen = 0;
+
        timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 restart:
 
@@ -1013,6 +1017,9 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
                goto exit;
        }
 
+       /* will be updated in set_orig_addr() if needed */
+       m->msg_namelen = 0;
+
        target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
        timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 
index 971282b6f6a38fd056dd65d127b85f044b7c6041..2db702d82e7d16fea7a27a82cc7c5dc3d3d95726 100644 (file)
@@ -1412,8 +1412,8 @@ static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
        if (UNIXCB(skb).cred)
                return;
        if (test_bit(SOCK_PASSCRED, &sock->flags) ||
-           (other->sk_socket &&
-           test_bit(SOCK_PASSCRED, &other->sk_socket->flags))) {
+           !other->sk_socket ||
+           test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
                UNIXCB(skb).pid  = get_pid(task_tgid(current));
                UNIXCB(skb).cred = get_current_cred();
        }
@@ -1993,7 +1993,7 @@ again:
                        if ((UNIXCB(skb).pid  != siocb->scm->pid) ||
                            (UNIXCB(skb).cred != siocb->scm->cred))
                                break;
-               } else {
+               } else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
                        /* Copy credentials */
                        scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
                        check_creds = 1;
index ca511c4f388a56cf1fdaf110d31aff7d30b5d0fb..7f93e2a42d7a57f0cbdbe2305c942cce7b544d1b 100644 (file)
@@ -207,7 +207,7 @@ static struct sock *__vsock_find_bound_socket(struct sockaddr_vm *addr)
        struct vsock_sock *vsk;
 
        list_for_each_entry(vsk, vsock_bound_sockets(addr), bound_table)
-               if (vsock_addr_equals_addr_any(addr, &vsk->local_addr))
+               if (addr->svm_port == vsk->local_addr.svm_port)
                        return sk_vsock(vsk);
 
        return NULL;
@@ -220,8 +220,8 @@ static struct sock *__vsock_find_connected_socket(struct sockaddr_vm *src,
 
        list_for_each_entry(vsk, vsock_connected_sockets(src, dst),
                            connected_table) {
-               if (vsock_addr_equals_addr(src, &vsk->remote_addr)
-                   && vsock_addr_equals_addr(dst, &vsk->local_addr)) {
+               if (vsock_addr_equals_addr(src, &vsk->remote_addr) &&
+                   dst->svm_port == vsk->local_addr.svm_port) {
                        return sk_vsock(vsk);
                }
        }
@@ -1670,6 +1670,8 @@ vsock_stream_recvmsg(struct kiocb *kiocb,
        vsk = vsock_sk(sk);
        err = 0;
 
+       msg->msg_namelen = 0;
+
        lock_sock(sk);
 
        if (sk->sk_state != SS_CONNECTED) {
index a70ace83a1531232a2f11afc63c8b4ab1c4ea918..5e04d3d96285daaa01ff8d35e58081ce4807f093 100644 (file)
@@ -464,19 +464,16 @@ static struct sock *vmci_transport_get_pending(
        struct vsock_sock *vlistener;
        struct vsock_sock *vpending;
        struct sock *pending;
+       struct sockaddr_vm src;
+
+       vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
 
        vlistener = vsock_sk(listener);
 
        list_for_each_entry(vpending, &vlistener->pending_links,
                            pending_links) {
-               struct sockaddr_vm src;
-               struct sockaddr_vm dst;
-
-               vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
-               vsock_addr_init(&dst, pkt->dg.dst.context, pkt->dst_port);
-
                if (vsock_addr_equals_addr(&src, &vpending->remote_addr) &&
-                   vsock_addr_equals_addr(&dst, &vpending->local_addr)) {
+                   pkt->dst_port == vpending->local_addr.svm_port) {
                        pending = sk_vsock(vpending);
                        sock_hold(pending);
                        goto found;
@@ -739,10 +736,15 @@ static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg)
         */
        bh_lock_sock(sk);
 
-       if (!sock_owned_by_user(sk) && sk->sk_state == SS_CONNECTED)
-               vmci_trans(vsk)->notify_ops->handle_notify_pkt(
-                               sk, pkt, true, &dst, &src,
-                               &bh_process_pkt);
+       if (!sock_owned_by_user(sk)) {
+               /* The local context ID may be out of date, update it. */
+               vsk->local_addr.svm_cid = dst.svm_cid;
+
+               if (sk->sk_state == SS_CONNECTED)
+                       vmci_trans(vsk)->notify_ops->handle_notify_pkt(
+                                       sk, pkt, true, &dst, &src,
+                                       &bh_process_pkt);
+       }
 
        bh_unlock_sock(sk);
 
@@ -902,6 +904,9 @@ static void vmci_transport_recv_pkt_work(struct work_struct *work)
 
        lock_sock(sk);
 
+       /* The local context ID may be out of date. */
+       vsock_sk(sk)->local_addr.svm_cid = pkt->dg.dst.context;
+
        switch (sk->sk_state) {
        case SS_LISTEN:
                vmci_transport_recv_listen(sk, pkt);
@@ -958,6 +963,10 @@ static int vmci_transport_recv_listen(struct sock *sk,
        pending = vmci_transport_get_pending(sk, pkt);
        if (pending) {
                lock_sock(pending);
+
+               /* The local context ID may be out of date. */
+               vsock_sk(pending)->local_addr.svm_cid = pkt->dg.dst.context;
+
                switch (pending->sk_state) {
                case SS_CONNECTING:
                        err = vmci_transport_recv_connecting_server(sk,
@@ -1727,6 +1736,8 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb,
        if (flags & MSG_OOB || flags & MSG_ERRQUEUE)
                return -EOPNOTSUPP;
 
+       msg->msg_namelen = 0;
+
        /* Retrieve the head sk_buff from the socket's receive queue. */
        err = 0;
        skb = skb_recv_datagram(&vsk->sk, flags, noblock, &err);
@@ -1759,7 +1770,6 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb,
        if (err)
                goto out;
 
-       msg->msg_namelen = 0;
        if (msg->msg_name) {
                struct sockaddr_vm *vm_addr;
 
index b7df1aea7c59364b18f4e7a71b448909120a9b45..ec2611b4ea0ee4fc073926c9a33347ace8de9e4f 100644 (file)
@@ -64,16 +64,6 @@ bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
 }
 EXPORT_SYMBOL_GPL(vsock_addr_equals_addr);
 
-bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
-                               const struct sockaddr_vm *other)
-{
-       return (addr->svm_cid == VMADDR_CID_ANY ||
-               other->svm_cid == VMADDR_CID_ANY ||
-               addr->svm_cid == other->svm_cid) &&
-              addr->svm_port == other->svm_port;
-}
-EXPORT_SYMBOL_GPL(vsock_addr_equals_addr_any);
-
 int vsock_addr_cast(const struct sockaddr *addr,
                    size_t len, struct sockaddr_vm **out_addr)
 {
index cdfbcefdf84300f71fd598a782a8de66d6c095fb..9ccd5316eac09ddfeb7a07f030a9f4f993da7de2 100644 (file)
@@ -24,8 +24,6 @@ bool vsock_addr_bound(const struct sockaddr_vm *addr);
 void vsock_addr_unbind(struct sockaddr_vm *addr);
 bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
                            const struct sockaddr_vm *other);
-bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
-                               const struct sockaddr_vm *other);
 int vsock_addr_cast(const struct sockaddr *addr, size_t len,
                    struct sockaddr_vm **out_addr);
 
index ea4155fe97334f91794dbb7a55f0dab28219c2a3..6ddf74f0ae1e5ace4346f3c0cf6b4f1ce13fa580 100644 (file)
@@ -212,6 +212,39 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
        rdev_rfkill_poll(rdev);
 }
 
+void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
+                             struct wireless_dev *wdev)
+{
+       lockdep_assert_held(&rdev->devlist_mtx);
+       lockdep_assert_held(&rdev->sched_scan_mtx);
+
+       if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
+               return;
+
+       if (!wdev->p2p_started)
+               return;
+
+       rdev_stop_p2p_device(rdev, wdev);
+       wdev->p2p_started = false;
+
+       rdev->opencount--;
+
+       if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
+               bool busy = work_busy(&rdev->scan_done_wk);
+
+               /*
+                * If the work isn't pending or running (in which case it would
+                * be waiting for the lock we hold) the driver didn't properly
+                * cancel the scan when the interface was removed. In this case
+                * warn and leak the scan request object to not crash later.
+                */
+               WARN_ON(!busy);
+
+               rdev->scan_req->aborted = true;
+               ___cfg80211_scan_done(rdev, !busy);
+       }
+}
+
 static int cfg80211_rfkill_set_block(void *data, bool blocked)
 {
        struct cfg80211_registered_device *rdev = data;
@@ -221,7 +254,8 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
                return 0;
 
        rtnl_lock();
-       mutex_lock(&rdev->devlist_mtx);
+
+       /* read-only iteration need not hold the devlist_mtx */
 
        list_for_each_entry(wdev, &rdev->wdev_list, list) {
                if (wdev->netdev) {
@@ -231,18 +265,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
                /* otherwise, check iftype */
                switch (wdev->iftype) {
                case NL80211_IFTYPE_P2P_DEVICE:
-                       if (!wdev->p2p_started)
-                               break;
-                       rdev_stop_p2p_device(rdev, wdev);
-                       wdev->p2p_started = false;
-                       rdev->opencount--;
+                       /* but this requires it */
+                       mutex_lock(&rdev->devlist_mtx);
+                       mutex_lock(&rdev->sched_scan_mtx);
+                       cfg80211_stop_p2p_device(rdev, wdev);
+                       mutex_unlock(&rdev->sched_scan_mtx);
+                       mutex_unlock(&rdev->devlist_mtx);
                        break;
                default:
                        break;
                }
        }
 
-       mutex_unlock(&rdev->devlist_mtx);
        rtnl_unlock();
 
        return 0;
@@ -745,17 +779,13 @@ static void wdev_cleanup_work(struct work_struct *work)
        wdev = container_of(work, struct wireless_dev, cleanup_work);
        rdev = wiphy_to_dev(wdev->wiphy);
 
-       cfg80211_lock_rdev(rdev);
+       mutex_lock(&rdev->sched_scan_mtx);
 
        if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
                rdev->scan_req->aborted = true;
                ___cfg80211_scan_done(rdev, true);
        }
 
-       cfg80211_unlock_rdev(rdev);
-
-       mutex_lock(&rdev->sched_scan_mtx);
-
        if (WARN_ON(rdev->sched_scan_req &&
                    rdev->sched_scan_req->dev == wdev->netdev)) {
                __cfg80211_stop_sched_scan(rdev, false);
@@ -781,21 +811,19 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
                return;
 
        mutex_lock(&rdev->devlist_mtx);
+       mutex_lock(&rdev->sched_scan_mtx);
        list_del_rcu(&wdev->list);
        rdev->devlist_generation++;
 
        switch (wdev->iftype) {
        case NL80211_IFTYPE_P2P_DEVICE:
-               if (!wdev->p2p_started)
-                       break;
-               rdev_stop_p2p_device(rdev, wdev);
-               wdev->p2p_started = false;
-               rdev->opencount--;
+               cfg80211_stop_p2p_device(rdev, wdev);
                break;
        default:
                WARN_ON_ONCE(1);
                break;
        }
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
 }
 EXPORT_SYMBOL(cfg80211_unregister_wdev);
@@ -936,6 +964,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                cfg80211_update_iface_num(rdev, wdev->iftype, 1);
                cfg80211_lock_rdev(rdev);
                mutex_lock(&rdev->devlist_mtx);
+               mutex_lock(&rdev->sched_scan_mtx);
                wdev_lock(wdev);
                switch (wdev->iftype) {
 #ifdef CONFIG_CFG80211_WEXT
@@ -967,6 +996,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                        break;
                }
                wdev_unlock(wdev);
+               mutex_unlock(&rdev->sched_scan_mtx);
                rdev->opencount++;
                mutex_unlock(&rdev->devlist_mtx);
                cfg80211_unlock_rdev(rdev);
index 3aec0e429d8adbf9d44c7fbc5bb7fa503e5b9818..5845c2b37aa832b444906ad4fb0e4e74f06c3ee3 100644 (file)
@@ -503,6 +503,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
                               enum nl80211_iftype iftype, int num);
 
+void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
+                             struct wireless_dev *wdev);
+
 #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
 
 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
index d44ab216c0ecd8b01d4386edf62cd07c3f2071db..58e13a8c95f90a7b880a9d65530799fc02451f1e 100644 (file)
@@ -4702,14 +4702,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->scan)
                return -EOPNOTSUPP;
 
-       if (rdev->scan_req)
-               return -EBUSY;
+       mutex_lock(&rdev->sched_scan_mtx);
+       if (rdev->scan_req) {
+               err = -EBUSY;
+               goto unlock;
+       }
 
        if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
                n_channels = validate_scan_freqs(
                                info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
-               if (!n_channels)
-                       return -EINVAL;
+               if (!n_channels) {
+                       err = -EINVAL;
+                       goto unlock;
+               }
        } else {
                enum ieee80211_band band;
                n_channels = 0;
@@ -4723,23 +4728,29 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
                        n_ssids++;
 
-       if (n_ssids > wiphy->max_scan_ssids)
-               return -EINVAL;
+       if (n_ssids > wiphy->max_scan_ssids) {
+               err = -EINVAL;
+               goto unlock;
+       }
 
        if (info->attrs[NL80211_ATTR_IE])
                ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        else
                ie_len = 0;
 
-       if (ie_len > wiphy->max_scan_ie_len)
-               return -EINVAL;
+       if (ie_len > wiphy->max_scan_ie_len) {
+               err = -EINVAL;
+               goto unlock;
+       }
 
        request = kzalloc(sizeof(*request)
                        + sizeof(*request->ssids) * n_ssids
                        + sizeof(*request->channels) * n_channels
                        + ie_len, GFP_KERNEL);
-       if (!request)
-               return -ENOMEM;
+       if (!request) {
+               err = -ENOMEM;
+               goto unlock;
+       }
 
        if (n_ssids)
                request->ssids = (void *)&request->channels[n_channels];
@@ -4876,6 +4887,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                kfree(request);
        }
 
+ unlock:
+       mutex_unlock(&rdev->sched_scan_mtx);
        return err;
 }
 
@@ -7749,20 +7762,9 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->stop_p2p_device)
                return -EOPNOTSUPP;
 
-       if (!wdev->p2p_started)
-               return 0;
-
-       rdev_stop_p2p_device(rdev, wdev);
-       wdev->p2p_started = false;
-
-       mutex_lock(&rdev->devlist_mtx);
-       rdev->opencount--;
-       mutex_unlock(&rdev->devlist_mtx);
-
-       if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
-               rdev->scan_req->aborted = true;
-               ___cfg80211_scan_done(rdev, true);
-       }
+       mutex_lock(&rdev->sched_scan_mtx);
+       cfg80211_stop_p2p_device(rdev, wdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
 
        return 0;
 }
@@ -8486,7 +8488,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
        struct nlattr *nest;
        int i;
 
-       ASSERT_RDEV_LOCK(rdev);
+       lockdep_assert_held(&rdev->sched_scan_mtx);
 
        if (WARN_ON(!req))
                return 0;
index 674aadca007982257b14b3c68abbafc39ee01461..fd99ea495b7e68cd9e5265542a6aa059d0ac7760 100644 (file)
@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
        union iwreq_data wrqu;
 #endif
 
-       ASSERT_RDEV_LOCK(rdev);
+       lockdep_assert_held(&rdev->sched_scan_mtx);
 
        request = rdev->scan_req;
 
@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
        rdev = container_of(wk, struct cfg80211_registered_device,
                            scan_done_wk);
 
-       cfg80211_lock_rdev(rdev);
+       mutex_lock(&rdev->sched_scan_mtx);
        ___cfg80211_scan_done(rdev, false);
-       cfg80211_unlock_rdev(rdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
 }
 
 void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
@@ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
        found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR);
 
        if (found) {
-               found->pub.beacon_interval = tmp->pub.beacon_interval;
-               found->pub.signal = tmp->pub.signal;
-               found->pub.capability = tmp->pub.capability;
-               found->ts = tmp->ts;
-
                /* Update IEs */
                if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
                        const struct cfg80211_bss_ies *old;
@@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
 
                        if (found->pub.hidden_beacon_bss &&
                            !list_empty(&found->hidden_list)) {
+                               const struct cfg80211_bss_ies *f;
+
                                /*
                                 * The found BSS struct is one of the probe
                                 * response members of a group, but we're
@@ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
                                 * SSID to showing it, which is confusing so
                                 * drop this information.
                                 */
+
+                               f = rcu_access_pointer(tmp->pub.beacon_ies);
+                               kfree_rcu((struct cfg80211_bss_ies *)f,
+                                         rcu_head);
                                goto drop;
                        }
 
@@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
                                kfree_rcu((struct cfg80211_bss_ies *)old,
                                          rcu_head);
                }
+
+               found->pub.beacon_interval = tmp->pub.beacon_interval;
+               found->pub.signal = tmp->pub.signal;
+               found->pub.capability = tmp->pub.capability;
+               found->ts = tmp->ts;
        } else {
                struct cfg80211_internal_bss *new;
                struct cfg80211_internal_bss *hidden;
@@ -1056,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
        if (IS_ERR(rdev))
                return PTR_ERR(rdev);
 
+       mutex_lock(&rdev->sched_scan_mtx);
        if (rdev->scan_req) {
                err = -EBUSY;
                goto out;
@@ -1162,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
                dev_hold(dev);
        }
  out:
+       mutex_unlock(&rdev->sched_scan_mtx);
        kfree(creq);
        cfg80211_unlock_rdev(rdev);
        return err;
index f432bd3755b19f0d865b1b2e9f2a132890f3b6a3..482c70e7012727fe66e400872379e115b7a7caad 100644 (file)
@@ -85,6 +85,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
        ASSERT_RTNL();
        ASSERT_RDEV_LOCK(rdev);
        ASSERT_WDEV_LOCK(wdev);
+       lockdep_assert_held(&rdev->sched_scan_mtx);
 
        if (rdev->scan_req)
                return -EBUSY;
@@ -223,6 +224,7 @@ void cfg80211_conn_work(struct work_struct *work)
        rtnl_lock();
        cfg80211_lock_rdev(rdev);
        mutex_lock(&rdev->devlist_mtx);
+       mutex_lock(&rdev->sched_scan_mtx);
 
        list_for_each_entry(wdev, &rdev->wdev_list, list) {
                wdev_lock(wdev);
@@ -247,6 +249,7 @@ void cfg80211_conn_work(struct work_struct *work)
                wdev_unlock(wdev);
        }
 
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
        cfg80211_unlock_rdev(rdev);
        rtnl_unlock();
@@ -320,11 +323,9 @@ void cfg80211_sme_scan_done(struct net_device *dev)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
 
-       mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
        wdev_lock(wdev);
        __cfg80211_sme_scan_done(dev);
        wdev_unlock(wdev);
-       mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
 }
 
 void cfg80211_sme_rx_auth(struct net_device *dev,
@@ -924,9 +925,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
        int err;
 
        mutex_lock(&rdev->devlist_mtx);
+       /* might request scan - scan_mtx -> wdev_mtx dependency */
+       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(dev->ieee80211_ptr);
        err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
        wdev_unlock(dev->ieee80211_ptr);
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
 
        return err;
index b7a531380e19d5bf879f2395eee1176a1abfac93..7586de77a2f8b57ebb9b832b76563ab66a59111a 100644 (file)
@@ -27,7 +27,8 @@
 #define WIPHY_PR_ARG   __entry->wiphy_name
 
 #define WDEV_ENTRY     __field(u32, id)
-#define WDEV_ASSIGN    (__entry->id) = (wdev ? wdev->identifier : 0)
+#define WDEV_ASSIGN    (__entry->id) = (!IS_ERR_OR_NULL(wdev)  \
+                                        ? wdev->identifier : 0)
 #define WDEV_PR_FMT    "wdev(%u)"
 #define WDEV_PR_ARG    (__entry->id)
 
@@ -1778,7 +1779,7 @@ TRACE_EVENT(rdev_set_mac_acl,
        ),
        TP_fast_assign(
                WIPHY_ASSIGN;
-               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
                __entry->acl_policy = params->acl_policy;
        ),
        TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d",
index fb9622f6d99c4b6b6c87f8a8d8e2c88e4fb3705c..e79cb5c0655ad34ec0e8df85471e6c77ad856716 100644 (file)
@@ -89,6 +89,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
 
        cfg80211_lock_rdev(rdev);
        mutex_lock(&rdev->devlist_mtx);
+       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(wdev);
 
        if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -135,6 +136,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
        err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
        wdev_unlock(wdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
        cfg80211_unlock_rdev(rdev);
        return err;
@@ -190,6 +192,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
 
        cfg80211_lock_rdev(rdev);
        mutex_lock(&rdev->devlist_mtx);
+       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(wdev);
 
        err = 0;
@@ -223,6 +226,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
        err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
        wdev_unlock(wdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
        cfg80211_unlock_rdev(rdev);
        return err;
@@ -285,6 +289,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
 
        cfg80211_lock_rdev(rdev);
        mutex_lock(&rdev->devlist_mtx);
+       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(wdev);
 
        if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -313,6 +318,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
        err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
        wdev_unlock(wdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
        cfg80211_unlock_rdev(rdev);
        return err;
index 35754cc8a9e5b9c51cdaf52693128ee2098718f7..8dafe6d3c6e41ebd20e5d0347d4ab9b0e6326a34 100644 (file)
@@ -334,6 +334,70 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
                x->xflags &= ~XFRM_TIME_DEFER;
 }
 
+static void xfrm_replay_notify_esn(struct xfrm_state *x, int event)
+{
+       u32 seq_diff, oseq_diff;
+       struct km_event c;
+       struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+       struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
+
+       /* we send notify messages in case
+        *  1. we updated on of the sequence numbers, and the seqno difference
+        *     is at least x->replay_maxdiff, in this case we also update the
+        *     timeout of our timer function
+        *  2. if x->replay_maxage has elapsed since last update,
+        *     and there were changes
+        *
+        *  The state structure must be locked!
+        */
+
+       switch (event) {
+       case XFRM_REPLAY_UPDATE:
+               if (!x->replay_maxdiff)
+                       break;
+
+               if (replay_esn->seq_hi == preplay_esn->seq_hi)
+                       seq_diff = replay_esn->seq - preplay_esn->seq;
+               else
+                       seq_diff = ~preplay_esn->seq + replay_esn->seq + 1;
+
+               if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
+                       oseq_diff = replay_esn->oseq - preplay_esn->oseq;
+               else
+                       oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1;
+
+               if (seq_diff < x->replay_maxdiff &&
+                   oseq_diff < x->replay_maxdiff) {
+
+                       if (x->xflags & XFRM_TIME_DEFER)
+                               event = XFRM_REPLAY_TIMEOUT;
+                       else
+                               return;
+               }
+
+               break;
+
+       case XFRM_REPLAY_TIMEOUT:
+               if (memcmp(x->replay_esn, x->preplay_esn,
+                          xfrm_replay_state_esn_len(replay_esn)) == 0) {
+                       x->xflags |= XFRM_TIME_DEFER;
+                       return;
+               }
+
+               break;
+       }
+
+       memcpy(x->preplay_esn, x->replay_esn,
+              xfrm_replay_state_esn_len(replay_esn));
+       c.event = XFRM_MSG_NEWAE;
+       c.data.aevent = event;
+       km_state_notify(x, &c);
+
+       if (x->replay_maxage &&
+           !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+               x->xflags &= ~XFRM_TIME_DEFER;
+}
+
 static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err = 0;
@@ -510,7 +574,7 @@ static struct xfrm_replay xfrm_replay_esn = {
        .advance        = xfrm_replay_advance_esn,
        .check          = xfrm_replay_check_esn,
        .recheck        = xfrm_replay_recheck_esn,
-       .notify         = xfrm_replay_notify_bmp,
+       .notify         = xfrm_replay_notify_esn,
        .overflow       = xfrm_replay_overflow_esn,
 };
 
index b28cc384a5bcf30952f66d7da5b349978e39b49a..4de4bc48493bca4947182bc10483bc272f459331 100755 (executable)
@@ -3016,6 +3016,7 @@ sub process {
                            $dstat !~ /^'X'$/ &&                                        # character constants
                            $dstat !~ /$exceptions/ &&
                            $dstat !~ /^\.$Ident\s*=/ &&                                # .foo =
+                           $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ &&          # stringification #foo
                            $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ &&       # do {...} while (...); // do {...} while (...)
                            $dstat !~ /^for\s*$Constant$/ &&                            # for (...)
                            $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ &&   # for (...) bar()
index 579775088967fdb11a044beb75c70de48d572ad6..6783c3e6c88e24fa5e2dacd07fd64ea5b61ac636 100644 (file)
@@ -737,6 +737,11 @@ static int cap_tun_dev_open(void *security)
 {
        return 0;
 }
+
+static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk)
+{
+}
+
 #endif /* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1071,6 +1076,7 @@ void __init security_fixup_ops(struct security_operations *ops)
        set_to_cap_if_null(ops, tun_dev_open);
        set_to_cap_if_null(ops, tun_dev_attach_queue);
        set_to_cap_if_null(ops, tun_dev_attach);
+       set_to_cap_if_null(ops, skb_owned_by);
 #endif /* CONFIG_SECURITY_NETWORK */
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
        set_to_cap_if_null(ops, xfrm_policy_alloc_security);
index 7b88c6aeaed43e5f37b449fd8ec87610b3b69a93..03f248b84e9fd964a8c2ba706916ce3a4a9a3f34 100644 (file)
@@ -1290,6 +1290,11 @@ int security_tun_dev_open(void *security)
 }
 EXPORT_SYMBOL(security_tun_dev_open);
 
+void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
+{
+       security_ops->skb_owned_by(skb, sk);
+}
+
 #endif /* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
index 2fa28c88900c1cb4ad7a1cc57e7b28421f4c1587..7171a957b9335694c1bbd1c5c9a41e2ec13bbda9 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/tty.h>
 #include <net/icmp.h>
 #include <net/ip.h>            /* for local_port_range[] */
+#include <net/sock.h>
 #include <net/tcp.h>           /* struct or_callable used in sock_rcv_skb */
 #include <net/net_namespace.h>
 #include <net/netlabel.h>
@@ -4363,6 +4364,11 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
        selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
 }
 
+static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
+{
+       skb_set_owner_w(skb, sk);
+}
+
 static int selinux_secmark_relabel_packet(u32 sid)
 {
        const struct task_security_struct *__tsec;
@@ -5664,6 +5670,7 @@ static struct security_operations selinux_ops = {
        .tun_dev_attach_queue =         selinux_tun_dev_attach_queue,
        .tun_dev_attach =               selinux_tun_dev_attach,
        .tun_dev_open =                 selinux_tun_dev_open,
+       .skb_owned_by =                 selinux_skb_owned_by,
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
        .xfrm_policy_alloc_security =   selinux_xfrm_policy_alloc,
index 71ae86ca64ac3b696121c66cbc7b334bc03cb3f3..eb560fa32321eff55002830cf78f2764d7a09518 100644 (file)
@@ -3222,18 +3222,10 @@ EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap);
 int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
                           struct vm_area_struct *area)
 {
-       long size;
-       unsigned long offset;
+       struct snd_pcm_runtime *runtime = substream->runtime;;
 
        area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
-       area->vm_flags |= VM_IO;
-       size = area->vm_end - area->vm_start;
-       offset = area->vm_pgoff << PAGE_SHIFT;
-       if (io_remap_pfn_range(area, area->vm_start,
-                               (substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
-                               size, area->vm_page_prot))
-               return -EAGAIN;
-       return 0;
+       return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
 }
 
 EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
index ecdf30eb5879ab4547e1e72b70bca366cb39ca78..4aba7646dd9c4999dafa488c7482ee4c65740167 100644 (file)
@@ -173,7 +173,7 @@ const char *snd_hda_get_jack_type(u32 cfg)
                "Line Out", "Speaker", "HP Out", "CD",
                "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
                "Line In", "Aux", "Mic", "Telephony",
-               "SPDIF In", "Digitial In", "Reserved", "Other"
+               "SPDIF In", "Digital In", "Reserved", "Other"
        };
 
        return jack_types[(cfg & AC_DEFCFG_DEVICE)
index 7dd846380a5015bffdfe628182ba1d22168362c1..d0d7ac1e99d24cc606b441e6ec23470a75800dcd 100644 (file)
@@ -320,7 +320,7 @@ int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
                     unsigned char *buf, int *eld_size)
 {
        int i;
-       int ret;
+       int ret = 0;
        int size;
 
        /*
index 43c2ea5395618f9ca1c166c9125b006839714f6d..2dbe767be16bba7e84a3f3219ea1e9e98f52ef84 100644 (file)
@@ -740,7 +740,7 @@ EXPORT_SYMBOL_HDA(snd_hda_activate_path);
 static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
 {
        struct hda_gen_spec *spec = codec->spec;
-       bool changed;
+       bool changed = false;
        int i;
 
        if (!spec->power_down_unused || path->active)
index 418bfc0eb0a3127234899aa6f84586feaa19eeef..bcd40ee488e35c85c880bc3d6764a2c7318cc5c2 100644 (file)
@@ -134,8 +134,8 @@ MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
  * this may give more power-saving, but will take longer time to
  * wake up.
  */
-static int power_save_controller = -1;
-module_param(power_save_controller, bint, 0644);
+static bool power_save_controller = 1;
+module_param(power_save_controller, bool, 0644);
 MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
 #endif /* CONFIG_PM */
 
@@ -2931,8 +2931,6 @@ static int azx_runtime_idle(struct device *dev)
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip = card->private_data;
 
-       if (power_save_controller > 0)
-               return 0;
        if (!power_save_controller ||
            !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
                return -EBUSY;
index 78e1827d0a956cd2ce9eaeb7fcc92d1f7ab3f6b2..de8ac5c07fd06628f971aed091b1668a697233d1 100644 (file)
@@ -1196,7 +1196,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
 
        _snd_printd(SND_PR_VERBOSE,
                "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-               codec->addr, pin_nid, eld->monitor_present, eld->eld_valid);
+               codec->addr, pin_nid, pin_eld->monitor_present, eld->eld_valid);
 
        if (eld->eld_valid) {
                if (snd_hdmi_get_eld(codec, pin_nid, eld->eld_buffer,
index 563c24df4d6f03f393def96afcd8340ee4538180..f15c36bde5403478513c5880e7ae65a9e1a42fe7 100644 (file)
@@ -3440,7 +3440,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
        const hda_nid_t *ssids;
 
        if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
-           codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
+           codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670 ||
+           codec->vendor_id == 0x10ec0671)
                ssids = alc663_ssids;
        else
                ssids = alc662_ssids;
@@ -3894,6 +3895,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
        { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
        { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
+       { .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 },
        { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
        { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
        { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index f2d61a18783089a61632d43b27653e912b4eafa4..566ea3256e2d784c38745ea05972917e19b4021e 100644 (file)
@@ -159,6 +159,7 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
                width = SI476X_PCM_FORMAT_S8;
+               break;
        case SNDRV_PCM_FORMAT_S16_LE:
                width = SI476X_PCM_FORMAT_S16_LE;
                break;
index b82bbf584146dc0b7c1bbaeb416a96f03f0d67af..34d0201d6a78a86a5dd6f1568dd898919fb8b512 100644 (file)
@@ -584,7 +584,7 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
                            struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
-       struct arizona *arizona = dev_get_drvdata(codec->dev);
+       struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
        struct regmap *regmap = codec->control_data;
        const struct reg_default *patch = NULL;
        int i, patch_size;
index 134e41c870b9a0077ae364eef131e471d15c96bf..f8a31ad0b203bcb64a027960775c465974a56970 100644 (file)
@@ -1083,6 +1083,8 @@ static const struct snd_soc_dapm_route wm8903_intercon[] = {
        { "ROP", NULL, "Right Speaker PGA" },
        { "RON", NULL, "Right Speaker PGA" },
 
+       { "Charge Pump", NULL, "CLK_DSP" },
+
        { "Left Headphone Output PGA", NULL, "Charge Pump" },
        { "Right Headphone Output PGA", NULL, "Charge Pump" },
        { "Left Line Output PGA", NULL, "Charge Pump" },
index f3f7e75f86280ef5160facc2a7f3cfa7972c6b91..9af1bddc4c62734d95dde719f37a8d2797d084ae 100644 (file)
@@ -828,7 +828,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                                                &buf_list);
                        if (!buf) {
                                adsp_err(dsp, "Out of memory\n");
-                               return -ENOMEM;
+                               ret = -ENOMEM;
+                               goto out_fw;
                        }
 
                        adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
@@ -865,7 +866,7 @@ out_fw:
        wm_adsp_buf_free(&buf_list);
 out:
        kfree(file);
-       return 0;
+       return ret;
 }
 
 int wm_adsp1_init(struct wm_adsp *adsp)
index 55464a5b0706161fffd7c94bc3c524f4b3e40224..810c7eeb7b03998d39a69dde175f21a9c8fcee1c 100644 (file)
@@ -496,6 +496,8 @@ static void imx_ssi_ac97_reset(struct snd_ac97 *ac97)
 
        if (imx_ssi->ac97_reset)
                imx_ssi->ac97_reset(ac97);
+       /* First read sometimes fails, do a dummy read */
+       imx_ssi_ac97_read(ac97, 0);
 }
 
 static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
@@ -504,6 +506,9 @@ static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
 
        if (imx_ssi->ac97_warm_reset)
                imx_ssi->ac97_warm_reset(ac97);
+
+       /* First read sometimes fails, do a dummy read */
+       imx_ssi_ac97_read(ac97, 0);
 }
 
 struct snd_ac97_bus_ops soc_ac97_ops = {
index 8e52c1485df37bfdbe21cbbbc49e801663f4126c..eb4373840bb6e1ab2cbbb1e5e9220e1c8474cb29 100644 (file)
@@ -51,7 +51,7 @@ static struct snd_soc_card pcm030_card = {
        .num_links = ARRAY_SIZE(pcm030_fabric_dai),
 };
 
-static int __init pcm030_fabric_probe(struct platform_device *op)
+static int pcm030_fabric_probe(struct platform_device *op)
 {
        struct device_node *np = op->dev.of_node;
        struct device_node *platform_np;
index d7231e336a7c678e4b8b5f86ef0efa4a2eb04e8a..6bbeb0bf1a73a58fa9e3a573e00655dc3e8763d2 100644 (file)
@@ -972,6 +972,7 @@ static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
 static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 {
        struct i2s_dai *i2s;
+       int ret;
 
        i2s = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dai), GFP_KERNEL);
        if (i2s == NULL)
@@ -996,15 +997,17 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
                i2s->i2s_dai_drv.capture.channels_max = 2;
                i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES;
                i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
+               dev_set_drvdata(&i2s->pdev->dev, i2s);
        } else {        /* Create a new platform_device for Secondary */
-               i2s->pdev = platform_device_register_resndata(NULL,
-                               "samsung-i2s-sec", -1, NULL, 0, NULL, 0);
+               i2s->pdev = platform_device_alloc("samsung-i2s-sec", -1);
                if (IS_ERR(i2s->pdev))
                        return NULL;
-       }
 
-       /* Pre-assign snd_soc_dai_set_drvdata */
-       dev_set_drvdata(&i2s->pdev->dev, i2s);
+               platform_set_drvdata(i2s->pdev, i2s);
+               ret = platform_device_add(i2s->pdev);
+               if (ret < 0)
+                       return NULL;
+       }
 
        return i2s;
 }
@@ -1107,6 +1110,10 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 
        if (samsung_dai_type == TYPE_SEC) {
                sec_dai = dev_get_drvdata(&pdev->dev);
+               if (!sec_dai) {
+                       dev_err(&pdev->dev, "Unable to get drvdata\n");
+                       return -EFAULT;
+               }
                snd_soc_register_dai(&sec_dai->pdev->dev,
                        &sec_dai->i2s_dai_drv);
                asoc_dma_platform_register(&pdev->dev);
index 19eff8fc4fdddda4a8ca47972a8c9700c7ea0af1..1a8b03e4b41b9c3f7ce38fcc79130307d757cb51 100644 (file)
@@ -342,8 +342,8 @@ static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-static struct snd_soc_platform sh7760_soc_platform = {
-       .pcm_ops        = &camelot_pcm_ops,
+static struct snd_soc_platform_driver sh7760_soc_platform = {
+       .ops            = &camelot_pcm_ops,
        .pcm_new        = camelot_pcm_new,
        .pcm_free       = camelot_pcm_free,
 };
index b5b3db71e25303813bfe216e7f0c7020dcf97ff3..ed0bfb0ddb96ffb8bb0321810085b8f9409623a1 100644 (file)
@@ -211,19 +211,27 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream,
        if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
                ret = platform->driver->compr_ops->set_params(cstream, params);
                if (ret < 0)
-                       goto out;
+                       goto err;
        }
 
        if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
                ret = rtd->dai_link->compr_ops->set_params(cstream);
                if (ret < 0)
-                       goto out;
+                       goto err;
        }
 
        snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
                                SND_SOC_DAPM_STREAM_START);
 
-out:
+       /* cancel any delayed stream shutdown that is pending */
+       rtd->pop_wait = 0;
+       mutex_unlock(&rtd->pcm_mutex);
+
+       cancel_delayed_work_sync(&rtd->delayed_work);
+
+       return ret;
+
+err:
        mutex_unlock(&rtd->pcm_mutex);
        return ret;
 }
index b7e84a7cd9ee70451e453f9ef8febb23f3ad05ab..ff4b45a5d796f0f16dcd09b7611ad6dc3bda5bb0 100644 (file)
@@ -2963,7 +2963,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
        val = val << shift;
 
        ret = snd_soc_update_bits_locked(codec, reg, val_mask, val);
-       if (ret != 0)
+       if (ret < 0)
                return ret;
 
        if (snd_soc_volsw_is_stereo(mc)) {
@@ -3140,7 +3140,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
        if (params->mask) {
                ret = regmap_read(codec->control_data, params->base, &val);
                if (ret != 0)
-                       return ret;
+                       goto out;
 
                val &= params->mask;
 
@@ -3158,13 +3158,15 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
                        ((u32 *)data)[0] |= cpu_to_be32(val);
                        break;
                default:
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto out;
                }
        }
 
        ret = regmap_raw_write(codec->control_data, params->base,
                               data, len);
 
+out:
        kfree(data);
 
        return ret;
@@ -4197,7 +4199,6 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
                        dev_err(card->dev,
                                "ASoC: Property '%s' index %d could not be read: %d\n",
                                propname, 2 * i, ret);
-                       kfree(routes);
                        return -EINVAL;
                }
                ret = of_property_read_string_index(np, propname,
@@ -4206,7 +4207,6 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
                        dev_err(card->dev,
                                "ASoC: Property '%s' index %d could not be read: %d\n",
                                propname, (2 * i) + 1, ret);
-                       kfree(routes);
                        return -EINVAL;
                }
        }
index 1d6a9b3ceb27cc0b9a6ea307faecaf5872d6b6c9..d6d9ba2e6916fe8f0ab263c03e3a0de2cd208232 100644 (file)
@@ -831,6 +831,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
                if (path->weak)
                        continue;
 
+               if (path->walking)
+                       return 1;
+
                if (path->walked)
                        continue;
 
@@ -838,6 +841,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
 
                if (path->sink && path->connect) {
                        path->walked = 1;
+                       path->walking = 1;
 
                        /* do we need to add this widget to the list ? */
                        if (list) {
@@ -847,11 +851,14 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
                                        dev_err(widget->dapm->dev,
                                                "ASoC: could not add widget %s\n",
                                                widget->name);
+                                       path->walking = 0;
                                        return con;
                                }
                        }
 
                        con += is_connected_output_ep(path->sink, list);
+
+                       path->walking = 0;
                }
        }
 
@@ -931,6 +938,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
                if (path->weak)
                        continue;
 
+               if (path->walking)
+                       return 1;
+
                if (path->walked)
                        continue;
 
@@ -938,6 +948,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
 
                if (path->source && path->connect) {
                        path->walked = 1;
+                       path->walking = 1;
 
                        /* do we need to add this widget to the list ? */
                        if (list) {
@@ -947,11 +958,14 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
                                        dev_err(widget->dapm->dev,
                                                "ASoC: could not add widget %s\n",
                                                widget->name);
+                                       path->walking = 0;
                                        return con;
                                }
                        }
 
                        con += is_connected_input_ep(path->source, list);
+
+                       path->walking = 0;
                }
        }
 
index 9b76cc5a114897613ed3d19e87b13b649037c4be..5e7aebe1e664bad240ded255bf03565f20670cc2 100644 (file)
@@ -149,9 +149,9 @@ static void spear_pcm_free(struct snd_pcm *pcm)
 
 static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
 
-static int spear_pcm_new(struct snd_card *card,
-               struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_card *card = rtd->card->snd_card;
        int ret;
 
        if (!card->dev->dma_mask)
@@ -159,16 +159,16 @@ static int spear_pcm_new(struct snd_card *card,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-       if (dai->driver->playback.channels_min) {
-               ret = spear_pcm_preallocate_dma_buffer(pcm,
+       if (rtd->cpu_dai->driver->playback.channels_min) {
+               ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
                                SNDRV_PCM_STREAM_PLAYBACK,
                                spear_pcm_hardware.buffer_bytes_max);
                if (ret)
                        return ret;
        }
 
-       if (dai->driver->capture.channels_min) {
-               ret = spear_pcm_preallocate_dma_buffer(pcm,
+       if (rtd->cpu_dai->driver->capture.channels_min) {
+               ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
                                SNDRV_PCM_STREAM_CAPTURE,
                                spear_pcm_hardware.buffer_bytes_max);
                if (ret)
index c925ab0adeb6b0a2750106518f825cfd7b1ef864..5e2c55c5b255920ae26f38b705662f31b785d512 100644 (file)
@@ -43,8 +43,6 @@
 static const struct snd_pcm_hardware tegra_pcm_hardware = {
        .info                   = SNDRV_PCM_INFO_MMAP |
                                  SNDRV_PCM_INFO_MMAP_VALID |
-                                 SNDRV_PCM_INFO_PAUSE |
-                                 SNDRV_PCM_INFO_RESUME |
                                  SNDRV_PCM_INFO_INTERLEAVED,
        .formats                = SNDRV_PCM_FMTBIT_S16_LE,
        .channels_min           = 2,
@@ -127,26 +125,6 @@ static int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               return snd_dmaengine_pcm_trigger(substream,
-                                       SNDRV_PCM_TRIGGER_START);
-
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               return snd_dmaengine_pcm_trigger(substream,
-                                       SNDRV_PCM_TRIGGER_STOP);
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
 static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
                                struct vm_area_struct *vma)
 {
@@ -164,7 +142,7 @@ static struct snd_pcm_ops tegra_pcm_ops = {
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = tegra_pcm_hw_params,
        .hw_free        = tegra_pcm_hw_free,
-       .trigger        = tegra_pcm_trigger,
+       .trigger        = snd_dmaengine_pcm_trigger,
        .pointer        = snd_dmaengine_pcm_pointer,
        .mmap           = tegra_pcm_mmap,
 };
index 5e634a2eb2829461e9efea055a042384e3714b29..9e2703a2515630b82d5659200ae50d6da44c90e6 100644 (file)
@@ -253,7 +253,7 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
 {
        struct usb_device *dev = chip->dev;
        unsigned char data[4];
-       int err, crate;
+       int err, cur_rate, prev_rate;
        int clock = snd_usb_clock_find_source(chip, fmt->clock);
 
        if (clock < 0)
@@ -266,6 +266,19 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
                return -ENXIO;
        }
 
+       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+                             snd_usb_ctrl_intf(chip) | (clock << 8),
+                             data, sizeof(data));
+       if (err < 0) {
+               snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
+                          dev->devnum, iface, fmt->altsetting);
+               prev_rate = 0;
+       } else {
+               prev_rate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+       }
+
        data[0] = rate;
        data[1] = rate >> 8;
        data[2] = rate >> 16;
@@ -280,19 +293,31 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
                return err;
        }
 
-       if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                                  USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                                  UAC2_CS_CONTROL_SAM_FREQ << 8,
-                                  snd_usb_ctrl_intf(chip) | (clock << 8),
-                                  data, sizeof(data))) < 0) {
+       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+                             snd_usb_ctrl_intf(chip) | (clock << 8),
+                             data, sizeof(data));
+       if (err < 0) {
                snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
                           dev->devnum, iface, fmt->altsetting);
-               return err;
+               cur_rate = 0;
+       } else {
+               cur_rate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
        }
 
-       crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
-       if (crate != rate)
-               snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
+       if (cur_rate != rate) {
+               snd_printd(KERN_WARNING
+                          "current rate %d is different from the runtime rate %d\n",
+                          cur_rate, rate);
+       }
+
+       /* Some devices doesn't respond to sample rate changes while the
+        * interface is active. */
+       if (rate != prev_rate) {
+               usb_set_interface(dev, iface, 0);
+               usb_set_interface(dev, iface, fmt->altsetting);
+       }
 
        return 0;
 }
index 497d2741d1192f7b5b8eea43d9347023faa220f2..ebe91440a068a8f500901652892d5a3575b68e63 100644 (file)
@@ -509,7 +509,7 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
        else
                ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-                                 0, cpu_to_le16(wIndex),
+                                 0, wIndex,
                                  &tmp, sizeof(tmp), 1000);
        up_read(&mixer->chip->shutdown_rwsem);
 
@@ -540,7 +540,7 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
        else
                ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
-                                 cpu_to_le16(wValue), cpu_to_le16(wIndex),
+                                 wValue, wIndex,
                                  NULL, 0, 1000);
        up_read(&mixer->chip->shutdown_rwsem);
 
index 5325a3869bb7fbbb714bbb7d6bc894062e00b2b7..9c5ab22358b159f919612fd20779dc81bb19b7d2 100644 (file)
@@ -486,7 +486,7 @@ static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
 {
        int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                  0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                                 cpu_to_le16(1), 0, NULL, 0, 1000);
+                                 1, 0, NULL, 0, 1000);
 
        if (ret < 0)
                return ret;
index 6f3214ed4444ecb14c33cc29c3119057bf812cf5..321e066a07533bcf7a18e72c471e01cc1bef9527 100644 (file)
@@ -1421,6 +1421,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
        case 0x3C:      /* HSW */
        case 0x3F:      /* HSW */
        case 0x45:      /* HSW */
+       case 0x46:      /* HSW */
                return 1;
        case 0x2E:      /* Nehalem-EX Xeon - Beckton */
        case 0x2F:      /* Westmere-EX Xeon - Eagleton */
@@ -1515,6 +1516,7 @@ void rapl_probe(unsigned int family, unsigned int model)
        case 0x3C:      /* HSW */
        case 0x3F:      /* HSW */
        case 0x45:      /* HSW */
+       case 0x46:      /* HSW */
                do_rapl = RAPL_PKG | RAPL_CORES | RAPL_GFX;
                break;
        case 0x2D:
@@ -1754,6 +1756,7 @@ int is_snb(unsigned int family, unsigned int model)
        case 0x3C:      /* HSW */
        case 0x3F:      /* HSW */
        case 0x45:      /* HSW */
+       case 0x46:      /* HSW */
                return 1;
        }
        return 0;
@@ -2276,7 +2279,7 @@ int main(int argc, char **argv)
        cmdline(argc, argv);
 
        if (verbose)
-               fprintf(stderr, "turbostat v3.2 February 11, 2013"
+               fprintf(stderr, "turbostat v3.3 March 15, 2013"
                        " - Len Brown <lenb@kernel.org>\n");
 
        turbostat_init();
index adc68feb5c5a338080ac8ca2385f73577ac6c29a..f18013f09e68423d68d4033d1e22fe1f8701886b 100644 (file)
@@ -1541,21 +1541,38 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data,
 }
 
 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
-                             gpa_t gpa)
+                             gpa_t gpa, unsigned long len)
 {
        struct kvm_memslots *slots = kvm_memslots(kvm);
        int offset = offset_in_page(gpa);
-       gfn_t gfn = gpa >> PAGE_SHIFT;
+       gfn_t start_gfn = gpa >> PAGE_SHIFT;
+       gfn_t end_gfn = (gpa + len - 1) >> PAGE_SHIFT;
+       gfn_t nr_pages_needed = end_gfn - start_gfn + 1;
+       gfn_t nr_pages_avail;
 
        ghc->gpa = gpa;
        ghc->generation = slots->generation;
-       ghc->memslot = gfn_to_memslot(kvm, gfn);
-       ghc->hva = gfn_to_hva_many(ghc->memslot, gfn, NULL);
-       if (!kvm_is_error_hva(ghc->hva))
+       ghc->len = len;
+       ghc->memslot = gfn_to_memslot(kvm, start_gfn);
+       ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail);
+       if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) {
                ghc->hva += offset;
-       else
-               return -EFAULT;
-
+       } else {
+               /*
+                * If the requested region crosses two memslots, we still
+                * verify that the entire region is valid here.
+                */
+               while (start_gfn <= end_gfn) {
+                       ghc->memslot = gfn_to_memslot(kvm, start_gfn);
+                       ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn,
+                                                  &nr_pages_avail);
+                       if (kvm_is_error_hva(ghc->hva))
+                               return -EFAULT;
+                       start_gfn += nr_pages_avail;
+               }
+               /* Use the slow path for cross page reads and writes. */
+               ghc->memslot = NULL;
+       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(kvm_gfn_to_hva_cache_init);
@@ -1566,8 +1583,13 @@ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
        struct kvm_memslots *slots = kvm_memslots(kvm);
        int r;
 
+       BUG_ON(len > ghc->len);
+
        if (slots->generation != ghc->generation)
-               kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
+               kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
+
+       if (unlikely(!ghc->memslot))
+               return kvm_write_guest(kvm, ghc->gpa, data, len);
 
        if (kvm_is_error_hva(ghc->hva))
                return -EFAULT;
@@ -1587,8 +1609,13 @@ int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
        struct kvm_memslots *slots = kvm_memslots(kvm);
        int r;
 
+       BUG_ON(len > ghc->len);
+
        if (slots->generation != ghc->generation)
-               kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
+               kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
+
+       if (unlikely(!ghc->memslot))
+               return kvm_read_guest(kvm, ghc->gpa, data, len);
 
        if (kvm_is_error_hva(ghc->hva))
                return -EFAULT;