Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 12 Jun 2011 18:03:08 +0000 (11:03 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 12 Jun 2011 18:03:08 +0000 (11:03 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (55 commits)
  ISDN, hfcsusb: Don't leak in hfcsusb_ph_info()
  netpoll: call dev_put() on error in netpoll_setup()
  net: ep93xx_eth: fix DMA API violations
  net: ep93xx_eth: drop GFP_DMA from call to dma_alloc_coherent()
  net: ep93xx_eth: allocate buffers using kmalloc()
  net: ep93xx_eth: pass struct device to DMA API functions
  ep93xx: set DMA masks for the ep93xx_eth
  vlan: Fix the ingress VLAN_FLAG_REORDER_HDR check
  dl2k: EEPROM CRC calculation wrong endianess on bigendian machine
  NET: am79c961: fix assembler warnings
  NET: am79c961: ensure multicast filter is correctly set at open
  NET: am79c961: ensure asm() statements are marked volatile
  ethtool.h: fix typos
  ep93xx_eth: Update MAINTAINERS
  ipv4: Fix packet size calculation for raw IPsec packets in __ip_append_data
  netpoll: prevent netpoll setup on slave devices
  net: pmtu_expires fixes
  gianfar:localized filer table
  iwlegacy: fix channel switch locking
  mac80211: fix IBSS teardown race
  ...

335 files changed:
CREDITS
Documentation/kernel-parameters.txt
MAINTAINERS
Makefile
arch/arm/mach-omap1/dma.c
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-cm-t3517.c
arch/arm/mach-omap2/board-devkit8000.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-omap3touchbook.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-zoom-display.c
arch/arm/mach-omap2/common-board-devices.c
arch/arm/mach-omap2/common-board-devices.h
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/hsmmc.h
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/mux.h
arch/arm/mach-omap2/mux44xx.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_phy_internal.c
arch/arm/mach-tegra/board-harmony-power.c
arch/arm/mach-tegra/board-harmony.h
arch/arm/plat-omap/include/plat/flash.h
arch/arm/plat-omap/include/plat/iovmm.h
arch/arm/plat-omap/include/plat/mmc.h
arch/arm/plat-omap/iovmm.c
arch/arm/plat-omap/sram.c
arch/mn10300/kernel/traps.c
arch/mn10300/kernel/vmlinux.lds.S
arch/mn10300/mm/cache-dbg-flush-by-reg.S
arch/powerpc/boot/.gitignore
arch/powerpc/boot/dtc-src/.gitignore [deleted file]
arch/powerpc/include/asm/rio.h
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/prom.c
arch/powerpc/mm/init_32.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/sysdev/fsl_lbc.c
arch/s390/Kconfig
arch/s390/include/asm/pgalloc.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/qdio.h
arch/s390/include/asm/tlb.h
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/sie64a.S
arch/s390/mm/pgtable.c
arch/sparc/Kconfig
arch/sparc/include/asm/floppy_32.h
arch/sparc/include/asm/floppy_64.h
arch/sparc/include/asm/leon.h
arch/sparc/include/asm/leon_pci.h [new file with mode: 0644]
arch/sparc/include/asm/pci_32.h
arch/sparc/include/asm/pcic.h
arch/sparc/include/asm/system_32.h
arch/sparc/include/asm/system_64.h
arch/sparc/kernel/Makefile
arch/sparc/kernel/apc.c
arch/sparc/kernel/auxio_32.c
arch/sparc/kernel/chmc.c
arch/sparc/kernel/entry.S
arch/sparc/kernel/leon_kernel.c
arch/sparc/kernel/leon_pci.c [new file with mode: 0644]
arch/sparc/kernel/leon_pci_grpci2.c [new file with mode: 0644]
arch/sparc/kernel/module.c
arch/sparc/kernel/pci_common.c
arch/sparc/kernel/pci_schizo.c
arch/sparc/kernel/prom_irqtrans.c
arch/sparc/kernel/psycho_common.c
arch/sparc/kernel/sbus.c
arch/sparc/kernel/setup_32.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/smp_32.c
arch/sparc/kernel/sun4d_irq.c
arch/sparc/kernel/sys_sparc32.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/time_64.c
arch/sparc/kernel/traps_64.c
arch/sparc/kernel/unaligned_64.c
arch/sparc/kernel/us2e_cpufreq.c
arch/sparc/kernel/us3_cpufreq.c
arch/sparc/kernel/viohs.c
arch/sparc/kernel/visemul.c
arch/sparc/mm/fault_32.c
arch/sparc/mm/init_32.c
arch/sparc/mm/init_64.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
arch/sparc/mm/tsb.c
arch/sparc/prom/console_32.c
arch/sparc/prom/init_32.c
arch/sparc/prom/mp.c
arch/unicore32/Kconfig
arch/unicore32/Makefile
arch/unicore32/boot/compressed/Makefile
arch/unicore32/configs/debug_defconfig [deleted file]
arch/unicore32/configs/unicore32_defconfig [new file with mode: 0644]
arch/unicore32/include/asm/Kbuild
arch/unicore32/kernel/Makefile
arch/unicore32/kernel/rtc.c [deleted file]
arch/unicore32/kernel/vmlinux.lds.S
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kvm/emulate.c
arch/x86/xen/multicalls.c
drivers/ata/libata-eh.c
drivers/base/power/clock_ops.c
drivers/firmware/iscsi_ibft_find.c
drivers/gpio/Kconfig
drivers/gpio/gpio-exynos4.c
drivers/gpio/gpio-omap.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_modes.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/nouveau/nouveau_hw.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nouveau_vm.c
drivers/gpu/drm/nouveau/nv04_crtc.c
drivers/gpu/drm/nouveau/nvreg.h
drivers/gpu/drm/radeon/Kconfig
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/cayman_blit_shaders.c
drivers/gpu/drm/radeon/cayman_blit_shaders.h
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_blit_kms.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_family.h
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/reg_srcs/r600
drivers/hwmon/coretemp.c
drivers/hwmon/max6642.c
drivers/media/dvb/dvb-usb/anysee.c
drivers/media/media-devnode.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/gspca/coarse_expo_autogain.h [deleted file]
drivers/media/video/gspca/ov519.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-firmware.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-ioctl.h
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/ivtv/ivtv-vbi.c
drivers/media/video/ivtv/ivtvfb.c
drivers/media/video/omap3isp/isp.c
drivers/media/video/soc_camera.c
drivers/media/video/uvc/uvc_entity.c
drivers/mmc/host/omap_hsmmc.c
drivers/pci/Makefile
drivers/pci/intel-iommu.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-m41t93.c
drivers/rtc/rtc-puv3.c [new file with mode: 0644]
drivers/s390/cio/qdio_main.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_qdio.h
drivers/spi/omap2_mcspi.c
drivers/staging/Kconfig
drivers/staging/altera-stapl/altera-jtag.c
drivers/staging/altera-stapl/altera.c
drivers/staging/altera-stapl/altera.h [new file with mode: 0644]
drivers/staging/ath6kl/Kconfig
drivers/staging/ath6kl/os/linux/cfg80211.c
drivers/staging/brcm80211/brcmfmac/wl_iw.c
drivers/staging/gma500/psb_drv.c
drivers/staging/gma500/psb_fb.c
drivers/staging/gma500/psb_intel_bios.c
drivers/staging/iio/dac/max517.c
drivers/staging/iio/imu/adis16400_ring.c
drivers/staging/iio/industrialio-trigger.c
drivers/staging/mei/init.c
drivers/staging/olpc_dcon/Kconfig
drivers/staging/rts_pstor/sd.c
drivers/staging/usbip/stub_dev.c
drivers/staging/usbip/stub_rx.c
drivers/tty/tty_buffer.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/hub.c
drivers/usb/core/inode.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/amd5536udc.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/mv_udc_core.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/s3c-hsudc.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_core.c
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/storage/transport.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
drivers/usb/storage/usb.h
drivers/video/arcfb.c
drivers/video/bf537-lq035.c
drivers/video/broadsheetfb.c
drivers/video/efifb.c
drivers/video/hecubafb.c
drivers/video/imxfb.c
drivers/video/metronomefb.c
drivers/video/modedb.c
drivers/video/pxa168fb.c
drivers/video/savage/savagefb_driver.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/vga16fb.c
drivers/video/xen-fbfront.c
drivers/xen/events.c
drivers/xen/swiotlb-xen.c
fs/btrfs/btrfs_inode.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/volumes.c
fs/btrfs/xattr.c
fs/cifs/Kconfig
fs/cifs/cifsencrypt.c
fs/cifs/connect.c
fs/exec.c
fs/fat/file.c
fs/fuse/inode.c
fs/gfs2/glock.c
fs/jfs/jfs_logmgr.c
fs/namei.c
fs/ocfs2/super.c
fs/super.c
include/drm/drm_pciids.h
include/linux/fs.h
include/linux/irqreturn.h
include/linux/perf_event.h
include/linux/sched.h
include/linux/seqlock.h
include/linux/swiotlb.h
include/linux/usb_usual.h
include/media/v4l2-dev.h
include/staging/altera.h [deleted file]
kernel/events/core.c
kernel/irq/handle.c
kernel/irq/irqdesc.c
kernel/irq/manage.c
kernel/irq/spurious.c
kernel/lockdep.c
kernel/sched.c
kernel/sysctl.c
kernel/time/clockevents.c
kernel/timer.c
lib/swiotlb.c
lib/vsprintf.c
mm/filemap.c
mm/hugetlb.c
scripts/Makefile.asm-generic
scripts/depmod.sh [new file with mode: 0755]
security/apparmor/lsm.c
security/selinux/hooks.c
sound/pci/asihpi/hpidspcd.c
sound/pci/fm801.c
sound/pci/hda/patch_analog.c
sound/soc/codecs/wm_hubs.c
sound/soc/soc-dapm.c
sound/usb/6fire/firmware.c
sound/usb/quirks.c
tools/perf/builtin-test.c
tools/perf/util/PERF-VERSION-GEN
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/python.c
tools/perf/util/session.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index a7ea8e3..d78359f 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -518,6 +518,14 @@ N: Zach Brown
 E: zab@zabbo.net
 D: maestro pci sound
 
+M: David Brownell
+D: Kernel engineer, mentor, and friend.  Maintained USB EHCI and
+D: gadget layers, SPI subsystem, GPIO subsystem, and more than a few
+D: device drivers.  His encouragement also helped many engineers get
+D: started working on the Linux kernel.  David passed away in early
+D: 2011, and will be greatly missed.
+W: https://lkml.org/lkml/2011/4/5/36
+
 N: Gary Brubaker
 E: xavyer@ix.netcom.com
 D: USB Serial Empeg Empeg-car Mark I/II Driver
index d9a203b..fd248a3 100644 (file)
@@ -2598,6 +2598,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                                        unlock ejectable media);
                                m = MAX_SECTORS_64 (don't transfer more
                                        than 64 sectors = 32 KB at a time);
+                               n = INITIAL_READ10 (force a retry of the
+                                       initial READ(10) command);
                                o = CAPACITY_OK (accept the capacity
                                        reported by the device);
                                r = IGNORE_RESIDUE (the device reports
index 6a1c430..e50fc6e 100644 (file)
@@ -4252,8 +4252,7 @@ F:        drivers/mmc/
 F:     include/linux/mmc/
 
 MULTIMEDIA CARD (MMC) ETC. OVER SPI
-M:     David Brownell <dbrownell@users.sourceforge.net>
-S:     Odd Fixes
+S:     Orphan
 F:     drivers/mmc/host/mmc_spi.c
 F:     include/linux/spi/mmc_spi.h
 
@@ -4603,7 +4602,6 @@ F:        drivers/media/video/omap3isp/*
 
 OMAP USB SUPPORT
 M:     Felipe Balbi <balbi@ti.com>
-M:     David Brownell <dbrownell@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
 L:     linux-omap@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
@@ -4947,6 +4945,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.gi
 F:     drivers/input/serio/i8042-unicore32io.h
 F:     drivers/i2c/busses/i2c-puv3.c
 F:     drivers/video/fb-puv3.c
+F:     drivers/rtc/rtc-puv3.c
 
 PMC SIERRA MaxRAID DRIVER
 M:     Anil Ravindranath <anil_ravindranath@pmc-sierra.com>
@@ -5984,7 +5983,6 @@ F:        Documentation/serial/specialix.txt
 F:     drivers/staging/tty/specialix*
 
 SPI SUBSYSTEM
-M:     David Brownell <dbrownell@users.sourceforge.net>
 M:     Grant Likely <grant.likely@secretlab.ca>
 L:     spi-devel-general@lists.sourceforge.net
 Q:     http://patchwork.kernel.org/project/spi-devel-general/list/
@@ -6432,9 +6430,8 @@ S:        Maintained
 F:     drivers/usb/misc/rio500*
 
 USB EHCI DRIVER
-M:     David Brownell <dbrownell@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
-S:     Odd Fixes
+S:     Orphan
 F:     Documentation/usb/ehci.txt
 F:     drivers/usb/host/ehci*
 
@@ -6448,9 +6445,10 @@ S:       Maintained
 F:     drivers/media/video/et61x251/
 
 USB GADGET/PERIPHERAL SUBSYSTEM
-M:     David Brownell <dbrownell@users.sourceforge.net>
+M:     Felipe Balbi <balbi@ti.com>
 L:     linux-usb@vger.kernel.org
 W:     http://www.linux-usb.org/gadget
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
 S:     Maintained
 F:     drivers/usb/gadget/
 F:     include/linux/usb/gadget*
@@ -6492,9 +6490,8 @@ S:        Maintained
 F:     sound/usb/midi.*
 
 USB OHCI DRIVER
-M:     David Brownell <dbrownell@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
-S:     Odd Fixes
+S:     Orphan
 F:     Documentation/usb/ohci.txt
 F:     drivers/usb/host/ohci*
 
index afb8e0d..72c0e32 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 NAME = Sneaky Weasel
 
 # *DOCUMENTATION*
@@ -378,7 +378,7 @@ KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
 
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
 KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
-KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
 
 export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
 export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
@@ -1005,7 +1005,7 @@ endef
 
 define filechk_version.h
        (echo \#define LINUX_VERSION_CODE $(shell                             \
-       expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + $(SUBLEVEL));     \
+       expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL));    \
        echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
 endef
 
@@ -1110,11 +1110,6 @@ modules_install: _modinst_ _modinst_post
 
 PHONY += _modinst_
 _modinst_:
-       @if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
-               echo "Warning: you may need to install module-init-tools"; \
-               echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
-               sleep 1; \
-       fi
        @rm -rf $(MODLIB)/kernel
        @rm -f $(MODLIB)/source
        @mkdir -p $(MODLIB)/kernel
@@ -1531,12 +1526,7 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files))
 
 # Run depmod only if we have System.map and depmod is executable
 quiet_cmd_depmod = DEPMOD  $(KERNELRELEASE)
-      cmd_depmod = \
-       if [ -r System.map -a -x $(DEPMOD) ]; then                              \
-               $(DEPMOD) -ae -F System.map                                     \
-               $(if $(strip $(INSTALL_MOD_PATH)), -b $(INSTALL_MOD_PATH) )     \
-               $(KERNELRELEASE);                                               \
-       fi
+      cmd_depmod = $(srctree)/scripts/depmod.sh $(DEPMOD) $(KERNELRELEASE)
 
 # Create temporary dir for module support files
 # clean it up only when building all modules
index d855934..f5a5220 100644 (file)
@@ -284,14 +284,15 @@ static int __init omap1_system_dma_init(void)
        dma_base = ioremap(res[0].start, resource_size(&res[0]));
        if (!dma_base) {
                pr_err("%s: Unable to ioremap\n", __func__);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto exit_device_put;
        }
 
        ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
        if (ret) {
                dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
                        __func__, pdev->name, pdev->id);
-               goto exit_device_del;
+               goto exit_device_put;
        }
 
        p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
@@ -299,7 +300,7 @@ static int __init omap1_system_dma_init(void)
                dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n",
                        __func__, pdev->name);
                ret = -ENOMEM;
-               goto exit_device_put;
+               goto exit_device_del;
        }
 
        d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
@@ -380,10 +381,10 @@ exit_release_d:
        kfree(d);
 exit_release_p:
        kfree(p);
-exit_device_put:
-       platform_device_put(pdev);
 exit_device_del:
        platform_device_del(pdev);
+exit_device_put:
+       platform_device_put(pdev);
 
        return ret;
 }
index d54969b..5de6eac 100644 (file)
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/board.h>
 #include <plat/common.h>
 #include <plat/gpmc.h>
index ae2963a..5dac974 100644 (file)
@@ -622,19 +622,19 @@ static struct omap_device_pad serial3_pads[] __initdata = {
                         OMAP_MUX_MODE0),
 };
 
-static struct omap_board_data serial1_data = {
+static struct omap_board_data serial1_data __initdata = {
        .id             = 0,
        .pads           = serial1_pads,
        .pads_cnt       = ARRAY_SIZE(serial1_pads),
 };
 
-static struct omap_board_data serial2_data = {
+static struct omap_board_data serial2_data __initdata = {
        .id             = 1,
        .pads           = serial2_pads,
        .pads_cnt       = ARRAY_SIZE(serial2_pads),
 };
 
-static struct omap_board_data serial3_data = {
+static struct omap_board_data serial3_data __initdata = {
        .id             = 2,
        .pads           = serial3_pads,
        .pads_cnt       = ARRAY_SIZE(serial3_pads),
index 73fa90b..63de2d3 100644 (file)
@@ -258,7 +258,7 @@ static struct gpio sdp4430_eth_gpios[] __initdata = {
        { ETH_KS8851_IRQ,       GPIOF_IN,               "eth_irq"       },
 };
 
-static int omap_ethernet_init(void)
+static int __init omap_ethernet_init(void)
 {
        int status;
 
@@ -322,6 +322,7 @@ static struct omap2_hsmmc_info mmc[] = {
                .gpio_wp        = -EINVAL,
                .nonremovable   = true,
                .ocr_mask       = MMC_VDD_29_30,
+               .no_off_init    = true,
        },
        {
                .mmc            = 1,
@@ -681,19 +682,19 @@ static struct omap_device_pad serial4_pads[] __initdata = {
                         OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
 };
 
-static struct omap_board_data serial2_data = {
+static struct omap_board_data serial2_data __initdata = {
        .id             = 1,
        .pads           = serial2_pads,
        .pads_cnt       = ARRAY_SIZE(serial2_pads),
 };
 
-static struct omap_board_data serial3_data = {
+static struct omap_board_data serial3_data __initdata = {
        .id             = 2,
        .pads           = serial3_pads,
        .pads_cnt       = ARRAY_SIZE(serial3_pads),
 };
 
-static struct omap_board_data serial4_data = {
+static struct omap_board_data serial4_data __initdata = {
        .id             = 3,
        .pads           = serial4_pads,
        .pads_cnt       = ARRAY_SIZE(serial4_pads),
@@ -729,7 +730,7 @@ static void __init omap_4430sdp_init(void)
 
        if (omap_rev() == OMAP4430_REV_ES1_0)
                package = OMAP_PACKAGE_CBL;
-       omap4_mux_init(board_mux, package);
+       omap4_mux_init(board_mux, NULL, package);
 
        omap_board_config = sdp4430_config;
        omap_board_config_size = ARRAY_SIZE(sdp4430_config);
index f3beb8e..b124bdf 100644 (file)
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/smc91x.h>
+#include <linux/gpio.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
-#include <mach/gpio.h>
 #include <plat/led.h>
 #include <plat/usb.h>
 #include <plat/board.h>
index c63115b..77456de 100644 (file)
@@ -63,8 +63,6 @@
 #define SB_T35_SMSC911X_CS     4
 #define SB_T35_SMSC911X_GPIO   65
 
-#define NAND_BLOCK_SIZE                SZ_128K
-
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <linux/smsc911x.h>
 #include <plat/gpmc-smsc911x.h>
index 08f08e8..c3a9fd3 100644 (file)
@@ -48,6 +48,7 @@
 
 #include "mux.h"
 #include "control.h"
+#include "common-board-devices.h"
 
 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
 static struct gpio_led cm_t3517_leds[] = {
@@ -177,7 +178,7 @@ static struct usbhs_omap_board_data cm_t3517_ehci_pdata __initdata = {
        .reset_gpio_port[2]  = -EINVAL,
 };
 
-static int cm_t3517_init_usbh(void)
+static int __init cm_t3517_init_usbh(void)
 {
        int err;
 
@@ -203,8 +204,6 @@ static inline int cm_t3517_init_usbh(void)
 #endif
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-#define NAND_BLOCK_SIZE                SZ_128K
-
 static struct mtd_partition cm_t3517_nand_partitions[] = {
        {
                .name           = "xloader",
index cf520d7..34956ec 100644 (file)
@@ -61,8 +61,6 @@
 #include "timer-gp.h"
 #include "common-board-devices.h"
 
-#define NAND_BLOCK_SIZE                SZ_128K
-
 #define OMAP_DM9000_GPIO_IRQ   25
 #define OMAP3_DEVKIT_TS_GPIO   27
 
index be71426..7f21d24 100644 (file)
@@ -54,8 +54,6 @@
 #include "pm.h"
 #include "common-board-devices.h"
 
-#define NAND_BLOCK_SIZE                SZ_128K
-
 /*
  * OMAP3 Beagle revision
  * Run time detection of Beagle revision is done by reading GPIO.
@@ -106,6 +104,9 @@ static void __init omap3_beagle_init_rev(void)
        beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1)
                        | (gpio_get_value(173) << 2);
 
+       gpio_free_array(omap3_beagle_rev_gpios,
+                       ARRAY_SIZE(omap3_beagle_rev_gpios));
+
        switch (beagle_rev) {
        case 7:
                printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
@@ -579,6 +580,9 @@ static void __init omap3_beagle_init(void)
        omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
                             ARRAY_SIZE(omap3beagle_nand_partitions));
 
+       /* Ensure msecure is mux'd to be able to set the RTC. */
+       omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
+
        /* Ensure SDRC pins are mux'd for self-refresh */
        omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
        omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
index 1d10736..2a0bb48 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/leds.h>
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
@@ -41,7 +42,6 @@
 
 #include <plat/board.h>
 #include <plat/common.h>
-#include <mach/gpio.h>
 #include <mach/hardware.h>
 #include <plat/mcspi.h>
 #include <plat/usb.h>
@@ -57,8 +57,6 @@
 #define PANDORA_WIFI_NRESET_GPIO       23
 #define OMAP3_PANDORA_TS_GPIO          94
 
-#define NAND_BLOCK_SIZE                        SZ_128K
-
 static struct mtd_partition omap3pandora_nand_partitions[] = {
        {
                .name           = "xloader",
index 82872d7..5f649fa 100644 (file)
@@ -56,8 +56,6 @@
 
 #include <asm/setup.h>
 
-#define NAND_BLOCK_SIZE                SZ_128K
-
 #define OMAP3_AC_GPIO          136
 #define OMAP3_TS_GPIO          162
 #define TB_BL_PWM_TIMER                9
index 90485fc..0cfe200 100644 (file)
@@ -526,19 +526,19 @@ static struct omap_device_pad serial4_pads[] __initdata = {
                         OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
 };
 
-static struct omap_board_data serial2_data = {
+static struct omap_board_data serial2_data __initdata = {
        .id             = 1,
        .pads           = serial2_pads,
        .pads_cnt       = ARRAY_SIZE(serial2_pads),
 };
 
-static struct omap_board_data serial3_data = {
+static struct omap_board_data serial3_data __initdata = {
        .id             = 2,
        .pads           = serial3_pads,
        .pads_cnt       = ARRAY_SIZE(serial3_pads),
 };
 
-static struct omap_board_data serial4_data = {
+static struct omap_board_data serial4_data __initdata = {
        .id             = 3,
        .pads           = serial4_pads,
        .pads_cnt       = ARRAY_SIZE(serial4_pads),
@@ -687,7 +687,7 @@ static void __init omap4_panda_init(void)
 
        if (omap_rev() == OMAP4430_REV_ES1_0)
                package = OMAP_PACKAGE_CBL;
-       omap4_mux_init(board_mux, package);
+       omap4_mux_init(board_mux, NULL, package);
 
        if (wl12xx_set_platform_data(&omap_panda_wlan_data))
                pr_err("error setting wl12xx data\n");
index 1555918..175e1ab 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/i2c/twl.h>
@@ -45,7 +46,6 @@
 #include <plat/common.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
-#include <mach/gpio.h>
 #include <plat/gpmc.h>
 #include <mach/hardware.h>
 #include <plat/nand.h>
@@ -65,8 +65,6 @@
 #define OVERO_GPIO_USBH_CPEN   168
 #define OVERO_GPIO_USBH_NRESET 183
 
-#define NAND_BLOCK_SIZE SZ_128K
-
 #define OVERO_SMSC911X_CS      5
 #define OVERO_SMSC911X_GPIO    176
 #define OVERO_SMSC911X2_CS     4
index f6247e7..9903667 100644 (file)
@@ -488,6 +488,7 @@ static struct regulator_init_data rx51_vmmc2 = {
                .name                   = "V28_A",
                .min_uV                 = 2800000,
                .max_uV                 = 3000000,
+               .always_on              = true, /* due VIO leak to AIC34 VDDs */
                .apply_uV               = true,
                .valid_modes_mask       = REGULATOR_MODE_NORMAL
                                        | REGULATOR_MODE_STANDBY,
@@ -582,7 +583,7 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
 {
        /* FIXME this gpio setup is just a placeholder for now */
        gpio_request_one(gpio + 6, GPIOF_OUT_INIT_LOW, "backlight_pwm");
-       gpio_request_one(gpio + 7, GPIOF_OUT_INIT_HIGH, "speaker_en");
+       gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "speaker_en");
 
        return 0;
 }
index c7c6beb..d4683ba 100644 (file)
@@ -26,7 +26,7 @@ static struct gpio zoom_lcd_gpios[] __initdata = {
        { LCD_PANEL_QVGA_GPIO,  GPIOF_OUT_INIT_HIGH, "lcd qvga"  },
 };
 
-static void zoom_lcd_panel_init(void)
+static void __init zoom_lcd_panel_init(void)
 {
        zoom_lcd_gpios[0].gpio = (omap_rev() > OMAP3430_REV_ES3_0) ?
                        LCD_PANEL_RESET_GPIO_PROD :
index e94903b..94ccf46 100644 (file)
@@ -85,17 +85,17 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
        struct spi_board_info *spi_bi = &ads7846_spi_board_info;
        int err;
 
-       err = gpio_request(gpio_pendown, "TS PenDown");
-       if (err) {
-               pr_err("Could not obtain gpio for TS PenDown: %d\n", err);
-               return;
-       }
-
-       gpio_direction_input(gpio_pendown);
-       gpio_export(gpio_pendown, 0);
+       if (board_pdata && board_pdata->get_pendown_state) {
+               err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
+               if (err) {
+                       pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
+                       return;
+               }
+               gpio_export(gpio_pendown, 0);
 
-       if (gpio_debounce)
-               gpio_set_debounce(gpio_pendown, gpio_debounce);
+               if (gpio_debounce)
+                       gpio_set_debounce(gpio_pendown, gpio_debounce);
+       }
 
        ads7846_config.gpio_pendown = gpio_pendown;
 
index eb80b3b..6797190 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __OMAP_COMMON_BOARD_DEVICES__
 #define __OMAP_COMMON_BOARD_DEVICES__
 
+#define NAND_BLOCK_SIZE        SZ_128K
+
 struct twl4030_platform_data;
 struct mtd_partition;
 
index 7b85585..5b8ca68 100644 (file)
@@ -97,7 +97,7 @@ static int __init omap4_l3_init(void)
 
        WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
 
-       return PTR_ERR(od);
+       return IS_ERR(od) ? PTR_ERR(od) : 0;
 }
 postcore_initcall(omap4_l3_init);
 
index b2f30be..66868c5 100644 (file)
@@ -145,6 +145,7 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
                                 int power_on, int vdd)
 {
        u32 reg;
+       unsigned long timeout;
 
        if (power_on) {
                reg = omap4_ctrl_pad_readl(control_pbias_offset);
@@ -157,9 +158,15 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
                        OMAP4_MMC1_PWRDNZ_MASK |
                        OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
                omap4_ctrl_pad_writel(reg, control_pbias_offset);
-               /* 4 microsec delay for comparator to generate an error*/
-               udelay(4);
-               reg = omap4_ctrl_pad_readl(control_pbias_offset);
+
+               timeout = jiffies + msecs_to_jiffies(5);
+               do {
+                       reg = omap4_ctrl_pad_readl(control_pbias_offset);
+                       if (!(reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK))
+                               break;
+                       usleep_range(100, 200);
+               } while (!time_after(jiffies, timeout));
+
                if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK) {
                        pr_err("Pbias Voltage is not same as LDO\n");
                        /* Caution : On VMODE_ERROR Power Down MMC IO */
@@ -331,6 +338,9 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
        if (c->no_off)
                mmc->slots[0].no_off = 1;
 
+       if (c->no_off_init)
+               mmc->slots[0].no_regulator_off_init = c->no_off_init;
+
        if (c->vcc_aux_disable_is_sleep)
                mmc->slots[0].vcc_aux_disable_is_sleep = 1;
 
index f119348..f757e78 100644 (file)
@@ -18,6 +18,7 @@ struct omap2_hsmmc_info {
        bool    nonremovable;   /* Nonremovable e.g. eMMC */
        bool    power_saving;   /* Try to sleep or power off when possible */
        bool    no_off;         /* power_saving and power is not to go off */
+       bool    no_off_init;    /* no power off when not in MMC sleep state */
        bool    vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */
        int     gpio_cd;        /* or -EINVAL */
        int     gpio_wp;        /* or -EINVAL */
index a4ab1e3..c7fb22a 100644 (file)
@@ -83,6 +83,9 @@ void omap_mux_write(struct omap_mux_partition *partition, u16 val,
 void omap_mux_write_array(struct omap_mux_partition *partition,
                                 struct omap_board_mux *board_mux)
 {
+       if (!board_mux)
+               return;
+
        while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) {
                omap_mux_write(partition, board_mux->value,
                               board_mux->reg_offset);
@@ -906,7 +909,7 @@ static struct omap_mux *omap_mux_get_by_gpio(
 u16 omap_mux_get_gpio(int gpio)
 {
        struct omap_mux_partition *partition;
-       struct omap_mux *m;
+       struct omap_mux *m = NULL;
 
        list_for_each_entry(partition, &mux_partitions, node) {
                m = omap_mux_get_by_gpio(partition, gpio);
index 137f321..2132308 100644 (file)
@@ -323,10 +323,12 @@ int omap3_mux_init(struct omap_board_mux *board_mux, int flags);
 
 /**
  * omap4_mux_init() - initialize mux system with board specific set
- * @board_mux:         Board specific mux table
+ * @board_subset:      Board specific mux table
+ * @board_wkup_subset: Board specific mux table for wakeup instance
  * @flags:             OMAP package type used for the board
  */
-int omap4_mux_init(struct omap_board_mux *board_mux, int flags);
+int omap4_mux_init(struct omap_board_mux *board_subset,
+       struct omap_board_mux *board_wkup_subset, int flags);
 
 /**
  * omap_mux_init - private mux init function, do not call
index 9a66445..f5a74da 100644 (file)
@@ -1309,7 +1309,8 @@ static struct omap_ball __initdata omap4_wkup_cbl_cbs_ball[] = {
 #define omap4_wkup_cbl_cbs_ball  NULL
 #endif
 
-int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags)
+int __init omap4_mux_init(struct omap_board_mux *board_subset,
+       struct omap_board_mux *board_wkup_subset, int flags)
 {
        struct omap_ball *package_balls_core;
        struct omap_ball *package_balls_wkup = omap4_wkup_cbl_cbs_ball;
@@ -1347,7 +1348,7 @@ int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags)
                            OMAP_MUX_GPIO_IN_MODE3,
                            OMAP4_CTRL_MODULE_PAD_WKUP_MUX_PBASE,
                            OMAP4_CTRL_MODULE_PAD_WKUP_MUX_SIZE,
-                           omap4_wkup_muxmodes, NULL, board_subset,
+                           omap4_wkup_muxmodes, NULL, board_wkup_subset,
                            package_balls_wkup);
 
        return ret;
index e034294..293fa6c 100644 (file)
@@ -1628,7 +1628,7 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
                        void *data)
 {
        struct omap_hwmod *temp_oh;
-       int ret;
+       int ret = 0;
 
        if (!fn)
                return -EINVAL;
index abc548a..e1c69ff 100644 (file)
@@ -5109,7 +5109,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
        &omap44xx_iva_seq1_hwmod,
 
        /* kbd class */
-/*     &omap44xx_kbd_hwmod, */
+       &omap44xx_kbd_hwmod,
 
        /* mailbox class */
        &omap44xx_mailbox_hwmod,
index f47813e..58775e3 100644 (file)
@@ -56,8 +56,10 @@ int omap4430_phy_init(struct device *dev)
        /* Power down the phy */
        __raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
 
-       if (!dev)
+       if (!dev) {
+               iounmap(ctrl_base);
                return 0;
+       }
 
        phyclk = clk_get(dev, "ocp2scp_usb_phy_ick");
        if (IS_ERR(phyclk)) {
index c84442c..5ad8b2f 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <mach/irqs.h>
 
+#include "board-harmony.h"
+
 #define PMC_CTRL               0x0
 #define PMC_CTRL_INTR_LOW      (1 << 17)
 
@@ -98,7 +100,7 @@ static struct tps6586x_platform_data tps_platform = {
        .irq_base       = TEGRA_NR_IRQS,
        .num_subdevs    = ARRAY_SIZE(tps_devs),
        .subdevs        = tps_devs,
-       .gpio_base      = TEGRA_NR_GPIOS,
+       .gpio_base      = HARMONY_GPIO_TPS6586X(0),
 };
 
 static struct i2c_board_info __initdata harmony_regulators[] = {
index 1e57b07..d85142e 100644 (file)
@@ -17,7 +17,8 @@
 #ifndef _MACH_TEGRA_BOARD_HARMONY_H
 #define _MACH_TEGRA_BOARD_HARMONY_H
 
-#define HARMONY_GPIO_WM8903(_x_)       (TEGRA_NR_GPIOS + (_x_))
+#define HARMONY_GPIO_TPS6586X(_x_)     (TEGRA_NR_GPIOS + (_x_))
+#define HARMONY_GPIO_WM8903(_x_)       (HARMONY_GPIO_TPS6586X(4) + (_x_))
 
 #define TEGRA_GPIO_SD2_CD              TEGRA_GPIO_PI5
 #define TEGRA_GPIO_SD2_WP              TEGRA_GPIO_PH1
index 3083195..0d88499 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/mtd/map.h>
 
+struct platform_device;
 extern void omap1_set_vpp(struct platform_device *pdev, int enable);
 
 #endif
index 32a2f6c..e992b96 100644 (file)
@@ -29,9 +29,6 @@ struct iovm_struct {
  * lower 16 bit is used for h/w and upper 16 bit is for s/w.
  */
 #define IOVMF_SW_SHIFT         16
-#define IOVMF_HW_SIZE          (1 << IOVMF_SW_SHIFT)
-#define IOVMF_HW_MASK          (IOVMF_HW_SIZE - 1)
-#define IOVMF_SW_MASK          (~IOVMF_HW_MASK)UL
 
 /*
  * iovma: h/w flags derived from cam and ram attribute
index f38fef9..c7b8741 100644 (file)
@@ -101,6 +101,9 @@ struct omap_mmc_platform_data {
                /* If using power_saving and the MMC power is not to go off */
                unsigned no_off:1;
 
+               /* eMMC does not handle power off when not in sleep state */
+               unsigned no_regulator_off_init:1;
+
                /* Regulator off remapped to sleep */
                unsigned vcc_aux_disable_is_sleep:1;
 
index 51ef43e..83a37c5 100644 (file)
@@ -648,7 +648,6 @@ u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
                        return PTR_ERR(va);
        }
 
-       flags &= IOVMF_HW_MASK;
        flags |= IOVMF_DISCONT;
        flags |= IOVMF_MMIO;
 
@@ -706,7 +705,6 @@ u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
        if (!va)
                return -ENOMEM;
 
-       flags &= IOVMF_HW_MASK;
        flags |= IOVMF_DISCONT;
        flags |= IOVMF_ALLOC;
 
@@ -795,7 +793,6 @@ u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
        if (!va)
                return -ENOMEM;
 
-       flags &= IOVMF_HW_MASK;
        flags |= IOVMF_LINEAR;
        flags |= IOVMF_MMIO;
 
@@ -853,7 +850,6 @@ u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
                return -ENOMEM;
        pa = virt_to_phys(va);
 
-       flags &= IOVMF_HW_MASK;
        flags |= IOVMF_LINEAR;
        flags |= IOVMF_ALLOC;
 
index a3f50b3..6af3d0b 100644 (file)
@@ -166,7 +166,7 @@ static void __init omap_detect_sram(void)
                else if (cpu_is_omap1611())
                        omap_sram_size = SZ_256K;
                else {
-                       printk(KERN_ERR "Could not detect SRAM size\n");
+                       pr_err("Could not detect SRAM size\n");
                        omap_sram_size = 0x4000;
                }
        }
@@ -221,10 +221,10 @@ static void __init omap_map_sram(void)
        omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE);
        iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
 
-       printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
-       __pfn_to_phys(omap_sram_io_desc[0].pfn),
-       omap_sram_io_desc[0].virtual,
-              omap_sram_io_desc[0].length);
+       pr_info("SRAM: Mapped pa 0x%08llx to va 0x%08lx size: 0x%lx\n",
+               (long long) __pfn_to_phys(omap_sram_io_desc[0].pfn),
+               omap_sram_io_desc[0].virtual,
+               omap_sram_io_desc[0].length);
 
        /*
         * Normally devicemaps_init() would flush caches and tlb after
@@ -252,7 +252,7 @@ static void __init omap_map_sram(void)
 void *omap_sram_push_address(unsigned long size)
 {
        if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
-               printk(KERN_ERR "Not enough space in SRAM\n");
+               pr_err("Not enough space in SRAM\n");
                return NULL;
        }
 
index f03cb27..bd3e5e7 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/irq.h>
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/atomic.h>
 #include <asm/smp.h>
@@ -156,7 +156,7 @@ int die_if_no_fixup(const char *str, struct pt_regs *regs,
 
        case EXCEP_TRAP:
        case EXCEP_UNIMPINS:
-               if (get_user(opcode, (uint8_t __user *)regs->pc) != 0)
+               if (probe_kernel_read(&opcode, (u8 *)regs->pc, 1) < 0)
                        break;
                if (opcode == 0xff) {
                        if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0))
index 6f702a6..13c4814 100644 (file)
@@ -44,6 +44,7 @@ SECTIONS
   RO_DATA(PAGE_SIZE)
 
   /* writeable */
+  _sdata = .;     /* Start of rw data section */
   RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE)
   _edata = .;
 
index 665919f..a775ea5 100644 (file)
@@ -120,14 +120,14 @@ debugger_local_cache_flushinv_one:
        # conditionally purge this line in all ways
        mov     d1,(L1_CACHE_WAYDISP*0,a0)
 
-debugger_local_cache_flushinv_no_dcache:
+debugger_local_cache_flushinv_one_no_dcache:
        #
        # now try to flush the icache
        #
        mov     CHCTR,a0
        movhu   (a0),d0
        btst    CHCTR_ICEN,d0
-       beq     mn10300_local_icache_inv_range_reg_end
+       beq     debugger_local_cache_flushinv_one_end
 
        LOCAL_CLI_SAVE(d1)
 
index 3d80c3e..12da77e 100644 (file)
@@ -1,5 +1,4 @@
 addnote
-dtc
 empty.c
 hack-coff
 infblock.c
diff --git a/arch/powerpc/boot/dtc-src/.gitignore b/arch/powerpc/boot/dtc-src/.gitignore
deleted file mode 100644 (file)
index a7c3f94..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-dtc-lexer.lex.c
-dtc-parser.tab.c
-dtc-parser.tab.h
index d902abd..b1d2dec 100644 (file)
@@ -14,7 +14,7 @@
 #define ASM_PPC_RIO_H
 
 extern void platform_rio_init(void);
-#ifdef CONFIG_RAPIDIO
+#ifdef CONFIG_FSL_RIO
 extern int fsl_rio_mcheck_exception(struct pt_regs *);
 #else
 static inline int fsl_rio_mcheck_exception(struct pt_regs *regs) {return 0; }
index 34d2722..9fb9332 100644 (file)
@@ -1979,7 +1979,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .pvr_value              = 0x80240000,
                .cpu_name               = "e5500",
                .cpu_features           = CPU_FTRS_E5500,
-               .cpu_user_features      = COMMON_USER_BOOKE,
+               .cpu_user_features      = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
                .mmu_features           = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
                        MMU_FTR_USE_TLBILX,
                .icache_bsize           = 64,
index f2c906b..8c3112a 100644 (file)
@@ -82,11 +82,29 @@ static int __init early_parse_mem(char *p)
 }
 early_param("mem", early_parse_mem);
 
+/*
+ * overlaps_initrd - check for overlap with page aligned extension of
+ * initrd.
+ */
+static inline int overlaps_initrd(unsigned long start, unsigned long size)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (!initrd_start)
+               return 0;
+
+       return  (start + size) > _ALIGN_DOWN(initrd_start, PAGE_SIZE) &&
+                       start <= _ALIGN_UP(initrd_end, PAGE_SIZE);
+#else
+       return 0;
+#endif
+}
+
 /**
  * move_device_tree - move tree to an unused area, if needed.
  *
  * The device tree may be allocated beyond our memory limit, or inside the
- * crash kernel region for kdump. If so, move it out of the way.
+ * crash kernel region for kdump, or within the page aligned range of initrd.
+ * If so, move it out of the way.
  */
 static void __init move_device_tree(void)
 {
@@ -99,7 +117,8 @@ static void __init move_device_tree(void)
        size = be32_to_cpu(initial_boot_params->totalsize);
 
        if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) ||
-                       overlaps_crashkernel(start, size)) {
+                       overlaps_crashkernel(start, size) ||
+                       overlaps_initrd(start, size)) {
                p = __va(memblock_alloc(size, PAGE_SIZE));
                memcpy(p, initial_boot_params, size);
                initial_boot_params = (struct boot_param_header *)p;
@@ -555,7 +574,9 @@ static void __init early_reserve_mem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
        /* then reserve the initrd, if any */
        if (initrd_start && (initrd_end > initrd_start))
-               memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+               memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE),
+                       _ALIGN_UP(initrd_end, PAGE_SIZE) -
+                       _ALIGN_DOWN(initrd_start, PAGE_SIZE));
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 #ifdef CONFIG_PPC32
index d65b591..5de0f25 100644 (file)
@@ -223,21 +223,6 @@ void free_initmem(void)
 #undef FREESEC
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       if (start < end)
-               printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
-       for (; start < end; start += PAGE_SIZE) {
-               ClearPageReserved(virt_to_page(start));
-               init_page_count(virt_to_page(start));
-               free_page(start);
-               totalram_pages++;
-       }
-}
-#endif
-
-
 #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
                                phys_addr_t first_memblock_size)
index 6374b21..f6dbb4c 100644 (file)
@@ -99,20 +99,6 @@ void free_initmem(void)
                ((unsigned long)__init_end - (unsigned long)__init_begin) >> 10);
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       if (start < end)
-               printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
-       for (; start < end; start += PAGE_SIZE) {
-               ClearPageReserved(virt_to_page(start));
-               init_page_count(virt_to_page(start));
-               free_page(start);
-               totalram_pages++;
-       }
-}
-#endif
-
 static void pgd_ctor(void *addr)
 {
        memset(addr, 0, PGD_TABLE_SIZE);
index 57e545b..29d4dde 100644 (file)
@@ -382,6 +382,25 @@ void __init mem_init(void)
        mem_init_done = 1;
 }
 
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init free_initrd_mem(unsigned long start, unsigned long end)
+{
+       if (start >= end)
+               return;
+
+       start = _ALIGN_DOWN(start, PAGE_SIZE);
+       end = _ALIGN_UP(end, PAGE_SIZE);
+       pr_info("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+
+       for (; start < end; start += PAGE_SIZE) {
+               ClearPageReserved(virt_to_page(start));
+               init_page_count(virt_to_page(start));
+               free_page(start);
+               totalram_pages++;
+       }
+}
+#endif
+
 /*
  * This is called when a page has been modified by the kernel.
  * It just marks the page as not i-cache clean.  We do the i-cache
index 0608b16..d917573 100644 (file)
@@ -196,9 +196,6 @@ static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl,
        out_be32(&lbc->lteccr, LTECCR_CLEAR);
        out_be32(&lbc->ltedr, LTEDR_ENABLE);
 
-       /* Enable interrupts for any detected events */
-       out_be32(&lbc->lteir, LTEIR_ENABLE);
-
        /* Set the monitor timeout value to the maximum for erratum A001 */
        if (of_device_is_compatible(node, "fsl,elbc"))
                clrsetbits_be32(&lbc->lbcr, LBCR_BMT, LBCR_BMTPS);
@@ -322,6 +319,9 @@ static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
                goto err;
        }
 
+       /* Enable interrupts for any detected events */
+       out_be32(&fsl_lbc_ctrl_dev->regs->lteir, LTEIR_ENABLE);
+
        return 0;
 
 err:
index 9fab2aa..90d77bd 100644 (file)
@@ -89,6 +89,7 @@ config S390
        select HAVE_GET_USER_PAGES_FAST
        select HAVE_ARCH_MUTEX_CPU_RELAX
        select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
+       select HAVE_RCU_TABLE_FREE if SMP
        select ARCH_INLINE_SPIN_TRYLOCK
        select ARCH_INLINE_SPIN_TRYLOCK_BH
        select ARCH_INLINE_SPIN_LOCK
index f6314af..38e71eb 100644 (file)
 #include <linux/gfp.h>
 #include <linux/mm.h>
 
-#define check_pgt_cache()      do {} while (0)
-
 unsigned long *crst_table_alloc(struct mm_struct *);
 void crst_table_free(struct mm_struct *, unsigned long *);
-void crst_table_free_rcu(struct mm_struct *, unsigned long *);
 
 unsigned long *page_table_alloc(struct mm_struct *);
 void page_table_free(struct mm_struct *, unsigned long *);
-void page_table_free_rcu(struct mm_struct *, unsigned long *);
+#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+void page_table_free_rcu(struct mmu_gather *, unsigned long *);
+void __tlb_remove_table(void *_table);
+#endif
 
 static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
 {
index e4efacf..801fbe1 100644 (file)
@@ -293,19 +293,6 @@ extern unsigned long VMALLOC_START;
  * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid.
  */
 
-/* Page status table bits for virtualization */
-#define RCP_ACC_BITS   0xf000000000000000UL
-#define RCP_FP_BIT     0x0800000000000000UL
-#define RCP_PCL_BIT    0x0080000000000000UL
-#define RCP_HR_BIT     0x0040000000000000UL
-#define RCP_HC_BIT     0x0020000000000000UL
-#define RCP_GR_BIT     0x0004000000000000UL
-#define RCP_GC_BIT     0x0002000000000000UL
-
-/* User dirty / referenced bit for KVM's migration feature */
-#define KVM_UR_BIT     0x0000800000000000UL
-#define KVM_UC_BIT     0x0000400000000000UL
-
 #ifndef __s390x__
 
 /* Bits in the segment table address-space-control-element */
@@ -325,6 +312,19 @@ extern unsigned long VMALLOC_START;
 #define _SEGMENT_ENTRY         (_SEGMENT_ENTRY_PTL)
 #define _SEGMENT_ENTRY_EMPTY   (_SEGMENT_ENTRY_INV)
 
+/* Page status table bits for virtualization */
+#define RCP_ACC_BITS   0xf0000000UL
+#define RCP_FP_BIT     0x08000000UL
+#define RCP_PCL_BIT    0x00800000UL
+#define RCP_HR_BIT     0x00400000UL
+#define RCP_HC_BIT     0x00200000UL
+#define RCP_GR_BIT     0x00040000UL
+#define RCP_GC_BIT     0x00020000UL
+
+/* User dirty / referenced bit for KVM's migration feature */
+#define KVM_UR_BIT     0x00008000UL
+#define KVM_UC_BIT     0x00004000UL
+
 #else /* __s390x__ */
 
 /* Bits in the segment/region table address-space-control-element */
@@ -367,6 +367,19 @@ extern unsigned long VMALLOC_START;
 #define _SEGMENT_ENTRY_LARGE   0x400   /* STE-format control, large page   */
 #define _SEGMENT_ENTRY_CO      0x100   /* change-recording override   */
 
+/* Page status table bits for virtualization */
+#define RCP_ACC_BITS   0xf000000000000000UL
+#define RCP_FP_BIT     0x0800000000000000UL
+#define RCP_PCL_BIT    0x0080000000000000UL
+#define RCP_HR_BIT     0x0040000000000000UL
+#define RCP_HC_BIT     0x0020000000000000UL
+#define RCP_GR_BIT     0x0004000000000000UL
+#define RCP_GC_BIT     0x0002000000000000UL
+
+/* User dirty / referenced bit for KVM's migration feature */
+#define KVM_UR_BIT     0x0000800000000000UL
+#define KVM_UC_BIT     0x0000400000000000UL
+
 #endif /* __s390x__ */
 
 /*
index 350e7ee..15c9762 100644 (file)
@@ -139,110 +139,47 @@ struct slib {
        struct slibe slibe[QDIO_MAX_BUFFERS_PER_Q];
 } __attribute__ ((packed, aligned(2048)));
 
-/**
- * struct sbal_flags - storage block address list flags
- * @last: last entry
- * @cont: contiguous storage
- * @frag: fragmentation
- */
-struct sbal_flags {
-       u8      : 1;
-       u8 last : 1;
-       u8 cont : 1;
-       u8      : 1;
-       u8 frag : 2;
-       u8      : 2;
-} __attribute__ ((packed));
-
-#define SBAL_FLAGS_FIRST_FRAG          0x04000000UL
-#define SBAL_FLAGS_MIDDLE_FRAG         0x08000000UL
-#define SBAL_FLAGS_LAST_FRAG           0x0c000000UL
-#define SBAL_FLAGS_LAST_ENTRY          0x40000000UL
-#define SBAL_FLAGS_CONTIGUOUS          0x20000000UL
+#define SBAL_EFLAGS_LAST_ENTRY         0x40
+#define SBAL_EFLAGS_CONTIGUOUS         0x20
+#define SBAL_EFLAGS_FIRST_FRAG         0x04
+#define SBAL_EFLAGS_MIDDLE_FRAG                0x08
+#define SBAL_EFLAGS_LAST_FRAG          0x0c
+#define SBAL_EFLAGS_MASK               0x6f
 
-#define SBAL_FLAGS0_DATA_CONTINUATION  0x20UL
+#define SBAL_SFLAGS0_PCI_REQ           0x40
+#define SBAL_SFLAGS0_DATA_CONTINUATION 0x20
 
 /* Awesome OpenFCP extensions */
-#define SBAL_FLAGS0_TYPE_STATUS                0x00UL
-#define SBAL_FLAGS0_TYPE_WRITE         0x08UL
-#define SBAL_FLAGS0_TYPE_READ          0x10UL
-#define SBAL_FLAGS0_TYPE_WRITE_READ    0x18UL
-#define SBAL_FLAGS0_MORE_SBALS         0x04UL
-#define SBAL_FLAGS0_COMMAND            0x02UL
-#define SBAL_FLAGS0_LAST_SBAL          0x00UL
-#define SBAL_FLAGS0_ONLY_SBAL          SBAL_FLAGS0_COMMAND
-#define SBAL_FLAGS0_MIDDLE_SBAL                SBAL_FLAGS0_MORE_SBALS
-#define SBAL_FLAGS0_FIRST_SBAL SBAL_FLAGS0_MORE_SBALS | SBAL_FLAGS0_COMMAND
-#define SBAL_FLAGS0_PCI                        0x40
-
-/**
- * struct sbal_sbalf_0 - sbal flags for sbale 0
- * @pci: PCI indicator
- * @cont: data continuation
- * @sbtype: storage-block type (FCP)
- */
-struct sbal_sbalf_0 {
-       u8        : 1;
-       u8 pci    : 1;
-       u8 cont   : 1;
-       u8 sbtype : 2;
-       u8        : 3;
-} __attribute__ ((packed));
-
-/**
- * struct sbal_sbalf_1 - sbal flags for sbale 1
- * @key: storage key
- */
-struct sbal_sbalf_1 {
-       u8     : 4;
-       u8 key : 4;
-} __attribute__ ((packed));
-
-/**
- * struct sbal_sbalf_14 - sbal flags for sbale 14
- * @erridx: error index
- */
-struct sbal_sbalf_14 {
-       u8        : 4;
-       u8 erridx : 4;
-} __attribute__ ((packed));
-
-/**
- * struct sbal_sbalf_15 - sbal flags for sbale 15
- * @reason: reason for error state
- */
-struct sbal_sbalf_15 {
-       u8 reason;
-} __attribute__ ((packed));
-
-/**
- * union sbal_sbalf - storage block address list flags
- * @i0: sbalf0
- * @i1: sbalf1
- * @i14: sbalf14
- * @i15: sblaf15
- * @value: raw value
- */
-union sbal_sbalf {
-       struct sbal_sbalf_0  i0;
-       struct sbal_sbalf_1  i1;
-       struct sbal_sbalf_14 i14;
-       struct sbal_sbalf_15 i15;
-       u8 value;
-};
+#define SBAL_SFLAGS0_TYPE_STATUS       0x00
+#define SBAL_SFLAGS0_TYPE_WRITE                0x08
+#define SBAL_SFLAGS0_TYPE_READ         0x10
+#define SBAL_SFLAGS0_TYPE_WRITE_READ   0x18
+#define SBAL_SFLAGS0_MORE_SBALS                0x04
+#define SBAL_SFLAGS0_COMMAND           0x02
+#define SBAL_SFLAGS0_LAST_SBAL         0x00
+#define SBAL_SFLAGS0_ONLY_SBAL         SBAL_SFLAGS0_COMMAND
+#define SBAL_SFLAGS0_MIDDLE_SBAL       SBAL_SFLAGS0_MORE_SBALS
+#define SBAL_SFLAGS0_FIRST_SBAL (SBAL_SFLAGS0_MORE_SBALS | SBAL_SFLAGS0_COMMAND)
 
 /**
  * struct qdio_buffer_element - SBAL entry
- * @flags: flags
+ * @eflags: SBAL entry flags
+ * @scount: SBAL count
+ * @sflags: whole SBAL flags
  * @length: length
  * @addr: address
 */
 struct qdio_buffer_element {
-       u32 flags;
+       u8 eflags;
+       /* private: */
+       u8 res1;
+       /* public: */
+       u8 scount;
+       u8 sflags;
        u32 length;
 #ifdef CONFIG_32BIT
        /* private: */
-       void *reserved;
+       void *res2;
        /* public: */
 #endif
        void *addr;
index 77eee54..c687a2c 100644 (file)
 #include <linux/swap.h>
 #include <asm/processor.h>
 #include <asm/pgalloc.h>
-#include <asm/smp.h>
 #include <asm/tlbflush.h>
 
 struct mmu_gather {
        struct mm_struct *mm;
+#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+       struct mmu_table_batch *batch;
+#endif
        unsigned int fullmm;
-       unsigned int nr_ptes;
-       unsigned int nr_pxds;
-       unsigned int max;
-       void **array;
-       void *local[8];
+       unsigned int need_flush;
 };
 
-static inline void __tlb_alloc_page(struct mmu_gather *tlb)
-{
-       unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);
+#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+struct mmu_table_batch {
+       struct rcu_head         rcu;
+       unsigned int            nr;
+       void                    *tables[0];
+};
 
-       if (addr) {
-               tlb->array = (void *) addr;
-               tlb->max = PAGE_SIZE / sizeof(void *);
-       }
-}
+#define MAX_TABLE_BATCH                \
+       ((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *))
+
+extern void tlb_table_flush(struct mmu_gather *tlb);
+extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
+#endif
 
 static inline void tlb_gather_mmu(struct mmu_gather *tlb,
                                  struct mm_struct *mm,
                                  unsigned int full_mm_flush)
 {
        tlb->mm = mm;
-       tlb->max = ARRAY_SIZE(tlb->local);
-       tlb->array = tlb->local;
        tlb->fullmm = full_mm_flush;
+       tlb->need_flush = 0;
+#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+       tlb->batch = NULL;
+#endif
        if (tlb->fullmm)
                __tlb_flush_mm(mm);
-       else
-               __tlb_alloc_page(tlb);
-       tlb->nr_ptes = 0;
-       tlb->nr_pxds = tlb->max;
 }
 
 static inline void tlb_flush_mmu(struct mmu_gather *tlb)
 {
-       if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pxds < tlb->max))
-               __tlb_flush_mm(tlb->mm);
-       while (tlb->nr_ptes > 0)
-               page_table_free_rcu(tlb->mm, tlb->array[--tlb->nr_ptes]);
-       while (tlb->nr_pxds < tlb->max)
-               crst_table_free_rcu(tlb->mm, tlb->array[tlb->nr_pxds++]);
+       if (!tlb->need_flush)
+               return;
+       tlb->need_flush = 0;
+       __tlb_flush_mm(tlb->mm);
+#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+       tlb_table_flush(tlb);
+#endif
 }
 
 static inline void tlb_finish_mmu(struct mmu_gather *tlb,
                                  unsigned long start, unsigned long end)
 {
        tlb_flush_mmu(tlb);
-
-       rcu_table_freelist_finish();
-
-       /* keep the page table cache within bounds */
-       check_pgt_cache();
-
-       if (tlb->array != tlb->local)
-               free_pages((unsigned long) tlb->array, 0);
 }
 
 /*
@@ -112,12 +105,11 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
                                unsigned long address)
 {
-       if (!tlb->fullmm) {
-               tlb->array[tlb->nr_ptes++] = pte;
-               if (tlb->nr_ptes >= tlb->nr_pxds)
-                       tlb_flush_mmu(tlb);
-       } else
-               page_table_free(tlb->mm, (unsigned long *) pte);
+#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+       if (!tlb->fullmm)
+               return page_table_free_rcu(tlb, (unsigned long *) pte);
+#endif
+       page_table_free(tlb->mm, (unsigned long *) pte);
 }
 
 /*
@@ -133,12 +125,11 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
 #ifdef __s390x__
        if (tlb->mm->context.asce_limit <= (1UL << 31))
                return;
-       if (!tlb->fullmm) {
-               tlb->array[--tlb->nr_pxds] = pmd;
-               if (tlb->nr_ptes >= tlb->nr_pxds)
-                       tlb_flush_mmu(tlb);
-       } else
-               crst_table_free(tlb->mm, (unsigned long *) pmd);
+#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+       if (!tlb->fullmm)
+               return tlb_remove_table(tlb, pmd);
+#endif
+       crst_table_free(tlb->mm, (unsigned long *) pmd);
 #endif
 }
 
@@ -155,12 +146,11 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
 #ifdef __s390x__
        if (tlb->mm->context.asce_limit <= (1UL << 42))
                return;
-       if (!tlb->fullmm) {
-               tlb->array[--tlb->nr_pxds] = pud;
-               if (tlb->nr_ptes >= tlb->nr_pxds)
-                       tlb_flush_mmu(tlb);
-       } else
-               crst_table_free(tlb->mm, (unsigned long *) pud);
+#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+       if (!tlb->fullmm)
+               return tlb_remove_table(tlb, pud);
+#endif
+       crst_table_free(tlb->mm, (unsigned long *) pud);
 #endif
 }
 
index 30ca85c..67345ae 100644 (file)
@@ -731,6 +731,7 @@ static int __init kvm_s390_init(void)
        }
        memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
        facilities[0] &= 0xff00fff3f47c0000ULL;
+       facilities[1] &= 0x201c000000000000ULL;
        return 0;
 }
 
index ab0e041..5faa1b1 100644 (file)
@@ -93,4 +93,6 @@ sie_err:
 
        .section __ex_table,"a"
        .quad   sie_inst,sie_err
+       .quad   sie_exit,sie_err
+       .quad   sie_reenter,sie_err
        .previous
index b09763f..37a23c2 100644 (file)
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 
-struct rcu_table_freelist {
-       struct rcu_head rcu;
-       struct mm_struct *mm;
-       unsigned int pgt_index;
-       unsigned int crst_index;
-       unsigned long *table[0];
-};
-
-#define RCU_FREELIST_SIZE \
-       ((PAGE_SIZE - sizeof(struct rcu_table_freelist)) \
-         / sizeof(unsigned long))
-
-static DEFINE_PER_CPU(struct rcu_table_freelist *, rcu_table_freelist);
-
-static void __page_table_free(struct mm_struct *mm, unsigned long *table);
-
-static struct rcu_table_freelist *rcu_table_freelist_get(struct mm_struct *mm)
-{
-       struct rcu_table_freelist **batchp = &__get_cpu_var(rcu_table_freelist);
-       struct rcu_table_freelist *batch = *batchp;
-
-       if (batch)
-               return batch;
-       batch = (struct rcu_table_freelist *) __get_free_page(GFP_ATOMIC);
-       if (batch) {
-               batch->mm = mm;
-               batch->pgt_index = 0;
-               batch->crst_index = RCU_FREELIST_SIZE;
-               *batchp = batch;
-       }
-       return batch;
-}
-
-static void rcu_table_freelist_callback(struct rcu_head *head)
-{
-       struct rcu_table_freelist *batch =
-               container_of(head, struct rcu_table_freelist, rcu);
-
-       while (batch->pgt_index > 0)
-               __page_table_free(batch->mm, batch->table[--batch->pgt_index]);
-       while (batch->crst_index < RCU_FREELIST_SIZE)
-               crst_table_free(batch->mm, batch->table[batch->crst_index++]);
-       free_page((unsigned long) batch);
-}
-
-void rcu_table_freelist_finish(void)
-{
-       struct rcu_table_freelist **batchp = &get_cpu_var(rcu_table_freelist);
-       struct rcu_table_freelist *batch = *batchp;
-
-       if (!batch)
-               goto out;
-       call_rcu(&batch->rcu, rcu_table_freelist_callback);
-       *batchp = NULL;
-out:
-       put_cpu_var(rcu_table_freelist);
-}
-
-static void smp_sync(void *arg)
-{
-}
-
 #ifndef CONFIG_64BIT
 #define ALLOC_ORDER    1
-#define TABLES_PER_PAGE        4
-#define FRAG_MASK      15UL
-#define SECOND_HALVES  10UL
-
-void clear_table_pgstes(unsigned long *table)
-{
-       clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/4);
-       memset(table + 256, 0, PAGE_SIZE/4);
-       clear_table(table + 512, _PAGE_TYPE_EMPTY, PAGE_SIZE/4);
-       memset(table + 768, 0, PAGE_SIZE/4);
-}
-
+#define FRAG_MASK      0x0f
 #else
 #define ALLOC_ORDER    2
-#define TABLES_PER_PAGE        2
-#define FRAG_MASK      3UL
-#define SECOND_HALVES  2UL
-
-void clear_table_pgstes(unsigned long *table)
-{
-       clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2);
-       memset(table + 256, 0, PAGE_SIZE/2);
-}
-
+#define FRAG_MASK      0x03
 #endif
 
 unsigned long VMALLOC_START = VMALLOC_END - VMALLOC_SIZE;
@@ -140,29 +58,6 @@ void crst_table_free(struct mm_struct *mm, unsigned long *table)
        free_pages((unsigned long) table, ALLOC_ORDER);
 }
 
-void crst_table_free_rcu(struct mm_struct *mm, unsigned long *table)
-{
-       struct rcu_table_freelist *batch;
-
-       preempt_disable();
-       if (atomic_read(&mm->mm_users) < 2 &&
-           cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
-               crst_table_free(mm, table);
-               goto out;
-       }
-       batch = rcu_table_freelist_get(mm);
-       if (!batch) {
-               smp_call_function(smp_sync, NULL, 1);
-               crst_table_free(mm, table);
-               goto out;
-       }
-       batch->table[--batch->crst_index] = table;
-       if (batch->pgt_index >= batch->crst_index)
-               rcu_table_freelist_finish();
-out:
-       preempt_enable();
-}
-
 #ifdef CONFIG_64BIT
 int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
 {
@@ -238,124 +133,175 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
 }
 #endif
 
+static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
+{
+       unsigned int old, new;
+
+       do {
+               old = atomic_read(v);
+               new = old ^ bits;
+       } while (atomic_cmpxchg(v, old, new) != old);
+       return new;
+}
+
 /*
  * page table entry allocation/free routines.
  */
+#ifdef CONFIG_PGSTE
+static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm)
+{
+       struct page *page;
+       unsigned long *table;
+
+       page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
+       if (!page)
+               return NULL;
+       pgtable_page_ctor(page);
+       atomic_set(&page->_mapcount, 3);
+       table = (unsigned long *) page_to_phys(page);
+       clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2);
+       clear_table(table + PTRS_PER_PTE, 0, PAGE_SIZE/2);
+       return table;
+}
+
+static inline void page_table_free_pgste(unsigned long *table)
+{
+       struct page *page;
+
+       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+       pgtable_page_ctor(page);
+       atomic_set(&page->_mapcount, -1);
+       __free_page(page);
+}
+#endif
+
 unsigned long *page_table_alloc(struct mm_struct *mm)
 {
        struct page *page;
        unsigned long *table;
-       unsigned long bits;
+       unsigned int mask, bit;
 
-       bits = (mm->context.has_pgste) ? 3UL : 1UL;
+#ifdef CONFIG_PGSTE
+       if (mm_has_pgste(mm))
+               return page_table_alloc_pgste(mm);
+#endif
+       /* Allocate fragments of a 4K page as 1K/2K page table */
        spin_lock_bh(&mm->context.list_lock);
-       page = NULL;
+       mask = FRAG_MASK;
        if (!list_empty(&mm->context.pgtable_list)) {
                page = list_first_entry(&mm->context.pgtable_list,
                                        struct page, lru);
-               if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1))
-                       page = NULL;
+               table = (unsigned long *) page_to_phys(page);
+               mask = atomic_read(&page->_mapcount);
+               mask = mask | (mask >> 4);
        }
-       if (!page) {
+       if ((mask & FRAG_MASK) == FRAG_MASK) {
                spin_unlock_bh(&mm->context.list_lock);
                page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
                if (!page)
                        return NULL;
                pgtable_page_ctor(page);
-               page->flags &= ~FRAG_MASK;
+               atomic_set(&page->_mapcount, 1);
                table = (unsigned long *) page_to_phys(page);
-               if (mm->context.has_pgste)
-                       clear_table_pgstes(table);
-               else
-                       clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
+               clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
                spin_lock_bh(&mm->context.list_lock);
                list_add(&page->lru, &mm->context.pgtable_list);
+       } else {
+               for (bit = 1; mask & bit; bit <<= 1)
+                       table += PTRS_PER_PTE;
+               mask = atomic_xor_bits(&page->_mapcount, bit);
+               if ((mask & FRAG_MASK) == FRAG_MASK)
+                       list_del(&page->lru);
        }
-       table = (unsigned long *) page_to_phys(page);
-       while (page->flags & bits) {
-               table += 256;
-               bits <<= 1;
-       }
-       page->flags |= bits;
-       if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1))
-               list_move_tail(&page->lru, &mm->context.pgtable_list);
        spin_unlock_bh(&mm->context.list_lock);
        return table;
 }
 
-static void __page_table_free(struct mm_struct *mm, unsigned long *table)
+void page_table_free(struct mm_struct *mm, unsigned long *table)
 {
        struct page *page;
-       unsigned long bits;
+       unsigned int bit, mask;
 
-       bits = ((unsigned long) table) & 15;
-       table = (unsigned long *)(((unsigned long) table) ^ bits);
+#ifdef CONFIG_PGSTE
+       if (mm_has_pgste(mm))
+               return page_table_free_pgste(table);
+#endif
+       /* Free 1K/2K page table fragment of a 4K page */
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-       page->flags ^= bits;
-       if (!(page->flags & FRAG_MASK)) {
+       bit = 1 << ((__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t)));
+       spin_lock_bh(&mm->context.list_lock);
+       if ((atomic_read(&page->_mapcount) & FRAG_MASK) != FRAG_MASK)
+               list_del(&page->lru);
+       mask = atomic_xor_bits(&page->_mapcount, bit);
+       if (mask & FRAG_MASK)
+               list_add(&page->lru, &mm->context.pgtable_list);
+       spin_unlock_bh(&mm->context.list_lock);
+       if (mask == 0) {
                pgtable_page_dtor(page);
+               atomic_set(&page->_mapcount, -1);
                __free_page(page);
        }
 }
 
-void page_table_free(struct mm_struct *mm, unsigned long *table)
+#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+
+static void __page_table_free_rcu(void *table, unsigned bit)
 {
        struct page *page;
-       unsigned long bits;
 
-       bits = (mm->context.has_pgste) ? 3UL : 1UL;
-       bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
+#ifdef CONFIG_PGSTE
+       if (bit == FRAG_MASK)
+               return page_table_free_pgste(table);
+#endif
+       /* Free 1K/2K page table fragment of a 4K page */
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-       spin_lock_bh(&mm->context.list_lock);
-       page->flags ^= bits;
-       if (page->flags & FRAG_MASK) {
-               /* Page now has some free pgtable fragments. */
-               if (!list_empty(&page->lru))
-                       list_move(&page->lru, &mm->context.pgtable_list);
-               page = NULL;
-       } else
-               /* All fragments of the 4K page have been freed. */
-               list_del(&page->lru);
-       spin_unlock_bh(&mm->context.list_lock);
-       if (page) {
+       if (atomic_xor_bits(&page->_mapcount, bit) == 0) {
                pgtable_page_dtor(page);
+               atomic_set(&page->_mapcount, -1);
                __free_page(page);
        }
 }
 
-void page_table_free_rcu(struct mm_struct *mm, unsigned long *table)
+void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table)
 {
-       struct rcu_table_freelist *batch;
+       struct mm_struct *mm;
        struct page *page;
-       unsigned long bits;
+       unsigned int bit, mask;
 
-       preempt_disable();
-       if (atomic_read(&mm->mm_users) < 2 &&
-           cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
-               page_table_free(mm, table);
-               goto out;
-       }
-       batch = rcu_table_freelist_get(mm);
-       if (!batch) {
-               smp_call_function(smp_sync, NULL, 1);
-               page_table_free(mm, table);
-               goto out;
+       mm = tlb->mm;
+#ifdef CONFIG_PGSTE
+       if (mm_has_pgste(mm)) {
+               table = (unsigned long *) (__pa(table) | FRAG_MASK);
+               tlb_remove_table(tlb, table);
+               return;
        }
-       bits = (mm->context.has_pgste) ? 3UL : 1UL;
-       bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
+#endif
+       bit = 1 << ((__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t)));
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
        spin_lock_bh(&mm->context.list_lock);
-       /* Delayed freeing with rcu prevents reuse of pgtable fragments */
-       list_del_init(&page->lru);
+       if ((atomic_read(&page->_mapcount) & FRAG_MASK) != FRAG_MASK)
+               list_del(&page->lru);
+       mask = atomic_xor_bits(&page->_mapcount, bit | (bit << 4));
+       if (mask & FRAG_MASK)
+               list_add_tail(&page->lru, &mm->context.pgtable_list);
        spin_unlock_bh(&mm->context.list_lock);
-       table = (unsigned long *)(((unsigned long) table) | bits);
-       batch->table[batch->pgt_index++] = table;
-       if (batch->pgt_index >= batch->crst_index)
-               rcu_table_freelist_finish();
-out:
-       preempt_enable();
+       table = (unsigned long *) (__pa(table) | (bit << 4));
+       tlb_remove_table(tlb, table);
 }
 
+void __tlb_remove_table(void *_table)
+{
+       void *table = (void *)((unsigned long) _table & PAGE_MASK);
+       unsigned type = (unsigned long) _table & ~PAGE_MASK;
+
+       if (type)
+               __page_table_free_rcu(table, type);
+       else
+               free_pages((unsigned long) table, ALLOC_ORDER);
+}
+
+#endif
+
 /*
  * switch on pgstes for its userspace process (for kvm)
  */
@@ -369,7 +315,7 @@ int s390_enable_sie(void)
                return -EINVAL;
 
        /* Do we have pgstes? if yes, we are done */
-       if (tsk->mm->context.has_pgste)
+       if (mm_has_pgste(tsk->mm))
                return 0;
 
        /* lets check if we are allowed to replace the mm */
index af32e17..253986b 100644 (file)
@@ -26,7 +26,6 @@ config SPARC
        select HAVE_DMA_API_DEBUG
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_GENERIC_HARDIRQS
-       select GENERIC_HARDIRQS_NO_DEPRECATED
        select GENERIC_IRQ_SHOW
        select USE_GENERIC_SMP_HELPERS if SMP
 
@@ -528,6 +527,23 @@ config PCI_DOMAINS
 config PCI_SYSCALL
        def_bool PCI
 
+config PCIC_PCI
+       bool
+       depends on PCI && SPARC32 && !SPARC_LEON
+       default y
+
+config LEON_PCI
+       bool
+       depends on PCI && SPARC_LEON
+       default y
+
+config GRPCI2
+       bool "GRPCI2 Host Bridge Support"
+       depends on LEON_PCI
+       default y
+       help
+         Say Y here to include the GRPCI2 Host Bridge Driver.
+
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
index 482c79e..7440915 100644 (file)
@@ -138,7 +138,7 @@ static unsigned char sun_82072_fd_inb(int port)
                return sun_fdc->data_82072;
        case 7: /* FD_DIR */
                return sun_read_dir();
-       };
+       }
        panic("sun_82072_fd_inb: How did I get here?");
 }
 
@@ -161,7 +161,7 @@ static void sun_82072_fd_outb(unsigned char value, int port)
        case 4: /* FD_STATUS */
                sun_fdc->status_82072 = value;
                break;
-       };
+       }
        return;
 }
 
@@ -186,7 +186,7 @@ static unsigned char sun_82077_fd_inb(int port)
                return sun_fdc->data_82077;
        case 7: /* FD_DIR */
                return sun_read_dir();
-       };
+       }
        panic("sun_82077_fd_inb: How did I get here?");
 }
 
@@ -212,7 +212,7 @@ static void sun_82077_fd_outb(unsigned char value, int port)
        case 3: /* FD_TDR */
                sun_fdc->tapectl_82077 = value;
                break;
-       };
+       }
        return;
 }
 
index 6597ce8..bcef1f5 100644 (file)
@@ -111,7 +111,7 @@ static unsigned char sun_82077_fd_inb(unsigned long port)
        case 7: /* FD_DIR */
                /* XXX: Is DCL on 0x80 in sun4m? */
                return sbus_readb(&sun_fdc->dir_82077);
-       };
+       }
        panic("sun_82072_fd_inb: How did I get here?");
 }
 
@@ -135,7 +135,7 @@ static void sun_82077_fd_outb(unsigned char value, unsigned long port)
        case 4: /* FD_STATUS */
                sbus_writeb(value, &sun_fdc->status_82077);
                break;
-       };
+       }
        return;
 }
 
index 6bdaf1e..a4e457f 100644 (file)
@@ -318,6 +318,9 @@ struct device_node;
 extern unsigned int leon_build_device_irq(unsigned int real_irq,
                                           irq_flow_handler_t flow_handler,
                                           const char *name, int do_ack);
+extern void leon_update_virq_handling(unsigned int virq,
+                             irq_flow_handler_t flow_handler,
+                             const char *name, int do_ack);
 extern void leon_clear_clock_irq(void);
 extern void leon_load_profile_irq(int cpu, unsigned int limit);
 extern void leon_init_timers(irq_handler_t counter_fn);
diff --git a/arch/sparc/include/asm/leon_pci.h b/arch/sparc/include/asm/leon_pci.h
new file mode 100644 (file)
index 0000000..42b4b31
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * asm/leon_pci.h
+ *
+ * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom
+ */
+
+#ifndef _ASM_LEON_PCI_H_
+#define _ASM_LEON_PCI_H_
+
+/* PCI related definitions */
+struct leon_pci_info {
+       struct pci_ops *ops;
+       struct resource io_space;
+       struct resource mem_space;
+       int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
+};
+
+extern void leon_pci_init(struct platform_device *ofdev,
+                               struct leon_pci_info *info);
+
+#endif /* _ASM_LEON_PCI_H_ */
index 332ac9a..862e3ce 100644 (file)
@@ -47,7 +47,31 @@ extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
 
 #endif /* __KERNEL__ */
 
+#ifndef CONFIG_LEON_PCI
 /* generic pci stuff */
 #include <asm-generic/pci.h>
+#else
+/*
+ * On LEON PCI Memory space is mapped 1:1 with physical address space.
+ *
+ * I/O space is located at low 64Kbytes in PCI I/O space. The I/O addresses
+ * are converted into CPU addresses to virtual addresses that are mapped with
+ * MMU to the PCI Host PCI I/O space window which are translated to the low
+ * 64Kbytes by the Host controller.
+ */
+
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+                       struct resource *res);
+
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                       struct pci_bus_region *region);
+
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+       return PCI_IRQ_NONE;
+}
+#endif
 
 #endif /* __SPARC_PCI_H */
index 7eb5d78..6676cbc 100644 (file)
@@ -29,7 +29,7 @@ struct linux_pcic {
        int                     pcic_imdim;
 };
 
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCIC_PCI
 extern int pcic_present(void);
 extern int pcic_probe(void);
 extern void pci_time_init(void);
index 47a7e86..aba1609 100644 (file)
@@ -220,7 +220,7 @@ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int
        switch (size) {
        case 4:
                return xchg_u32(ptr, x);
-       };
+       }
        __xchg_called_with_bad_pointer();
        return x;
 }
index 3c96d3b..10bcabc 100644 (file)
@@ -234,7 +234,7 @@ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
                return xchg32(ptr, x);
        case 8:
                return xchg64(ptr, x);
-       };
+       }
        __xchg_called_with_bad_pointer();
        return x;
 }
index 9cff270..b90b4a1 100644 (file)
@@ -73,7 +73,9 @@ obj-$(CONFIG_SPARC64_SMP) += cpumap.o
 
 obj-y                     += dma.o
 
-obj-$(CONFIG_SPARC32_PCI) += pcic.o
+obj-$(CONFIG_PCIC_PCI)    += pcic.o
+obj-$(CONFIG_LEON_PCI)    += leon_pci.o
+obj-$(CONFIG_GRPCI2)      += leon_pci_grpci2.o
 
 obj-$(CONFIG_SMP)         += trampoline_$(BITS).o smp_$(BITS).o
 obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o
index 1e34f29..caef9de 100644 (file)
@@ -123,7 +123,7 @@ static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg)
 
        default:
                return -EINVAL;
-       };
+       }
 
        return 0;
 }
index 8505e0a..acf5151 100644 (file)
@@ -101,7 +101,7 @@ void set_auxio(unsigned char bits_on, unsigned char bits_off)
                break;
        default:
                panic("Can't set AUXIO register on this machine.");
-       };
+       }
        spin_unlock_irqrestore(&auxio_lock, flags);
 }
 EXPORT_SYMBOL(set_auxio);
index 668c7be..5f45026 100644 (file)
@@ -664,7 +664,7 @@ static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 va
        case 0x0:
                bp->interleave = 16;
                break;
-       };
+       }
 
        /* UK[10] is reserved, and UK[11] is not set for the SDRAM
         * bank size definition.
index 8341963..9fe08a1 100644 (file)
@@ -229,7 +229,7 @@ real_irq_entry:
 #ifdef CONFIG_SMP
        .globl  patchme_maybe_smp_msg
 
-       cmp     %l7, 12
+       cmp     %l7, 11
 patchme_maybe_smp_msg:
        bgu     maybe_smp4m_msg
         nop
@@ -293,7 +293,7 @@ maybe_smp4m_msg:
        WRITE_PAUSE
        wr      %l4, PSR_ET, %psr
        WRITE_PAUSE
-       sll     %o2, 28, %o2            ! shift for simpler checks below
+       sll     %o3, 28, %o2            ! shift for simpler checks below
 maybe_smp4m_msg_check_single:
        andcc   %o2, 0x1, %g0
        beq,a   maybe_smp4m_msg_check_mask
@@ -1604,7 +1604,7 @@ restore_current:
        retl
         nop
 
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCIC_PCI
 #include <asm/pcic.h>
 
        .align  4
@@ -1650,7 +1650,7 @@ pcic_nmi_trap_patch:
         rd     %psr, %l0
        .word   0
 
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCIC_PCI */
 
        .globl  flushw_all
 flushw_all:
index 2f538ac..d17255a 100644 (file)
@@ -236,6 +236,21 @@ static unsigned int _leon_build_device_irq(struct platform_device *op,
        return leon_build_device_irq(real_irq, handle_simple_irq, "edge", 0);
 }
 
+void leon_update_virq_handling(unsigned int virq,
+                             irq_flow_handler_t flow_handler,
+                             const char *name, int do_ack)
+{
+       unsigned long mask = (unsigned long)irq_get_chip_data(virq);
+
+       mask &= ~LEON_DO_ACK_HW;
+       if (do_ack)
+               mask |= LEON_DO_ACK_HW;
+
+       irq_set_chip_and_handler_name(virq, &leon_irq,
+                                     flow_handler, name);
+       irq_set_chip_data(virq, (void *)mask);
+}
+
 void __init leon_init_timers(irq_handler_t counter_fn)
 {
        int irq, eirq;
@@ -361,6 +376,22 @@ void __init leon_init_timers(irq_handler_t counter_fn)
                prom_halt();
        }
 
+#ifdef CONFIG_SMP
+       {
+               unsigned long flags;
+
+               /*
+                * In SMP, sun4m adds a IPI handler to IRQ trap handler that
+                * LEON never must take, sun4d and LEON overwrites the branch
+                * with a NOP.
+                */
+               local_irq_save(flags);
+               patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
+               local_flush_cache_all();
+               local_irq_restore(flags);
+       }
+#endif
+
        LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
                              LEON3_GPTIMER_EN |
                              LEON3_GPTIMER_RL |
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
new file mode 100644 (file)
index 0000000..a8a9a27
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * leon_pci.c: LEON Host PCI support
+ *
+ * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom
+ *
+ * Code is partially derived from pcic.c
+ */
+
+#include <linux/of_device.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/leon.h>
+#include <asm/leon_pci.h>
+
+/* The LEON architecture does not rely on a BIOS or bootloader to setup
+ * PCI for us. The Linux generic routines are used to setup resources,
+ * reset values of confuration-space registers settings ae preseved.
+ */
+void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
+{
+       struct pci_bus *root_bus;
+
+       root_bus = pci_scan_bus_parented(&ofdev->dev, 0, info->ops, info);
+       if (root_bus) {
+               root_bus->resource[0] = &info->io_space;
+               root_bus->resource[1] = &info->mem_space;
+               root_bus->resource[2] = NULL;
+
+               /* Init all PCI devices into PCI tree */
+               pci_bus_add_devices(root_bus);
+
+               /* Setup IRQs of all devices using custom routines */
+               pci_fixup_irqs(pci_common_swizzle, info->map_irq);
+
+               /* Assign devices with resources */
+               pci_assign_unassigned_resources();
+       }
+}
+
+/* PCI Memory and Prefetchable Memory is direct-mapped. However I/O Space is
+ * accessed through a Window which is translated to low 64KB in PCI space, the
+ * first 4KB is not used so 60KB is available.
+ *
+ * This function is used by generic code to translate resource addresses into
+ * PCI addresses.
+ */
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+                            struct resource *res)
+{
+       struct leon_pci_info *info = dev->bus->sysdata;
+
+       region->start = res->start;
+       region->end = res->end;
+
+       if (res->flags & IORESOURCE_IO) {
+               region->start -= (info->io_space.start - 0x1000);
+               region->end -= (info->io_space.start - 0x1000);
+       }
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+/* see pcibios_resource_to_bus() comment */
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                            struct pci_bus_region *region)
+{
+       struct leon_pci_info *info = dev->bus->sysdata;
+
+       res->start = region->start;
+       res->end = region->end;
+
+       if (res->flags & IORESOURCE_IO) {
+               res->start += (info->io_space.start - 0x1000);
+               res->end += (info->io_space.start - 0x1000);
+       }
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
+void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
+{
+       struct leon_pci_info *info = pbus->sysdata;
+       struct pci_dev *dev;
+       int i, has_io, has_mem;
+       u16 cmd;
+
+       /* Generic PCI bus probing sets these to point at
+        * &io{port,mem}_resouce which is wrong for us.
+        */
+       if (pbus->self == NULL) {
+               pbus->resource[0] = &info->io_space;
+               pbus->resource[1] = &info->mem_space;
+               pbus->resource[2] = NULL;
+       }
+
+       list_for_each_entry(dev, &pbus->devices, bus_list) {
+               /*
+                * We can not rely on that the bootloader has enabled I/O
+                * or memory access to PCI devices. Instead we enable it here
+                * if the device has BARs of respective type.
+                */
+               has_io = has_mem = 0;
+               for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+                       unsigned long f = dev->resource[i].flags;
+                       if (f & IORESOURCE_IO)
+                               has_io = 1;
+                       else if (f & IORESOURCE_MEM)
+                               has_mem = 1;
+               }
+               /* ROM BARs are mapped into 32-bit memory space */
+               if (dev->resource[PCI_ROM_RESOURCE].end != 0) {
+                       dev->resource[PCI_ROM_RESOURCE].flags |=
+                                                       IORESOURCE_ROM_ENABLE;
+                       has_mem = 1;
+               }
+               pci_bus_read_config_word(pbus, dev->devfn, PCI_COMMAND, &cmd);
+               if (has_io && !(cmd & PCI_COMMAND_IO)) {
+#ifdef CONFIG_PCI_DEBUG
+                       printk(KERN_INFO "LEONPCI: Enabling I/O for dev %s\n",
+                                        pci_name(dev));
+#endif
+                       cmd |= PCI_COMMAND_IO;
+                       pci_bus_write_config_word(pbus, dev->devfn, PCI_COMMAND,
+                                                                       cmd);
+               }
+               if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
+#ifdef CONFIG_PCI_DEBUG
+                       printk(KERN_INFO "LEONPCI: Enabling MEMORY for dev"
+                                        "%s\n", pci_name(dev));
+#endif
+                       cmd |= PCI_COMMAND_MEMORY;
+                       pci_bus_write_config_word(pbus, dev->devfn, PCI_COMMAND,
+                                                                       cmd);
+               }
+       }
+}
+
+/*
+ * Other archs parse arguments here.
+ */
+char * __devinit pcibios_setup(char *str)
+{
+       return str;
+}
+
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+                               resource_size_t size, resource_size_t align)
+{
+       return res->start;
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+       return pci_enable_resources(dev, mask);
+}
+
+struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
+{
+       /*
+        * Currently the OpenBoot nodes are not connected with the PCI device,
+        * this is because the LEON PROM does not create PCI nodes. Eventually
+        * this will change and the same approach as pcic.c can be used to
+        * match PROM nodes with pci devices.
+        */
+       return NULL;
+}
+EXPORT_SYMBOL(pci_device_to_OF_node);
+
+void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+#ifdef CONFIG_PCI_DEBUG
+       printk(KERN_DEBUG "LEONPCI: Assigning IRQ %02d to %s\n", irq,
+               pci_name(dev));
+#endif
+       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/* in/out routines taken from pcic.c
+ *
+ * This probably belongs here rather than ioport.c because
+ * we do not want this crud linked into SBus kernels.
+ * Also, think for a moment about likes of floppy.c that
+ * include architecture specific parts. They may want to redefine ins/outs.
+ *
+ * We do not use horrible macros here because we want to
+ * advance pointer by sizeof(size).
+ */
+void outsb(unsigned long addr, const void *src, unsigned long count)
+{
+       while (count) {
+               count -= 1;
+               outb(*(const char *)src, addr);
+               src += 1;
+               /* addr += 1; */
+       }
+}
+EXPORT_SYMBOL(outsb);
+
+void outsw(unsigned long addr, const void *src, unsigned long count)
+{
+       while (count) {
+               count -= 2;
+               outw(*(const short *)src, addr);
+               src += 2;
+               /* addr += 2; */
+       }
+}
+EXPORT_SYMBOL(outsw);
+
+void outsl(unsigned long addr, const void *src, unsigned long count)
+{
+       while (count) {
+               count -= 4;
+               outl(*(const long *)src, addr);
+               src += 4;
+               /* addr += 4; */
+       }
+}
+EXPORT_SYMBOL(outsl);
+
+void insb(unsigned long addr, void *dst, unsigned long count)
+{
+       while (count) {
+               count -= 1;
+               *(unsigned char *)dst = inb(addr);
+               dst += 1;
+               /* addr += 1; */
+       }
+}
+EXPORT_SYMBOL(insb);
+
+void insw(unsigned long addr, void *dst, unsigned long count)
+{
+       while (count) {
+               count -= 2;
+               *(unsigned short *)dst = inw(addr);
+               dst += 2;
+               /* addr += 2; */
+       }
+}
+EXPORT_SYMBOL(insw);
+
+void insl(unsigned long addr, void *dst, unsigned long count)
+{
+       while (count) {
+               count -= 4;
+               /*
+                * XXX I am sure we are in for an unaligned trap here.
+                */
+               *(unsigned long *)dst = inl(addr);
+               dst += 4;
+               /* addr += 4; */
+       }
+}
+EXPORT_SYMBOL(insl);
diff --git a/arch/sparc/kernel/leon_pci_grpci2.c b/arch/sparc/kernel/leon_pci_grpci2.c
new file mode 100644 (file)
index 0000000..44dc093
--- /dev/null
@@ -0,0 +1,897 @@
+/*
+ * leon_pci_grpci2.c: GRPCI2 Host PCI driver
+ *
+ * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom
+ *
+ */
+
+#include <linux/of_device.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/leon.h>
+#include <asm/vaddrs.h>
+#include <asm/sections.h>
+#include <asm/leon_pci.h>
+
+#include "irq.h"
+
+struct grpci2_barcfg {
+       unsigned long pciadr;   /* PCI Space Address */
+       unsigned long ahbadr;   /* PCI Base address mapped to this AHB addr */
+};
+
+/* Device Node Configuration options:
+ *  - barcfgs    : Custom Configuration of Host's 6 target BARs
+ *  - irq_mask   : Limit which PCI interrupts are enabled
+ *  - do_reset   : Force PCI Reset on startup
+ *
+ * barcfgs
+ * =======
+ *
+ * Optional custom Target BAR configuration (see struct grpci2_barcfg). All
+ * addresses are physical. Array always contains 6 elements (len=2*4*6 bytes)
+ *
+ * -1 means not configured (let host driver do default setup).
+ *
+ * [i*2+0] = PCI Address of BAR[i] on target interface
+ * [i*2+1] = Accessing PCI address of BAR[i] result in this AMBA address
+ *
+ *
+ * irq_mask
+ * ========
+ *
+ * Limit which PCI interrupts are enabled. 0=Disable, 1=Enable. By default
+ * all are enabled. Use this when PCI interrupt pins are floating on PCB.
+ * int, len=4.
+ *  bit0 = PCI INTA#
+ *  bit1 = PCI INTB#
+ *  bit2 = PCI INTC#
+ *  bit3 = PCI INTD#
+ *
+ *
+ * reset
+ * =====
+ *
+ * Force PCI reset on startup. int, len=4
+ */
+
+/* Enable Debugging Configuration Space Access */
+#undef GRPCI2_DEBUG_CFGACCESS
+
+/*
+ * GRPCI2 APB Register MAP
+ */
+struct grpci2_regs {
+       unsigned int ctrl;              /* 0x00 Control */
+       unsigned int sts_cap;           /* 0x04 Status / Capabilities */
+       int res1;                       /* 0x08 */
+       unsigned int io_map;            /* 0x0C I/O Map address */
+       unsigned int dma_ctrl;          /* 0x10 DMA */
+       unsigned int dma_bdbase;        /* 0x14 DMA */
+       int res2[2];                    /* 0x18 */
+       unsigned int bars[6];           /* 0x20 read-only PCI BARs */
+       int res3[2];                    /* 0x38 */
+       unsigned int ahbmst_map[16];    /* 0x40 AHB->PCI Map per AHB Master */
+
+       /* PCI Trace Buffer Registers (OPTIONAL) */
+       unsigned int t_ctrl;            /* 0x80 */
+       unsigned int t_cnt;             /* 0x84 */
+       unsigned int t_adpat;           /* 0x88 */
+       unsigned int t_admask;          /* 0x8C */
+       unsigned int t_sigpat;          /* 0x90 */
+       unsigned int t_sigmask;         /* 0x94 */
+       unsigned int t_adstate;         /* 0x98 */
+       unsigned int t_sigstate;        /* 0x9C */
+};
+
+#define REGLOAD(a)     (be32_to_cpu(__raw_readl(&(a))))
+#define REGSTORE(a, v) (__raw_writel(cpu_to_be32(v), &(a)))
+
+#define CTRL_BUS_BIT 16
+
+#define CTRL_RESET (1<<31)
+#define CTRL_SI (1<<27)
+#define CTRL_PE (1<<26)
+#define CTRL_EI (1<<25)
+#define CTRL_ER (1<<24)
+#define CTRL_BUS (0xff<<CTRL_BUS_BIT)
+#define CTRL_HOSTINT 0xf
+
+#define STS_HOST_BIT   31
+#define STS_MST_BIT    30
+#define STS_TAR_BIT    29
+#define STS_DMA_BIT    28
+#define STS_DI_BIT     27
+#define STS_HI_BIT     26
+#define STS_IRQMODE_BIT        24
+#define STS_TRACE_BIT  23
+#define STS_CFGERRVALID_BIT 20
+#define STS_CFGERR_BIT 19
+#define STS_INTTYPE_BIT        12
+#define STS_INTSTS_BIT 8
+#define STS_FDEPTH_BIT 2
+#define STS_FNUM_BIT   0
+
+#define STS_HOST       (1<<STS_HOST_BIT)
+#define STS_MST                (1<<STS_MST_BIT)
+#define STS_TAR                (1<<STS_TAR_BIT)
+#define STS_DMA                (1<<STS_DMA_BIT)
+#define STS_DI         (1<<STS_DI_BIT)
+#define STS_HI         (1<<STS_HI_BIT)
+#define STS_IRQMODE    (0x3<<STS_IRQMODE_BIT)
+#define STS_TRACE      (1<<STS_TRACE_BIT)
+#define STS_CFGERRVALID        (1<<STS_CFGERRVALID_BIT)
+#define STS_CFGERR     (1<<STS_CFGERR_BIT)
+#define STS_INTTYPE    (0x3f<<STS_INTTYPE_BIT)
+#define STS_INTSTS     (0xf<<STS_INTSTS_BIT)
+#define STS_FDEPTH     (0x7<<STS_FDEPTH_BIT)
+#define STS_FNUM       (0x3<<STS_FNUM_BIT)
+
+#define STS_ISYSERR    (1<<17)
+#define STS_IDMA       (1<<16)
+#define STS_IDMAERR    (1<<15)
+#define STS_IMSTABRT   (1<<14)
+#define STS_ITGTABRT   (1<<13)
+#define STS_IPARERR    (1<<12)
+
+#define STS_ERR_IRQ (STS_ISYSERR | STS_IMSTABRT | STS_ITGTABRT | STS_IPARERR)
+
+struct grpci2_bd_chan {
+       unsigned int ctrl;      /* 0x00 DMA Control */
+       unsigned int nchan;     /* 0x04 Next DMA Channel Address */
+       unsigned int nbd;       /* 0x08 Next Data Descriptor in chan */
+       unsigned int res;       /* 0x0C Reserved */
+};
+
+#define BD_CHAN_EN             0x80000000
+#define BD_CHAN_TYPE           0x00300000
+#define BD_CHAN_BDCNT          0x0000ffff
+#define BD_CHAN_EN_BIT         31
+#define BD_CHAN_TYPE_BIT       20
+#define BD_CHAN_BDCNT_BIT      0
+
+struct grpci2_bd_data {
+       unsigned int ctrl;      /* 0x00 DMA Data Control */
+       unsigned int pci_adr;   /* 0x04 PCI Start Address */
+       unsigned int ahb_adr;   /* 0x08 AHB Start address */
+       unsigned int next;      /* 0x0C Next Data Descriptor in chan */
+};
+
+#define BD_DATA_EN             0x80000000
+#define BD_DATA_IE             0x40000000
+#define BD_DATA_DR             0x20000000
+#define BD_DATA_TYPE           0x00300000
+#define BD_DATA_ER             0x00080000
+#define BD_DATA_LEN            0x0000ffff
+#define BD_DATA_EN_BIT         31
+#define BD_DATA_IE_BIT         30
+#define BD_DATA_DR_BIT         29
+#define BD_DATA_TYPE_BIT       20
+#define BD_DATA_ER_BIT         19
+#define BD_DATA_LEN_BIT                0
+
+/* GRPCI2 Capability */
+struct grpci2_cap_first {
+       unsigned int ctrl;
+       unsigned int pci2ahb_map[6];
+       unsigned int ext2ahb_map;
+       unsigned int io_map;
+       unsigned int pcibar_size[6];
+};
+#define CAP9_CTRL_OFS 0
+#define CAP9_BAR_OFS 0x4
+#define CAP9_IOMAP_OFS 0x20
+#define CAP9_BARSIZE_OFS 0x24
+
+struct grpci2_priv {
+       struct leon_pci_info    info; /* must be on top of this structure */
+       struct grpci2_regs      *regs;
+       char                    irq;
+       char                    irq_mode; /* IRQ Mode from CAPSTS REG */
+       char                    bt_enabled;
+       char                    do_reset;
+       char                    irq_mask;
+       u32                     pciid; /* PCI ID of Host */
+       unsigned char           irq_map[4];
+
+       /* Virtual IRQ numbers */
+       unsigned int            virq_err;
+       unsigned int            virq_dma;
+
+       /* AHB PCI Windows */
+       unsigned long           pci_area;       /* MEMORY */
+       unsigned long           pci_area_end;
+       unsigned long           pci_io;         /* I/O */
+       unsigned long           pci_conf;       /* CONFIGURATION */
+       unsigned long           pci_conf_end;
+       unsigned long           pci_io_va;
+
+       struct grpci2_barcfg    tgtbars[6];
+};
+
+DEFINE_SPINLOCK(grpci2_dev_lock);
+struct grpci2_priv *grpci2priv;
+
+int grpci2_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       struct grpci2_priv *priv = dev->bus->sysdata;
+       int irq_group;
+
+       /* Use default IRQ decoding on PCI BUS0 according slot numbering */
+       irq_group = slot & 0x3;
+       pin = ((pin - 1) + irq_group) & 0x3;
+
+       return priv->irq_map[pin];
+}
+
+static int grpci2_cfg_r32(struct grpci2_priv *priv, unsigned int bus,
+                               unsigned int devfn, int where, u32 *val)
+{
+       unsigned int *pci_conf;
+       unsigned long flags;
+       u32 tmp;
+
+       if (where & 0x3)
+               return -EINVAL;
+
+       if (bus == 0 && PCI_SLOT(devfn) != 0)
+               devfn += (0x8 * 6);
+
+       /* Select bus */
+       spin_lock_irqsave(&grpci2_dev_lock, flags);
+       REGSTORE(priv->regs->ctrl, (REGLOAD(priv->regs->ctrl) & ~(0xff << 16)) |
+                                  (bus << 16));
+       spin_unlock_irqrestore(&grpci2_dev_lock, flags);
+
+       /* clear old status */
+       REGSTORE(priv->regs->sts_cap, (STS_CFGERR | STS_CFGERRVALID));
+
+       pci_conf = (unsigned int *) (priv->pci_conf |
+                                               (devfn << 8) | (where & 0xfc));
+       tmp = LEON3_BYPASS_LOAD_PA(pci_conf);
+
+       /* Wait until GRPCI2 signals that CFG access is done, it should be
+        * done instantaneously unless a DMA operation is ongoing...
+        */
+       while ((REGLOAD(priv->regs->sts_cap) & STS_CFGERRVALID) == 0)
+               ;
+
+       if (REGLOAD(priv->regs->sts_cap) & STS_CFGERR) {
+               *val = 0xffffffff;
+       } else {
+               /* Bus always little endian (unaffected by byte-swapping) */
+               *val = flip_dword(tmp);
+       }
+
+       return 0;
+}
+
+static int grpci2_cfg_r16(struct grpci2_priv *priv, unsigned int bus,
+                               unsigned int devfn, int where, u32 *val)
+{
+       u32 v;
+       int ret;
+
+       if (where & 0x1)
+               return -EINVAL;
+       ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v);
+       *val = 0xffff & (v >> (8 * (where & 0x3)));
+       return ret;
+}
+
+static int grpci2_cfg_r8(struct grpci2_priv *priv, unsigned int bus,
+                               unsigned int devfn, int where, u32 *val)
+{
+       u32 v;
+       int ret;
+
+       ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v);
+       *val = 0xff & (v >> (8 * (where & 3)));
+
+       return ret;
+}
+
+static int grpci2_cfg_w32(struct grpci2_priv *priv, unsigned int bus,
+                               unsigned int devfn, int where, u32 val)
+{
+       unsigned int *pci_conf;
+       unsigned long flags;
+
+       if (where & 0x3)
+               return -EINVAL;
+
+       if (bus == 0 && PCI_SLOT(devfn) != 0)
+               devfn += (0x8 * 6);
+
+       /* Select bus */
+       spin_lock_irqsave(&grpci2_dev_lock, flags);
+       REGSTORE(priv->regs->ctrl, (REGLOAD(priv->regs->ctrl) & ~(0xff << 16)) |
+                                  (bus << 16));
+       spin_unlock_irqrestore(&grpci2_dev_lock, flags);
+
+       /* clear old status */
+       REGSTORE(priv->regs->sts_cap, (STS_CFGERR | STS_CFGERRVALID));
+
+       pci_conf = (unsigned int *) (priv->pci_conf |
+                                               (devfn << 8) | (where & 0xfc));
+       LEON3_BYPASS_STORE_PA(pci_conf, flip_dword(val));
+
+       /* Wait until GRPCI2 signals that CFG access is done, it should be
+        * done instantaneously unless a DMA operation is ongoing...
+        */
+       while ((REGLOAD(priv->regs->sts_cap) & STS_CFGERRVALID) == 0)
+               ;
+
+       return 0;
+}
+
+static int grpci2_cfg_w16(struct grpci2_priv *priv, unsigned int bus,
+                               unsigned int devfn, int where, u32 val)
+{
+       int ret;
+       u32 v;
+
+       if (where & 0x1)
+               return -EINVAL;
+       ret = grpci2_cfg_r32(priv, bus, devfn, where&~3, &v);
+       if (ret)
+               return ret;
+       v = (v & ~(0xffff << (8 * (where & 0x3)))) |
+           ((0xffff & val) << (8 * (where & 0x3)));
+       return grpci2_cfg_w32(priv, bus, devfn, where & ~0x3, v);
+}
+
+static int grpci2_cfg_w8(struct grpci2_priv *priv, unsigned int bus,
+                               unsigned int devfn, int where, u32 val)
+{
+       int ret;
+       u32 v;
+
+       ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v);
+       if (ret != 0)
+               return ret;
+       v = (v & ~(0xff << (8 * (where & 0x3)))) |
+           ((0xff & val) << (8 * (where & 0x3)));
+       return grpci2_cfg_w32(priv, bus, devfn, where & ~0x3, v);
+}
+
+/* Read from Configuration Space. When entering here the PCI layer has taken
+ * the pci_lock spinlock and IRQ is off.
+ */
+static int grpci2_read_config(struct pci_bus *bus, unsigned int devfn,
+                             int where, int size, u32 *val)
+{
+       struct grpci2_priv *priv = grpci2priv;
+       unsigned int busno = bus->number;
+       int ret;
+
+       if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0)) {
+               *val = ~0;
+               return 0;
+       }
+
+       switch (size) {
+       case 1:
+               ret = grpci2_cfg_r8(priv, busno, devfn, where, val);
+               break;
+       case 2:
+               ret = grpci2_cfg_r16(priv, busno, devfn, where, val);
+               break;
+       case 4:
+               ret = grpci2_cfg_r32(priv, busno, devfn, where, val);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+#ifdef GRPCI2_DEBUG_CFGACCESS
+       printk(KERN_INFO "grpci2_read_config: [%02x:%02x:%x] ofs=%d val=%x "
+               "size=%d\n", busno, PCI_SLOT(devfn), PCI_FUNC(devfn), where,
+               *val, size);
+#endif
+
+       return ret;
+}
+
+/* Write to Configuration Space. When entering here the PCI layer has taken
+ * the pci_lock spinlock and IRQ is off.
+ */
+static int grpci2_write_config(struct pci_bus *bus, unsigned int devfn,
+                              int where, int size, u32 val)
+{
+       struct grpci2_priv *priv = grpci2priv;
+       unsigned int busno = bus->number;
+
+       if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0))
+               return 0;
+
+#ifdef GRPCI2_DEBUG_CFGACCESS
+       printk(KERN_INFO "grpci2_write_config: [%02x:%02x:%x] ofs=%d size=%d "
+               "val=%x\n", busno, PCI_SLOT(devfn), PCI_FUNC(devfn),
+               where, size, val);
+#endif
+
+       switch (size) {
+       default:
+               return -EINVAL;
+       case 1:
+               return grpci2_cfg_w8(priv, busno, devfn, where, val);
+       case 2:
+               return grpci2_cfg_w16(priv, busno, devfn, where, val);
+       case 4:
+               return grpci2_cfg_w32(priv, busno, devfn, where, val);
+       }
+}
+
+static struct pci_ops grpci2_ops = {
+       .read =         grpci2_read_config,
+       .write =        grpci2_write_config,
+};
+
+/* GENIRQ IRQ chip implementation for GRPCI2 irqmode=0..2. In configuration
+ * 3 where all PCI Interrupts has a separate IRQ on the system IRQ controller
+ * this is not needed and the standard IRQ controller can be used.
+ */
+
+static void grpci2_mask_irq(struct irq_data *data)
+{
+       unsigned long flags;
+       unsigned int irqidx;
+       struct grpci2_priv *priv = grpci2priv;
+
+       irqidx = (unsigned int)data->chip_data - 1;
+       if (irqidx > 3) /* only mask PCI interrupts here */
+               return;
+
+       spin_lock_irqsave(&grpci2_dev_lock, flags);
+       REGSTORE(priv->regs->ctrl, REGLOAD(priv->regs->ctrl) & ~(1 << irqidx));
+       spin_unlock_irqrestore(&grpci2_dev_lock, flags);
+}
+
+static void grpci2_unmask_irq(struct irq_data *data)
+{
+       unsigned long flags;
+       unsigned int irqidx;
+       struct grpci2_priv *priv = grpci2priv;
+
+       irqidx = (unsigned int)data->chip_data - 1;
+       if (irqidx > 3) /* only unmask PCI interrupts here */
+               return;
+
+       spin_lock_irqsave(&grpci2_dev_lock, flags);
+       REGSTORE(priv->regs->ctrl, REGLOAD(priv->regs->ctrl) | (1 << irqidx));
+       spin_unlock_irqrestore(&grpci2_dev_lock, flags);
+}
+
+static unsigned int grpci2_startup_irq(struct irq_data *data)
+{
+       grpci2_unmask_irq(data);
+       return 0;
+}
+
+static void grpci2_shutdown_irq(struct irq_data *data)
+{
+       grpci2_mask_irq(data);
+}
+
+static struct irq_chip grpci2_irq = {
+       .name           = "grpci2",
+       .irq_startup    = grpci2_startup_irq,
+       .irq_shutdown   = grpci2_shutdown_irq,
+       .irq_mask       = grpci2_mask_irq,
+       .irq_unmask     = grpci2_unmask_irq,
+};
+
+/* Handle one or multiple IRQs from the PCI core */
+static void grpci2_pci_flow_irq(unsigned int irq, struct irq_desc *desc)
+{
+       struct grpci2_priv *priv = grpci2priv;
+       int i, ack = 0;
+       unsigned int ctrl, sts_cap, pci_ints;
+
+       ctrl = REGLOAD(priv->regs->ctrl);
+       sts_cap = REGLOAD(priv->regs->sts_cap);
+
+       /* Error Interrupt? */
+       if (sts_cap & STS_ERR_IRQ) {
+               generic_handle_irq(priv->virq_err);
+               ack = 1;
+       }
+
+       /* PCI Interrupt? */
+       pci_ints = ((~sts_cap) >> STS_INTSTS_BIT) & ctrl & CTRL_HOSTINT;
+       if (pci_ints) {
+               /* Call respective PCI Interrupt handler */
+               for (i = 0; i < 4; i++) {
+                       if (pci_ints & (1 << i))
+                               generic_handle_irq(priv->irq_map[i]);
+               }
+               ack = 1;
+       }
+
+       /*
+        * Decode DMA Interrupt only when shared with Err and PCI INTX#, when
+        * the DMA is a unique IRQ the DMA interrupts doesn't end up here, they
+        * goes directly to DMA ISR.
+        */
+       if ((priv->irq_mode == 0) && (sts_cap & (STS_IDMA | STS_IDMAERR))) {
+               generic_handle_irq(priv->virq_dma);
+               ack = 1;
+       }
+
+       /*
+        * Call "first level" IRQ chip end-of-irq handler. It will ACK LEON IRQ
+        * Controller, this must be done after IRQ sources have been handled to
+        * avoid double IRQ generation
+        */
+       if (ack)
+               desc->irq_data.chip->irq_eoi(&desc->irq_data);
+}
+
+/* Create a virtual IRQ */
+static unsigned int grpci2_build_device_irq(unsigned int irq)
+{
+       unsigned int virq = 0, pil;
+
+       pil = 1 << 8;
+       virq = irq_alloc(irq, pil);
+       if (virq == 0)
+               goto out;
+
+       irq_set_chip_and_handler_name(virq, &grpci2_irq, handle_simple_irq,
+                                     "pcilvl");
+       irq_set_chip_data(virq, (void *)irq);
+
+out:
+       return virq;
+}
+
+void grpci2_hw_init(struct grpci2_priv *priv)
+{
+       u32 ahbadr, pciadr, bar_sz, capptr, io_map, data;
+       struct grpci2_regs *regs = priv->regs;
+       int i;
+       struct grpci2_barcfg *barcfg = priv->tgtbars;
+
+       /* Reset any earlier setup */
+       if (priv->do_reset) {
+               printk(KERN_INFO "GRPCI2: Resetting PCI bus\n");
+               REGSTORE(regs->ctrl, CTRL_RESET);
+               ssleep(1); /* Wait for boards to settle */
+       }
+       REGSTORE(regs->ctrl, 0);
+       REGSTORE(regs->sts_cap, ~0); /* Clear Status */
+       REGSTORE(regs->dma_ctrl, 0);
+       REGSTORE(regs->dma_bdbase, 0);
+
+       /* Translate I/O accesses to 0, I/O Space always @ PCI low 64Kbytes */
+       REGSTORE(regs->io_map, REGLOAD(regs->io_map) & 0x0000ffff);
+
+       /* set 1:1 mapping between AHB -> PCI memory space, for all Masters
+        * Each AHB master has it's own mapping registers. Max 16 AHB masters.
+        */
+       for (i = 0; i < 16; i++)
+               REGSTORE(regs->ahbmst_map[i], priv->pci_area);
+
+       /* Get the GRPCI2 Host PCI ID */
+       grpci2_cfg_r32(priv, 0, 0, PCI_VENDOR_ID, &priv->pciid);
+
+       /* Get address to first (always defined) capability structure */
+       grpci2_cfg_r8(priv, 0, 0, PCI_CAPABILITY_LIST, &capptr);
+
+       /* Enable/Disable Byte twisting */
+       grpci2_cfg_r32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, &io_map);
+       io_map = (io_map & ~0x1) | (priv->bt_enabled ? 1 : 0);
+       grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, io_map);
+
+       /* Setup the Host's PCI Target BARs for other peripherals to access,
+        * and do DMA to the host's memory. The target BARs can be sized and
+        * enabled individually.
+        *
+        * User may set custom target BARs, but default is:
+        * The first BARs is used to map kernel low (DMA is part of normal
+        * region on sparc which is SRMMU_MAXMEM big) main memory 1:1 to the
+        * PCI bus, the other BARs are disabled. We assume that the first BAR
+        * is always available.
+        */
+       for (i = 0; i < 6; i++) {
+               if (barcfg[i].pciadr != ~0 && barcfg[i].ahbadr != ~0) {
+                       /* Target BARs must have the proper alignment */
+                       ahbadr = barcfg[i].ahbadr;
+                       pciadr = barcfg[i].pciadr;
+                       bar_sz = ((pciadr - 1) & ~pciadr) + 1;
+               } else {
+                       if (i == 0) {
+                               /* Map main memory */
+                               bar_sz = 0xf0000008; /* 256MB prefetchable */
+                               ahbadr = 0xf0000000 & (u32)__pa(PAGE_ALIGN(
+                                       (unsigned long) &_end));
+                               pciadr = ahbadr;
+                       } else {
+                               bar_sz = 0;
+                               ahbadr = 0;
+                               pciadr = 0;
+                       }
+               }
+               grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BARSIZE_OFS+i*4, bar_sz);
+               grpci2_cfg_w32(priv, 0, 0, PCI_BASE_ADDRESS_0+i*4, pciadr);
+               grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BAR_OFS+i*4, ahbadr);
+               printk(KERN_INFO "        TGT BAR[%d]: 0x%08x (PCI)-> 0x%08x\n",
+                       i, pciadr, ahbadr);
+       }
+
+       /* set as bus master and enable pci memory responses */
+       grpci2_cfg_r32(priv, 0, 0, PCI_COMMAND, &data);
+       data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+       grpci2_cfg_w32(priv, 0, 0, PCI_COMMAND, data);
+
+       /* Enable Error respone (CPU-TRAP) on illegal memory access. */
+       REGSTORE(regs->ctrl, CTRL_ER | CTRL_PE);
+}
+
+static irqreturn_t grpci2_jump_interrupt(int irq, void *arg)
+{
+       printk(KERN_ERR "GRPCI2: Jump IRQ happened\n");
+       return IRQ_NONE;
+}
+
+/* Handle GRPCI2 Error Interrupt */
+static irqreturn_t grpci2_err_interrupt(int irq, void *arg)
+{
+       struct grpci2_priv *priv = arg;
+       struct grpci2_regs *regs = priv->regs;
+       unsigned int status;
+
+       status = REGLOAD(regs->sts_cap);
+       if ((status & STS_ERR_IRQ) == 0)
+               return IRQ_NONE;
+
+       if (status & STS_IPARERR)
+               printk(KERN_ERR "GRPCI2: Parity Error\n");
+
+       if (status & STS_ITGTABRT)
+               printk(KERN_ERR "GRPCI2: Target Abort\n");
+
+       if (status & STS_IMSTABRT)
+               printk(KERN_ERR "GRPCI2: Master Abort\n");
+
+       if (status & STS_ISYSERR)
+               printk(KERN_ERR "GRPCI2: System Error\n");
+
+       /* Clear handled INT TYPE IRQs */
+       REGSTORE(regs->sts_cap, status & STS_ERR_IRQ);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit grpci2_of_probe(struct platform_device *ofdev)
+{
+       struct grpci2_regs *regs;
+       struct grpci2_priv *priv;
+       int err, i, len;
+       const int *tmp;
+       unsigned int capability;
+
+       if (grpci2priv) {
+               printk(KERN_ERR "GRPCI2: only one GRPCI2 core supported\n");
+               return -ENODEV;
+       }
+
+       if (ofdev->num_resources < 3) {
+               printk(KERN_ERR "GRPCI2: not enough APB/AHB resources\n");
+               return -EIO;
+       }
+
+       /* Find Device Address */
+       regs = of_ioremap(&ofdev->resource[0], 0,
+                         resource_size(&ofdev->resource[0]),
+                         "grlib-grpci2 regs");
+       if (regs == NULL) {
+               printk(KERN_ERR "GRPCI2: ioremap failed\n");
+               return -EIO;
+       }
+
+       /*
+        * Check that we're in Host Slot and that we can act as a Host Bridge
+        * and not only as target.
+        */
+       capability = REGLOAD(regs->sts_cap);
+       if ((capability & STS_HOST) || !(capability & STS_MST)) {
+               printk(KERN_INFO "GRPCI2: not in host system slot\n");
+               err = -EIO;
+               goto err1;
+       }
+
+       priv = grpci2priv = kzalloc(sizeof(struct grpci2_priv), GFP_KERNEL);
+       if (grpci2priv == NULL) {
+               err = -ENOMEM;
+               goto err1;
+       }
+       memset(grpci2priv, 0, sizeof(*grpci2priv));
+       priv->regs = regs;
+       priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */
+       priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT;
+
+       printk(KERN_INFO "GRPCI2: host found at %p, irq%d\n", regs, priv->irq);
+
+       /* Byte twisting should be made configurable from kernel command line */
+       priv->bt_enabled = 1;
+
+       /* Let user do custom Target BAR assignment */
+       tmp = of_get_property(ofdev->dev.of_node, "barcfg", &len);
+       if (tmp && (len == 2*4*6))
+               memcpy(priv->tgtbars, tmp, 2*4*6);
+       else
+               memset(priv->tgtbars, -1, 2*4*6);
+
+       /* Limit IRQ unmasking in irq_mode 2 and 3 */
+       tmp = of_get_property(ofdev->dev.of_node, "irq_mask", &len);
+       if (tmp && (len == 4))
+               priv->do_reset = *tmp;
+       else
+               priv->irq_mask = 0xf;
+
+       /* Optional PCI reset. Force PCI reset on startup */
+       tmp = of_get_property(ofdev->dev.of_node, "reset", &len);
+       if (tmp && (len == 4))
+               priv->do_reset = *tmp;
+       else
+               priv->do_reset = 0;
+
+       /* Find PCI Memory, I/O and Configuration Space Windows */
+       priv->pci_area = ofdev->resource[1].start;
+       priv->pci_area_end = ofdev->resource[1].end+1;
+       priv->pci_io = ofdev->resource[2].start;
+       priv->pci_conf = ofdev->resource[2].start + 0x10000;
+       priv->pci_conf_end = priv->pci_conf + 0x10000;
+       priv->pci_io_va = (unsigned long)ioremap(priv->pci_io, 0x10000);
+       if (!priv->pci_io_va) {
+               err = -EIO;
+               goto err2;
+       }
+
+       printk(KERN_INFO
+               "GRPCI2: MEMORY SPACE [0x%08lx - 0x%08lx]\n"
+               "        I/O    SPACE [0x%08lx - 0x%08lx]\n"
+               "        CONFIG SPACE [0x%08lx - 0x%08lx]\n",
+               priv->pci_area, priv->pci_area_end-1,
+               priv->pci_io, priv->pci_conf-1,
+               priv->pci_conf, priv->pci_conf_end-1);
+
+       /*
+        * I/O Space resources in I/O Window mapped into Virtual Adr Space
+        * We never use low 4KB because some devices seem have problems using
+        * address 0.
+        */
+       memset(&priv->info.io_space, 0, sizeof(struct resource));
+       priv->info.io_space.name = "GRPCI2 PCI I/O Space";
+       priv->info.io_space.start = priv->pci_io_va + 0x1000;
+       priv->info.io_space.end = priv->pci_io_va + 0x10000 - 1;
+       priv->info.io_space.flags = IORESOURCE_IO;
+
+       /*
+        * GRPCI2 has no prefetchable memory, map everything as
+        * non-prefetchable memory
+        */
+       memset(&priv->info.mem_space, 0, sizeof(struct resource));
+       priv->info.mem_space.name = "GRPCI2 PCI MEM Space";
+       priv->info.mem_space.start = priv->pci_area;
+       priv->info.mem_space.end = priv->pci_area_end - 1;
+       priv->info.mem_space.flags = IORESOURCE_MEM;
+
+       if (request_resource(&iomem_resource, &priv->info.mem_space) < 0)
+               goto err3;
+       if (request_resource(&ioport_resource, &priv->info.io_space) < 0)
+               goto err4;
+
+       grpci2_hw_init(priv);
+
+       /*
+        * Get PCI Interrupt to System IRQ mapping and setup IRQ handling
+        * Error IRQ always on PCI INTA.
+        */
+       if (priv->irq_mode < 2) {
+               /* All PCI interrupts are shared using the same system IRQ */
+               leon_update_virq_handling(priv->irq, grpci2_pci_flow_irq,
+                                        "pcilvl", 0);
+
+               priv->irq_map[0] = grpci2_build_device_irq(1);
+               priv->irq_map[1] = grpci2_build_device_irq(2);
+               priv->irq_map[2] = grpci2_build_device_irq(3);
+               priv->irq_map[3] = grpci2_build_device_irq(4);
+
+               priv->virq_err = grpci2_build_device_irq(5);
+               if (priv->irq_mode & 1)
+                       priv->virq_dma = ofdev->archdata.irqs[1];
+               else
+                       priv->virq_dma = grpci2_build_device_irq(6);
+
+               /* Enable IRQs on LEON IRQ controller */
+               err = request_irq(priv->irq, grpci2_jump_interrupt, 0,
+                                       "GRPCI2_JUMP", priv);
+               if (err)
+                       printk(KERN_ERR "GRPCI2: ERR IRQ request failed\n");
+       } else {
+               /* All PCI interrupts have an unique IRQ interrupt */
+               for (i = 0; i < 4; i++) {
+                       /* Make LEON IRQ layer handle level IRQ by acking */
+                       leon_update_virq_handling(ofdev->archdata.irqs[i],
+                                                handle_fasteoi_irq, "pcilvl",
+                                                1);
+                       priv->irq_map[i] = ofdev->archdata.irqs[i];
+               }
+               priv->virq_err = priv->irq_map[0];
+               if (priv->irq_mode & 1)
+                       priv->virq_dma = ofdev->archdata.irqs[4];
+               else
+                       priv->virq_dma = priv->irq_map[0];
+
+               /* Unmask all PCI interrupts, request_irq will not do that */
+               REGSTORE(regs->ctrl, REGLOAD(regs->ctrl)|(priv->irq_mask&0xf));
+       }
+
+       /* Setup IRQ handler for non-configuration space access errors */
+       err = request_irq(priv->virq_err, grpci2_err_interrupt, IRQF_SHARED,
+                               "GRPCI2_ERR", priv);
+       if (err) {
+               printk(KERN_DEBUG "GRPCI2: ERR VIRQ request failed: %d\n", err);
+               goto err5;
+       }
+
+       /*
+        * Enable Error Interrupts. PCI interrupts are unmasked once request_irq
+        * is called by the PCI Device drivers
+        */
+       REGSTORE(regs->ctrl, REGLOAD(regs->ctrl) | CTRL_EI | CTRL_SI);
+
+       /* Init common layer and scan buses */
+       priv->info.ops = &grpci2_ops;
+       priv->info.map_irq = grpci2_map_irq;
+       leon_pci_init(ofdev, &priv->info);
+
+       return 0;
+
+err5:
+       release_resource(&priv->info.io_space);
+err4:
+       release_resource(&priv->info.mem_space);
+err3:
+       err = -ENOMEM;
+       iounmap((void *)priv->pci_io_va);
+err2:
+       kfree(priv);
+err1:
+       of_iounmap(&ofdev->resource[0], regs,
+               resource_size(&ofdev->resource[0]));
+       return err;
+}
+
+static struct of_device_id grpci2_of_match[] = {
+       {
+        .name = "GAISLER_GRPCI2",
+        },
+       {
+        .name = "01_07c",
+        },
+       {},
+};
+
+static struct platform_driver grpci2_of_driver = {
+       .driver = {
+               .name = "grpci2",
+               .owner = THIS_MODULE,
+               .of_match_table = grpci2_of_match,
+       },
+       .probe = grpci2_of_probe,
+};
+
+static int __init grpci2_init(void)
+{
+       return platform_driver_register(&grpci2_of_driver);
+}
+
+subsys_initcall(grpci2_init);
index 8d348c4..99ba5ba 100644 (file)
@@ -214,7 +214,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                               me->name,
                               (int) (ELF_R_TYPE(rel[i].r_info) & 0xff));
                        return -ENOEXEC;
-               };
+               }
        }
        return 0;
 }
index 6e3874b..a689598 100644 (file)
@@ -281,7 +281,7 @@ static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
        case 4:
                *value = ret & 0xffffffff;
                break;
-       };
+       }
 
 
        return PCIBIOS_SUCCESSFUL;
@@ -456,7 +456,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
 
                default:
                        break;
-               };
+               }
        }
 
        if (!saw_io || !saw_mem) {
index 283fbc3..f030b02 100644 (file)
@@ -264,7 +264,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
                default:
                        type_string = "ECC Error";
                        break;
-               };
+               }
                printk("%s: IOMMU Error, type[%s]\n",
                       pbm->name, type_string);
 
@@ -319,7 +319,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
                        default:
                                type_string = "ECC Error";
                                break;
-                       };
+                       }
                        printk("%s: IOMMU TAG(%d)[error(%s) ctx(%x) wr(%d) str(%d) "
                               "sz(%dK) vpg(%08lx)]\n",
                               pbm->name, i, type_string,
@@ -1328,7 +1328,7 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm,
        default:
                chipset_name = "SCHIZO";
                break;
-       };
+       }
 
        /* For SCHIZO, three OBP regs:
         * 1) PBM controller regs
index 570b98f..40e4936 100644 (file)
@@ -694,7 +694,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp,
                case 3:
                        iclr = reg_base + SYSIO_ICLR_SLOT3;
                        break;
-               };
+               }
 
                iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
        }
index fe2af66..8db48e8 100644 (file)
@@ -228,7 +228,7 @@ void psycho_check_iommu_error(struct pci_pbm_info *pbm,
                default:
                        type_str = "ECC Error";
                        break;
-               };
+               }
                printk(KERN_ERR "%s: IOMMU Error, type[%s]\n",
                       pbm->name, type_str);
 
index 2ca32d1..a161b9c 100644 (file)
@@ -97,7 +97,7 @@ void sbus_set_sbus64(struct device *dev, int bursts)
 
        default:
                return;
-       };
+       }
 
        val = upa_readq(cfg_reg);
        if (val & (1UL << 14UL)) {
@@ -244,7 +244,7 @@ static unsigned int sbus_build_irq(struct platform_device *op, unsigned int ino)
                case 3:
                        iclr = reg_base + SYSIO_ICLR_SLOT3;
                        break;
-               };
+               }
 
                iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
        }
index 3249d3f..d26e1f6 100644 (file)
@@ -267,7 +267,7 @@ void __init setup_arch(char **cmdline_p)
        default:
                printk("UNKNOWN!\n");
                break;
-       };
+       }
 
 #ifdef CONFIG_DUMMY_CONSOLE
        conswitchp = &dummy_con;
index f3b6850..c4dd099 100644 (file)
@@ -209,7 +209,7 @@ void __init per_cpu_patch(void)
                default:
                        prom_printf("Unknown cpu type, halting.\n");
                        prom_halt();
-               };
+               }
 
                *(unsigned int *) (addr +  0) = insns[0];
                wmb();
index d5b3958..21b1253 100644 (file)
@@ -114,7 +114,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
                printk("UNKNOWN!\n");
                BUG();
                break;
-       };
+       }
 }
 
 void cpu_panic(void)
@@ -374,7 +374,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                printk("UNKNOWN!\n");
                BUG();
                break;
-       };
+       }
 }
 
 /* Set this up early so that things like the scheduler can init
@@ -447,7 +447,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
                printk("UNKNOWN!\n");
                BUG();
                break;
-       };
+       }
 
        if (!ret) {
                cpumask_set_cpu(cpu, &smp_commenced_mask);
index a9ea60e..1d13c5b 100644 (file)
@@ -103,10 +103,9 @@ static void sun4d_sbus_handler_irq(int sbusl)
 
        sbil = (sbusl << 2);
        /* Loop for each pending SBI */
-       for (sbino = 0; bus_mask; sbino++) {
+       for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) {
                unsigned int idx, mask;
 
-               bus_mask >>= 1;
                if (!(bus_mask & 1))
                        continue;
                /* XXX This seems to ACK the irq twice.  acquire_sbi()
@@ -118,19 +117,16 @@ static void sun4d_sbus_handler_irq(int sbusl)
                mask &= (0xf << sbil);
 
                /* Loop for each pending SBI slot */
-               idx = 0;
                slot = (1 << sbil);
-               while (mask != 0) {
+               for (idx = 0; mask != 0; idx++, slot <<= 1) {
                        unsigned int pil;
                        struct irq_bucket *p;
 
-                       idx++;
-                       slot <<= 1;
                        if (!(mask & slot))
                                continue;
 
                        mask &= ~slot;
-                       pil = sun4d_encode_irq(sbino, sbil, idx);
+                       pil = sun4d_encode_irq(sbino, sbusl, idx);
 
                        p = irq_map[pil];
                        while (p) {
@@ -218,10 +214,10 @@ static void sun4d_unmask_irq(struct irq_data *data)
 
 #ifdef CONFIG_SMP
        spin_lock_irqsave(&sun4d_imsk_lock, flags);
-       cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | ~(1 << real_irq));
+       cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) & ~(1 << real_irq));
        spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
 #else
-       cc_set_imsk(cc_get_imsk() | ~(1 << real_irq));
+       cc_set_imsk(cc_get_imsk() & ~(1 << real_irq));
 #endif
 }
 
@@ -299,26 +295,68 @@ static void __init sun4d_load_profile_irqs(void)
        }
 }
 
+unsigned int _sun4d_build_device_irq(unsigned int real_irq,
+                                     unsigned int pil,
+                                     unsigned int board)
+{
+       struct sun4d_handler_data *handler_data;
+       unsigned int irq;
+
+       irq = irq_alloc(real_irq, pil);
+       if (irq == 0) {
+               prom_printf("IRQ: allocate for %d %d %d failed\n",
+                       real_irq, pil, board);
+               goto err_out;
+       }
+
+       handler_data = irq_get_handler_data(irq);
+       if (unlikely(handler_data))
+               goto err_out;
+
+       handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC);
+       if (unlikely(!handler_data)) {
+               prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n");
+               prom_halt();
+       }
+       handler_data->cpuid    = board_to_cpu[board];
+       handler_data->real_irq = real_irq;
+       irq_set_chip_and_handler_name(irq, &sun4d_irq,
+                                     handle_level_irq, "level");
+       irq_set_handler_data(irq, handler_data);
+
+err_out:
+       return irq;
+}
+
+
+
 unsigned int sun4d_build_device_irq(struct platform_device *op,
                                     unsigned int real_irq)
 {
        struct device_node *dp = op->dev.of_node;
-       struct device_node *io_unit, *sbi = dp->parent;
+       struct device_node *board_parent, *bus = dp->parent;
+       char *bus_connection;
        const struct linux_prom_registers *regs;
-       struct sun4d_handler_data *handler_data;
        unsigned int pil;
        unsigned int irq;
        int board, slot;
        int sbusl;
 
-       irq = 0;
-       while (sbi) {
-               if (!strcmp(sbi->name, "sbi"))
+       irq = real_irq;
+       while (bus) {
+               if (!strcmp(bus->name, "sbi")) {
+                       bus_connection = "io-unit";
+                       break;
+               }
+
+               if (!strcmp(bus->name, "bootbus")) {
+                       bus_connection = "cpu-unit";
                        break;
+               }
 
-               sbi = sbi->parent;
+               bus = bus->parent;
        }
-       if (!sbi)
+       if (!bus)
                goto err_out;
 
        regs = of_get_property(dp, "reg", NULL);
@@ -328,17 +366,19 @@ unsigned int sun4d_build_device_irq(struct platform_device *op,
        slot = regs->which_io;
 
        /*
-        *  If SBI's parent is not io-unit or the io-unit lacks
-        * a "board#" property, something is very wrong.
+        * If Bus nodes parent is not io-unit/cpu-unit or the io-unit/cpu-unit
+        * lacks a "board#" property, something is very wrong.
         */
-       if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
-               printk("%s: Error, parent is not io-unit.\n", sbi->full_name);
+       if (!bus->parent || strcmp(bus->parent->name, bus_connection)) {
+               printk(KERN_ERR "%s: Error, parent is not %s.\n",
+                       bus->full_name, bus_connection);
                goto err_out;
        }
-       io_unit = sbi->parent;
-       board = of_getintprop_default(io_unit, "board#", -1);
+       board_parent = bus->parent;
+       board = of_getintprop_default(board_parent, "board#", -1);
        if (board == -1) {
-               printk("%s: Error, lacks board# property.\n", io_unit->full_name);
+               printk(KERN_ERR "%s: Error, lacks board# property.\n",
+                       board_parent->full_name);
                goto err_out;
        }
 
@@ -348,29 +388,17 @@ unsigned int sun4d_build_device_irq(struct platform_device *op,
        else
                pil = real_irq;
 
-       irq = irq_alloc(real_irq, pil);
-       if (irq == 0)
-               goto err_out;
-
-       handler_data = irq_get_handler_data(irq);
-       if (unlikely(handler_data))
-               goto err_out;
-
-       handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC);
-       if (unlikely(!handler_data)) {
-               prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n");
-               prom_halt();
-       }
-       handler_data->cpuid    = board_to_cpu[board];
-       handler_data->real_irq = real_irq;
-       irq_set_chip_and_handler_name(irq, &sun4d_irq,
-                                     handle_level_irq, "level");
-       irq_set_handler_data(irq, handler_data);
-
+       irq = _sun4d_build_device_irq(real_irq, pil, board);
 err_out:
-       return real_irq;
+       return irq;
 }
 
+unsigned int sun4d_build_timer_irq(unsigned int board, unsigned int real_irq)
+{
+       return _sun4d_build_device_irq(real_irq, real_irq, board);
+}
+
+
 static void __init sun4d_fixup_trap_table(void)
 {
 #ifdef CONFIG_SMP
@@ -402,6 +430,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
        unsigned int irq;
        const u32 *reg;
        int err;
+       int board;
 
        dp = of_find_node_by_name(NULL, "cpu-unit");
        if (!dp) {
@@ -414,12 +443,19 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
         * bootbus.
         */
        reg = of_get_property(dp, "reg", NULL);
-       of_node_put(dp);
        if (!reg) {
                prom_printf("sun4d_init_timers: No reg property\n");
                prom_halt();
        }
 
+       board = of_getintprop_default(dp, "board#", -1);
+       if (board == -1) {
+               prom_printf("sun4d_init_timers: No board# property on cpu-unit\n");
+               prom_halt();
+       }
+
+       of_node_put(dp);
+
        res.start = reg[1];
        res.end = reg[2] - 1;
        res.flags = reg[0] & 0xff;
@@ -434,7 +470,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
 
        master_l10_counter = &sun4d_timers->l10_cur_count;
 
-       irq = sun4d_build_device_irq(NULL, SUN4D_TIMER_IRQ);
+       irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ);
        err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
        if (err) {
                prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
index 6db18c6..170cd8e 100644 (file)
@@ -109,7 +109,7 @@ asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compa
 
        default:
                return -ENOSYS;
-       };
+       }
 
        return -ENOSYS;
 }
index 96082d3..908b47a 100644 (file)
@@ -460,7 +460,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
                default:
                        err = -ENOSYS;
                        goto out;
-               };
+               }
        }
        if (call <= MSGCTL) {
                switch (call) {
@@ -481,7 +481,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
                default:
                        err = -ENOSYS;
                        goto out;
-               };
+               }
        }
        if (call <= SHMCTL) {
                switch (call) {
@@ -507,7 +507,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
                default:
                        err = -ENOSYS;
                        goto out;
-               };
+               }
        } else {
                err = -ENOSYS;
        }
index 2b8d54b..1db6b18 100644 (file)
@@ -708,7 +708,7 @@ static void sparc64_timer_setup(enum clock_event_mode mode,
        case CLOCK_EVT_MODE_UNUSED:
                WARN_ON(1);
                break;
-       };
+       }
 }
 
 static struct clock_event_device sparc64_clockevent = {
index 1ed547b..0cbdaa4 100644 (file)
@@ -1804,7 +1804,7 @@ static const char *sun4v_err_type_to_str(u32 type)
                return "warning resumable";
        default:
                return "unknown";
-       };
+       }
 }
 
 static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
index c752c4c..b2b019e 100644 (file)
@@ -211,7 +211,7 @@ static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr,
                default:
                        BUG();
                        break;
-               };
+               }
        }
        return __do_int_store(dst_addr, size, src_val, asi);
 }
@@ -328,7 +328,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
                case ASI_SNFL:
                        asi &= ~0x08;
                        break;
-               };
+               }
                switch (dir) {
                case load:
                        reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs);
@@ -351,7 +351,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
                                default:
                                        BUG();
                                        break;
-                               };
+                               }
                                *reg_addr = val_in;
                        }
                        break;
index 531d54f..489fc15 100644 (file)
@@ -176,7 +176,7 @@ static unsigned long index_to_estar_mode(unsigned int index)
 
        default:
                BUG();
-       };
+       }
 }
 
 static unsigned long index_to_divisor(unsigned int index)
@@ -199,7 +199,7 @@ static unsigned long index_to_divisor(unsigned int index)
 
        default:
                BUG();
-       };
+       }
 }
 
 static unsigned long estar_to_divisor(unsigned long estar)
@@ -224,7 +224,7 @@ static unsigned long estar_to_divisor(unsigned long estar)
                break;
        default:
                BUG();
-       };
+       }
 
        return ret;
 }
index 9a8ceb7..eb1624b 100644 (file)
@@ -71,7 +71,7 @@ static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg
                break;
        default:
                BUG();
-       };
+       }
 
        return ret;
 }
@@ -125,7 +125,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)
 
        default:
                BUG();
-       };
+       }
 
        reg = read_safari_cfg();
 
index aa6ac70..29348ea 100644 (file)
@@ -363,7 +363,7 @@ static int process_ver(struct vio_driver_state *vio, struct vio_ver_info *pkt)
 
        default:
                return handshake_failure(vio);
-       };
+       }
 }
 
 static int process_attr(struct vio_driver_state *vio, void *pkt)
index 9dfd2eb..3635771 100644 (file)
@@ -334,7 +334,7 @@ static void edge(struct pt_regs *regs, unsigned int insn, unsigned int opf)
                left = edge32_tab_l[(rs1 >> 2) & 0x1].left;
                right = edge32_tab_l[(rs2 >> 2) & 0x1].right;
                break;
-       };
+       }
 
        if ((rs1 & ~0x7UL) == (rs2 & ~0x7UL))
                rd_val = right & left;
@@ -360,7 +360,7 @@ static void edge(struct pt_regs *regs, unsigned int insn, unsigned int opf)
                tstate = regs->tstate & ~(TSTATE_XCC | TSTATE_ICC);
                regs->tstate = tstate | (ccr << 32UL);
        }
-       };
+       }
 }
 
 static void array(struct pt_regs *regs, unsigned int insn, unsigned int opf)
@@ -392,7 +392,7 @@ static void array(struct pt_regs *regs, unsigned int insn, unsigned int opf)
 
        case ARRAY32_OPF:
                rd_val <<= 2;
-       };
+       }
 
        store_reg(regs, rd_val, RD(insn));
 }
@@ -577,7 +577,7 @@ static void pformat(struct pt_regs *regs, unsigned int insn, unsigned int opf)
                *fpd_regaddr(f, RD(insn)) = rd_val;
                break;
        }
-       };
+       }
 }
 
 static void pmul(struct pt_regs *regs, unsigned int insn, unsigned int opf)
@@ -693,7 +693,7 @@ static void pmul(struct pt_regs *regs, unsigned int insn, unsigned int opf)
                *fpd_regaddr(f, RD(insn)) = rd_val;
                break;
        }
-       };
+       }
 }
 
 static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
@@ -786,7 +786,7 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
                                rd_val |= 1 << i;
                }
                break;
-       };
+       }
 
        maybe_flush_windows(0, 0, RD(insn), 0);
        store_reg(regs, rd_val, RD(insn));
@@ -885,7 +885,7 @@ int vis_emul(struct pt_regs *regs, unsigned int insn)
        case BSHUFFLE_OPF:
                bshuffle(regs, insn);
                break;
-       };
+       }
 
        regs->tpc = regs->tnpc;
        regs->tnpc += 4;
index b10ac4d..7543ddb 100644 (file)
@@ -135,7 +135,7 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
 
        default:
                break;
-       };
+       }
 
        memset(&regs, 0, sizeof (regs));
        regs.pc = pc;
index ca21732..7b00de6 100644 (file)
@@ -340,7 +340,7 @@ void __init paging_init(void)
                prom_printf("paging_init: sparc_cpu_model = %d\n", sparc_cpu_model);
                prom_printf("paging_init: Halting...\n");
                prom_halt();
-       };
+       }
 
        /* Initialize the protection map with non-constant, MMU dependent values. */
        protection_map[0] = PAGE_NONE;
index e10cd03..3fd8e18 100644 (file)
@@ -1625,7 +1625,7 @@ static void __init sun4v_ktsb_init(void)
                ktsb_descr[0].pgsz_idx = HV_PGSZ_IDX_4MB;
                ktsb_descr[0].pgsz_mask = HV_PGSZ_MASK_4MB;
                break;
-       };
+       }
 
        ktsb_descr[0].assoc = 1;
        ktsb_descr[0].num_ttes = KERNEL_TSB_NENTRIES;
@@ -2266,7 +2266,7 @@ unsigned long pte_sz_bits(unsigned long sz)
                        return _PAGE_SZ512K_4V;
                case 4 * 1024 * 1024:
                        return _PAGE_SZ4MB_4V;
-               };
+               }
        } else {
                switch (sz) {
                case 8 * 1024:
@@ -2278,7 +2278,7 @@ unsigned long pte_sz_bits(unsigned long sz)
                        return _PAGE_SZ512K_4U;
                case 4 * 1024 * 1024:
                        return _PAGE_SZ4MB_4U;
-               };
+               }
        }
 }
 
index fe09fd8..cbef74e 100644 (file)
@@ -1665,7 +1665,7 @@ static void __init init_swift(void)
        default:
                srmmu_modtype = Swift_ok;
                break;
-       };
+       }
 
        BTFIXUPSET_CALL(flush_cache_all, swift_flush_cache_all, BTFIXUPCALL_NORM);
        BTFIXUPSET_CALL(flush_cache_mm, swift_flush_cache_mm, BTFIXUPCALL_NORM);
@@ -2069,7 +2069,7 @@ static void __init get_srmmu_type(void)
                        /* Some other Cypress revision, assume a 605. */
                        init_cypress_605(mod_rev);
                        break;
-               };
+               }
                return;
        }
        
index a2350b5..1cf4f19 100644 (file)
@@ -318,7 +318,7 @@ void __init sun4c_probe_vac(void)
                prom_printf("probe_vac: Didn't expect vac-linesize of %d, halting\n",
                            sun4c_vacinfo.linesize);
                prom_halt();
-       };
+       }
 
        sun4c_flush_all();
        sun4c_enable_vac();
@@ -364,7 +364,7 @@ static void __init patch_kernel_fault_handler(void)
                        prom_printf("Unhandled number of segmaps: %d\n",
                                    num_segmaps);
                        prom_halt();
-       };
+       }
        switch (num_contexts) {
                case 8:
                        /* Default, nothing to do. */
@@ -377,7 +377,7 @@ static void __init patch_kernel_fault_handler(void)
                        prom_printf("Unhandled number of contexts: %d\n",
                                    num_contexts);
                        prom_halt();
-       };
+       }
 
        if (sun4c_vacinfo.do_hwflushes != 0) {
                PATCH_INSN(vac_hwflush_patch1_on, vac_hwflush_patch1);
@@ -394,7 +394,7 @@ static void __init patch_kernel_fault_handler(void)
                        prom_printf("Impossible VAC linesize %d, halting...\n",
                                    sun4c_vacinfo.linesize);
                        prom_halt();
-               };
+               }
        }
 }
 
index 9484615..a5f51b2 100644 (file)
@@ -180,7 +180,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
                printk(KERN_ERR "TSB[%s:%d]: Impossible TSB size %lu, killing process.\n",
                       current->comm, current->pid, tsb_bytes);
                do_exit(SIGSEGV);
-       };
+       }
        tte |= pte_sz_bits(page_sz);
 
        if (tlb_type == cheetah_plus || tlb_type == hypervisor) {
@@ -215,7 +215,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
 #endif
                default:
                        BUG();
-               };
+               }
                hp->assoc = 1;
                hp->num_ttes = tsb_bytes / 16;
                hp->ctx_idx = 0;
@@ -230,7 +230,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
 #endif
                default:
                        BUG();
-               };
+               }
                hp->tsb_base = tsb_paddr;
                hp->resv = 0;
        }
index b05e3db..a00f47b 100644 (file)
@@ -38,7 +38,7 @@ static int prom_nbputchar(const char *buf)
                break;
        default:
                break;
-       };
+       }
        restore_current();
        spin_unlock_irqrestore(&prom_lock, flags);
        return i; /* Ugh, we could spin forever on unsupported proms ;( */
index 0a601b3..26c64ce 100644 (file)
@@ -53,7 +53,7 @@ void __init prom_init(struct linux_romvec *rp)
                            romvec->pv_romvers);
                prom_halt();
                break;
-       };
+       }
 
        prom_rev = romvec->pv_plugin_revision;
        prom_prev = romvec->pv_printrev;
index 97c44c9..0da8256 100644 (file)
@@ -35,7 +35,7 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha
        case PROM_V3:
                ret = (*(romvec->v3_cpustart))(cpunode, (int) ctable_reg, ctx, pc);
                break;
-       };
+       }
        restore_current();
        spin_unlock_irqrestore(&prom_lock, flags);
 
index d3a3032..e57dcce 100644 (file)
@@ -231,10 +231,6 @@ config PUV3_PWM
        help
          Enable support for NB0916 PWM controllers
 
-config PUV3_RTC
-       tristate "PKUnity v3 RTC Support"
-       depends on !ARCH_FPGA
-
 if PUV3_NB0916
 
 menu "PKUnity NetBook-0916 Features"
index 76a8bee..6af4bc4 100644 (file)
@@ -40,42 +40,10 @@ core-y                      += arch/unicore32/mm/
 
 libs-y                 += arch/unicore32/lib/
 
-ASM_GENERATED_DIR      := $(srctree)/arch/unicore32/include/generated
-LINUXINCLUDE           += -I$(ASM_GENERATED_DIR)
-
-ASM_GENERIC_HEADERS    := atomic.h auxvec.h
-ASM_GENERIC_HEADERS    += bitsperlong.h bug.h bugs.h
-ASM_GENERIC_HEADERS    += cputime.h current.h
-ASM_GENERIC_HEADERS    += device.h div64.h
-ASM_GENERIC_HEADERS    += emergency-restart.h errno.h
-ASM_GENERIC_HEADERS    += fb.h fcntl.h ftrace.h futex.h
-ASM_GENERIC_HEADERS    += hardirq.h hw_irq.h
-ASM_GENERIC_HEADERS    += ioctl.h ioctls.h ipcbuf.h irq_regs.h
-ASM_GENERIC_HEADERS    += kdebug.h kmap_types.h
-ASM_GENERIC_HEADERS    += local.h
-ASM_GENERIC_HEADERS    += mman.h module.h msgbuf.h
-ASM_GENERIC_HEADERS    += param.h parport.h percpu.h poll.h posix_types.h
-ASM_GENERIC_HEADERS    += resource.h
-ASM_GENERIC_HEADERS    += scatterlist.h sections.h segment.h sembuf.h serial.h
-ASM_GENERIC_HEADERS    += setup.h shmbuf.h shmparam.h
-ASM_GENERIC_HEADERS    += siginfo.h signal.h sizes.h
-ASM_GENERIC_HEADERS    += socket.h sockios.h stat.h statfs.h swab.h syscalls.h
-ASM_GENERIC_HEADERS    += termbits.h termios.h topology.h types.h
-ASM_GENERIC_HEADERS    += ucontext.h unaligned.h user.h
-ASM_GENERIC_HEADERS    += vga.h
-ASM_GENERIC_HEADERS    += xor.h
-
-archprepare:
-ifneq ($(ASM_GENERATED_DIR), $(wildcard $(ASM_GENERATED_DIR)))
-       $(Q)mkdir -p $(ASM_GENERATED_DIR)/asm
-       $(Q)$(foreach a, $(ASM_GENERIC_HEADERS),        \
-               echo '#include <asm-generic/$a>'        \
-                       > $(ASM_GENERATED_DIR)/asm/$a; )
-endif
-
 boot                   := arch/unicore32/boot
 
-# Default target when executing plain make
+# Default defconfig and target when executing plain make
+KBUILD_DEFCONFIG       := $(ARCH)_defconfig
 KBUILD_IMAGE           := zImage
 
 all:   $(KBUILD_IMAGE)
@@ -83,8 +51,6 @@ all:  $(KBUILD_IMAGE)
 zImage Image uImage: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
-MRPROPER_DIRS          += $(ASM_GENERATED_DIR)
-
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
index 9537342..b0954a2 100644 (file)
@@ -59,7 +59,7 @@ $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head.o $(obj)/piggy.o \
 # We now have a PIC decompressor implementation.  Decompressors running
 # from RAM should not define ZTEXTADDR.  Decompressors running directly
 # from ROM or Flash must define ZTEXTADDR (preferably via the config)
-ZTEXTADDR      := 0
+ZTEXTADDR      := 0x03000000
 ZBSSADDR       := ALIGN(4)
 
 SEDFLAGS_lds   = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/debug_defconfig
deleted file mode 100644 (file)
index b5fbde9..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-### General setup
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCALVERSION="-debug"
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_HOTPLUG=y
-#      Initial RAM filesystem and RAM disk (initramfs/initrd) support
-#CONFIG_BLK_DEV_INITRD=y
-#CONFIG_INITRAMFS_SOURCE="arch/unicore/ramfs/ramfs_config"
-
-### Enable loadable module support
-CONFIG_MODULES=n
-CONFIG_MODULE_UNLOAD=y
-
-### System Type
-CONFIG_ARCH_PUV3=y
-#      Board Selection
-CONFIG_PUV3_NB0916=y
-#      Processor Features
-CONFIG_CPU_DCACHE_LINE_DISABLE=y
-CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE=n
-
-### Bus support
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY=n
-
-### Boot options
-#      for debug, adding: earlyprintk=ocd,keep initcall_debug
-#      others support: test_suspend=mem root=/dev/sda
-#      hibernate support: resume=/dev/sda3
-CONFIG_CMDLINE="earlyprintk=ocd,keep ignore_loglevel"
-# TODO: mem=512M video=unifb:1024x600-16@75
-# for nfs: root=/dev/nfs rw nfsroot=192.168.10.88:/home/udb/nfs/,rsize=1024,wsize=1024
-#      ip=192.168.10.83:192.168.10.88:192.168.10.1:255.255.255.0::eth0:off
-CONFIG_CMDLINE_FORCE=y
-
-### Power management options
-CONFIG_PM=y
-CONFIG_HIBERNATION=y
-CONFIG_PM_STD_PARTITION="/dev/sda3"
-CONFIG_CPU_FREQ=n
-CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
-
-### Networking support
-CONFIG_NET=y
-#      Networking options
-CONFIG_PACKET=m
-CONFIG_UNIX=m
-#      TCP/IP networking
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IPV6=n
-#      Wireless
-CONFIG_WIRELESS=y
-CONFIG_WIRELESS_EXT=y
-CONFIG_MAC80211=m
-
-### PKUnity SoC Features
-CONFIG_USB_WLAN_HED_AQ3=n
-CONFIG_USB_CMMB_INNOFIDEI=n
-CONFIG_I2C_BATTERY_BQ27200=n
-CONFIG_I2C_EEPROM_AT24=n
-CONFIG_LCD_BACKLIGHT=n
-
-CONFIG_PUV3_RTC=y
-CONFIG_PUV3_UMAL=y
-CONFIG_PUV3_MUSB=n
-CONFIG_PUV3_AC97=n
-CONFIG_PUV3_NAND=n
-CONFIG_PUV3_MMC=n
-CONFIG_PUV3_UART=n
-
-### Device Drivers
-#      Memory Technology Device (MTD) support
-CONFIG_MTD=m
-CONFIG_MTD_UBI=m
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=m
-CONFIG_MTD_BLKDEVS=m
-#      RAM/ROM/Flash chip drivers
-CONFIG_MTD_CFI=m
-CONFIG_MTD_JEDECPROBE=m
-CONFIG_MTD_CFI_AMDSTD=m
-#      Mapping drivers for chip access
-CONFIG_MTD_PHYSMAP=m
-
-#      Block devices
-CONFIG_BLK_DEV_LOOP=m
-
-#      SCSI device support
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-
-#      Serial ATA (prod) and Parallel ATA (experimental) drivers
-CONFIG_ATA=y
-CONFIG_SATA_VIA=y
-
-#      Network device support
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_NETDEV_1000=y
-#      Wireless LAN
-CONFIG_WLAN_80211=n
-CONFIG_RT2X00=n
-CONFIG_RT73USB=n
-
-#      Input device support
-CONFIG_INPUT_EVDEV=m
-#      Keyboards
-CONFIG_KEYBOARD_GPIO=m
-
-#      I2C support
-CONFIG_I2C=y
-CONFIG_I2C_PUV3=y
-
-#      Hardware Monitoring support
-#CONFIG_SENSORS_LM75=m
-#      Generic Thermal sysfs driver
-#CONFIG_THERMAL=m
-#CONFIG_THERMAL_HWMON=y
-
-#      Multimedia support
-CONFIG_MEDIA_SUPPORT=n
-CONFIG_VIDEO_DEV=n
-CONFIG_USB_VIDEO_CLASS=n
-
-#      Graphics support
-CONFIG_FB=y
-CONFIG_FB_PUV3_UNIGFX=y
-#      Console display driver support
-CONFIG_VGA_CONSOLE=n
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-#      Bootup logo
-CONFIG_LOGO=n
-
-#      Sound card support
-CONFIG_SOUND=m
-#      Advanced Linux Sound Architecture
-CONFIG_SND=m
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-
-#      USB support
-CONFIG_USB_ARCH_HAS_HCD=n
-CONFIG_USB=n
-CONFIG_USB_DEVICEFS=n
-CONFIG_USB_PRINTER=n
-CONFIG_USB_STORAGE=n
-#      Inventra Highspeed Dual Role Controller
-CONFIG_USB_MUSB_HDRC=n
-
-#      LED Support
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-#      LED Triggers
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_IDE_DISK=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-
-#      Real Time Clock
-CONFIG_RTC_LIB=m
-CONFIG_RTC_CLASS=m
-
-### File systems
-CONFIG_EXT2_FS=m
-CONFIG_EXT3_FS=y
-CONFIG_EXT4_FS=y
-CONFIG_FUSE_FS=m
-#      CD-ROM/DVD Filesystems
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=m
-#      DOS/FAT/NT Filesystems
-CONFIG_VFAT_FS=m
-#      Pseudo filesystems
-CONFIG_PROC_FS=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-#      Miscellaneous filesystems
-CONFIG_MISC_FILESYSTEMS=y
-CONFIG_JFFS2_FS=m
-CONFIG_UBIFS_FS=m
-#      Network File Systems
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-#      Partition Types
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MSDOS_PARTITION=y
-#      Native language support
-CONFIG_NLS=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_UTF8=m
-
-### Kernel hacking
-CONFIG_FRAME_WARN=8096
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_PROVE_LOCKING=n
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_LL=y
-
diff --git a/arch/unicore32/configs/unicore32_defconfig b/arch/unicore32/configs/unicore32_defconfig
new file mode 100644 (file)
index 0000000..c9dd319
--- /dev/null
@@ -0,0 +1,215 @@
+### General setup
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="-unicore32"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_HOTPLUG=y
+#      Initial RAM filesystem and RAM disk (initramfs/initrd) support
+#CONFIG_BLK_DEV_INITRD=y
+#CONFIG_INITRAMFS_SOURCE="arch/unicore/ramfs/ramfs_config"
+
+### Enable loadable module support
+CONFIG_MODULES=n
+CONFIG_MODULE_UNLOAD=y
+
+### System Type
+CONFIG_ARCH_PUV3=y
+#      Board Selection
+CONFIG_PUV3_NB0916=y
+#      Processor Features
+CONFIG_CPU_DCACHE_LINE_DISABLE=y
+CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE=n
+
+### Bus support
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY=n
+
+### Boot options
+#      for debug, adding: earlyprintk=ocd,keep initcall_debug
+#      others support: test_suspend=mem root=/dev/sda
+#      hibernate support: resume=/dev/sda3
+CONFIG_CMDLINE="earlyprintk=ocd,keep ignore_loglevel"
+# TODO: mem=512M video=unifb:1024x600-16@75
+# for nfs: root=/dev/nfs rw nfsroot=192.168.10.88:/home/udb/nfs/,rsize=1024,wsize=1024
+#      ip=192.168.10.83:192.168.10.88:192.168.10.1:255.255.255.0::eth0:off
+CONFIG_CMDLINE_FORCE=y
+
+### Power management options
+CONFIG_PM=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION="/dev/sda3"
+CONFIG_CPU_FREQ=n
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+
+### Networking support
+CONFIG_NET=y
+#      Networking options
+CONFIG_PACKET=m
+CONFIG_UNIX=m
+#      TCP/IP networking
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IPV6=n
+#      Wireless
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_MAC80211=m
+
+### PKUnity SoC Features
+CONFIG_USB_WLAN_HED_AQ3=n
+CONFIG_USB_CMMB_INNOFIDEI=n
+CONFIG_I2C_BATTERY_BQ27200=n
+CONFIG_I2C_EEPROM_AT24=n
+CONFIG_LCD_BACKLIGHT=n
+
+CONFIG_PUV3_UMAL=y
+CONFIG_PUV3_MUSB=n
+CONFIG_PUV3_AC97=n
+CONFIG_PUV3_NAND=n
+CONFIG_PUV3_MMC=n
+CONFIG_PUV3_UART=n
+
+### Device Drivers
+#      Memory Technology Device (MTD) support
+CONFIG_MTD=m
+CONFIG_MTD_UBI=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+#      RAM/ROM/Flash chip drivers
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_CFI_AMDSTD=m
+#      Mapping drivers for chip access
+CONFIG_MTD_PHYSMAP=m
+
+#      Block devices
+CONFIG_BLK_DEV_LOOP=m
+
+#      SCSI device support
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=m
+
+#      Serial ATA (prod) and Parallel ATA (experimental) drivers
+CONFIG_ATA=y
+CONFIG_SATA_VIA=y
+
+#      Network device support
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_NETDEV_1000=y
+#      Wireless LAN
+CONFIG_WLAN_80211=n
+CONFIG_RT2X00=n
+CONFIG_RT73USB=n
+
+#      Input device support
+CONFIG_INPUT_EVDEV=m
+#      Keyboards
+CONFIG_KEYBOARD_GPIO=m
+
+#      I2C support
+CONFIG_I2C=y
+CONFIG_I2C_PUV3=y
+
+#      Hardware Monitoring support
+#CONFIG_SENSORS_LM75=m
+#      Generic Thermal sysfs driver
+#CONFIG_THERMAL=m
+#CONFIG_THERMAL_HWMON=y
+
+#      Multimedia support
+CONFIG_MEDIA_SUPPORT=n
+CONFIG_VIDEO_DEV=n
+CONFIG_USB_VIDEO_CLASS=n
+
+#      Graphics support
+CONFIG_FB=y
+CONFIG_FB_PUV3_UNIGFX=y
+#      Console display driver support
+CONFIG_VGA_CONSOLE=n
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+#      Bootup logo
+CONFIG_LOGO=n
+
+#      Sound card support
+CONFIG_SOUND=m
+#      Advanced Linux Sound Architecture
+CONFIG_SND=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+
+#      USB support
+CONFIG_USB_ARCH_HAS_HCD=n
+CONFIG_USB=n
+CONFIG_USB_DEVICEFS=n
+CONFIG_USB_PRINTER=n
+CONFIG_USB_STORAGE=n
+#      Inventra Highspeed Dual Role Controller
+CONFIG_USB_MUSB_HDRC=n
+
+#      LED Support
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+#      LED Triggers
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+
+#      Real Time Clock
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PUV3=y
+
+### File systems
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=m
+#      CD-ROM/DVD Filesystems
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=m
+#      DOS/FAT/NT Filesystems
+CONFIG_VFAT_FS=m
+#      Pseudo filesystems
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+#      Miscellaneous filesystems
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_JFFS2_FS=m
+CONFIG_UBIFS_FS=m
+#      Network File Systems
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+#      Partition Types
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MSDOS_PARTITION=y
+#      Native language support
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_UTF8=m
+
+### Kernel hacking
+CONFIG_FRAME_WARN=8096
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_PROVE_LOCKING=n
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_LL=y
+
index b200fda..ca113d6 100644 (file)
@@ -1,2 +1,61 @@
 include include/asm-generic/Kbuild.asm
 
+generic-y += atomic.h
+generic-y += auxvec.h
+generic-y += bitsperlong.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fb.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += futex.h
+generic-y += hardirq.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += local.h
+generic-y += mman.h
+generic-y += module.h
+generic-y += msgbuf.h
+generic-y += param.h
+generic-y += parport.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += sembuf.h
+generic-y += serial.h
+generic-y += setup.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += siginfo.h
+generic-y += signal.h
+generic-y += sizes.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += stat.h
+generic-y += statfs.h
+generic-y += swab.h
+generic-y += syscalls.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += types.h
+generic-y += ucontext.h
+generic-y += unaligned.h
+generic-y += user.h
+generic-y += vga.h
+generic-y += xor.h
index ec23a2f..aeb0f18 100644 (file)
@@ -16,7 +16,6 @@ obj-$(CONFIG_UNICORE_FPU_F64) += fpu-ucf64.o
 obj-$(CONFIG_ARCH_PUV3)                += clock.o irq.o time.o
 
 obj-$(CONFIG_PUV3_GPIO)                += gpio.o
-obj-$(CONFIG_PUV3_RTC)         += rtc.o
 obj-$(CONFIG_PUV3_PWM)         += pwm.o
 obj-$(CONFIG_PUV3_PM)          += pm.o sleep.o
 obj-$(CONFIG_HIBERNATION)      += hibernate.o hibernate_asm.o
diff --git a/arch/unicore32/kernel/rtc.c b/arch/unicore32/kernel/rtc.c
deleted file mode 100644 (file)
index 8cad70b..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * linux/arch/unicore32/kernel/rtc.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- *     Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
- *     Copyright (C) 2001-2010 Guan Xuetao
- *
- * 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/module.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/rtc.h>
-#include <linux/bcd.h>
-#include <linux/clk.h>
-#include <linux/log2.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-static struct resource *puv3_rtc_mem;
-
-static int puv3_rtc_alarmno = IRQ_RTCAlarm;
-static int puv3_rtc_tickno  = IRQ_RTC;
-
-static DEFINE_SPINLOCK(puv3_rtc_pie_lock);
-
-/* IRQ Handlers */
-
-static irqreturn_t puv3_rtc_alarmirq(int irq, void *id)
-{
-       struct rtc_device *rdev = id;
-
-       writel(readl(RTC_RTSR) | RTC_RTSR_AL, RTC_RTSR);
-       rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t puv3_rtc_tickirq(int irq, void *id)
-{
-       struct rtc_device *rdev = id;
-
-       writel(readl(RTC_RTSR) | RTC_RTSR_HZ, RTC_RTSR);
-       rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
-       return IRQ_HANDLED;
-}
-
-/* Update control registers */
-static void puv3_rtc_setaie(int to)
-{
-       unsigned int tmp;
-
-       pr_debug("%s: aie=%d\n", __func__, to);
-
-       tmp = readl(RTC_RTSR) & ~RTC_RTSR_ALE;
-
-       if (to)
-               tmp |= RTC_RTSR_ALE;
-
-       writel(tmp, RTC_RTSR);
-}
-
-static int puv3_rtc_setpie(struct device *dev, int enabled)
-{
-       unsigned int tmp;
-
-       pr_debug("%s: pie=%d\n", __func__, enabled);
-
-       spin_lock_irq(&puv3_rtc_pie_lock);
-       tmp = readl(RTC_RTSR) & ~RTC_RTSR_HZE;
-
-       if (enabled)
-               tmp |= RTC_RTSR_HZE;
-
-       writel(tmp, RTC_RTSR);
-       spin_unlock_irq(&puv3_rtc_pie_lock);
-
-       return 0;
-}
-
-/* Time read/write */
-
-static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
-{
-       rtc_time_to_tm(readl(RTC_RCNR), rtc_tm);
-
-       pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
-                rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
-                rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
-
-       return 0;
-}
-
-static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm)
-{
-       unsigned long rtc_count = 0;
-
-       pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",
-                tm->tm_year, tm->tm_mon, tm->tm_mday,
-                tm->tm_hour, tm->tm_min, tm->tm_sec);
-
-       rtc_tm_to_time(tm, &rtc_count);
-       writel(rtc_count, RTC_RCNR);
-
-       return 0;
-}
-
-static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
-       struct rtc_time *alm_tm = &alrm->time;
-
-       rtc_time_to_tm(readl(RTC_RTAR), alm_tm);
-
-       alrm->enabled = readl(RTC_RTSR) & RTC_RTSR_ALE;
-
-       pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
-                alrm->enabled,
-                alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
-                alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
-
-       return 0;
-}
-
-static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
-       struct rtc_time *tm = &alrm->time;
-       unsigned long rtcalarm_count = 0;
-
-       pr_debug("puv3_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
-                alrm->enabled,
-                tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
-                tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
-
-       rtc_tm_to_time(tm, &rtcalarm_count);
-       writel(rtcalarm_count, RTC_RTAR);
-
-       puv3_rtc_setaie(alrm->enabled);
-
-       if (alrm->enabled)
-               enable_irq_wake(puv3_rtc_alarmno);
-       else
-               disable_irq_wake(puv3_rtc_alarmno);
-
-       return 0;
-}
-
-static int puv3_rtc_proc(struct device *dev, struct seq_file *seq)
-{
-       seq_printf(seq, "periodic_IRQ\t: %s\n",
-                    (readl(RTC_RTSR) & RTC_RTSR_HZE) ? "yes" : "no");
-       return 0;
-}
-
-static int puv3_rtc_open(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
-       int ret;
-
-       ret = request_irq(puv3_rtc_alarmno, puv3_rtc_alarmirq,
-                         IRQF_DISABLED,  "pkunity-rtc alarm", rtc_dev);
-
-       if (ret) {
-               dev_err(dev, "IRQ%d error %d\n", puv3_rtc_alarmno, ret);
-               return ret;
-       }
-
-       ret = request_irq(puv3_rtc_tickno, puv3_rtc_tickirq,
-                         IRQF_DISABLED,  "pkunity-rtc tick", rtc_dev);
-
-       if (ret) {
-               dev_err(dev, "IRQ%d error %d\n", puv3_rtc_tickno, ret);
-               goto tick_err;
-       }
-
-       return ret;
-
- tick_err:
-       free_irq(puv3_rtc_alarmno, rtc_dev);
-       return ret;
-}
-
-static void puv3_rtc_release(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
-
-       /* do not clear AIE here, it may be needed for wake */
-
-       puv3_rtc_setpie(dev, 0);
-       free_irq(puv3_rtc_alarmno, rtc_dev);
-       free_irq(puv3_rtc_tickno, rtc_dev);
-}
-
-static const struct rtc_class_ops puv3_rtcops = {
-       .open           = puv3_rtc_open,
-       .release        = puv3_rtc_release,
-       .read_time      = puv3_rtc_gettime,
-       .set_time       = puv3_rtc_settime,
-       .read_alarm     = puv3_rtc_getalarm,
-       .set_alarm      = puv3_rtc_setalarm,
-       .proc           = puv3_rtc_proc,
-};
-
-static void puv3_rtc_enable(struct platform_device *pdev, int en)
-{
-       if (!en) {
-               writel(readl(RTC_RTSR) & ~RTC_RTSR_HZE, RTC_RTSR);
-       } else {
-               /* re-enable the device, and check it is ok */
-
-               if ((readl(RTC_RTSR) & RTC_RTSR_HZE) == 0) {
-                       dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
-                       writel(readl(RTC_RTSR) | RTC_RTSR_HZE, RTC_RTSR);
-               }
-       }
-}
-
-static int puv3_rtc_remove(struct platform_device *dev)
-{
-       struct rtc_device *rtc = platform_get_drvdata(dev);
-
-       platform_set_drvdata(dev, NULL);
-       rtc_device_unregister(rtc);
-
-       puv3_rtc_setpie(&dev->dev, 0);
-       puv3_rtc_setaie(0);
-
-       release_resource(puv3_rtc_mem);
-       kfree(puv3_rtc_mem);
-
-       return 0;
-}
-
-static int puv3_rtc_probe(struct platform_device *pdev)
-{
-       struct rtc_device *rtc;
-       struct resource *res;
-       int ret;
-
-       pr_debug("%s: probe=%p\n", __func__, pdev);
-
-       /* find the IRQs */
-
-       puv3_rtc_tickno = platform_get_irq(pdev, 1);
-       if (puv3_rtc_tickno < 0) {
-               dev_err(&pdev->dev, "no irq for rtc tick\n");
-               return -ENOENT;
-       }
-
-       puv3_rtc_alarmno = platform_get_irq(pdev, 0);
-       if (puv3_rtc_alarmno < 0) {
-               dev_err(&pdev->dev, "no irq for alarm\n");
-               return -ENOENT;
-       }
-
-       pr_debug("PKUnity_rtc: tick irq %d, alarm irq %d\n",
-                puv3_rtc_tickno, puv3_rtc_alarmno);
-
-       /* get the memory region */
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to get memory region resource\n");
-               return -ENOENT;
-       }
-
-       puv3_rtc_mem = request_mem_region(res->start,
-                                        res->end-res->start+1,
-                                        pdev->name);
-
-       if (puv3_rtc_mem == NULL) {
-               dev_err(&pdev->dev, "failed to reserve memory region\n");
-               ret = -ENOENT;
-               goto err_nores;
-       }
-
-       puv3_rtc_enable(pdev, 1);
-
-       /* register RTC and exit */
-
-       rtc = rtc_device_register("pkunity", &pdev->dev, &puv3_rtcops,
-                                 THIS_MODULE);
-
-       if (IS_ERR(rtc)) {
-               dev_err(&pdev->dev, "cannot attach rtc\n");
-               ret = PTR_ERR(rtc);
-               goto err_nortc;
-       }
-
-       /* platform setup code should have handled this; sigh */
-       if (!device_can_wakeup(&pdev->dev))
-               device_init_wakeup(&pdev->dev, 1);
-
-       platform_set_drvdata(pdev, rtc);
-       return 0;
-
- err_nortc:
-       puv3_rtc_enable(pdev, 0);
-       release_resource(puv3_rtc_mem);
-
- err_nores:
-       return ret;
-}
-
-#ifdef CONFIG_PM
-
-/* RTC Power management control */
-
-static int ticnt_save;
-
-static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       /* save RTAR for anyone using periodic interrupts */
-       ticnt_save = readl(RTC_RTAR);
-       puv3_rtc_enable(pdev, 0);
-       return 0;
-}
-
-static int puv3_rtc_resume(struct platform_device *pdev)
-{
-       puv3_rtc_enable(pdev, 1);
-       writel(ticnt_save, RTC_RTAR);
-       return 0;
-}
-#else
-#define puv3_rtc_suspend NULL
-#define puv3_rtc_resume  NULL
-#endif
-
-static struct platform_driver puv3_rtcdrv = {
-       .probe          = puv3_rtc_probe,
-       .remove         = __devexit_p(puv3_rtc_remove),
-       .suspend        = puv3_rtc_suspend,
-       .resume         = puv3_rtc_resume,
-       .driver         = {
-               .name   = "PKUnity-v3-RTC",
-               .owner  = THIS_MODULE,
-       }
-};
-
-static char __initdata banner[] = "PKUnity-v3 RTC, (c) 2009 PKUnity Co.\n";
-
-static int __init puv3_rtc_init(void)
-{
-       printk(banner);
-       return platform_driver_register(&puv3_rtcdrv);
-}
-
-static void __exit puv3_rtc_exit(void)
-{
-       platform_driver_unregister(&puv3_rtcdrv);
-}
-
-module_init(puv3_rtc_init);
-module_exit(puv3_rtc_exit);
-
-MODULE_DESCRIPTION("RTC Driver for the PKUnity v3 chip");
-MODULE_AUTHOR("Hu Dongliang");
-MODULE_LICENSE("GPL v2");
-
index 9bf7f7a..77e407e 100644 (file)
@@ -30,7 +30,7 @@ SECTIONS
        HEAD_TEXT_SECTION
        INIT_TEXT_SECTION(PAGE_SIZE)
        INIT_DATA_SECTION(16)
-       PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
+       PERCPU_SECTION(L1_CACHE_BYTES)
        __init_end = .;
 
        _stext = .;
index cd8cbeb..7c3a95e 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/proto.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
+#include <asm/dma.h>
 #include <asm/amd_iommu_proto.h>
 #include <asm/amd_iommu_types.h>
 #include <asm/amd_iommu.h>
@@ -154,6 +155,10 @@ static int iommu_init_device(struct device *dev)
        pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff);
        if (pdev)
                dev_data->alias = &pdev->dev;
+       else {
+               kfree(dev_data);
+               return -ENOTSUPP;
+       }
 
        atomic_set(&dev_data->bind, 0);
 
@@ -163,6 +168,20 @@ static int iommu_init_device(struct device *dev)
        return 0;
 }
 
+static void iommu_ignore_device(struct device *dev)
+{
+       u16 devid, alias;
+
+       devid = get_device_id(dev);
+       alias = amd_iommu_alias_table[devid];
+
+       memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry));
+       memset(&amd_iommu_dev_table[alias], 0, sizeof(struct dev_table_entry));
+
+       amd_iommu_rlookup_table[devid] = NULL;
+       amd_iommu_rlookup_table[alias] = NULL;
+}
+
 static void iommu_uninit_device(struct device *dev)
 {
        kfree(dev->archdata.iommu);
@@ -192,7 +211,9 @@ int __init amd_iommu_init_devices(void)
                        continue;
 
                ret = iommu_init_device(&pdev->dev);
-               if (ret)
+               if (ret == -ENOTSUPP)
+                       iommu_ignore_device(&pdev->dev);
+               else if (ret)
                        goto out_free;
        }
 
@@ -2383,6 +2404,23 @@ static struct dma_map_ops amd_iommu_dma_ops = {
        .dma_supported = amd_iommu_dma_supported,
 };
 
+static unsigned device_dma_ops_init(void)
+{
+       struct pci_dev *pdev = NULL;
+       unsigned unhandled = 0;
+
+       for_each_pci_dev(pdev) {
+               if (!check_device(&pdev->dev)) {
+                       unhandled += 1;
+                       continue;
+               }
+
+               pdev->dev.archdata.dma_ops = &amd_iommu_dma_ops;
+       }
+
+       return unhandled;
+}
+
 /*
  * The function which clues the AMD IOMMU driver into dma_ops.
  */
@@ -2395,7 +2433,7 @@ void __init amd_iommu_init_api(void)
 int __init amd_iommu_init_dma_ops(void)
 {
        struct amd_iommu *iommu;
-       int ret;
+       int ret, unhandled;
 
        /*
         * first allocate a default protection domain for every IOMMU we
@@ -2421,7 +2459,11 @@ int __init amd_iommu_init_dma_ops(void)
        swiotlb = 0;
 
        /* Make the driver finally visible to the drivers */
-       dma_ops = &amd_iommu_dma_ops;
+       unhandled = device_dma_ops_init();
+       if (unhandled && max_pfn > MAX_DMA32_PFN) {
+               /* There are unhandled devices - initialize swiotlb for them */
+               swiotlb = 1;
+       }
 
        amd_iommu_stats_init();
 
index 9179c21..bfc8453 100644 (file)
@@ -731,8 +731,8 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
 {
        u8 *p = (u8 *)h;
        u8 *end = p, flags = 0;
-       u16 dev_i, devid = 0, devid_start = 0, devid_to = 0;
-       u32 ext_flags = 0;
+       u16 devid = 0, devid_start = 0, devid_to = 0;
+       u32 dev_i, ext_flags = 0;
        bool alias = false;
        struct ivhd_entry *e;
 
@@ -887,7 +887,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
 /* Initializes the device->iommu mapping for the driver */
 static int __init init_iommu_devices(struct amd_iommu *iommu)
 {
-       u16 i;
+       u32 i;
 
        for (i = iommu->first_device; i <= iommu->last_device; ++i)
                set_iommu_for_device(iommu, i);
@@ -1177,7 +1177,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table)
  */
 static void init_device_table(void)
 {
-       u16 devid;
+       u32 devid;
 
        for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) {
                set_dev_entry_bit(devid, DEV_ENTRY_VALID);
index 8d12878..a3d0dc5 100644 (file)
@@ -245,7 +245,6 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
 {
        set_user_gs(regs, 0);
        regs->fs                = 0;
-       set_fs(USER_DS);
        regs->ds                = __USER_DS;
        regs->es                = __USER_DS;
        regs->ss                = __USER_DS;
index 6c9dd92..ca6f7ab 100644 (file)
@@ -338,7 +338,6 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip,
        regs->cs                = _cs;
        regs->ss                = _ss;
        regs->flags             = X86_EFLAGS_IF;
-       set_fs(USER_DS);
        /*
         * Free the old FP and other extended state
         */
index d6e2477..6df88c7 100644 (file)
 #define DstDI       (5<<1)     /* Destination is in ES:(E)DI */
 #define DstMem64    (6<<1)     /* 64bit memory operand */
 #define DstImmUByte (7<<1)     /* 8-bit unsigned immediate operand */
-#define DstMask     (7<<1)
+#define DstDX       (8<<1)     /* Destination is in DX register */
+#define DstMask     (0xf<<1)
 /* Source operand type. */
-#define SrcNone     (0<<4)     /* No source operand. */
-#define SrcReg      (1<<4)     /* Register operand. */
-#define SrcMem      (2<<4)     /* Memory operand. */
-#define SrcMem16    (3<<4)     /* Memory operand (16-bit). */
-#define SrcMem32    (4<<4)     /* Memory operand (32-bit). */
-#define SrcImm      (5<<4)     /* Immediate operand. */
-#define SrcImmByte  (6<<4)     /* 8-bit sign-extended immediate operand. */
-#define SrcOne      (7<<4)     /* Implied '1' */
-#define SrcImmUByte (8<<4)      /* 8-bit unsigned immediate operand. */
-#define SrcImmU     (9<<4)      /* Immediate operand, unsigned */
-#define SrcSI       (0xa<<4)   /* Source is in the DS:RSI */
-#define SrcImmFAddr (0xb<<4)   /* Source is immediate far address */
-#define SrcMemFAddr (0xc<<4)   /* Source is far address in memory */
-#define SrcAcc      (0xd<<4)   /* Source Accumulator */
-#define SrcImmU16   (0xe<<4)    /* Immediate operand, unsigned, 16 bits */
-#define SrcMask     (0xf<<4)
+#define SrcNone     (0<<5)     /* No source operand. */
+#define SrcReg      (1<<5)     /* Register operand. */
+#define SrcMem      (2<<5)     /* Memory operand. */
+#define SrcMem16    (3<<5)     /* Memory operand (16-bit). */
+#define SrcMem32    (4<<5)     /* Memory operand (32-bit). */
+#define SrcImm      (5<<5)     /* Immediate operand. */
+#define SrcImmByte  (6<<5)     /* 8-bit sign-extended immediate operand. */
+#define SrcOne      (7<<5)     /* Implied '1' */
+#define SrcImmUByte (8<<5)      /* 8-bit unsigned immediate operand. */
+#define SrcImmU     (9<<5)      /* Immediate operand, unsigned */
+#define SrcSI       (0xa<<5)   /* Source is in the DS:RSI */
+#define SrcImmFAddr (0xb<<5)   /* Source is immediate far address */
+#define SrcMemFAddr (0xc<<5)   /* Source is far address in memory */
+#define SrcAcc      (0xd<<5)   /* Source Accumulator */
+#define SrcImmU16   (0xe<<5)    /* Immediate operand, unsigned, 16 bits */
+#define SrcDX       (0xf<<5)   /* Source is in DX register */
+#define SrcMask     (0xf<<5)
 /* Generic ModRM decode. */
-#define ModRM       (1<<8)
+#define ModRM       (1<<9)
 /* Destination is only written; never read. */
-#define Mov         (1<<9)
-#define BitOp       (1<<10)
-#define MemAbs      (1<<11)      /* Memory operand is absolute displacement */
-#define String      (1<<12)     /* String instruction (rep capable) */
-#define Stack       (1<<13)     /* Stack instruction (push/pop) */
-#define GroupMask   (7<<14)     /* Opcode uses one of the group mechanisms */
-#define Group       (1<<14)     /* Bits 3:5 of modrm byte extend opcode */
-#define GroupDual   (2<<14)     /* Alternate decoding of mod == 3 */
-#define Prefix      (3<<14)     /* Instruction varies with 66/f2/f3 prefix */
-#define RMExt       (4<<14)     /* Opcode extension in ModRM r/m if mod == 3 */
-#define Sse         (1<<17)     /* SSE Vector instruction */
+#define Mov         (1<<10)
+#define BitOp       (1<<11)
+#define MemAbs      (1<<12)      /* Memory operand is absolute displacement */
+#define String      (1<<13)     /* String instruction (rep capable) */
+#define Stack       (1<<14)     /* Stack instruction (push/pop) */
+#define GroupMask   (7<<15)     /* Opcode uses one of the group mechanisms */
+#define Group       (1<<15)     /* Bits 3:5 of modrm byte extend opcode */
+#define GroupDual   (2<<15)     /* Alternate decoding of mod == 3 */
+#define Prefix      (3<<15)     /* Instruction varies with 66/f2/f3 prefix */
+#define RMExt       (4<<15)     /* Opcode extension in ModRM r/m if mod == 3 */
+#define Sse         (1<<18)     /* SSE Vector instruction */
 /* Misc flags */
 #define Prot        (1<<21) /* instruction generates #UD if not in prot-mode */
 #define VendorSpecific (1<<22) /* Vendor specific instruction */
@@ -3154,8 +3156,8 @@ static struct opcode opcode_table[256] = {
        I(DstReg | SrcMem | ModRM | Src2Imm, em_imul_3op),
        I(SrcImmByte | Mov | Stack, em_push),
        I(DstReg | SrcMem | ModRM | Src2ImmByte, em_imul_3op),
-       D2bvIP(DstDI | Mov | String, ins, check_perm_in), /* insb, insw/insd */
-       D2bvIP(SrcSI | ImplicitOps | String, outs, check_perm_out), /* outsb, outsw/outsd */
+       D2bvIP(DstDI | SrcDX | Mov | String, ins, check_perm_in), /* insb, insw/insd */
+       D2bvIP(SrcSI | DstDX | String, outs, check_perm_out), /* outsb, outsw/outsd */
        /* 0x70 - 0x7F */
        X16(D(SrcImmByte)),
        /* 0x80 - 0x87 */
@@ -3212,8 +3214,8 @@ static struct opcode opcode_table[256] = {
        /* 0xE8 - 0xEF */
        D(SrcImm | Stack), D(SrcImm | ImplicitOps),
        D(SrcImmFAddr | No64), D(SrcImmByte | ImplicitOps),
-       D2bvIP(SrcNone | DstAcc,     in,  check_perm_in),
-       D2bvIP(SrcAcc | ImplicitOps, out, check_perm_out),
+       D2bvIP(SrcDX | DstAcc, in,  check_perm_in),
+       D2bvIP(SrcAcc | DstDX, out, check_perm_out),
        /* 0xF0 - 0xF7 */
        N, DI(ImplicitOps, icebp), N, N,
        DI(ImplicitOps | Priv, hlt), D(ImplicitOps),
@@ -3613,6 +3615,12 @@ done_prefixes:
                memop.bytes = c->op_bytes + 2;
                goto srcmem_common;
                break;
+       case SrcDX:
+               c->src.type = OP_REG;
+               c->src.bytes = 2;
+               c->src.addr.reg = &c->regs[VCPU_REGS_RDX];
+               fetch_register_operand(&c->src);
+               break;
        }
 
        if (rc != X86EMUL_CONTINUE)
@@ -3682,6 +3690,12 @@ done_prefixes:
                c->dst.addr.mem.seg = VCPU_SREG_ES;
                c->dst.val = 0;
                break;
+       case DstDX:
+               c->dst.type = OP_REG;
+               c->dst.bytes = 2;
+               c->dst.addr.reg = &c->regs[VCPU_REGS_RDX];
+               fetch_register_operand(&c->dst);
+               break;
        case ImplicitOps:
                /* Special instructions do their own operand decoding. */
        default:
@@ -4027,7 +4041,6 @@ special_insn:
                break;
        case 0xec: /* in al,dx */
        case 0xed: /* in (e/r)ax,dx */
-               c->src.val = c->regs[VCPU_REGS_RDX];
        do_io_in:
                if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val,
                                     &c->dst.val))
@@ -4035,7 +4048,6 @@ special_insn:
                break;
        case 0xee: /* out dx,al */
        case 0xef: /* out dx,(e/r)ax */
-               c->dst.val = c->regs[VCPU_REGS_RDX];
        do_io_out:
                ops->pio_out_emulated(ctxt, c->src.bytes, c->dst.val,
                                      &c->src.val, 1);
index 8bff7e7..1b2b73f 100644 (file)
@@ -189,10 +189,10 @@ struct multicall_space __xen_mc_entry(size_t args)
        unsigned argidx = roundup(b->argidx, sizeof(u64));
 
        BUG_ON(preemptible());
-       BUG_ON(b->argidx > MC_ARGS);
+       BUG_ON(b->argidx >= MC_ARGS);
 
        if (b->mcidx == MC_BATCH ||
-           (argidx + args) > MC_ARGS) {
+           (argidx + args) >= MC_ARGS) {
                mc_stats_flush(b->mcidx == MC_BATCH ? FL_SLOTS : FL_ARGS);
                xen_mc_flush();
                argidx = roundup(b->argidx, sizeof(u64));
@@ -206,7 +206,7 @@ struct multicall_space __xen_mc_entry(size_t args)
        ret.args = &b->args[argidx];
        b->argidx = argidx + args;
 
-       BUG_ON(b->argidx > MC_ARGS);
+       BUG_ON(b->argidx >= MC_ARGS);
        return ret;
 }
 
@@ -216,7 +216,7 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size)
        struct multicall_space ret = { NULL, NULL };
 
        BUG_ON(preemptible());
-       BUG_ON(b->argidx > MC_ARGS);
+       BUG_ON(b->argidx >= MC_ARGS);
 
        if (b->mcidx == 0)
                return ret;
@@ -224,14 +224,14 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size)
        if (b->entries[b->mcidx - 1].op != op)
                return ret;
 
-       if ((b->argidx + size) > MC_ARGS)
+       if ((b->argidx + size) >= MC_ARGS)
                return ret;
 
        ret.mc = &b->entries[b->mcidx - 1];
        ret.args = &b->args[b->argidx];
        b->argidx += size;
 
-       BUG_ON(b->argidx > MC_ARGS);
+       BUG_ON(b->argidx >= MC_ARGS);
        return ret;
 }
 
index dfb6e9d..7f099d6 100644 (file)
@@ -2802,10 +2802,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
        }
 
        /*
-        * Some controllers can't be frozen very well and may set
-        * spuruious error conditions during reset.  Clear accumulated
-        * error information.  As reset is the final recovery action,
-        * nothing is lost by doing this.
+        * Some controllers can't be frozen very well and may set spurious
+        * error conditions during reset.  Clear accumulated error
+        * information and re-thaw the port if frozen.  As reset is the
+        * final recovery action and we cross check link onlineness against
+        * device classification later, no hotplug event is lost by this.
         */
        spin_lock_irqsave(link->ap->lock, flags);
        memset(&link->eh_info, 0, sizeof(link->eh_info));
@@ -2814,6 +2815,9 @@ int ata_eh_reset(struct ata_link *link, int classify,
        ap->pflags &= ~ATA_PFLAG_EH_PENDING;
        spin_unlock_irqrestore(link->ap->lock, flags);
 
+       if (ap->pflags & ATA_PFLAG_FROZEN)
+               ata_eh_thaw_port(ap);
+
        /*
         * Make sure onlineness and classification result correspond.
         * Hotplug could have happened during reset and some
index c0dd09d..eaa8a85 100644 (file)
@@ -291,7 +291,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
 {
        struct pm_clk_notifier_block *clknb;
        struct device *dev = data;
-       char *con_id;
+       char **con_id;
        int error;
 
        dev_dbg(dev, "%s() %ld\n", __func__, action);
@@ -309,8 +309,8 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
 
                dev->pwr_domain = clknb->pwr_domain;
                if (clknb->con_ids[0]) {
-                       for (con_id = clknb->con_ids[0]; *con_id; con_id++)
-                               pm_runtime_clk_add(dev, con_id);
+                       for (con_id = clknb->con_ids; *con_id; con_id++)
+                               pm_runtime_clk_add(dev, *con_id);
                } else {
                        pm_runtime_clk_add(dev, NULL);
                }
@@ -380,7 +380,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
 {
        struct pm_clk_notifier_block *clknb;
        struct device *dev = data;
-       char *con_id;
+       char **con_id;
 
        dev_dbg(dev, "%s() %ld\n", __func__, action);
 
@@ -389,16 +389,16 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
        switch (action) {
        case BUS_NOTIFY_ADD_DEVICE:
                if (clknb->con_ids[0]) {
-                       for (con_id = clknb->con_ids[0]; *con_id; con_id++)
-                               enable_clock(dev, con_id);
+                       for (con_id = clknb->con_ids; *con_id; con_id++)
+                               enable_clock(dev, *con_id);
                } else {
                        enable_clock(dev, NULL);
                }
                break;
        case BUS_NOTIFY_DEL_DEVICE:
                if (clknb->con_ids[0]) {
-                       for (con_id = clknb->con_ids[0]; *con_id; con_id++)
-                               disable_clock(dev, con_id);
+                       for (con_id = clknb->con_ids; *con_id; con_id++)
+                               disable_clock(dev, *con_id);
                } else {
                        disable_clock(dev, NULL);
                }
index f032e44..bfe7232 100644 (file)
@@ -108,7 +108,9 @@ done:
  */
 unsigned long __init find_ibft_region(unsigned long *sizep)
 {
+#ifdef CONFIG_ACPI
        int i;
+#endif
        ibft_addr = NULL;
 
 #ifdef CONFIG_ACPI
index 4a7f631..2967002 100644 (file)
@@ -87,32 +87,20 @@ config GPIO_IT8761E
          Say yes here to support GPIO functionality of IT8761E super I/O chip.
 
 config GPIO_EXYNOS4
-       bool "Samsung Exynos4 GPIO library support"
-       default y if CPU_EXYNOS4210
-       depends on ARM
-       help
-         Say yes here to support Samsung Exynos4 series SoCs GPIO library
+       def_bool y
+       depends on CPU_EXYNOS4210
 
 config GPIO_PLAT_SAMSUNG
-       bool "Samsung SoCs GPIO library support"
-       default y if SAMSUNG_GPIOLIB_4BIT
-       depends on ARM
-       help
-         Say yes here to support Samsung SoCs GPIO library
+       def_bool y
+       depends on SAMSUNG_GPIOLIB_4BIT
 
 config GPIO_S5PC100
-       bool "Samsung S5PC100 GPIO library support"
-       default y if CPU_S5PC100
-       depends on ARM
-       help
-         Say yes here to support Samsung S5PC100 SoCs GPIO library
+       def_bool y
+       depends on CPU_S5PC100
 
 config GPIO_S5PV210
-       bool "Samsung S5PV210/S5PC110 GPIO library support"
-       default y if CPU_S5PV210
-       depends on ARM
-       help
-         Say yes here to support Samsung S5PV210/S5PC110 SoCs GPIO library
+       def_bool y
+       depends on CPU_S5PV210
 
 config GPIO_PL061
        bool "PrimeCell PL061 GPIO support"
index d54ca6a..9029835 100644 (file)
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
 
+int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip,
+                               unsigned int off, s3c_gpio_pull_t pull)
+{
+       if (pull == S3C_GPIO_PULL_UP)
+               pull = 3;
+
+       return s3c_gpio_setpull_updown(chip, off, pull);
+}
+
+s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip,
+                                               unsigned int off)
+{
+       s3c_gpio_pull_t pull;
+
+       pull = s3c_gpio_getpull_updown(chip, off);
+       if (pull == 3)
+               pull = S3C_GPIO_PULL_UP;
+
+       return pull;
+}
+
 static struct s3c_gpio_cfg gpio_cfg = {
        .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
+       .set_pull       = s3c_gpio_setpull_exynos4,
+       .get_pull       = s3c_gpio_getpull_exynos4,
 };
 
 static struct s3c_gpio_cfg gpio_cfg_noint = {
        .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
+       .set_pull       = s3c_gpio_setpull_exynos4,
+       .get_pull       = s3c_gpio_getpull_exynos4,
 };
 
 /*
index 6c51191..01f74a8 100644 (file)
@@ -432,7 +432,6 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
 {
        void __iomem *base = bank->base;
        u32 gpio_bit = 1 << gpio;
-       u32 val;
 
        if (cpu_is_omap44xx()) {
                MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit,
@@ -455,15 +454,8 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
        }
        if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
                if (cpu_is_omap44xx()) {
-                       if (trigger != 0)
-                               __raw_writel(1 << gpio, bank->base+
-                                               OMAP4_GPIO_IRQWAKEN0);
-                       else {
-                               val = __raw_readl(bank->base +
-                                                       OMAP4_GPIO_IRQWAKEN0);
-                               __raw_writel(val & (~(1 << gpio)), bank->base +
-                                                        OMAP4_GPIO_IRQWAKEN0);
-                       }
+                       MOD_REG_BIT(OMAP4_GPIO_IRQWAKEN0, gpio_bit,
+                               trigger != 0);
                } else {
                        /*
                         * GPIO wakeup request can only be generated on edge
@@ -1134,8 +1126,11 @@ static void gpio_irq_shutdown(struct irq_data *d)
 {
        unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned long flags;
 
+       spin_lock_irqsave(&bank->lock, flags);
        _reset_gpio(bank, gpio);
+       spin_unlock_irqrestore(&bank->lock, flags);
 }
 
 static void gpio_ack_irq(struct irq_data *d)
@@ -1150,9 +1145,12 @@ static void gpio_mask_irq(struct irq_data *d)
 {
        unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned long flags;
 
+       spin_lock_irqsave(&bank->lock, flags);
        _set_gpio_irqenable(bank, gpio, 0);
        _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
+       spin_unlock_irqrestore(&bank->lock, flags);
 }
 
 static void gpio_unmask_irq(struct irq_data *d)
@@ -1161,7 +1159,9 @@ static void gpio_unmask_irq(struct irq_data *d)
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
        unsigned int irq_mask = 1 << get_gpio_index(gpio);
        u32 trigger = irqd_get_trigger_type(d);
+       unsigned long flags;
 
+       spin_lock_irqsave(&bank->lock, flags);
        if (trigger)
                _set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
 
@@ -1173,6 +1173,7 @@ static void gpio_unmask_irq(struct irq_data *d)
        }
 
        _set_gpio_irqenable(bank, gpio, 1);
+       spin_unlock_irqrestore(&bank->lock, flags);
 }
 
 static struct irq_chip gpio_irq_chip = {
@@ -1524,7 +1525,7 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id)
        }
 }
 
-static void __init omap_gpio_chip_init(struct gpio_bank *bank)
+static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
 {
        int j;
        static int gpio;
index 51c2257..4d46441 100644 (file)
@@ -776,7 +776,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
        seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm);
        seq_printf(m, "  seqno: 0x%08x\n", error->seqno);
 
-       for (i = 0; i < 16; i++)
+       for (i = 0; i < dev_priv->num_fence_regs; i++)
                seq_printf(m, "  fence[%d] = %08llx\n", i, error->fence[i]);
 
        if (error->active_bo)
index ee66035..f63ee16 100644 (file)
@@ -716,6 +716,7 @@ typedef struct drm_i915_private {
        struct intel_fbdev *fbdev;
 
        struct drm_property *broadcast_rgb_property;
+       struct drm_property *force_audio_property;
 
        atomic_t forcewake_count;
 } drm_i915_private_t;
@@ -909,13 +910,6 @@ struct drm_i915_file_private {
        } mm;
 };
 
-enum intel_chip_family {
-       CHIP_I8XX = 0x01,
-       CHIP_I9XX = 0x02,
-       CHIP_I915 = 0x04,
-       CHIP_I965 = 0x08,
-};
-
 #define INTEL_INFO(dev)        (((struct drm_i915_private *) (dev)->dev_private)->info)
 
 #define IS_I830(dev)           ((dev)->pci_device == 0x3577)
index 0b2e167..12d3257 100644 (file)
@@ -354,7 +354,7 @@ i915_gem_shmem_pread_fast(struct drm_device *dev,
                 * page_offset = offset within page
                 * page_length = bytes to copy for this page
                 */
-               page_offset = offset & (PAGE_SIZE-1);
+               page_offset = offset_in_page(offset);
                page_length = remain;
                if ((page_offset + remain) > PAGE_SIZE)
                        page_length = PAGE_SIZE - page_offset;
@@ -453,9 +453,9 @@ i915_gem_shmem_pread_slow(struct drm_device *dev,
                 * data_page_offset = offset with data_page_index page.
                 * page_length = bytes to copy for this page
                 */
-               shmem_page_offset = offset & ~PAGE_MASK;
+               shmem_page_offset = offset_in_page(offset);
                data_page_index = data_ptr / PAGE_SIZE - first_data_page;
-               data_page_offset = data_ptr & ~PAGE_MASK;
+               data_page_offset = offset_in_page(data_ptr);
 
                page_length = remain;
                if ((shmem_page_offset + page_length) > PAGE_SIZE)
@@ -638,8 +638,8 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
                 * page_offset = offset within page
                 * page_length = bytes to copy for this page
                 */
-               page_base = (offset & ~(PAGE_SIZE-1));
-               page_offset = offset & (PAGE_SIZE-1);
+               page_base = offset & PAGE_MASK;
+               page_offset = offset_in_page(offset);
                page_length = remain;
                if ((page_offset + remain) > PAGE_SIZE)
                        page_length = PAGE_SIZE - page_offset;
@@ -650,7 +650,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
                 */
                if (fast_user_write(dev_priv->mm.gtt_mapping, page_base,
                                    page_offset, user_data, page_length))
-
                        return -EFAULT;
 
                remain -= page_length;
@@ -730,9 +729,9 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev,
                 * page_length = bytes to copy for this page
                 */
                gtt_page_base = offset & PAGE_MASK;
-               gtt_page_offset = offset & ~PAGE_MASK;
+               gtt_page_offset = offset_in_page(offset);
                data_page_index = data_ptr / PAGE_SIZE - first_data_page;
-               data_page_offset = data_ptr & ~PAGE_MASK;
+               data_page_offset = offset_in_page(data_ptr);
 
                page_length = remain;
                if ((gtt_page_offset + page_length) > PAGE_SIZE)
@@ -791,7 +790,7 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev,
                 * page_offset = offset within page
                 * page_length = bytes to copy for this page
                 */
-               page_offset = offset & (PAGE_SIZE-1);
+               page_offset = offset_in_page(offset);
                page_length = remain;
                if ((page_offset + remain) > PAGE_SIZE)
                        page_length = PAGE_SIZE - page_offset;
@@ -896,9 +895,9 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev,
                 * data_page_offset = offset with data_page_index page.
                 * page_length = bytes to copy for this page
                 */
-               shmem_page_offset = offset & ~PAGE_MASK;
+               shmem_page_offset = offset_in_page(offset);
                data_page_index = data_ptr / PAGE_SIZE - first_data_page;
-               data_page_offset = data_ptr & ~PAGE_MASK;
+               data_page_offset = offset_in_page(data_ptr);
 
                page_length = remain;
                if ((shmem_page_offset + page_length) > PAGE_SIZE)
@@ -1450,8 +1449,9 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj)
         * edge of an even tile row (where tile rows are counted as if the bo is
         * placed in a fenced gtt region).
         */
-       if (IS_GEN2(dev) ||
-           (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
+       if (IS_GEN2(dev))
+               tile_height = 16;
+       else if (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
                tile_height = 32;
        else
                tile_height = 8;
index b79619a..b9fafe3 100644 (file)
@@ -517,7 +517,7 @@ irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
        if (de_iir & DE_PIPEA_VBLANK_IVB)
                drm_handle_vblank(dev, 0);
 
-       if (de_iir & DE_PIPEB_VBLANK_IVB);
+       if (de_iir & DE_PIPEB_VBLANK_IVB)
                drm_handle_vblank(dev, 1);
 
        /* check event from PCH */
index e93f93c..0979d88 100644 (file)
@@ -288,6 +288,8 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
                 * This may be a DVI-I connector with a shared DDC
                 * link between analog and digital outputs, so we
                 * have to check the EDID input spec of the attached device.
+                *
+                * On the other hand, what should we do if it is a broken EDID?
                 */
                if (edid != NULL) {
                        is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
@@ -298,6 +300,8 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
                if (!is_digital) {
                        DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
                        return true;
+               } else {
+                       DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
                }
        }
 
index f553ddf..81a9059 100644 (file)
@@ -3983,54 +3983,6 @@ static void i830_update_wm(struct drm_device *dev)
 #define ILK_LP0_PLANE_LATENCY          700
 #define ILK_LP0_CURSOR_LATENCY         1300
 
-static bool ironlake_compute_wm0(struct drm_device *dev,
-                                int pipe,
-                                const struct intel_watermark_params *display,
-                                int display_latency_ns,
-                                const struct intel_watermark_params *cursor,
-                                int cursor_latency_ns,
-                                int *plane_wm,
-                                int *cursor_wm)
-{
-       struct drm_crtc *crtc;
-       int htotal, hdisplay, clock, pixel_size;
-       int line_time_us, line_count;
-       int entries, tlb_miss;
-
-       crtc = intel_get_crtc_for_pipe(dev, pipe);
-       if (crtc->fb == NULL || !crtc->enabled)
-               return false;
-
-       htotal = crtc->mode.htotal;
-       hdisplay = crtc->mode.hdisplay;
-       clock = crtc->mode.clock;
-       pixel_size = crtc->fb->bits_per_pixel / 8;
-
-       /* Use the small buffer method to calculate plane watermark */
-       entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
-       tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8;
-       if (tlb_miss > 0)
-               entries += tlb_miss;
-       entries = DIV_ROUND_UP(entries, display->cacheline_size);
-       *plane_wm = entries + display->guard_size;
-       if (*plane_wm > (int)display->max_wm)
-               *plane_wm = display->max_wm;
-
-       /* Use the large buffer method to calculate cursor watermark */
-       line_time_us = ((htotal * 1000) / clock);
-       line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
-       entries = line_count * 64 * pixel_size;
-       tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
-       if (tlb_miss > 0)
-               entries += tlb_miss;
-       entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
-       *cursor_wm = entries + cursor->guard_size;
-       if (*cursor_wm > (int)cursor->max_wm)
-               *cursor_wm = (int)cursor->max_wm;
-
-       return true;
-}
-
 /*
  * Check the wm result.
  *
@@ -4139,12 +4091,12 @@ static void ironlake_update_wm(struct drm_device *dev)
        unsigned int enabled;
 
        enabled = 0;
-       if (ironlake_compute_wm0(dev, 0,
-                                &ironlake_display_wm_info,
-                                ILK_LP0_PLANE_LATENCY,
-                                &ironlake_cursor_wm_info,
-                                ILK_LP0_CURSOR_LATENCY,
-                                &plane_wm, &cursor_wm)) {
+       if (g4x_compute_wm0(dev, 0,
+                           &ironlake_display_wm_info,
+                           ILK_LP0_PLANE_LATENCY,
+                           &ironlake_cursor_wm_info,
+                           ILK_LP0_CURSOR_LATENCY,
+                           &plane_wm, &cursor_wm)) {
                I915_WRITE(WM0_PIPEA_ILK,
                           (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
                DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
@@ -4153,12 +4105,12 @@ static void ironlake_update_wm(struct drm_device *dev)
                enabled |= 1;
        }
 
-       if (ironlake_compute_wm0(dev, 1,
-                                &ironlake_display_wm_info,
-                                ILK_LP0_PLANE_LATENCY,
-                                &ironlake_cursor_wm_info,
-                                ILK_LP0_CURSOR_LATENCY,
-                                &plane_wm, &cursor_wm)) {
+       if (g4x_compute_wm0(dev, 1,
+                           &ironlake_display_wm_info,
+                           ILK_LP0_PLANE_LATENCY,
+                           &ironlake_cursor_wm_info,
+                           ILK_LP0_CURSOR_LATENCY,
+                           &plane_wm, &cursor_wm)) {
                I915_WRITE(WM0_PIPEB_ILK,
                           (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
                DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
@@ -4223,10 +4175,10 @@ static void sandybridge_update_wm(struct drm_device *dev)
        unsigned int enabled;
 
        enabled = 0;
-       if (ironlake_compute_wm0(dev, 0,
-                                &sandybridge_display_wm_info, latency,
-                                &sandybridge_cursor_wm_info, latency,
-                                &plane_wm, &cursor_wm)) {
+       if (g4x_compute_wm0(dev, 0,
+                           &sandybridge_display_wm_info, latency,
+                           &sandybridge_cursor_wm_info, latency,
+                           &plane_wm, &cursor_wm)) {
                I915_WRITE(WM0_PIPEA_ILK,
                           (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
                DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
@@ -4235,10 +4187,10 @@ static void sandybridge_update_wm(struct drm_device *dev)
                enabled |= 1;
        }
 
-       if (ironlake_compute_wm0(dev, 1,
-                                &sandybridge_display_wm_info, latency,
-                                &sandybridge_cursor_wm_info, latency,
-                                &plane_wm, &cursor_wm)) {
+       if (g4x_compute_wm0(dev, 1,
+                           &sandybridge_display_wm_info, latency,
+                           &sandybridge_cursor_wm_info, latency,
+                           &plane_wm, &cursor_wm)) {
                I915_WRITE(WM0_PIPEB_ILK,
                           (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
                DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
@@ -7675,6 +7627,7 @@ static void intel_init_display(struct drm_device *dev)
                        dev_priv->display.update_wm = NULL;
                } else
                        dev_priv->display.update_wm = pineview_update_wm;
+               dev_priv->display.init_clock_gating = gen3_init_clock_gating;
        } else if (IS_G4X(dev)) {
                dev_priv->display.update_wm = g4x_update_wm;
                dev_priv->display.init_clock_gating = g4x_init_clock_gating;
index a4d8031..391b55f 100644 (file)
@@ -59,8 +59,6 @@ struct intel_dp {
        bool is_pch_edp;
        uint8_t train_set[4];
        uint8_t link_status[DP_LINK_STATUS_SIZE];
-
-       struct drm_property *force_audio_property;
 };
 
 /**
@@ -1702,7 +1700,7 @@ intel_dp_set_property(struct drm_connector *connector,
        if (ret)
                return ret;
 
-       if (property == intel_dp->force_audio_property) {
+       if (property == dev_priv->force_audio_property) {
                int i = val;
                bool has_audio;
 
@@ -1841,16 +1839,7 @@ bool intel_dpd_is_edp(struct drm_device *dev)
 static void
 intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector)
 {
-       struct drm_device *dev = connector->dev;
-
-       intel_dp->force_audio_property =
-               drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2);
-       if (intel_dp->force_audio_property) {
-               intel_dp->force_audio_property->values[0] = -1;
-               intel_dp->force_audio_property->values[1] = 1;
-               drm_connector_attach_property(connector, intel_dp->force_audio_property, 0);
-       }
-
+       intel_attach_force_audio_property(connector);
        intel_attach_broadcast_rgb_property(connector);
 }
 
index 831d7a4..9ffa61e 100644 (file)
@@ -236,6 +236,7 @@ struct intel_unpin_work {
 int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
 extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
 
+extern void intel_attach_force_audio_property(struct drm_connector *connector);
 extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
 
 extern void intel_crt_init(struct drm_device *dev);
index f289b86..aa0a8e8 100644 (file)
@@ -45,7 +45,6 @@ struct intel_hdmi {
        bool has_hdmi_sink;
        bool has_audio;
        int force_audio;
-       struct drm_property *force_audio_property;
 };
 
 static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
@@ -194,7 +193,7 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector,
        if (mode->clock > 165000)
                return MODE_CLOCK_HIGH;
        if (mode->clock < 20000)
-               return MODE_CLOCK_HIGH;
+               return MODE_CLOCK_LOW;
 
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
@@ -287,7 +286,7 @@ intel_hdmi_set_property(struct drm_connector *connector,
        if (ret)
                return ret;
 
-       if (property == intel_hdmi->force_audio_property) {
+       if (property == dev_priv->force_audio_property) {
                int i = val;
                bool has_audio;
 
@@ -365,16 +364,7 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
 static void
 intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
 {
-       struct drm_device *dev = connector->dev;
-
-       intel_hdmi->force_audio_property =
-               drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2);
-       if (intel_hdmi->force_audio_property) {
-               intel_hdmi->force_audio_property->values[0] = -1;
-               intel_hdmi->force_audio_property->values[1] = 1;
-               drm_connector_attach_property(connector, intel_hdmi->force_audio_property, 0);
-       }
-
+       intel_attach_force_audio_property(connector);
        intel_attach_broadcast_rgb_property(connector);
 }
 
index 67cb076..b28f7bd 100644 (file)
@@ -727,6 +727,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Asus EeeBox PC EB1007",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
+               },
+       },
 
        { }     /* terminating entry */
 };
index 9034dd8..3b26a3b 100644 (file)
@@ -81,6 +81,36 @@ int intel_ddc_get_modes(struct drm_connector *connector,
        return ret;
 }
 
+static const char *force_audio_names[] = {
+       "off",
+       "auto",
+       "on",
+};
+
+void
+intel_attach_force_audio_property(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_property *prop;
+       int i;
+
+       prop = dev_priv->force_audio_property;
+       if (prop == NULL) {
+               prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
+                                          "audio",
+                                          ARRAY_SIZE(force_audio_names));
+               if (prop == NULL)
+                       return;
+
+               for (i = 0; i < ARRAY_SIZE(force_audio_names); i++)
+                       drm_property_add_enum(prop, i, i-1, force_audio_names[i]);
+
+               dev_priv->force_audio_property = prop;
+       }
+       drm_connector_attach_property(connector, prop, 0);
+}
+
 static const char *broadcast_rgb_names[] = {
        "Full",
        "Limited 16:235",
index 754086f..30fe554 100644 (file)
@@ -148,8 +148,6 @@ struct intel_sdvo_connector {
        int   format_supported_num;
        struct drm_property *tv_format;
 
-       struct drm_property *force_audio_property;
-
        /* add the property for the SDVO-TV */
        struct drm_property *left;
        struct drm_property *right;
@@ -1712,7 +1710,7 @@ intel_sdvo_set_property(struct drm_connector *connector,
        if (ret)
                return ret;
 
-       if (property == intel_sdvo_connector->force_audio_property) {
+       if (property == dev_priv->force_audio_property) {
                int i = val;
                bool has_audio;
 
@@ -2037,15 +2035,7 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo_connector *connector)
 {
        struct drm_device *dev = connector->base.base.dev;
 
-       connector->force_audio_property =
-               drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2);
-       if (connector->force_audio_property) {
-               connector->force_audio_property->values[0] = -1;
-               connector->force_audio_property->values[1] = 1;
-               drm_connector_attach_property(&connector->base.base,
-                                             connector->force_audio_property, 0);
-       }
-
+       intel_attach_force_audio_property(&connector->base.base);
        if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev))
                intel_attach_broadcast_rgb_property(&connector->base.base);
 }
index 053edf9..ba896e5 100644 (file)
@@ -900,6 +900,7 @@ nv_save_state_ext(struct drm_device *dev, int head,
        }
        /* NV11 and NV20 don't have this, they stop at 0x52. */
        if (nv_gf4_disp_arch(dev)) {
+               rd_cio_state(dev, head, regp, NV_CIO_CRE_42);
                rd_cio_state(dev, head, regp, NV_CIO_CRE_53);
                rd_cio_state(dev, head, regp, NV_CIO_CRE_54);
 
@@ -1003,6 +1004,7 @@ nv_load_state_ext(struct drm_device *dev, int head,
                        nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0);
                }
 
+               wr_cio_state(dev, head, regp, NV_CIO_CRE_42);
                wr_cio_state(dev, head, regp, NV_CIO_CRE_53);
                wr_cio_state(dev, head, regp, NV_CIO_CRE_54);
 
index 2960f58..5ee14d2 100644 (file)
@@ -397,7 +397,7 @@ nouveau_mem_vram_init(struct drm_device *dev)
                if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
                        dma_bits = 40;
        } else
-       if (drm_pci_device_is_pcie(dev) &&
+       if (0 && drm_pci_device_is_pcie(dev) &&
            dev_priv->chipset  > 0x40 &&
            dev_priv->chipset != 0x45) {
                if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39)))
@@ -868,7 +868,9 @@ nouveau_gart_manager_del(struct ttm_mem_type_manager *man,
                nouveau_vm_unmap(&node->tmp_vma);
                nouveau_vm_put(&node->tmp_vma);
        }
+
        mem->mm_node = NULL;
+       kfree(node);
 }
 
 static int
index c77111e..82fad91 100644 (file)
@@ -458,7 +458,7 @@ nouveau_sgdma_init(struct drm_device *dev)
                dev_priv->gart_info.type = NOUVEAU_GART_HW;
                dev_priv->gart_info.func = &nv50_sgdma_backend;
        } else
-       if (drm_pci_device_is_pcie(dev) &&
+       if (0 && drm_pci_device_is_pcie(dev) &&
            dev_priv->chipset > 0x40 && dev_priv->chipset != 0x45) {
                if (nv44_graph_class(dev)) {
                        dev_priv->gart_info.func = &nv44_sgdma_backend;
index 38ea662..8021888 100644 (file)
@@ -371,6 +371,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->vram.flags_valid        = nv50_vram_flags_valid;
                break;
        case 0xC0:
+       case 0xD0:
                engine->instmem.init            = nvc0_instmem_init;
                engine->instmem.takedown        = nvc0_instmem_takedown;
                engine->instmem.suspend         = nvc0_instmem_suspend;
@@ -563,68 +564,68 @@ nouveau_card_init(struct drm_device *dev)
        if (ret)
                goto out_timer;
 
-       switch (dev_priv->card_type) {
-       case NV_04:
-               nv04_graph_create(dev);
-               break;
-       case NV_10:
-               nv10_graph_create(dev);
-               break;
-       case NV_20:
-       case NV_30:
-               nv20_graph_create(dev);
-               break;
-       case NV_40:
-               nv40_graph_create(dev);
-               break;
-       case NV_50:
-               nv50_graph_create(dev);
-               break;
-       case NV_C0:
-               nvc0_graph_create(dev);
-               break;
-       default:
-               break;
-       }
-
-       switch (dev_priv->chipset) {
-       case 0x84:
-       case 0x86:
-       case 0x92:
-       case 0x94:
-       case 0x96:
-       case 0xa0:
-               nv84_crypt_create(dev);
-               break;
-       }
+       if (!nouveau_noaccel) {
+               switch (dev_priv->card_type) {
+               case NV_04:
+                       nv04_graph_create(dev);
+                       break;
+               case NV_10:
+                       nv10_graph_create(dev);
+                       break;
+               case NV_20:
+               case NV_30:
+                       nv20_graph_create(dev);
+                       break;
+               case NV_40:
+                       nv40_graph_create(dev);
+                       break;
+               case NV_50:
+                       nv50_graph_create(dev);
+                       break;
+               case NV_C0:
+                       nvc0_graph_create(dev);
+                       break;
+               default:
+                       break;
+               }
 
-       switch (dev_priv->card_type) {
-       case NV_50:
                switch (dev_priv->chipset) {
-               case 0xa3:
-               case 0xa5:
-               case 0xa8:
-               case 0xaf:
-                       nva3_copy_create(dev);
+               case 0x84:
+               case 0x86:
+               case 0x92:
+               case 0x94:
+               case 0x96:
+               case 0xa0:
+                       nv84_crypt_create(dev);
                        break;
                }
-               break;
-       case NV_C0:
-               nvc0_copy_create(dev, 0);
-               nvc0_copy_create(dev, 1);
-               break;
-       default:
-               break;
-       }
 
-       if (dev_priv->card_type == NV_40)
-               nv40_mpeg_create(dev);
-       else
-       if (dev_priv->card_type == NV_50 &&
-           (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0))
-               nv50_mpeg_create(dev);
+               switch (dev_priv->card_type) {
+               case NV_50:
+                       switch (dev_priv->chipset) {
+                       case 0xa3:
+                       case 0xa5:
+                       case 0xa8:
+                       case 0xaf:
+                               nva3_copy_create(dev);
+                               break;
+                       }
+                       break;
+               case NV_C0:
+                       nvc0_copy_create(dev, 0);
+                       nvc0_copy_create(dev, 1);
+                       break;
+               default:
+                       break;
+               }
+
+               if (dev_priv->card_type == NV_40)
+                       nv40_mpeg_create(dev);
+               else
+               if (dev_priv->card_type == NV_50 &&
+                   (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0))
+                       nv50_mpeg_create(dev);
 
-       if (!nouveau_noaccel) {
                for (e = 0; e < NVOBJ_ENGINE_NR; e++) {
                        if (dev_priv->eng[e]) {
                                ret = dev_priv->eng[e]->init(dev, e);
@@ -922,6 +923,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
                dev_priv->card_type = NV_50;
                break;
        case 0xc0:
+       case 0xd0:
                dev_priv->card_type = NV_C0;
                break;
        default:
index 0059e6f..519a6b4 100644 (file)
@@ -58,6 +58,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)
                        num -= len;
                        pte += len;
                        if (unlikely(end >= max)) {
+                               phys += len << (bits + 12);
                                pde++;
                                pte = 0;
                        }
index 3c78bc8..f1a3ae4 100644 (file)
@@ -376,7 +376,10 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
         */
 
        /* framebuffer can be larger than crtc scanout area. */
-       regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = XLATE(fb->pitch / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8);
+       regp->CRTC[NV_CIO_CRE_RPC0_INDEX] =
+               XLATE(fb->pitch / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8);
+       regp->CRTC[NV_CIO_CRE_42] =
+               XLATE(fb->pitch / 8, 11, NV_CIO_CRE_42_OFFSET_11);
        regp->CRTC[NV_CIO_CRE_RPC1_INDEX] = mode->crtc_hdisplay < 1280 ?
                                            MASK(NV_CIO_CRE_RPC1_LARGE) : 0x00;
        regp->CRTC[NV_CIO_CRE_LSR_INDEX] = XLATE(horizBlankEnd, 6, NV_CIO_CRE_LSR_HBE_6) |
@@ -824,8 +827,11 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = drm_fb->pitch >> 3;
        regp->CRTC[NV_CIO_CRE_RPC0_INDEX] =
                XLATE(drm_fb->pitch >> 3, 8, NV_CIO_CRE_RPC0_OFFSET_10_8);
+       regp->CRTC[NV_CIO_CRE_42] =
+               XLATE(drm_fb->pitch / 8, 11, NV_CIO_CRE_42_OFFSET_11);
        crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_RPC0_INDEX);
        crtc_wr_cio_state(crtc, regp, NV_CIO_CR_OFFSET_INDEX);
+       crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_42);
 
        /* Update the framebuffer location. */
        regp->fb_start = nv_crtc->fb.offset & ~3;
index fe0f253..bbfb1a6 100644 (file)
 #              define NV_CIO_CRE_EBR_VDE_11            2:2
 #              define NV_CIO_CRE_EBR_VRS_11            4:4
 #              define NV_CIO_CRE_EBR_VBS_11            6:6
+#      define NV_CIO_CRE_42                    0x42
+#              define NV_CIO_CRE_42_OFFSET_11          6:6
 #      define NV_CIO_CRE_43                    0x43
 #      define NV_CIO_CRE_44                    0x44    /* head control */
 #      define NV_CIO_CRE_CSB                   0x45    /* colour saturation boost */
index 9746fee..ea92bbe 100644 (file)
@@ -28,11 +28,4 @@ config DRM_RADEON_KMS
          The kernel will also perform security check on command stream
          provided by the user, we want to catch and forbid any illegal use
          of the GPU such as DMA into random system memory or into memory
-         not owned by the process supplying the command stream. This part
-         of the code is still incomplete and this why we propose that patch
-         as a staging driver addition, future security might forbid current
-         experimental userspace to run.
-
-         This code support the following hardware : R1XX,R2XX,R3XX,R4XX,R5XX
-         (radeon up to X1950). Works is underway to provide support for R6XX,
-         R7XX and newer hardware (radeon from HD2XXX to HD4XXX).
+         not owned by the process supplying the command stream.
index ec84878..84a69e7 100644 (file)
@@ -1045,7 +1045,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        uint64_t fb_location;
        uint32_t fb_format, fb_pitch_pixels, tiling_flags;
        u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
-       u32 tmp;
+       u32 tmp, viewport_w, viewport_h;
        int r;
 
        /* no fb bound */
@@ -1171,8 +1171,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        y &= ~1;
        WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
               (x << 16) | y);
+       viewport_w = crtc->mode.hdisplay;
+       viewport_h = (crtc->mode.vdisplay + 1) & ~1;
        WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
-              (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
+              (viewport_w << 16) | viewport_h);
 
        /* pageflip setup */
        /* make sure flip is at vb rather than hb */
@@ -1213,7 +1215,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        uint64_t fb_location;
        uint32_t fb_format, fb_pitch_pixels, tiling_flags;
        u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
-       u32 tmp;
+       u32 tmp, viewport_w, viewport_h;
        int r;
 
        /* no fb bound */
@@ -1338,8 +1340,10 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        y &= ~1;
        WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
               (x << 16) | y);
+       viewport_w = crtc->mode.hdisplay;
+       viewport_h = (crtc->mode.vdisplay + 1) & ~1;
        WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
-              (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
+              (viewport_w << 16) | viewport_h);
 
        /* pageflip setup */
        /* make sure flip is at vb rather than hb */
index e148ab0..7b4eeb7 100644 (file)
 
 const u32 cayman_default_state[] =
 {
-       /* XXX fill in additional blit state */
+       0xc0066900,
+       0x00000000,
+       0x00000060, /* DB_RENDER_CONTROL */
+       0x00000000, /* DB_COUNT_CONTROL */
+       0x00000000, /* DB_DEPTH_VIEW */
+       0x0000002a, /* DB_RENDER_OVERRIDE */
+       0x00000000, /* DB_RENDER_OVERRIDE2 */
+       0x00000000, /* DB_HTILE_DATA_BASE */
 
        0xc0026900,
-       0x00000316,
-       0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */
-       0x00000010, /*  */
+       0x0000000a,
+       0x00000000, /* DB_STENCIL_CLEAR */
+       0x00000000, /* DB_DEPTH_CLEAR */
+
+       0xc0036900,
+       0x0000000f,
+       0x00000000, /* DB_DEPTH_INFO */
+       0x00000000, /* DB_Z_INFO */
+       0x00000000, /* DB_STENCIL_INFO */
+
+       0xc0016900,
+       0x00000080,
+       0x00000000, /* PA_SC_WINDOW_OFFSET */
+
+       0xc00d6900,
+       0x00000083,
+       0x0000ffff, /* PA_SC_CLIPRECT_RULE */
+       0x00000000, /* PA_SC_CLIPRECT_0_TL */
+       0x20002000, /* PA_SC_CLIPRECT_0_BR */
+       0x00000000,
+       0x20002000,
+       0x00000000,
+       0x20002000,
+       0x00000000,
+       0x20002000,
+       0xaaaaaaaa, /* PA_SC_EDGERULE */
+       0x00000000, /* PA_SU_HARDWARE_SCREEN_OFFSET */
+       0x0000000f, /* CB_TARGET_MASK */
+       0x0000000f, /* CB_SHADER_MASK */
+
+       0xc0226900,
+       0x00000094,
+       0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */
+       0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x80000000,
+       0x20002000,
+       0x00000000, /* PA_SC_VPORT_ZMIN_0 */
+       0x3f800000, /* PA_SC_VPORT_ZMAX_0 */
+
+       0xc0016900,
+       0x000000d4,
+       0x00000000, /* SX_MISC */
 
        0xc0026900,
        0x000000d9,
        0x00000000, /* CP_RINGID */
        0x00000000, /* CP_VMID */
+
+       0xc0096900,
+       0x00000100,
+       0x00ffffff, /* VGT_MAX_VTX_INDX */
+       0x00000000, /* VGT_MIN_VTX_INDX */
+       0x00000000, /* VGT_INDX_OFFSET */
+       0x00000000, /* VGT_MULTI_PRIM_IB_RESET_INDX */
+       0x00000000, /* SX_ALPHA_TEST_CONTROL */
+       0x00000000, /* CB_BLEND_RED */
+       0x00000000, /* CB_BLEND_GREEN */
+       0x00000000, /* CB_BLEND_BLUE */
+       0x00000000, /* CB_BLEND_ALPHA */
+
+       0xc0016900,
+       0x00000187,
+       0x00000100, /* SPI_VS_OUT_ID_0 */
+
+       0xc0026900,
+       0x00000191,
+       0x00000100, /* SPI_PS_INPUT_CNTL_0 */
+       0x00000101, /* SPI_PS_INPUT_CNTL_1 */
+
+       0xc0016900,
+       0x000001b1,
+       0x00000000, /* SPI_VS_OUT_CONFIG */
+
+       0xc0106900,
+       0x000001b3,
+       0x20000001, /* SPI_PS_IN_CONTROL_0 */
+       0x00000000, /* SPI_PS_IN_CONTROL_1 */
+       0x00000000, /* SPI_INTERP_CONTROL_0 */
+       0x00000000, /* SPI_INPUT_Z */
+       0x00000000, /* SPI_FOG_CNTL */
+       0x00100000, /* SPI_BARYC_CNTL */
+       0x00000000, /* SPI_PS_IN_CONTROL_2 */
+       0x00000000, /* SPI_COMPUTE_INPUT_CNTL */
+       0x00000000, /* SPI_COMPUTE_NUM_THREAD_X */
+       0x00000000, /* SPI_COMPUTE_NUM_THREAD_Y */
+       0x00000000, /* SPI_COMPUTE_NUM_THREAD_Z */
+       0x00000000, /* SPI_GPR_MGMT */
+       0x00000000, /* SPI_LDS_MGMT */
+       0x00000000, /* SPI_STACK_MGMT */
+       0x00000000, /* SPI_WAVE_MGMT_1 */
+       0x00000000, /* SPI_WAVE_MGMT_2 */
+
+       0xc0016900,
+       0x000001e0,
+       0x00000000, /* CB_BLEND0_CONTROL */
+
+       0xc00e6900,
+       0x00000200,
+       0x00000000, /* DB_DEPTH_CONTROL */
+       0x00000000, /* DB_EQAA */
+       0x00cc0010, /* CB_COLOR_CONTROL */
+       0x00000210, /* DB_SHADER_CONTROL */
+       0x00010000, /* PA_CL_CLIP_CNTL */
+       0x00000004, /* PA_SU_SC_MODE_CNTL */
+       0x00000100, /* PA_CL_VTE_CNTL */
+       0x00000000, /* PA_CL_VS_OUT_CNTL */
+       0x00000000, /* PA_CL_NANINF_CNTL */
+       0x00000000, /* PA_SU_LINE_STIPPLE_CNTL */
+       0x00000000, /* PA_SU_LINE_STIPPLE_SCALE */
+       0x00000000, /* PA_SU_PRIM_FILTER_CNTL */
+       0x00000000, /*  */
+       0x00000000, /*  */
+
+       0xc0026900,
+       0x00000229,
+       0x00000000, /* SQ_PGM_START_FS */
+       0x00000000,
+
+       0xc0016900,
+       0x0000023b,
+       0x00000000, /* SQ_LDS_ALLOC_PS */
+
+       0xc0066900,
+       0x00000240,
+       0x00000000, /* SQ_ESGS_RING_ITEMSIZE */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+
+       0xc0046900,
+       0x00000247,
+       0x00000000, /* SQ_GS_VERT_ITEMSIZE */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+
+       0xc0116900,
+       0x00000280,
+       0x00000000, /* PA_SU_POINT_SIZE */
+       0x00000000, /* PA_SU_POINT_MINMAX */
+       0x00000008, /* PA_SU_LINE_CNTL */
+       0x00000000, /* PA_SC_LINE_STIPPLE */
+       0x00000000, /* VGT_OUTPUT_PATH_CNTL */
+       0x00000000, /* VGT_HOS_CNTL */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000, /* VGT_GS_MODE */
+
+       0xc0026900,
+       0x00000292,
+       0x00000000, /* PA_SC_MODE_CNTL_0 */
+       0x00000000, /* PA_SC_MODE_CNTL_1 */
+
+       0xc0016900,
+       0x000002a1,
+       0x00000000, /* VGT_PRIMITIVEID_EN */
+
+       0xc0016900,
+       0x000002a5,
+       0x00000000, /* VGT_MULTI_PRIM_IB_RESET_EN */
+
+       0xc0026900,
+       0x000002a8,
+       0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */
+       0x00000000,
+
+       0xc0026900,
+       0x000002ad,
+       0x00000000, /* VGT_REUSE_OFF */
+       0x00000000,
+
+       0xc0016900,
+       0x000002d5,
+       0x00000000, /* VGT_SHADER_STAGES_EN */
+
+       0xc0016900,
+       0x000002dc,
+       0x0000aa00, /* DB_ALPHA_TO_MASK */
+
+       0xc0066900,
+       0x000002de,
+       0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+
+       0xc0026900,
+       0x000002e5,
+       0x00000000, /* VGT_STRMOUT_CONFIG */
+       0x00000000,
+
+       0xc01b6900,
+       0x000002f5,
+       0x76543210, /* PA_SC_CENTROID_PRIORITY_0 */
+       0xfedcba98, /* PA_SC_CENTROID_PRIORITY_1 */
+       0x00000000, /* PA_SC_LINE_CNTL */
+       0x00000000, /* PA_SC_AA_CONFIG */
+       0x00000005, /* PA_SU_VTX_CNTL */
+       0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */
+       0x3f800000, /* PA_CL_GB_VERT_DISC_ADJ */
+       0x3f800000, /* PA_CL_GB_HORZ_CLIP_ADJ */
+       0x3f800000, /* PA_CL_GB_HORZ_DISC_ADJ */
+       0x00000000, /* PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0xffffffff, /* PA_SC_AA_MASK_X0Y0_X1Y0 */
+       0xffffffff,
+
+       0xc0026900,
+       0x00000316,
+       0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */
+       0x00000010, /*  */
+};
+
+const u32 cayman_vs[] =
+{
+       0x00000004,
+       0x80400400,
+       0x0000a03c,
+       0x95000688,
+       0x00004000,
+       0x15000688,
+       0x00000000,
+       0x88000000,
+       0x04000000,
+       0x67961001,
+#ifdef __BIG_ENDIAN
+       0x00020000,
+#else
+       0x00000000,
+#endif
+       0x00000000,
+       0x04000000,
+       0x67961000,
+#ifdef __BIG_ENDIAN
+       0x00020008,
+#else
+       0x00000008,
+#endif
+       0x00000000,
+};
+
+const u32 cayman_ps[] =
+{
+       0x00000004,
+       0xa00c0000,
+       0x00000008,
+       0x80400000,
+       0x00000000,
+       0x95000688,
+       0x00000000,
+       0x88000000,
+       0x00380400,
+       0x00146b10,
+       0x00380000,
+       0x20146b10,
+       0x00380400,
+       0x40146b00,
+       0x80380000,
+       0x60146b00,
+       0x00000010,
+       0x000d1000,
+       0xb0800000,
+       0x00000000,
 };
 
+const u32 cayman_ps_size = ARRAY_SIZE(cayman_ps);
+const u32 cayman_vs_size = ARRAY_SIZE(cayman_vs);
 const u32 cayman_default_size = ARRAY_SIZE(cayman_default_state);
index 33b75e5..f5d0e9a 100644 (file)
 #ifndef CAYMAN_BLIT_SHADERS_H
 #define CAYMAN_BLIT_SHADERS_H
 
+extern const u32 cayman_ps[];
+extern const u32 cayman_vs[];
 extern const u32 cayman_default_state[];
 
+extern const u32 cayman_ps_size, cayman_vs_size;
 extern const u32 cayman_default_size;
 
 #endif
index 7c37638..98ea597 100644 (file)
@@ -88,21 +88,39 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 /* get temperature in millidegrees */
 int evergreen_get_temp(struct radeon_device *rdev)
 {
-       u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >>
-               ASIC_T_SHIFT;
-       u32 actual_temp = 0;
-
-       if (temp & 0x400)
-               actual_temp = -256;
-       else if (temp & 0x200)
-               actual_temp = 255;
-       else if (temp & 0x100) {
-               actual_temp = temp & 0x1ff;
-               actual_temp |= ~0x1ff;
-       } else
-               actual_temp = temp & 0xff;
+       u32 temp, toffset, actual_temp = 0;
+
+       if (rdev->family == CHIP_JUNIPER) {
+               toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >>
+                       TOFFSET_SHIFT;
+               temp = (RREG32(CG_TS0_STATUS) & TS0_ADC_DOUT_MASK) >>
+                       TS0_ADC_DOUT_SHIFT;
+
+               if (toffset & 0x100)
+                       actual_temp = temp / 2 - (0x200 - toffset);
+               else
+                       actual_temp = temp / 2 + toffset;
+
+               actual_temp = actual_temp * 1000;
+
+       } else {
+               temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >>
+                       ASIC_T_SHIFT;
 
-       return (actual_temp * 1000) / 2;
+               if (temp & 0x400)
+                       actual_temp = -256;
+               else if (temp & 0x200)
+                       actual_temp = 255;
+               else if (temp & 0x100) {
+                       actual_temp = temp & 0x1ff;
+                       actual_temp |= ~0x1ff;
+               } else
+                       actual_temp = temp & 0xff;
+
+               actual_temp = (actual_temp * 1000) / 2;
+       }
+
+       return actual_temp;
 }
 
 int sumo_get_temp(struct radeon_device *rdev)
@@ -1415,6 +1433,8 @@ static u32 evergreen_get_tile_pipe_to_backend_map(struct radeon_device *rdev,
        case CHIP_CEDAR:
        case CHIP_REDWOOD:
        case CHIP_PALM:
+       case CHIP_SUMO:
+       case CHIP_SUMO2:
        case CHIP_TURKS:
        case CHIP_CAICOS:
                force_no_swizzle = false;
@@ -1544,6 +1564,8 @@ static void evergreen_program_channel_remap(struct radeon_device *rdev)
        case CHIP_REDWOOD:
        case CHIP_CEDAR:
        case CHIP_PALM:
+       case CHIP_SUMO:
+       case CHIP_SUMO2:
        case CHIP_TURKS:
        case CHIP_CAICOS:
        default:
@@ -1685,6 +1707,54 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
                rdev->config.evergreen.max_hw_contexts = 4;
                rdev->config.evergreen.sq_num_cf_insts = 1;
 
+               rdev->config.evergreen.sc_prim_fifo_size = 0x40;
+               rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30;
+               rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130;
+               break;
+       case CHIP_SUMO:
+               rdev->config.evergreen.num_ses = 1;
+               rdev->config.evergreen.max_pipes = 4;
+               rdev->config.evergreen.max_tile_pipes = 2;
+               if (rdev->pdev->device == 0x9648)
+                       rdev->config.evergreen.max_simds = 3;
+               else if ((rdev->pdev->device == 0x9647) ||
+                        (rdev->pdev->device == 0x964a))
+                       rdev->config.evergreen.max_simds = 4;
+               else
+                       rdev->config.evergreen.max_simds = 5;
+               rdev->config.evergreen.max_backends = 2 * rdev->config.evergreen.num_ses;
+               rdev->config.evergreen.max_gprs = 256;
+               rdev->config.evergreen.max_threads = 248;
+               rdev->config.evergreen.max_gs_threads = 32;
+               rdev->config.evergreen.max_stack_entries = 256;
+               rdev->config.evergreen.sx_num_of_sets = 4;
+               rdev->config.evergreen.sx_max_export_size = 256;
+               rdev->config.evergreen.sx_max_export_pos_size = 64;
+               rdev->config.evergreen.sx_max_export_smx_size = 192;
+               rdev->config.evergreen.max_hw_contexts = 8;
+               rdev->config.evergreen.sq_num_cf_insts = 2;
+
+               rdev->config.evergreen.sc_prim_fifo_size = 0x40;
+               rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30;
+               rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130;
+               break;
+       case CHIP_SUMO2:
+               rdev->config.evergreen.num_ses = 1;
+               rdev->config.evergreen.max_pipes = 4;
+               rdev->config.evergreen.max_tile_pipes = 4;
+               rdev->config.evergreen.max_simds = 2;
+               rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses;
+               rdev->config.evergreen.max_gprs = 256;
+               rdev->config.evergreen.max_threads = 248;
+               rdev->config.evergreen.max_gs_threads = 32;
+               rdev->config.evergreen.max_stack_entries = 512;
+               rdev->config.evergreen.sx_num_of_sets = 4;
+               rdev->config.evergreen.sx_max_export_size = 256;
+               rdev->config.evergreen.sx_max_export_pos_size = 64;
+               rdev->config.evergreen.sx_max_export_smx_size = 192;
+               rdev->config.evergreen.max_hw_contexts = 8;
+               rdev->config.evergreen.sq_num_cf_insts = 2;
+
                rdev->config.evergreen.sc_prim_fifo_size = 0x40;
                rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30;
                rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130;
@@ -2039,6 +2109,8 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        switch (rdev->family) {
        case CHIP_CEDAR:
        case CHIP_PALM:
+       case CHIP_SUMO:
+       case CHIP_SUMO2:
        case CHIP_CAICOS:
                /* no vertex cache */
                sq_config &= ~VC_ENABLE;
@@ -2060,6 +2132,8 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        switch (rdev->family) {
        case CHIP_CEDAR:
        case CHIP_PALM:
+       case CHIP_SUMO:
+       case CHIP_SUMO2:
                ps_thread_count = 96;
                break;
        default:
@@ -2099,6 +2173,8 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        switch (rdev->family) {
        case CHIP_CEDAR:
        case CHIP_PALM:
+       case CHIP_SUMO:
+       case CHIP_SUMO2:
        case CHIP_CAICOS:
                vgt_cache_invalidation = CACHE_INVALIDATION(TC_ONLY);
                break;
index ba06a69..57f3bc1 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "evergreend.h"
 #include "evergreen_blit_shaders.h"
+#include "cayman_blit_shaders.h"
 
 #define DI_PT_RECTLIST        0x11
 #define DI_INDEX_SIZE_16_BIT  0x0
@@ -152,6 +153,8 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr)
 
        if ((rdev->family == CHIP_CEDAR) ||
            (rdev->family == CHIP_PALM) ||
+           (rdev->family == CHIP_SUMO) ||
+           (rdev->family == CHIP_SUMO2) ||
            (rdev->family == CHIP_CAICOS))
                cp_set_surface_sync(rdev,
                                    PACKET3_TC_ACTION_ENA, 48, gpu_addr);
@@ -199,6 +202,16 @@ static void
 set_scissors(struct radeon_device *rdev, int x1, int y1,
             int x2, int y2)
 {
+       /* workaround some hw bugs */
+       if (x2 == 0)
+               x1 = 1;
+       if (y2 == 0)
+               y1 = 1;
+       if (rdev->family == CHIP_CAYMAN) {
+               if ((x2 == 1) && (y2 == 1))
+                       x2 = 2;
+       }
+
        radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2));
        radeon_ring_write(rdev, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2);
        radeon_ring_write(rdev, (x1 << 0) | (y1 << 16));
@@ -255,238 +268,284 @@ set_default_state(struct radeon_device *rdev)
        u64 gpu_addr;
        int dwords;
 
-       switch (rdev->family) {
-       case CHIP_CEDAR:
-       default:
-               num_ps_gprs = 93;
-               num_vs_gprs = 46;
-               num_temp_gprs = 4;
-               num_gs_gprs = 31;
-               num_es_gprs = 31;
-               num_hs_gprs = 23;
-               num_ls_gprs = 23;
-               num_ps_threads = 96;
-               num_vs_threads = 16;
-               num_gs_threads = 16;
-               num_es_threads = 16;
-               num_hs_threads = 16;
-               num_ls_threads = 16;
-               num_ps_stack_entries = 42;
-               num_vs_stack_entries = 42;
-               num_gs_stack_entries = 42;
-               num_es_stack_entries = 42;
-               num_hs_stack_entries = 42;
-               num_ls_stack_entries = 42;
-               break;
-       case CHIP_REDWOOD:
-               num_ps_gprs = 93;
-               num_vs_gprs = 46;
-               num_temp_gprs = 4;
-               num_gs_gprs = 31;
-               num_es_gprs = 31;
-               num_hs_gprs = 23;
-               num_ls_gprs = 23;
-               num_ps_threads = 128;
-               num_vs_threads = 20;
-               num_gs_threads = 20;
-               num_es_threads = 20;
-               num_hs_threads = 20;
-               num_ls_threads = 20;
-               num_ps_stack_entries = 42;
-               num_vs_stack_entries = 42;
-               num_gs_stack_entries = 42;
-               num_es_stack_entries = 42;
-               num_hs_stack_entries = 42;
-               num_ls_stack_entries = 42;
-               break;
-       case CHIP_JUNIPER:
-               num_ps_gprs = 93;
-               num_vs_gprs = 46;
-               num_temp_gprs = 4;
-               num_gs_gprs = 31;
-               num_es_gprs = 31;
-               num_hs_gprs = 23;
-               num_ls_gprs = 23;
-               num_ps_threads = 128;
-               num_vs_threads = 20;
-               num_gs_threads = 20;
-               num_es_threads = 20;
-               num_hs_threads = 20;
-               num_ls_threads = 20;
-               num_ps_stack_entries = 85;
-               num_vs_stack_entries = 85;
-               num_gs_stack_entries = 85;
-               num_es_stack_entries = 85;
-               num_hs_stack_entries = 85;
-               num_ls_stack_entries = 85;
-               break;
-       case CHIP_CYPRESS:
-       case CHIP_HEMLOCK:
-               num_ps_gprs = 93;
-               num_vs_gprs = 46;
-               num_temp_gprs = 4;
-               num_gs_gprs = 31;
-               num_es_gprs = 31;
-               num_hs_gprs = 23;
-               num_ls_gprs = 23;
-               num_ps_threads = 128;
-               num_vs_threads = 20;
-               num_gs_threads = 20;
-               num_es_threads = 20;
-               num_hs_threads = 20;
-               num_ls_threads = 20;
-               num_ps_stack_entries = 85;
-               num_vs_stack_entries = 85;
-               num_gs_stack_entries = 85;
-               num_es_stack_entries = 85;
-               num_hs_stack_entries = 85;
-               num_ls_stack_entries = 85;
-               break;
-       case CHIP_PALM:
-               num_ps_gprs = 93;
-               num_vs_gprs = 46;
-               num_temp_gprs = 4;
-               num_gs_gprs = 31;
-               num_es_gprs = 31;
-               num_hs_gprs = 23;
-               num_ls_gprs = 23;
-               num_ps_threads = 96;
-               num_vs_threads = 16;
-               num_gs_threads = 16;
-               num_es_threads = 16;
-               num_hs_threads = 16;
-               num_ls_threads = 16;
-               num_ps_stack_entries = 42;
-               num_vs_stack_entries = 42;
-               num_gs_stack_entries = 42;
-               num_es_stack_entries = 42;
-               num_hs_stack_entries = 42;
-               num_ls_stack_entries = 42;
-               break;
-       case CHIP_BARTS:
-               num_ps_gprs = 93;
-               num_vs_gprs = 46;
-               num_temp_gprs = 4;
-               num_gs_gprs = 31;
-               num_es_gprs = 31;
-               num_hs_gprs = 23;
-               num_ls_gprs = 23;
-               num_ps_threads = 128;
-               num_vs_threads = 20;
-               num_gs_threads = 20;
-               num_es_threads = 20;
-               num_hs_threads = 20;
-               num_ls_threads = 20;
-               num_ps_stack_entries = 85;
-               num_vs_stack_entries = 85;
-               num_gs_stack_entries = 85;
-               num_es_stack_entries = 85;
-               num_hs_stack_entries = 85;
-               num_ls_stack_entries = 85;
-               break;
-       case CHIP_TURKS:
-               num_ps_gprs = 93;
-               num_vs_gprs = 46;
-               num_temp_gprs = 4;
-               num_gs_gprs = 31;
-               num_es_gprs = 31;
-               num_hs_gprs = 23;
-               num_ls_gprs = 23;
-               num_ps_threads = 128;
-               num_vs_threads = 20;
-               num_gs_threads = 20;
-               num_es_threads = 20;
-               num_hs_threads = 20;
-               num_ls_threads = 20;
-               num_ps_stack_entries = 42;
-               num_vs_stack_entries = 42;
-               num_gs_stack_entries = 42;
-               num_es_stack_entries = 42;
-               num_hs_stack_entries = 42;
-               num_ls_stack_entries = 42;
-               break;
-       case CHIP_CAICOS:
-               num_ps_gprs = 93;
-               num_vs_gprs = 46;
-               num_temp_gprs = 4;
-               num_gs_gprs = 31;
-               num_es_gprs = 31;
-               num_hs_gprs = 23;
-               num_ls_gprs = 23;
-               num_ps_threads = 128;
-               num_vs_threads = 10;
-               num_gs_threads = 10;
-               num_es_threads = 10;
-               num_hs_threads = 10;
-               num_ls_threads = 10;
-               num_ps_stack_entries = 42;
-               num_vs_stack_entries = 42;
-               num_gs_stack_entries = 42;
-               num_es_stack_entries = 42;
-               num_hs_stack_entries = 42;
-               num_ls_stack_entries = 42;
-               break;
-       }
-
-       if ((rdev->family == CHIP_CEDAR) ||
-           (rdev->family == CHIP_PALM) ||
-           (rdev->family == CHIP_CAICOS))
-               sq_config = 0;
-       else
-               sq_config = VC_ENABLE;
-
-       sq_config |= (EXPORT_SRC_C |
-                     CS_PRIO(0) |
-                     LS_PRIO(0) |
-                     HS_PRIO(0) |
-                     PS_PRIO(0) |
-                     VS_PRIO(1) |
-                     GS_PRIO(2) |
-                     ES_PRIO(3));
-
-       sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) |
-                                 NUM_VS_GPRS(num_vs_gprs) |
-                                 NUM_CLAUSE_TEMP_GPRS(num_temp_gprs));
-       sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) |
-                                 NUM_ES_GPRS(num_es_gprs));
-       sq_gpr_resource_mgmt_3 = (NUM_HS_GPRS(num_hs_gprs) |
-                                 NUM_LS_GPRS(num_ls_gprs));
-       sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) |
-                                  NUM_VS_THREADS(num_vs_threads) |
-                                  NUM_GS_THREADS(num_gs_threads) |
-                                  NUM_ES_THREADS(num_es_threads));
-       sq_thread_resource_mgmt_2 = (NUM_HS_THREADS(num_hs_threads) |
-                                    NUM_LS_THREADS(num_ls_threads));
-       sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) |
-                                   NUM_VS_STACK_ENTRIES(num_vs_stack_entries));
-       sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) |
-                                   NUM_ES_STACK_ENTRIES(num_es_stack_entries));
-       sq_stack_resource_mgmt_3 = (NUM_HS_STACK_ENTRIES(num_hs_stack_entries) |
-                                   NUM_LS_STACK_ENTRIES(num_ls_stack_entries));
-
        /* set clear context state */
        radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0));
        radeon_ring_write(rdev, 0);
 
-       /* disable dyn gprs */
-       radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
-       radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2);
-       radeon_ring_write(rdev, 0);
+       if (rdev->family < CHIP_CAYMAN) {
+               switch (rdev->family) {
+               case CHIP_CEDAR:
+               default:
+                       num_ps_gprs = 93;
+                       num_vs_gprs = 46;
+                       num_temp_gprs = 4;
+                       num_gs_gprs = 31;
+                       num_es_gprs = 31;
+                       num_hs_gprs = 23;
+                       num_ls_gprs = 23;
+                       num_ps_threads = 96;
+                       num_vs_threads = 16;
+                       num_gs_threads = 16;
+                       num_es_threads = 16;
+                       num_hs_threads = 16;
+                       num_ls_threads = 16;
+                       num_ps_stack_entries = 42;
+                       num_vs_stack_entries = 42;
+                       num_gs_stack_entries = 42;
+                       num_es_stack_entries = 42;
+                       num_hs_stack_entries = 42;
+                       num_ls_stack_entries = 42;
+                       break;
+               case CHIP_REDWOOD:
+                       num_ps_gprs = 93;
+                       num_vs_gprs = 46;
+                       num_temp_gprs = 4;
+                       num_gs_gprs = 31;
+                       num_es_gprs = 31;
+                       num_hs_gprs = 23;
+                       num_ls_gprs = 23;
+                       num_ps_threads = 128;
+                       num_vs_threads = 20;
+                       num_gs_threads = 20;
+                       num_es_threads = 20;
+                       num_hs_threads = 20;
+                       num_ls_threads = 20;
+                       num_ps_stack_entries = 42;
+                       num_vs_stack_entries = 42;
+                       num_gs_stack_entries = 42;
+                       num_es_stack_entries = 42;
+                       num_hs_stack_entries = 42;
+                       num_ls_stack_entries = 42;
+                       break;
+               case CHIP_JUNIPER:
+                       num_ps_gprs = 93;
+                       num_vs_gprs = 46;
+                       num_temp_gprs = 4;
+                       num_gs_gprs = 31;
+                       num_es_gprs = 31;
+                       num_hs_gprs = 23;
+                       num_ls_gprs = 23;
+                       num_ps_threads = 128;
+                       num_vs_threads = 20;
+                       num_gs_threads = 20;
+                       num_es_threads = 20;
+                       num_hs_threads = 20;
+                       num_ls_threads = 20;
+                       num_ps_stack_entries = 85;
+                       num_vs_stack_entries = 85;
+                       num_gs_stack_entries = 85;
+                       num_es_stack_entries = 85;
+                       num_hs_stack_entries = 85;
+                       num_ls_stack_entries = 85;
+                       break;
+               case CHIP_CYPRESS:
+               case CHIP_HEMLOCK:
+                       num_ps_gprs = 93;
+                       num_vs_gprs = 46;
+                       num_temp_gprs = 4;
+                       num_gs_gprs = 31;
+                       num_es_gprs = 31;
+                       num_hs_gprs = 23;
+                       num_ls_gprs = 23;
+                       num_ps_threads = 128;
+                       num_vs_threads = 20;
+                       num_gs_threads = 20;
+                       num_es_threads = 20;
+                       num_hs_threads = 20;
+                       num_ls_threads = 20;
+                       num_ps_stack_entries = 85;
+                       num_vs_stack_entries = 85;
+                       num_gs_stack_entries = 85;
+                       num_es_stack_entries = 85;
+                       num_hs_stack_entries = 85;
+                       num_ls_stack_entries = 85;
+                       break;
+               case CHIP_PALM:
+                       num_ps_gprs = 93;
+                       num_vs_gprs = 46;
+                       num_temp_gprs = 4;
+                       num_gs_gprs = 31;
+                       num_es_gprs = 31;
+                       num_hs_gprs = 23;
+                       num_ls_gprs = 23;
+                       num_ps_threads = 96;
+                       num_vs_threads = 16;
+                       num_gs_threads = 16;
+                       num_es_threads = 16;
+                       num_hs_threads = 16;
+                       num_ls_threads = 16;
+                       num_ps_stack_entries = 42;
+                       num_vs_stack_entries = 42;
+                       num_gs_stack_entries = 42;
+                       num_es_stack_entries = 42;
+                       num_hs_stack_entries = 42;
+                       num_ls_stack_entries = 42;
+                       break;
+               case CHIP_SUMO:
+                       num_ps_gprs = 93;
+                       num_vs_gprs = 46;
+                       num_temp_gprs = 4;
+                       num_gs_gprs = 31;
+                       num_es_gprs = 31;
+                       num_hs_gprs = 23;
+                       num_ls_gprs = 23;
+                       num_ps_threads = 96;
+                       num_vs_threads = 25;
+                       num_gs_threads = 25;
+                       num_es_threads = 25;
+                       num_hs_threads = 25;
+                       num_ls_threads = 25;
+                       num_ps_stack_entries = 42;
+                       num_vs_stack_entries = 42;
+                       num_gs_stack_entries = 42;
+                       num_es_stack_entries = 42;
+                       num_hs_stack_entries = 42;
+                       num_ls_stack_entries = 42;
+                       break;
+               case CHIP_SUMO2:
+                       num_ps_gprs = 93;
+                       num_vs_gprs = 46;
+                       num_temp_gprs = 4;
+                       num_gs_gprs = 31;
+                       num_es_gprs = 31;
+                       num_hs_gprs = 23;
+                       num_ls_gprs = 23;
+                       num_ps_threads = 96;
+                       num_vs_threads = 25;
+                       num_gs_threads = 25;
+                       num_es_threads = 25;
+                       num_hs_threads = 25;
+                       num_ls_threads = 25;
+                       num_ps_stack_entries = 85;
+                       num_vs_stack_entries = 85;
+                       num_gs_stack_entries = 85;
+                       num_es_stack_entries = 85;
+                       num_hs_stack_entries = 85;
+                       num_ls_stack_entries = 85;
+                       break;
+               case CHIP_BARTS:
+                       num_ps_gprs = 93;
+                       num_vs_gprs = 46;
+                       num_temp_gprs = 4;
+                       num_gs_gprs = 31;
+                       num_es_gprs = 31;
+                       num_hs_gprs = 23;
+                       num_ls_gprs = 23;
+                       num_ps_threads = 128;
+                       num_vs_threads = 20;
+                       num_gs_threads = 20;
+                       num_es_threads = 20;
+                       num_hs_threads = 20;
+                       num_ls_threads = 20;
+                       num_ps_stack_entries = 85;
+                       num_vs_stack_entries = 85;
+                       num_gs_stack_entries = 85;
+                       num_es_stack_entries = 85;
+                       num_hs_stack_entries = 85;
+                       num_ls_stack_entries = 85;
+                       break;
+               case CHIP_TURKS:
+                       num_ps_gprs = 93;
+                       num_vs_gprs = 46;
+                       num_temp_gprs = 4;
+                       num_gs_gprs = 31;
+                       num_es_gprs = 31;
+                       num_hs_gprs = 23;
+                       num_ls_gprs = 23;
+                       num_ps_threads = 128;
+                       num_vs_threads = 20;
+                       num_gs_threads = 20;
+                       num_es_threads = 20;
+                       num_hs_threads = 20;
+                       num_ls_threads = 20;
+                       num_ps_stack_entries = 42;
+                       num_vs_stack_entries = 42;
+                       num_gs_stack_entries = 42;
+                       num_es_stack_entries = 42;
+                       num_hs_stack_entries = 42;
+                       num_ls_stack_entries = 42;
+                       break;
+               case CHIP_CAICOS:
+                       num_ps_gprs = 93;
+                       num_vs_gprs = 46;
+                       num_temp_gprs = 4;
+                       num_gs_gprs = 31;
+                       num_es_gprs = 31;
+                       num_hs_gprs = 23;
+                       num_ls_gprs = 23;
+                       num_ps_threads = 128;
+                       num_vs_threads = 10;
+                       num_gs_threads = 10;
+                       num_es_threads = 10;
+                       num_hs_threads = 10;
+                       num_ls_threads = 10;
+                       num_ps_stack_entries = 42;
+                       num_vs_stack_entries = 42;
+                       num_gs_stack_entries = 42;
+                       num_es_stack_entries = 42;
+                       num_hs_stack_entries = 42;
+                       num_ls_stack_entries = 42;
+                       break;
+               }
 
-       /* SQ config */
-       radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11));
-       radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2);
-       radeon_ring_write(rdev, sq_config);
-       radeon_ring_write(rdev, sq_gpr_resource_mgmt_1);
-       radeon_ring_write(rdev, sq_gpr_resource_mgmt_2);
-       radeon_ring_write(rdev, sq_gpr_resource_mgmt_3);
-       radeon_ring_write(rdev, 0);
-       radeon_ring_write(rdev, 0);
-       radeon_ring_write(rdev, sq_thread_resource_mgmt);
-       radeon_ring_write(rdev, sq_thread_resource_mgmt_2);
-       radeon_ring_write(rdev, sq_stack_resource_mgmt_1);
-       radeon_ring_write(rdev, sq_stack_resource_mgmt_2);
-       radeon_ring_write(rdev, sq_stack_resource_mgmt_3);
+               if ((rdev->family == CHIP_CEDAR) ||
+                   (rdev->family == CHIP_PALM) ||
+                   (rdev->family == CHIP_SUMO) ||
+                   (rdev->family == CHIP_SUMO2) ||
+                   (rdev->family == CHIP_CAICOS))
+                       sq_config = 0;
+               else
+                       sq_config = VC_ENABLE;
+
+               sq_config |= (EXPORT_SRC_C |
+                             CS_PRIO(0) |
+                             LS_PRIO(0) |
+                             HS_PRIO(0) |
+                             PS_PRIO(0) |
+                             VS_PRIO(1) |
+                             GS_PRIO(2) |
+                             ES_PRIO(3));
+
+               sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) |
+                                         NUM_VS_GPRS(num_vs_gprs) |
+                                         NUM_CLAUSE_TEMP_GPRS(num_temp_gprs));
+               sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) |
+                                         NUM_ES_GPRS(num_es_gprs));
+               sq_gpr_resource_mgmt_3 = (NUM_HS_GPRS(num_hs_gprs) |
+                                         NUM_LS_GPRS(num_ls_gprs));
+               sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) |
+                                          NUM_VS_THREADS(num_vs_threads) |
+                                          NUM_GS_THREADS(num_gs_threads) |
+                                          NUM_ES_THREADS(num_es_threads));
+               sq_thread_resource_mgmt_2 = (NUM_HS_THREADS(num_hs_threads) |
+                                            NUM_LS_THREADS(num_ls_threads));
+               sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) |
+                                           NUM_VS_STACK_ENTRIES(num_vs_stack_entries));
+               sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) |
+                                           NUM_ES_STACK_ENTRIES(num_es_stack_entries));
+               sq_stack_resource_mgmt_3 = (NUM_HS_STACK_ENTRIES(num_hs_stack_entries) |
+                                           NUM_LS_STACK_ENTRIES(num_ls_stack_entries));
+
+               /* disable dyn gprs */
+               radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
+               radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2);
+               radeon_ring_write(rdev, 0);
+
+               /* SQ config */
+               radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11));
+               radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2);
+               radeon_ring_write(rdev, sq_config);
+               radeon_ring_write(rdev, sq_gpr_resource_mgmt_1);
+               radeon_ring_write(rdev, sq_gpr_resource_mgmt_2);
+               radeon_ring_write(rdev, sq_gpr_resource_mgmt_3);
+               radeon_ring_write(rdev, 0);
+               radeon_ring_write(rdev, 0);
+               radeon_ring_write(rdev, sq_thread_resource_mgmt);
+               radeon_ring_write(rdev, sq_thread_resource_mgmt_2);
+               radeon_ring_write(rdev, sq_stack_resource_mgmt_1);
+               radeon_ring_write(rdev, sq_stack_resource_mgmt_2);
+               radeon_ring_write(rdev, sq_stack_resource_mgmt_3);
+       }
 
        /* CONTEXT_CONTROL */
        radeon_ring_write(rdev, 0xc0012800);
@@ -560,7 +619,10 @@ int evergreen_blit_init(struct radeon_device *rdev)
        mutex_init(&rdev->r600_blit.mutex);
        rdev->r600_blit.state_offset = 0;
 
-       rdev->r600_blit.state_len = evergreen_default_size;
+       if (rdev->family < CHIP_CAYMAN)
+               rdev->r600_blit.state_len = evergreen_default_size;
+       else
+               rdev->r600_blit.state_len = cayman_default_size;
 
        dwords = rdev->r600_blit.state_len;
        while (dwords & 0xf) {
@@ -572,11 +634,17 @@ int evergreen_blit_init(struct radeon_device *rdev)
        obj_size = ALIGN(obj_size, 256);
 
        rdev->r600_blit.vs_offset = obj_size;
-       obj_size += evergreen_vs_size * 4;
+       if (rdev->family < CHIP_CAYMAN)
+               obj_size += evergreen_vs_size * 4;
+       else
+               obj_size += cayman_vs_size * 4;
        obj_size = ALIGN(obj_size, 256);
 
        rdev->r600_blit.ps_offset = obj_size;
-       obj_size += evergreen_ps_size * 4;
+       if (rdev->family < CHIP_CAYMAN)
+               obj_size += evergreen_ps_size * 4;
+       else
+               obj_size += cayman_ps_size * 4;
        obj_size = ALIGN(obj_size, 256);
 
        r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
@@ -599,16 +667,29 @@ int evergreen_blit_init(struct radeon_device *rdev)
                return r;
        }
 
-       memcpy_toio(ptr + rdev->r600_blit.state_offset,
-                   evergreen_default_state, rdev->r600_blit.state_len * 4);
-
-       if (num_packet2s)
-               memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4),
-                           packet2s, num_packet2s * 4);
-       for (i = 0; i < evergreen_vs_size; i++)
-               *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(evergreen_vs[i]);
-       for (i = 0; i < evergreen_ps_size; i++)
-               *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(evergreen_ps[i]);
+       if (rdev->family < CHIP_CAYMAN) {
+               memcpy_toio(ptr + rdev->r600_blit.state_offset,
+                           evergreen_default_state, rdev->r600_blit.state_len * 4);
+
+               if (num_packet2s)
+                       memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4),
+                                   packet2s, num_packet2s * 4);
+               for (i = 0; i < evergreen_vs_size; i++)
+                       *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(evergreen_vs[i]);
+               for (i = 0; i < evergreen_ps_size; i++)
+                       *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(evergreen_ps[i]);
+       } else {
+               memcpy_toio(ptr + rdev->r600_blit.state_offset,
+                           cayman_default_state, rdev->r600_blit.state_len * 4);
+
+               if (num_packet2s)
+                       memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4),
+                                   packet2s, num_packet2s * 4);
+               for (i = 0; i < cayman_vs_size; i++)
+                       *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(cayman_vs[i]);
+               for (i = 0; i < cayman_ps_size; i++)
+                       *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(cayman_ps[i]);
+       }
        radeon_bo_kunmap(rdev->r600_blit.shader_obj);
        radeon_bo_unreserve(rdev->r600_blit.shader_obj);
 
index f37e91e..1636e34 100644 (file)
 #define                SE_DB_BUSY                                      (1 << 30)
 #define                SE_CB_BUSY                                      (1 << 31)
 /* evergreen */
+#define        CG_THERMAL_CTRL                                 0x72c
+#define                TOFFSET_MASK                            0x00003FE0
+#define                TOFFSET_SHIFT                           5
 #define        CG_MULT_THERMAL_STATUS                          0x740
 #define                ASIC_T(x)                               ((x) << 16)
-#define                ASIC_T_MASK                             0x7FF0000
+#define                ASIC_T_MASK                             0x07FF0000
 #define                ASIC_T_SHIFT                            16
+#define        CG_TS0_STATUS                                   0x760
+#define                TS0_ADC_DOUT_MASK                       0x000003FF
+#define                TS0_ADC_DOUT_SHIFT                      0
 /* APU */
 #define        CG_THERMAL_STATUS                               0x678
 
index b205ba1..16caafe 100644 (file)
@@ -1387,14 +1387,12 @@ static int cayman_startup(struct radeon_device *rdev)
                return r;
        cayman_gpu_init(rdev);
 
-#if 0
-       r = cayman_blit_init(rdev);
+       r = evergreen_blit_init(rdev);
        if (r) {
-               cayman_blit_fini(rdev);
+               evergreen_blit_fini(rdev);
                rdev->asic->copy = NULL;
                dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
        }
-#endif
 
        /* allocate wb buffer */
        r = radeon_wb_init(rdev);
@@ -1452,7 +1450,7 @@ int cayman_resume(struct radeon_device *rdev)
 
 int cayman_suspend(struct radeon_device *rdev)
 {
-       /* int r; */
+       int r;
 
        /* FIXME: we should wait for ring to be empty */
        cayman_cp_enable(rdev, false);
@@ -1461,14 +1459,13 @@ int cayman_suspend(struct radeon_device *rdev)
        radeon_wb_disable(rdev);
        cayman_pcie_gart_disable(rdev);
 
-#if 0
        /* unpin shaders bo */
        r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
        if (likely(r == 0)) {
                radeon_bo_unpin(rdev->r600_blit.shader_obj);
                radeon_bo_unreserve(rdev->r600_blit.shader_obj);
        }
-#endif
+
        return 0;
 }
 
@@ -1580,7 +1577,7 @@ int cayman_init(struct radeon_device *rdev)
 
 void cayman_fini(struct radeon_device *rdev)
 {
-       /* cayman_blit_fini(rdev); */
+       evergreen_blit_fini(rdev);
        cayman_cp_fini(rdev);
        r600_irq_fini(rdev);
        radeon_wb_fini(rdev);
index 6f27593..d74d4d7 100644 (file)
@@ -87,6 +87,10 @@ MODULE_FIRMWARE("radeon/CYPRESS_rlc.bin");
 MODULE_FIRMWARE("radeon/PALM_pfp.bin");
 MODULE_FIRMWARE("radeon/PALM_me.bin");
 MODULE_FIRMWARE("radeon/SUMO_rlc.bin");
+MODULE_FIRMWARE("radeon/SUMO_pfp.bin");
+MODULE_FIRMWARE("radeon/SUMO_me.bin");
+MODULE_FIRMWARE("radeon/SUMO2_pfp.bin");
+MODULE_FIRMWARE("radeon/SUMO2_me.bin");
 
 int r600_debugfs_mc_info_init(struct radeon_device *rdev);
 
@@ -2024,6 +2028,14 @@ int r600_init_microcode(struct radeon_device *rdev)
                chip_name = "PALM";
                rlc_chip_name = "SUMO";
                break;
+       case CHIP_SUMO:
+               chip_name = "SUMO";
+               rlc_chip_name = "SUMO";
+               break;
+       case CHIP_SUMO2:
+               chip_name = "SUMO2";
+               rlc_chip_name = "SUMO";
+               break;
        default: BUG();
        }
 
index fd18be9..909bda8 100644 (file)
@@ -71,20 +71,21 @@ struct r600_cs_track {
        u64                     db_bo_mc;
 };
 
-#define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc }
-#define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc }
-#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 3, 0 }
-#define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc }
-#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 6, 0 }
-#define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc }
-#define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0 }
-#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16, vc }
+#define FMT_8_BIT(fmt, vc)   [fmt] = { 1, 1, 1, vc, CHIP_R600 }
+#define FMT_16_BIT(fmt, vc)  [fmt] = { 1, 1, 2, vc, CHIP_R600 }
+#define FMT_24_BIT(fmt)      [fmt] = { 1, 1, 3,  0, CHIP_R600 }
+#define FMT_32_BIT(fmt, vc)  [fmt] = { 1, 1, 4, vc, CHIP_R600 }
+#define FMT_48_BIT(fmt)      [fmt] = { 1, 1, 6,  0, CHIP_R600 }
+#define FMT_64_BIT(fmt, vc)  [fmt] = { 1, 1, 8, vc, CHIP_R600 }
+#define FMT_96_BIT(fmt)      [fmt] = { 1, 1, 12, 0, CHIP_R600 }
+#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16,vc, CHIP_R600 }
 
 struct gpu_formats {
        unsigned blockwidth;
        unsigned blockheight;
        unsigned blocksize;
        unsigned valid_color;
+       enum radeon_family min_family;
 };
 
 static const struct gpu_formats color_formats_table[] = {
@@ -154,7 +155,11 @@ static const struct gpu_formats color_formats_table[] = {
        [V_038004_FMT_BC3] = { 4, 4, 16, 0 },
        [V_038004_FMT_BC4] = { 4, 4, 8, 0 },
        [V_038004_FMT_BC5] = { 4, 4, 16, 0},
+       [V_038004_FMT_BC6] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */
+       [V_038004_FMT_BC7] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */
 
+       /* The other Evergreen formats */
+       [V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR},
 };
 
 static inline bool fmt_is_valid_color(u32 format)
@@ -168,11 +173,14 @@ static inline bool fmt_is_valid_color(u32 format)
        return false;
 }
 
-static inline bool fmt_is_valid_texture(u32 format)
+static inline bool fmt_is_valid_texture(u32 format, enum radeon_family family)
 {
        if (format >= ARRAY_SIZE(color_formats_table))
                return false;
        
+       if (family < color_formats_table[format].min_family)
+               return false;
+
        if (color_formats_table[format].blockwidth > 0)
                return true;
 
@@ -1325,7 +1333,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 i
                return -EINVAL;
        }
        format = G_038004_DATA_FORMAT(word1);
-       if (!fmt_is_valid_texture(format)) {
+       if (!fmt_is_valid_texture(format, p->family)) {
                dev_warn(p->dev, "%s:%d texture invalid format %d\n",
                         __func__, __LINE__, format);
                return -EINVAL;
index b2b944b..f140a0d 100644 (file)
 #define     V_038004_FMT_BC3                           0x00000033
 #define     V_038004_FMT_BC4                           0x00000034
 #define     V_038004_FMT_BC5                           0x00000035
+#define     V_038004_FMT_BC6                           0x00000036
+#define     V_038004_FMT_BC7                           0x00000037
+#define     V_038004_FMT_32_AS_32_32_32_32             0x00000038
 #define R_038010_SQ_TEX_RESOURCE_WORD4_0             0x038010
 #define   S_038010_FORMAT_COMP_X(x)                    (((x) & 0x3) << 0)
 #define   G_038010_FORMAT_COMP_X(x)                    (((x) >> 0) & 0x3)
index d948265..9bd162f 100644 (file)
@@ -906,9 +906,9 @@ static struct radeon_asic cayman_asic = {
        .get_vblank_counter = &evergreen_get_vblank_counter,
        .fence_ring_emit = &r600_fence_ring_emit,
        .cs_parse = &evergreen_cs_parse,
-       .copy_blit = NULL,
-       .copy_dma = NULL,
-       .copy = NULL,
+       .copy_blit = &evergreen_copy_blit,
+       .copy_dma = &evergreen_copy_blit,
+       .copy = &evergreen_copy_blit,
        .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
        .get_memory_clock = &radeon_atom_get_memory_clock,
@@ -1020,6 +1020,8 @@ int radeon_asic_init(struct radeon_device *rdev)
                rdev->asic = &evergreen_asic;
                break;
        case CHIP_PALM:
+       case CHIP_SUMO:
+       case CHIP_SUMO2:
                rdev->asic = &sumo_asic;
                break;
        case CHIP_BARTS:
index 8c19169..fae00c0 100644 (file)
@@ -228,6 +228,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        parser.filp = filp;
        parser.rdev = rdev;
        parser.dev = rdev->dev;
+       parser.family = rdev->family;
        r = radeon_cs_parser_init(&parser, data);
        if (r) {
                DRM_ERROR("Failed to initialize parser !\n");
index 5b61364..e680501 100644 (file)
@@ -82,6 +82,8 @@ static const char radeon_family_name[][16] = {
        "CYPRESS",
        "HEMLOCK",
        "PALM",
+       "SUMO",
+       "SUMO2",
        "BARTS",
        "TURKS",
        "CAICOS",
@@ -752,6 +754,7 @@ int radeon_device_init(struct radeon_device *rdev,
        dma_bits = rdev->need_dma32 ? 32 : 40;
        r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
        if (r) {
+               rdev->need_dma32 = true;
                printk(KERN_WARNING "radeon: No suitable DMA available.\n");
        }
 
index ae247ee..292f73f 100644 (file)
@@ -264,6 +264,8 @@ static void radeon_unpin_work_func(struct work_struct *__work)
                radeon_bo_unreserve(work->old_rbo);
        } else
                DRM_ERROR("failed to reserve buffer after flip\n");
+
+       drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
        kfree(work);
 }
 
@@ -371,6 +373,8 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        new_radeon_fb = to_radeon_framebuffer(fb);
        /* schedule unpin of the old buffer */
        obj = old_radeon_fb->obj;
+       /* take a reference to the old object */
+       drm_gem_object_reference(obj);
        rbo = gem_to_radeon_bo(obj);
        work->old_rbo = rbo;
        INIT_WORK(&work->work, radeon_unpin_work_func);
@@ -378,12 +382,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        /* We borrow the event spin lock for protecting unpin_work */
        spin_lock_irqsave(&dev->event_lock, flags);
        if (radeon_crtc->unpin_work) {
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-               kfree(work);
-               radeon_fence_unref(&fence);
-
                DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
-               return -EBUSY;
+               r = -EBUSY;
+               goto unlock_free;
        }
        radeon_crtc->unpin_work = work;
        radeon_crtc->deferred_flip_completion = 0;
@@ -497,6 +498,8 @@ pflip_cleanup1:
 pflip_cleanup:
        spin_lock_irqsave(&dev->event_lock, flags);
        radeon_crtc->unpin_work = NULL;
+unlock_free:
+       drm_gem_object_unreference_unlocked(old_radeon_fb->obj);
        spin_unlock_irqrestore(&dev->event_lock, flags);
        radeon_fence_unref(&fence);
        kfree(work);
index 1d33060..73dfbe8 100644 (file)
@@ -113,7 +113,7 @@ int radeon_benchmarking = 0;
 int radeon_testing = 0;
 int radeon_connector_table = 0;
 int radeon_tv = 1;
-int radeon_audio = 1;
+int radeon_audio = 0;
 int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
 int radeon_pcie_gen2 = 0;
@@ -151,7 +151,7 @@ module_param_named(connector_table, radeon_connector_table, int, 0444);
 MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
 module_param_named(tv, radeon_tv, int, 0444);
 
-MODULE_PARM_DESC(audio, "Audio enable (0 = disable)");
+MODULE_PARM_DESC(audio, "Audio enable (1 = enable)");
 module_param_named(audio, radeon_audio, int, 0444);
 
 MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)");
index 1b55755..03f124d 100644 (file)
@@ -954,10 +954,15 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
        int dp_lane_count = 0;
        int connector_object_id = 0;
        int igp_lane_info = 0;
+       int dig_encoder = dig->dig_encoder;
 
-       if (action == ATOM_TRANSMITTER_ACTION_INIT)
+       if (action == ATOM_TRANSMITTER_ACTION_INIT) {
                connector = radeon_get_connector_for_encoder_init(encoder);
-       else
+               /* just needed to avoid bailing in the encoder check.  the encoder
+                * isn't used for init
+                */
+               dig_encoder = 0;
+       } else
                connector = radeon_get_connector_for_encoder(encoder);
 
        if (connector) {
@@ -973,7 +978,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
        }
 
        /* no dig encoder assigned */
-       if (dig->dig_encoder == -1)
+       if (dig_encoder == -1)
                return;
 
        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
@@ -1023,7 +1028,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
 
                if (dig->linkb)
                        args.v3.acConfig.ucLinkSel = 1;
-               if (dig->dig_encoder & 1)
+               if (dig_encoder & 1)
                        args.v3.acConfig.ucEncoderSel = 1;
 
                /* Select the PLL for the PHY
@@ -1073,7 +1078,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                                args.v3.acConfig.fDualLinkConnector = 1;
                }
        } else if (ASIC_IS_DCE32(rdev)) {
-               args.v2.acConfig.ucEncoderSel = dig->dig_encoder;
+               args.v2.acConfig.ucEncoderSel = dig_encoder;
                if (dig->linkb)
                        args.v2.acConfig.ucLinkSel = 1;
 
@@ -1100,7 +1105,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
        } else {
                args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
 
-               if (dig->dig_encoder)
+               if (dig_encoder)
                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
                else
                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
index 6f1d9e5..ec2f1ea 100644 (file)
@@ -81,6 +81,8 @@ enum radeon_family {
        CHIP_CYPRESS,
        CHIP_HEMLOCK,
        CHIP_PALM,
+       CHIP_SUMO,
+       CHIP_SUMO2,
        CHIP_BARTS,
        CHIP_TURKS,
        CHIP_CAICOS,
index 86eda1e..aaa19dc 100644 (file)
@@ -487,6 +487,7 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
        case THERMAL_TYPE_RV6XX:
        case THERMAL_TYPE_RV770:
        case THERMAL_TYPE_EVERGREEN:
+       case THERMAL_TYPE_NI:
        case THERMAL_TYPE_SUMO:
                rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev);
                if (IS_ERR(rdev->pm.int_hwmon_dev)) {
index 92f1900..ea49752 100644 (file)
@@ -758,6 +758,5 @@ r600 0x9400
 0x00009714 VC_ENHANCE
 0x00009830 DB_DEBUG
 0x00009838 DB_WATERMARKS
-0x00028D28 DB_SRESULTS_COMPARE_STATE0
 0x00028D44 DB_ALPHA_TO_MASK
 0x00009700 VC_CNTL
index de3d246..85e9379 100644 (file)
@@ -296,7 +296,7 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
                 * If the TjMax is not plausible, an assumption
                 * will be used
                 */
-               if (val > 80 && val < 120) {
+               if (val) {
                        dev_info(dev, "TjMax is %d C.\n", val);
                        return val * 1000;
                }
@@ -304,24 +304,9 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
 
        /*
         * An assumption is made for early CPUs and unreadable MSR.
-        * NOTE: the given value may not be correct.
+        * NOTE: the calculated value may not be correct.
         */
-
-       switch (c->x86_model) {
-       case 0xe:
-       case 0xf:
-       case 0x16:
-       case 0x1a:
-               dev_warn(dev, "TjMax is assumed as 100 C!\n");
-               return 100000;
-       case 0x17:
-       case 0x1c:              /* Atom CPUs */
-               return adjust_tjmax(c, id, dev);
-       default:
-               dev_warn(dev, "CPU (model=0x%x) is not supported yet,"
-                       " using default TjMax of 100C.\n", c->x86_model);
-               return 100000;
-       }
+       return adjust_tjmax(c, id, dev);
 }
 
 static void __devinit get_ucode_rev_on_cpu(void *edx)
@@ -341,7 +326,7 @@ static int get_pkg_tjmax(unsigned int cpu, struct device *dev)
        err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
        if (!err) {
                val = (eax >> 16) & 0xff;
-               if (val > 80 && val < 120)
+               if (val)
                        return val * 1000;
        }
        dev_warn(dev, "Unable to read Pkg-TjMax from CPU:%u\n", cpu);
index 0f9fc40..e855d3b 100644 (file)
@@ -136,15 +136,29 @@ static int max6642_detect(struct i2c_client *client,
        if (man_id != 0x4D)
                return -ENODEV;
 
+       /* sanity check */
+       if (i2c_smbus_read_byte_data(client, 0x04) != 0x4D
+           || i2c_smbus_read_byte_data(client, 0x06) != 0x4D
+           || i2c_smbus_read_byte_data(client, 0xff) != 0x4D)
+               return -ENODEV;
+
        /*
         * We read the config and status register, the 4 lower bits in the
         * config register should be zero and bit 5, 3, 1 and 0 should be
         * zero in the status register.
         */
        reg_config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG);
+       if ((reg_config & 0x0f) != 0x00)
+               return -ENODEV;
+
+       /* in between, another round of sanity checks */
+       if (i2c_smbus_read_byte_data(client, 0x04) != reg_config
+           || i2c_smbus_read_byte_data(client, 0x06) != reg_config
+           || i2c_smbus_read_byte_data(client, 0xff) != reg_config)
+               return -ENODEV;
+
        reg_status = i2c_smbus_read_byte_data(client, MAX6642_REG_R_STATUS);
-       if (((reg_config & 0x0f) != 0x00) ||
-           ((reg_status & 0x2b) != 0x00))
+       if ((reg_status & 0x2b) != 0x00)
                return -ENODEV;
 
        strlcpy(info->type, "max6642", I2C_NAME_SIZE);
@@ -246,7 +260,7 @@ static SENSOR_DEVICE_ATTR_2(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
                            set_temp_max, 0, MAX6642_REG_W_LOCAL_HIGH);
 static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
                            set_temp_max, 1, MAX6642_REG_W_REMOTE_HIGH);
-static SENSOR_DEVICE_ATTR(temp_fault, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
 static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
 static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
 
@@ -256,7 +270,7 @@ static struct attribute *max6642_attributes[] = {
        &sensor_dev_attr_temp1_max.dev_attr.attr,
        &sensor_dev_attr_temp2_max.dev_attr.attr,
 
-       &sensor_dev_attr_temp_fault.dev_attr.attr,
+       &sensor_dev_attr_temp2_fault.dev_attr.attr,
        &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
        &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
        NULL
index 4dc1ca3..7c327b5 100644 (file)
@@ -60,8 +60,6 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
        int act_len, ret;
        u8 buf[64];
 
-       if (slen > sizeof(buf))
-               slen = sizeof(buf);
        memcpy(&buf[0], sbuf, slen);
        buf[60] = state->seq++;
 
@@ -180,30 +178,37 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 {
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
        int ret = 0, inc, i = 0;
+       u8 buf[52]; /* 4 + 48 (I2C WR USB command header + I2C WR max) */
 
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
                return -EAGAIN;
 
        while (i < num) {
                if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
-                       u8 buf[6];
+                       if (msg[i].len > 2 || msg[i+1].len > 60) {
+                               ret = -EOPNOTSUPP;
+                               break;
+                       }
                        buf[0] = CMD_I2C_READ;
                        buf[1] = (msg[i].addr << 1) | 0x01;
                        buf[2] = msg[i].buf[0];
                        buf[3] = msg[i].buf[1];
                        buf[4] = msg[i].len-1;
                        buf[5] = msg[i+1].len;
-                       ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf,
+                       ret = anysee_ctrl_msg(d, buf, 6, msg[i+1].buf,
                                msg[i+1].len);
                        inc = 2;
                } else {
-                       u8 buf[4+msg[i].len];
+                       if (msg[i].len > 48) {
+                               ret = -EOPNOTSUPP;
+                               break;
+                       }
                        buf[0] = CMD_I2C_WRITE;
                        buf[1] = (msg[i].addr << 1);
                        buf[2] = msg[i].len;
                        buf[3] = 0x01;
                        memcpy(&buf[4], msg[i].buf, msg[i].len);
-                       ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+                       ret = anysee_ctrl_msg(d, buf, 4 + msg[i].len, NULL, 0);
                        inc = 1;
                }
                if (ret)
index af5263c..7b42ace 100644 (file)
@@ -213,14 +213,14 @@ int __must_check media_devnode_register(struct media_devnode *mdev)
 
        /* Part 1: Find a free minor number */
        mutex_lock(&media_devnode_lock);
-       minor = find_next_zero_bit(media_devnode_nums, 0, MEDIA_NUM_DEVICES);
+       minor = find_next_zero_bit(media_devnode_nums, MEDIA_NUM_DEVICES, 0);
        if (minor == MEDIA_NUM_DEVICES) {
                mutex_unlock(&media_devnode_lock);
                printk(KERN_ERR "could not get a free minor\n");
                return -ENFILE;
        }
 
-       set_bit(mdev->minor, media_devnode_nums);
+       set_bit(minor, media_devnode_nums);
        mutex_unlock(&media_devnode_lock);
 
        mdev->minor = minor;
index 2354336..934185c 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/delay.h>
 #include <media/cx25840.h>
 #include <linux/firmware.h>
-#include <staging/altera.h>
 
+#include "../../../staging/altera-stapl/altera.h"
 #include "cx23885.h"
 #include "tuner-xc2028.h"
 #include "netup-init.h"
diff --git a/drivers/media/video/gspca/coarse_expo_autogain.h b/drivers/media/video/gspca/coarse_expo_autogain.h
deleted file mode 100644 (file)
index 1cb9d94..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Auto gain algorithm for camera's with a coarse exposure control
- *
- * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.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
- */
-
-/* Autogain + exposure algorithm for cameras with a coarse exposure control
-   (usually this means we can only control the clockdiv to change exposure)
-   As changing the clockdiv so that the fps drops from 30 to 15 fps for
-   example, will lead to a huge exposure change (it effectively doubles),
-   this algorithm normally tries to only adjust the gain (between 40 and
-   80 %) and if that does not help, only then changes exposure. This leads
-   to a much more stable image then using the knee algorithm which at
-   certain points of the knee graph will only try to adjust exposure,
-   which leads to oscilating as one exposure step is huge.
-
-   Note this assumes that the sd struct for the cam in question has
-   exp_too_high_cnt and exp_too_high_cnt int members for use by this function.
-
-   Returns 0 if no changes were made, 1 if the gain and or exposure settings
-   where changed. */
-static int gspca_coarse_grained_expo_autogain(struct gspca_dev *gspca_dev,
-       int avg_lum, int desired_avg_lum, int deadzone)
-{
-       int i, steps, gain, orig_gain, exposure, orig_exposure;
-       int gain_low, gain_high;
-       const struct ctrl *gain_ctrl = NULL;
-       const struct ctrl *exposure_ctrl = NULL;
-       struct sd *sd = (struct sd *) gspca_dev;
-       int retval = 0;
-
-       for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
-               if (gspca_dev->ctrl_dis & (1 << i))
-                       continue;
-               if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
-                       gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
-               if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
-                       exposure_ctrl = &gspca_dev->sd_desc->ctrls[i];
-       }
-       if (!gain_ctrl || !exposure_ctrl) {
-               PDEBUG(D_ERR, "Error: gspca_coarse_grained_expo_autogain "
-                       "called on cam without gain or exposure");
-               return 0;
-       }
-
-       if (gain_ctrl->get(gspca_dev, &gain) ||
-           exposure_ctrl->get(gspca_dev, &exposure))
-               return 0;
-
-       orig_gain = gain;
-       orig_exposure = exposure;
-       gain_low =
-               (gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 2;
-       gain_low += gain_ctrl->qctrl.minimum;
-       gain_high =
-               (gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 4;
-       gain_high += gain_ctrl->qctrl.minimum;
-
-       /* If we are of a multiple of deadzone, do multiple steps to reach the
-          desired lumination fast (with the risc of a slight overshoot) */
-       steps = (desired_avg_lum - avg_lum) / deadzone;
-
-       PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
-               avg_lum, desired_avg_lum, steps);
-
-       if ((gain + steps) > gain_high &&
-           sd->exposure < exposure_ctrl->qctrl.maximum) {
-               gain = gain_high;
-               sd->exp_too_low_cnt++;
-       } else if ((gain + steps) < gain_low &&
-                  sd->exposure > exposure_ctrl->qctrl.minimum) {
-               gain = gain_low;
-               sd->exp_too_high_cnt++;
-       } else {
-               gain += steps;
-               if (gain > gain_ctrl->qctrl.maximum)
-                       gain = gain_ctrl->qctrl.maximum;
-               else if (gain < gain_ctrl->qctrl.minimum)
-                       gain = gain_ctrl->qctrl.minimum;
-               sd->exp_too_high_cnt = 0;
-               sd->exp_too_low_cnt = 0;
-       }
-
-       if (sd->exp_too_high_cnt > 3) {
-               exposure--;
-               sd->exp_too_high_cnt = 0;
-       } else if (sd->exp_too_low_cnt > 3) {
-               exposure++;
-               sd->exp_too_low_cnt = 0;
-       }
-
-       if (gain != orig_gain) {
-               gain_ctrl->set(gspca_dev, gain);
-               retval = 1;
-       }
-       if (exposure != orig_exposure) {
-               exposure_ctrl->set(gspca_dev, exposure);
-               retval = 1;
-       }
-
-       return retval;
-}
index 36a46fc..057e287 100644 (file)
@@ -609,7 +609,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
  * buffers, there are some pretty strict real time constraints for
  * isochronous transfer for larger frame sizes).
  */
-/*jfm: this value works well for 1600x1200, but not 800x600 - see isoc_init */
+/*jfm: this value does not work for 800x600 - see isoc_init */
 #define OVFX2_BULK_SIZE (13 * 4096)
 
 /* I2C registers */
@@ -3307,6 +3307,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
 
        gspca_dev->cam.ctrls = sd->ctrls;
        sd->quality = QUALITY_DEF;
+       sd->frame_rate = 15;
 
        return 0;
 }
@@ -3469,7 +3470,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
                                ARRAY_SIZE(init_519_ov7660));
                write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660));
                sd->gspca_dev.curr_mode = 1;    /* 640x480 */
-               sd->frame_rate = 15;
                ov519_set_mode(sd);
                ov519_set_fr(sd);
                sd->ctrls[COLORS].max = 4;      /* 0..4 */
@@ -3511,7 +3511,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
 
        switch (sd->bridge) {
        case BRIDGE_OVFX2:
-               if (gspca_dev->width == 1600)
+               if (gspca_dev->width != 800)
                        gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE;
                else
                        gspca_dev->cam.bulk_size = 7 * 4096;
@@ -4478,7 +4478,7 @@ static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev,
        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 
        /* A short read signals EOF */
-       if (len < OVFX2_BULK_SIZE) {
+       if (len < gspca_dev->cam.bulk_size) {
                /* If the frame is short, and it is one of the first ones
                   the sensor and bridge are still syncing, so drop it. */
                if (sd->first_frame) {
index 6415aff..81b8a60 100644 (file)
@@ -60,7 +60,7 @@ struct sd {
 
        u32 pktsz;                      /* (used by pkt_scan) */
        u16 npkt;
-       u8 nchg;
+       s8 nchg;
        s8 short_mark;
 
        u8 quality;                     /* image quality */
index b538dce..a14a84a 100644 (file)
 #define HDCS_SLEEP_MODE                (1 << 1)
 
 #define HDCS_DEFAULT_EXPOSURE  48
-#define HDCS_DEFAULT_GAIN      128
+#define HDCS_DEFAULT_GAIN      50
 
 static int hdcs_probe_1x00(struct sd *sd);
 static int hdcs_probe_1020(struct sd *sd);
index a4e4dfd..0fb7552 100644 (file)
@@ -1328,6 +1328,8 @@ int ivtv_init_on_first_open(struct ivtv *itv)
        if (!itv->has_cx23415)
                write_reg_sync(0x03, IVTV_REG_DMACONTROL);
 
+       ivtv_s_std_enc(itv, &itv->tuner_std);
+
        /* Default interrupts enabled. For the PVR350 this includes the
           decoder VSYNC interrupt, which is always on. It is not only used
           during decoding but also by the OSD.
@@ -1336,12 +1338,10 @@ int ivtv_init_on_first_open(struct ivtv *itv)
        if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
                ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
                ivtv_set_osd_alpha(itv);
-       }
-       else
+               ivtv_s_std_dec(itv, &itv->tuner_std);
+       } else {
                ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
-
-       /* For cards with video out, this call needs interrupts enabled */
-       ivtv_s_std(NULL, &fh, &itv->tuner_std);
+       }
 
        /* Setup initial controls */
        cx2341x_handler_setup(&itv->cxhdl);
index 14a1cea..02c5ade 100644 (file)
@@ -280,8 +280,6 @@ int ivtv_firmware_restart(struct ivtv *itv)
 {
        int rc = 0;
        v4l2_std_id std;
-       struct ivtv_open_id fh;
-       fh.itv = itv;
 
        if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
                /* Display test image during restart */
@@ -301,14 +299,19 @@ int ivtv_firmware_restart(struct ivtv *itv)
        /* Allow settings to reload */
        ivtv_mailbox_cache_invalidate(itv);
 
-       /* Restore video standard */
+       /* Restore encoder video standard */
        std = itv->std;
        itv->std = 0;
-       ivtv_s_std(NULL, &fh, &std);
+       ivtv_s_std_enc(itv, &std);
 
        if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
                ivtv_init_mpeg_decoder(itv);
 
+               /* Restore decoder video standard */
+               std = itv->std_out;
+               itv->std_out = 0;
+               ivtv_s_std_dec(itv, &std);
+
                /* Restore framebuffer if active */
                if (itv->ivtvfb_restore)
                        itv->ivtvfb_restore(itv);
index 1689783..f9e347d 100644 (file)
@@ -1071,28 +1071,8 @@ static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
        return 0;
 }
 
-int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
+void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
 {
-       DEFINE_WAIT(wait);
-       struct ivtv *itv = fh2id(fh)->itv;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       int f;
-
-       if ((*std & V4L2_STD_ALL) == 0)
-               return -EINVAL;
-
-       if (*std == itv->std)
-               return 0;
-
-       if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
-           atomic_read(&itv->capturing) > 0 ||
-           atomic_read(&itv->decoding) > 0) {
-               /* Switching standard would turn off the radio or mess
-                  with already running streams, prevent that by
-                  returning EBUSY. */
-               return -EBUSY;
-       }
-
        itv->std = *std;
        itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
        itv->is_50hz = !itv->is_60hz;
@@ -1106,48 +1086,79 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
        if (itv->hw_flags & IVTV_HW_CX25840)
                itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
 
-       IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
-
        /* Tuner */
        ivtv_call_all(itv, core, s_std, itv->std);
+}
 
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
-               /* set display standard */
-               itv->std_out = *std;
-               itv->is_out_60hz = itv->is_60hz;
-               itv->is_out_50hz = itv->is_50hz;
-               ivtv_call_all(itv, video, s_std_output, itv->std_out);
-
-               /*
-                * The next firmware call is time sensitive. Time it to
-                * avoid risk of a hard lock, by trying to ensure the call
-                * happens within the first 100 lines of the top field.
-                * Make 4 attempts to sync to the decoder before giving up.
-                */
-               for (f = 0; f < 4; f++) {
-                       prepare_to_wait(&itv->vsync_waitq, &wait,
-                                       TASK_UNINTERRUPTIBLE);
-                       if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
-                               break;
-                       schedule_timeout(msecs_to_jiffies(25));
-               }
-               finish_wait(&itv->vsync_waitq, &wait);
-
-               if (f == 4)
-                       IVTV_WARN("Mode change failed to sync to decoder\n");
-
-               ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
-               itv->main_rect.left = itv->main_rect.top = 0;
-               itv->main_rect.width = 720;
-               itv->main_rect.height = itv->cxhdl.height;
-               ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
-                       720, itv->main_rect.height, 0, 0);
-               yi->main_rect = itv->main_rect;
-               if (!itv->osd_info) {
-                       yi->osd_full_w = 720;
-                       yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
-               }
+void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       DEFINE_WAIT(wait);
+       int f;
+
+       /* set display standard */
+       itv->std_out = *std;
+       itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
+       itv->is_out_50hz = !itv->is_out_60hz;
+       ivtv_call_all(itv, video, s_std_output, itv->std_out);
+
+       /*
+        * The next firmware call is time sensitive. Time it to
+        * avoid risk of a hard lock, by trying to ensure the call
+        * happens within the first 100 lines of the top field.
+        * Make 4 attempts to sync to the decoder before giving up.
+        */
+       for (f = 0; f < 4; f++) {
+               prepare_to_wait(&itv->vsync_waitq, &wait,
+                               TASK_UNINTERRUPTIBLE);
+               if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
+                       break;
+               schedule_timeout(msecs_to_jiffies(25));
        }
+       finish_wait(&itv->vsync_waitq, &wait);
+
+       if (f == 4)
+               IVTV_WARN("Mode change failed to sync to decoder\n");
+
+       ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
+       itv->main_rect.left = 0;
+       itv->main_rect.top = 0;
+       itv->main_rect.width = 720;
+       itv->main_rect.height = itv->is_out_50hz ? 576 : 480;
+       ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+               720, itv->main_rect.height, 0, 0);
+       yi->main_rect = itv->main_rect;
+       if (!itv->osd_info) {
+               yi->osd_full_w = 720;
+               yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
+       }
+}
+
+int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if ((*std & V4L2_STD_ALL) == 0)
+               return -EINVAL;
+
+       if (*std == itv->std)
+               return 0;
+
+       if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
+           atomic_read(&itv->capturing) > 0 ||
+           atomic_read(&itv->decoding) > 0) {
+               /* Switching standard would mess with already running
+                  streams, prevent that by returning EBUSY. */
+               return -EBUSY;
+       }
+
+       IVTV_DEBUG_INFO("Switching standard to %llx.\n",
+               (unsigned long long)itv->std);
+
+       ivtv_s_std_enc(itv, std);
+       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
+               ivtv_s_std_dec(itv, std);
+
        return 0;
 }
 
index 58f0034..89185ca 100644 (file)
@@ -27,7 +27,8 @@ u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt);
 void ivtv_set_osd_alpha(struct ivtv *itv);
 int ivtv_set_speed(struct ivtv *itv, int speed);
 void ivtv_set_funcs(struct video_device *vdev);
-int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std);
+void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std);
+void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std);
 int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
 int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
 long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
index 9426833..e7794dc 100644 (file)
@@ -589,7 +589,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
                v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1);
                /* Avoid unpredictable PCI bus hang - disable video clocks */
                v4l2_subdev_call(itv->sd_video, video, s_stream, 0);
-               ivtv_msleep_timeout(300, 1);
+               ivtv_msleep_timeout(300, 0);
                ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
                v4l2_subdev_call(itv->sd_video, video, s_stream, 1);
        }
@@ -834,7 +834,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
                }
 
                /* Handle any pending interrupts */
-               ivtv_msleep_timeout(100, 1);
+               ivtv_msleep_timeout(100, 0);
        }
 
        atomic_dec(&itv->capturing);
index b6eb51c..293db80 100644 (file)
@@ -71,7 +71,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
           Turning this signal on and off can confuse certain
           TVs. As far as I can tell there is no reason not to
           transmit this signal. */
-       if ((itv->std & V4L2_STD_625_50) && !enabled) {
+       if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
                enabled = 1;
                mode = 0x08;  /* 4x3 full format */
        }
index 1724745..6b7c9c8 100644 (file)
@@ -247,7 +247,7 @@ static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords
 
 static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
 {
-       int osd_height_limit = itv->is_50hz ? 576 : 480;
+       int osd_height_limit = itv->is_out_50hz ? 576 : 480;
 
        /* Only fail if resolution too high, otherwise fudge the start coords. */
        if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH))
@@ -471,9 +471,9 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar
                        vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
                                        FB_VBLANK_HAVE_VSYNC;
                        trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
-                       if (itv->is_50hz && trace > 312)
+                       if (itv->is_out_50hz && trace > 312)
                                trace -= 312;
-                       else if (itv->is_60hz && trace > 262)
+                       else if (itv->is_out_60hz && trace > 262)
                                trace -= 262;
                        if (trace == 1)
                                vblank.flags |= FB_VBLANK_VSYNCING;
@@ -656,7 +656,7 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
        IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
 
        /* Set base references for mode calcs. */
-       if (itv->is_50hz) {
+       if (itv->is_out_50hz) {
                pixclock = 84316;
                hlimit = 776;
                vlimit = 591;
@@ -784,12 +784,12 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
           If the margins are too large, just center the screen
           (enforcing margins causes too many problems) */
 
-       if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) {
+       if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
                var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
-       }
-       if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) {
-               var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2);
-       }
+
+       if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
+               var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) -
+                       var->yres) / 2);
 
        /* Maintain overall 'size' for a constant refresh rate */
        var->right_margin = hlimit - var->left_margin - var->xres;
@@ -836,7 +836,12 @@ static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf
        u32 osd_pan_index;
        struct ivtv *itv = (struct ivtv *) info->par;
 
-       osd_pan_index = (var->xoffset + (var->yoffset * var->xres_virtual))*var->bits_per_pixel/8;
+       if (var->yoffset + info->var.yres > info->var.yres_virtual ||
+           var->xoffset + info->var.xres > info->var.xres_virtual)
+               return -EINVAL;
+
+       osd_pan_index = var->yoffset * info->fix.line_length
+                     + var->xoffset * info->var.bits_per_pixel / 8;
        write_reg(osd_pan_index, 0x02A0C);
 
        /* Pass this info back the yuv handler */
@@ -1003,19 +1008,21 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
        /* Hardware coords start at 0, user coords start at 1. */
        osd_left--;
 
-       start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
+       start_window.left = osd_left >= 0 ?
+                osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
 
        oi->display_byte_stride =
                        start_window.width * oi->bytes_per_pixel;
 
        /* Vertical size & position */
 
-       max_height = itv->is_50hz ? 576 : 480;
+       max_height = itv->is_out_50hz ? 576 : 480;
 
        if (osd_yres > max_height)
                osd_yres = max_height;
 
-       start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400;
+       start_window.height = osd_yres ?
+               osd_yres : itv->is_out_50hz ? 480 : 400;
 
        /* Check vertical start (osd_upper). */
        if (osd_upper + start_window.height > max_height + 1) {
index 472a693..c9fd04e 100644 (file)
@@ -391,7 +391,7 @@ static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus)
        };
        int i;
 
-       dev_dbg(isp->dev, "");
+       dev_dbg(isp->dev, "ISP IRQ: ");
 
        for (i = 0; i < ARRAY_SIZE(name); i++) {
                if ((1 << i) & irqstatus)
index 3988643..4e4d412 100644 (file)
@@ -1512,7 +1512,7 @@ static int video_dev_create(struct soc_camera_device *icd)
  */
 static int soc_camera_video_start(struct soc_camera_device *icd)
 {
-       struct device_type *type = icd->vdev->dev.type;
+       const struct device_type *type = icd->vdev->dev.type;
        int ret;
 
        if (!icd->dev.parent)
index ede7852..c3ab0c8 100644 (file)
@@ -30,7 +30,7 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain,
        struct uvc_entity *remote;
        unsigned int i;
        u8 remote_pad;
-       int ret;
+       int ret = 0;
 
        for (i = 0; i < entity->num_pads; ++i) {
                struct media_entity *source;
index 259ece0..5b2e215 100644 (file)
@@ -435,6 +435,9 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
                reg = regulator_get(host->dev, "vmmc_aux");
                host->vcc_aux = IS_ERR(reg) ? NULL : reg;
 
+               /* For eMMC do not power off when not in sleep state */
+               if (mmc_slot(host).no_regulator_off_init)
+                       return 0;
                /*
                * UGLY HACK:  workaround regulator framework bugs.
                * When the bootloader leaves a supply active, it's
index c85f744..094308e 100644 (file)
@@ -51,6 +51,7 @@ obj-$(CONFIG_X86_VISWS) += setup-irq.o
 obj-$(CONFIG_MN10300) += setup-bus.o
 obj-$(CONFIG_MICROBLAZE) += setup-bus.o
 obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
+obj-$(CONFIG_SPARC_LEON) += setup-bus.o setup-irq.o
 
 #
 # ACPI Related PCI FW Functions
index 59f17ac..f02c34d 100644 (file)
@@ -3388,7 +3388,7 @@ static void __init init_iommu_pm_ops(void)
 }
 
 #else
-static inline int init_iommu_pm_ops(void) { }
+static inline void init_iommu_pm_ops(void) {}
 #endif /* CONFIG_PM */
 
 /*
index f822e13..ce2aabf 100644 (file)
@@ -1051,4 +1051,13 @@ config RTC_DRV_TILE
          Enable support for the Linux driver side of the Tilera
          hypervisor's real-time clock interface.
 
+config RTC_DRV_PUV3
+       tristate "PKUnity v3 RTC support"
+       depends on ARCH_PUV3
+       help
+         This enables support for the RTC in the PKUnity-v3 SoCs.
+
+         This drive can also be built as a module. If so, the module
+         will be called rtc-puv3.
+
 endif # RTC_CLASS
index 213d725..0ffefe8 100644 (file)
@@ -78,6 +78,7 @@ obj-$(CONFIG_RTC_DRV_PCF50633)        += rtc-pcf50633.o
 obj-$(CONFIG_RTC_DRV_PL030)    += rtc-pl030.o
 obj-$(CONFIG_RTC_DRV_PL031)    += rtc-pl031.o
 obj-$(CONFIG_RTC_DRV_PS3)      += rtc-ps3.o
+obj-$(CONFIG_RTC_DRV_PUV3)     += rtc-puv3.o
 obj-$(CONFIG_RTC_DRV_PXA)      += rtc-pxa.o
 obj-$(CONFIG_RTC_DRV_R9701)    += rtc-r9701.o
 obj-$(CONFIG_RTC_DRV_RP5C01)   += rtc-rp5c01.o
index 1a84b3e..7317d3b 100644 (file)
@@ -189,7 +189,7 @@ static int __devinit m41t93_probe(struct spi_device *spi)
 
 static int __devexit m41t93_remove(struct spi_device *spi)
 {
-       struct rtc_device *rtc = platform_get_drvdata(spi);
+       struct rtc_device *rtc = spi_get_drvdata(spi);
 
        if (rtc)
                rtc_device_unregister(rtc);
diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c
new file mode 100644 (file)
index 0000000..46f14b8
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * RTC driver code specific to PKUnity SoC and UniCore ISA
+ *
+ *     Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *     Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/clk.h>
+#include <linux/log2.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+#include <mach/hardware.h>
+
+static struct resource *puv3_rtc_mem;
+
+static int puv3_rtc_alarmno = IRQ_RTCAlarm;
+static int puv3_rtc_tickno  = IRQ_RTC;
+
+static DEFINE_SPINLOCK(puv3_rtc_pie_lock);
+
+/* IRQ Handlers */
+static irqreturn_t puv3_rtc_alarmirq(int irq, void *id)
+{
+       struct rtc_device *rdev = id;
+
+       writel(readl(RTC_RTSR) | RTC_RTSR_AL, RTC_RTSR);
+       rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t puv3_rtc_tickirq(int irq, void *id)
+{
+       struct rtc_device *rdev = id;
+
+       writel(readl(RTC_RTSR) | RTC_RTSR_HZ, RTC_RTSR);
+       rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
+       return IRQ_HANDLED;
+}
+
+/* Update control registers */
+static void puv3_rtc_setaie(int to)
+{
+       unsigned int tmp;
+
+       pr_debug("%s: aie=%d\n", __func__, to);
+
+       tmp = readl(RTC_RTSR) & ~RTC_RTSR_ALE;
+
+       if (to)
+               tmp |= RTC_RTSR_ALE;
+
+       writel(tmp, RTC_RTSR);
+}
+
+static int puv3_rtc_setpie(struct device *dev, int enabled)
+{
+       unsigned int tmp;
+
+       pr_debug("%s: pie=%d\n", __func__, enabled);
+
+       spin_lock_irq(&puv3_rtc_pie_lock);
+       tmp = readl(RTC_RTSR) & ~RTC_RTSR_HZE;
+
+       if (enabled)
+               tmp |= RTC_RTSR_HZE;
+
+       writel(tmp, RTC_RTSR);
+       spin_unlock_irq(&puv3_rtc_pie_lock);
+
+       return 0;
+}
+
+/* Time read/write */
+static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
+{
+       rtc_time_to_tm(readl(RTC_RCNR), rtc_tm);
+
+       pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
+                rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
+                rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
+
+       return 0;
+}
+
+static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+       unsigned long rtc_count = 0;
+
+       pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",
+                tm->tm_year, tm->tm_mon, tm->tm_mday,
+                tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+       rtc_tm_to_time(tm, &rtc_count);
+       writel(rtc_count, RTC_RCNR);
+
+       return 0;
+}
+
+static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct rtc_time *alm_tm = &alrm->time;
+
+       rtc_time_to_tm(readl(RTC_RTAR), alm_tm);
+
+       alrm->enabled = readl(RTC_RTSR) & RTC_RTSR_ALE;
+
+       pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
+                alrm->enabled,
+                alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
+                alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
+
+       return 0;
+}
+
+static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct rtc_time *tm = &alrm->time;
+       unsigned long rtcalarm_count = 0;
+
+       pr_debug("puv3_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
+                alrm->enabled,
+                tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
+                tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
+
+       rtc_tm_to_time(tm, &rtcalarm_count);
+       writel(rtcalarm_count, RTC_RTAR);
+
+       puv3_rtc_setaie(alrm->enabled);
+
+       if (alrm->enabled)
+               enable_irq_wake(puv3_rtc_alarmno);
+       else
+               disable_irq_wake(puv3_rtc_alarmno);
+
+       return 0;
+}
+
+static int puv3_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+       seq_printf(seq, "periodic_IRQ\t: %s\n",
+                    (readl(RTC_RTSR) & RTC_RTSR_HZE) ? "yes" : "no");
+       return 0;
+}
+
+static int puv3_rtc_open(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = request_irq(puv3_rtc_alarmno, puv3_rtc_alarmirq,
+                         IRQF_DISABLED,  "pkunity-rtc alarm", rtc_dev);
+
+       if (ret) {
+               dev_err(dev, "IRQ%d error %d\n", puv3_rtc_alarmno, ret);
+               return ret;
+       }
+
+       ret = request_irq(puv3_rtc_tickno, puv3_rtc_tickirq,
+                         IRQF_DISABLED,  "pkunity-rtc tick", rtc_dev);
+
+       if (ret) {
+               dev_err(dev, "IRQ%d error %d\n", puv3_rtc_tickno, ret);
+               goto tick_err;
+       }
+
+       return ret;
+
+ tick_err:
+       free_irq(puv3_rtc_alarmno, rtc_dev);
+       return ret;
+}
+
+static void puv3_rtc_release(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
+
+       /* do not clear AIE here, it may be needed for wake */
+       puv3_rtc_setpie(dev, 0);
+       free_irq(puv3_rtc_alarmno, rtc_dev);
+       free_irq(puv3_rtc_tickno, rtc_dev);
+}
+
+static const struct rtc_class_ops puv3_rtcops = {
+       .open           = puv3_rtc_open,
+       .release        = puv3_rtc_release,
+       .read_time      = puv3_rtc_gettime,
+       .set_time       = puv3_rtc_settime,
+       .read_alarm     = puv3_rtc_getalarm,
+       .set_alarm      = puv3_rtc_setalarm,
+       .proc           = puv3_rtc_proc,
+};
+
+static void puv3_rtc_enable(struct platform_device *pdev, int en)
+{
+       if (!en) {
+               writel(readl(RTC_RTSR) & ~RTC_RTSR_HZE, RTC_RTSR);
+       } else {
+               /* re-enable the device, and check it is ok */
+               if ((readl(RTC_RTSR) & RTC_RTSR_HZE) == 0) {
+                       dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
+                       writel(readl(RTC_RTSR) | RTC_RTSR_HZE, RTC_RTSR);
+               }
+       }
+}
+
+static int puv3_rtc_remove(struct platform_device *dev)
+{
+       struct rtc_device *rtc = platform_get_drvdata(dev);
+
+       platform_set_drvdata(dev, NULL);
+       rtc_device_unregister(rtc);
+
+       puv3_rtc_setpie(&dev->dev, 0);
+       puv3_rtc_setaie(0);
+
+       release_resource(puv3_rtc_mem);
+       kfree(puv3_rtc_mem);
+
+       return 0;
+}
+
+static int puv3_rtc_probe(struct platform_device *pdev)
+{
+       struct rtc_device *rtc;
+       struct resource *res;
+       int ret;
+
+       pr_debug("%s: probe=%p\n", __func__, pdev);
+
+       /* find the IRQs */
+       puv3_rtc_tickno = platform_get_irq(pdev, 1);
+       if (puv3_rtc_tickno < 0) {
+               dev_err(&pdev->dev, "no irq for rtc tick\n");
+               return -ENOENT;
+       }
+
+       puv3_rtc_alarmno = platform_get_irq(pdev, 0);
+       if (puv3_rtc_alarmno < 0) {
+               dev_err(&pdev->dev, "no irq for alarm\n");
+               return -ENOENT;
+       }
+
+       pr_debug("PKUnity_rtc: tick irq %d, alarm irq %d\n",
+                puv3_rtc_tickno, puv3_rtc_alarmno);
+
+       /* get the memory region */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to get memory region resource\n");
+               return -ENOENT;
+       }
+
+       puv3_rtc_mem = request_mem_region(res->start,
+                                        res->end-res->start+1,
+                                        pdev->name);
+
+       if (puv3_rtc_mem == NULL) {
+               dev_err(&pdev->dev, "failed to reserve memory region\n");
+               ret = -ENOENT;
+               goto err_nores;
+       }
+
+       puv3_rtc_enable(pdev, 1);
+
+       /* register RTC and exit */
+       rtc = rtc_device_register("pkunity", &pdev->dev, &puv3_rtcops,
+                                 THIS_MODULE);
+
+       if (IS_ERR(rtc)) {
+               dev_err(&pdev->dev, "cannot attach rtc\n");
+               ret = PTR_ERR(rtc);
+               goto err_nortc;
+       }
+
+       /* platform setup code should have handled this; sigh */
+       if (!device_can_wakeup(&pdev->dev))
+               device_init_wakeup(&pdev->dev, 1);
+
+       platform_set_drvdata(pdev, rtc);
+       return 0;
+
+ err_nortc:
+       puv3_rtc_enable(pdev, 0);
+       release_resource(puv3_rtc_mem);
+
+ err_nores:
+       return ret;
+}
+
+#ifdef CONFIG_PM
+
+static int ticnt_save;
+
+static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       /* save RTAR for anyone using periodic interrupts */
+       ticnt_save = readl(RTC_RTAR);
+       puv3_rtc_enable(pdev, 0);
+       return 0;
+}
+
+static int puv3_rtc_resume(struct platform_device *pdev)
+{
+       puv3_rtc_enable(pdev, 1);
+       writel(ticnt_save, RTC_RTAR);
+       return 0;
+}
+#else
+#define puv3_rtc_suspend NULL
+#define puv3_rtc_resume  NULL
+#endif
+
+static struct platform_driver puv3_rtcdrv = {
+       .probe          = puv3_rtc_probe,
+       .remove         = __devexit_p(puv3_rtc_remove),
+       .suspend        = puv3_rtc_suspend,
+       .resume         = puv3_rtc_resume,
+       .driver         = {
+               .name   = "PKUnity-v3-RTC",
+               .owner  = THIS_MODULE,
+       }
+};
+
+static char __initdata banner[] = "PKUnity-v3 RTC, (c) 2009 PKUnity Co.\n";
+
+static int __init puv3_rtc_init(void)
+{
+       printk(banner);
+       return platform_driver_register(&puv3_rtcdrv);
+}
+
+static void __exit puv3_rtc_exit(void)
+{
+       platform_driver_unregister(&puv3_rtcdrv);
+}
+
+module_init(puv3_rtc_init);
+module_exit(puv3_rtc_exit);
+
+MODULE_DESCRIPTION("RTC Driver for the PKUnity v3 chip");
+MODULE_AUTHOR("Hu Dongliang");
+MODULE_LICENSE("GPL v2");
index 55e8f72..570d4da 100644 (file)
@@ -416,7 +416,7 @@ static void process_buffer_error(struct qdio_q *q, int count)
 
        /* special handling for no target buffer empty */
        if ((!q->is_input_q &&
-           (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) {
+           (q->sbal[q->first_to_check]->element[15].sflags) == 0x10)) {
                qperf_inc(q, target_full);
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x",
                              q->first_to_check);
@@ -427,8 +427,8 @@ static void process_buffer_error(struct qdio_q *q, int count)
        DBF_ERROR((q->is_input_q) ? "IN:%2d" : "OUT:%2d", q->nr);
        DBF_ERROR("FTC:%3d C:%3d", q->first_to_check, count);
        DBF_ERROR("F14:%2x F15:%2x",
-                 q->sbal[q->first_to_check]->element[14].flags & 0xff,
-                 q->sbal[q->first_to_check]->element[15].flags & 0xff);
+                 q->sbal[q->first_to_check]->element[14].sflags,
+                 q->sbal[q->first_to_check]->element[15].sflags);
 
        /*
         * Interrupts may be avoided as long as the error is present
index 55c6aa1..d3cee33 100644 (file)
@@ -361,7 +361,7 @@ enum qeth_header_ids {
 
 static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale)
 {
-       return (sbale->flags & SBAL_FLAGS_LAST_ENTRY);
+       return (sbale->eflags & SBAL_EFLAGS_LAST_ENTRY);
 }
 
 enum qeth_qdio_buffer_states {
index 503678a..dd08f7b 100644 (file)
@@ -890,7 +890,7 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
        struct sk_buff *skb;
 
        /* is PCI flag set on buffer? */
-       if (buf->buffer->element[0].flags & 0x40)
+       if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ)
                atomic_dec(&queue->set_pci_flags_count);
 
        skb = skb_dequeue(&buf->skb_list);
@@ -906,9 +906,11 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
                buf->is_header[i] = 0;
                buf->buffer->element[i].length = 0;
                buf->buffer->element[i].addr = NULL;
-               buf->buffer->element[i].flags = 0;
+               buf->buffer->element[i].eflags = 0;
+               buf->buffer->element[i].sflags = 0;
        }
-       buf->buffer->element[15].flags = 0;
+       buf->buffer->element[15].eflags = 0;
+       buf->buffer->element[15].sflags = 0;
        buf->next_element_to_fill = 0;
        atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
 }
@@ -2368,9 +2370,10 @@ static int qeth_init_input_buffer(struct qeth_card *card,
                buf->buffer->element[i].length = PAGE_SIZE;
                buf->buffer->element[i].addr =  pool_entry->elements[i];
                if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
-                       buf->buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY;
+                       buf->buffer->element[i].eflags = SBAL_EFLAGS_LAST_ENTRY;
                else
-                       buf->buffer->element[i].flags = 0;
+                       buf->buffer->element[i].eflags = 0;
+               buf->buffer->element[i].sflags = 0;
        }
        return 0;
 }
@@ -2718,11 +2721,11 @@ int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf,
        if (qdio_error) {
                QETH_CARD_TEXT(card, 2, dbftext);
                QETH_CARD_TEXT_(card, 2, " F15=%02X",
-                              buf->element[15].flags & 0xff);
+                              buf->element[15].sflags);
                QETH_CARD_TEXT_(card, 2, " F14=%02X",
-                              buf->element[14].flags & 0xff);
+                              buf->element[14].sflags);
                QETH_CARD_TEXT_(card, 2, " qerr=%X", qdio_error);
-               if ((buf->element[15].flags & 0xff) == 0x12) {
+               if ((buf->element[15].sflags) == 0x12) {
                        card->stats.rx_dropped++;
                        return 0;
                } else
@@ -2798,7 +2801,7 @@ EXPORT_SYMBOL_GPL(qeth_queue_input_buffer);
 static int qeth_handle_send_error(struct qeth_card *card,
                struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err)
 {
-       int sbalf15 = buffer->buffer->element[15].flags & 0xff;
+       int sbalf15 = buffer->buffer->element[15].sflags;
 
        QETH_CARD_TEXT(card, 6, "hdsnderr");
        if (card->info.type == QETH_CARD_TYPE_IQD) {
@@ -2907,8 +2910,8 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
 
        for (i = index; i < index + count; ++i) {
                buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
-               buf->buffer->element[buf->next_element_to_fill - 1].flags |=
-                               SBAL_FLAGS_LAST_ENTRY;
+               buf->buffer->element[buf->next_element_to_fill - 1].eflags |=
+                               SBAL_EFLAGS_LAST_ENTRY;
 
                if (queue->card->info.type == QETH_CARD_TYPE_IQD)
                        continue;
@@ -2921,7 +2924,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
                                /* it's likely that we'll go to packing
                                 * mode soon */
                                atomic_inc(&queue->set_pci_flags_count);
-                               buf->buffer->element[0].flags |= 0x40;
+                               buf->buffer->element[0].sflags |= SBAL_SFLAGS0_PCI_REQ;
                        }
                } else {
                        if (!atomic_read(&queue->set_pci_flags_count)) {
@@ -2934,7 +2937,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
                                 * further send was requested by the stack
                                 */
                                atomic_inc(&queue->set_pci_flags_count);
-                               buf->buffer->element[0].flags |= 0x40;
+                               buf->buffer->element[0].sflags |= SBAL_SFLAGS0_PCI_REQ;
                        }
                }
        }
@@ -3180,20 +3183,20 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
                if (!length) {
                        if (first_lap)
                                if (skb_shinfo(skb)->nr_frags)
-                                       buffer->element[element].flags =
-                                               SBAL_FLAGS_FIRST_FRAG;
+                                       buffer->element[element].eflags =
+                                               SBAL_EFLAGS_FIRST_FRAG;
                                else
-                                       buffer->element[element].flags = 0;
+                                       buffer->element[element].eflags = 0;
                        else
-                               buffer->element[element].flags =
-                                   SBAL_FLAGS_MIDDLE_FRAG;
+                               buffer->element[element].eflags =
+                                   SBAL_EFLAGS_MIDDLE_FRAG;
                } else {
                        if (first_lap)
-                               buffer->element[element].flags =
-                                   SBAL_FLAGS_FIRST_FRAG;
+                               buffer->element[element].eflags =
+                                   SBAL_EFLAGS_FIRST_FRAG;
                        else
-                               buffer->element[element].flags =
-                                   SBAL_FLAGS_MIDDLE_FRAG;
+                               buffer->element[element].eflags =
+                                   SBAL_EFLAGS_MIDDLE_FRAG;
                }
                data += length_here;
                element++;
@@ -3205,12 +3208,12 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
                buffer->element[element].addr = (char *)page_to_phys(frag->page)
                        + frag->page_offset;
                buffer->element[element].length = frag->size;
-               buffer->element[element].flags = SBAL_FLAGS_MIDDLE_FRAG;
+               buffer->element[element].eflags = SBAL_EFLAGS_MIDDLE_FRAG;
                element++;
        }
 
-       if (buffer->element[element - 1].flags)
-               buffer->element[element - 1].flags = SBAL_FLAGS_LAST_FRAG;
+       if (buffer->element[element - 1].eflags)
+               buffer->element[element - 1].eflags = SBAL_EFLAGS_LAST_FRAG;
        *next_element_to_fill = element;
 }
 
@@ -3234,7 +3237,7 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
                /*fill first buffer entry only with header information */
                buffer->element[element].addr = skb->data;
                buffer->element[element].length = hdr_len;
-               buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
+               buffer->element[element].eflags = SBAL_EFLAGS_FIRST_FRAG;
                buf->next_element_to_fill++;
                skb->data += hdr_len;
                skb->len  -= hdr_len;
@@ -3246,7 +3249,7 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
                buffer->element[element].addr = hdr;
                buffer->element[element].length = sizeof(struct qeth_hdr) +
                                                        hd_len;
-               buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
+               buffer->element[element].eflags = SBAL_EFLAGS_FIRST_FRAG;
                buf->is_header[element] = 1;
                buf->next_element_to_fill++;
        }
index 8512b5c..022fb6a 100644 (file)
@@ -640,7 +640,7 @@ static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
 }
 
 static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
-                                               u32 fsf_cmd, u32 sbtype,
+                                               u32 fsf_cmd, u8 sbtype,
                                                mempool_t *pool)
 {
        struct zfcp_adapter *adapter = qdio->adapter;
@@ -841,7 +841,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
-                                 SBAL_FLAGS0_TYPE_READ,
+                                 SBAL_SFLAGS0_TYPE_READ,
                                  qdio->adapter->pool.scsi_abort);
        if (IS_ERR(req)) {
                req = NULL;
@@ -1012,7 +1012,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC,
-                                 SBAL_FLAGS0_TYPE_WRITE_READ, pool);
+                                 SBAL_SFLAGS0_TYPE_WRITE_READ, pool);
 
        if (IS_ERR(req)) {
                ret = PTR_ERR(req);
@@ -1110,7 +1110,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS,
-                                 SBAL_FLAGS0_TYPE_WRITE_READ, NULL);
+                                 SBAL_SFLAGS0_TYPE_WRITE_READ, NULL);
 
        if (IS_ERR(req)) {
                ret = PTR_ERR(req);
@@ -1156,7 +1156,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
-                                 SBAL_FLAGS0_TYPE_READ,
+                                 SBAL_SFLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1198,7 +1198,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
                goto out_unlock;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
-                                 SBAL_FLAGS0_TYPE_READ, NULL);
+                                 SBAL_SFLAGS0_TYPE_READ, NULL);
 
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
@@ -1250,7 +1250,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
-                                 SBAL_FLAGS0_TYPE_READ,
+                                 SBAL_SFLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1296,7 +1296,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
                goto out_unlock;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
-                                 SBAL_FLAGS0_TYPE_READ, NULL);
+                                 SBAL_SFLAGS0_TYPE_READ, NULL);
 
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
@@ -1412,7 +1412,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
-                                 SBAL_FLAGS0_TYPE_READ,
+                                 SBAL_SFLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1478,7 +1478,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
-                                 SBAL_FLAGS0_TYPE_READ,
+                                 SBAL_SFLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1553,7 +1553,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
-                                 SBAL_FLAGS0_TYPE_READ,
+                                 SBAL_SFLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1606,7 +1606,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
-                                 SBAL_FLAGS0_TYPE_READ,
+                                 SBAL_SFLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1698,7 +1698,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
-                                 SBAL_FLAGS0_TYPE_READ,
+                                 SBAL_SFLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1812,7 +1812,7 @@ int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
-                                 SBAL_FLAGS0_TYPE_READ,
+                                 SBAL_SFLAGS0_TYPE_READ,
                                  adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1901,7 +1901,7 @@ int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
-                                 SBAL_FLAGS0_TYPE_READ,
+                                 SBAL_SFLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -2161,7 +2161,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
 {
        struct zfcp_fsf_req *req;
        struct fcp_cmnd *fcp_cmnd;
-       unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
+       u8 sbtype = SBAL_SFLAGS0_TYPE_READ;
        int real_bytes, retval = -EIO, dix_bytes = 0;
        struct scsi_device *sdev = scsi_cmnd->device;
        struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
@@ -2181,7 +2181,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
        }
 
        if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE)
-               sbtype = SBAL_FLAGS0_TYPE_WRITE;
+               sbtype = SBAL_SFLAGS0_TYPE_WRITE;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
                                  sbtype, adapter->pool.scsi_req);
@@ -2280,7 +2280,7 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
-                                 SBAL_FLAGS0_TYPE_WRITE,
+                                 SBAL_SFLAGS0_TYPE_WRITE,
                                  qdio->adapter->pool.scsi_req);
 
        if (IS_ERR(req)) {
@@ -2328,17 +2328,18 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
        struct zfcp_qdio *qdio = adapter->qdio;
        struct zfcp_fsf_req *req = NULL;
        struct fsf_qtcb_bottom_support *bottom;
-       int direction, retval = -EIO, bytes;
+       int retval = -EIO, bytes;
+       u8 direction;
 
        if (!(adapter->adapter_features & FSF_FEATURE_CFDC))
                return ERR_PTR(-EOPNOTSUPP);
 
        switch (fsf_cfdc->command) {
        case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
-               direction = SBAL_FLAGS0_TYPE_WRITE;
+               direction = SBAL_SFLAGS0_TYPE_WRITE;
                break;
        case FSF_QTCB_UPLOAD_CONTROL_FILE:
-               direction = SBAL_FLAGS0_TYPE_READ;
+               direction = SBAL_SFLAGS0_TYPE_READ;
                break;
        default:
                return ERR_PTR(-EINVAL);
@@ -2413,7 +2414,7 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
                fsf_req->qdio_req.sbal_response = sbal_idx;
                zfcp_fsf_req_complete(fsf_req);
 
-               if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
+               if (likely(sbale->eflags & SBAL_EFLAGS_LAST_ENTRY))
                        break;
        }
 }
index 98e97d9..d9c40ea 100644 (file)
@@ -124,7 +124,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
 
        /* set last entry flag in current SBALE of current SBAL */
        sbale = zfcp_qdio_sbale_curr(qdio, q_req);
-       sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
+       sbale->eflags |= SBAL_EFLAGS_LAST_ENTRY;
 
        /* don't exceed last allowed SBAL */
        if (q_req->sbal_last == q_req->sbal_limit)
@@ -132,7 +132,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
 
        /* set chaining flag in first SBALE of current SBAL */
        sbale = zfcp_qdio_sbale_req(qdio, q_req);
-       sbale->flags |= SBAL_FLAGS0_MORE_SBALS;
+       sbale->sflags |= SBAL_SFLAGS0_MORE_SBALS;
 
        /* calculate index of next SBAL */
        q_req->sbal_last++;
@@ -147,7 +147,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
 
        /* set storage-block type for new SBAL */
        sbale = zfcp_qdio_sbale_curr(qdio, q_req);
-       sbale->flags |= q_req->sbtype;
+       sbale->sflags |= q_req->sbtype;
 
        return sbale;
 }
@@ -177,7 +177,7 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
 
        /* set storage-block type for this request */
        sbale = zfcp_qdio_sbale_req(qdio, q_req);
-       sbale->flags |= q_req->sbtype;
+       sbale->sflags |= q_req->sbtype;
 
        for (; sg; sg = sg_next(sg)) {
                sbale = zfcp_qdio_sbale_next(qdio, q_req);
@@ -384,7 +384,8 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
        for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
                sbale = &(qdio->res_q[cc]->element[0]);
                sbale->length = 0;
-               sbale->flags = SBAL_FLAGS_LAST_ENTRY;
+               sbale->eflags = SBAL_EFLAGS_LAST_ENTRY;
+               sbale->sflags = 0;
                sbale->addr = NULL;
        }
 
index 2297d8d..54e22ac 100644 (file)
@@ -67,7 +67,7 @@ struct zfcp_qdio {
  * @qdio_outb_usage: usage of outbound queue
  */
 struct zfcp_qdio_req {
-       u32     sbtype;
+       u     sbtype;
        u8      sbal_number;
        u8      sbal_first;
        u8      sbal_last;
@@ -116,7 +116,7 @@ zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
  */
 static inline
 void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
-                       unsigned long req_id, u32 sbtype, void *data, u32 len)
+                       unsigned long req_id, u8 sbtype, void *data, u32 len)
 {
        struct qdio_buffer_element *sbale;
        int count = min(atomic_read(&qdio->req_q_free),
@@ -131,7 +131,8 @@ void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
 
        sbale = zfcp_qdio_sbale_req(qdio, q_req);
        sbale->addr = (void *) req_id;
-       sbale->flags = SBAL_FLAGS0_COMMAND | sbtype;
+       sbale->eflags = 0;
+       sbale->sflags = SBAL_SFLAGS0_COMMAND | sbtype;
 
        if (unlikely(!data))
                return;
@@ -173,7 +174,7 @@ void zfcp_qdio_set_sbale_last(struct zfcp_qdio *qdio,
        struct qdio_buffer_element *sbale;
 
        sbale = zfcp_qdio_sbale_curr(qdio, q_req);
-       sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
+       sbale->eflags |= SBAL_EFLAGS_LAST_ENTRY;
 }
 
 /**
index 6f86ba0..969cdd2 100644 (file)
@@ -298,7 +298,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
        unsigned int            count, c;
        unsigned long           base, tx_reg, rx_reg;
        int                     word_len, data_type, element_count;
-       int                     elements;
+       int                     elements = 0;
        u32                     l;
        u8                      * rx;
        const u8                * tx;
index dfc16f9..196284d 100644 (file)
@@ -24,23 +24,6 @@ menuconfig STAGING
 
 if STAGING
 
-config STAGING_EXCLUDE_BUILD
-       bool "Exclude Staging drivers from being built" if STAGING
-       default y
-       ---help---
-         Are you sure you really want to build the staging drivers?
-         They taint your kernel, don't live up to the normal Linux
-         kernel quality standards, are a bit crufty around the edges,
-         and might go off and kick your dog when you aren't paying
-         attention.
-
-         Say N here to be able to select and build the Staging drivers.
-         This option is primarily here to prevent them from being built
-         when selecting 'make allyesconfg' and 'make allmodconfig' so
-         don't be all that put off, your dog will be just fine.
-
-if !STAGING_EXCLUDE_BUILD
-
 source "drivers/staging/tty/Kconfig"
 
 source "drivers/staging/generic_serial/Kconfig"
@@ -177,5 +160,4 @@ source "drivers/staging/mei/Kconfig"
 
 source "drivers/staging/nvec/Kconfig"
 
-endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
index 8763088..8b1620b 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
-#include <staging/altera.h>
+#include "altera.h"
 #include "altera-exprt.h"
 #include "altera-jtag.h"
 
index 05aad35..9cd5e76 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/string.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
-#include <staging/altera.h>
+#include "altera.h"
 #include "altera-exprt.h"
 #include "altera-jtag.h"
 
diff --git a/drivers/staging/altera-stapl/altera.h b/drivers/staging/altera-stapl/altera.h
new file mode 100644 (file)
index 0000000..94c0c61
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * altera.h
+ *
+ * altera FPGA driver
+ *
+ * Copyright (C) Altera Corporation 1998-2001
+ * Copyright (C) 2010 NetUP Inc.
+ * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ALTERA_H_
+#define _ALTERA_H_
+
+struct altera_config {
+       void *dev;
+       u8 *action;
+       int (*jtag_io) (void *dev, int tms, int tdi, int tdo);
+};
+
+#if defined(CONFIG_ALTERA_STAPL) || \
+               (defined(CONFIG_ALTERA_STAPL_MODULE) && defined(MODULE))
+
+extern int altera_init(struct altera_config *config, const struct firmware *fw);
+#else
+
+static inline int altera_init(struct altera_config *config,
+                                               const struct firmware *fw)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return 0;
+}
+#endif /* CONFIG_ALTERA_STAPL */
+
+#endif /* _ALTERA_H_ */
index 1f15e1f..afd6cc1 100644 (file)
@@ -1,6 +1,7 @@
 config ATH6K_LEGACY
        tristate "Atheros AR6003 support (non mac80211)"
         depends on MMC && WLAN
+       depends on CFG80211
         select WIRELESS_EXT
         select WEXT_PRIV
        help
index 77dfb40..d3a774d 100644 (file)
@@ -870,7 +870,8 @@ ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status)
     if(ar->scan_request)
     {
         /* Translate data to cfg80211 mgmt format */
-        wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy);
+       if (ar->arWmi)
+               wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy);
 
         cfg80211_scan_done(ar->scan_request,
             ((status & A_ECANCELED) || (status & A_EBUSY)) ? true : false);
index 929ceaf..15e1b05 100644 (file)
@@ -64,8 +64,6 @@ wl_iw_extra_params_t g_wl_iw_params;
 extern bool wl_iw_conn_status_str(u32 event_type, u32 status,
                                  u32 reason, char *stringBuf, uint buflen);
 
-uint wl_msg_level = WL_ERROR_VAL;
-
 #define MAX_WLIW_IOCTL_LEN 1024
 
 #ifdef CONFIG_WIRELESS_EXT
index 1c45c11..aa87b1b 100644 (file)
@@ -542,6 +542,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        unsigned long irqflags;
        int ret = -ENOMEM;
        uint32_t tt_pages;
+       struct drm_connector *connector;
+       struct psb_intel_output *psb_intel_output;
 
        dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
        if (dev_priv == NULL)
@@ -663,7 +665,18 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
                drm_kms_helper_poll_init(dev);
        }
 
-       ret = psb_backlight_init(dev);
+       /* Only add backlight support if we have LVDS output */
+       list_for_each_entry(connector, &dev->mode_config.connector_list,
+                           head) {
+               psb_intel_output = to_psb_intel_output(connector);
+
+               switch (psb_intel_output->type) {
+               case INTEL_OUTPUT_LVDS:
+                       ret = psb_backlight_init(dev);
+                       break;
+               }
+       }
+
        if (ret)
                return ret;
 #if 0
index 99c03a2..084c36b 100644 (file)
@@ -441,6 +441,16 @@ static int psbfb_create(struct psb_fbdev *fbdev,
        info->screen_size = size;
        memset(info->screen_base, 0, size);
 
+       if (dev_priv->pg->stolen_size) {
+               info->apertures = alloc_apertures(1);
+               if (!info->apertures) {
+                       ret = -ENOMEM;
+                       goto out_err0;
+               }
+               info->apertures->ranges[0].base = dev->mode_config.fb_base;
+               info->apertures->ranges[0].size = dev_priv->pg->stolen_size;
+       }
+
        drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
        drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
                                sizes->fb_width, sizes->fb_height);
index 48ac8ba..417965d 100644 (file)
@@ -154,10 +154,15 @@ static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
 
        fill_detail_timing_data(panel_fixed_mode, dvo_timing);
 
-       dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
-
-       DRM_DEBUG("Found panel mode in BIOS VBT tables:\n");
-       drm_mode_debug_printmodeline(panel_fixed_mode);
+       if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) {
+               dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
+               DRM_DEBUG("Found panel mode in BIOS VBT tables:\n");
+               drm_mode_debug_printmodeline(panel_fixed_mode);
+       } else {
+               DRM_DEBUG("Ignoring bogus LVDS VBT mode.\n");
+               dev_priv->lvds_vbt = 0;
+               kfree(panel_fixed_mode);
+       }
 
        return;
 }
index 881768d..2fe34d2 100644 (file)
@@ -195,7 +195,7 @@ static const struct iio_info max517_info = {
 };
 
 static const struct iio_info max518_info = {
-       .attrs = &max517_attribute_group,
+       .attrs = &max518_attribute_group,
        .driver_module = THIS_MODULE,
 };
 
index 2589a7e..3612373 100644 (file)
@@ -137,13 +137,13 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
                if (st->variant->flags & ADIS16400_NO_BURST) {
                        ret = adis16350_spi_read_all(&indio_dev->dev, st->rx);
                        if (ret < 0)
-                               return ret;
+                               goto err;
                        for (; i < ring->scan_count; i++)
                                data[i] = *(s16 *)(st->rx + i*2);
                } else {
                        ret = adis16400_spi_read_burst(&indio_dev->dev, st->rx);
                        if (ret < 0)
-                               return ret;
+                               goto err;
                        for (; i < indio_dev->ring->scan_count; i++) {
                                j = __ffs(mask);
                                mask &= ~(1 << j);
@@ -158,9 +158,13 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
        ring->access->store_to(indio_dev->ring, (u8 *) data, pf->timestamp);
 
        iio_trigger_notify_done(indio_dev->trig);
-       kfree(data);
 
+       kfree(data);
        return IRQ_HANDLED;
+
+err:
+       kfree(data);
+       return ret;
 }
 
 void adis16400_unconfigure_ring(struct iio_dev *indio_dev)
index 6159023..d504aa2 100644 (file)
@@ -294,6 +294,7 @@ struct iio_poll_func
        pf->h = h;
        pf->thread = thread;
        pf->type = type;
+       pf->private_data = private;
 
        return pf;
 }
index 2818851..d1ffa32 100644 (file)
@@ -205,10 +205,10 @@ int mei_hw_init(struct mei_device *dev)
                        "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
                        dev->host_hw_state, dev->me_hw_state);
 
-               if (!(dev->host_hw_state & H_RDY) != H_RDY)
+               if (!(dev->host_hw_state & H_RDY))
                        dev_dbg(&dev->pdev->dev, "host turn off H_RDY.\n");
 
-               if (!(dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
+               if (!(dev->me_hw_state & ME_RDY_HRA))
                        dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n");
 
                printk(KERN_ERR "mei: link layer initialization failed.\n");
index b053067..fe40e0b 100644 (file)
@@ -2,6 +2,7 @@ config FB_OLPC_DCON
        tristate "One Laptop Per Child Display CONtroller support"
        depends on OLPC && FB
        select I2C
+       select BACKLIGHT_CLASS_DEVICE
        ---help---
          Add support for the OLPC XO DCON controller.  This controller is
          only available on OLPC platforms.   Unless you have one of these
index bddb031..cdae497 100644 (file)
@@ -2328,7 +2328,7 @@ Switch_Fail:
 
                        retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, SD_RSP_TYPE_R4, rsp, 5);
                        if (retval == STATUS_SUCCESS) {
-                               int func_num = (rsp[1] >> 4) && 0x07;
+                               int func_num = (rsp[1] >> 4) & 0x07;
                                if (func_num) {
                                        RTSX_DEBUGP("SD_IO card (Function number: %d)!\n", func_num);
                                        chip->sd_io = 1;
index 6e99ec8..8cbea42 100644 (file)
@@ -26,6 +26,8 @@
 static int stub_probe(struct usb_interface *interface,
                      const struct usb_device_id *id);
 static void stub_disconnect(struct usb_interface *interface);
+static int stub_pre_reset(struct usb_interface *interface);
+static int stub_post_reset(struct usb_interface *interface);
 
 /*
  * Define device IDs here if you want to explicitly limit exportable devices.
@@ -59,6 +61,8 @@ struct usb_driver stub_driver = {
        .probe          = stub_probe,
        .disconnect     = stub_disconnect,
        .id_table       = stub_table,
+       .pre_reset      = stub_pre_reset,
+       .post_reset     = stub_post_reset,
 };
 
 /*
@@ -541,3 +545,20 @@ static void stub_disconnect(struct usb_interface *interface)
                del_match_busid((char *)udev_busid);
        }
 }
+
+/* 
+ * Presence of pre_reset and post_reset prevents the driver from being unbound
+ * when the device is being reset
+ */
+int stub_pre_reset(struct usb_interface *interface)
+{
+       dev_dbg(&interface->dev, "pre_reset\n");
+       return 0;
+}
+
+int stub_post_reset(struct usb_interface *interface)
+{
+       dev_dbg(&interface->dev, "post_reset\n");
+       return 0;
+}
index a5c1fa1..bc57844 100644 (file)
@@ -175,16 +175,18 @@ static int tweak_reset_device_cmd(struct urb *urb)
        dev_info(&urb->dev->dev, "usb_queue_reset_device\n");
 
        /*
-        * usb_lock_device_for_reset caused a deadlock: it causes the driver
-        * to unbind. In the shutdown the rx thread is signalled to shut down
-        * but this thread is pending in the usb_lock_device_for_reset.
-        *
-        * Instead queue the reset.
-        *
-        * Unfortunatly an existing usbip connection will be dropped due to
-        * driver unbinding.
+        * With the implementation of pre_reset and post_reset the driver no 
+        * longer unbinds. This allows the use of synchronous reset.
         */
-       usb_queue_reset_device(sdev->interface);
+
+       if (usb_lock_device_for_reset(sdev->udev, sdev->interface)<0)
+       {
+               dev_err(&urb->dev->dev, "could not obtain lock to reset device\n");
+               return 0;
+       }
+       usb_reset_device(sdev->udev);
+       usb_unlock_device(sdev->udev);
+
        return 0;
 }
 
index f1a7918..6c9b7cd 100644 (file)
@@ -413,8 +413,7 @@ static void flush_to_ldisc(struct work_struct *work)
        spin_lock_irqsave(&tty->buf.lock, flags);
 
        if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
-               struct tty_buffer *head, *tail = tty->buf.tail;
-               int seen_tail = 0;
+               struct tty_buffer *head;
                while ((head = tty->buf.head) != NULL) {
                        int count;
                        char *char_buf;
@@ -424,15 +423,6 @@ static void flush_to_ldisc(struct work_struct *work)
                        if (!count) {
                                if (head->next == NULL)
                                        break;
-                               /*
-                                 There's a possibility tty might get new buffer
-                                 added during the unlock window below. We could
-                                 end up spinning in here forever hogging the CPU
-                                 completely. To avoid this let's have a rest each
-                                 time we processed the tail buffer.
-                               */
-                               if (tail == head)
-                                       seen_tail = 1;
                                tty->buf.head = head->next;
                                tty_buffer_free(tty, head);
                                continue;
@@ -442,7 +432,7 @@ static void flush_to_ldisc(struct work_struct *work)
                           line discipline as we want to empty the queue */
                        if (test_bit(TTY_FLUSHPENDING, &tty->flags))
                                break;
-                       if (!tty->receive_room || seen_tail)
+                       if (!tty->receive_room)
                                break;
                        if (count > tty->receive_room)
                                count = tty->receive_room;
index 395a347..dac7676 100644 (file)
@@ -1530,6 +1530,8 @@ static const struct usb_device_id acm_ids[] = {
        { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */
        { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */
        { NOKIA_PCSUITE_ACM_INFO(0x0302), }, /* Nokia N8 */
+       { NOKIA_PCSUITE_ACM_INFO(0x0335), }, /* Nokia E7 */
+       { NOKIA_PCSUITE_ACM_INFO(0x03cd), }, /* Nokia C7 */
        { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */
 
        /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */
index 79a58c3..90ae175 100644 (file)
@@ -339,7 +339,8 @@ static int get_hub_status(struct usb_device *hdev,
 {
        int i, status = -ETIMEDOUT;
 
-       for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
+       for (i = 0; i < USB_STS_RETRIES &&
+                       (status == -ETIMEDOUT || status == -EPIPE); i++) {
                status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
                        USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
                        data, sizeof(*data), USB_STS_TIMEOUT);
@@ -355,7 +356,8 @@ static int get_port_status(struct usb_device *hdev, int port1,
 {
        int i, status = -ETIMEDOUT;
 
-       for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
+       for (i = 0; i < USB_STS_RETRIES &&
+                       (status == -ETIMEDOUT || status == -EPIPE); i++) {
                status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
                        USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1,
                        data, sizeof(*data), USB_STS_TIMEOUT);
index 1b125c2..2278dad 100644 (file)
@@ -389,7 +389,6 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
        mutex_unlock(&inode->i_mutex);
        if (!error)
                d_delete(dentry);
-       dput(dentry);
        return error;
 }
 
index 58456d1..029e288 100644 (file)
@@ -632,13 +632,10 @@ config USB_DUMMY_HCD
 
 endchoice
 
+# Selected by UDC drivers that support high-speed operation.
 config USB_GADGET_DUALSPEED
        bool
        depends on USB_GADGET
-       default n
-       help
-         Means that gadget drivers should include extra descriptors
-         and code to handle dual-speed controllers.
 
 #
 # USB Gadget Drivers
index 6e42aab..95e8138 100644 (file)
@@ -60,6 +60,7 @@
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/prefetch.h>
 
 #include <asm/byteorder.h>
 #include <asm/system.h>
index 41dc093..f4690ff 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/clk.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/prefetch.h>
 
 #include <asm/byteorder.h>
 #include <mach/hardware.h>
index 61ff927..d3dcabc 100644 (file)
@@ -1906,6 +1906,7 @@ static int dummy_hcd_probe(struct platform_device *pdev)
        if (!hcd)
                return -ENOMEM;
        the_controller = hcd_to_dummy (hcd);
+       hcd->has_tt = 1;
 
        retval = usb_add_hcd(hcd, 0, 0);
        if (retval != 0) {
index a01383f..a56876a 100644 (file)
@@ -431,8 +431,10 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 
        /* halt any endpoint by doing a "wrong direction" i/o call */
        if (!usb_endpoint_dir_in(&data->desc)) {
-               if (usb_endpoint_xfer_isoc(&data->desc))
+               if (usb_endpoint_xfer_isoc(&data->desc)) {
+                       mutex_unlock(&data->lock);
                        return -EINVAL;
+               }
                DBG (data->dev, "%s halt\n", data->name);
                spin_lock_irq (&data->dev->lock);
                if (likely (data->ep != NULL))
index b62b264..b1a8146 100644 (file)
@@ -2083,7 +2083,7 @@ out:
 }
 
 #ifdef CONFIG_PM
-static int mv_udc_suspend(struct platform_device *_dev, pm_message_t state)
+static int mv_udc_suspend(struct device *_dev)
 {
        struct mv_udc *udc = the_controller;
 
@@ -2092,7 +2092,7 @@ static int mv_udc_suspend(struct platform_device *_dev, pm_message_t state)
        return 0;
 }
 
-static int mv_udc_resume(struct platform_device *_dev)
+static int mv_udc_resume(struct device *_dev)
 {
        struct mv_udc *udc = the_controller;
        int retval;
@@ -2100,7 +2100,7 @@ static int mv_udc_resume(struct platform_device *_dev)
        retval = mv_udc_phy_init(udc->phy_regs);
        if (retval) {
                dev_err(_dev, "phy initialization error %d\n", retval);
-               goto error;
+               return retval;
        }
        udc_reset(udc);
        ep0_reset(udc);
@@ -2122,7 +2122,7 @@ static struct platform_driver udc_driver = {
                .owner  = THIS_MODULE,
                .name   = "pxa-u2o",
 #ifdef CONFIG_PM
-               .pm     = mv_udc_pm_ops,
+               .pm     = &mv_udc_pm_ops,
 #endif
        },
 };
index 24696f7..476d88e 100644 (file)
@@ -63,6 +63,7 @@
 #include <linux/device.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/prefetch.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
index 365c02f..7745454 100644 (file)
@@ -2216,7 +2216,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
                if (retval != 0) {
                        pr_err("%s: can't get irq %i, err %d\n",
                                driver_name, LUBBOCK_USB_DISC_IRQ, retval);
-lubbock_fail0:
                        goto err_irq_lub;
                }
                retval = request_irq(LUBBOCK_USB_IRQ,
@@ -2226,7 +2225,6 @@ lubbock_fail0:
                if (retval != 0) {
                        pr_err("%s: can't get irq %i, err %d\n",
                                driver_name, LUBBOCK_USB_IRQ, retval);
-                       free_irq(LUBBOCK_USB_DISC_IRQ, dev);
                        goto lubbock_fail0;
                }
        } else
@@ -2236,10 +2234,11 @@ lubbock_fail0:
        return 0;
 
 #ifdef CONFIG_ARCH_LUBBOCK
+lubbock_fail0:
        free_irq(LUBBOCK_USB_DISC_IRQ, dev);
  err_irq_lub:
-#endif
        free_irq(irq, dev);
+#endif
  err_irq1:
        if (gpio_is_valid(dev->mach->gpio_pullup))
                gpio_free(dev->mach->gpio_pullup);
index acb9cc4..0dfee28 100644 (file)
@@ -2680,9 +2680,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 
        writel(0, hsotg->regs + S3C_DAINTMSK);
 
-       dev_info(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-                readl(hsotg->regs + S3C_DIEPCTL0),
-                readl(hsotg->regs + S3C_DOEPCTL0));
+       dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
+               readl(hsotg->regs + S3C_DIEPCTL0),
+               readl(hsotg->regs + S3C_DOEPCTL0));
 
        /* enable in and out endpoint interrupts */
        s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt);
@@ -2701,7 +2701,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
        udelay(10);  /* see openiboot */
        __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone);
 
-       dev_info(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL));
+       dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL));
 
        /* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by
           writing to the EPCTL register.. */
@@ -2721,9 +2721,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 
        s3c_hsotg_enqueue_setup(hsotg);
 
-       dev_info(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-                readl(hsotg->regs + S3C_DIEPCTL0),
-                readl(hsotg->regs + S3C_DOEPCTL0));
+       dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
+               readl(hsotg->regs + S3C_DIEPCTL0),
+               readl(hsotg->regs + S3C_DOEPCTL0));
 
        /* clear global NAKs */
        writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK,
@@ -2921,9 +2921,9 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
 
        /* setup fifos */
 
-       dev_info(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
-                readl(hsotg->regs + S3C_GRXFSIZ),
-                readl(hsotg->regs + S3C_GNPTXFSIZ));
+       dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
+               readl(hsotg->regs + S3C_GRXFSIZ),
+               readl(hsotg->regs + S3C_GNPTXFSIZ));
 
        s3c_hsotg_init_fifo(hsotg);
 
@@ -2945,6 +2945,7 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
 
 static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
 {
+#ifdef DEBUG
        struct device *dev = hsotg->dev;
        void __iomem *regs = hsotg->regs;
        u32 val;
@@ -2987,6 +2988,7 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
 
        dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n",
                 readl(regs + S3C_DVBUSDIS), readl(regs + S3C_DVBUSPULSE));
+#endif
 }
 
 
index cfe3cf5..d5e3e1e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/clk.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/prefetch.h>
 
 #include <mach/regs-s3c2443-clock.h>
 #include <plat/udc.h>
@@ -1301,7 +1302,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
        hsudc->uclk = clk_get(&pdev->dev, "usb-device");
        if (IS_ERR(hsudc->uclk)) {
                dev_err(dev, "failed to find usb-device clock source\n");
-               return PTR_ERR(hsudc->uclk);
+               ret = PTR_ERR(hsudc->uclk);
+               goto err_clk;
        }
        clk_enable(hsudc->uclk);
 
@@ -1310,7 +1312,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
        disable_irq(hsudc->irq);
        local_irq_enable();
        return 0;
-
+err_clk:
+       free_irq(hsudc->irq, hsudc);
 err_irq:
        iounmap(hsudc->regs);
 
index 6d8b040..100f263 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/prefetch.h>
 
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
index afef7b0..80be547 100644 (file)
@@ -312,8 +312,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
                return PTR_ERR(usb_clk);
 
        hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x");
-       if (!hcd)
-               return -ENOMEM;
+       if (!hcd) {
+               retval = -ENOMEM;
+               goto err0;
+       }
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!r) {
@@ -368,6 +370,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  err1:
        usb_put_hcd(hcd);
+ err0:
        clk_put(usb_clk);
        return retval;
 }
index 2e04861..1f50b44 100644 (file)
@@ -438,13 +438,13 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci,
        struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
 
        switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) {
-       case 0:
+       case SLOT_STATE_ENABLED:
                return "enabled/disabled";
-       case 1:
+       case SLOT_STATE_DEFAULT:
                return "default";
-       case 2:
+       case SLOT_STATE_ADDRESSED:
                return "addressed";
-       case 3:
+       case SLOT_STATE_CONFIGURED:
                return "configured";
        default:
                return "reserved";
index 26caba4..0f8e1d2 100644 (file)
@@ -985,9 +985,19 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
        interval = clamp_val(ep->desc.bInterval, 1, 16) - 1;
        if (interval != ep->desc.bInterval - 1)
                dev_warn(&udev->dev,
-                        "ep %#x - rounding interval to %d microframes\n",
+                        "ep %#x - rounding interval to %d %sframes\n",
                         ep->desc.bEndpointAddress,
-                        1 << interval);
+                        1 << interval,
+                        udev->speed == USB_SPEED_FULL ? "" : "micro");
+
+       if (udev->speed == USB_SPEED_FULL) {
+               /*
+                * Full speed isoc endpoints specify interval in frames,
+                * not microframes. We are using microframes everywhere,
+                * so adjust accordingly.
+                */
+               interval += 3;  /* 1 frame = 2^3 uframes */
+       }
 
        return interval;
 }
index c408e9f..17541d0 100644 (file)
@@ -106,12 +106,22 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
 
        /* Look for vendor-specific quirks */
        if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
-                       pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
-                       pdev->revision == 0x0) {
+                       pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) {
+               if (pdev->revision == 0x0) {
                        xhci->quirks |= XHCI_RESET_EP_QUIRK;
                        xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
                                        " endpoint cmd after reset endpoint\n");
+               }
+               /* Fresco Logic confirms: all revisions of this chip do not
+                * support MSI, even though some of them claim to in their PCI
+                * capabilities.
+                */
+               xhci->quirks |= XHCI_BROKEN_MSI;
+               xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u "
+                               "has broken MSI implementation\n",
+                               pdev->revision);
        }
+
        if (pdev->vendor == PCI_VENDOR_ID_NEC)
                xhci->quirks |= XHCI_NEC_HOST;
 
index cc1485b..800f417 100644 (file)
@@ -1782,7 +1782,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
        struct usb_iso_packet_descriptor *frame;
        int idx;
 
-       ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+       ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
        urb_priv = td->urb->hcpriv;
        idx = urb_priv->td_cnt;
        frame = &td->urb->iso_frame_desc[idx];
index d9660eb..06e7023 100644 (file)
@@ -430,12 +430,19 @@ int xhci_run(struct usb_hcd *hcd)
                free_irq(hcd->irq, hcd);
        hcd->irq = -1;
 
+       /* Some Fresco Logic host controllers advertise MSI, but fail to
+        * generate interrupts.  Don't even try to enable MSI.
+        */
+       if (xhci->quirks & XHCI_BROKEN_MSI)
+               goto legacy_irq;
+
        ret = xhci_setup_msix(xhci);
        if (ret)
                /* fall back to msi*/
                ret = xhci_setup_msi(xhci);
 
        if (ret) {
+legacy_irq:
                /* fall back to legacy interrupt*/
                ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
                                        hcd->irq_descr, hcd);
@@ -1849,8 +1856,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
 
        /* Free any rings that were dropped, but not changed. */
        for (i = 1; i < 31; ++i) {
-               if ((ctrl_ctx->drop_flags & (1 << (i + 1))) &&
-                               !(ctrl_ctx->add_flags & (1 << (i + 1))))
+               if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) &&
+                   !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1))))
                        xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
        }
        xhci_zero_in_ctx(xhci, virt_dev);
@@ -2467,6 +2474,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
        struct xhci_command *reset_device_cmd;
        int timeleft;
        int last_freed_endpoint;
+       struct xhci_slot_ctx *slot_ctx;
 
        ret = xhci_check_args(hcd, udev, NULL, 0, false, __func__);
        if (ret <= 0)
@@ -2499,6 +2507,12 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
                        return -EINVAL;
        }
 
+       /* If device is not setup, there is no point in resetting it */
+       slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
+       if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) ==
+                                               SLOT_STATE_DISABLED)
+               return 0;
+
        xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
        /* Allocate the command structure that holds the struct completion.
         * Assume we're in process context, since the normal device reset
index ac0196e..7d1ea3b 100644 (file)
@@ -560,6 +560,11 @@ struct xhci_slot_ctx {
 #define SLOT_STATE     (0x1f << 27)
 #define GET_SLOT_STATE(p)      (((p) & (0x1f << 27)) >> 27)
 
+#define SLOT_STATE_DISABLED    0
+#define SLOT_STATE_ENABLED     SLOT_STATE_DISABLED
+#define SLOT_STATE_DEFAULT     1
+#define SLOT_STATE_ADDRESSED   2
+#define SLOT_STATE_CONFIGURED  3
 
 /**
  * struct xhci_ep_ctx
@@ -1302,6 +1307,7 @@ struct xhci_hcd {
  * commands.
  */
 #define XHCI_EP_LIMIT_QUIRK    (1 << 5)
+#define XHCI_BROKEN_MSI                (1 << 6)
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
        /* There are two roothubs to keep track of bus suspend info for */
index ab8e100..c71b037 100644 (file)
@@ -96,6 +96,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/kobject.h>
+#include <linux/prefetch.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
index 206cfab..547486c 100644 (file)
@@ -1380,5 +1380,6 @@ void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv)
 {
        struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
 
+       kfree(gpriv->uep);
        kfree(gpriv);
 }
index e8dbde5..1627289 100644 (file)
@@ -647,6 +647,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
        { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_3_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) },
index 1d946cd..ab1fcdf 100644 (file)
  */
 #define FTDI_4N_GALAXY_DE_1_PID        0xF3C0
 #define FTDI_4N_GALAXY_DE_2_PID        0xF3C1
+#define FTDI_4N_GALAXY_DE_3_PID        0xF3C2
 
 /*
  * Linx Technologies product ids
index 318dd00..60b25d8 100644 (file)
@@ -311,10 +311,6 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_AC2726                     0xfff5
 #define ZTE_PRODUCT_AC8710T                    0xffff
 
-/* ZTE PRODUCTS -- alternate vendor ID */
-#define ZTE_VENDOR_ID2                         0x1d6b
-#define ZTE_PRODUCT_MF_330                     0x0002
-
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
 
@@ -340,11 +336,12 @@ static void option_instat_callback(struct urb *urb);
 #define TOSHIBA_PRODUCT_G450                   0x0d45
 
 #define ALINK_VENDOR_ID                                0x1e0e
+#define ALINK_PRODUCT_PH300                    0x9100
 #define ALINK_PRODUCT_3GU                      0x9200
 
 /* ALCATEL PRODUCTS */
 #define ALCATEL_VENDOR_ID                      0x1bbb
-#define ALCATEL_PRODUCT_X060S                  0x0000
+#define ALCATEL_PRODUCT_X060S_X200             0x0000
 
 #define PIRELLI_VENDOR_ID                      0x1266
 #define PIRELLI_PRODUCT_C100_1                 0x1002
@@ -379,6 +376,9 @@ static void option_instat_callback(struct urb *urb);
  * It seems to contain a Qualcomm QSC6240/6290 chipset            */
 #define FOUR_G_SYSTEMS_PRODUCT_W14             0x9603
 
+/* Zoom */
+#define ZOOM_PRODUCT_4597                      0x9607
+
 /* Haier products */
 #define HAIER_VENDOR_ID                                0x201e
 #define HAIER_PRODUCT_CE100                    0x2009
@@ -432,6 +432,20 @@ static const struct option_blacklist_info four_g_w14_blacklist = {
        .reason = OPTION_BLACKLIST_SENDSETUP
 };
 
+static const u8 alcatel_x200_no_sendsetup[] = { 0, 1 };
+static const struct option_blacklist_info alcatel_x200_blacklist = {
+       .infolen = ARRAY_SIZE(alcatel_x200_no_sendsetup),
+       .ifaceinfo = alcatel_x200_no_sendsetup,
+       .reason = OPTION_BLACKLIST_SENDSETUP
+};
+
+static const u8 zte_k3765_z_no_sendsetup[] = { 0, 1, 2 };
+static const struct option_blacklist_info zte_k3765_z_blacklist = {
+       .infolen = ARRAY_SIZE(zte_k3765_z_no_sendsetup),
+       .ifaceinfo = zte_k3765_z_no_sendsetup,
+       .reason = OPTION_BLACKLIST_SENDSETUP
+};
+
 static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -916,13 +930,13 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
+         0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
-       { USB_DEVICE(ZTE_VENDOR_ID2, ZTE_PRODUCT_MF_330) },
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
        { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
@@ -935,13 +949,17 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
        { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
        { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
+       { USB_DEVICE(ALINK_VENDOR_ID, ALINK_PRODUCT_PH300) },
        { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
-       { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
+       { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
+         .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
+       },
        { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
        { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
        { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
          .driver_info = (kernel_ulong_t)&four_g_w14_blacklist
        },
+       { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
        { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
        /* Pirelli  */
        { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)},
index 0041899..e8ae21b 100644 (file)
@@ -819,6 +819,35 @@ Retry_Sense:
                }
        }
 
+       /*
+        * Some devices don't work or return incorrect data the first
+        * time they get a READ(10) command, or for the first READ(10)
+        * after a media change.  If the INITIAL_READ10 flag is set,
+        * keep track of whether READ(10) commands succeed.  If the
+        * previous one succeeded and this one failed, set the REDO_READ10
+        * flag to force a retry.
+        */
+       if (unlikely((us->fflags & US_FL_INITIAL_READ10) &&
+                       srb->cmnd[0] == READ_10)) {
+               if (srb->result == SAM_STAT_GOOD) {
+                       set_bit(US_FLIDX_READ10_WORKED, &us->dflags);
+               } else if (test_bit(US_FLIDX_READ10_WORKED, &us->dflags)) {
+                       clear_bit(US_FLIDX_READ10_WORKED, &us->dflags);
+                       set_bit(US_FLIDX_REDO_READ10, &us->dflags);
+               }
+
+               /*
+                * Next, if the REDO_READ10 flag is set, return a result
+                * code that will cause the SCSI core to retry the READ(10)
+                * command immediately.
+                */
+               if (test_bit(US_FLIDX_REDO_READ10, &us->dflags)) {
+                       clear_bit(US_FLIDX_REDO_READ10, &us->dflags);
+                       srb->result = DID_IMM_RETRY << 16;
+                       srb->sense_buffer[0] = 0;
+               }
+       }
+
        /* Did we transfer less than the minimum amount required? */
        if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) &&
                        scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
index c1602b8..ccff348 100644 (file)
@@ -1114,6 +1114,16 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY ),
 
+/* Reported by Paul Hartman <paul.hartman+linux@gmail.com>
+ * This card reader returns "Illegal Request, Logical Block Address
+ * Out of Range" for the first READ(10) after a new card is inserted.
+ */
+UNUSUAL_DEV(  0x090c, 0x6000, 0x0100, 0x0100,
+               "Feiya",
+               "SD/SDHC Card Reader",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_INITIAL_READ10 ),
+
 /* This Pentax still camera is not conformant
  * to the USB storage specification: -
  * - It does not like the INQUIRY command. So we must handle this command
@@ -1888,6 +1898,15 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_READ_DISC_INFO ),
 
+/* Reported by Sven Geggus <sven-usbst@geggus.net>
+ * This encrypted pen drive returns bogus data for the initial READ(10).
+ */
+UNUSUAL_DEV(  0x1b1c, 0x1ab5, 0x0200, 0x0200,
+               "Corsair",
+               "Padlock v2",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_INITIAL_READ10 ),
+
 /* Patch by Richard Schütz <r.schtz@t-online.de>
  * This external hard drive enclosure uses a JMicron chip which
  * needs the US_FL_IGNORE_RESIDUE flag to work properly. */
index 5ee7ac4..0ca0958 100644 (file)
@@ -440,7 +440,8 @@ static void adjust_quirks(struct us_data *us)
                        US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
                        US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
                        US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT |
-                       US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16);
+                       US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 |
+                       US_FL_INITIAL_READ10);
 
        p = quirks;
        while (*p) {
@@ -490,6 +491,9 @@ static void adjust_quirks(struct us_data *us)
                case 'm':
                        f |= US_FL_MAX_SECTORS_64;
                        break;
+               case 'n':
+                       f |= US_FL_INITIAL_READ10;
+                       break;
                case 'o':
                        f |= US_FL_CAPACITY_OK;
                        break;
@@ -953,6 +957,13 @@ int usb_stor_probe2(struct us_data *us)
        if (result)
                goto BadDevice;
 
+       /*
+        * If the device returns invalid data for the first READ(10)
+        * command, indicate the command should be retried.
+        */
+       if (us->fflags & US_FL_INITIAL_READ10)
+               set_bit(US_FLIDX_REDO_READ10, &us->dflags);
+
        /* Acquire all the other resources and add the host */
        result = usb_stor_acquire_resources(us);
        if (result)
index 89d3bff..7b0f211 100644 (file)
@@ -73,6 +73,8 @@ struct us_unusual_dev {
 #define US_FLIDX_RESETTING     4       /* device reset in progress */
 #define US_FLIDX_TIMED_OUT     5       /* SCSI midlayer timed out  */
 #define US_FLIDX_DONT_SCAN     6       /* don't scan (disconnect)  */
+#define US_FLIDX_REDO_READ10   7       /* redo READ(10) command    */
+#define US_FLIDX_READ10_WORKED 8       /* previous READ(10) succeeded */
 
 #define USB_STOR_STRING_LEN 32
 
index 3ec4923..c22e8d3 100644 (file)
@@ -515,11 +515,10 @@ static int __devinit arcfb_probe(struct platform_device *dev)
 
        /* We need a flat backing store for the Arc's
           less-flat actual paged framebuffer */
-       if (!(videomemory = vmalloc(videomemorysize)))
+       videomemory = vzalloc(videomemorysize);
+       if (!videomemory)
                return retval;
 
-       memset(videomemory, 0, videomemorysize);
-
        info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
        if (!info)
                goto err;
index 47c21fb..bea53c1 100644 (file)
@@ -789,6 +789,7 @@ static int __devinit bfin_lq035_probe(struct platform_device *pdev)
        i2c_add_driver(&ad5280_driver);
 
        memset(&props, 0, sizeof(props));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = MAX_BRIGHENESS;
        bl_dev = backlight_device_register("bf537-bl", NULL, NULL,
                                           &bfin_lq035fb_bl_ops, &props);
index ebda687..377dde3 100644 (file)
@@ -1101,12 +1101,10 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
 
        videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
 
-       videomemory = vmalloc(videomemorysize);
+       videomemory = vzalloc(videomemorysize);
        if (!videomemory)
                goto err_fb_rel;
 
-       memset(videomemory, 0, videomemorysize);
-
        info->screen_base = (char *)videomemory;
        info->fbops = &broadsheetfb_ops;
 
index fb20584..69c49df 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/pci.h>
 #include <video/vga.h>
 
+static bool request_mem_succeeded = false;
+
 static struct fb_var_screeninfo efifb_defined __devinitdata = {
        .activate               = FB_ACTIVATE_NOW,
        .height                 = -1,
@@ -281,7 +283,9 @@ static void efifb_destroy(struct fb_info *info)
 {
        if (info->screen_base)
                iounmap(info->screen_base);
-       release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
+       if (request_mem_succeeded)
+               release_mem_region(info->apertures->ranges[0].base,
+                                  info->apertures->ranges[0].size);
        framebuffer_release(info);
 }
 
@@ -326,14 +330,13 @@ static int __init efifb_setup(char *options)
        return 0;
 }
 
-static int __devinit efifb_probe(struct platform_device *dev)
+static int __init efifb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        int err;
        unsigned int size_vmode;
        unsigned int size_remap;
        unsigned int size_total;
-       int request_succeeded = 0;
 
        if (!screen_info.lfb_depth)
                screen_info.lfb_depth = 32;
@@ -387,7 +390,7 @@ static int __devinit efifb_probe(struct platform_device *dev)
        efifb_fix.smem_len = size_remap;
 
        if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
-               request_succeeded = 1;
+               request_mem_succeeded = true;
        } else {
                /* We cannot make this fatal. Sometimes this comes from magic
                   spaces our resource handlers simply don't know about */
@@ -413,7 +416,7 @@ static int __devinit efifb_probe(struct platform_device *dev)
        info->apertures->ranges[0].base = efifb_fix.smem_start;
        info->apertures->ranges[0].size = size_remap;
 
-       info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
+       info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
        if (!info->screen_base) {
                printk(KERN_ERR "efifb: abort, cannot ioremap video memory "
                                "0x%x @ 0x%lx\n",
@@ -491,13 +494,12 @@ err_unmap:
 err_release_fb:
        framebuffer_release(info);
 err_release_mem:
-       if (request_succeeded)
+       if (request_mem_succeeded)
                release_mem_region(efifb_fix.smem_start, size_total);
        return err;
 }
 
 static struct platform_driver efifb_driver = {
-       .probe  = efifb_probe,
        .driver = {
                .name   = "efifb",
        },
@@ -528,13 +530,21 @@ static int __init efifb_init(void)
        if (!screen_info.lfb_linelength)
                return -ENODEV;
 
-       ret = platform_driver_register(&efifb_driver);
+       ret = platform_device_register(&efifb_device);
+       if (ret)
+               return ret;
 
-       if (!ret) {
-               ret = platform_device_register(&efifb_device);
-               if (ret)
-                       platform_driver_unregister(&efifb_driver);
+       /*
+        * This is not just an optimization.  We will interfere
+        * with a real driver if we get reprobed, so don't allow
+        * it.
+        */
+       ret = platform_driver_probe(&efifb_driver, efifb_probe);
+       if (ret) {
+               platform_device_unregister(&efifb_driver);
+               return ret;
        }
+
        return ret;
 }
 module_init(efifb_init);
index 1b94643..fbef15f 100644 (file)
@@ -231,11 +231,10 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
 
        videomemorysize = (DPY_W*DPY_H)/8;
 
-       if (!(videomemory = vmalloc(videomemorysize)))
+       videomemory = vzalloc(videomemorysize);
+       if (!videomemory)
                return retval;
 
-       memset(videomemory, 0, videomemorysize);
-
        info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev);
        if (!info)
                goto err_fballoc;
index d2ccfd6..f135dbe 100644 (file)
@@ -856,10 +856,10 @@ failed_platform_init:
                dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu,
                        fbi->map_dma);
 failed_map:
-       clk_put(fbi->clk);
-failed_getclock:
        iounmap(fbi->regs);
 failed_ioremap:
+       clk_put(fbi->clk);
+failed_getclock:
        release_mem_region(res->start, resource_size(res));
 failed_req:
        kfree(info->pseudo_palette);
index ed64edf..97d45e5 100644 (file)
@@ -628,12 +628,10 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
        /* we need to add a spare page because our csum caching scheme walks
         * to the end of the page */
        videomemorysize = PAGE_SIZE + (fw * fh);
-       videomemory = vmalloc(videomemorysize);
+       videomemory = vzalloc(videomemorysize);
        if (!videomemory)
                goto err_fb_rel;
 
-       memset(videomemory, 0, videomemorysize);
-
        info->screen_base = (char __force __iomem *)videomemory;
        info->fbops = &metronomefb_ops;
 
index 48c3ea8..cb175fe 100644 (file)
@@ -1128,3 +1128,4 @@ EXPORT_SYMBOL(fb_find_best_mode);
 EXPORT_SYMBOL(fb_find_nearest_mode);
 EXPORT_SYMBOL(fb_videomode_to_modelist);
 EXPORT_SYMBOL(fb_find_mode);
+EXPORT_SYMBOL(fb_find_mode_cvt);
index 35f61dd..bb95ec5 100644 (file)
@@ -623,19 +623,21 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res == NULL) {
                dev_err(&pdev->dev, "no IO memory defined\n");
-               return -ENOENT;
+               ret = -ENOENT;
+               goto failed_put_clk;
        }
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(&pdev->dev, "no IRQ defined\n");
-               return -ENOENT;
+               ret = -ENOENT;
+               goto failed_put_clk;
        }
 
        info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev);
        if (info == NULL) {
-               clk_put(clk);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto failed_put_clk;
        }
 
        /* Initialize private data */
@@ -671,7 +673,7 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
        fbi->reg_base = ioremap_nocache(res->start, resource_size(res));
        if (fbi->reg_base == NULL) {
                ret = -ENOMEM;
-               goto failed;
+               goto failed_free_info;
        }
 
        /*
@@ -683,7 +685,7 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
                                                &fbi->fb_start_dma, GFP_KERNEL);
        if (info->screen_base == NULL) {
                ret = -ENOMEM;
-               goto failed;
+               goto failed_free_info;
        }
 
        info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
@@ -772,8 +774,9 @@ failed_free_clk:
 failed_free_fbmem:
        dma_free_coherent(fbi->dev, info->fix.smem_len,
                        info->screen_base, fbi->fb_start_dma);
-failed:
+failed_free_info:
        kfree(info);
+failed_put_clk:
        clk_put(clk);
 
        dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret);
index 3b7f2f5..4de541c 100644 (file)
@@ -2237,6 +2237,22 @@ static int __devinit savagefb_probe(struct pci_dev* dev,
                                 &info->modelist);
 #endif
        info->var = savagefb_var800x600x8;
+       /* if a panel was detected, default to a CVT mode instead */
+       if (par->SavagePanelWidth) {
+               struct fb_videomode cvt_mode;
+
+               memset(&cvt_mode, 0, sizeof(cvt_mode));
+               cvt_mode.xres = par->SavagePanelWidth;
+               cvt_mode.yres = par->SavagePanelHeight;
+               cvt_mode.refresh = 60;
+               /* FIXME: if we know there is only the panel
+                * we can enable reduced blanking as well */
+               if (fb_find_mode_cvt(&cvt_mode, 0, 0))
+                       printk(KERN_WARNING "No CVT mode found for panel\n");
+               else if (fb_find_mode(&info->var, info, NULL, NULL, 0,
+                                     &cvt_mode, 0) != 3)
+                       info->var = savagefb_var800x600x8;
+       }
 
        if (mode_option) {
                fb_find_mode(&info->var, info, mode_option,
index 404c03b..019dbd3 100644 (file)
@@ -470,7 +470,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
        unsigned long tmp;
        int bpp = 0;
        unsigned long ldddsr;
-       int k, m;
+       int k, m, ret;
 
        /* enable clocks before accessing the hardware */
        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
@@ -540,7 +540,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 
                board_cfg = &ch->cfg.board_cfg;
                if (board_cfg->setup_sys) {
-                       int ret = board_cfg->setup_sys(board_cfg->board_data,
+                       ret = board_cfg->setup_sys(board_cfg->board_data,
                                                ch, &sh_mobile_lcdc_sys_bus_ops);
                        if (ret)
                                return ret;
index 53b2c5a..305c975 100644 (file)
@@ -1265,9 +1265,11 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image
 
 static void vga16fb_destroy(struct fb_info *info)
 {
+       struct platform_device *dev = container_of(info->device, struct platform_device, dev);
        iounmap(info->screen_base);
        fb_dealloc_cmap(&info->cmap);
        /* XXX unshare VGA regions */
+       platform_set_drvdata(dev, NULL);
        framebuffer_release(info);
 }
 
index a20218c..beac52f 100644 (file)
@@ -395,10 +395,9 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
        spin_lock_init(&info->dirty_lock);
        spin_lock_init(&info->resize_lock);
 
-       info->fb = vmalloc(fb_size);
+       info->fb = vzalloc(fb_size);
        if (info->fb == NULL)
                goto error_nomem;
-       memset(info->fb, 0, fb_size);
 
        info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
index 3ff822b..553da68 100644 (file)
@@ -626,6 +626,9 @@ int xen_allocate_pirq_gsi(unsigned gsi)
  *
  * Note: We don't assign an event channel until the irq actually started
  * up.  Return an existing irq if we've already got one for the gsi.
+ *
+ * Shareable implies level triggered, not shareable implies edge
+ * triggered here.
  */
 int xen_bind_pirq_gsi_to_irq(unsigned gsi,
                             unsigned pirq, int shareable, char *name)
@@ -664,16 +667,13 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
 
        pirq_query_unmask(irq);
        /* We try to use the handler with the appropriate semantic for the
-        * type of interrupt: if the interrupt doesn't need an eoi
-        * (pirq_needs_eoi returns false), we treat it like an edge
-        * triggered interrupt so we use handle_edge_irq.
-        * As a matter of fact this only happens when the corresponding
-        * physical interrupt is edge triggered or an msi.
+        * type of interrupt: if the interrupt is an edge triggered
+        * interrupt we use handle_edge_irq.
         *
-        * On the other hand if the interrupt needs an eoi (pirq_needs_eoi
-        * returns true) we treat it like a level triggered interrupt so we
-        * use handle_fasteoi_irq like the native code does for this kind of
+        * On the other hand if the interrupt is level triggered we use
+        * handle_fasteoi_irq like the native code does for this kind of
         * interrupts.
+        *
         * Depending on the Xen version, pirq_needs_eoi might return true
         * not only for level triggered interrupts but for edge triggered
         * interrupts too. In any case Xen always honors the eoi mechanism,
@@ -681,7 +681,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
         * hasn't received an eoi yet. Therefore using the fasteoi handler
         * is the right choice either way.
         */
-       if (pirq_needs_eoi(irq))
+       if (shareable)
                irq_set_chip_and_handler_name(irq, &xen_pirq_chip,
                                handle_fasteoi_irq, name);
        else
index 65ea21a..6e8c15a 100644 (file)
@@ -147,9 +147,15 @@ void __init xen_swiotlb_init(int verbose)
 {
        unsigned long bytes;
        int rc;
-
-       xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT);
-       xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE);
+       unsigned long nr_tbl;
+
+       nr_tbl = swioltb_nr_tbl();
+       if (nr_tbl)
+               xen_io_tlb_nslabs = nr_tbl;
+       else {
+               xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT);
+               xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE);
+       }
 
        bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT;
 
index 93b1aa9..52d7eca 100644 (file)
@@ -121,9 +121,6 @@ struct btrfs_inode {
         */
        u64 index_cnt;
 
-       /* the start of block group preferred for allocations. */
-       u64 block_group;
-
        /* the fsync log has some corner cases that mean we have to check
         * directories to see if any unlinks have been done before
         * the directory was logged.  See tree-log.c for all the
index b0e18d9..d840893 100644 (file)
@@ -43,8 +43,6 @@ struct btrfs_path *btrfs_alloc_path(void)
 {
        struct btrfs_path *path;
        path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS);
-       if (path)
-               path->reada = 1;
        return path;
 }
 
@@ -1224,6 +1222,7 @@ static void reada_for_search(struct btrfs_root *root,
        u64 search;
        u64 target;
        u64 nread = 0;
+       u64 gen;
        int direction = path->reada;
        struct extent_buffer *eb;
        u32 nr;
@@ -1251,6 +1250,15 @@ static void reada_for_search(struct btrfs_root *root,
        nritems = btrfs_header_nritems(node);
        nr = slot;
        while (1) {
+               if (!node->map_token) {
+                       unsigned long offset = btrfs_node_key_ptr_offset(nr);
+                       map_private_extent_buffer(node, offset,
+                                                 sizeof(struct btrfs_key_ptr),
+                                                 &node->map_token,
+                                                 &node->kaddr,
+                                                 &node->map_start,
+                                                 &node->map_len, KM_USER1);
+               }
                if (direction < 0) {
                        if (nr == 0)
                                break;
@@ -1268,14 +1276,23 @@ static void reada_for_search(struct btrfs_root *root,
                search = btrfs_node_blockptr(node, nr);
                if ((search <= target && target - search <= 65536) ||
                    (search > target && search - target <= 65536)) {
-                       readahead_tree_block(root, search, blocksize,
-                                    btrfs_node_ptr_generation(node, nr));
+                       gen = btrfs_node_ptr_generation(node, nr);
+                       if (node->map_token) {
+                               unmap_extent_buffer(node, node->map_token,
+                                                   KM_USER1);
+                               node->map_token = NULL;
+                       }
+                       readahead_tree_block(root, search, blocksize, gen);
                        nread += blocksize;
                }
                nscan++;
                if ((nread > 65536 || nscan > 32))
                        break;
        }
+       if (node->map_token) {
+               unmap_extent_buffer(node, node->map_token, KM_USER1);
+               node->map_token = NULL;
+       }
 }
 
 /*
@@ -1648,9 +1665,6 @@ again:
                }
 cow_done:
                BUG_ON(!cow && ins_len);
-               if (level != btrfs_header_level(b))
-                       WARN_ON(1);
-               level = btrfs_header_level(b);
 
                p->nodes[level] = b;
                if (!p->skip_locking)
index 6c093fa..378b5b4 100644 (file)
@@ -930,7 +930,6 @@ struct btrfs_fs_info {
         * is required instead of the faster short fsync log commits
         */
        u64 last_trans_log_full_commit;
-       u64 open_ioctl_trans;
        unsigned long mount_opt:20;
        unsigned long compress_type:4;
        u64 max_inline;
@@ -947,7 +946,6 @@ struct btrfs_fs_info {
        struct super_block *sb;
        struct inode *btree_inode;
        struct backing_dev_info bdi;
-       struct mutex trans_mutex;
        struct mutex tree_log_mutex;
        struct mutex transaction_kthread_mutex;
        struct mutex cleaner_mutex;
@@ -968,6 +966,7 @@ struct btrfs_fs_info {
        struct rw_semaphore subvol_sem;
        struct srcu_struct subvol_srcu;
 
+       spinlock_t trans_lock;
        struct list_head trans_list;
        struct list_head hashers;
        struct list_head dead_roots;
@@ -980,6 +979,7 @@ struct btrfs_fs_info {
        atomic_t async_submit_draining;
        atomic_t nr_async_bios;
        atomic_t async_delalloc_pages;
+       atomic_t open_ioctl_trans;
 
        /*
         * this is used by the balancing code to wait for all the pending
@@ -1044,6 +1044,7 @@ struct btrfs_fs_info {
        int closing;
        int log_root_recovering;
        int enospc_unlink;
+       int trans_no_join;
 
        u64 total_pinned;
 
@@ -1065,7 +1066,6 @@ struct btrfs_fs_info {
        struct reloc_control *reloc_ctl;
 
        spinlock_t delalloc_lock;
-       spinlock_t new_trans_lock;
        u64 delalloc_bytes;
 
        /* data_alloc_cluster is only used in ssd mode */
@@ -1340,6 +1340,7 @@ struct btrfs_ioctl_defrag_range_args {
 #define BTRFS_MOUNT_USER_SUBVOL_RM_ALLOWED (1 << 14)
 #define BTRFS_MOUNT_ENOSPC_DEBUG        (1 << 15)
 #define BTRFS_MOUNT_AUTO_DEFRAG                (1 << 16)
+#define BTRFS_MOUNT_INODE_MAP_CACHE    (1 << 17)
 
 #define btrfs_clear_opt(o, opt)                ((o) &= ~BTRFS_MOUNT_##opt)
 #define btrfs_set_opt(o, opt)          ((o) |= BTRFS_MOUNT_##opt)
@@ -2238,6 +2239,9 @@ int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
 void btrfs_block_rsv_release(struct btrfs_root *root,
                             struct btrfs_block_rsv *block_rsv,
                             u64 num_bytes);
+int btrfs_truncate_reserve_metadata(struct btrfs_trans_handle *trans,
+                                   struct btrfs_root *root,
+                                   struct btrfs_block_rsv *rsv);
 int btrfs_set_block_group_ro(struct btrfs_root *root,
                             struct btrfs_block_group_cache *cache);
 int btrfs_set_block_group_rw(struct btrfs_root *root,
@@ -2350,6 +2354,15 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root,
                        struct extent_buffer *node,
                        struct extent_buffer *parent);
+static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info)
+{
+       /*
+        * Get synced with close_ctree()
+        */
+       smp_mb();
+       return fs_info->closing;
+}
+
 /* root-item.c */
 int btrfs_find_root_ref(struct btrfs_root *tree_root,
                        struct btrfs_path *path,
@@ -2512,8 +2525,7 @@ int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
 int btrfs_writepages(struct address_space *mapping,
                     struct writeback_control *wbc);
 int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
-                            struct btrfs_root *new_root,
-                            u64 new_dirid, u64 alloc_hint);
+                            struct btrfs_root *new_root, u64 new_dirid);
 int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
                         size_t size, struct bio *bio, unsigned long bio_flags);
 
index 01e2950..6462c29 100644 (file)
@@ -678,6 +678,7 @@ static int btrfs_batch_insert_items(struct btrfs_trans_handle *trans,
        INIT_LIST_HEAD(&head);
 
        next = item;
+       nitems = 0;
 
        /*
         * count the number of the continuous items that we can insert in batch
@@ -1129,7 +1130,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)
        delayed_node = async_node->delayed_node;
        root = delayed_node->root;
 
-       trans = btrfs_join_transaction(root, 0);
+       trans = btrfs_join_transaction(root);
        if (IS_ERR(trans))
                goto free_path;
 
@@ -1572,8 +1573,7 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans,
        btrfs_set_stack_inode_transid(inode_item, trans->transid);
        btrfs_set_stack_inode_rdev(inode_item, inode->i_rdev);
        btrfs_set_stack_inode_flags(inode_item, BTRFS_I(inode)->flags);
-       btrfs_set_stack_inode_block_group(inode_item,
-                                         BTRFS_I(inode)->block_group);
+       btrfs_set_stack_inode_block_group(inode_item, 0);
 
        btrfs_set_stack_timespec_sec(btrfs_inode_atime(inode_item),
                                     inode->i_atime.tv_sec);
@@ -1595,7 +1595,7 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans,
                               struct btrfs_root *root, struct inode *inode)
 {
        struct btrfs_delayed_node *delayed_node;
-       int ret;
+       int ret = 0;
 
        delayed_node = btrfs_get_or_create_delayed_node(inode);
        if (IS_ERR(delayed_node))
index 98b6a71..a203d36 100644 (file)
@@ -1505,24 +1505,24 @@ static int transaction_kthread(void *arg)
                vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
                mutex_lock(&root->fs_info->transaction_kthread_mutex);
 
-               spin_lock(&root->fs_info->new_trans_lock);
+               spin_lock(&root->fs_info->trans_lock);
                cur = root->fs_info->running_transaction;
                if (!cur) {
-                       spin_unlock(&root->fs_info->new_trans_lock);
+                       spin_unlock(&root->fs_info->trans_lock);
                        goto sleep;
                }
 
                now = get_seconds();
                if (!cur->blocked &&
                    (now < cur->start_time || now - cur->start_time < 30)) {
-                       spin_unlock(&root->fs_info->new_trans_lock);
+                       spin_unlock(&root->fs_info->trans_lock);
                        delay = HZ * 5;
                        goto sleep;
                }
                transid = cur->transid;
-               spin_unlock(&root->fs_info->new_trans_lock);
+               spin_unlock(&root->fs_info->trans_lock);
 
-               trans = btrfs_join_transaction(root, 1);
+               trans = btrfs_join_transaction(root);
                BUG_ON(IS_ERR(trans));
                if (transid == trans->transid) {
                        ret = btrfs_commit_transaction(trans, root);
@@ -1613,7 +1613,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        INIT_LIST_HEAD(&fs_info->ordered_operations);
        INIT_LIST_HEAD(&fs_info->caching_block_groups);
        spin_lock_init(&fs_info->delalloc_lock);
-       spin_lock_init(&fs_info->new_trans_lock);
+       spin_lock_init(&fs_info->trans_lock);
        spin_lock_init(&fs_info->ref_cache_lock);
        spin_lock_init(&fs_info->fs_roots_radix_lock);
        spin_lock_init(&fs_info->delayed_iput_lock);
@@ -1645,6 +1645,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        fs_info->max_inline = 8192 * 1024;
        fs_info->metadata_ratio = 0;
        fs_info->defrag_inodes = RB_ROOT;
+       fs_info->trans_no_join = 0;
 
        fs_info->thread_pool_size = min_t(unsigned long,
                                          num_online_cpus() + 2, 8);
@@ -1709,7 +1710,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        fs_info->do_barriers = 1;
 
 
-       mutex_init(&fs_info->trans_mutex);
        mutex_init(&fs_info->ordered_operations_mutex);
        mutex_init(&fs_info->tree_log_mutex);
        mutex_init(&fs_info->chunk_mutex);
@@ -2479,13 +2479,13 @@ int btrfs_commit_super(struct btrfs_root *root)
        down_write(&root->fs_info->cleanup_work_sem);
        up_write(&root->fs_info->cleanup_work_sem);
 
-       trans = btrfs_join_transaction(root, 1);
+       trans = btrfs_join_transaction(root);
        if (IS_ERR(trans))
                return PTR_ERR(trans);
        ret = btrfs_commit_transaction(trans, root);
        BUG_ON(ret);
        /* run commit again to drop the original snapshot */
-       trans = btrfs_join_transaction(root, 1);
+       trans = btrfs_join_transaction(root);
        if (IS_ERR(trans))
                return PTR_ERR(trans);
        btrfs_commit_transaction(trans, root);
@@ -3024,10 +3024,13 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
 
        WARN_ON(1);
 
-       mutex_lock(&root->fs_info->trans_mutex);
        mutex_lock(&root->fs_info->transaction_kthread_mutex);
 
+       spin_lock(&root->fs_info->trans_lock);
        list_splice_init(&root->fs_info->trans_list, &list);
+       root->fs_info->trans_no_join = 1;
+       spin_unlock(&root->fs_info->trans_lock);
+
        while (!list_empty(&list)) {
                t = list_entry(list.next, struct btrfs_transaction, list);
                if (!t)
@@ -3052,23 +3055,18 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
                t->blocked = 0;
                if (waitqueue_active(&root->fs_info->transaction_wait))
                        wake_up(&root->fs_info->transaction_wait);
-               mutex_unlock(&root->fs_info->trans_mutex);
 
-               mutex_lock(&root->fs_info->trans_mutex);
                t->commit_done = 1;
                if (waitqueue_active(&t->commit_wait))
                        wake_up(&t->commit_wait);
-               mutex_unlock(&root->fs_info->trans_mutex);
-
-               mutex_lock(&root->fs_info->trans_mutex);
 
                btrfs_destroy_pending_snapshots(t);
 
                btrfs_destroy_delalloc_inodes(root);
 
-               spin_lock(&root->fs_info->new_trans_lock);
+               spin_lock(&root->fs_info->trans_lock);
                root->fs_info->running_transaction = NULL;
-               spin_unlock(&root->fs_info->new_trans_lock);
+               spin_unlock(&root->fs_info->trans_lock);
 
                btrfs_destroy_marked_extents(root, &t->dirty_pages,
                                             EXTENT_DIRTY);
@@ -3082,8 +3080,10 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
                kmem_cache_free(btrfs_transaction_cachep, t);
        }
 
+       spin_lock(&root->fs_info->trans_lock);
+       root->fs_info->trans_no_join = 0;
+       spin_unlock(&root->fs_info->trans_lock);
        mutex_unlock(&root->fs_info->transaction_kthread_mutex);
-       mutex_unlock(&root->fs_info->trans_mutex);
 
        return 0;
 }
index 169bd62..5b9b6b6 100644 (file)
@@ -348,7 +348,7 @@ static int caching_kthread(void *data)
         */
        path->skip_locking = 1;
        path->search_commit_root = 1;
-       path->reada = 2;
+       path->reada = 1;
 
        key.objectid = last;
        key.offset = 0;
@@ -366,8 +366,7 @@ again:
        nritems = btrfs_header_nritems(leaf);
 
        while (1) {
-               smp_mb();
-               if (fs_info->closing > 1) {
+               if (btrfs_fs_closing(fs_info) > 1) {
                        last = (u64)-1;
                        break;
                }
@@ -379,15 +378,18 @@ again:
                        if (ret)
                                break;
 
-                       caching_ctl->progress = last;
-                       btrfs_release_path(path);
-                       up_read(&fs_info->extent_commit_sem);
-                       mutex_unlock(&caching_ctl->mutex);
-                       if (btrfs_transaction_in_commit(fs_info))
-                               schedule_timeout(1);
-                       else
+                       if (need_resched() ||
+                           btrfs_next_leaf(extent_root, path)) {
+                               caching_ctl->progress = last;
+                               btrfs_release_path(path);
+                               up_read(&fs_info->extent_commit_sem);
+                               mutex_unlock(&caching_ctl->mutex);
                                cond_resched();
-                       goto again;
+                               goto again;
+                       }
+                       leaf = path->nodes[0];
+                       nritems = btrfs_header_nritems(leaf);
+                       continue;
                }
 
                if (key.objectid < block_group->key.objectid) {
@@ -3065,7 +3067,7 @@ again:
                        spin_unlock(&data_sinfo->lock);
 alloc:
                        alloc_target = btrfs_get_alloc_profile(root, 1);
-                       trans = btrfs_join_transaction(root, 1);
+                       trans = btrfs_join_transaction(root);
                        if (IS_ERR(trans))
                                return PTR_ERR(trans);
 
@@ -3091,9 +3093,10 @@ alloc:
 
                /* commit the current transaction and try again */
 commit_trans:
-               if (!committed && !root->fs_info->open_ioctl_trans) {
+               if (!committed &&
+                   !atomic_read(&root->fs_info->open_ioctl_trans)) {
                        committed = 1;
-                       trans = btrfs_join_transaction(root, 1);
+                       trans = btrfs_join_transaction(root);
                        if (IS_ERR(trans))
                                return PTR_ERR(trans);
                        ret = btrfs_commit_transaction(trans, root);
@@ -3472,7 +3475,7 @@ again:
                goto out;
 
        ret = -ENOSPC;
-       trans = btrfs_join_transaction(root, 1);
+       trans = btrfs_join_transaction(root);
        if (IS_ERR(trans))
                goto out;
        ret = btrfs_commit_transaction(trans, root);
@@ -3699,7 +3702,7 @@ int btrfs_block_rsv_check(struct btrfs_trans_handle *trans,
                if (trans)
                        return -EAGAIN;
 
-               trans = btrfs_join_transaction(root, 1);
+               trans = btrfs_join_transaction(root);
                BUG_ON(IS_ERR(trans));
                ret = btrfs_commit_transaction(trans, root);
                return 0;
@@ -3837,6 +3840,37 @@ static void release_global_block_rsv(struct btrfs_fs_info *fs_info)
        WARN_ON(fs_info->chunk_block_rsv.reserved > 0);
 }
 
+int btrfs_truncate_reserve_metadata(struct btrfs_trans_handle *trans,
+                                   struct btrfs_root *root,
+                                   struct btrfs_block_rsv *rsv)
+{
+       struct btrfs_block_rsv *trans_rsv = &root->fs_info->trans_block_rsv;
+       u64 num_bytes;
+       int ret;
+
+       /*
+        * Truncate should be freeing data, but give us 2 items just in case it
+        * needs to use some space.  We may want to be smarter about this in the
+        * future.
+        */
+       num_bytes = btrfs_calc_trans_metadata_size(root, 2);
+
+       /* We already have enough bytes, just return */
+       if (rsv->reserved >= num_bytes)
+               return 0;
+
+       num_bytes -= rsv->reserved;
+
+       /*
+        * You should have reserved enough space before hand to do this, so this
+        * should not fail.
+        */
+       ret = block_rsv_migrate_bytes(trans_rsv, rsv, num_bytes);
+       BUG_ON(ret);
+
+       return 0;
+}
+
 int btrfs_trans_reserve_metadata(struct btrfs_trans_handle *trans,
                                 struct btrfs_root *root,
                                 int num_items)
@@ -3877,23 +3911,18 @@ int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,
        struct btrfs_block_rsv *dst_rsv = root->orphan_block_rsv;
 
        /*
-        * one for deleting orphan item, one for updating inode and
-        * two for calling btrfs_truncate_inode_items.
-        *
-        * btrfs_truncate_inode_items is a delete operation, it frees
-        * more space than it uses in most cases. So two units of
-        * metadata space should be enough for calling it many times.
-        * If all of the metadata space is used, we can commit
-        * transaction and use space it freed.
+        * We need to hold space in order to delete our orphan item once we've
+        * added it, so this takes the reservation so we can release it later
+        * when we are truly done with the orphan item.
         */
-       u64 num_bytes = btrfs_calc_trans_metadata_size(root, 4);
+       u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1);
        return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes);
 }
 
 void btrfs_orphan_release_metadata(struct inode *inode)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
-       u64 num_bytes = btrfs_calc_trans_metadata_size(root, 4);
+       u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1);
        btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes);
 }
 
@@ -4987,6 +5016,15 @@ have_block_group:
                if (unlikely(block_group->ro))
                        goto loop;
 
+               spin_lock(&block_group->free_space_ctl->tree_lock);
+               if (cached &&
+                   block_group->free_space_ctl->free_space <
+                   num_bytes + empty_size) {
+                       spin_unlock(&block_group->free_space_ctl->tree_lock);
+                       goto loop;
+               }
+               spin_unlock(&block_group->free_space_ctl->tree_lock);
+
                /*
                 * Ok we want to try and use the cluster allocator, so lets look
                 * there, unless we are on LOOP_NO_EMPTY_SIZE, since we will
@@ -5150,6 +5188,7 @@ checks:
                        btrfs_add_free_space(block_group, offset,
                                             search_start - offset);
                BUG_ON(offset > search_start);
+               btrfs_put_block_group(block_group);
                break;
 loop:
                failed_cluster_refill = false;
@@ -5242,14 +5281,7 @@ loop:
                ret = -ENOSPC;
        } else if (!ins->objectid) {
                ret = -ENOSPC;
-       }
-
-       /* we found what we needed */
-       if (ins->objectid) {
-               if (!(data & BTRFS_BLOCK_GROUP_DATA))
-                       trans->block_group = block_group->key.objectid;
-
-               btrfs_put_block_group(block_group);
+       } else if (ins->objectid) {
                ret = 0;
        }
 
@@ -6526,7 +6558,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
 
        BUG_ON(cache->ro);
 
-       trans = btrfs_join_transaction(root, 1);
+       trans = btrfs_join_transaction(root);
        BUG_ON(IS_ERR(trans));
 
        alloc_flags = update_block_group_flags(root, cache->flags);
@@ -6882,6 +6914,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
+       path->reada = 1;
 
        cache_gen = btrfs_super_cache_generation(&root->fs_info->super_copy);
        if (cache_gen != 0 &&
index c5d9fbb..7055d11 100644 (file)
@@ -1476,7 +1476,7 @@ u64 count_range_bits(struct extent_io_tree *tree,
                        if (total_bytes >= max_bytes)
                                break;
                        if (!found) {
-                               *start = state->start;
+                               *start = max(cur_start, state->start);
                                found = 1;
                        }
                        last = state->end;
index c6a22d7..fa4ef18 100644 (file)
@@ -129,7 +129,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
        if (!btrfs_test_opt(root, AUTO_DEFRAG))
                return 0;
 
-       if (root->fs_info->closing)
+       if (btrfs_fs_closing(root->fs_info))
                return 0;
 
        if (BTRFS_I(inode)->in_defrag)
@@ -144,7 +144,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
        if (!defrag)
                return -ENOMEM;
 
-       defrag->ino = inode->i_ino;
+       defrag->ino = btrfs_ino(inode);
        defrag->transid = transid;
        defrag->root = root->root_key.objectid;
 
@@ -229,7 +229,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
                first_ino = defrag->ino + 1;
                rb_erase(&defrag->rb_node, &fs_info->defrag_inodes);
 
-               if (fs_info->closing)
+               if (btrfs_fs_closing(fs_info))
                        goto next_free;
 
                spin_unlock(&fs_info->defrag_inodes_lock);
@@ -1480,14 +1480,12 @@ int btrfs_sync_file(struct file *file, int datasync)
         * the current transaction, we can bail out now without any
         * syncing
         */
-       mutex_lock(&root->fs_info->trans_mutex);
+       smp_mb();
        if (BTRFS_I(inode)->last_trans <=
            root->fs_info->last_trans_committed) {
                BTRFS_I(inode)->last_trans = 0;
-               mutex_unlock(&root->fs_info->trans_mutex);
                goto out;
        }
-       mutex_unlock(&root->fs_info->trans_mutex);
 
        /*
         * ok we haven't committed the transaction yet, lets do a commit
index 70d4579..ad14473 100644 (file)
@@ -98,7 +98,7 @@ struct inode *lookup_free_space_inode(struct btrfs_root *root,
                return inode;
 
        spin_lock(&block_group->lock);
-       if (!root->fs_info->closing) {
+       if (!btrfs_fs_closing(root->fs_info)) {
                block_group->inode = igrab(inode);
                block_group->iref = 1;
        }
@@ -402,7 +402,14 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
                                spin_lock(&ctl->tree_lock);
                                ret = link_free_space(ctl, e);
                                spin_unlock(&ctl->tree_lock);
-                               BUG_ON(ret);
+                               if (ret) {
+                                       printk(KERN_ERR "Duplicate entries in "
+                                              "free space cache, dumping\n");
+                                       kunmap(page);
+                                       unlock_page(page);
+                                       page_cache_release(page);
+                                       goto free_cache;
+                               }
                        } else {
                                e->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
                                if (!e->bitmap) {
@@ -419,6 +426,14 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
                                ctl->op->recalc_thresholds(ctl);
                                spin_unlock(&ctl->tree_lock);
                                list_add_tail(&e->list, &bitmaps);
+                               if (ret) {
+                                       printk(KERN_ERR "Duplicate entries in "
+                                              "free space cache, dumping\n");
+                                       kunmap(page);
+                                       unlock_page(page);
+                                       page_cache_release(page);
+                                       goto free_cache;
+                               }
                        }
 
                        num_entries--;
@@ -478,8 +493,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
         * If we're unmounting then just return, since this does a search on the
         * normal root and not the commit root and we could deadlock.
         */
-       smp_mb();
-       if (fs_info->closing)
+       if (btrfs_fs_closing(fs_info))
                return 0;
 
        /*
@@ -575,10 +589,25 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 
        num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
                PAGE_CACHE_SHIFT;
+
+       /* Since the first page has all of our checksums and our generation we
+        * need to calculate the offset into the page that we can start writing
+        * our entries.
+        */
+       first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64);
+
        filemap_write_and_wait(inode->i_mapping);
        btrfs_wait_ordered_range(inode, inode->i_size &
                                 ~(root->sectorsize - 1), (u64)-1);
 
+       /* make sure we don't overflow that first page */
+       if (first_page_offset + sizeof(struct btrfs_free_space_entry) >= PAGE_CACHE_SIZE) {
+               /* this is really the same as running out of space, where we also return 0 */
+               printk(KERN_CRIT "Btrfs: free space cache was too big for the crc page\n");
+               ret = 0;
+               goto out_update;
+       }
+
        /* We need a checksum per page. */
        crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS);
        if (!crc)
@@ -590,12 +619,6 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
                return -1;
        }
 
-       /* Since the first page has all of our checksums and our generation we
-        * need to calculate the offset into the page that we can start writing
-        * our entries.
-        */
-       first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64);
-
        /* Get the cluster for this block_group if it exists */
        if (block_group && !list_empty(&block_group->cluster_list))
                cluster = list_entry(block_group->cluster_list.next,
@@ -857,12 +880,14 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
        ret = 1;
 
 out_free:
+       kfree(checksums);
+       kfree(pages);
+
+out_update:
        if (ret != 1) {
                invalidate_inode_pages2_range(inode->i_mapping, 0, index);
                BTRFS_I(inode)->generation = 0;
        }
-       kfree(checksums);
-       kfree(pages);
        btrfs_update_inode(trans, root, inode);
        return ret;
 }
@@ -963,10 +988,16 @@ static int tree_insert_offset(struct rb_root *root, u64 offset,
                         * logically.
                         */
                        if (bitmap) {
-                               WARN_ON(info->bitmap);
+                               if (info->bitmap) {
+                                       WARN_ON_ONCE(1);
+                                       return -EEXIST;
+                               }
                                p = &(*p)->rb_right;
                        } else {
-                               WARN_ON(!info->bitmap);
+                               if (!info->bitmap) {
+                                       WARN_ON_ONCE(1);
+                                       return -EEXIST;
+                               }
                                p = &(*p)->rb_left;
                        }
                }
@@ -2481,7 +2512,7 @@ struct inode *lookup_free_ino_inode(struct btrfs_root *root,
                return inode;
 
        spin_lock(&root->cache_lock);
-       if (!root->fs_info->closing)
+       if (!btrfs_fs_closing(root->fs_info))
                root->cache_inode = igrab(inode);
        spin_unlock(&root->cache_lock);
 
@@ -2504,12 +2535,14 @@ int load_free_ino_cache(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
        int ret = 0;
        u64 root_gen = btrfs_root_generation(&root->root_item);
 
+       if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+               return 0;
+
        /*
         * If we're unmounting then just return, since this does a search on the
         * normal root and not the commit root and we could deadlock.
         */
-       smp_mb();
-       if (fs_info->closing)
+       if (btrfs_fs_closing(fs_info))
                return 0;
 
        path = btrfs_alloc_path();
@@ -2543,6 +2576,9 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root,
        struct inode *inode;
        int ret;
 
+       if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+               return 0;
+
        inode = lookup_free_ino_inode(root, path);
        if (IS_ERR(inode))
                return 0;
index 3262cd1..b4087e0 100644 (file)
@@ -38,6 +38,9 @@ static int caching_kthread(void *data)
        int slot;
        int ret;
 
+       if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+               return 0;
+
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -59,8 +62,7 @@ again:
                goto out;
 
        while (1) {
-               smp_mb();
-               if (fs_info->closing)
+               if (btrfs_fs_closing(fs_info))
                        goto out;
 
                leaf = path->nodes[0];
@@ -141,6 +143,9 @@ static void start_caching(struct btrfs_root *root)
        int ret;
        u64 objectid;
 
+       if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+               return;
+
        spin_lock(&root->cache_lock);
        if (root->cached != BTRFS_CACHE_NO) {
                spin_unlock(&root->cache_lock);
@@ -178,6 +183,9 @@ static void start_caching(struct btrfs_root *root)
 
 int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid)
 {
+       if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+               return btrfs_find_free_objectid(root, objectid);
+
 again:
        *objectid = btrfs_find_ino_for_alloc(root);
 
@@ -201,6 +209,10 @@ void btrfs_return_ino(struct btrfs_root *root, u64 objectid)
 {
        struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
        struct btrfs_free_space_ctl *pinned = root->free_ino_pinned;
+
+       if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+               return;
+
 again:
        if (root->cached == BTRFS_CACHE_FINISHED) {
                __btrfs_add_free_space(ctl, objectid, 1);
@@ -250,6 +262,9 @@ void btrfs_unpin_free_ino(struct btrfs_root *root)
        struct rb_node *n;
        u64 count;
 
+       if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+               return;
+
        while (1) {
                n = rb_first(rbroot);
                if (!n)
@@ -388,9 +403,24 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
        int prealloc;
        bool retry = false;
 
+       /* only fs tree and subvol/snap needs ino cache */
+       if (root->root_key.objectid != BTRFS_FS_TREE_OBJECTID &&
+           (root->root_key.objectid < BTRFS_FIRST_FREE_OBJECTID ||
+            root->root_key.objectid > BTRFS_LAST_FREE_OBJECTID))
+               return 0;
+
+       /* Don't save inode cache if we are deleting this root */
+       if (btrfs_root_refs(&root->root_item) == 0 &&
+           root != root->fs_info->tree_root)
+               return 0;
+
+       if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+               return 0;
+
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
+
 again:
        inode = lookup_free_ino_inode(root, path);
        if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) {
index 39a9d57..ebf95f7 100644 (file)
@@ -138,7 +138,6 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
                return -ENOMEM;
 
        path->leave_spinning = 1;
-       btrfs_set_trans_block_group(trans, inode);
 
        key.objectid = btrfs_ino(inode);
        key.offset = start;
@@ -426,9 +425,8 @@ again:
                }
        }
        if (start == 0) {
-               trans = btrfs_join_transaction(root, 1);
+               trans = btrfs_join_transaction(root);
                BUG_ON(IS_ERR(trans));
-               btrfs_set_trans_block_group(trans, inode);
                trans->block_rsv = &root->fs_info->delalloc_block_rsv;
 
                /* lets try to make an inline extent */
@@ -623,8 +621,9 @@ retry:
                            async_extent->start + async_extent->ram_size - 1,
                            GFP_NOFS);
 
-               trans = btrfs_join_transaction(root, 1);
+               trans = btrfs_join_transaction(root);
                BUG_ON(IS_ERR(trans));
+               trans->block_rsv = &root->fs_info->delalloc_block_rsv;
                ret = btrfs_reserve_extent(trans, root,
                                           async_extent->compressed_size,
                                           async_extent->compressed_size,
@@ -793,9 +792,8 @@ static noinline int cow_file_range(struct inode *inode,
        int ret = 0;
 
        BUG_ON(is_free_space_inode(root, inode));
-       trans = btrfs_join_transaction(root, 1);
+       trans = btrfs_join_transaction(root);
        BUG_ON(IS_ERR(trans));
-       btrfs_set_trans_block_group(trans, inode);
        trans->block_rsv = &root->fs_info->delalloc_block_rsv;
 
        num_bytes = (end - start + blocksize) & ~(blocksize - 1);
@@ -1077,10 +1075,12 @@ static noinline int run_delalloc_nocow(struct inode *inode,
        nolock = is_free_space_inode(root, inode);
 
        if (nolock)
-               trans = btrfs_join_transaction_nolock(root, 1);
+               trans = btrfs_join_transaction_nolock(root);
        else
-               trans = btrfs_join_transaction(root, 1);
+               trans = btrfs_join_transaction(root);
+
        BUG_ON(IS_ERR(trans));
+       trans->block_rsv = &root->fs_info->delalloc_block_rsv;
 
        cow_start = (u64)-1;
        cur_offset = start;
@@ -1519,8 +1519,6 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,
 {
        struct btrfs_ordered_sum *sum;
 
-       btrfs_set_trans_block_group(trans, inode);
-
        list_for_each_entry(sum, list, list) {
                btrfs_csum_file_blocks(trans,
                       BTRFS_I(inode)->root->fs_info->csum_root, sum);
@@ -1735,11 +1733,10 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
                ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
                if (!ret) {
                        if (nolock)
-                               trans = btrfs_join_transaction_nolock(root, 1);
+                               trans = btrfs_join_transaction_nolock(root);
                        else
-                               trans = btrfs_join_transaction(root, 1);
+                               trans = btrfs_join_transaction(root);
                        BUG_ON(IS_ERR(trans));
-                       btrfs_set_trans_block_group(trans, inode);
                        trans->block_rsv = &root->fs_info->delalloc_block_rsv;
                        ret = btrfs_update_inode(trans, root, inode);
                        BUG_ON(ret);
@@ -1752,11 +1749,10 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
                         0, &cached_state, GFP_NOFS);
 
        if (nolock)
-               trans = btrfs_join_transaction_nolock(root, 1);
+               trans = btrfs_join_transaction_nolock(root);
        else
-               trans = btrfs_join_transaction(root, 1);
+               trans = btrfs_join_transaction(root);
        BUG_ON(IS_ERR(trans));
-       btrfs_set_trans_block_group(trans, inode);
        trans->block_rsv = &root->fs_info->delalloc_block_rsv;
 
        if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
@@ -2431,7 +2427,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                                        (u64)-1);
 
        if (root->orphan_block_rsv || root->orphan_item_inserted) {
-               trans = btrfs_join_transaction(root, 1);
+               trans = btrfs_join_transaction(root);
                if (!IS_ERR(trans))
                        btrfs_end_transaction(trans, root);
        }
@@ -2511,12 +2507,12 @@ static void btrfs_read_locked_inode(struct inode *inode)
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_key location;
        int maybe_acls;
-       u64 alloc_group_block;
        u32 rdev;
        int ret;
 
        path = btrfs_alloc_path();
        BUG_ON(!path);
+       path->leave_spinning = 1;
        memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
 
        ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
@@ -2526,6 +2522,12 @@ static void btrfs_read_locked_inode(struct inode *inode)
        leaf = path->nodes[0];
        inode_item = btrfs_item_ptr(leaf, path->slots[0],
                                    struct btrfs_inode_item);
+       if (!leaf->map_token)
+               map_private_extent_buffer(leaf, (unsigned long)inode_item,
+                                         sizeof(struct btrfs_inode_item),
+                                         &leaf->map_token, &leaf->kaddr,
+                                         &leaf->map_start, &leaf->map_len,
+                                         KM_USER1);
 
        inode->i_mode = btrfs_inode_mode(leaf, inode_item);
        inode->i_nlink = btrfs_inode_nlink(leaf, inode_item);
@@ -2555,8 +2557,6 @@ static void btrfs_read_locked_inode(struct inode *inode)
        BTRFS_I(inode)->index_cnt = (u64)-1;
        BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
 
-       alloc_group_block = btrfs_inode_block_group(leaf, inode_item);
-
        /*
         * try to precache a NULL acl entry for files that don't have
         * any xattrs or acls
@@ -2566,8 +2566,11 @@ static void btrfs_read_locked_inode(struct inode *inode)
        if (!maybe_acls)
                cache_no_acl(inode);
 
-       BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0,
-                                               alloc_group_block, 0);
+       if (leaf->map_token) {
+               unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
+               leaf->map_token = NULL;
+       }
+
        btrfs_free_path(path);
        inode_item = NULL;
 
@@ -2647,7 +2650,7 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
        btrfs_set_inode_transid(leaf, item, trans->transid);
        btrfs_set_inode_rdev(leaf, item, inode->i_rdev);
        btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags);
-       btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group);
+       btrfs_set_inode_block_group(leaf, item, 0);
 
        if (leaf->map_token) {
                unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
@@ -3004,8 +3007,6 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
-       btrfs_set_trans_block_group(trans, dir);
-
        btrfs_record_unlink_dir(trans, dir, dentry->d_inode, 0);
 
        ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode,
@@ -3094,8 +3095,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
-       btrfs_set_trans_block_group(trans, dir);
-
        if (unlikely(btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
                err = btrfs_unlink_subvol(trans, root, dir,
                                          BTRFS_I(inode)->location.objectid,
@@ -3514,7 +3513,6 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
                                err = PTR_ERR(trans);
                                break;
                        }
-                       btrfs_set_trans_block_group(trans, inode);
 
                        err = btrfs_drop_extents(trans, inode, cur_offset,
                                                 cur_offset + hole_size,
@@ -3650,7 +3648,6 @@ void btrfs_evict_inode(struct inode *inode)
        while (1) {
                trans = btrfs_start_transaction(root, 0);
                BUG_ON(IS_ERR(trans));
-               btrfs_set_trans_block_group(trans, inode);
                trans->block_rsv = root->orphan_block_rsv;
 
                ret = btrfs_block_rsv_check(trans, root,
@@ -4133,7 +4130,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
-       path->reada = 2;
+
+       path->reada = 1;
 
        if (key_type == BTRFS_DIR_INDEX_KEY) {
                INIT_LIST_HEAD(&ins_list);
@@ -4268,18 +4266,16 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)
        if (BTRFS_I(inode)->dummy_inode)
                return 0;
 
-       smp_mb();
-       if (root->fs_info->closing && is_free_space_inode(root, inode))
+       if (btrfs_fs_closing(root->fs_info) && is_free_space_inode(root, inode))
                nolock = true;
 
        if (wbc->sync_mode == WB_SYNC_ALL) {
                if (nolock)
-                       trans = btrfs_join_transaction_nolock(root, 1);
+                       trans = btrfs_join_transaction_nolock(root);
                else
-                       trans = btrfs_join_transaction(root, 1);
+                       trans = btrfs_join_transaction(root);
                if (IS_ERR(trans))
                        return PTR_ERR(trans);
-               btrfs_set_trans_block_group(trans, inode);
                if (nolock)
                        ret = btrfs_end_transaction_nolock(trans, root);
                else
@@ -4303,9 +4299,8 @@ void btrfs_dirty_inode(struct inode *inode, int flags)
        if (BTRFS_I(inode)->dummy_inode)
                return;
 
-       trans = btrfs_join_transaction(root, 1);
+       trans = btrfs_join_transaction(root);
        BUG_ON(IS_ERR(trans));
-       btrfs_set_trans_block_group(trans, inode);
 
        ret = btrfs_update_inode(trans, root, inode);
        if (ret && ret == -ENOSPC) {
@@ -4319,7 +4314,6 @@ void btrfs_dirty_inode(struct inode *inode, int flags)
                                       PTR_ERR(trans));
                        return;
                }
-               btrfs_set_trans_block_group(trans, inode);
 
                ret = btrfs_update_inode(trans, root, inode);
                if (ret) {
@@ -4418,8 +4412,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                                     struct btrfs_root *root,
                                     struct inode *dir,
                                     const char *name, int name_len,
-                                    u64 ref_objectid, u64 objectid,
-                                    u64 alloc_hint, int mode, u64 *index)
+                                    u64 ref_objectid, u64 objectid, int mode,
+                                    u64 *index)
 {
        struct inode *inode;
        struct btrfs_inode_item *inode_item;
@@ -4472,8 +4466,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                owner = 0;
        else
                owner = 1;
-       BTRFS_I(inode)->block_group =
-                       btrfs_find_block_group(root, 0, alloc_hint, owner);
 
        key[0].objectid = objectid;
        btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY);
@@ -4629,15 +4621,13 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
-       btrfs_set_trans_block_group(trans, dir);
-
        err = btrfs_find_free_ino(root, &objectid);
        if (err)
                goto out_unlock;
 
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
                                dentry->d_name.len, btrfs_ino(dir), objectid,
-                               BTRFS_I(dir)->block_group, mode, &index);
+                               mode, &index);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                goto out_unlock;
@@ -4649,7 +4639,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
                goto out_unlock;
        }
 
-       btrfs_set_trans_block_group(trans, inode);
        err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
        if (err)
                drop_inode = 1;
@@ -4658,8 +4647,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
                init_special_inode(inode, inode->i_mode, rdev);
                btrfs_update_inode(trans, root, inode);
        }
-       btrfs_update_inode_block_group(trans, inode);
-       btrfs_update_inode_block_group(trans, dir);
 out_unlock:
        nr = trans->blocks_used;
        btrfs_end_transaction_throttle(trans, root);
@@ -4692,15 +4679,13 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
-       btrfs_set_trans_block_group(trans, dir);
-
        err = btrfs_find_free_ino(root, &objectid);
        if (err)
                goto out_unlock;
 
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
                                dentry->d_name.len, btrfs_ino(dir), objectid,
-                               BTRFS_I(dir)->block_group, mode, &index);
+                               mode, &index);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                goto out_unlock;
@@ -4712,7 +4697,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
                goto out_unlock;
        }
 
-       btrfs_set_trans_block_group(trans, inode);
        err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
        if (err)
                drop_inode = 1;
@@ -4723,8 +4707,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
                inode->i_op = &btrfs_file_inode_operations;
                BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
        }
-       btrfs_update_inode_block_group(trans, inode);
-       btrfs_update_inode_block_group(trans, dir);
 out_unlock:
        nr = trans->blocks_used;
        btrfs_end_transaction_throttle(trans, root);
@@ -4771,8 +4753,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
 
        btrfs_inc_nlink(inode);
        inode->i_ctime = CURRENT_TIME;
-
-       btrfs_set_trans_block_group(trans, dir);
        ihold(inode);
 
        err = btrfs_add_nondir(trans, dir, dentry, inode, 1, index);
@@ -4781,7 +4761,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
                drop_inode = 1;
        } else {
                struct dentry *parent = dget_parent(dentry);
-               btrfs_update_inode_block_group(trans, dir);
                err = btrfs_update_inode(trans, root, inode);
                BUG_ON(err);
                btrfs_log_new_name(trans, inode, NULL, parent);
@@ -4818,7 +4797,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        trans = btrfs_start_transaction(root, 5);
        if (IS_ERR(trans))
                return PTR_ERR(trans);
-       btrfs_set_trans_block_group(trans, dir);
 
        err = btrfs_find_free_ino(root, &objectid);
        if (err)
@@ -4826,8 +4804,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
                                dentry->d_name.len, btrfs_ino(dir), objectid,
-                               BTRFS_I(dir)->block_group, S_IFDIR | mode,
-                               &index);
+                               S_IFDIR | mode, &index);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                goto out_fail;
@@ -4841,7 +4818,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        inode->i_op = &btrfs_dir_inode_operations;
        inode->i_fop = &btrfs_dir_file_operations;
-       btrfs_set_trans_block_group(trans, inode);
 
        btrfs_i_size_write(inode, 0);
        err = btrfs_update_inode(trans, root, inode);
@@ -4855,8 +4831,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        d_instantiate(dentry, inode);
        drop_on_err = 0;
-       btrfs_update_inode_block_group(trans, inode);
-       btrfs_update_inode_block_group(trans, dir);
 
 out_fail:
        nr = trans->blocks_used;
@@ -4989,7 +4963,15 @@ again:
 
        if (!path) {
                path = btrfs_alloc_path();
-               BUG_ON(!path);
+               if (!path) {
+                       err = -ENOMEM;
+                       goto out;
+               }
+               /*
+                * Chances are we'll be called again, so go ahead and do
+                * readahead
+                */
+               path->reada = 1;
        }
 
        ret = btrfs_lookup_file_extent(trans, root, path,
@@ -5130,8 +5112,10 @@ again:
                                kunmap(page);
                                free_extent_map(em);
                                em = NULL;
+
                                btrfs_release_path(path);
-                               trans = btrfs_join_transaction(root, 1);
+                               trans = btrfs_join_transaction(root);
+
                                if (IS_ERR(trans))
                                        return ERR_CAST(trans);
                                goto again;
@@ -5375,7 +5359,7 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
                btrfs_drop_extent_cache(inode, start, start + len - 1, 0);
        }
 
-       trans = btrfs_join_transaction(root, 0);
+       trans = btrfs_join_transaction(root);
        if (IS_ERR(trans))
                return ERR_CAST(trans);
 
@@ -5611,7 +5595,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
                 * to make sure the current transaction stays open
                 * while we look for nocow cross refs
                 */
-               trans = btrfs_join_transaction(root, 0);
+               trans = btrfs_join_transaction(root);
                if (IS_ERR(trans))
                        goto must_cow;
 
@@ -5750,7 +5734,7 @@ again:
 
        BUG_ON(!ordered);
 
-       trans = btrfs_join_transaction(root, 1);
+       trans = btrfs_join_transaction(root);
        if (IS_ERR(trans)) {
                err = -ENOMEM;
                goto out;
@@ -6500,6 +6484,7 @@ out:
 static int btrfs_truncate(struct inode *inode)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_block_rsv *rsv;
        int ret;
        int err = 0;
        struct btrfs_trans_handle *trans;
@@ -6513,28 +6498,80 @@ static int btrfs_truncate(struct inode *inode)
        btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
        btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
 
-       trans = btrfs_start_transaction(root, 5);
-       if (IS_ERR(trans))
-               return PTR_ERR(trans);
+       /*
+        * Yes ladies and gentelment, this is indeed ugly.  The fact is we have
+        * 3 things going on here
+        *
+        * 1) We need to reserve space for our orphan item and the space to
+        * delete our orphan item.  Lord knows we don't want to have a dangling
+        * orphan item because we didn't reserve space to remove it.
+        *
+        * 2) We need to reserve space to update our inode.
+        *
+        * 3) We need to have something to cache all the space that is going to
+        * be free'd up by the truncate operation, but also have some slack
+        * space reserved in case it uses space during the truncate (thank you
+        * very much snapshotting).
+        *
+        * And we need these to all be seperate.  The fact is we can use alot of
+        * space doing the truncate, and we have no earthly idea how much space
+        * we will use, so we need the truncate reservation to be seperate so it
+        * doesn't end up using space reserved for updating the inode or
+        * removing the orphan item.  We also need to be able to stop the
+        * transaction and start a new one, which means we need to be able to
+        * update the inode several times, and we have no idea of knowing how
+        * many times that will be, so we can't just reserve 1 item for the
+        * entirety of the opration, so that has to be done seperately as well.
+        * Then there is the orphan item, which does indeed need to be held on
+        * to for the whole operation, and we need nobody to touch this reserved
+        * space except the orphan code.
+        *
+        * So that leaves us with
+        *
+        * 1) root->orphan_block_rsv - for the orphan deletion.
+        * 2) rsv - for the truncate reservation, which we will steal from the
+        * transaction reservation.
+        * 3) fs_info->trans_block_rsv - this will have 1 items worth left for
+        * updating the inode.
+        */
+       rsv = btrfs_alloc_block_rsv(root);
+       if (!rsv)
+               return -ENOMEM;
+       btrfs_add_durable_block_rsv(root->fs_info, rsv);
+
+       trans = btrfs_start_transaction(root, 4);
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
+               goto out;
+       }
 
-       btrfs_set_trans_block_group(trans, inode);
+       /*
+        * Reserve space for the truncate process.  Truncate should be adding
+        * space, but if there are snapshots it may end up using space.
+        */
+       ret = btrfs_truncate_reserve_metadata(trans, root, rsv);
+       BUG_ON(ret);
 
        ret = btrfs_orphan_add(trans, inode);
        if (ret) {
                btrfs_end_transaction(trans, root);
-               return ret;
+               goto out;
        }
 
        nr = trans->blocks_used;
        btrfs_end_transaction(trans, root);
        btrfs_btree_balance_dirty(root, nr);
 
-       /* Now start a transaction for the truncate */
-       trans = btrfs_start_transaction(root, 0);
-       if (IS_ERR(trans))
-               return PTR_ERR(trans);
-       btrfs_set_trans_block_group(trans, inode);
-       trans->block_rsv = root->orphan_block_rsv;
+       /*
+        * Ok so we've already migrated our bytes over for the truncate, so here
+        * just reserve the one slot we need for updating the inode.
+        */
+       trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
+               goto out;
+       }
+       trans->block_rsv = rsv;
 
        /*
         * setattr is responsible for setting the ordered_data_close flag,
@@ -6558,24 +6595,17 @@ static int btrfs_truncate(struct inode *inode)
 
        while (1) {
                if (!trans) {
-                       trans = btrfs_start_transaction(root, 0);
-                       if (IS_ERR(trans))
-                               return PTR_ERR(trans);
-                       btrfs_set_trans_block_group(trans, inode);
-                       trans->block_rsv = root->orphan_block_rsv;
-               }
+                       trans = btrfs_start_transaction(root, 3);
+                       if (IS_ERR(trans)) {
+                               err = PTR_ERR(trans);
+                               goto out;
+                       }
 
-               ret = btrfs_block_rsv_check(trans, root,
-                                           root->orphan_block_rsv, 0, 5);
-               if (ret == -EAGAIN) {
-                       ret = btrfs_commit_transaction(trans, root);
-                       if (ret)
-                               return ret;
-                       trans = NULL;
-                       continue;
-               } else if (ret) {
-                       err = ret;
-                       break;
+                       ret = btrfs_truncate_reserve_metadata(trans, root,
+                                                             rsv);
+                       BUG_ON(ret);
+
+                       trans->block_rsv = rsv;
                }
 
                ret = btrfs_truncate_inode_items(trans, root, inode,
@@ -6586,6 +6616,7 @@ static int btrfs_truncate(struct inode *inode)
                        break;
                }
 
+               trans->block_rsv = &root->fs_info->trans_block_rsv;
                ret = btrfs_update_inode(trans, root, inode);
                if (ret) {
                        err = ret;
@@ -6599,6 +6630,7 @@ static int btrfs_truncate(struct inode *inode)
        }
 
        if (ret == 0 && inode->i_nlink > 0) {
+               trans->block_rsv = root->orphan_block_rsv;
                ret = btrfs_orphan_del(trans, inode);
                if (ret)
                        err = ret;
@@ -6610,15 +6642,20 @@ static int btrfs_truncate(struct inode *inode)
                ret = btrfs_orphan_del(NULL, inode);
        }
 
+       trans->block_rsv = &root->fs_info->trans_block_rsv;
        ret = btrfs_update_inode(trans, root, inode);
        if (ret && !err)
                err = ret;
 
        nr = trans->blocks_used;
        ret = btrfs_end_transaction_throttle(trans, root);
+       btrfs_btree_balance_dirty(root, nr);
+
+out:
+       btrfs_free_block_rsv(root, rsv);
+
        if (ret && !err)
                err = ret;
-       btrfs_btree_balance_dirty(root, nr);
 
        return err;
 }
@@ -6627,15 +6664,14 @@ static int btrfs_truncate(struct inode *inode)
  * create a new subvolume directory/inode (helper for the ioctl).
  */
 int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
-                            struct btrfs_root *new_root,
-                            u64 new_dirid, u64 alloc_hint)
+                            struct btrfs_root *new_root, u64 new_dirid)
 {
        struct inode *inode;
        int err;
        u64 index = 0;
 
        inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid,
-                               new_dirid, alloc_hint, S_IFDIR | 0700, &index);
+                               new_dirid, S_IFDIR | 0700, &index);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
        inode->i_op = &btrfs_dir_inode_operations;
@@ -6748,21 +6784,6 @@ void btrfs_destroy_inode(struct inode *inode)
                spin_unlock(&root->fs_info->ordered_extent_lock);
        }
 
-       if (root == root->fs_info->tree_root) {
-               struct btrfs_block_group_cache *block_group;
-
-               block_group = btrfs_lookup_block_group(root->fs_info,
-                                               BTRFS_I(inode)->block_group);
-               if (block_group && block_group->inode == inode) {
-                       spin_lock(&block_group->lock);
-                       block_group->inode = NULL;
-                       spin_unlock(&block_group->lock);
-                       btrfs_put_block_group(block_group);
-               } else if (block_group) {
-                       btrfs_put_block_group(block_group);
-               }
-       }
-
        spin_lock(&root->orphan_lock);
        if (!list_empty(&BTRFS_I(inode)->i_orphan)) {
                printk(KERN_INFO "BTRFS: inode %llu still on the orphan list\n",
@@ -6948,8 +6969,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                 goto out_notrans;
         }
 
-       btrfs_set_trans_block_group(trans, new_dir);
-
        if (dest != root)
                btrfs_record_root_in_trans(trans, dest);
 
@@ -7131,16 +7150,13 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
-       btrfs_set_trans_block_group(trans, dir);
-
        err = btrfs_find_free_ino(root, &objectid);
        if (err)
                goto out_unlock;
 
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
                                dentry->d_name.len, btrfs_ino(dir), objectid,
-                               BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO,
-                               &index);
+                               S_IFLNK|S_IRWXUGO, &index);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                goto out_unlock;
@@ -7152,7 +7168,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
                goto out_unlock;
        }
 
-       btrfs_set_trans_block_group(trans, inode);
        err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
        if (err)
                drop_inode = 1;
@@ -7163,8 +7178,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
                inode->i_op = &btrfs_file_inode_operations;
                BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
        }
-       btrfs_update_inode_block_group(trans, inode);
-       btrfs_update_inode_block_group(trans, dir);
        if (drop_inode)
                goto out_unlock;
 
index 85e818c..ac37040 100644 (file)
@@ -243,7 +243,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
                ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
        }
 
-       trans = btrfs_join_transaction(root, 1);
+       trans = btrfs_join_transaction(root);
        BUG_ON(IS_ERR(trans));
 
        ret = btrfs_update_inode(trans, root, inode);
@@ -414,8 +414,7 @@ static noinline int create_subvol(struct btrfs_root *root,
 
        btrfs_record_root_in_trans(trans, new_root);
 
-       ret = btrfs_create_subvol_root(trans, new_root, new_dirid,
-                                      BTRFS_I(dir)->block_group);
+       ret = btrfs_create_subvol_root(trans, new_root, new_dirid);
        /*
         * insert the directory item
         */
@@ -707,16 +706,17 @@ static int find_new_extents(struct btrfs_root *root,
        struct btrfs_file_extent_item *extent;
        int type;
        int ret;
+       u64 ino = btrfs_ino(inode);
 
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
 
-       min_key.objectid = inode->i_ino;
+       min_key.objectid = ino;
        min_key.type = BTRFS_EXTENT_DATA_KEY;
        min_key.offset = *off;
 
-       max_key.objectid = inode->i_ino;
+       max_key.objectid = ino;
        max_key.type = (u8)-1;
        max_key.offset = (u64)-1;
 
@@ -727,7 +727,7 @@ static int find_new_extents(struct btrfs_root *root,
                                           path, 0, newer_than);
                if (ret != 0)
                        goto none;
-               if (min_key.objectid != inode->i_ino)
+               if (min_key.objectid != ino)
                        goto none;
                if (min_key.type != BTRFS_EXTENT_DATA_KEY)
                        goto none;
@@ -2489,12 +2489,10 @@ static long btrfs_ioctl_trans_start(struct file *file)
        if (ret)
                goto out;
 
-       mutex_lock(&root->fs_info->trans_mutex);
-       root->fs_info->open_ioctl_trans++;
-       mutex_unlock(&root->fs_info->trans_mutex);
+       atomic_inc(&root->fs_info->open_ioctl_trans);
 
        ret = -ENOMEM;
-       trans = btrfs_start_ioctl_transaction(root, 0);
+       trans = btrfs_start_ioctl_transaction(root);
        if (IS_ERR(trans))
                goto out_drop;
 
@@ -2502,9 +2500,7 @@ static long btrfs_ioctl_trans_start(struct file *file)
        return 0;
 
 out_drop:
-       mutex_lock(&root->fs_info->trans_mutex);
-       root->fs_info->open_ioctl_trans--;
-       mutex_unlock(&root->fs_info->trans_mutex);
+       atomic_dec(&root->fs_info->open_ioctl_trans);
        mnt_drop_write(file->f_path.mnt);
 out:
        return ret;
@@ -2738,9 +2734,7 @@ long btrfs_ioctl_trans_end(struct file *file)
 
        btrfs_end_transaction(trans, root);
 
-       mutex_lock(&root->fs_info->trans_mutex);
-       root->fs_info->open_ioctl_trans--;
-       mutex_unlock(&root->fs_info->trans_mutex);
+       atomic_dec(&root->fs_info->open_ioctl_trans);
 
        mnt_drop_write(file->f_path.mnt);
        return 0;
index ca38eca..b1ef27c 100644 (file)
@@ -677,6 +677,8 @@ struct backref_node *build_backref_tree(struct reloc_control *rc,
                err = -ENOMEM;
                goto out;
        }
+       path1->reada = 1;
+       path2->reada = 2;
 
        node = alloc_backref_node(cache);
        if (!node) {
@@ -1999,6 +2001,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
+       path->reada = 1;
 
        reloc_root = root->reloc_root;
        root_item = &reloc_root->root_item;
@@ -2139,10 +2142,10 @@ int prepare_to_merge(struct reloc_control *rc, int err)
        u64 num_bytes = 0;
        int ret;
 
-       mutex_lock(&root->fs_info->trans_mutex);
+       spin_lock(&root->fs_info->trans_lock);
        rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2;
        rc->merging_rsv_size += rc->nodes_relocated * 2;
-       mutex_unlock(&root->fs_info->trans_mutex);
+       spin_unlock(&root->fs_info->trans_lock);
 again:
        if (!err) {
                num_bytes = rc->merging_rsv_size;
@@ -2152,7 +2155,7 @@ again:
                        err = ret;
        }
 
-       trans = btrfs_join_transaction(rc->extent_root, 1);
+       trans = btrfs_join_transaction(rc->extent_root);
        if (IS_ERR(trans)) {
                if (!err)
                        btrfs_block_rsv_release(rc->extent_root,
@@ -2211,9 +2214,9 @@ int merge_reloc_roots(struct reloc_control *rc)
        int ret;
 again:
        root = rc->extent_root;
-       mutex_lock(&root->fs_info->trans_mutex);
+       spin_lock(&root->fs_info->trans_lock);
        list_splice_init(&rc->reloc_roots, &reloc_roots);
-       mutex_unlock(&root->fs_info->trans_mutex);
+       spin_unlock(&root->fs_info->trans_lock);
 
        while (!list_empty(&reloc_roots)) {
                found = 1;
@@ -3236,7 +3239,7 @@ truncate:
                goto out;
        }
 
-       trans = btrfs_join_transaction(root, 0);
+       trans = btrfs_join_transaction(root);
        if (IS_ERR(trans)) {
                btrfs_free_path(path);
                ret = PTR_ERR(trans);
@@ -3300,6 +3303,7 @@ static int find_data_references(struct reloc_control *rc,
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
+       path->reada = 1;
 
        root = read_fs_root(rc->extent_root->fs_info, ref_root);
        if (IS_ERR(root)) {
@@ -3586,17 +3590,17 @@ next:
 static void set_reloc_control(struct reloc_control *rc)
 {
        struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
-       mutex_lock(&fs_info->trans_mutex);
+       spin_lock(&fs_info->trans_lock);
        fs_info->reloc_ctl = rc;
-       mutex_unlock(&fs_info->trans_mutex);
+       spin_unlock(&fs_info->trans_lock);
 }
 
 static void unset_reloc_control(struct reloc_control *rc)
 {
        struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
-       mutex_lock(&fs_info->trans_mutex);
+       spin_lock(&fs_info->trans_lock);
        fs_info->reloc_ctl = NULL;
-       mutex_unlock(&fs_info->trans_mutex);
+       spin_unlock(&fs_info->trans_lock);
 }
 
 static int check_extent_flags(u64 flags)
@@ -3645,7 +3649,7 @@ int prepare_to_relocate(struct reloc_control *rc)
        rc->create_reloc_tree = 1;
        set_reloc_control(rc);
 
-       trans = btrfs_join_transaction(rc->extent_root, 1);
+       trans = btrfs_join_transaction(rc->extent_root);
        BUG_ON(IS_ERR(trans));
        btrfs_commit_transaction(trans, rc->extent_root);
        return 0;
@@ -3668,6 +3672,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
+       path->reada = 1;
 
        ret = prepare_to_relocate(rc);
        if (ret) {
@@ -3834,7 +3839,7 @@ restart:
        btrfs_block_rsv_release(rc->extent_root, rc->block_rsv, (u64)-1);
 
        /* get rid of pinned extents */
-       trans = btrfs_join_transaction(rc->extent_root, 1);
+       trans = btrfs_join_transaction(rc->extent_root);
        if (IS_ERR(trans))
                err = PTR_ERR(trans);
        else
@@ -4093,6 +4098,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
+       path->reada = -1;
 
        key.objectid = BTRFS_TREE_RELOC_OBJECTID;
        key.type = BTRFS_ROOT_ITEM_KEY;
@@ -4159,7 +4165,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
 
        set_reloc_control(rc);
 
-       trans = btrfs_join_transaction(rc->extent_root, 1);
+       trans = btrfs_join_transaction(rc->extent_root);
        if (IS_ERR(trans)) {
                unset_reloc_control(rc);
                err = PTR_ERR(trans);
@@ -4193,7 +4199,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
 
        unset_reloc_control(rc);
 
-       trans = btrfs_join_transaction(rc->extent_root, 1);
+       trans = btrfs_join_transaction(rc->extent_root);
        if (IS_ERR(trans))
                err = PTR_ERR(trans);
        else
index 6dfed0c..df50fd1 100644 (file)
@@ -117,33 +117,37 @@ static void scrub_free_csums(struct scrub_dev *sdev)
        }
 }
 
+static void scrub_free_bio(struct bio *bio)
+{
+       int i;
+       struct page *last_page = NULL;
+
+       if (!bio)
+               return;
+
+       for (i = 0; i < bio->bi_vcnt; ++i) {
+               if (bio->bi_io_vec[i].bv_page == last_page)
+                       continue;
+               last_page = bio->bi_io_vec[i].bv_page;
+               __free_page(last_page);
+       }
+       bio_put(bio);
+}
+
 static noinline_for_stack void scrub_free_dev(struct scrub_dev *sdev)
 {
        int i;
-       int j;
-       struct page *last_page;
 
        if (!sdev)
                return;
 
        for (i = 0; i < SCRUB_BIOS_PER_DEV; ++i) {
                struct scrub_bio *sbio = sdev->bios[i];
-               struct bio *bio;
 
                if (!sbio)
                        break;
 
-               bio = sbio->bio;
-               if (bio) {
-                       last_page = NULL;
-                       for (j = 0; j < bio->bi_vcnt; ++j) {
-                               if (bio->bi_io_vec[j].bv_page == last_page)
-                                       continue;
-                               last_page = bio->bi_io_vec[j].bv_page;
-                               __free_page(last_page);
-                       }
-                       bio_put(bio);
-               }
+               scrub_free_bio(sbio->bio);
                kfree(sbio);
        }
 
@@ -156,8 +160,6 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev)
 {
        struct scrub_dev *sdev;
        int             i;
-       int             j;
-       int             ret;
        struct btrfs_fs_info *fs_info = dev->dev_root->fs_info;
 
        sdev = kzalloc(sizeof(*sdev), GFP_NOFS);
@@ -165,7 +167,6 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev)
                goto nomem;
        sdev->dev = dev;
        for (i = 0; i < SCRUB_BIOS_PER_DEV; ++i) {
-               struct bio *bio;
                struct scrub_bio *sbio;
 
                sbio = kzalloc(sizeof(*sbio), GFP_NOFS);
@@ -173,32 +174,10 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev)
                        goto nomem;
                sdev->bios[i] = sbio;
 
-               bio = bio_kmalloc(GFP_NOFS, SCRUB_PAGES_PER_BIO);
-               if (!bio)
-                       goto nomem;
-
                sbio->index = i;
                sbio->sdev = sdev;
-               sbio->bio = bio;
                sbio->count = 0;
                sbio->work.func = scrub_checksum;
-               bio->bi_private = sdev->bios[i];
-               bio->bi_end_io = scrub_bio_end_io;
-               bio->bi_sector = 0;
-               bio->bi_bdev = dev->bdev;
-               bio->bi_size = 0;
-
-               for (j = 0; j < SCRUB_PAGES_PER_BIO; ++j) {
-                       struct page *page;
-                       page = alloc_page(GFP_NOFS);
-                       if (!page)
-                               goto nomem;
-
-                       ret = bio_add_page(bio, page, PAGE_SIZE, 0);
-                       if (!ret)
-                               goto nomem;
-               }
-               WARN_ON(bio->bi_vcnt != SCRUB_PAGES_PER_BIO);
 
                if (i != SCRUB_BIOS_PER_DEV-1)
                        sdev->bios[i]->next_free = i + 1;
@@ -369,9 +348,6 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector,
        int ret;
        DECLARE_COMPLETION_ONSTACK(complete);
 
-       /* we are going to wait on this IO */
-       rw |= REQ_SYNC;
-
        bio = bio_alloc(GFP_NOFS, 1);
        bio->bi_bdev = bdev;
        bio->bi_sector = sector;
@@ -380,6 +356,7 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector,
        bio->bi_private = &complete;
        submit_bio(rw, bio);
 
+       /* this will also unplug the queue */
        wait_for_completion(&complete);
 
        ret = !test_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -394,6 +371,7 @@ static void scrub_bio_end_io(struct bio *bio, int err)
        struct btrfs_fs_info *fs_info = sdev->dev->dev_root->fs_info;
 
        sbio->err = err;
+       sbio->bio = bio;
 
        btrfs_queue_worker(&fs_info->scrub_workers, &sbio->work);
 }
@@ -453,6 +431,8 @@ static void scrub_checksum(struct btrfs_work *work)
        }
 
 out:
+       scrub_free_bio(sbio->bio);
+       sbio->bio = NULL;
        spin_lock(&sdev->list_lock);
        sbio->next_free = sdev->first_free;
        sdev->first_free = sbio->index;
@@ -583,25 +563,50 @@ static int scrub_checksum_super(struct scrub_bio *sbio, void *buffer)
 static int scrub_submit(struct scrub_dev *sdev)
 {
        struct scrub_bio *sbio;
+       struct bio *bio;
+       int i;
 
        if (sdev->curr == -1)
                return 0;
 
        sbio = sdev->bios[sdev->curr];
 
-       sbio->bio->bi_sector = sbio->physical >> 9;
-       sbio->bio->bi_size = sbio->count * PAGE_SIZE;
-       sbio->bio->bi_next = NULL;
-       sbio->bio->bi_flags |= 1 << BIO_UPTODATE;
-       sbio->bio->bi_comp_cpu = -1;
-       sbio->bio->bi_bdev = sdev->dev->bdev;
+       bio = bio_alloc(GFP_NOFS, sbio->count);
+       if (!bio)
+               goto nomem;
+
+       bio->bi_private = sbio;
+       bio->bi_end_io = scrub_bio_end_io;
+       bio->bi_bdev = sdev->dev->bdev;
+       bio->bi_sector = sbio->physical >> 9;
+
+       for (i = 0; i < sbio->count; ++i) {
+               struct page *page;
+               int ret;
+
+               page = alloc_page(GFP_NOFS);
+               if (!page)
+                       goto nomem;
+
+               ret = bio_add_page(bio, page, PAGE_SIZE, 0);
+               if (!ret) {
+                       __free_page(page);
+                       goto nomem;
+               }
+       }
+
        sbio->err = 0;
        sdev->curr = -1;
        atomic_inc(&sdev->in_flight);
 
-       submit_bio(0, sbio->bio);
+       submit_bio(READ, bio);
 
        return 0;
+
+nomem:
+       scrub_free_bio(bio);
+
+       return -ENOMEM;
 }
 
 static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len,
@@ -633,7 +638,11 @@ again:
                sbio->logical = logical;
        } else if (sbio->physical + sbio->count * PAGE_SIZE != physical ||
                   sbio->logical + sbio->count * PAGE_SIZE != logical) {
-               scrub_submit(sdev);
+               int ret;
+
+               ret = scrub_submit(sdev);
+               if (ret)
+                       return ret;
                goto again;
        }
        sbio->spag[sbio->count].flags = flags;
@@ -645,8 +654,13 @@ again:
                memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size);
        }
        ++sbio->count;
-       if (sbio->count == SCRUB_PAGES_PER_BIO || force)
-               scrub_submit(sdev);
+       if (sbio->count == SCRUB_PAGES_PER_BIO || force) {
+               int ret;
+
+               ret = scrub_submit(sdev);
+               if (ret)
+                       return ret;
+       }
 
        return 0;
 }
@@ -727,6 +741,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev,
        struct btrfs_root *root = fs_info->extent_root;
        struct btrfs_root *csum_root = fs_info->csum_root;
        struct btrfs_extent_item *extent;
+       struct blk_plug plug;
        u64 flags;
        int ret;
        int slot;
@@ -831,6 +846,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev,
         * the scrub. This might currently (crc32) end up to be about 1MB
         */
        start_stripe = 0;
+       blk_start_plug(&plug);
 again:
        logical = base + offset + start_stripe * increment;
        for (i = start_stripe; i < nstripes; ++i) {
@@ -972,6 +988,7 @@ next:
        scrub_submit(sdev);
 
 out:
+       blk_finish_plug(&plug);
        btrfs_free_path(path);
        return ret < 0 ? ret : 0;
 }
@@ -1166,7 +1183,7 @@ int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end,
        int ret;
        struct btrfs_device *dev;
 
-       if (root->fs_info->closing)
+       if (btrfs_fs_closing(root->fs_info))
                return -EINVAL;
 
        /*
index 9b2e7e5..0bb4ebb 100644 (file)
@@ -161,7 +161,8 @@ enum {
        Opt_compress_type, Opt_compress_force, Opt_compress_force_type,
        Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,
        Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed,
-       Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_err,
+       Opt_enospc_debug, Opt_subvolrootid, Opt_defrag,
+       Opt_inode_cache, Opt_err,
 };
 
 static match_table_t tokens = {
@@ -193,6 +194,7 @@ static match_table_t tokens = {
        {Opt_enospc_debug, "enospc_debug"},
        {Opt_subvolrootid, "subvolrootid=%d"},
        {Opt_defrag, "autodefrag"},
+       {Opt_inode_cache, "inode_cache"},
        {Opt_err, NULL},
 };
 
@@ -361,6 +363,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        printk(KERN_INFO "btrfs: enabling disk space caching\n");
                        btrfs_set_opt(info->mount_opt, SPACE_CACHE);
                        break;
+               case Opt_inode_cache:
+                       printk(KERN_INFO "btrfs: enabling inode map caching\n");
+                       btrfs_set_opt(info->mount_opt, INODE_MAP_CACHE);
+                       break;
                case Opt_clear_cache:
                        printk(KERN_INFO "btrfs: force clearing of disk cache\n");
                        btrfs_set_opt(info->mount_opt, CLEAR_CACHE);
@@ -819,7 +825,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        } else {
                char b[BDEVNAME_SIZE];
 
-               s->s_flags = flags;
+               s->s_flags = flags | MS_NOSEC;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
                error = btrfs_fill_super(s, fs_devices, data,
                                         flags & MS_SILENT ? 1 : 0);
index dc80f71..dd71966 100644 (file)
@@ -35,6 +35,7 @@ static noinline void put_transaction(struct btrfs_transaction *transaction)
 {
        WARN_ON(atomic_read(&transaction->use_count) == 0);
        if (atomic_dec_and_test(&transaction->use_count)) {
+               BUG_ON(!list_empty(&transaction->list));
                memset(transaction, 0, sizeof(*transaction));
                kmem_cache_free(btrfs_transaction_cachep, transaction);
        }
@@ -49,46 +50,72 @@ static noinline void switch_commit_root(struct btrfs_root *root)
 /*
  * either allocate a new transaction or hop into the existing one
  */
-static noinline int join_transaction(struct btrfs_root *root)
+static noinline int join_transaction(struct btrfs_root *root, int nofail)
 {
        struct btrfs_transaction *cur_trans;
+
+       spin_lock(&root->fs_info->trans_lock);
+       if (root->fs_info->trans_no_join) {
+               if (!nofail) {
+                       spin_unlock(&root->fs_info->trans_lock);
+                       return -EBUSY;
+               }
+       }
+
        cur_trans = root->fs_info->running_transaction;
-       if (!cur_trans) {
-               cur_trans = kmem_cache_alloc(btrfs_transaction_cachep,
-                                            GFP_NOFS);
-               if (!cur_trans)
-                       return -ENOMEM;
-               root->fs_info->generation++;
-               atomic_set(&cur_trans->num_writers, 1);
-               cur_trans->num_joined = 0;
-               cur_trans->transid = root->fs_info->generation;
-               init_waitqueue_head(&cur_trans->writer_wait);
-               init_waitqueue_head(&cur_trans->commit_wait);
-               cur_trans->in_commit = 0;
-               cur_trans->blocked = 0;
-               atomic_set(&cur_trans->use_count, 1);
-               cur_trans->commit_done = 0;
-               cur_trans->start_time = get_seconds();
-
-               cur_trans->delayed_refs.root = RB_ROOT;
-               cur_trans->delayed_refs.num_entries = 0;
-               cur_trans->delayed_refs.num_heads_ready = 0;
-               cur_trans->delayed_refs.num_heads = 0;
-               cur_trans->delayed_refs.flushing = 0;
-               cur_trans->delayed_refs.run_delayed_start = 0;
-               spin_lock_init(&cur_trans->delayed_refs.lock);
-
-               INIT_LIST_HEAD(&cur_trans->pending_snapshots);
-               list_add_tail(&cur_trans->list, &root->fs_info->trans_list);
-               extent_io_tree_init(&cur_trans->dirty_pages,
-                                    root->fs_info->btree_inode->i_mapping);
-               spin_lock(&root->fs_info->new_trans_lock);
-               root->fs_info->running_transaction = cur_trans;
-               spin_unlock(&root->fs_info->new_trans_lock);
-       } else {
+       if (cur_trans) {
+               atomic_inc(&cur_trans->use_count);
                atomic_inc(&cur_trans->num_writers);
                cur_trans->num_joined++;
+               spin_unlock(&root->fs_info->trans_lock);
+               return 0;
        }
+       spin_unlock(&root->fs_info->trans_lock);
+
+       cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS);
+       if (!cur_trans)
+               return -ENOMEM;
+       spin_lock(&root->fs_info->trans_lock);
+       if (root->fs_info->running_transaction) {
+               kmem_cache_free(btrfs_transaction_cachep, cur_trans);
+               cur_trans = root->fs_info->running_transaction;
+               atomic_inc(&cur_trans->use_count);
+               atomic_inc(&cur_trans->num_writers);
+               cur_trans->num_joined++;
+               spin_unlock(&root->fs_info->trans_lock);
+               return 0;
+       }
+       atomic_set(&cur_trans->num_writers, 1);
+       cur_trans->num_joined = 0;
+       init_waitqueue_head(&cur_trans->writer_wait);
+       init_waitqueue_head(&cur_trans->commit_wait);
+       cur_trans->in_commit = 0;
+       cur_trans->blocked = 0;
+       /*
+        * One for this trans handle, one so it will live on until we
+        * commit the transaction.
+        */
+       atomic_set(&cur_trans->use_count, 2);
+       cur_trans->commit_done = 0;
+       cur_trans->start_time = get_seconds();
+
+       cur_trans->delayed_refs.root = RB_ROOT;
+       cur_trans->delayed_refs.num_entries = 0;
+       cur_trans->delayed_refs.num_heads_ready = 0;
+       cur_trans->delayed_refs.num_heads = 0;
+       cur_trans->delayed_refs.flushing = 0;
+       cur_trans->delayed_refs.run_delayed_start = 0;
+       spin_lock_init(&cur_trans->commit_lock);
+       spin_lock_init(&cur_trans->delayed_refs.lock);
+
+       INIT_LIST_HEAD(&cur_trans->pending_snapshots);
+       list_add_tail(&cur_trans->list, &root->fs_info->trans_list);
+       extent_io_tree_init(&cur_trans->dirty_pages,
+                            root->fs_info->btree_inode->i_mapping);
+       root->fs_info->generation++;
+       cur_trans->transid = root->fs_info->generation;
+       root->fs_info->running_transaction = cur_trans;
+       spin_unlock(&root->fs_info->trans_lock);
 
        return 0;
 }
@@ -99,39 +126,28 @@ static noinline int join_transaction(struct btrfs_root *root)
  * to make sure the old root from before we joined the transaction is deleted
  * when the transaction commits
  */
-static noinline int record_root_in_trans(struct btrfs_trans_handle *trans,
-                                        struct btrfs_root *root)
+int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
+                              struct btrfs_root *root)
 {
        if (root->ref_cows && root->last_trans < trans->transid) {
                WARN_ON(root == root->fs_info->extent_root);
                WARN_ON(root->commit_root != root->node);
 
+               spin_lock(&root->fs_info->fs_roots_radix_lock);
+               if (root->last_trans == trans->transid) {
+                       spin_unlock(&root->fs_info->fs_roots_radix_lock);
+                       return 0;
+               }
+               root->last_trans = trans->transid;
                radix_tree_tag_set(&root->fs_info->fs_roots_radix,
                           (unsigned long)root->root_key.objectid,
                           BTRFS_ROOT_TRANS_TAG);
-               root->last_trans = trans->transid;
+               spin_unlock(&root->fs_info->fs_roots_radix_lock);
                btrfs_init_reloc_root(trans, root);
        }
        return 0;
 }
 
-int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
-                              struct btrfs_root *root)
-{
-       if (!root->ref_cows)
-               return 0;
-
-       mutex_lock(&root->fs_info->trans_mutex);
-       if (root->last_trans == trans->transid) {
-               mutex_unlock(&root->fs_info->trans_mutex);
-               return 0;
-       }
-
-       record_root_in_trans(trans, root);
-       mutex_unlock(&root->fs_info->trans_mutex);
-       return 0;
-}
-
 /* wait for commit against the current transaction to become unblocked
  * when this is done, it is safe to start a new transaction, but the current
  * transaction might not be fully on disk.
@@ -140,21 +156,23 @@ static void wait_current_trans(struct btrfs_root *root)
 {
        struct btrfs_transaction *cur_trans;
 
+       spin_lock(&root->fs_info->trans_lock);
        cur_trans = root->fs_info->running_transaction;
        if (cur_trans && cur_trans->blocked) {
                DEFINE_WAIT(wait);
                atomic_inc(&cur_trans->use_count);
+               spin_unlock(&root->fs_info->trans_lock);
                while (1) {
                        prepare_to_wait(&root->fs_info->transaction_wait, &wait,
                                        TASK_UNINTERRUPTIBLE);
                        if (!cur_trans->blocked)
                                break;
-                       mutex_unlock(&root->fs_info->trans_mutex);
                        schedule();
-                       mutex_lock(&root->fs_info->trans_mutex);
                }
                finish_wait(&root->fs_info->transaction_wait, &wait);
                put_transaction(cur_trans);
+       } else {
+               spin_unlock(&root->fs_info->trans_lock);
        }
 }
 
@@ -167,10 +185,16 @@ enum btrfs_trans_type {
 
 static int may_wait_transaction(struct btrfs_root *root, int type)
 {
-       if (!root->fs_info->log_root_recovering &&
-           ((type == TRANS_START && !root->fs_info->open_ioctl_trans) ||
-            type == TRANS_USERSPACE))
+       if (root->fs_info->log_root_recovering)
+               return 0;
+
+       if (type == TRANS_USERSPACE)
+               return 1;
+
+       if (type == TRANS_START &&
+           !atomic_read(&root->fs_info->open_ioctl_trans))
                return 1;
+
        return 0;
 }
 
@@ -184,36 +208,44 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
 
        if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
                return ERR_PTR(-EROFS);
+
+       if (current->journal_info) {
+               WARN_ON(type != TRANS_JOIN && type != TRANS_JOIN_NOLOCK);
+               h = current->journal_info;
+               h->use_count++;
+               h->orig_rsv = h->block_rsv;
+               h->block_rsv = NULL;
+               goto got_it;
+       }
 again:
        h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
        if (!h)
                return ERR_PTR(-ENOMEM);
 
-       if (type != TRANS_JOIN_NOLOCK)
-               mutex_lock(&root->fs_info->trans_mutex);
        if (may_wait_transaction(root, type))
                wait_current_trans(root);
 
-       ret = join_transaction(root);
+       do {
+               ret = join_transaction(root, type == TRANS_JOIN_NOLOCK);
+               if (ret == -EBUSY)
+                       wait_current_trans(root);
+       } while (ret == -EBUSY);
+
        if (ret < 0) {
                kmem_cache_free(btrfs_trans_handle_cachep, h);
-               if (type != TRANS_JOIN_NOLOCK)
-                       mutex_unlock(&root->fs_info->trans_mutex);
                return ERR_PTR(ret);
        }
 
        cur_trans = root->fs_info->running_transaction;
-       atomic_inc(&cur_trans->use_count);
-       if (type != TRANS_JOIN_NOLOCK)
-               mutex_unlock(&root->fs_info->trans_mutex);
 
        h->transid = cur_trans->transid;
        h->transaction = cur_trans;
        h->blocks_used = 0;
-       h->block_group = 0;
        h->bytes_reserved = 0;
        h->delayed_ref_updates = 0;
+       h->use_count = 1;
        h->block_rsv = NULL;
+       h->orig_rsv = NULL;
 
        smp_mb();
        if (cur_trans->blocked && may_wait_transaction(root, type)) {
@@ -241,11 +273,8 @@ again:
                }
        }
 
-       if (type != TRANS_JOIN_NOLOCK)
-               mutex_lock(&root->fs_info->trans_mutex);
-       record_root_in_trans(h, root);
-       if (type != TRANS_JOIN_NOLOCK)
-               mutex_unlock(&root->fs_info->trans_mutex);
+got_it:
+       btrfs_record_root_in_trans(h, root);
 
        if (!current->journal_info && type != TRANS_USERSPACE)
                current->journal_info = h;
@@ -257,22 +286,19 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
 {
        return start_transaction(root, num_items, TRANS_START);
 }
-struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root,
-                                                  int num_blocks)
+struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root)
 {
        return start_transaction(root, 0, TRANS_JOIN);
 }
 
-struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root,
-                                                         int num_blocks)
+struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root)
 {
        return start_transaction(root, 0, TRANS_JOIN_NOLOCK);
 }
 
-struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r,
-                                                        int num_blocks)
+struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root)
 {
-       return start_transaction(r, 0, TRANS_USERSPACE);
+       return start_transaction(root, 0, TRANS_USERSPACE);
 }
 
 /* wait for a transaction commit to be fully complete */
@@ -280,17 +306,13 @@ static noinline int wait_for_commit(struct btrfs_root *root,
                                    struct btrfs_transaction *commit)
 {
        DEFINE_WAIT(wait);
-       mutex_lock(&root->fs_info->trans_mutex);
        while (!commit->commit_done) {
                prepare_to_wait(&commit->commit_wait, &wait,
                                TASK_UNINTERRUPTIBLE);
                if (commit->commit_done)
                        break;
-               mutex_unlock(&root->fs_info->trans_mutex);
                schedule();
-               mutex_lock(&root->fs_info->trans_mutex);
        }
-       mutex_unlock(&root->fs_info->trans_mutex);
        finish_wait(&commit->commit_wait, &wait);
        return 0;
 }
@@ -300,59 +322,56 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid)
        struct btrfs_transaction *cur_trans = NULL, *t;
        int ret;
 
-       mutex_lock(&root->fs_info->trans_mutex);
-
        ret = 0;
        if (transid) {
                if (transid <= root->fs_info->last_trans_committed)
-                       goto out_unlock;
+                       goto out;
 
                /* find specified transaction */
+               spin_lock(&root->fs_info->trans_lock);
                list_for_each_entry(t, &root->fs_info->trans_list, list) {
                        if (t->transid == transid) {
                                cur_trans = t;
+                               atomic_inc(&cur_trans->use_count);
                                break;
                        }
                        if (t->transid > transid)
                                break;
                }
+               spin_unlock(&root->fs_info->trans_lock);
                ret = -EINVAL;
                if (!cur_trans)
-                       goto out_unlock;  /* bad transid */
+                       goto out;  /* bad transid */
        } else {
                /* find newest transaction that is committing | committed */
+               spin_lock(&root->fs_info->trans_lock);
                list_for_each_entry_reverse(t, &root->fs_info->trans_list,
                                            list) {
                        if (t->in_commit) {
                                if (t->commit_done)
-                                       goto out_unlock;
+                                       goto out;
                                cur_trans = t;
+                               atomic_inc(&cur_trans->use_count);
                                break;
                        }
                }
+               spin_unlock(&root->fs_info->trans_lock);
                if (!cur_trans)
-                       goto out_unlock;  /* nothing committing|committed */
+                       goto out;  /* nothing committing|committed */
        }
 
-       atomic_inc(&cur_trans->use_count);
-       mutex_unlock(&root->fs_info->trans_mutex);
-
        wait_for_commit(root, cur_trans);
 
-       mutex_lock(&root->fs_info->trans_mutex);
        put_transaction(cur_trans);
        ret = 0;
-out_unlock:
-       mutex_unlock(&root->fs_info->trans_mutex);
+out:
        return ret;
 }
 
 void btrfs_throttle(struct btrfs_root *root)
 {
-       mutex_lock(&root->fs_info->trans_mutex);
-       if (!root->fs_info->open_ioctl_trans)
+       if (!atomic_read(&root->fs_info->open_ioctl_trans))
                wait_current_trans(root);
-       mutex_unlock(&root->fs_info->trans_mutex);
 }
 
 static int should_end_transaction(struct btrfs_trans_handle *trans,
@@ -370,6 +389,7 @@ int btrfs_should_end_transaction(struct btrfs_trans_handle *trans,
        struct btrfs_transaction *cur_trans = trans->transaction;
        int updates;
 
+       smp_mb();
        if (cur_trans->blocked || cur_trans->delayed_refs.flushing)
                return 1;
 
@@ -388,6 +408,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
        struct btrfs_fs_info *info = root->fs_info;
        int count = 0;
 
+       if (--trans->use_count) {
+               trans->block_rsv = trans->orig_rsv;
+               return 0;
+       }
+
        while (count < 4) {
                unsigned long cur = trans->delayed_ref_updates;
                trans->delayed_ref_updates = 0;
@@ -410,9 +435,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 
        btrfs_trans_release_metadata(trans, root);
 
-       if (lock && !root->fs_info->open_ioctl_trans &&
-           should_end_transaction(trans, root))
+       if (lock && !atomic_read(&root->fs_info->open_ioctl_trans) &&
+           should_end_transaction(trans, root)) {
                trans->transaction->blocked = 1;
+               smp_wmb();
+       }
 
        if (lock && cur_trans->blocked && !cur_trans->in_commit) {
                if (throttle)
@@ -703,9 +730,9 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
  */
 int btrfs_add_dead_root(struct btrfs_root *root)
 {
-       mutex_lock(&root->fs_info->trans_mutex);
+       spin_lock(&root->fs_info->trans_lock);
        list_add(&root->root_list, &root->fs_info->dead_roots);
-       mutex_unlock(&root->fs_info->trans_mutex);
+       spin_unlock(&root->fs_info->trans_lock);
        return 0;
 }
 
@@ -721,6 +748,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,
        int ret;
        int err = 0;
 
+       spin_lock(&fs_info->fs_roots_radix_lock);
        while (1) {
                ret = radix_tree_gang_lookup_tag(&fs_info->fs_roots_radix,
                                                 (void **)gang, 0,
@@ -733,6 +761,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,
                        radix_tree_tag_clear(&fs_info->fs_roots_radix,
                                        (unsigned long)root->root_key.objectid,
                                        BTRFS_ROOT_TRANS_TAG);
+                       spin_unlock(&fs_info->fs_roots_radix_lock);
 
                        btrfs_free_log(trans, root);
                        btrfs_update_reloc_root(trans, root);
@@ -753,10 +782,12 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,
                        err = btrfs_update_root(trans, fs_info->tree_root,
                                                &root->root_key,
                                                &root->root_item);
+                       spin_lock(&fs_info->fs_roots_radix_lock);
                        if (err)
                                break;
                }
        }
+       spin_unlock(&fs_info->fs_roots_radix_lock);
        return err;
 }
 
@@ -786,7 +817,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
                btrfs_btree_balance_dirty(info->tree_root, nr);
                cond_resched();
 
-               if (root->fs_info->closing || ret != -EAGAIN)
+               if (btrfs_fs_closing(root->fs_info) || ret != -EAGAIN)
                        break;
        }
        root->defrag_running = 0;
@@ -851,7 +882,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        parent = dget_parent(dentry);
        parent_inode = parent->d_inode;
        parent_root = BTRFS_I(parent_inode)->root;
-       record_root_in_trans(trans, parent_root);
+       btrfs_record_root_in_trans(trans, parent_root);
 
        /*
         * insert the directory item
@@ -869,7 +900,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        ret = btrfs_update_inode(trans, parent_root, parent_inode);
        BUG_ON(ret);
 
-       record_root_in_trans(trans, root);
+       btrfs_record_root_in_trans(trans, root);
        btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
        memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
        btrfs_check_and_init_root_item(new_root_item);
@@ -967,20 +998,20 @@ static void update_super_roots(struct btrfs_root *root)
 int btrfs_transaction_in_commit(struct btrfs_fs_info *info)
 {
        int ret = 0;
-       spin_lock(&info->new_trans_lock);
+       spin_lock(&info->trans_lock);
        if (info->running_transaction)
                ret = info->running_transaction->in_commit;
-       spin_unlock(&info->new_trans_lock);
+       spin_unlock(&info->trans_lock);
        return ret;
 }
 
 int btrfs_transaction_blocked(struct btrfs_fs_info *info)
 {
        int ret = 0;
-       spin_lock(&info->new_trans_lock);
+       spin_lock(&info->trans_lock);
        if (info->running_transaction)
                ret = info->running_transaction->blocked;
-       spin_unlock(&info->new_trans_lock);
+       spin_unlock(&info->trans_lock);
        return ret;
 }
 
@@ -1004,9 +1035,7 @@ static void wait_current_trans_commit_start(struct btrfs_root *root,
                                    &wait);
                        break;
                }
-               mutex_unlock(&root->fs_info->trans_mutex);
                schedule();
-               mutex_lock(&root->fs_info->trans_mutex);
                finish_wait(&root->fs_info->transaction_blocked_wait, &wait);
        }
 }
@@ -1032,9 +1061,7 @@ static void wait_current_trans_commit_start_and_unblock(struct btrfs_root *root,
                                    &wait);
                        break;
                }
-               mutex_unlock(&root->fs_info->trans_mutex);
                schedule();
-               mutex_lock(&root->fs_info->trans_mutex);
                finish_wait(&root->fs_info->transaction_wait,
                            &wait);
        }
@@ -1072,7 +1099,7 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
 
        INIT_DELAYED_WORK(&ac->work, do_async_commit);
        ac->root = root;
-       ac->newtrans = btrfs_join_transaction(root, 0);
+       ac->newtrans = btrfs_join_transaction(root);
        if (IS_ERR(ac->newtrans)) {
                int err = PTR_ERR(ac->newtrans);
                kfree(ac);
@@ -1080,22 +1107,18 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
        }
 
        /* take transaction reference */
-       mutex_lock(&root->fs_info->trans_mutex);
        cur_trans = trans->transaction;
        atomic_inc(&cur_trans->use_count);
-       mutex_unlock(&root->fs_info->trans_mutex);
 
        btrfs_end_transaction(trans, root);
        schedule_delayed_work(&ac->work, 0);
 
        /* wait for transaction to start and unblock */
-       mutex_lock(&root->fs_info->trans_mutex);
        if (wait_for_unblock)
                wait_current_trans_commit_start_and_unblock(root, cur_trans);
        else
                wait_current_trans_commit_start(root, cur_trans);
        put_transaction(cur_trans);
-       mutex_unlock(&root->fs_info->trans_mutex);
 
        return 0;
 }
@@ -1139,38 +1162,41 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        ret = btrfs_run_delayed_refs(trans, root, 0);
        BUG_ON(ret);
 
-       mutex_lock(&root->fs_info->trans_mutex);
+       spin_lock(&cur_trans->commit_lock);
        if (cur_trans->in_commit) {
+               spin_unlock(&cur_trans->commit_lock);
                atomic_inc(&cur_trans->use_count);
-               mutex_unlock(&root->fs_info->trans_mutex);
                btrfs_end_transaction(trans, root);
 
                ret = wait_for_commit(root, cur_trans);
                BUG_ON(ret);
 
-               mutex_lock(&root->fs_info->trans_mutex);
                put_transaction(cur_trans);
-               mutex_unlock(&root->fs_info->trans_mutex);
 
                return 0;
        }
 
        trans->transaction->in_commit = 1;
        trans->transaction->blocked = 1;
+       spin_unlock(&cur_trans->commit_lock);
        wake_up(&root->fs_info->transaction_blocked_wait);
 
+       spin_lock(&root->fs_info->trans_lock);
        if (cur_trans->list.prev != &root->fs_info->trans_list) {
                prev_trans = list_entry(cur_trans->list.prev,
                                        struct btrfs_transaction, list);
                if (!prev_trans->commit_done) {
                        atomic_inc(&prev_trans->use_count);
-                       mutex_unlock(&root->fs_info->trans_mutex);
+                       spin_unlock(&root->fs_info->trans_lock);
 
                        wait_for_commit(root, prev_trans);
 
-                       mutex_lock(&root->fs_info->trans_mutex);
                        put_transaction(prev_trans);
+               } else {
+                       spin_unlock(&root->fs_info->trans_lock);
                }
+       } else {
+               spin_unlock(&root->fs_info->trans_lock);
        }
 
        if (now < cur_trans->start_time || now - cur_trans->start_time < 1)
@@ -1178,12 +1204,12 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
        do {
                int snap_pending = 0;
+
                joined = cur_trans->num_joined;
                if (!list_empty(&trans->transaction->pending_snapshots))
                        snap_pending = 1;
 
                WARN_ON(cur_trans != trans->transaction);
-               mutex_unlock(&root->fs_info->trans_mutex);
 
                if (flush_on_commit || snap_pending) {
                        btrfs_start_delalloc_inodes(root, 1);
@@ -1206,14 +1232,15 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                prepare_to_wait(&cur_trans->writer_wait, &wait,
                                TASK_UNINTERRUPTIBLE);
 
-               smp_mb();
                if (atomic_read(&cur_trans->num_writers) > 1)
                        schedule_timeout(MAX_SCHEDULE_TIMEOUT);
                else if (should_grow)
                        schedule_timeout(1);
 
-               mutex_lock(&root->fs_info->trans_mutex);
                finish_wait(&cur_trans->writer_wait, &wait);
+               spin_lock(&root->fs_info->trans_lock);
+               root->fs_info->trans_no_join = 1;
+               spin_unlock(&root->fs_info->trans_lock);
        } while (atomic_read(&cur_trans->num_writers) > 1 ||
                 (should_grow && cur_trans->num_joined != joined));
 
@@ -1258,9 +1285,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        btrfs_prepare_extent_commit(trans, root);
 
        cur_trans = root->fs_info->running_transaction;
-       spin_lock(&root->fs_info->new_trans_lock);
-       root->fs_info->running_transaction = NULL;
-       spin_unlock(&root->fs_info->new_trans_lock);
 
        btrfs_set_root_node(&root->fs_info->tree_root->root_item,
                            root->fs_info->tree_root->node);
@@ -1281,10 +1305,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
               sizeof(root->fs_info->super_copy));
 
        trans->transaction->blocked = 0;
+       spin_lock(&root->fs_info->trans_lock);
+       root->fs_info->running_transaction = NULL;
+       root->fs_info->trans_no_join = 0;
+       spin_unlock(&root->fs_info->trans_lock);
 
        wake_up(&root->fs_info->transaction_wait);
 
-       mutex_unlock(&root->fs_info->trans_mutex);
        ret = btrfs_write_and_wait_transaction(trans, root);
        BUG_ON(ret);
        write_ctree_super(trans, root, 0);
@@ -1297,22 +1324,21 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
        btrfs_finish_extent_commit(trans, root);
 
-       mutex_lock(&root->fs_info->trans_mutex);
-
        cur_trans->commit_done = 1;
 
        root->fs_info->last_trans_committed = cur_trans->transid;
 
        wake_up(&cur_trans->commit_wait);
 
+       spin_lock(&root->fs_info->trans_lock);
        list_del_init(&cur_trans->list);
+       spin_unlock(&root->fs_info->trans_lock);
+
        put_transaction(cur_trans);
        put_transaction(cur_trans);
 
        trace_btrfs_transaction_commit(root);
 
-       mutex_unlock(&root->fs_info->trans_mutex);
-
        btrfs_scrub_continue(root);
 
        if (current->journal_info == trans)
@@ -1334,9 +1360,9 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root)
        LIST_HEAD(list);
        struct btrfs_fs_info *fs_info = root->fs_info;
 
-       mutex_lock(&fs_info->trans_mutex);
+       spin_lock(&fs_info->trans_lock);
        list_splice_init(&fs_info->dead_roots, &list);
-       mutex_unlock(&fs_info->trans_mutex);
+       spin_unlock(&fs_info->trans_lock);
 
        while (!list_empty(&list)) {
                root = list_entry(list.next, struct btrfs_root, root_list);
index 804c886..02564e6 100644 (file)
@@ -28,10 +28,12 @@ struct btrfs_transaction {
         * transaction can end
         */
        atomic_t num_writers;
+       atomic_t use_count;
 
        unsigned long num_joined;
+
+       spinlock_t commit_lock;
        int in_commit;
-       atomic_t use_count;
        int commit_done;
        int blocked;
        struct list_head list;
@@ -45,13 +47,14 @@ struct btrfs_transaction {
 
 struct btrfs_trans_handle {
        u64 transid;
-       u64 block_group;
        u64 bytes_reserved;
+       unsigned long use_count;
        unsigned long blocks_reserved;
        unsigned long blocks_used;
        unsigned long delayed_ref_updates;
        struct btrfs_transaction *transaction;
        struct btrfs_block_rsv *block_rsv;
+       struct btrfs_block_rsv *orig_rsv;
 };
 
 struct btrfs_pending_snapshot {
@@ -66,19 +69,6 @@ struct btrfs_pending_snapshot {
        struct list_head list;
 };
 
-static inline void btrfs_set_trans_block_group(struct btrfs_trans_handle *trans,
-                                              struct inode *inode)
-{
-       trans->block_group = BTRFS_I(inode)->block_group;
-}
-
-static inline void btrfs_update_inode_block_group(
-                                         struct btrfs_trans_handle *trans,
-                                         struct inode *inode)
-{
-       BTRFS_I(inode)->block_group = trans->block_group;
-}
-
 static inline void btrfs_set_inode_last_trans(struct btrfs_trans_handle *trans,
                                              struct inode *inode)
 {
@@ -92,12 +82,9 @@ int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans,
                                 struct btrfs_root *root);
 struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
                                                   int num_items);
-struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root,
-                                                 int num_blocks);
-struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root,
-                                                         int num_blocks);
-struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r,
-                                                        int num_blocks);
+struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root);
+struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root);
+struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root);
 int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid);
 int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
                                     struct btrfs_root *root);
index c48214e..da541df 100644 (file)
@@ -504,7 +504,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
                BUG_ON(!new_device);
                memcpy(new_device, device, sizeof(*new_device));
                new_device->name = kstrdup(device->name, GFP_NOFS);
-               BUG_ON(!new_device->name);
+               BUG_ON(device->name && !new_device->name);
                new_device->bdev = NULL;
                new_device->writeable = 0;
                new_device->in_fs_metadata = 0;
index f3107e4..5366fe4 100644 (file)
@@ -158,8 +158,6 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans,
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
-       btrfs_set_trans_block_group(trans, inode);
-
        ret = do_setxattr(trans, inode, name, value, size, flags);
        if (ret)
                goto out;
index 1cd4c3a..53ed1ad 100644 (file)
@@ -7,6 +7,7 @@ config CIFS
        select CRYPTO_MD5
        select CRYPTO_HMAC
        select CRYPTO_ARC4
+       select CRYPTO_ECB
        select CRYPTO_DES
        help
          This is the client VFS module for the Common Internet File System
@@ -148,7 +149,7 @@ config CIFS_FSCACHE
 
 config CIFS_ACL
          bool "Provide CIFS ACL support (EXPERIMENTAL)"
-         depends on EXPERIMENTAL && CIFS_XATTR
+         depends on EXPERIMENTAL && CIFS_XATTR && KEYS
          help
            Allows to fetch CIFS/NTFS ACL from the server.  The DACL blob
            is handed over to the application/caller.
index dfbd9f1..5a0ee7f 100644 (file)
@@ -184,7 +184,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
        if (cifs_pdu == NULL || server == NULL)
                return -EINVAL;
 
-       if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
+       if (!server->session_estab)
                return 0;
 
        if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
index 6d88b82..bb659eb 100644 (file)
@@ -784,7 +784,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                         struct smb_vol *vol)
 {
        char *value, *data, *end;
-       char *mountdata_copy, *options;
+       char *mountdata_copy = NULL, *options;
        unsigned int  temp_len, i, j;
        char separator[2];
        short int override_uid = -1;
@@ -1391,7 +1391,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                                "/proc/fs/cifs/LookupCacheEnabled to 0\n");
                } else if (strnicmp(data, "fsc", 3) == 0) {
 #ifndef CONFIG_CIFS_FSCACHE
-                       cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE"
+                       cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
                                  "kernel config option set");
                        goto cifs_parse_mount_err;
 #endif
@@ -1976,7 +1976,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
                warned_on_ntlm = true;
                cERROR(1, "default security mechanism requested.  The default "
                        "security mechanism will be upgraded from ntlm to "
-                       "ntlmv2 in kernel release 2.6.41");
+                       "ntlmv2 in kernel release 3.1");
        }
        ses->overrideSecFlg = volume_info->secFlg;
 
index ea5f748..97e0d52 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1093,6 +1093,7 @@ int flush_old_exec(struct linux_binprm * bprm)
 
        bprm->mm = NULL;                /* We're using it now */
 
+       set_fs(USER_DS);
        current->flags &= ~(PF_RANDOMIZE | PF_KTHREAD);
        flush_thread();
        current->personality &= ~bprm->per_clear;
@@ -1357,10 +1358,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
        if (retval)
                return retval;
 
-       /* kernel module loader fixup */
-       /* so we don't try to load run modprobe in kernel space. */
-       set_fs(USER_DS);
-
        retval = audit_bprm(bprm);
        if (retval)
                return retval;
index 7257752..7018e1d 100644 (file)
@@ -102,7 +102,7 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)
                if (attr & ATTR_SYS)
                        inode->i_flags |= S_IMMUTABLE;
                else
-                       inode->i_flags &= S_IMMUTABLE;
+                       inode->i_flags &= ~S_IMMUTABLE;
        }
 
        fat_save_attrs(inode, attr);
index cc6ec4b..38f84cd 100644 (file)
@@ -921,6 +921,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        if (sb->s_flags & MS_MANDLOCK)
                goto err;
 
+       sb->s_flags &= ~MS_NOSEC;
+
        if (!parse_fuse_opt((char *) data, &d, is_bdev))
                goto err;
 
index 2792a79..1c1336e 100644 (file)
@@ -663,14 +663,19 @@ static void glock_work_func(struct work_struct *work)
                drop_ref = 1;
        }
        spin_lock(&gl->gl_spin);
-       if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
+       if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
            gl->gl_state != LM_ST_UNLOCKED &&
            gl->gl_demote_state != LM_ST_EXCLUSIVE) {
                unsigned long holdtime, now = jiffies;
+
                holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
                if (time_before(now, holdtime))
                        delay = holdtime - now;
-               set_bit(delay ? GLF_PENDING_DEMOTE : GLF_DEMOTE, &gl->gl_flags);
+
+               if (!delay) {
+                       clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags);
+                       set_bit(GLF_DEMOTE, &gl->gl_flags);
+               }
        }
        run_queue(gl, 0);
        spin_unlock(&gl->gl_spin);
index 278e3fb..583636f 100644 (file)
@@ -1123,7 +1123,7 @@ int lmLogOpen(struct super_block *sb)
        bdev = blkdev_get_by_dev(sbi->logdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
                                 log);
        if (IS_ERR(bdev)) {
-               rc = -PTR_ERR(bdev);
+               rc = PTR_ERR(bdev);
                goto free;
        }
 
index e2e4e8d..9802345 100644 (file)
@@ -2624,6 +2624,10 @@ static long do_rmdir(int dfd, const char __user *pathname)
        error = PTR_ERR(dentry);
        if (IS_ERR(dentry))
                goto exit2;
+       if (!dentry->d_inode) {
+               error = -ENOENT;
+               goto exit3;
+       }
        error = mnt_want_write(nd.path.mnt);
        if (error)
                goto exit3;
@@ -2709,11 +2713,10 @@ static long do_unlinkat(int dfd, const char __user *pathname)
        error = PTR_ERR(dentry);
        if (!IS_ERR(dentry)) {
                /* Why not before? Because we want correct error value */
-               if (nd.last.name[nd.last.len])
-                       goto slashes;
                inode = dentry->d_inode;
-               if (inode)
-                       ihold(inode);
+               if (nd.last.name[nd.last.len] || !inode)
+                       goto slashes;
+               ihold(inode);
                error = mnt_want_write(nd.path.mnt);
                if (error)
                        goto exit2;
index cdbaf5e..56f6102 100644 (file)
@@ -1072,7 +1072,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_magic = OCFS2_SUPER_MAGIC;
 
-       sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+       sb->s_flags = (sb->s_flags & ~(MS_POSIXACL | MS_NOSEC)) |
                ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
 
        /* Hard readonly mode only if: bdev_read_only, MS_RDONLY,
index c755939..ab3d672 100644 (file)
@@ -822,7 +822,7 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
        } else {
                char b[BDEVNAME_SIZE];
 
-               s->s_flags = flags;
+               s->s_flags = flags | MS_NOSEC;
                s->s_mode = mode;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
                sb_set_blocksize(s, block_size(bdev));
index f04b2a3..e08f344 100644 (file)
        {0x1002, 0x9614, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9615, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9616, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9642, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9643, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
+       {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
+       {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x964e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
+       {0x1002, 0x964f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
        {0x1002, 0x9710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
index c55d6b7..1c77787 100644 (file)
@@ -208,6 +208,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT   (1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION   (1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME (1<<24) /* Always perform atime updates */
+#define MS_NOSEC       (1<<28)
 #define MS_BORN                (1<<29)
 #define MS_ACTIVE      (1<<30)
 #define MS_NOUSER      (1<<31)
@@ -743,9 +744,13 @@ struct inode {
 
        spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
        unsigned int            i_flags;
+       unsigned int            i_state;
+#ifdef CONFIG_SECURITY
+       void                    *i_security;
+#endif
        struct mutex            i_mutex;
 
-       unsigned long           i_state;
+
        unsigned long           dirtied_when;   /* jiffies of first dirtying */
 
        struct hlist_node       i_hash;
@@ -797,9 +802,6 @@ struct inode {
        atomic_t                i_readcount; /* struct files open RO */
 #endif
        atomic_t                i_writecount;
-#ifdef CONFIG_SECURITY
-       void                    *i_security;
-#endif
 #ifdef CONFIG_FS_POSIX_ACL
        struct posix_acl        *i_acl;
        struct posix_acl        *i_default_acl;
@@ -2591,7 +2593,7 @@ static inline int is_sxid(mode_t mode)
 
 static inline void inode_has_no_xattr(struct inode *inode)
 {
-       if (!is_sxid(inode->i_mode))
+       if (!is_sxid(inode->i_mode) && (inode->i_sb->s_flags & MS_NOSEC))
                inode->i_flags |= S_NOSEC;
 }
 
index 819acaa..714ba08 100644 (file)
@@ -8,9 +8,9 @@
  * @IRQ_WAKE_THREAD    handler requests to wake the handler thread
  */
 enum irqreturn {
-       IRQ_NONE,
-       IRQ_HANDLED,
-       IRQ_WAKE_THREAD,
+       IRQ_NONE                = (0 << 0),
+       IRQ_HANDLED             = (1 << 0),
+       IRQ_WAKE_THREAD         = (1 << 1),
 };
 
 typedef enum irqreturn irqreturn_t;
index 3412684..e0786e3 100644 (file)
@@ -137,14 +137,14 @@ enum perf_event_sample_format {
  *
  * struct read_format {
  *     { u64           value;
- *       { u64         time_enabled; } && PERF_FORMAT_ENABLED
- *       { u64         time_running; } && PERF_FORMAT_RUNNING
+ *       { u64         time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
+ *       { u64         time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
  *       { u64         id;           } && PERF_FORMAT_ID
  *     } && !PERF_FORMAT_GROUP
  *
  *     { u64           nr;
- *       { u64         time_enabled; } && PERF_FORMAT_ENABLED
- *       { u64         time_running; } && PERF_FORMAT_RUNNING
+ *       { u64         time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
+ *       { u64         time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
  *       { u64         value;
  *         { u64       id;           } && PERF_FORMAT_ID
  *       }             cntr[nr];
index 2a8621c..a837b20 100644 (file)
@@ -1063,6 +1063,7 @@ struct sched_domain;
  */
 #define WF_SYNC                0x01            /* waker goes to sleep after wakup */
 #define WF_FORK                0x02            /* child wakeup after fork */
+#define WF_MIGRATED    0x04            /* internal use, task got migrated */
 
 #define ENQUEUE_WAKEUP         1
 #define ENQUEUE_HEAD           2
index e981189..c6db9fb 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/preempt.h>
+#include <asm/processor.h>
 
 typedef struct {
        unsigned sequence;
index 8c0e349..445702c 100644 (file)
@@ -24,6 +24,7 @@ extern int swiotlb_force;
 
 extern void swiotlb_init(int verbose);
 extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
+extern unsigned long swioltb_nr_tbl(void);
 
 /*
  * Enumeration for sync targets
index 71693d4..17df360 100644 (file)
@@ -62,7 +62,9 @@
        US_FLAG(NO_READ_DISC_INFO,      0x00040000)             \
                /* cannot handle READ_DISC_INFO */              \
        US_FLAG(NO_READ_CAPACITY_16,    0x00080000)             \
-               /* cannot handle READ_CAPACITY_16 */
+               /* cannot handle READ_CAPACITY_16 */            \
+       US_FLAG(INITIAL_READ10, 0x00100000)                     \
+               /* Initial READ(10) (and others) must be retried */
 
 #define US_FLAG(name, value)   US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
index 93e96fb..c7c40f1 100644 (file)
@@ -128,8 +128,8 @@ struct video_device
        struct mutex *lock;
 };
 
-#define media_entity_to_video_device(entity) \
-       container_of(entity, struct video_device, entity)
+#define media_entity_to_video_device(__e) \
+       container_of(__e, struct video_device, entity)
 /* dev to video-device */
 #define to_video_device(cd) container_of(cd, struct video_device, dev)
 
diff --git a/include/staging/altera.h b/include/staging/altera.h
deleted file mode 100644 (file)
index 94c0c61..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * altera.h
- *
- * altera FPGA driver
- *
- * Copyright (C) Altera Corporation 1998-2001
- * Copyright (C) 2010 NetUP Inc.
- * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _ALTERA_H_
-#define _ALTERA_H_
-
-struct altera_config {
-       void *dev;
-       u8 *action;
-       int (*jtag_io) (void *dev, int tms, int tdi, int tdo);
-};
-
-#if defined(CONFIG_ALTERA_STAPL) || \
-               (defined(CONFIG_ALTERA_STAPL_MODULE) && defined(MODULE))
-
-extern int altera_init(struct altera_config *config, const struct firmware *fw);
-#else
-
-static inline int altera_init(struct altera_config *config,
-                                               const struct firmware *fw)
-{
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-       return 0;
-}
-#endif /* CONFIG_ALTERA_STAPL */
-
-#endif /* _ALTERA_H_ */
index d863b3c..9efe710 100644 (file)
@@ -7402,26 +7402,12 @@ static int __perf_cgroup_move(void *info)
        return 0;
 }
 
-static void perf_cgroup_move(struct task_struct *task)
+static void
+perf_cgroup_attach_task(struct cgroup *cgrp, struct task_struct *task)
 {
        task_function_call(task, __perf_cgroup_move, task);
 }
 
-static void perf_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
-               struct cgroup *old_cgrp, struct task_struct *task,
-               bool threadgroup)
-{
-       perf_cgroup_move(task);
-       if (threadgroup) {
-               struct task_struct *c;
-               rcu_read_lock();
-               list_for_each_entry_rcu(c, &task->thread_group, thread_group) {
-                       perf_cgroup_move(c);
-               }
-               rcu_read_unlock();
-       }
-}
-
 static void perf_cgroup_exit(struct cgroup_subsys *ss, struct cgroup *cgrp,
                struct cgroup *old_cgrp, struct task_struct *task)
 {
@@ -7433,7 +7419,7 @@ static void perf_cgroup_exit(struct cgroup_subsys *ss, struct cgroup *cgrp,
        if (!(task->flags & PF_EXITING))
                return;
 
-       perf_cgroup_move(task);
+       perf_cgroup_attach_task(cgrp, task);
 }
 
 struct cgroup_subsys perf_subsys = {
@@ -7442,6 +7428,6 @@ struct cgroup_subsys perf_subsys = {
        .create         = perf_cgroup_create,
        .destroy        = perf_cgroup_destroy,
        .exit           = perf_cgroup_exit,
-       .attach         = perf_cgroup_attach,
+       .attach_task    = perf_cgroup_attach_task,
 };
 #endif /* CONFIG_CGROUP_PERF */
index 90cb55f..470d08c 100644 (file)
@@ -132,12 +132,6 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
 
                switch (res) {
                case IRQ_WAKE_THREAD:
-                       /*
-                        * Set result to handled so the spurious check
-                        * does not trigger.
-                        */
-                       res = IRQ_HANDLED;
-
                        /*
                         * Catch drivers which return WAKE_THREAD but
                         * did not set up a thread function
index 886e803..4c60a50 100644 (file)
@@ -257,13 +257,11 @@ int __init early_irq_init(void)
        count = ARRAY_SIZE(irq_desc);
 
        for (i = 0; i < count; i++) {
-               desc[i].irq_data.irq = i;
-               desc[i].irq_data.chip = &no_irq_chip;
                desc[i].kstat_irqs = alloc_percpu(unsigned int);
-               irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
-               alloc_masks(desc + i, GFP_KERNEL, node);
-               desc_smp_init(desc + i, node);
+               alloc_masks(&desc[i], GFP_KERNEL, node);
+               raw_spin_lock_init(&desc[i].lock);
                lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
+               desc_set_defaults(i, &desc[i], node);
        }
        return arch_early_irq_init();
 }
@@ -346,6 +344,12 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
        if (!cnt)
                return -EINVAL;
 
+       if (irq >= 0) {
+               if (from > irq)
+                       return -EINVAL;
+               from = irq;
+       }
+
        mutex_lock(&sparse_irq_lock);
 
        start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS,
index f7ce002..d64bafb 100644 (file)
@@ -723,13 +723,16 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { }
  * context. So we need to disable bh here to avoid deadlocks and other
  * side effects.
  */
-static void
+static irqreturn_t
 irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
 {
+       irqreturn_t ret;
+
        local_bh_disable();
-       action->thread_fn(action->irq, action->dev_id);
+       ret = action->thread_fn(action->irq, action->dev_id);
        irq_finalize_oneshot(desc, action, false);
        local_bh_enable();
+       return ret;
 }
 
 /*
@@ -737,10 +740,14 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
  * preemtible - many of them need to sleep and wait for slow busses to
  * complete.
  */
-static void irq_thread_fn(struct irq_desc *desc, struct irqaction *action)
+static irqreturn_t irq_thread_fn(struct irq_desc *desc,
+               struct irqaction *action)
 {
-       action->thread_fn(action->irq, action->dev_id);
+       irqreturn_t ret;
+
+       ret = action->thread_fn(action->irq, action->dev_id);
        irq_finalize_oneshot(desc, action, false);
+       return ret;
 }
 
 /*
@@ -753,7 +760,8 @@ static int irq_thread(void *data)
        };
        struct irqaction *action = data;
        struct irq_desc *desc = irq_to_desc(action->irq);
-       void (*handler_fn)(struct irq_desc *desc, struct irqaction *action);
+       irqreturn_t (*handler_fn)(struct irq_desc *desc,
+                       struct irqaction *action);
        int wake;
 
        if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD,
@@ -783,8 +791,12 @@ static int irq_thread(void *data)
                        desc->istate |= IRQS_PENDING;
                        raw_spin_unlock_irq(&desc->lock);
                } else {
+                       irqreturn_t action_ret;
+
                        raw_spin_unlock_irq(&desc->lock);
-                       handler_fn(desc, action);
+                       action_ret = handler_fn(desc, action);
+                       if (!noirqdebug)
+                               note_interrupt(action->irq, desc, action_ret);
                }
 
                wake = atomic_dec_and_test(&desc->threads_active);
index dfbd550..aa57d5d 100644 (file)
@@ -167,6 +167,13 @@ out:
                  jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
 }
 
+static inline int bad_action_ret(irqreturn_t action_ret)
+{
+       if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD)))
+               return 0;
+       return 1;
+}
+
 /*
  * If 99,900 of the previous 100,000 interrupts have not been handled
  * then assume that the IRQ is stuck in some manner. Drop a diagnostic
@@ -182,7 +189,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
        struct irqaction *action;
        unsigned long flags;
 
-       if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
+       if (bad_action_ret(action_ret)) {
                printk(KERN_ERR "irq event %d: bogus return value %x\n",
                                irq, action_ret);
        } else {
@@ -201,10 +208,11 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
        raw_spin_lock_irqsave(&desc->lock, flags);
        action = desc->action;
        while (action) {
-               printk(KERN_ERR "[<%p>]", action->handler);
-               print_symbol(" (%s)",
-                       (unsigned long)action->handler);
-               printk("\n");
+               printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler);
+               if (action->thread_fn)
+                       printk(KERN_CONT " threaded [<%p>] %pf",
+                                       action->thread_fn, action->thread_fn);
+               printk(KERN_CONT "\n");
                action = action->next;
        }
        raw_spin_unlock_irqrestore(&desc->lock, flags);
@@ -262,7 +270,16 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
        if (desc->istate & IRQS_POLL_INPROGRESS)
                return;
 
-       if (unlikely(action_ret != IRQ_HANDLED)) {
+       /* we get here again via the threaded handler */
+       if (action_ret == IRQ_WAKE_THREAD)
+               return;
+
+       if (bad_action_ret(action_ret)) {
+               report_bad_irq(irq, desc, action_ret);
+               return;
+       }
+
+       if (unlikely(action_ret == IRQ_NONE)) {
                /*
                 * If we are seeing only the odd spurious IRQ caused by
                 * bus asynchronicity then don't eventually trigger an error,
@@ -274,8 +291,6 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
                else
                        desc->irqs_unhandled++;
                desc->last_unhandled = jiffies;
-               if (unlikely(action_ret != IRQ_NONE))
-                       report_bad_irq(irq, desc, action_ret);
        }
 
        if (unlikely(try_misrouted_irq(irq, desc, action_ret))) {
index 63437d0..298c927 100644 (file)
@@ -3426,7 +3426,7 @@ int lock_is_held(struct lockdep_map *lock)
        int ret = 0;
 
        if (unlikely(current->lockdep_recursion))
-               return ret;
+               return 1; /* avoid false negative lockdep_assert_held() */
 
        raw_local_irq_save(flags);
        check_flags(flags);
index cbb3a0e..3f2e502 100644 (file)
@@ -605,10 +605,10 @@ static inline int cpu_of(struct rq *rq)
 /*
  * Return the group to which this tasks belongs.
  *
- * We use task_subsys_state_check() and extend the RCU verification
- * with lockdep_is_held(&p->pi_lock) because cpu_cgroup_attach()
- * holds that lock for each task it moves into the cgroup. Therefore
- * by holding that lock, we pin the task to the current cgroup.
+ * We use task_subsys_state_check() and extend the RCU verification with
+ * pi->lock and rq->lock because cpu_cgroup_attach() holds those locks for each
+ * task it moves into the cgroup. Therefore by holding either of those locks,
+ * we pin the task to the current cgroup.
  */
 static inline struct task_group *task_group(struct task_struct *p)
 {
@@ -616,7 +616,8 @@ static inline struct task_group *task_group(struct task_struct *p)
        struct cgroup_subsys_state *css;
 
        css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
-                       lockdep_is_held(&p->pi_lock));
+                       lockdep_is_held(&p->pi_lock) ||
+                       lockdep_is_held(&task_rq(p)->lock));
        tg = container_of(css, struct task_group, css);
 
        return autogroup_task_group(p, tg);
@@ -2200,6 +2201,16 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
                        !(task_thread_info(p)->preempt_count & PREEMPT_ACTIVE));
 
 #ifdef CONFIG_LOCKDEP
+       /*
+        * The caller should hold either p->pi_lock or rq->lock, when changing
+        * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks.
+        *
+        * sched_move_task() holds both and thus holding either pins the cgroup,
+        * see set_task_rq().
+        *
+        * Furthermore, all task_rq users should acquire both locks, see
+        * task_rq_lock().
+        */
        WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) ||
                                      lockdep_is_held(&task_rq(p)->lock)));
 #endif
@@ -2447,6 +2458,10 @@ ttwu_stat(struct task_struct *p, int cpu, int wake_flags)
                }
                rcu_read_unlock();
        }
+
+       if (wake_flags & WF_MIGRATED)
+               schedstat_inc(p, se.statistics.nr_wakeups_migrate);
+
 #endif /* CONFIG_SMP */
 
        schedstat_inc(rq, ttwu_count);
@@ -2455,9 +2470,6 @@ ttwu_stat(struct task_struct *p, int cpu, int wake_flags)
        if (wake_flags & WF_SYNC)
                schedstat_inc(p, se.statistics.nr_wakeups_sync);
 
-       if (cpu != task_cpu(p))
-               schedstat_inc(p, se.statistics.nr_wakeups_migrate);
-
 #endif /* CONFIG_SCHEDSTATS */
 }
 
@@ -2600,6 +2612,7 @@ static void ttwu_queue(struct task_struct *p, int cpu)
 
 #if defined(CONFIG_SMP)
        if (sched_feat(TTWU_QUEUE) && cpu != smp_processor_id()) {
+               sched_clock_cpu(cpu); /* sync clocks x-cpu */
                ttwu_queue_remote(p, cpu);
                return;
        }
@@ -2674,8 +2687,10 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
                p->sched_class->task_waking(p);
 
        cpu = select_task_rq(p, SD_BALANCE_WAKE, wake_flags);
-       if (task_cpu(p) != cpu)
+       if (task_cpu(p) != cpu) {
+               wake_flags |= WF_MIGRATED;
                set_task_cpu(p, cpu);
+       }
 #endif /* CONFIG_SMP */
 
        ttwu_queue(p, cpu);
index 4fc9244..f175d98 100644 (file)
@@ -938,6 +938,12 @@ static struct ctl_table kern_table[] = {
        },
 #endif
 #ifdef CONFIG_PERF_EVENTS
+       /*
+        * User-space scripts rely on the existence of this file
+        * as a feature check for perf_events being enabled.
+        *
+        * So it's an ABI, do not remove!
+        */
        {
                .procname       = "perf_event_paranoid",
                .data           = &sysctl_perf_event_paranoid,
index c027d4f..e4c699d 100644 (file)
@@ -182,7 +182,10 @@ void clockevents_register_device(struct clock_event_device *dev)
        unsigned long flags;
 
        BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
-       BUG_ON(!dev->cpumask);
+       if (!dev->cpumask) {
+               WARN_ON(num_possible_cpus() > 1);
+               dev->cpumask = cpumask_of(smp_processor_id());
+       }
 
        raw_spin_lock_irqsave(&clockevents_lock, flags);
 
index fd61986..8cff361 100644 (file)
@@ -749,16 +749,15 @@ unsigned long apply_slack(struct timer_list *timer, unsigned long expires)
        unsigned long expires_limit, mask;
        int bit;
 
-       expires_limit = expires;
-
        if (timer->slack >= 0) {
                expires_limit = expires + timer->slack;
        } else {
-               unsigned long now = jiffies;
+               long delta = expires - jiffies;
+
+               if (delta < 256)
+                       return expires;
 
-               /* No slack, if already expired else auto slack 0.4% */
-               if (time_after(expires, now))
-                       expires_limit = expires + (expires - now)/256;
+               expires_limit = expires + delta / 256;
        }
        mask = expires ^ expires_limit;
        if (mask == 0)
@@ -795,6 +794,8 @@ unsigned long apply_slack(struct timer_list *timer, unsigned long expires)
  */
 int mod_timer(struct timer_list *timer, unsigned long expires)
 {
+       expires = apply_slack(timer, expires);
+
        /*
         * This is a common optimization triggered by the
         * networking code - if the timer is re-modified
@@ -803,8 +804,6 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
        if (timer_pending(timer) && timer->expires == expires)
                return 1;
 
-       expires = apply_slack(timer, expires);
-
        return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
 }
 EXPORT_SYMBOL(mod_timer);
index 93ca08b..99093b3 100644 (file)
@@ -110,6 +110,11 @@ setup_io_tlb_npages(char *str)
 __setup("swiotlb=", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
+unsigned long swioltb_nr_tbl(void)
+{
+       return io_tlb_nslabs;
+}
+
 /* Note that this doesn't work with highmem page */
 static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
                                      volatile void *address)
index c112056..4365df3 100644 (file)
@@ -666,6 +666,8 @@ char *ip6_compressed_string(char *p, const char *addr)
                        colonpos = i;
                }
        }
+       if (longest == 1)               /* don't compress a single 0 */
+               colonpos = -1;
 
        /* emit address */
        for (i = 0; i < range; i++) {
@@ -826,7 +828,7 @@ int kptr_restrict __read_mostly;
  *       IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
  * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order
  * - 'I6c' for IPv6 addresses printed as specified by
- *       http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
+ *       http://tools.ietf.org/html/rfc5952
  * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
  *       "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  *       Options for %pU are:
index d7b1057..a8251a8 100644 (file)
@@ -2000,7 +2000,7 @@ int file_remove_suid(struct file *file)
                error = security_inode_killpriv(dentry);
        if (!error && killsuid)
                error = __remove_suid(dentry, killsuid);
-       if (!error)
+       if (!error && (inode->i_sb->s_flags & MS_NOSEC))
                inode->i_flags |= S_NOSEC;
 
        return error;
index f33bb31..6402458 100644 (file)
@@ -1033,10 +1033,10 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
         */
        chg = vma_needs_reservation(h, vma, addr);
        if (chg < 0)
-               return ERR_PTR(chg);
+               return ERR_PTR(-VM_FAULT_OOM);
        if (chg)
                if (hugetlb_get_quota(inode->i_mapping, chg))
-                       return ERR_PTR(-ENOSPC);
+                       return ERR_PTR(-VM_FAULT_SIGBUS);
 
        spin_lock(&hugetlb_lock);
        page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve);
index 490122c..40caf3c 100644 (file)
@@ -17,6 +17,7 @@ quiet_cmd_wrap = WRAP    $@
 cmd_wrap = echo "\#include <asm-generic/$*.h>" >$@
 
 all: $(patsubst %, $(obj)/%, $(generic-y))
+       @:
 
 $(obj)/%.h:
        $(call cmd,wrap)
diff --git a/scripts/depmod.sh b/scripts/depmod.sh
new file mode 100755 (executable)
index 0000000..3b029cb
--- /dev/null
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# A depmod wrapper used by the toplevel Makefile
+
+if test $# -ne 2; then
+       echo "Usage: $0 /sbin/depmod <kernelrelease>" >&2
+       exit 1
+fi
+DEPMOD=$1
+KERNELRELEASE=$2
+
+if ! "$DEPMOD" -V 2>/dev/null | grep -q module-init-tools; then
+       echo "Warning: you may need to install module-init-tools" >&2
+       echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt" >&2
+       sleep 1
+fi
+
+if ! test -r System.map -a -x "$DEPMOD"; then
+       exit 0
+fi
+# older versions of depmod require the version string to start with three
+# numbers, so we cheat with a symlink here
+depmod_hack_needed=true
+mkdir -p .tmp_depmod/lib/modules/$KERNELRELEASE
+if "$DEPMOD" -b .tmp_depmod $KERNELRELEASE 2>/dev/null; then
+       if test -e .tmp_depmod/lib/modules/$KERNELRELEASE/modules.dep -o \
+               -e .tmp_depmod/lib/modules/$KERNELRELEASE/modules.dep.bin; then
+               depmod_hack_needed=false
+       fi
+fi
+if $depmod_hack_needed; then
+       symlink="$INSTALL_MOD_PATH/lib/modules/99.98.$KERNELRELEASE"
+       ln -s "$KERNELRELEASE" "$symlink"
+       KERNELRELEASE=99.98.$KERNELRELEASE
+fi
+
+set -- -ae -F System.map
+if test -n "$INSTALL_MOD_PATH"; then
+       set -- "$@" -b "$INSTALL_MOD_PATH"
+fi
+"$DEPMOD" "$@" "$KERNELRELEASE"
+ret=$?
+
+if $depmod_hack_needed; then
+       rm -f "$symlink"
+fi
+
+exit $ret
index ec1bcec..3d2fd14 100644 (file)
@@ -612,7 +612,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
 static int apparmor_task_setrlimit(struct task_struct *task,
                unsigned int resource, struct rlimit *new_rlim)
 {
-       struct aa_profile *profile = aa_current_profile();
+       struct aa_profile *profile = __aa_current_profile();
        int error = 0;
 
        if (!unconfined(profile))
index a0d3845..20219ef 100644 (file)
@@ -1476,7 +1476,6 @@ static int inode_has_perm(const struct cred *cred,
                          unsigned flags)
 {
        struct inode_security_struct *isec;
-       struct common_audit_data ad;
        u32 sid;
 
        validate_creds(cred);
@@ -1487,15 +1486,21 @@ static int inode_has_perm(const struct cred *cred,
        sid = cred_sid(cred);
        isec = inode->i_security;
 
-       if (!adp) {
-               adp = &ad;
-               COMMON_AUDIT_DATA_INIT(&ad, INODE);
-               ad.u.inode = inode;
-       }
-
        return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
 }
 
+static int inode_has_perm_noadp(const struct cred *cred,
+                               struct inode *inode,
+                               u32 perms,
+                               unsigned flags)
+{
+       struct common_audit_data ad;
+
+       COMMON_AUDIT_DATA_INIT(&ad, INODE);
+       ad.u.inode = inode;
+       return inode_has_perm(cred, inode, perms, &ad, flags);
+}
+
 /* Same as inode_has_perm, but pass explicit audit data containing
    the dentry to help the auditing code to more easily generate the
    pathname if needed. */
@@ -2122,8 +2127,8 @@ static inline void flush_unauthorized_files(const struct cred *cred,
                                                struct tty_file_private, list);
                        file = file_priv->file;
                        inode = file->f_path.dentry->d_inode;
-                       if (inode_has_perm(cred, inode,
-                                          FILE__READ | FILE__WRITE, NULL, 0)) {
+                       if (inode_has_perm_noadp(cred, inode,
+                                          FILE__READ | FILE__WRITE, 0)) {
                                drop_tty = 1;
                        }
                }
@@ -3228,7 +3233,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
         * new inode label or new policy.
         * This check is not redundant - do not remove.
         */
-       return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0);
+       return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0);
 }
 
 /* task security operations */
index fb311d8..5c6ea11 100644 (file)
@@ -60,7 +60,7 @@ struct code_header {
            HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER)))
 
 /***********************************************************************/
-#include "linux/pci.h"
+#include <linux/pci.h>
 /*-------------------------------------------------------------------*/
 short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code,
        u32 *pos_error_code)
index eacd490..a7ec703 100644 (file)
@@ -1234,9 +1234,12 @@ static int __devinit snd_fm801_create(struct snd_card *card,
        sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci));
        if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 &&
            (tea575x_tuner & TUNER_TYPE_MASK) < 4) {
-               if (snd_tea575x_init(&chip->tea))
+               if (snd_tea575x_init(&chip->tea)) {
                        snd_printk(KERN_ERR "TEA575x radio not found\n");
-       } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0)
+                       snd_fm801_free(chip);
+                       return -ENODEV;
+               }
+       } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) {
                /* autodetect tuner connection */
                for (tea575x_tuner = 1; tea575x_tuner <= 3; tea575x_tuner++) {
                        chip->tea575x_tuner = tea575x_tuner;
@@ -1246,6 +1249,12 @@ static int __devinit snd_fm801_create(struct snd_card *card,
                                break;
                        }
                }
+               if (tea575x_tuner == 4) {
+                       snd_printk(KERN_ERR "TEA575x radio not found\n");
+                       snd_fm801_free(chip);
+                       return -ENODEV;
+               }
+       }
        strlcpy(chip->tea.card, snd_fm801_tea575x_gpios[(tea575x_tuner & TUNER_TYPE_MASK) - 1].name, sizeof(chip->tea.card));
 #endif
 
index 696ac25..d694e9d 100644 (file)
@@ -506,9 +506,11 @@ static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
                                hda_nid_t hp)
 {
        struct ad198x_spec *spec = codec->spec;
-       snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
+       if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
+               snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
                            !spec->inv_eapd ? 0x00 : 0x02);
-       snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
+       if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
+               snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
                            !spec->inv_eapd ? 0x00 : 0x02);
 }
 
@@ -524,6 +526,10 @@ static void ad198x_power_eapd(struct hda_codec *codec)
        case 0x11d4184a:
        case 0x11d4194a:
        case 0x11d4194b:
+       case 0x11d41988:
+       case 0x11d4198b:
+       case 0x11d4989a:
+       case 0x11d4989b:
                ad198x_power_eapd_write(codec, 0x12, 0x11);
                break;
        case 0x11d41981:
@@ -533,12 +539,6 @@ static void ad198x_power_eapd(struct hda_codec *codec)
        case 0x11d41986:
                ad198x_power_eapd_write(codec, 0x1b, 0x1a);
                break;
-       case 0x11d41988:
-       case 0x11d4198b:
-       case 0x11d4989a:
-       case 0x11d4989b:
-               ad198x_power_eapd_write(codec, 0x29, 0x22);
-               break;
        }
 }
 
index e55b298..9e370d1 100644 (file)
@@ -215,23 +215,23 @@ static const struct snd_kcontrol_new analogue_snd_controls[] = {
 SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
               inpga_tlv),
 SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
-SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 0),
+SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 6, 1, 0),
 
 SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
               inpga_tlv),
 SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
-SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 0),
+SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 6, 1, 0),
 
 
 SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
               inpga_tlv),
 SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
-SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 0),
+SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 6, 1, 0),
 
 SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
               inpga_tlv),
 SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
-SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 0),
+SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 6, 1, 0),
 
 SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0,
               inmix_sw_tlv),
index 999bb08..776e6f4 100644 (file)
@@ -325,6 +325,7 @@ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,
 }
 
 static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
+       struct snd_soc_dapm_widget *kcontrolw,
        const struct snd_kcontrol_new *kcontrol_new,
        struct snd_kcontrol **kcontrol)
 {
@@ -334,6 +335,8 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
        *kcontrol = NULL;
 
        list_for_each_entry(w, &dapm->card->widgets, list) {
+               if (w == kcontrolw || w->dapm != kcontrolw->dapm)
+                       continue;
                for (i = 0; i < w->num_kcontrols; i++) {
                        if (&w->kcontrol_news[i] == kcontrol_new) {
                                if (w->kcontrols)
@@ -468,7 +471,7 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm,
                return -EINVAL;
        }
 
-       shared = dapm_is_shared_kcontrol(dapm, &w->kcontrol_news[0],
+       shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[0],
                                         &kcontrol);
        if (kcontrol) {
                wlist = kcontrol->private_data;
index d47beff..a91719d 100644 (file)
@@ -227,6 +227,7 @@ static int usb6fire_fw_ezusb_upload(
        ret = usb6fire_fw_ihex_init(fw, rec);
        if (ret < 0) {
                kfree(rec);
+               release_firmware(fw);
                snd_printk(KERN_ERR PREFIX "error validating ezusb "
                                "firmware %s.\n", fwname);
                return ret;
index 2e969cb..090e193 100644 (file)
@@ -403,7 +403,7 @@ static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
 static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
 {
        int err, reg;
-       int val[] = {0x200c, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000};
+       int val[] = {0x2004, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000};
 
        for (reg = 0; reg < ARRAY_SIZE(val); reg++) {
                err = snd_usb_cm106_write_int_reg(dev, reg, val[reg]);
index b671862..2da9162 100644 (file)
@@ -474,7 +474,7 @@ static int test__basic_mmap(void)
        unsigned int nr_events[nsyscalls],
                     expected_nr_events[nsyscalls], i, j;
        struct perf_evsel *evsels[nsyscalls], *evsel;
-       int sample_size = perf_sample_size(attr.sample_type);
+       int sample_size = __perf_evsel__sample_size(attr.sample_type);
 
        for (i = 0; i < nsyscalls; ++i) {
                char name[64];
index 26d4d3f..9c5fb4d 100755 (executable)
@@ -23,12 +23,7 @@ if test -d ../../.git -o -f ../../.git &&
 then
        VN=$(echo "$VN" | sed -e 's/-/./g');
 else
-       eval $(grep '^VERSION[[:space:]]*=' ../../Makefile|tr -d ' ')
-       eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ')
-       eval $(grep '^SUBLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ')
-       eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../Makefile|tr -d ' ')
-
-       VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
+       VN=$(make -sC ../.. kernelversion)
 fi
 
 VN=$(expr "$VN" : v*'\(.*\)')
index 0fe9adf..3c1b8a6 100644 (file)
@@ -35,22 +35,6 @@ const char *perf_event__name(unsigned int id)
        return perf_event__names[id];
 }
 
-int perf_sample_size(u64 sample_type)
-{
-       u64 mask = sample_type & PERF_SAMPLE_MASK;
-       int size = 0;
-       int i;
-
-       for (i = 0; i < 64; i++) {
-               if (mask & (1ULL << i))
-                       size++;
-       }
-
-       size *= sizeof(u64);
-
-       return size;
-}
-
 static struct perf_sample synth_sample = {
        .pid       = -1,
        .tid       = -1,
index c083328..1d7f664 100644 (file)
@@ -82,8 +82,6 @@ struct perf_sample {
        struct ip_callchain *callchain;
 };
 
-int perf_sample_size(u64 sample_type);
-
 #define BUILD_ID_SIZE 20
 
 struct build_id_event {
index 50aa348..b021ea9 100644 (file)
@@ -12,7 +12,6 @@
 #include "evlist.h"
 #include "evsel.h"
 #include "util.h"
-#include "debug.h"
 
 #include <sys/mman.h>
 
@@ -257,19 +256,15 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
        return evlist->mmap != NULL ? 0 : -ENOMEM;
 }
 
-static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel,
+static int __perf_evlist__mmap(struct perf_evlist *evlist,
                               int idx, int prot, int mask, int fd)
 {
        evlist->mmap[idx].prev = 0;
        evlist->mmap[idx].mask = mask;
        evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
                                      MAP_SHARED, fd, 0);
-       if (evlist->mmap[idx].base == MAP_FAILED) {
-               if (evlist->cpus->map[idx] == -1 && evsel->attr.inherit)
-                       ui__warning("Inherit is not allowed on per-task "
-                                   "events using mmap.\n");
+       if (evlist->mmap[idx].base == MAP_FAILED)
                return -1;
-       }
 
        perf_evlist__add_pollfd(evlist, fd);
        return 0;
@@ -289,7 +284,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m
 
                                if (output == -1) {
                                        output = fd;
-                                       if (__perf_evlist__mmap(evlist, evsel, cpu,
+                                       if (__perf_evlist__mmap(evlist, cpu,
                                                                prot, mask, output) < 0)
                                                goto out_unmap;
                                } else {
@@ -329,7 +324,7 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in
 
                        if (output == -1) {
                                output = fd;
-                               if (__perf_evlist__mmap(evlist, evsel, thread,
+                               if (__perf_evlist__mmap(evlist, thread,
                                                        prot, mask, output) < 0)
                                        goto out_unmap;
                        } else {
@@ -460,33 +455,46 @@ int perf_evlist__set_filters(struct perf_evlist *evlist)
        return 0;
 }
 
-u64 perf_evlist__sample_type(struct perf_evlist *evlist)
+bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist)
 {
-       struct perf_evsel *pos;
-       u64 type = 0;
-
-       list_for_each_entry(pos, &evlist->entries, node) {
-               if (!type)
-                       type = pos->attr.sample_type;
-               else if (type != pos->attr.sample_type)
-                       die("non matching sample_type");
+       struct perf_evsel *pos, *first;
+
+       pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
+
+       list_for_each_entry_continue(pos, &evlist->entries, node) {
+               if (first->attr.sample_type != pos->attr.sample_type)
+                       return false;
        }
 
-       return type;
+       return true;
 }
 
-bool perf_evlist__sample_id_all(const struct perf_evlist *evlist)
+u64 perf_evlist__sample_type(const struct perf_evlist *evlist)
+{
+       struct perf_evsel *first;
+
+       first = list_entry(evlist->entries.next, struct perf_evsel, node);
+       return first->attr.sample_type;
+}
+
+bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
 {
-       bool value = false, first = true;
-       struct perf_evsel *pos;
-
-       list_for_each_entry(pos, &evlist->entries, node) {
-               if (first) {
-                       value = pos->attr.sample_id_all;
-                       first = false;
-               } else if (value != pos->attr.sample_id_all)
-                       die("non matching sample_id_all");
+       struct perf_evsel *pos, *first;
+
+       pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
+
+       list_for_each_entry_continue(pos, &evlist->entries, node) {
+               if (first->attr.sample_id_all != pos->attr.sample_id_all)
+                       return false;
        }
 
-       return value;
+       return true;
+}
+
+bool perf_evlist__sample_id_all(const struct perf_evlist *evlist)
+{
+       struct perf_evsel *first;
+
+       first = list_entry(evlist->entries.next, struct perf_evsel, node);
+       return first->attr.sample_id_all;
 }
index 0a1ef1f..b2b8623 100644 (file)
@@ -66,7 +66,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
 void perf_evlist__delete_maps(struct perf_evlist *evlist);
 int perf_evlist__set_filters(struct perf_evlist *evlist);
 
-u64 perf_evlist__sample_type(struct perf_evlist *evlist);
-bool perf_evlist__sample_id_all(const struct perf_evlist *evlist);
+u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
+bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
 
+bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
+bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
 #endif /* __PERF_EVLIST_H */
index cca29ed..0239eb8 100644 (file)
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
 
+int __perf_evsel__sample_size(u64 sample_type)
+{
+       u64 mask = sample_type & PERF_SAMPLE_MASK;
+       int size = 0;
+       int i;
+
+       for (i = 0; i < 64; i++) {
+               if (mask & (1ULL << i))
+                       size++;
+       }
+
+       size *= sizeof(u64);
+
+       return size;
+}
+
 void perf_evsel__init(struct perf_evsel *evsel,
                      struct perf_event_attr *attr, int idx)
 {
index f79bb2c..7e9366e 100644 (file)
@@ -149,4 +149,11 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
        return __perf_evsel__read(evsel, ncpus, nthreads, true);
 }
 
+int __perf_evsel__sample_size(u64 sample_type);
+
+static inline int perf_evsel__sample_size(struct perf_evsel *evsel)
+{
+       return __perf_evsel__sample_size(evsel->attr.sample_type);
+}
+
 #endif /* __PERF_EVSEL_H */
index 69436b3..a9ac050 100644 (file)
@@ -674,7 +674,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
        struct perf_evlist *evlist = &pevlist->evlist;
        union perf_event *event;
        int sample_id_all = 1, cpu;
-       static char *kwlist[] = {"sample_id_all", NULL, NULL};
+       static char *kwlist[] = {"cpu", "sample_id_all", NULL, NULL};
        int err;
 
        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
@@ -692,16 +692,14 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
 
                first = list_entry(evlist->entries.next, struct perf_evsel, node);
                err = perf_event__parse_sample(event, first->attr.sample_type,
-                                              perf_sample_size(first->attr.sample_type),
+                                              perf_evsel__sample_size(first),
                                               sample_id_all, &pevent->sample);
-               if (err) {
-                       pr_err("Can't parse sample, err = %d\n", err);
-                       goto end;
-               }
-
+               if (err)
+                       return PyErr_Format(PyExc_OSError,
+                                           "perf: can't parse sample, err=%d", err);
                return pyevent;
        }
-end:
+
        Py_INCREF(Py_None);
        return Py_None;
 }
index 64500fc..f5a8fbd 100644 (file)
@@ -58,6 +58,16 @@ static int perf_session__open(struct perf_session *self, bool force)
                goto out_close;
        }
 
+       if (!perf_evlist__valid_sample_type(self->evlist)) {
+               pr_err("non matching sample_type");
+               goto out_close;
+       }
+
+       if (!perf_evlist__valid_sample_id_all(self->evlist)) {
+               pr_err("non matching sample_id_all");
+               goto out_close;
+       }
+
        self->size = input_stat.st_size;
        return 0;
 
@@ -97,7 +107,7 @@ out:
 void perf_session__update_sample_type(struct perf_session *self)
 {
        self->sample_type = perf_evlist__sample_type(self->evlist);
-       self->sample_size = perf_sample_size(self->sample_type);
+       self->sample_size = __perf_evsel__sample_size(self->sample_type);
        self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
        perf_session__id_header_size(self);
 }
index 22cdb96..96ebc06 100644 (file)
@@ -467,12 +467,8 @@ static struct kvm *kvm_create_vm(void)
                if (!kvm->buses[i])
                        goto out_err;
        }
-       spin_lock_init(&kvm->mmu_lock);
-
-       r = kvm_init_mmu_notifier(kvm);
-       if (r)
-               goto out_err;
 
+       spin_lock_init(&kvm->mmu_lock);
        kvm->mm = current->mm;
        atomic_inc(&kvm->mm->mm_count);
        kvm_eventfd_init(kvm);
@@ -480,6 +476,11 @@ static struct kvm *kvm_create_vm(void)
        mutex_init(&kvm->irq_lock);
        mutex_init(&kvm->slots_lock);
        atomic_set(&kvm->users_count, 1);
+
+       r = kvm_init_mmu_notifier(kvm);
+       if (r)
+               goto out_err;
+
        raw_spin_lock(&kvm_lock);
        list_add(&kvm->vm_list, &vm_list);
        raw_spin_unlock(&kvm_lock);
@@ -651,7 +652,9 @@ int __kvm_set_memory_region(struct kvm *kvm,
        /* We can read the guest memory with __xxx_user() later on. */
        if (user_alloc &&
            ((mem->userspace_addr & (PAGE_SIZE - 1)) ||
-            !access_ok(VERIFY_WRITE, mem->userspace_addr, mem->memory_size)))
+            !access_ok(VERIFY_WRITE,
+                       (void __user *)(unsigned long)mem->userspace_addr,
+                       mem->memory_size)))
                goto out;
        if (mem->slot >= KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS)
                goto out;