Merge branch 'merge' of git://git.secretlab.ca/git/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 3 Apr 2010 02:49:50 +0000 (19:49 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 3 Apr 2010 02:49:50 +0000 (19:49 -0700)
* 'merge' of git://git.secretlab.ca/git/linux-2.6:
  powerpc/5200: in lpbfifo, flag DMA irqs as enabled after requesting them
  powerpc/fsl: add device tree binding for QE firmware
  of/flattree: Fix unhandled OF_DT_NOP tag when unflattening the device tree

480 files changed:
Documentation/DMA-API-HOWTO.txt [new file with mode: 0644]
Documentation/PCI/PCI-DMA-mapping.txt [deleted file]
Documentation/cgroups/memory.txt
Documentation/circular-buffers.txt [new file with mode: 0644]
Documentation/filesystems/00-INDEX
Documentation/filesystems/ceph.txt
Documentation/filesystems/tmpfs.txt
Documentation/memory-barriers.txt
Documentation/volatile-considered-harmful.txt
MAINTAINERS
Makefile
arch/arm/common/locomo.c
arch/arm/mach-ixp23xx/include/mach/memory.h
arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
arch/arm/mach-mmp/include/mach/uncompress.h
arch/arm/mach-orion5x/wrt350n-v2-setup.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/imote2.c
arch/arm/mach-pxa/include/mach/uncompress.h
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/stargate2.c
arch/arm/tools/mach-types
arch/cris/arch-v32/drivers/pci/bios.c
arch/frv/mb93090-mb00/pci-frv.c
arch/microblaze/Kconfig
arch/microblaze/Makefile
arch/microblaze/boot/Makefile
arch/microblaze/include/asm/processor.h
arch/microblaze/include/asm/segment.h [deleted file]
arch/microblaze/include/asm/thread_info.h
arch/microblaze/include/asm/tlbflush.h
arch/microblaze/include/asm/uaccess.h
arch/microblaze/kernel/dma.c
arch/microblaze/kernel/head.S
arch/microblaze/kernel/hw_exception_handler.S
arch/microblaze/kernel/misc.S
arch/microblaze/kernel/process.c
arch/microblaze/kernel/setup.c
arch/microblaze/kernel/traps.c
arch/microblaze/lib/Makefile
arch/microblaze/lib/fastcopy.S
arch/microblaze/lib/memcpy.c
arch/microblaze/lib/memset.c
arch/microblaze/lib/uaccess.c [deleted file]
arch/microblaze/lib/uaccess_old.S
arch/microblaze/mm/fault.c
arch/microblaze/mm/init.c
arch/microblaze/mm/pgtable.c
arch/powerpc/include/asm/asm-compat.h
arch/powerpc/kernel/misc.S
arch/s390/boot/compressed/misc.c
arch/s390/include/asm/system.h
arch/s390/kernel/head.S
arch/s390/kernel/head64.S
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/mm/maccess.c
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-se/7724/setup.c
arch/sh/configs/ecovec24_defconfig
arch/sh/include/asm/elf.h
arch/sh/include/cpu-sh4/cpu/mmu_context.h
arch/sh/include/cpu-sh4/cpu/watchdog.h
arch/sh/kernel/cpufreq.c
arch/sh/kernel/dwarf.c
arch/sh/kernel/idle.c
arch/sh/kernel/perf_event.c
arch/sh/kernel/process_64.c
arch/sh/kernel/return_address.c
arch/sh/kernel/smp.c
arch/sh/mm/pmb.c
arch/sh/mm/tlb-pteaex.c
arch/sh/mm/tlb-sh3.c
arch/sh/mm/tlb-sh4.c
arch/sh/mm/tlb-urb.c
arch/sh/mm/tlbflush_32.c
arch/sparc/include/asm/stat.h
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/sysfs.c
arch/sparc/kernel/us2e_cpufreq.c
arch/sparc/kernel/us3_cpufreq.c
arch/x86/include/asm/fixmap.h
arch/x86/include/asm/hw_irq.h
arch/x86/include/asm/msr-index.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/head32.c
arch/x86/kernel/head64.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/process.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/mm/init.c
arch/x86/pci/acpi.c
arch/x86/pci/i386.c
drivers/acpi/scan.c
drivers/ata/libata-sff.c
drivers/ata/pata_via.c
drivers/base/power/main.c
drivers/char/agp/intel-agp.c
drivers/char/tty_io.c
drivers/char/virtio_console.c
drivers/edac/edac_mce_amd.c
drivers/firewire/core-device.c
drivers/firewire/core-iso.c
drivers/firewire/ohci.c
drivers/gpio/max730x.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bios.h
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_dma.c
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_irq.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv04_crtc.c
drivers/gpu/drm/nouveau/nv04_fbcon.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_fb.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nv50_fbcon.c
drivers/gpu/drm/nouveau/nv50_graph.c
drivers/gpu/drm/nouveau/nv50_grctx.c
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/atom.c
drivers/gpu/drm/radeon/atom.h
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r200.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_audio.c
drivers/gpu/drm/radeon/r600_blit_shaders.c
drivers/gpu/drm/radeon/r600_cp.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/r600_reg.h
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_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_drv.h
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_legacy_tv.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_reg.h
drivers/gpu/drm/radeon/reg_srcs/r600
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs600d.h
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rs690d.h
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_memory.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/vmwgfx/Kconfig
drivers/hid/hid-gyration.c
drivers/hid/usbhid/hid-quirks.c
drivers/hwmon/Kconfig
drivers/hwmon/coretemp.c
drivers/hwmon/w83793.c
drivers/i2c/busses/i2c-scmi.c
drivers/ide/ide-probe.c
drivers/ide/via82cxxx.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/teles_cs.c
drivers/misc/c2port/core.c
drivers/misc/kgdbts.c
drivers/mmc/core/mmc.c
drivers/net/arm/ks8695net.c
drivers/net/atlx/atl1.c
drivers/net/benet/be_ethtool.c
drivers/net/bnx2.c
drivers/net/bonding/bond_main.c
drivers/net/can/bfin_can.c
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_main.c
drivers/net/e1000e/e1000.h
drivers/net/e1000e/netdev.c
drivers/net/gianfar.c
drivers/net/gianfar.h
drivers/net/igb/e1000_82575.c
drivers/net/igb/e1000_hw.h
drivers/net/igb/e1000_mac.c
drivers/net/igb/igb.h
drivers/net/igb/igb_main.c
drivers/net/igbvf/igbvf.h
drivers/net/igbvf/netdev.c
drivers/net/ixgbe/ixgbe.h
drivers/net/ixgbe/ixgbe_82599.c
drivers/net/ixgbe/ixgbe_ethtool.c
drivers/net/ixgbe/ixgbe_fcoe.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_type.h
drivers/net/ixgbevf/ethtool.c
drivers/net/ixgbevf/ixgbevf_main.c
drivers/net/ixgbevf/vf.h
drivers/net/jme.c
drivers/net/jme.h
drivers/net/ks8851.c
drivers/net/ksz884x.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_ctx.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/r8169.c
drivers/net/tulip/uli526x.c
drivers/net/usb/smsc95xx.c
drivers/net/via-velocity.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/wl12xx/wl1251_debugfs.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/ioapic.c
drivers/pci/pci.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/setup-res.c
drivers/pcmcia/at91_cf.c
drivers/pcmcia/au1000_generic.c
drivers/pcmcia/bfin_cf_pcmcia.c
drivers/pcmcia/cs.c
drivers/pcmcia/db1xxx_ss.c
drivers/pcmcia/ds.c
drivers/pcmcia/i82092.c
drivers/pcmcia/i82365.c
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m32r_pcc.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/omap_cf.c
drivers/pcmcia/pd6729.c
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/rsrc_nonstatic.c
drivers/pcmcia/sa1100_generic.c
drivers/pcmcia/sa1111_generic.c
drivers/pcmcia/tcic.c
drivers/pcmcia/vrc4171_card.c
drivers/pcmcia/yenta_socket.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/eeepc-wmi.c [new file with mode: 0644]
drivers/regulator/core.c
drivers/regulator/lp3971.c
drivers/regulator/max1586.c
drivers/regulator/max8649.c
drivers/regulator/max8660.c
drivers/regulator/max8925-regulator.c
drivers/rtc/rtc-mc13783.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_eckd.c
drivers/s390/char/sclp_async.c
drivers/s390/char/sclp_cmd.c
drivers/s390/char/zcore.c
drivers/serial/serial_cs.c
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
drivers/staging/et131x/et1310_mac.c
drivers/usb/gadget/r8a66597-udc.c
drivers/vhost/net.c
drivers/vhost/vhost.c
drivers/video/geode/lxfb.h
drivers/video/geode/lxfb_ops.c
drivers/video/omap2/displays/panel-generic.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/vram.c
drivers/video/pxa168fb.c
fs/afs/security.c
fs/binfmt_aout.c
fs/binfmt_elf_fdpic.c
fs/ceph/addr.c
fs/ceph/auth_x.c
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/messenger.c
fs/ceph/messenger.h
fs/ceph/osd_client.c
fs/ceph/osd_client.h
fs/ceph/osdmap.c
fs/ceph/snap.c
fs/ext3/ialloc.c
fs/ext3/inode.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/super.c
fs/fat/namei_vfat.c
fs/fscache/object.c
fs/fscache/operation.c
fs/fscache/page.c
fs/logfs/dev_bdev.c
fs/logfs/dir.c
fs/logfs/journal.c
fs/logfs/logfs.h
fs/logfs/readwrite.c
fs/logfs/segment.c
fs/logfs/super.c
fs/namei.c
fs/nfs/file.c
fs/nfs/nfs4xdr.c
fs/nilfs2/segbuf.c
fs/nilfs2/segment.c
fs/ocfs2/acl.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/inode.c
fs/ocfs2/localalloc.c
fs/ocfs2/locks.c
fs/ocfs2/namei.c
fs/ocfs2/ocfs2.h
fs/ocfs2/refcounttree.c
fs/ocfs2/suballoc.c
fs/ocfs2/suballoc.h
fs/ocfs2/xattr.c
fs/partitions/msdos.c
fs/proc/base.c
fs/proc/kcore.c
fs/read_write.c
fs/reiserfs/journal.c
fs/reiserfs/super.c
fs/reiserfs/xattr_security.c
include/acpi/acpi_drivers.h
include/drm/drmP.h
include/drm/drm_mem_util.h [new file with mode: 0644]
include/drm/drm_pciids.h
include/drm/ttm/ttm_bo_driver.h
include/linux/circ_buf.h
include/linux/clockchips.h
include/linux/ext3_fs.h
include/linux/ext3_fs_i.h
include/linux/freezer.h
include/linux/fscache-cache.h
include/linux/if_tunnel.h
include/linux/ioport.h
include/linux/kfifo.h
include/linux/mmc/mmc.h
include/linux/netdevice.h
include/linux/netfilter/nfnetlink.h
include/linux/netfilter_ipv6.h
include/linux/netlink.h
include/linux/rcupdate.h
include/linux/reiserfs_xattr.h
include/linux/skbuff.h
include/linux/socket.h
include/linux/sunrpc/bc_xprt.h
include/linux/syscalls.h
include/linux/tracepoint.h
include/net/bluetooth/bluetooth.h
include/net/netlink.h
include/pcmcia/ss.h
init/main.c
ipc/syscall.c
kernel/cgroup.c
kernel/cgroup_freezer.c
kernel/cpuset.c
kernel/cred.c
kernel/early_res.c
kernel/irq/chip.c
kernel/irq/manage.c
kernel/kgdb.c
kernel/kthread.c
kernel/posix-cpu-timers.c
kernel/power/process.c
kernel/rcupdate.c
kernel/resource.c
kernel/sched.c
kernel/slow-work.c
kernel/slow-work.h
kernel/softlockup.c
kernel/time/tick-oneshot.c
kernel/time/timekeeping.c
kernel/time/timer_list.c
kernel/timer.c
kernel/trace/ring_buffer.c
lib/Kconfig.debug
mm/bootmem.c
mm/ksm.c
mm/memcontrol.c
mm/memory.c
mm/mempolicy.c
mm/mmu_context.c
mm/nommu.c
net/8021q/vlan.c
net/8021q/vlan_core.c
net/8021q/vlan_dev.c
net/bluetooth/hci_sysfs.c
net/bluetooth/l2cap.c
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c
net/core/dev.c
net/core/netpoll.c
net/ipv4/devinet.c
net/ipv4/fib_trie.c
net/ipv4/ip_gre.c
net/ipv4/ipmr.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv6/addrconf.c
net/ipv6/ip6mr.c
net/ipv6/netfilter/ip6table_raw.c
net/ipv6/route.c
net/key/af_key.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nfnetlink.c
net/netfilter/xt_hashlimit.c
net/netfilter/xt_recent.c
net/netlink/af_netlink.c
net/rxrpc/ar-accept.c
net/sched/Kconfig
net/sched/cls_cgroup.c
net/socket.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/bc_svc.c
net/sunrpc/clnt.c
net/sunrpc/rpc_pipe.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c
scripts/get_maintainer.pl
scripts/kernel-doc
sound/arm/pxa2xx-pcm-lib.c
sound/core/pcm_lib.c
sound/oss/vidc.c
sound/pci/ac97/ac97_patch.c
sound/pci/cmipci.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_nvhdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/codecs/tlv320dac33.c
sound/soc/codecs/wm_hubs.c
sound/soc/imx/Kconfig
sound/soc/sh/Kconfig
tools/perf/builtin-probe.c
tools/perf/builtin-top.c
tools/perf/util/probe-event.c
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h
tools/perf/util/symbol.c
tools/perf/util/symbol.h

diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt
new file mode 100644 (file)
index 0000000..52618ab
--- /dev/null
@@ -0,0 +1,758 @@
+                    Dynamic DMA mapping Guide
+                    =========================
+
+                David S. Miller <davem@redhat.com>
+                Richard Henderson <rth@cygnus.com>
+                 Jakub Jelinek <jakub@redhat.com>
+
+This is a guide to device driver writers on how to use the DMA API
+with example pseudo-code.  For a concise description of the API, see
+DMA-API.txt.
+
+Most of the 64bit platforms have special hardware that translates bus
+addresses (DMA addresses) into physical addresses.  This is similar to
+how page tables and/or a TLB translates virtual addresses to physical
+addresses on a CPU.  This is needed so that e.g. PCI devices can
+access with a Single Address Cycle (32bit DMA address) any page in the
+64bit physical address space.  Previously in Linux those 64bit
+platforms had to set artificial limits on the maximum RAM size in the
+system, so that the virt_to_bus() static scheme works (the DMA address
+translation tables were simply filled on bootup to map each bus
+address to the physical page __pa(bus_to_virt())).
+
+So that Linux can use the dynamic DMA mapping, it needs some help from the
+drivers, namely it has to take into account that DMA addresses should be
+mapped only for the time they are actually used and unmapped after the DMA
+transfer.
+
+The following API will work of course even on platforms where no such
+hardware exists.
+
+Note that the DMA API works with any bus independent of the underlying
+microprocessor architecture. You should use the DMA API rather than
+the bus specific DMA API (e.g. pci_dma_*).
+
+First of all, you should make sure
+
+#include <linux/dma-mapping.h>
+
+is in your driver. This file will obtain for you the definition of the
+dma_addr_t (which can hold any valid DMA address for the platform)
+type which should be used everywhere you hold a DMA (bus) address
+returned from the DMA mapping functions.
+
+                        What memory is DMA'able?
+
+The first piece of information you must know is what kernel memory can
+be used with the DMA mapping facilities.  There has been an unwritten
+set of rules regarding this, and this text is an attempt to finally
+write them down.
+
+If you acquired your memory via the page allocator
+(i.e. __get_free_page*()) or the generic memory allocators
+(i.e. kmalloc() or kmem_cache_alloc()) then you may DMA to/from
+that memory using the addresses returned from those routines.
+
+This means specifically that you may _not_ use the memory/addresses
+returned from vmalloc() for DMA.  It is possible to DMA to the
+_underlying_ memory mapped into a vmalloc() area, but this requires
+walking page tables to get the physical addresses, and then
+translating each of those pages back to a kernel address using
+something like __va().  [ EDIT: Update this when we integrate
+Gerd Knorr's generic code which does this. ]
+
+This rule also means that you may use neither kernel image addresses
+(items in data/text/bss segments), nor module image addresses, nor
+stack addresses for DMA.  These could all be mapped somewhere entirely
+different than the rest of physical memory.  Even if those classes of
+memory could physically work with DMA, you'd need to ensure the I/O
+buffers were cacheline-aligned.  Without that, you'd see cacheline
+sharing problems (data corruption) on CPUs with DMA-incoherent caches.
+(The CPU could write to one word, DMA would write to a different one
+in the same cache line, and one of them could be overwritten.)
+
+Also, this means that you cannot take the return of a kmap()
+call and DMA to/from that.  This is similar to vmalloc().
+
+What about block I/O and networking buffers?  The block I/O and
+networking subsystems make sure that the buffers they use are valid
+for you to DMA from/to.
+
+                       DMA addressing limitations
+
+Does your device have any DMA addressing limitations?  For example, is
+your device only capable of driving the low order 24-bits of address?
+If so, you need to inform the kernel of this fact.
+
+By default, the kernel assumes that your device can address the full
+32-bits.  For a 64-bit capable device, this needs to be increased.
+And for a device with limitations, as discussed in the previous
+paragraph, it needs to be decreased.
+
+Special note about PCI: PCI-X specification requires PCI-X devices to
+support 64-bit addressing (DAC) for all transactions.  And at least
+one platform (SGI SN2) requires 64-bit consistent allocations to
+operate correctly when the IO bus is in PCI-X mode.
+
+For correct operation, you must interrogate the kernel in your device
+probe routine to see if the DMA controller on the machine can properly
+support the DMA addressing limitation your device has.  It is good
+style to do this even if your device holds the default setting,
+because this shows that you did think about these issues wrt. your
+device.
+
+The query is performed via a call to dma_set_mask():
+
+       int dma_set_mask(struct device *dev, u64 mask);
+
+The query for consistent allocations is performed via a call to
+dma_set_coherent_mask():
+
+       int dma_set_coherent_mask(struct device *dev, u64 mask);
+
+Here, dev is a pointer to the device struct of your device, and mask
+is a bit mask describing which bits of an address your device
+supports.  It returns zero if your card can perform DMA properly on
+the machine given the address mask you provided.  In general, the
+device struct of your device is embedded in the bus specific device
+struct of your device.  For example, a pointer to the device struct of
+your PCI device is pdev->dev (pdev is a pointer to the PCI device
+struct of your device).
+
+If it returns non-zero, your device cannot perform DMA properly on
+this platform, and attempting to do so will result in undefined
+behavior.  You must either use a different mask, or not use DMA.
+
+This means that in the failure case, you have three options:
+
+1) Use another DMA mask, if possible (see below).
+2) Use some non-DMA mode for data transfer, if possible.
+3) Ignore this device and do not initialize it.
+
+It is recommended that your driver print a kernel KERN_WARNING message
+when you end up performing either #2 or #3.  In this manner, if a user
+of your driver reports that performance is bad or that the device is not
+even detected, you can ask them for the kernel messages to find out
+exactly why.
+
+The standard 32-bit addressing device would do something like this:
+
+       if (dma_set_mask(dev, DMA_BIT_MASK(32))) {
+               printk(KERN_WARNING
+                      "mydev: No suitable DMA available.\n");
+               goto ignore_this_device;
+       }
+
+Another common scenario is a 64-bit capable device.  The approach here
+is to try for 64-bit addressing, but back down to a 32-bit mask that
+should not fail.  The kernel may fail the 64-bit mask not because the
+platform is not capable of 64-bit addressing.  Rather, it may fail in
+this case simply because 32-bit addressing is done more efficiently
+than 64-bit addressing.  For example, Sparc64 PCI SAC addressing is
+more efficient than DAC addressing.
+
+Here is how you would handle a 64-bit capable device which can drive
+all 64-bits when accessing streaming DMA:
+
+       int using_dac;
+
+       if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
+               using_dac = 1;
+       } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
+               using_dac = 0;
+       } else {
+               printk(KERN_WARNING
+                      "mydev: No suitable DMA available.\n");
+               goto ignore_this_device;
+       }
+
+If a card is capable of using 64-bit consistent allocations as well,
+the case would look like this:
+
+       int using_dac, consistent_using_dac;
+
+       if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
+               using_dac = 1;
+               consistent_using_dac = 1;
+               dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
+       } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
+               using_dac = 0;
+               consistent_using_dac = 0;
+               dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+       } else {
+               printk(KERN_WARNING
+                      "mydev: No suitable DMA available.\n");
+               goto ignore_this_device;
+       }
+
+dma_set_coherent_mask() will always be able to set the same or a
+smaller mask as dma_set_mask(). However for the rare case that a
+device driver only uses consistent allocations, one would have to
+check the return value from dma_set_coherent_mask().
+
+Finally, if your device can only drive the low 24-bits of
+address you might do something like:
+
+       if (dma_set_mask(dev, DMA_BIT_MASK(24))) {
+               printk(KERN_WARNING
+                      "mydev: 24-bit DMA addressing not available.\n");
+               goto ignore_this_device;
+       }
+
+When dma_set_mask() is successful, and returns zero, the kernel saves
+away this mask you have provided.  The kernel will use this
+information later when you make DMA mappings.
+
+There is a case which we are aware of at this time, which is worth
+mentioning in this documentation.  If your device supports multiple
+functions (for example a sound card provides playback and record
+functions) and the various different functions have _different_
+DMA addressing limitations, you may wish to probe each mask and
+only provide the functionality which the machine can handle.  It
+is important that the last call to dma_set_mask() be for the
+most specific mask.
+
+Here is pseudo-code showing how this might be done:
+
+       #define PLAYBACK_ADDRESS_BITS   DMA_BIT_MASK(32)
+       #define RECORD_ADDRESS_BITS     DMA_BIT_MASK(24)
+
+       struct my_sound_card *card;
+       struct device *dev;
+
+       ...
+       if (!dma_set_mask(dev, PLAYBACK_ADDRESS_BITS)) {
+               card->playback_enabled = 1;
+       } else {
+               card->playback_enabled = 0;
+               printk(KERN_WARNING "%s: Playback disabled due to DMA limitations.\n",
+                      card->name);
+       }
+       if (!dma_set_mask(dev, RECORD_ADDRESS_BITS)) {
+               card->record_enabled = 1;
+       } else {
+               card->record_enabled = 0;
+               printk(KERN_WARNING "%s: Record disabled due to DMA limitations.\n",
+                      card->name);
+       }
+
+A sound card was used as an example here because this genre of PCI
+devices seems to be littered with ISA chips given a PCI front end,
+and thus retaining the 16MB DMA addressing limitations of ISA.
+
+                       Types of DMA mappings
+
+There are two types of DMA mappings:
+
+- Consistent DMA mappings which are usually mapped at driver
+  initialization, unmapped at the end and for which the hardware should
+  guarantee that the device and the CPU can access the data
+  in parallel and will see updates made by each other without any
+  explicit software flushing.
+
+  Think of "consistent" as "synchronous" or "coherent".
+
+  The current default is to return consistent memory in the low 32
+  bits of the bus space.  However, for future compatibility you should
+  set the consistent mask even if this default is fine for your
+  driver.
+
+  Good examples of what to use consistent mappings for are:
+
+       - Network card DMA ring descriptors.
+       - SCSI adapter mailbox command data structures.
+       - Device firmware microcode executed out of
+         main memory.
+
+  The invariant these examples all require is that any CPU store
+  to memory is immediately visible to the device, and vice
+  versa.  Consistent mappings guarantee this.
+
+  IMPORTANT: Consistent DMA memory does not preclude the usage of
+             proper memory barriers.  The CPU may reorder stores to
+            consistent memory just as it may normal memory.  Example:
+            if it is important for the device to see the first word
+            of a descriptor updated before the second, you must do
+            something like:
+
+               desc->word0 = address;
+               wmb();
+               desc->word1 = DESC_VALID;
+
+             in order to get correct behavior on all platforms.
+
+            Also, on some platforms your driver may need to flush CPU write
+            buffers in much the same way as it needs to flush write buffers
+            found in PCI bridges (such as by reading a register's value
+            after writing it).
+
+- Streaming DMA mappings which are usually mapped for one DMA
+  transfer, unmapped right after it (unless you use dma_sync_* below)
+  and for which hardware can optimize for sequential accesses.
+
+  This of "streaming" as "asynchronous" or "outside the coherency
+  domain".
+
+  Good examples of what to use streaming mappings for are:
+
+       - Networking buffers transmitted/received by a device.
+       - Filesystem buffers written/read by a SCSI device.
+
+  The interfaces for using this type of mapping were designed in
+  such a way that an implementation can make whatever performance
+  optimizations the hardware allows.  To this end, when using
+  such mappings you must be explicit about what you want to happen.
+
+Neither type of DMA mapping has alignment restrictions that come from
+the underlying bus, although some devices may have such restrictions.
+Also, systems with caches that aren't DMA-coherent will work better
+when the underlying buffers don't share cache lines with other data.
+
+
+                Using Consistent DMA mappings.
+
+To allocate and map large (PAGE_SIZE or so) consistent DMA regions,
+you should do:
+
+       dma_addr_t dma_handle;
+
+       cpu_addr = dma_alloc_coherent(dev, size, &dma_handle, gfp);
+
+where device is a struct device *. This may be called in interrupt
+context with the GFP_ATOMIC flag.
+
+Size is the length of the region you want to allocate, in bytes.
+
+This routine will allocate RAM for that region, so it acts similarly to
+__get_free_pages (but takes size instead of a page order).  If your
+driver needs regions sized smaller than a page, you may prefer using
+the dma_pool interface, described below.
+
+The consistent DMA mapping interfaces, for non-NULL dev, will by
+default return a DMA address which is 32-bit addressable.  Even if the
+device indicates (via DMA mask) that it may address the upper 32-bits,
+consistent allocation will only return > 32-bit addresses for DMA if
+the consistent DMA mask has been explicitly changed via
+dma_set_coherent_mask().  This is true of the dma_pool interface as
+well.
+
+dma_alloc_coherent returns two values: the virtual address which you
+can use to access it from the CPU and dma_handle which you pass to the
+card.
+
+The cpu return address and the DMA bus master address are both
+guaranteed to be aligned to the smallest PAGE_SIZE order which
+is greater than or equal to the requested size.  This invariant
+exists (for example) to guarantee that if you allocate a chunk
+which is smaller than or equal to 64 kilobytes, the extent of the
+buffer you receive will not cross a 64K boundary.
+
+To unmap and free such a DMA region, you call:
+
+       dma_free_coherent(dev, size, cpu_addr, dma_handle);
+
+where dev, size are the same as in the above call and cpu_addr and
+dma_handle are the values dma_alloc_coherent returned to you.
+This function may not be called in interrupt context.
+
+If your driver needs lots of smaller memory regions, you can write
+custom code to subdivide pages returned by dma_alloc_coherent,
+or you can use the dma_pool API to do that.  A dma_pool is like
+a kmem_cache, but it uses dma_alloc_coherent not __get_free_pages.
+Also, it understands common hardware constraints for alignment,
+like queue heads needing to be aligned on N byte boundaries.
+
+Create a dma_pool like this:
+
+       struct dma_pool *pool;
+
+       pool = dma_pool_create(name, dev, size, align, alloc);
+
+The "name" is for diagnostics (like a kmem_cache name); dev and size
+are as above.  The device's hardware alignment requirement for this
+type of data is "align" (which is expressed in bytes, and must be a
+power of two).  If your device has no boundary crossing restrictions,
+pass 0 for alloc; passing 4096 says memory allocated from this pool
+must not cross 4KByte boundaries (but at that time it may be better to
+go for dma_alloc_coherent directly instead).
+
+Allocate memory from a dma pool like this:
+
+       cpu_addr = dma_pool_alloc(pool, flags, &dma_handle);
+
+flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor
+holding SMP locks), SLAB_ATOMIC otherwise.  Like dma_alloc_coherent,
+this returns two values, cpu_addr and dma_handle.
+
+Free memory that was allocated from a dma_pool like this:
+
+       dma_pool_free(pool, cpu_addr, dma_handle);
+
+where pool is what you passed to dma_pool_alloc, and cpu_addr and
+dma_handle are the values dma_pool_alloc returned. This function
+may be called in interrupt context.
+
+Destroy a dma_pool by calling:
+
+       dma_pool_destroy(pool);
+
+Make sure you've called dma_pool_free for all memory allocated
+from a pool before you destroy the pool. This function may not
+be called in interrupt context.
+
+                       DMA Direction
+
+The interfaces described in subsequent portions of this document
+take a DMA direction argument, which is an integer and takes on
+one of the following values:
+
+ DMA_BIDIRECTIONAL
+ DMA_TO_DEVICE
+ DMA_FROM_DEVICE
+ DMA_NONE
+
+One should provide the exact DMA direction if you know it.
+
+DMA_TO_DEVICE means "from main memory to the device"
+DMA_FROM_DEVICE means "from the device to main memory"
+It is the direction in which the data moves during the DMA
+transfer.
+
+You are _strongly_ encouraged to specify this as precisely
+as you possibly can.
+
+If you absolutely cannot know the direction of the DMA transfer,
+specify DMA_BIDIRECTIONAL.  It means that the DMA can go in
+either direction.  The platform guarantees that you may legally
+specify this, and that it will work, but this may be at the
+cost of performance for example.
+
+The value DMA_NONE is to be used for debugging.  One can
+hold this in a data structure before you come to know the
+precise direction, and this will help catch cases where your
+direction tracking logic has failed to set things up properly.
+
+Another advantage of specifying this value precisely (outside of
+potential platform-specific optimizations of such) is for debugging.
+Some platforms actually have a write permission boolean which DMA
+mappings can be marked with, much like page protections in the user
+program address space.  Such platforms can and do report errors in the
+kernel logs when the DMA controller hardware detects violation of the
+permission setting.
+
+Only streaming mappings specify a direction, consistent mappings
+implicitly have a direction attribute setting of
+DMA_BIDIRECTIONAL.
+
+The SCSI subsystem tells you the direction to use in the
+'sc_data_direction' member of the SCSI command your driver is
+working on.
+
+For Networking drivers, it's a rather simple affair.  For transmit
+packets, map/unmap them with the DMA_TO_DEVICE direction
+specifier.  For receive packets, just the opposite, map/unmap them
+with the DMA_FROM_DEVICE direction specifier.
+
+                 Using Streaming DMA mappings
+
+The streaming DMA mapping routines can be called from interrupt
+context.  There are two versions of each map/unmap, one which will
+map/unmap a single memory region, and one which will map/unmap a
+scatterlist.
+
+To map a single region, you do:
+
+       struct device *dev = &my_dev->dev;
+       dma_addr_t dma_handle;
+       void *addr = buffer->ptr;
+       size_t size = buffer->len;
+
+       dma_handle = dma_map_single(dev, addr, size, direction);
+
+and to unmap it:
+
+       dma_unmap_single(dev, dma_handle, size, direction);
+
+You should call dma_unmap_single when the DMA activity is finished, e.g.
+from the interrupt which told you that the DMA transfer is done.
+
+Using cpu pointers like this for single mappings has a disadvantage,
+you cannot reference HIGHMEM memory in this way.  Thus, there is a
+map/unmap interface pair akin to dma_{map,unmap}_single.  These
+interfaces deal with page/offset pairs instead of cpu pointers.
+Specifically:
+
+       struct device *dev = &my_dev->dev;
+       dma_addr_t dma_handle;
+       struct page *page = buffer->page;
+       unsigned long offset = buffer->offset;
+       size_t size = buffer->len;
+
+       dma_handle = dma_map_page(dev, page, offset, size, direction);
+
+       ...
+
+       dma_unmap_page(dev, dma_handle, size, direction);
+
+Here, "offset" means byte offset within the given page.
+
+With scatterlists, you map a region gathered from several regions by:
+
+       int i, count = dma_map_sg(dev, sglist, nents, direction);
+       struct scatterlist *sg;
+
+       for_each_sg(sglist, sg, count, i) {
+               hw_address[i] = sg_dma_address(sg);
+               hw_len[i] = sg_dma_len(sg);
+       }
+
+where nents is the number of entries in the sglist.
+
+The implementation is free to merge several consecutive sglist entries
+into one (e.g. if DMA mapping is done with PAGE_SIZE granularity, any
+consecutive sglist entries can be merged into one provided the first one
+ends and the second one starts on a page boundary - in fact this is a huge
+advantage for cards which either cannot do scatter-gather or have very
+limited number of scatter-gather entries) and returns the actual number
+of sg entries it mapped them to. On failure 0 is returned.
+
+Then you should loop count times (note: this can be less than nents times)
+and use sg_dma_address() and sg_dma_len() macros where you previously
+accessed sg->address and sg->length as shown above.
+
+To unmap a scatterlist, just call:
+
+       dma_unmap_sg(dev, sglist, nents, direction);
+
+Again, make sure DMA activity has already finished.
+
+PLEASE NOTE:  The 'nents' argument to the dma_unmap_sg call must be
+              the _same_ one you passed into the dma_map_sg call,
+             it should _NOT_ be the 'count' value _returned_ from the
+              dma_map_sg call.
+
+Every dma_map_{single,sg} call should have its dma_unmap_{single,sg}
+counterpart, because the bus address space is a shared resource (although
+in some ports the mapping is per each BUS so less devices contend for the
+same bus address space) and you could render the machine unusable by eating
+all bus addresses.
+
+If you need to use the same streaming DMA region multiple times and touch
+the data in between the DMA transfers, the buffer needs to be synced
+properly in order for the cpu and device to see the most uptodate and
+correct copy of the DMA buffer.
+
+So, firstly, just map it with dma_map_{single,sg}, and after each DMA
+transfer call either:
+
+       dma_sync_single_for_cpu(dev, dma_handle, size, direction);
+
+or:
+
+       dma_sync_sg_for_cpu(dev, sglist, nents, direction);
+
+as appropriate.
+
+Then, if you wish to let the device get at the DMA area again,
+finish accessing the data with the cpu, and then before actually
+giving the buffer to the hardware call either:
+
+       dma_sync_single_for_device(dev, dma_handle, size, direction);
+
+or:
+
+       dma_sync_sg_for_device(dev, sglist, nents, direction);
+
+as appropriate.
+
+After the last DMA transfer call one of the DMA unmap routines
+dma_unmap_{single,sg}. If you don't touch the data from the first dma_map_*
+call till dma_unmap_*, then you don't have to call the dma_sync_*
+routines at all.
+
+Here is pseudo code which shows a situation in which you would need
+to use the dma_sync_*() interfaces.
+
+       my_card_setup_receive_buffer(struct my_card *cp, char *buffer, int len)
+       {
+               dma_addr_t mapping;
+
+               mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE);
+
+               cp->rx_buf = buffer;
+               cp->rx_len = len;
+               cp->rx_dma = mapping;
+
+               give_rx_buf_to_card(cp);
+       }
+
+       ...
+
+       my_card_interrupt_handler(int irq, void *devid, struct pt_regs *regs)
+       {
+               struct my_card *cp = devid;
+
+               ...
+               if (read_card_status(cp) == RX_BUF_TRANSFERRED) {
+                       struct my_card_header *hp;
+
+                       /* Examine the header to see if we wish
+                        * to accept the data.  But synchronize
+                        * the DMA transfer with the CPU first
+                        * so that we see updated contents.
+                        */
+                       dma_sync_single_for_cpu(&cp->dev, cp->rx_dma,
+                                               cp->rx_len,
+                                               DMA_FROM_DEVICE);
+
+                       /* Now it is safe to examine the buffer. */
+                       hp = (struct my_card_header *) cp->rx_buf;
+                       if (header_is_ok(hp)) {
+                               dma_unmap_single(&cp->dev, cp->rx_dma, cp->rx_len,
+                                                DMA_FROM_DEVICE);
+                               pass_to_upper_layers(cp->rx_buf);
+                               make_and_setup_new_rx_buf(cp);
+                       } else {
+                               /* Just sync the buffer and give it back
+                                * to the card.
+                                */
+                               dma_sync_single_for_device(&cp->dev,
+                                                          cp->rx_dma,
+                                                          cp->rx_len,
+                                                          DMA_FROM_DEVICE);
+                               give_rx_buf_to_card(cp);
+                       }
+               }
+       }
+
+Drivers converted fully to this interface should not use virt_to_bus any
+longer, nor should they use bus_to_virt. Some drivers have to be changed a
+little bit, because there is no longer an equivalent to bus_to_virt in the
+dynamic DMA mapping scheme - you have to always store the DMA addresses
+returned by the dma_alloc_coherent, dma_pool_alloc, and dma_map_single
+calls (dma_map_sg stores them in the scatterlist itself if the platform
+supports dynamic DMA mapping in hardware) in your driver structures and/or
+in the card registers.
+
+All drivers should be using these interfaces with no exceptions.  It
+is planned to completely remove virt_to_bus() and bus_to_virt() as
+they are entirely deprecated.  Some ports already do not provide these
+as it is impossible to correctly support them.
+
+               Optimizing Unmap State Space Consumption
+
+On many platforms, dma_unmap_{single,page}() is simply a nop.
+Therefore, keeping track of the mapping address and length is a waste
+of space.  Instead of filling your drivers up with ifdefs and the like
+to "work around" this (which would defeat the whole purpose of a
+portable API) the following facilities are provided.
+
+Actually, instead of describing the macros one by one, we'll
+transform some example code.
+
+1) Use DEFINE_DMA_UNMAP_{ADDR,LEN} in state saving structures.
+   Example, before:
+
+       struct ring_state {
+               struct sk_buff *skb;
+               dma_addr_t mapping;
+               __u32 len;
+       };
+
+   after:
+
+       struct ring_state {
+               struct sk_buff *skb;
+               DEFINE_DMA_UNMAP_ADDR(mapping);
+               DEFINE_DMA_UNMAP_LEN(len);
+       };
+
+2) Use dma_unmap_{addr,len}_set to set these values.
+   Example, before:
+
+       ringp->mapping = FOO;
+       ringp->len = BAR;
+
+   after:
+
+       dma_unmap_addr_set(ringp, mapping, FOO);
+       dma_unmap_len_set(ringp, len, BAR);
+
+3) Use dma_unmap_{addr,len} to access these values.
+   Example, before:
+
+       dma_unmap_single(dev, ringp->mapping, ringp->len,
+                        DMA_FROM_DEVICE);
+
+   after:
+
+       dma_unmap_single(dev,
+                        dma_unmap_addr(ringp, mapping),
+                        dma_unmap_len(ringp, len),
+                        DMA_FROM_DEVICE);
+
+It really should be self-explanatory.  We treat the ADDR and LEN
+separately, because it is possible for an implementation to only
+need the address in order to perform the unmap operation.
+
+                       Platform Issues
+
+If you are just writing drivers for Linux and do not maintain
+an architecture port for the kernel, you can safely skip down
+to "Closing".
+
+1) Struct scatterlist requirements.
+
+   Struct scatterlist must contain, at a minimum, the following
+   members:
+
+       struct page *page;
+       unsigned int offset;
+       unsigned int length;
+
+   The base address is specified by a "page+offset" pair.
+
+   Previous versions of struct scatterlist contained a "void *address"
+   field that was sometimes used instead of page+offset.  As of Linux
+   2.5., page+offset is always used, and the "address" field has been
+   deleted.
+
+2) More to come...
+
+                       Handling Errors
+
+DMA address space is limited on some architectures and an allocation
+failure can be determined by:
+
+- checking if dma_alloc_coherent returns NULL or dma_map_sg returns 0
+
+- checking the returned dma_addr_t of dma_map_single and dma_map_page
+  by using dma_mapping_error():
+
+       dma_addr_t dma_handle;
+
+       dma_handle = dma_map_single(dev, addr, size, direction);
+       if (dma_mapping_error(dev, dma_handle)) {
+               /*
+                * reduce current DMA mapping usage,
+                * delay and try again later or
+                * reset driver.
+                */
+       }
+
+                          Closing
+
+This document, and the API itself, would not be in it's current
+form without the feedback and suggestions from numerous individuals.
+We would like to specifically mention, in no particular order, the
+following people:
+
+       Russell King <rmk@arm.linux.org.uk>
+       Leo Dagum <dagum@barrel.engr.sgi.com>
+       Ralf Baechle <ralf@oss.sgi.com>
+       Grant Grundler <grundler@cup.hp.com>
+       Jay Estabrook <Jay.Estabrook@compaq.com>
+       Thomas Sailer <sailer@ife.ee.ethz.ch>
+       Andrea Arcangeli <andrea@suse.de>
+       Jens Axboe <jens.axboe@oracle.com>
+       David Mosberger-Tang <davidm@hpl.hp.com>
diff --git a/Documentation/PCI/PCI-DMA-mapping.txt b/Documentation/PCI/PCI-DMA-mapping.txt
deleted file mode 100644 (file)
index 52618ab..0000000
+++ /dev/null
@@ -1,758 +0,0 @@
-                    Dynamic DMA mapping Guide
-                    =========================
-
-                David S. Miller <davem@redhat.com>
-                Richard Henderson <rth@cygnus.com>
-                 Jakub Jelinek <jakub@redhat.com>
-
-This is a guide to device driver writers on how to use the DMA API
-with example pseudo-code.  For a concise description of the API, see
-DMA-API.txt.
-
-Most of the 64bit platforms have special hardware that translates bus
-addresses (DMA addresses) into physical addresses.  This is similar to
-how page tables and/or a TLB translates virtual addresses to physical
-addresses on a CPU.  This is needed so that e.g. PCI devices can
-access with a Single Address Cycle (32bit DMA address) any page in the
-64bit physical address space.  Previously in Linux those 64bit
-platforms had to set artificial limits on the maximum RAM size in the
-system, so that the virt_to_bus() static scheme works (the DMA address
-translation tables were simply filled on bootup to map each bus
-address to the physical page __pa(bus_to_virt())).
-
-So that Linux can use the dynamic DMA mapping, it needs some help from the
-drivers, namely it has to take into account that DMA addresses should be
-mapped only for the time they are actually used and unmapped after the DMA
-transfer.
-
-The following API will work of course even on platforms where no such
-hardware exists.
-
-Note that the DMA API works with any bus independent of the underlying
-microprocessor architecture. You should use the DMA API rather than
-the bus specific DMA API (e.g. pci_dma_*).
-
-First of all, you should make sure
-
-#include <linux/dma-mapping.h>
-
-is in your driver. This file will obtain for you the definition of the
-dma_addr_t (which can hold any valid DMA address for the platform)
-type which should be used everywhere you hold a DMA (bus) address
-returned from the DMA mapping functions.
-
-                        What memory is DMA'able?
-
-The first piece of information you must know is what kernel memory can
-be used with the DMA mapping facilities.  There has been an unwritten
-set of rules regarding this, and this text is an attempt to finally
-write them down.
-
-If you acquired your memory via the page allocator
-(i.e. __get_free_page*()) or the generic memory allocators
-(i.e. kmalloc() or kmem_cache_alloc()) then you may DMA to/from
-that memory using the addresses returned from those routines.
-
-This means specifically that you may _not_ use the memory/addresses
-returned from vmalloc() for DMA.  It is possible to DMA to the
-_underlying_ memory mapped into a vmalloc() area, but this requires
-walking page tables to get the physical addresses, and then
-translating each of those pages back to a kernel address using
-something like __va().  [ EDIT: Update this when we integrate
-Gerd Knorr's generic code which does this. ]
-
-This rule also means that you may use neither kernel image addresses
-(items in data/text/bss segments), nor module image addresses, nor
-stack addresses for DMA.  These could all be mapped somewhere entirely
-different than the rest of physical memory.  Even if those classes of
-memory could physically work with DMA, you'd need to ensure the I/O
-buffers were cacheline-aligned.  Without that, you'd see cacheline
-sharing problems (data corruption) on CPUs with DMA-incoherent caches.
-(The CPU could write to one word, DMA would write to a different one
-in the same cache line, and one of them could be overwritten.)
-
-Also, this means that you cannot take the return of a kmap()
-call and DMA to/from that.  This is similar to vmalloc().
-
-What about block I/O and networking buffers?  The block I/O and
-networking subsystems make sure that the buffers they use are valid
-for you to DMA from/to.
-
-                       DMA addressing limitations
-
-Does your device have any DMA addressing limitations?  For example, is
-your device only capable of driving the low order 24-bits of address?
-If so, you need to inform the kernel of this fact.
-
-By default, the kernel assumes that your device can address the full
-32-bits.  For a 64-bit capable device, this needs to be increased.
-And for a device with limitations, as discussed in the previous
-paragraph, it needs to be decreased.
-
-Special note about PCI: PCI-X specification requires PCI-X devices to
-support 64-bit addressing (DAC) for all transactions.  And at least
-one platform (SGI SN2) requires 64-bit consistent allocations to
-operate correctly when the IO bus is in PCI-X mode.
-
-For correct operation, you must interrogate the kernel in your device
-probe routine to see if the DMA controller on the machine can properly
-support the DMA addressing limitation your device has.  It is good
-style to do this even if your device holds the default setting,
-because this shows that you did think about these issues wrt. your
-device.
-
-The query is performed via a call to dma_set_mask():
-
-       int dma_set_mask(struct device *dev, u64 mask);
-
-The query for consistent allocations is performed via a call to
-dma_set_coherent_mask():
-
-       int dma_set_coherent_mask(struct device *dev, u64 mask);
-
-Here, dev is a pointer to the device struct of your device, and mask
-is a bit mask describing which bits of an address your device
-supports.  It returns zero if your card can perform DMA properly on
-the machine given the address mask you provided.  In general, the
-device struct of your device is embedded in the bus specific device
-struct of your device.  For example, a pointer to the device struct of
-your PCI device is pdev->dev (pdev is a pointer to the PCI device
-struct of your device).
-
-If it returns non-zero, your device cannot perform DMA properly on
-this platform, and attempting to do so will result in undefined
-behavior.  You must either use a different mask, or not use DMA.
-
-This means that in the failure case, you have three options:
-
-1) Use another DMA mask, if possible (see below).
-2) Use some non-DMA mode for data transfer, if possible.
-3) Ignore this device and do not initialize it.
-
-It is recommended that your driver print a kernel KERN_WARNING message
-when you end up performing either #2 or #3.  In this manner, if a user
-of your driver reports that performance is bad or that the device is not
-even detected, you can ask them for the kernel messages to find out
-exactly why.
-
-The standard 32-bit addressing device would do something like this:
-
-       if (dma_set_mask(dev, DMA_BIT_MASK(32))) {
-               printk(KERN_WARNING
-                      "mydev: No suitable DMA available.\n");
-               goto ignore_this_device;
-       }
-
-Another common scenario is a 64-bit capable device.  The approach here
-is to try for 64-bit addressing, but back down to a 32-bit mask that
-should not fail.  The kernel may fail the 64-bit mask not because the
-platform is not capable of 64-bit addressing.  Rather, it may fail in
-this case simply because 32-bit addressing is done more efficiently
-than 64-bit addressing.  For example, Sparc64 PCI SAC addressing is
-more efficient than DAC addressing.
-
-Here is how you would handle a 64-bit capable device which can drive
-all 64-bits when accessing streaming DMA:
-
-       int using_dac;
-
-       if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
-               using_dac = 1;
-       } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
-               using_dac = 0;
-       } else {
-               printk(KERN_WARNING
-                      "mydev: No suitable DMA available.\n");
-               goto ignore_this_device;
-       }
-
-If a card is capable of using 64-bit consistent allocations as well,
-the case would look like this:
-
-       int using_dac, consistent_using_dac;
-
-       if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
-               using_dac = 1;
-               consistent_using_dac = 1;
-               dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
-       } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
-               using_dac = 0;
-               consistent_using_dac = 0;
-               dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
-       } else {
-               printk(KERN_WARNING
-                      "mydev: No suitable DMA available.\n");
-               goto ignore_this_device;
-       }
-
-dma_set_coherent_mask() will always be able to set the same or a
-smaller mask as dma_set_mask(). However for the rare case that a
-device driver only uses consistent allocations, one would have to
-check the return value from dma_set_coherent_mask().
-
-Finally, if your device can only drive the low 24-bits of
-address you might do something like:
-
-       if (dma_set_mask(dev, DMA_BIT_MASK(24))) {
-               printk(KERN_WARNING
-                      "mydev: 24-bit DMA addressing not available.\n");
-               goto ignore_this_device;
-       }
-
-When dma_set_mask() is successful, and returns zero, the kernel saves
-away this mask you have provided.  The kernel will use this
-information later when you make DMA mappings.
-
-There is a case which we are aware of at this time, which is worth
-mentioning in this documentation.  If your device supports multiple
-functions (for example a sound card provides playback and record
-functions) and the various different functions have _different_
-DMA addressing limitations, you may wish to probe each mask and
-only provide the functionality which the machine can handle.  It
-is important that the last call to dma_set_mask() be for the
-most specific mask.
-
-Here is pseudo-code showing how this might be done:
-
-       #define PLAYBACK_ADDRESS_BITS   DMA_BIT_MASK(32)
-       #define RECORD_ADDRESS_BITS     DMA_BIT_MASK(24)
-
-       struct my_sound_card *card;
-       struct device *dev;
-
-       ...
-       if (!dma_set_mask(dev, PLAYBACK_ADDRESS_BITS)) {
-               card->playback_enabled = 1;
-       } else {
-               card->playback_enabled = 0;
-               printk(KERN_WARNING "%s: Playback disabled due to DMA limitations.\n",
-                      card->name);
-       }
-       if (!dma_set_mask(dev, RECORD_ADDRESS_BITS)) {
-               card->record_enabled = 1;
-       } else {
-               card->record_enabled = 0;
-               printk(KERN_WARNING "%s: Record disabled due to DMA limitations.\n",
-                      card->name);
-       }
-
-A sound card was used as an example here because this genre of PCI
-devices seems to be littered with ISA chips given a PCI front end,
-and thus retaining the 16MB DMA addressing limitations of ISA.
-
-                       Types of DMA mappings
-
-There are two types of DMA mappings:
-
-- Consistent DMA mappings which are usually mapped at driver
-  initialization, unmapped at the end and for which the hardware should
-  guarantee that the device and the CPU can access the data
-  in parallel and will see updates made by each other without any
-  explicit software flushing.
-
-  Think of "consistent" as "synchronous" or "coherent".
-
-  The current default is to return consistent memory in the low 32
-  bits of the bus space.  However, for future compatibility you should
-  set the consistent mask even if this default is fine for your
-  driver.
-
-  Good examples of what to use consistent mappings for are:
-
-       - Network card DMA ring descriptors.
-       - SCSI adapter mailbox command data structures.
-       - Device firmware microcode executed out of
-         main memory.
-
-  The invariant these examples all require is that any CPU store
-  to memory is immediately visible to the device, and vice
-  versa.  Consistent mappings guarantee this.
-
-  IMPORTANT: Consistent DMA memory does not preclude the usage of
-             proper memory barriers.  The CPU may reorder stores to
-            consistent memory just as it may normal memory.  Example:
-            if it is important for the device to see the first word
-            of a descriptor updated before the second, you must do
-            something like:
-
-               desc->word0 = address;
-               wmb();
-               desc->word1 = DESC_VALID;
-
-             in order to get correct behavior on all platforms.
-
-            Also, on some platforms your driver may need to flush CPU write
-            buffers in much the same way as it needs to flush write buffers
-            found in PCI bridges (such as by reading a register's value
-            after writing it).
-
-- Streaming DMA mappings which are usually mapped for one DMA
-  transfer, unmapped right after it (unless you use dma_sync_* below)
-  and for which hardware can optimize for sequential accesses.
-
-  This of "streaming" as "asynchronous" or "outside the coherency
-  domain".
-
-  Good examples of what to use streaming mappings for are:
-
-       - Networking buffers transmitted/received by a device.
-       - Filesystem buffers written/read by a SCSI device.
-
-  The interfaces for using this type of mapping were designed in
-  such a way that an implementation can make whatever performance
-  optimizations the hardware allows.  To this end, when using
-  such mappings you must be explicit about what you want to happen.
-
-Neither type of DMA mapping has alignment restrictions that come from
-the underlying bus, although some devices may have such restrictions.
-Also, systems with caches that aren't DMA-coherent will work better
-when the underlying buffers don't share cache lines with other data.
-
-
-                Using Consistent DMA mappings.
-
-To allocate and map large (PAGE_SIZE or so) consistent DMA regions,
-you should do:
-
-       dma_addr_t dma_handle;
-
-       cpu_addr = dma_alloc_coherent(dev, size, &dma_handle, gfp);
-
-where device is a struct device *. This may be called in interrupt
-context with the GFP_ATOMIC flag.
-
-Size is the length of the region you want to allocate, in bytes.
-
-This routine will allocate RAM for that region, so it acts similarly to
-__get_free_pages (but takes size instead of a page order).  If your
-driver needs regions sized smaller than a page, you may prefer using
-the dma_pool interface, described below.
-
-The consistent DMA mapping interfaces, for non-NULL dev, will by
-default return a DMA address which is 32-bit addressable.  Even if the
-device indicates (via DMA mask) that it may address the upper 32-bits,
-consistent allocation will only return > 32-bit addresses for DMA if
-the consistent DMA mask has been explicitly changed via
-dma_set_coherent_mask().  This is true of the dma_pool interface as
-well.
-
-dma_alloc_coherent returns two values: the virtual address which you
-can use to access it from the CPU and dma_handle which you pass to the
-card.
-
-The cpu return address and the DMA bus master address are both
-guaranteed to be aligned to the smallest PAGE_SIZE order which
-is greater than or equal to the requested size.  This invariant
-exists (for example) to guarantee that if you allocate a chunk
-which is smaller than or equal to 64 kilobytes, the extent of the
-buffer you receive will not cross a 64K boundary.
-
-To unmap and free such a DMA region, you call:
-
-       dma_free_coherent(dev, size, cpu_addr, dma_handle);
-
-where dev, size are the same as in the above call and cpu_addr and
-dma_handle are the values dma_alloc_coherent returned to you.
-This function may not be called in interrupt context.
-
-If your driver needs lots of smaller memory regions, you can write
-custom code to subdivide pages returned by dma_alloc_coherent,
-or you can use the dma_pool API to do that.  A dma_pool is like
-a kmem_cache, but it uses dma_alloc_coherent not __get_free_pages.
-Also, it understands common hardware constraints for alignment,
-like queue heads needing to be aligned on N byte boundaries.
-
-Create a dma_pool like this:
-
-       struct dma_pool *pool;
-
-       pool = dma_pool_create(name, dev, size, align, alloc);
-
-The "name" is for diagnostics (like a kmem_cache name); dev and size
-are as above.  The device's hardware alignment requirement for this
-type of data is "align" (which is expressed in bytes, and must be a
-power of two).  If your device has no boundary crossing restrictions,
-pass 0 for alloc; passing 4096 says memory allocated from this pool
-must not cross 4KByte boundaries (but at that time it may be better to
-go for dma_alloc_coherent directly instead).
-
-Allocate memory from a dma pool like this:
-
-       cpu_addr = dma_pool_alloc(pool, flags, &dma_handle);
-
-flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor
-holding SMP locks), SLAB_ATOMIC otherwise.  Like dma_alloc_coherent,
-this returns two values, cpu_addr and dma_handle.
-
-Free memory that was allocated from a dma_pool like this:
-
-       dma_pool_free(pool, cpu_addr, dma_handle);
-
-where pool is what you passed to dma_pool_alloc, and cpu_addr and
-dma_handle are the values dma_pool_alloc returned. This function
-may be called in interrupt context.
-
-Destroy a dma_pool by calling:
-
-       dma_pool_destroy(pool);
-
-Make sure you've called dma_pool_free for all memory allocated
-from a pool before you destroy the pool. This function may not
-be called in interrupt context.
-
-                       DMA Direction
-
-The interfaces described in subsequent portions of this document
-take a DMA direction argument, which is an integer and takes on
-one of the following values:
-
- DMA_BIDIRECTIONAL
- DMA_TO_DEVICE
- DMA_FROM_DEVICE
- DMA_NONE
-
-One should provide the exact DMA direction if you know it.
-
-DMA_TO_DEVICE means "from main memory to the device"
-DMA_FROM_DEVICE means "from the device to main memory"
-It is the direction in which the data moves during the DMA
-transfer.
-
-You are _strongly_ encouraged to specify this as precisely
-as you possibly can.
-
-If you absolutely cannot know the direction of the DMA transfer,
-specify DMA_BIDIRECTIONAL.  It means that the DMA can go in
-either direction.  The platform guarantees that you may legally
-specify this, and that it will work, but this may be at the
-cost of performance for example.
-
-The value DMA_NONE is to be used for debugging.  One can
-hold this in a data structure before you come to know the
-precise direction, and this will help catch cases where your
-direction tracking logic has failed to set things up properly.
-
-Another advantage of specifying this value precisely (outside of
-potential platform-specific optimizations of such) is for debugging.
-Some platforms actually have a write permission boolean which DMA
-mappings can be marked with, much like page protections in the user
-program address space.  Such platforms can and do report errors in the
-kernel logs when the DMA controller hardware detects violation of the
-permission setting.
-
-Only streaming mappings specify a direction, consistent mappings
-implicitly have a direction attribute setting of
-DMA_BIDIRECTIONAL.
-
-The SCSI subsystem tells you the direction to use in the
-'sc_data_direction' member of the SCSI command your driver is
-working on.
-
-For Networking drivers, it's a rather simple affair.  For transmit
-packets, map/unmap them with the DMA_TO_DEVICE direction
-specifier.  For receive packets, just the opposite, map/unmap them
-with the DMA_FROM_DEVICE direction specifier.
-
-                 Using Streaming DMA mappings
-
-The streaming DMA mapping routines can be called from interrupt
-context.  There are two versions of each map/unmap, one which will
-map/unmap a single memory region, and one which will map/unmap a
-scatterlist.
-
-To map a single region, you do:
-
-       struct device *dev = &my_dev->dev;
-       dma_addr_t dma_handle;
-       void *addr = buffer->ptr;
-       size_t size = buffer->len;
-
-       dma_handle = dma_map_single(dev, addr, size, direction);
-
-and to unmap it:
-
-       dma_unmap_single(dev, dma_handle, size, direction);
-
-You should call dma_unmap_single when the DMA activity is finished, e.g.
-from the interrupt which told you that the DMA transfer is done.
-
-Using cpu pointers like this for single mappings has a disadvantage,
-you cannot reference HIGHMEM memory in this way.  Thus, there is a
-map/unmap interface pair akin to dma_{map,unmap}_single.  These
-interfaces deal with page/offset pairs instead of cpu pointers.
-Specifically:
-
-       struct device *dev = &my_dev->dev;
-       dma_addr_t dma_handle;
-       struct page *page = buffer->page;
-       unsigned long offset = buffer->offset;
-       size_t size = buffer->len;
-
-       dma_handle = dma_map_page(dev, page, offset, size, direction);
-
-       ...
-
-       dma_unmap_page(dev, dma_handle, size, direction);
-
-Here, "offset" means byte offset within the given page.
-
-With scatterlists, you map a region gathered from several regions by:
-
-       int i, count = dma_map_sg(dev, sglist, nents, direction);
-       struct scatterlist *sg;
-
-       for_each_sg(sglist, sg, count, i) {
-               hw_address[i] = sg_dma_address(sg);
-               hw_len[i] = sg_dma_len(sg);
-       }
-
-where nents is the number of entries in the sglist.
-
-The implementation is free to merge several consecutive sglist entries
-into one (e.g. if DMA mapping is done with PAGE_SIZE granularity, any
-consecutive sglist entries can be merged into one provided the first one
-ends and the second one starts on a page boundary - in fact this is a huge
-advantage for cards which either cannot do scatter-gather or have very
-limited number of scatter-gather entries) and returns the actual number
-of sg entries it mapped them to. On failure 0 is returned.
-
-Then you should loop count times (note: this can be less than nents times)
-and use sg_dma_address() and sg_dma_len() macros where you previously
-accessed sg->address and sg->length as shown above.
-
-To unmap a scatterlist, just call:
-
-       dma_unmap_sg(dev, sglist, nents, direction);
-
-Again, make sure DMA activity has already finished.
-
-PLEASE NOTE:  The 'nents' argument to the dma_unmap_sg call must be
-              the _same_ one you passed into the dma_map_sg call,
-             it should _NOT_ be the 'count' value _returned_ from the
-              dma_map_sg call.
-
-Every dma_map_{single,sg} call should have its dma_unmap_{single,sg}
-counterpart, because the bus address space is a shared resource (although
-in some ports the mapping is per each BUS so less devices contend for the
-same bus address space) and you could render the machine unusable by eating
-all bus addresses.
-
-If you need to use the same streaming DMA region multiple times and touch
-the data in between the DMA transfers, the buffer needs to be synced
-properly in order for the cpu and device to see the most uptodate and
-correct copy of the DMA buffer.
-
-So, firstly, just map it with dma_map_{single,sg}, and after each DMA
-transfer call either:
-
-       dma_sync_single_for_cpu(dev, dma_handle, size, direction);
-
-or:
-
-       dma_sync_sg_for_cpu(dev, sglist, nents, direction);
-
-as appropriate.
-
-Then, if you wish to let the device get at the DMA area again,
-finish accessing the data with the cpu, and then before actually
-giving the buffer to the hardware call either:
-
-       dma_sync_single_for_device(dev, dma_handle, size, direction);
-
-or:
-
-       dma_sync_sg_for_device(dev, sglist, nents, direction);
-
-as appropriate.
-
-After the last DMA transfer call one of the DMA unmap routines
-dma_unmap_{single,sg}. If you don't touch the data from the first dma_map_*
-call till dma_unmap_*, then you don't have to call the dma_sync_*
-routines at all.
-
-Here is pseudo code which shows a situation in which you would need
-to use the dma_sync_*() interfaces.
-
-       my_card_setup_receive_buffer(struct my_card *cp, char *buffer, int len)
-       {
-               dma_addr_t mapping;
-
-               mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE);
-
-               cp->rx_buf = buffer;
-               cp->rx_len = len;
-               cp->rx_dma = mapping;
-
-               give_rx_buf_to_card(cp);
-       }
-
-       ...
-
-       my_card_interrupt_handler(int irq, void *devid, struct pt_regs *regs)
-       {
-               struct my_card *cp = devid;
-
-               ...
-               if (read_card_status(cp) == RX_BUF_TRANSFERRED) {
-                       struct my_card_header *hp;
-
-                       /* Examine the header to see if we wish
-                        * to accept the data.  But synchronize
-                        * the DMA transfer with the CPU first
-                        * so that we see updated contents.
-                        */
-                       dma_sync_single_for_cpu(&cp->dev, cp->rx_dma,
-                                               cp->rx_len,
-                                               DMA_FROM_DEVICE);
-
-                       /* Now it is safe to examine the buffer. */
-                       hp = (struct my_card_header *) cp->rx_buf;
-                       if (header_is_ok(hp)) {
-                               dma_unmap_single(&cp->dev, cp->rx_dma, cp->rx_len,
-                                                DMA_FROM_DEVICE);
-                               pass_to_upper_layers(cp->rx_buf);
-                               make_and_setup_new_rx_buf(cp);
-                       } else {
-                               /* Just sync the buffer and give it back
-                                * to the card.
-                                */
-                               dma_sync_single_for_device(&cp->dev,
-                                                          cp->rx_dma,
-                                                          cp->rx_len,
-                                                          DMA_FROM_DEVICE);
-                               give_rx_buf_to_card(cp);
-                       }
-               }
-       }
-
-Drivers converted fully to this interface should not use virt_to_bus any
-longer, nor should they use bus_to_virt. Some drivers have to be changed a
-little bit, because there is no longer an equivalent to bus_to_virt in the
-dynamic DMA mapping scheme - you have to always store the DMA addresses
-returned by the dma_alloc_coherent, dma_pool_alloc, and dma_map_single
-calls (dma_map_sg stores them in the scatterlist itself if the platform
-supports dynamic DMA mapping in hardware) in your driver structures and/or
-in the card registers.
-
-All drivers should be using these interfaces with no exceptions.  It
-is planned to completely remove virt_to_bus() and bus_to_virt() as
-they are entirely deprecated.  Some ports already do not provide these
-as it is impossible to correctly support them.
-
-               Optimizing Unmap State Space Consumption
-
-On many platforms, dma_unmap_{single,page}() is simply a nop.
-Therefore, keeping track of the mapping address and length is a waste
-of space.  Instead of filling your drivers up with ifdefs and the like
-to "work around" this (which would defeat the whole purpose of a
-portable API) the following facilities are provided.
-
-Actually, instead of describing the macros one by one, we'll
-transform some example code.
-
-1) Use DEFINE_DMA_UNMAP_{ADDR,LEN} in state saving structures.
-   Example, before:
-
-       struct ring_state {
-               struct sk_buff *skb;
-               dma_addr_t mapping;
-               __u32 len;
-       };
-
-   after:
-
-       struct ring_state {
-               struct sk_buff *skb;
-               DEFINE_DMA_UNMAP_ADDR(mapping);
-               DEFINE_DMA_UNMAP_LEN(len);
-       };
-
-2) Use dma_unmap_{addr,len}_set to set these values.
-   Example, before:
-
-       ringp->mapping = FOO;
-       ringp->len = BAR;
-
-   after:
-
-       dma_unmap_addr_set(ringp, mapping, FOO);
-       dma_unmap_len_set(ringp, len, BAR);
-
-3) Use dma_unmap_{addr,len} to access these values.
-   Example, before:
-
-       dma_unmap_single(dev, ringp->mapping, ringp->len,
-                        DMA_FROM_DEVICE);
-
-   after:
-
-       dma_unmap_single(dev,
-                        dma_unmap_addr(ringp, mapping),
-                        dma_unmap_len(ringp, len),
-                        DMA_FROM_DEVICE);
-
-It really should be self-explanatory.  We treat the ADDR and LEN
-separately, because it is possible for an implementation to only
-need the address in order to perform the unmap operation.
-
-                       Platform Issues
-
-If you are just writing drivers for Linux and do not maintain
-an architecture port for the kernel, you can safely skip down
-to "Closing".
-
-1) Struct scatterlist requirements.
-
-   Struct scatterlist must contain, at a minimum, the following
-   members:
-
-       struct page *page;
-       unsigned int offset;
-       unsigned int length;
-
-   The base address is specified by a "page+offset" pair.
-
-   Previous versions of struct scatterlist contained a "void *address"
-   field that was sometimes used instead of page+offset.  As of Linux
-   2.5., page+offset is always used, and the "address" field has been
-   deleted.
-
-2) More to come...
-
-                       Handling Errors
-
-DMA address space is limited on some architectures and an allocation
-failure can be determined by:
-
-- checking if dma_alloc_coherent returns NULL or dma_map_sg returns 0
-
-- checking the returned dma_addr_t of dma_map_single and dma_map_page
-  by using dma_mapping_error():
-
-       dma_addr_t dma_handle;
-
-       dma_handle = dma_map_single(dev, addr, size, direction);
-       if (dma_mapping_error(dev, dma_handle)) {
-               /*
-                * reduce current DMA mapping usage,
-                * delay and try again later or
-                * reset driver.
-                */
-       }
-
-                          Closing
-
-This document, and the API itself, would not be in it's current
-form without the feedback and suggestions from numerous individuals.
-We would like to specifically mention, in no particular order, the
-following people:
-
-       Russell King <rmk@arm.linux.org.uk>
-       Leo Dagum <dagum@barrel.engr.sgi.com>
-       Ralf Baechle <ralf@oss.sgi.com>
-       Grant Grundler <grundler@cup.hp.com>
-       Jay Estabrook <Jay.Estabrook@compaq.com>
-       Thomas Sailer <sailer@ife.ee.ethz.ch>
-       Andrea Arcangeli <andrea@suse.de>
-       Jens Axboe <jens.axboe@oracle.com>
-       David Mosberger-Tang <davidm@hpl.hp.com>
index f8bc802d70b92d05545a87974af9e2645d6af6c6..3a6aecd078ba95c4d5a58e0ffb34ba8048cc879d 100644 (file)
@@ -340,7 +340,7 @@ Note:
 5.3 swappiness
   Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
 
-  Following cgroups' swapiness can't be changed.
+  Following cgroups' swappiness can't be changed.
   - root cgroup (uses /proc/sys/vm/swappiness).
   - a cgroup which uses hierarchy and it has child cgroup.
   - a cgroup which uses hierarchy and not the root of hierarchy.
diff --git a/Documentation/circular-buffers.txt b/Documentation/circular-buffers.txt
new file mode 100644 (file)
index 0000000..8117e5b
--- /dev/null
@@ -0,0 +1,234 @@
+                              ================
+                              CIRCULAR BUFFERS
+                              ================
+
+By: David Howells <dhowells@redhat.com>
+    Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+
+Linux provides a number of features that can be used to implement circular
+buffering.  There are two sets of such features:
+
+ (1) Convenience functions for determining information about power-of-2 sized
+     buffers.
+
+ (2) Memory barriers for when the producer and the consumer of objects in the
+     buffer don't want to share a lock.
+
+To use these facilities, as discussed below, there needs to be just one
+producer and just one consumer.  It is possible to handle multiple producers by
+serialising them, and to handle multiple consumers by serialising them.
+
+
+Contents:
+
+ (*) What is a circular buffer?
+
+ (*) Measuring power-of-2 buffers.
+
+ (*) Using memory barriers with circular buffers.
+     - The producer.
+     - The consumer.
+
+
+==========================
+WHAT IS A CIRCULAR BUFFER?
+==========================
+
+First of all, what is a circular buffer?  A circular buffer is a buffer of
+fixed, finite size into which there are two indices:
+
+ (1) A 'head' index - the point at which the producer inserts items into the
+     buffer.
+
+ (2) A 'tail' index - the point at which the consumer finds the next item in
+     the buffer.
+
+Typically when the tail pointer is equal to the head pointer, the buffer is
+empty; and the buffer is full when the head pointer is one less than the tail
+pointer.
+
+The head index is incremented when items are added, and the tail index when
+items are removed.  The tail index should never jump the head index, and both
+indices should be wrapped to 0 when they reach the end of the buffer, thus
+allowing an infinite amount of data to flow through the buffer.
+
+Typically, items will all be of the same unit size, but this isn't strictly
+required to use the techniques below.  The indices can be increased by more
+than 1 if multiple items or variable-sized items are to be included in the
+buffer, provided that neither index overtakes the other.  The implementer must
+be careful, however, as a region more than one unit in size may wrap the end of
+the buffer and be broken into two segments.
+
+
+============================
+MEASURING POWER-OF-2 BUFFERS
+============================
+
+Calculation of the occupancy or the remaining capacity of an arbitrarily sized
+circular buffer would normally be a slow operation, requiring the use of a
+modulus (divide) instruction.  However, if the buffer is of a power-of-2 size,
+then a much quicker bitwise-AND instruction can be used instead.
+
+Linux provides a set of macros for handling power-of-2 circular buffers.  These
+can be made use of by:
+
+       #include <linux/circ_buf.h>
+
+The macros are:
+
+ (*) Measure the remaining capacity of a buffer:
+
+       CIRC_SPACE(head_index, tail_index, buffer_size);
+
+     This returns the amount of space left in the buffer[1] into which items
+     can be inserted.
+
+
+ (*) Measure the maximum consecutive immediate space in a buffer:
+
+       CIRC_SPACE_TO_END(head_index, tail_index, buffer_size);
+
+     This returns the amount of consecutive space left in the buffer[1] into
+     which items can be immediately inserted without having to wrap back to the
+     beginning of the buffer.
+
+
+ (*) Measure the occupancy of a buffer:
+
+       CIRC_CNT(head_index, tail_index, buffer_size);
+
+     This returns the number of items currently occupying a buffer[2].
+
+
+ (*) Measure the non-wrapping occupancy of a buffer:
+
+       CIRC_CNT_TO_END(head_index, tail_index, buffer_size);
+
+     This returns the number of consecutive items[2] that can be extracted from
+     the buffer without having to wrap back to the beginning of the buffer.
+
+
+Each of these macros will nominally return a value between 0 and buffer_size-1,
+however:
+
+ [1] CIRC_SPACE*() are intended to be used in the producer.  To the producer
+     they will return a lower bound as the producer controls the head index,
+     but the consumer may still be depleting the buffer on another CPU and
+     moving the tail index.
+
+     To the consumer it will show an upper bound as the producer may be busy
+     depleting the space.
+
+ [2] CIRC_CNT*() are intended to be used in the consumer.  To the consumer they
+     will return a lower bound as the consumer controls the tail index, but the
+     producer may still be filling the buffer on another CPU and moving the
+     head index.
+
+     To the producer it will show an upper bound as the consumer may be busy
+     emptying the buffer.
+
+ [3] To a third party, the order in which the writes to the indices by the
+     producer and consumer become visible cannot be guaranteed as they are
+     independent and may be made on different CPUs - so the result in such a
+     situation will merely be a guess, and may even be negative.
+
+
+===========================================
+USING MEMORY BARRIERS WITH CIRCULAR BUFFERS
+===========================================
+
+By using memory barriers in conjunction with circular buffers, you can avoid
+the need to:
+
+ (1) use a single lock to govern access to both ends of the buffer, thus
+     allowing the buffer to be filled and emptied at the same time; and
+
+ (2) use atomic counter operations.
+
+There are two sides to this: the producer that fills the buffer, and the
+consumer that empties it.  Only one thing should be filling a buffer at any one
+time, and only one thing should be emptying a buffer at any one time, but the
+two sides can operate simultaneously.
+
+
+THE PRODUCER
+------------
+
+The producer will look something like this:
+
+       spin_lock(&producer_lock);
+
+       unsigned long head = buffer->head;
+       unsigned long tail = ACCESS_ONCE(buffer->tail);
+
+       if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
+               /* insert one item into the buffer */
+               struct item *item = buffer[head];
+
+               produce_item(item);
+
+               smp_wmb(); /* commit the item before incrementing the head */
+
+               buffer->head = (head + 1) & (buffer->size - 1);
+
+               /* wake_up() will make sure that the head is committed before
+                * waking anyone up */
+               wake_up(consumer);
+       }
+
+       spin_unlock(&producer_lock);
+
+This will instruct the CPU that the contents of the new item must be written
+before the head index makes it available to the consumer and then instructs the
+CPU that the revised head index must be written before the consumer is woken.
+
+Note that wake_up() doesn't have to be the exact mechanism used, but whatever
+is used must guarantee a (write) memory barrier between the update of the head
+index and the change of state of the consumer, if a change of state occurs.
+
+
+THE CONSUMER
+------------
+
+The consumer will look something like this:
+
+       spin_lock(&consumer_lock);
+
+       unsigned long head = ACCESS_ONCE(buffer->head);
+       unsigned long tail = buffer->tail;
+
+       if (CIRC_CNT(head, tail, buffer->size) >= 1) {
+               /* read index before reading contents at that index */
+               smp_read_barrier_depends();
+
+               /* extract one item from the buffer */
+               struct item *item = buffer[tail];
+
+               consume_item(item);
+
+               smp_mb(); /* finish reading descriptor before incrementing tail */
+
+               buffer->tail = (tail + 1) & (buffer->size - 1);
+       }
+
+       spin_unlock(&consumer_lock);
+
+This will instruct the CPU to make sure the index is up to date before reading
+the new item, and then it shall make sure the CPU has finished reading the item
+before it writes the new tail pointer, which will erase the item.
+
+
+Note the use of ACCESS_ONCE() in both algorithms to read the opposition index.
+This prevents the compiler from discarding and reloading its cached value -
+which some compilers will do across smp_read_barrier_depends().  This isn't
+strictly needed if you can be sure that the opposition index will _only_ be
+used the once.
+
+
+===============
+FURTHER READING
+===============
+
+See also Documentation/memory-barriers.txt for a description of Linux's memory
+barrier facilities.
index 3bae418c6ad3d51e8597485f15ef014a553a22b2..4303614b5add04f91461453882ecc77d719b32df 100644 (file)
@@ -16,6 +16,8 @@ befs.txt
        - information about the BeOS filesystem for Linux.
 bfs.txt
        - info for the SCO UnixWare Boot Filesystem (BFS).
+ceph.txt
+       - info for the Ceph Distributed File System
 cifs.txt
        - description of the CIFS filesystem.
 coda.txt
index 6e03917316bd477c9ff79fe813077cabdf579ec1..0660c9f5deef6dccf1bd47270f048195f21ddd69 100644 (file)
@@ -8,7 +8,7 @@ Basic features include:
 
  * POSIX semantics
  * Seamless scaling from 1 to many thousands of nodes
- * High availability and reliability.  No single points of failure.
+ * High availability and reliability.  No single point of failure.
  * N-way replication of data across storage nodes
  * Fast recovery from node failures
  * Automatic rebalancing of data on node addition/removal
@@ -94,7 +94,7 @@ Mount Options
 
   wsize=X
        Specify the maximum write size in bytes.  By default there is no
-       maximu.  Ceph will normally size writes based on the file stripe
+       maximum.  Ceph will normally size writes based on the file stripe
        size.
 
   rsize=X
@@ -115,7 +115,7 @@ Mount Options
        number of entries in that directory.
 
   nocrc
-       Disable CRC32C calculation for data writes.  If set, the OSD
+       Disable CRC32C calculation for data writes.  If set, the storage node
        must rely on TCP's error correction to detect data corruption
        in the data payload.
 
@@ -133,7 +133,8 @@ For more information on Ceph, see the home page at
        http://ceph.newdream.net/
 
 The Linux kernel client source tree is available at
-       git://ceph.newdream.net/linux-ceph-client.git
+       git://ceph.newdream.net/git/ceph-client.git
+       git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
 
 and the source for the full system is at
-       git://ceph.newdream.net/ceph.git
+       git://ceph.newdream.net/git/ceph.git
index 3015da0c6b2a253c4a1b65559a8a8ec82b24e3e9..fe09a2cb1858de038b39746bdc862af3f6dc21bc 100644 (file)
@@ -82,11 +82,13 @@ tmpfs has a mount option to set the NUMA memory allocation policy for
 all files in that instance (if CONFIG_NUMA is enabled) - which can be
 adjusted on the fly via 'mount -o remount ...'
 
-mpol=default             prefers to allocate memory from the local node
+mpol=default             use the process allocation policy
+                         (see set_mempolicy(2))
 mpol=prefer:Node         prefers to allocate memory from the given Node
 mpol=bind:NodeList       allocates memory only from nodes in NodeList
 mpol=interleave          prefers to allocate from each node in turn
 mpol=interleave:NodeList allocates from each node of NodeList in turn
+mpol=local              prefers to allocate memory from the local node
 
 NodeList format is a comma-separated list of decimal numbers and ranges,
 a range being two hyphen-separated decimal numbers, the smallest and
@@ -134,3 +136,5 @@ Author:
    Christoph Rohland <cr@sap.com>, 1.12.01
 Updated:
    Hugh Dickins, 4 June 2007
+Updated:
+   KOSAKI Motohiro, 16 Mar 2010
index 7f5809eddee62eaf524103eeda485f5e553d5a01..631ad2f1b229c1d020a9a8b746d8f6cbe72f4531 100644 (file)
@@ -3,6 +3,7 @@
                         ============================
 
 By: David Howells <dhowells@redhat.com>
+    Paul E. McKenney <paulmck@linux.vnet.ibm.com>
 
 Contents:
 
@@ -60,6 +61,10 @@ Contents:
 
      - And then there's the Alpha.
 
+ (*) Example uses.
+
+     - Circular buffers.
+
  (*) References.
 
 
@@ -2226,6 +2231,21 @@ The Alpha defines the Linux kernel's memory barrier model.
 See the subsection on "Cache Coherency" above.
 
 
+============
+EXAMPLE USES
+============
+
+CIRCULAR BUFFERS
+----------------
+
+Memory barriers can be used to implement circular buffering without the need
+of a lock to serialise the producer with the consumer.  See:
+
+       Documentation/circular-buffers.txt
+
+for details.
+
+
 ==========
 REFERENCES
 ==========
index 991c26a6ef64fcfdef0fc870d3ed404f55751407..db0cb228d64aa4a80a4fe380be3e46439de810e6 100644 (file)
@@ -63,9 +63,9 @@ way to perform a busy wait is:
         cpu_relax();
 
 The cpu_relax() call can lower CPU power consumption or yield to a
-hyperthreaded twin processor; it also happens to serve as a memory barrier,
-so, once again, volatile is unnecessary.  Of course, busy-waiting is
-generally an anti-social act to begin with.
+hyperthreaded twin processor; it also happens to serve as a compiler
+barrier, so, once again, volatile is unnecessary.  Of course, busy-
+waiting is generally an anti-social act to begin with.
 
 There are still a few rare situations where volatile makes sense in the
 kernel:
index 449d44402083aaada8a86aa68a05ae3e6398cd12..3d29fa3898883a51626b527ab0f0b21badb815ce 100644 (file)
@@ -797,12 +797,12 @@ M:        Michael Petchkovsky <mkpetch@internode.on.net>
 S:     Maintained
 
 ARM/NOMADIK ARCHITECTURE
-M:     Alessandro Rubini <rubini@unipv.it>
-M:     STEricsson <STEricsson_nomadik_linux@list.st.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-F:     arch/arm/mach-nomadik/
-F:     arch/arm/plat-nomadik/
+M:     Alessandro Rubini <rubini@unipv.it>
+M:     STEricsson <STEricsson_nomadik_linux@list.st.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-nomadik/
+F:     arch/arm/plat-nomadik/
 
 ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
 M:     Nelson Castillo <arhuaco@freaks-unidos.net>
@@ -1443,7 +1443,7 @@ F:        arch/powerpc/platforms/cell/
 
 CEPH DISTRIBUTED FILE SYSTEM CLIENT
 M:     Sage Weil <sage@newdream.net>
-L:     ceph-devel@lists.sourceforge.net
+L:     ceph-devel@vger.kernel.org
 W:     http://ceph.newdream.net/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
 S:     Supported
@@ -1926,17 +1926,17 @@ F:      drivers/scsi/dpt*
 F:     drivers/scsi/dpt/
 
 DRBD DRIVER
-P:     Philipp Reisner
-P:     Lars Ellenberg
-M:     drbd-dev@lists.linbit.com
-L:     drbd-user@lists.linbit.com
-W:     http://www.drbd.org
-T:     git git://git.drbd.org/linux-2.6-drbd.git drbd
-T:     git git://git.drbd.org/drbd-8.3.git
-S:     Supported
-F:     drivers/block/drbd/
-F:     lib/lru_cache.c
-F:     Documentation/blockdev/drbd/
+P:     Philipp Reisner
+P:     Lars Ellenberg
+M:     drbd-dev@lists.linbit.com
+L:     drbd-user@lists.linbit.com
+W:     http://www.drbd.org
+T:     git git://git.drbd.org/linux-2.6-drbd.git drbd
+T:     git git://git.drbd.org/drbd-8.3.git
+S:     Supported
+F:     drivers/block/drbd/
+F:     lib/lru_cache.c
+F:     Documentation/blockdev/drbd/
 
 DRIVER CORE, KOBJECTS, AND SYSFS
 M:     Greg Kroah-Hartman <gregkh@suse.de>
@@ -3083,6 +3083,7 @@ F:        include/scsi/*iscsi*
 ISDN SUBSYSTEM
 M:     Karsten Keil <isdn@linux-pingi.de>
 L:     isdn4linux@listserv.isdn4linux.de (subscribers-only)
+L:     netdev@vger.kernel.org
 W:     http://www.isdn4linux.de
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/isdn-2.6.git
 S:     Maintained
@@ -3269,6 +3270,16 @@ S:       Maintained
 F:     include/linux/kexec.h
 F:     kernel/kexec.c
 
+KEYS/KEYRINGS:
+M:     David Howells <dhowells@redhat.com>
+L:     keyrings@linux-nfs.org
+S:     Maintained
+F:     Documentation/keys.txt
+F:     include/linux/key.h
+F:     include/linux/key-type.h
+F:     include/keys/
+F:     security/keys/
+
 KGDB
 M:     Jason Wessel <jason.wessel@windriver.com>
 L:     kgdb-bugreport@lists.sourceforge.net
@@ -3518,8 +3529,8 @@ F:        drivers/scsi/sym53c8xx_2/
 LTP (Linux Test Project)
 M:     Rishikesh K Rajak <risrajak@linux.vnet.ibm.com>
 M:     Garrett Cooper <yanegomi@gmail.com>
-M:     Mike Frysinger <vapier@gentoo.org>
-M:     Subrata Modak <subrata@linux.vnet.ibm.com>
+M:     Mike Frysinger <vapier@gentoo.org>
+M:     Subrata Modak <subrata@linux.vnet.ibm.com>
 L:     ltp-list@lists.sourceforge.net (subscribers-only)
 W:     http://ltp.sourceforge.net/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/galak/ltp.git
@@ -5423,7 +5434,6 @@ S:        Maintained
 F:     sound/soc/codecs/twl4030*
 
 TIPC NETWORK LAYER
-M:     Per Liden <per.liden@ericsson.com>
 M:     Jon Maloy <jon.maloy@ericsson.com>
 M:     Allan Stephens <allan.stephens@windriver.com>
 L:     tipc-discussion@lists.sourceforge.net
@@ -6201,7 +6211,7 @@ F:        arch/x86/
 X86 PLATFORM DRIVERS
 M:     Matthew Garrett <mjg@redhat.com>
 L:     platform-driver-x86@vger.kernel.org
-T:      git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git
 S:     Maintained
 F:     drivers/platform/x86
 
index a5ba759e0fd5ff1cff5edf2244997306535bf1af..67c1001cfbf5cee56f16a31bc37b02bffe3ccc14 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 34
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Man-Eating Seals of Antiquity
 
 # *DOCUMENTATION*
index 90ae00b631c269c4ad5c15117055335e092865c1..9dff07c80ddb2eceec0a864275023a8d7a606636 100644 (file)
@@ -290,7 +290,7 @@ static int locomo_suspend(struct platform_device *dev, pm_message_t state)
        save->LCM_GPO     = locomo_readl(lchip->base + LOCOMO_GPO);     /* GPIO */
        locomo_writel(0x00, lchip->base + LOCOMO_GPO);
        save->LCM_SPICT   = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPICT);      /* SPI */
-       locomo_writel(0x40, lchip->base + LOCOMO_SPICT);
+       locomo_writel(0x40, lchip->base + LOCOMO_SPI + LOCOMO_SPICT);
        save->LCM_GPE     = locomo_readl(lchip->base + LOCOMO_GPE);     /* GPIO */
        locomo_writel(0x00, lchip->base + LOCOMO_GPE);
        save->LCM_ASD     = locomo_readl(lchip->base + LOCOMO_ASD);     /* ADSTART */
@@ -418,7 +418,7 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
        /* Longtime timer */
        locomo_writel(0, lchip->base + LOCOMO_LTINT);
        /* SPI */
-       locomo_writel(0, lchip->base + LOCOMO_SPIIE);
+       locomo_writel(0, lchip->base + LOCOMO_SPI + LOCOMO_SPIIE);
 
        locomo_writel(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD);
        r = locomo_readl(lchip->base + LOCOMO_ASD);
@@ -707,7 +707,7 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
        udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */
        if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {   /* High is error */
                printk(KERN_WARNING "locomo: m62332_senddata Error 1\n");
-               return;
+               goto out;
        }
 
        /* Send Sub address (LSB is channel select) */
@@ -735,7 +735,7 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
        udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */
        if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {   /* High is error */
                printk(KERN_WARNING "locomo: m62332_senddata Error 2\n");
-               return;
+               goto out;
        }
 
        /* Send DAC data */
@@ -760,9 +760,9 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
        udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */
        if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {   /* High is error */
                printk(KERN_WARNING "locomo: m62332_senddata Error 3\n");
-               return;
        }
 
+out:
        /* stop */
        r = locomo_readl(mapbase + LOCOMO_DAC);
        r &=  ~(LOCOMO_DAC_SCLOEB);
index 94a3a86cfeb8be7ae854aa26162e33c7796683d0..6ef65d813f161f729fe8e8be91ef6e13deb35603 100644 (file)
@@ -19,7 +19,7 @@
  */
 #define PHYS_OFFSET            (0x00000000)
 
-#define IXP23XX_PCI_SDRAM_OFFSET (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0))
+#define IXP23XX_PCI_SDRAM_OFFSET (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)
 
 #define __phys_to_bus(x)       ((x) + (IXP23XX_PCI_SDRAM_OFFSET - PHYS_OFFSET))
 #define __bus_to_phys(x)       ((x) - (IXP23XX_PCI_SDRAM_OFFSET - PHYS_OFFSET))
index 0358f45766cbe565c7571483bb251fc490f9f81f..5e6f711b1c6753713b8819078ec0bc053566f200 100644 (file)
@@ -74,9 +74,9 @@ static struct gpio_keys_button mv88f6281gtw_ge_button_pins[] = {
                .desc           = "SWR Button",
                .active_low     = 1,
        }, {
-               .code           = KEY_F1,
+               .code           = KEY_WPS_BUTTON,
                .gpio           = 46,
-               .desc           = "WPS Button(F1)",
+               .desc           = "WPS Button",
                .active_low     = 1,
        },
 };
index a7dcc5307216524b4f2e57c05af043530be64f5a..85bd8a2d84b5e47cc3acc1a24192a8387c3d28ab 100644 (file)
@@ -14,7 +14,7 @@
 #define UART2_BASE     (APB_PHYS_BASE + 0x17000)
 #define UART3_BASE     (APB_PHYS_BASE + 0x18000)
 
-static volatile unsigned long *UART = (unsigned long *)UART2_BASE;
+static volatile unsigned long *UART;
 
 static inline void putc(char c)
 {
@@ -37,6 +37,9 @@ static inline void flush(void)
 
 static inline void arch_decomp_setup(void)
 {
+       /* default to UART2 */
+       UART = (unsigned long *)UART2_BASE;
+
        if (machine_is_avengers_lite())
                UART = (unsigned long *)UART3_BASE;
 }
index cb0feca193d442781ffeb887915b601554a5a99b..f9f222ebb7ed0c5b12064cebddfe63c9399b3846 100644 (file)
@@ -77,7 +77,7 @@ static struct gpio_keys_button wrt350n_v2_buttons[] = {
                .desc           = "Reset Button",
                .active_low     = 1,
        }, {
-               .code           = KEY_WLAN,
+               .code           = KEY_WPS_BUTTON,
                .gpio           = 2,
                .desc           = "WPS Button",
                .active_low     = 1,
index 38fbd0a0e4022c1e9076fa43740b6468d50b8d19..5b6ee46fa7f6235b9203ae2b00a66453d28d2849 100644 (file)
@@ -272,7 +272,6 @@ config MACH_H5000
 config MACH_HIMALAYA
        bool "HTC Himalaya Support"
        select CPU_PXA26x
-       select FB_W100
 
 config MACH_MAGICIAN
        bool "Enable HTC Magician Support"
@@ -454,6 +453,13 @@ config PXA_SHARPSL
 config SHARPSL_PM
        bool
        select APM_EMULATION
+       select SHARPSL_PM_MAX1111
+
+config SHARPSL_PM_MAX1111
+       bool
+       depends on !CORGI_SSP_DEPRECATED
+       select HWMON
+       select SENSORS_MAX1111
 
 config CORGI_SSP_DEPRECATED
        bool
@@ -547,7 +553,6 @@ config MACH_E740
        bool "Toshiba e740"
        default y
        depends on ARCH_PXA_ESERIES
-       select FB_W100
        help
          Say Y here if you intend to run this kernel on a Toshiba
          e740 family PDA.
@@ -556,7 +561,6 @@ config MACH_E750
        bool "Toshiba e750"
        default y
        depends on ARCH_PXA_ESERIES
-       select FB_W100
        help
          Say Y here if you intend to run this kernel on a Toshiba
          e750 family PDA.
@@ -573,7 +577,6 @@ config MACH_E800
        bool "Toshiba e800"
        default y
        depends on ARCH_PXA_ESERIES
-       select FB_W100
        help
          Say Y here if you intend to run this kernel on a Toshiba
          e800 family PDA.
index b2f878bd460b5d136570560b8fe9f769ebb9d675..5161dca8ccc03d38bab8b92c4e1ed82ea2667ed6 100644 (file)
@@ -559,10 +559,6 @@ static void __init imote2_init(void)
        pxa_set_btuart_info(NULL);
        pxa_set_stuart_info(NULL);
 
-       /* SPI chip select directions - all other directions should
-        * be handled by drivers.*/
-       gpio_direction_output(37, 0);
-
        platform_add_devices(imote2_devices, ARRAY_SIZE(imote2_devices));
 
        pxa2xx_set_spi_info(1, &pxa_ssp_master_0_info);
index 5ef91d9d17e47fb08b7d810f4e739726d4802498..759b851ec985e02939d2b8f23cb7b9af8019a1c0 100644 (file)
@@ -16,9 +16,9 @@
 #define BTUART_BASE    (0x40200000)
 #define STUART_BASE    (0x40700000)
 
-static unsigned long uart_base = FFUART_BASE;
-static unsigned int uart_shift = 2;
-static unsigned int uart_is_pxa = 1;
+static unsigned long uart_base;
+static unsigned int uart_shift;
+static unsigned int uart_is_pxa;
 
 static inline unsigned char uart_read(int offset)
 {
@@ -56,6 +56,11 @@ static inline void flush(void)
 
 static inline void arch_decomp_setup(void)
 {
+       /* initialize to default */
+       uart_base = FFUART_BASE;
+       uart_shift = 2;
+       uart_is_pxa = 1;
+
        if (machine_is_littleton() || machine_is_intelmote2()
            || machine_is_csb726() || machine_is_stargate2()
            || machine_is_cm_x300() || machine_is_balloon3())
index 3184bdc14526bac6cdf762028f4980996fa8985d..44bb675e47f1f427e7e23cee1d53a14fd8aacac7 100644 (file)
@@ -37,8 +37,6 @@
 #include <linux/lis3lv02d.h>
 #include <linux/pda_power.h>
 #include <linux/power_supply.h>
-#include <linux/pda_power.h>
-#include <linux/power_supply.h>
 #include <linux/regulator/max8660.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
@@ -444,7 +442,7 @@ static struct gpio_keys_button gpio_keys_button[] = {
                .active_low             = 0,
                .wakeup                 = 0,
                .debounce_interval      = 5, /* ms */
-               .desc                   = "on/off button",
+               .desc                   = "on_off button",
        },
 };
 
index a98a434f011163321a6f1b79cc13e36b5159156f..2041eb1d90ba0be9582c843b241b318b0f8b611a 100644 (file)
@@ -764,11 +764,6 @@ static void __init stargate2_init(void)
        pxa_set_btuart_info(NULL);
        pxa_set_stuart_info(NULL);
 
-       /* spi chip selects */
-       gpio_direction_output(37, 0);
-       gpio_direction_output(24, 0);
-       gpio_direction_output(39, 0);
-
        platform_add_devices(ARRAY_AND_SIZE(stargate2_devices));
 
        pxa2xx_set_spi_info(1, &pxa_ssp_master_0_info);
index 31c2f4c30a95b94631bc9e9568247e644b9d0eb2..1536f1784cacba080d10c82e2900fe522c0ab4b1 100644 (file)
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Sat Feb 20 14:16:15 2010
+# Last update: Sat Mar 20 15:35:41 2010
 #
 # machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
 #
@@ -2663,7 +2663,7 @@ reb01                     MACH_REB01              REB01                   2675
 aquila                 MACH_AQUILA             AQUILA                  2676
 spark_sls_hw2          MACH_SPARK_SLS_HW2      SPARK_SLS_HW2           2677
 sheeva_esata           MACH_ESATA_SHEEVAPLUG   ESATA_SHEEVAPLUG        2678
-surf7x30               MACH_SURF7X30           SURF7X30                2679
+msm7x30_surf           MACH_MSM7X30_SURF       MSM7X30_SURF            2679
 micro2440              MACH_MICRO2440          MICRO2440               2680
 am2440                 MACH_AM2440             AM2440                  2681
 tq2440                 MACH_TQ2440             TQ2440                  2682
@@ -2678,3 +2678,74 @@ vc088x                   MACH_VC088X             VC088X                  2690
 mioa702                        MACH_MIOA702            MIOA702                 2691
 hpmin                  MACH_HPMIN              HPMIN                   2692
 ak880xak               MACH_AK880XAK           AK880XAK                2693
+arm926tomap850         MACH_ARM926TOMAP850     ARM926TOMAP850          2694
+lkevm                  MACH_LKEVM              LKEVM                   2695
+mw6410                 MACH_MW6410             MW6410                  2696
+terastation_wxl                MACH_TERASTATION_WXL    TERASTATION_WXL         2697
+cpu8000e               MACH_CPU8000E           CPU8000E                2698
+catania                        MACH_CATANIA            CATANIA                 2699
+tokyo                  MACH_TOKYO              TOKYO                   2700
+msm7201a_surf          MACH_MSM7201A_SURF      MSM7201A_SURF           2701
+msm7201a_ffa           MACH_MSM7201A_FFA       MSM7201A_FFA            2702
+msm7x25_surf           MACH_MSM7X25_SURF       MSM7X25_SURF            2703
+msm7x25_ffa            MACH_MSM7X25_FFA        MSM7X25_FFA             2704
+msm7x27_surf           MACH_MSM7X27_SURF       MSM7X27_SURF            2705
+msm7x27_ffa            MACH_MSM7X27_FFA        MSM7X27_FFA             2706
+msm7x30_ffa            MACH_MSM7X30_FFA        MSM7X30_FFA             2707
+qsd8x50_surf           MACH_QSD8X50_SURF       QSD8X50_SURF            2708
+qsd8x50_comet          MACH_QSD8X50_COMET      QSD8X50_COMET           2709
+qsd8x50_ffa            MACH_QSD8X50_FFA        QSD8X50_FFA             2710
+qsd8x50a_surf          MACH_QSD8X50A_SURF      QSD8X50A_SURF           2711
+qsd8x50a_ffa           MACH_QSD8X50A_FFA       QSD8X50A_FFA            2712
+adx_xgcp10             MACH_ADX_XGCP10         ADX_XGCP10              2713
+mcgwumts2a             MACH_MCGWUMTS2A         MCGWUMTS2A              2714
+mobikt                 MACH_MOBIKT             MOBIKT                  2715
+mx53_evk               MACH_MX53_EVK           MX53_EVK                2716
+igep0030               MACH_IGEP0030           IGEP0030                2717
+axell_h40_h50_ctrl     MACH_AXELL_H40_H50_CTRL AXELL_H40_H50_CTRL      2718
+dtcommod               MACH_DTCOMMOD           DTCOMMOD                2719
+gould                  MACH_GOULD              GOULD                   2720
+siberia                        MACH_SIBERIA            SIBERIA                 2721
+sbc3530                        MACH_SBC3530            SBC3530                 2722
+qarm                   MACH_QARM               QARM                    2723
+mips                   MACH_MIPS               MIPS                    2724
+mx27grb                        MACH_MX27GRB            MX27GRB                 2725
+sbc8100                        MACH_SBC8100            SBC8100                 2726
+saarb                  MACH_SAARB              SAARB                   2727
+omap3mini              MACH_OMAP3MINI          OMAP3MINI               2728
+cnmbook7se             MACH_CNMBOOK7SE         CNMBOOK7SE              2729
+catan                  MACH_CATAN              CATAN                   2730
+harmony                        MACH_HARMONY            HARMONY                 2731
+tonga                  MACH_TONGA              TONGA                   2732
+cybook_orizon          MACH_CYBOOK_ORIZON      CYBOOK_ORIZON           2733
+htcrhodiumcdma         MACH_HTCRHODIUMCDMA     HTCRHODIUMCDMA          2734
+epc_g45                        MACH_EPC_G45            EPC_G45                 2735
+epc_lpc3250            MACH_EPC_LPC3250        EPC_LPC3250             2736
+mxc91341evb            MACH_MXC91341EVB        MXC91341EVB             2737
+rtw1000                        MACH_RTW1000            RTW1000                 2738
+bobcat                 MACH_BOBCAT             BOBCAT                  2739
+trizeps6               MACH_TRIZEPS6           TRIZEPS6                2740
+msm7x30_fluid          MACH_MSM7X30_FLUID      MSM7X30_FLUID           2741
+nedap9263              MACH_NEDAP9263          NEDAP9263               2742
+netgear_ms2110         MACH_NETGEAR_MS2110     NETGEAR_MS2110          2743
+bmx                    MACH_BMX                BMX                     2744
+netstream              MACH_NETSTREAM          NETSTREAM               2745
+vpnext_rcu             MACH_VPNEXT_RCU         VPNEXT_RCU              2746
+vpnext_mpu             MACH_VPNEXT_MPU         VPNEXT_MPU              2747
+bcmring_tablet_v1      MACH_BCMRING_TABLET_V1  BCMRING_TABLET_V1       2748
+sgarm10                        MACH_SGARM10            SGARM10                 2749
+cm_t3517               MACH_CM_T3517           CM_T3517                2750
+omap3_cps              MACH_OMAP3_CPS          OMAP3_CPS               2751
+axar1500_receiver      MACH_AXAR1500_RECEIVER  AXAR1500_RECEIVER       2752
+wbd222                 MACH_WBD222             WBD222                  2753
+mt65xx                 MACH_MT65XX             MT65XX                  2754
+msm8x60_surf           MACH_MSM8X60_SURF       MSM8X60_SURF            2755
+msm8x60_sim            MACH_MSM8X60_SIM        MSM8X60_SIM             2756
+vmc300                 MACH_VMC300             VMC300                  2757
+tcc8000_sdk            MACH_TCC8000_SDK        TCC8000_SDK             2758
+nanos                  MACH_NANOS              NANOS                   2759
+stamp9g10              MACH_STAMP9G10          STAMP9G10               2760
+stamp9g45              MACH_STAMP9G45          STAMP9G45               2761
+h6053                  MACH_H6053              H6053                   2762
+smint01                        MACH_SMINT01            SMINT01                 2763
+prtlvt2                        MACH_PRTLVT2            PRTLVT2                 2764
index d4b9c36ddc0fb62f2f8f284897a9504f411307a6..bc0cfdad1cbceecd2c7347c427c087b6ed8105ee 100644 (file)
@@ -50,7 +50,7 @@ pcibios_align_resource(void *data, const struct resource *res,
        if ((res->flags & IORESOURCE_IO) && (start & 0x300))
                start = (start + 0x3ff) & ~0x3ff;
 
-       return start
+       return start;
 }
 
 int pcibios_enable_resources(struct pci_dev *dev, int mask)
index 1ed15d7fea20c0e8975b22d492fa1e5da3bfb107..6b4fb28e9f997d1a9bf64f19cd26fba08ac8b9df 100644 (file)
@@ -41,7 +41,7 @@ pcibios_align_resource(void *data, const struct resource *res,
        if ((res->flags & IORESOURCE_IO) && (start & 0x300))
                start = (start + 0x3ff) & ~0x3ff;
 
-       return start
+       return start;
 }
 
 
@@ -94,8 +94,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
                                r = &dev->resource[idx];
                                if (!r->start)
                                        continue;
-                               if (pci_claim_resource(dev, idx) < 0)
-                                       printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev));
+                               pci_claim_resource(dev, idx);
                        }
                }
                pcibios_allocate_bus_resources(&bus->children);
@@ -125,7 +124,6 @@ static void __init pcibios_allocate_resources(int pass)
                                DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",
                                    r->start, r->end, r->flags, disabled, pass);
                                if (pci_claim_resource(dev, idx) < 0) {
-                                       printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, pci_name(dev));
                                        /* We'll assign a new address later */
                                        r->end -= r->start;
                                        r->start = 0;
index 203ec61c6d4cf79c9d632aa33b36107218215c37..76818f926539bf444c8aa577d12dc1af1296d665 100644 (file)
@@ -75,9 +75,6 @@ config LOCKDEP_SUPPORT
 config HAVE_LATENCYTOP_SUPPORT
        def_bool y
 
-config PCI
-       def_bool n
-
 config DTC
        def_bool y
 
index 836832dd9b26cb8ba7bff598b805e308f4b95c6d..72f6e85837467679354d37ec148db56eb4868363 100644 (file)
@@ -84,7 +84,7 @@ define archhelp
   echo '* linux.bin    - Create raw binary'
   echo '  linux.bin.gz - Create compressed raw binary'
   echo '  simpleImage.<dt> - ELF image with $(arch)/boot/dts/<dt>.dts linked in'
-  echo '                   - stripped elf with fdt blob
+  echo '                   - stripped elf with fdt blob'
   echo '  simpleImage.<dt>.unstrip - full ELF image with fdt blob'
   echo '  *_defconfig      - Select default config from arch/microblaze/configs'
   echo ''
@@ -94,3 +94,5 @@ define archhelp
   echo '  name of a dts file from the arch/microblaze/boot/dts/ directory'
   echo '  (minus the .dts extension).'
 endef
+
+MRPROPER_FILES += $(boot)/simpleImage.*
index 902cf9846c3cb9b89f0940a8a635554cb265fd0b..57f50c2371c6e36372962886180324ffba5b5fd2 100644 (file)
@@ -23,8 +23,6 @@ $(obj)/system.dtb: $(obj)/$(DTB).dtb
 endif
 
 $(obj)/linux.bin: vmlinux FORCE
-       [ -n $(CONFIG_INITRAMFS_SOURCE) ] && [ ! -e $(CONFIG_INITRAMFS_SOURCE) ] && \
-       touch $(CONFIG_INITRAMFS_SOURCE) || echo "No CPIO image"
        $(call if_changed,objcopy)
        $(call if_changed,uimage)
        @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
@@ -62,6 +60,4 @@ quiet_cmd_dtc = DTC     $@
 $(obj)/%.dtb: $(dtstree)/%.dts FORCE
        $(call if_changed,dtc)
 
-clean-kernel += linux.bin linux.bin.gz simpleImage.*
-
-clean-files += *.dtb simpleImage.*.unstrip
+clean-files += *.dtb simpleImage.*.unstrip linux.bin.ub
index 563c6b9453f030a34344cf0e9d63f1a5dd994318..8eeb09211ece1b7f32fc31b6655a2cd8628d0ea6 100644 (file)
@@ -14,7 +14,6 @@
 #include <asm/ptrace.h>
 #include <asm/setup.h>
 #include <asm/registers.h>
-#include <asm/segment.h>
 #include <asm/entry.h>
 #include <asm/current.h>
 
diff --git a/arch/microblaze/include/asm/segment.h b/arch/microblaze/include/asm/segment.h
deleted file mode 100644 (file)
index 0e7102c..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2008-2009 PetaLogix
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_SEGMENT_H
-#define _ASM_MICROBLAZE_SEGMENT_H
-
-# ifndef __ASSEMBLY__
-
-typedef struct {
-       unsigned long seg;
-} mm_segment_t;
-
-/*
- * On Microblaze the fs value is actually the top of the corresponding
- * address space.
- *
- * The fs value determines whether argument validity checking should be
- * performed or not. If get_fs() == USER_DS, checking is performed, with
- * get_fs() == KERNEL_DS, checking is bypassed.
- *
- * For historical reasons, these macros are grossly misnamed.
- *
- * For non-MMU arch like Microblaze, KERNEL_DS and USER_DS is equal.
- */
-# define MAKE_MM_SEG(s)       ((mm_segment_t) { (s) })
-
-#  ifndef CONFIG_MMU
-#  define KERNEL_DS    MAKE_MM_SEG(0)
-#  define USER_DS      KERNEL_DS
-#  else
-#  define KERNEL_DS    MAKE_MM_SEG(0xFFFFFFFF)
-#  define USER_DS      MAKE_MM_SEG(TASK_SIZE - 1)
-#  endif
-
-# define get_ds()      (KERNEL_DS)
-# define get_fs()      (current_thread_info()->addr_limit)
-# define set_fs(val)   (current_thread_info()->addr_limit = (val))
-
-# define segment_eq(a, b)      ((a).seg == (b).seg)
-
-# endif /* __ASSEMBLY__ */
-#endif /* _ASM_MICROBLAZE_SEGMENT_H */
index 6e92885d381a80ee3adc680632415c3911ecdb64..b2ca80f646403d683fa9d9a10e3ea79f67bafb0c 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef __ASSEMBLY__
 # include <linux/types.h>
 # include <asm/processor.h>
-# include <asm/segment.h>
 
 /*
  * low level task data that entry.S needs immediate access to
@@ -60,6 +59,10 @@ struct cpu_context {
        __u32   fsr;
 };
 
+typedef struct {
+       unsigned long seg;
+} mm_segment_t;
+
 struct thread_info {
        struct task_struct      *task; /* main task structure */
        struct exec_domain      *exec_domain; /* execution domain */
index bcb8b41d55afb9b415f3f803259ada2b3326469a..2e1353c2d18d7d256a0d499ac3f6beae581a6dee 100644 (file)
@@ -24,6 +24,7 @@ extern void _tlbie(unsigned long address);
 extern void _tlbia(void);
 
 #define __tlbia()      { preempt_disable(); _tlbia(); preempt_enable(); }
+#define __tlbie(x)     { _tlbie(x); }
 
 static inline void local_flush_tlb_all(void)
        { __tlbia(); }
@@ -31,7 +32,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
        { __tlbia(); }
 static inline void local_flush_tlb_page(struct vm_area_struct *vma,
                                unsigned long vmaddr)
-       { _tlbie(vmaddr); }
+       { __tlbie(vmaddr); }
 static inline void local_flush_tlb_range(struct vm_area_struct *vma,
                unsigned long start, unsigned long end)
        { __tlbia(); }
index 371bd6e56d9a20e60624147a050366f9fd06d2ea..446bec29b142bc5509a445f28146c166c756cb11 100644 (file)
 #include <asm/mmu.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/segment.h>
 #include <linux/string.h>
 
 #define VERIFY_READ    0
 #define VERIFY_WRITE   1
 
-#define __clear_user(addr, n)  (memset((void *)(addr), 0, (n)), 0)
-
-#ifndef CONFIG_MMU
-
-extern int ___range_ok(unsigned long addr, unsigned long size);
-
-#define __range_ok(addr, size) \
-               ___range_ok((unsigned long)(addr), (unsigned long)(size))
-
-#define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0)
-#define __access_ok(add, size) (__range_ok((addr), (size)) == 0)
-
-/* Undefined function to trigger linker error */
-extern int bad_user_access_length(void);
-
-/* FIXME this is function for optimalization -> memcpy */
-#define __get_user(var, ptr)                           \
-({                                                     \
-       int __gu_err = 0;                               \
-       switch (sizeof(*(ptr))) {                       \
-       case 1:                                         \
-       case 2:                                         \
-       case 4:                                         \
-               (var) = *(ptr);                         \
-               break;                                  \
-       case 8:                                         \
-               memcpy((void *) &(var), (ptr), 8);      \
-               break;                                  \
-       default:                                        \
-               (var) = 0;                              \
-               __gu_err = __get_user_bad();            \
-               break;                                  \
-       }                                               \
-       __gu_err;                                       \
-})
+/*
+ * On Microblaze the fs value is actually the top of the corresponding
+ * address space.
+ *
+ * The fs value determines whether argument validity checking should be
+ * performed or not. If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ *
+ * For non-MMU arch like Microblaze, KERNEL_DS and USER_DS is equal.
+ */
+# define MAKE_MM_SEG(s)       ((mm_segment_t) { (s) })
 
-#define __get_user_bad()       (bad_user_access_length(), (-EFAULT))
+#  ifndef CONFIG_MMU
+#  define KERNEL_DS    MAKE_MM_SEG(0)
+#  define USER_DS      KERNEL_DS
+#  else
+#  define KERNEL_DS    MAKE_MM_SEG(0xFFFFFFFF)
+#  define USER_DS      MAKE_MM_SEG(TASK_SIZE - 1)
+#  endif
 
-/* FIXME is not there defined __pu_val */
-#define __put_user(var, ptr)                                   \
-({                                                             \
-       int __pu_err = 0;                                       \
-       switch (sizeof(*(ptr))) {                               \
-       case 1:                                                 \
-       case 2:                                                 \
-       case 4:                                                 \
-               *(ptr) = (var);                                 \
-               break;                                          \
-       case 8: {                                               \
-               typeof(*(ptr)) __pu_val = (var);                \
-               memcpy(ptr, &__pu_val, sizeof(__pu_val));       \
-               }                                               \
-               break;                                          \
-       default:                                                \
-               __pu_err = __put_user_bad();                    \
-               break;                                          \
-       }                                                       \
-       __pu_err;                                               \
-})
+# define get_ds()      (KERNEL_DS)
+# define get_fs()      (current_thread_info()->addr_limit)
+# define set_fs(val)   (current_thread_info()->addr_limit = (val))
 
-#define __put_user_bad()       (bad_user_access_length(), (-EFAULT))
+# define segment_eq(a, b)      ((a).seg == (b).seg)
 
-#define put_user(x, ptr)       __put_user((x), (ptr))
-#define get_user(x, ptr)       __get_user((x), (ptr))
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue. No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path. This means when everything is well,
+ * we don't even have to jump over them. Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+struct exception_table_entry {
+       unsigned long insn, fixup;
+};
 
-#define copy_to_user(to, from, n)      (memcpy((to), (from), (n)), 0)
-#define copy_from_user(to, from, n)    (memcpy((to), (from), (n)), 0)
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
 
-#define __copy_to_user(to, from, n)    (copy_to_user((to), (from), (n)))
-#define __copy_from_user(to, from, n)  (copy_from_user((to), (from), (n)))
-#define __copy_to_user_inatomic(to, from, n) \
-                       (__copy_to_user((to), (from), (n)))
-#define __copy_from_user_inatomic(to, from, n) \
-                       (__copy_from_user((to), (from), (n)))
+#ifndef CONFIG_MMU
 
-static inline unsigned long clear_user(void *addr, unsigned long size)
+/* Check against bounds of physical memory */
+static inline int ___range_ok(unsigned long addr, unsigned long size)
 {
-       if (access_ok(VERIFY_WRITE, addr, size))
-               size = __clear_user(addr, size);
-       return size;
+       return ((addr < memory_start) ||
+               ((addr + size) > memory_end));
 }
 
-/* Returns 0 if exception not found and fixup otherwise.  */
-extern unsigned long search_exception_table(unsigned long);
+#define __range_ok(addr, size) \
+               ___range_ok((unsigned long)(addr), (unsigned long)(size))
 
-extern long strncpy_from_user(char *dst, const char *src, long count);
-extern long strnlen_user(const char *src, long count);
+#define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0)
 
-#else /* CONFIG_MMU */
+#else
 
 /*
  * Address is valid if:
@@ -129,24 +101,88 @@ extern long strnlen_user(const char *src, long count);
 /* || printk("access_ok failed for %s at 0x%08lx (size %d), seg 0x%08x\n",
  type?"WRITE":"READ",addr,size,get_fs().seg)) */
 
-/*
- * All the __XXX versions macros/functions below do not perform
- * access checking. It is assumed that the necessary checks have been
- * already performed before the finction (macro) is called.
- */
+#endif
 
-#define get_user(x, ptr)                                               \
-({                                                                     \
-       access_ok(VERIFY_READ, (ptr), sizeof(*(ptr)))                   \
-               ? __get_user((x), (ptr)) : -EFAULT;                     \
-})
+#ifdef CONFIG_MMU
+# define __FIXUP_SECTION       ".section .fixup,\"ax\"\n"
+# define __EX_TABLE_SECTION    ".section __ex_table,\"a\"\n"
+#else
+# define __FIXUP_SECTION       ".section .discard,\"ax\"\n"
+# define __EX_TABLE_SECTION    ".section .discard,\"a\"\n"
+#endif
 
-#define put_user(x, ptr)                                               \
-({                                                                     \
-       access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr)))                  \
-               ? __put_user((x), (ptr)) : -EFAULT;                     \
+extern unsigned long __copy_tofrom_user(void __user *to,
+               const void __user *from, unsigned long size);
+
+/* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */
+static inline unsigned long __must_check __clear_user(void __user *to,
+                                                       unsigned long n)
+{
+       /* normal memset with two words to __ex_table */
+       __asm__ __volatile__ (                          \
+                       "1:     sb      r0, %2, r0;"    \
+                       "       addik   %0, %0, -1;"    \
+                       "       bneid   %0, 1b;"        \
+                       "       addik   %2, %2, 1;"     \
+                       "2:                     "       \
+                       __EX_TABLE_SECTION              \
+                       ".word  1b,2b;"                 \
+                       ".previous;"                    \
+               : "=r"(n)                               \
+               : "0"(n), "r"(to)
+       );
+       return n;
+}
+
+static inline unsigned long __must_check clear_user(void __user *to,
+                                                       unsigned long n)
+{
+       might_sleep();
+       if (unlikely(!access_ok(VERIFY_WRITE, to, n)))
+               return n;
+
+       return __clear_user(to, n);
+}
+
+/* put_user and get_user macros */
+extern long __user_bad(void);
+
+#define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err)     \
+({                                                             \
+       __asm__ __volatile__ (                                  \
+                       "1:"    insn    " %1, %2, r0;"          \
+                       "       addk    %0, r0, r0;"            \
+                       "2:                     "               \
+                       __FIXUP_SECTION                         \
+                       "3:     brid    2b;"                    \
+                       "       addik   %0, r0, %3;"            \
+                       ".previous;"                            \
+                       __EX_TABLE_SECTION                      \
+                       ".word  1b,3b;"                         \
+                       ".previous;"                            \
+               : "=&r"(__gu_err), "=r"(__gu_val)               \
+               : "r"(__gu_ptr), "i"(-EFAULT)                   \
+       );                                                      \
 })
 
+/**
+ * get_user: - Get a simple variable from user space.
+ * @x:   Variable to store result.
+ * @ptr: Source address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple variable from user space to kernel
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and the result of
+ * dereferencing @ptr must be assignable to @x without a cast.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
+
 #define __get_user(x, ptr)                                             \
 ({                                                                     \
        unsigned long __gu_val;                                         \
@@ -163,30 +199,74 @@ extern long strnlen_user(const char *src, long count);
                __get_user_asm("lw", (ptr), __gu_val, __gu_err);        \
                break;                                                  \
        default:                                                        \
-               __gu_val = 0; __gu_err = -EINVAL;                       \
+               /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\
        }                                                               \
        x = (__typeof__(*(ptr))) __gu_val;                              \
        __gu_err;                                                       \
 })
 
-#define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err)             \
+
+#define get_user(x, ptr)                                               \
 ({                                                                     \
-       __asm__ __volatile__ (                                          \
-                       "1:"    insn    " %1, %2, r0;                   \
-                               addk    %0, r0, r0;                     \
-                       2:                                              \
-                       .section .fixup,\"ax\";                         \
-                       3:      brid    2b;                             \
-                               addik   %0, r0, %3;                     \
-                       .previous;                                      \
-                       .section __ex_table,\"a\";                      \
-                       .word   1b,3b;                                  \
-                       .previous;"                                     \
-               : "=r"(__gu_err), "=r"(__gu_val)                        \
-               : "r"(__gu_ptr), "i"(-EFAULT)                           \
-       );                                                              \
+       access_ok(VERIFY_READ, (ptr), sizeof(*(ptr)))                   \
+               ? __get_user((x), (ptr)) : -EFAULT;                     \
+})
+
+#define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err)     \
+({                                                             \
+       __asm__ __volatile__ (                                  \
+                       "1:"    insn    " %1, %2, r0;"          \
+                       "       addk    %0, r0, r0;"            \
+                       "2:                     "               \
+                       __FIXUP_SECTION                         \
+                       "3:     brid    2b;"                    \
+                       "       addik   %0, r0, %3;"            \
+                       ".previous;"                            \
+                       __EX_TABLE_SECTION                      \
+                       ".word  1b,3b;"                         \
+                       ".previous;"                            \
+               : "=&r"(__gu_err)                               \
+               : "r"(__gu_val), "r"(__gu_ptr), "i"(-EFAULT)    \
+       );                                                      \
 })
 
+#define __put_user_asm_8(__gu_ptr, __gu_val, __gu_err)         \
+({                                                             \
+       __asm__ __volatile__ (" lwi     %0, %1, 0;"             \
+                       "1:     swi     %0, %2, 0;"             \
+                       "       lwi     %0, %1, 4;"             \
+                       "2:     swi     %0, %2, 4;"             \
+                       "       addk    %0, r0, r0;"            \
+                       "3:                     "               \
+                       __FIXUP_SECTION                         \
+                       "4:     brid    3b;"                    \
+                       "       addik   %0, r0, %3;"            \
+                       ".previous;"                            \
+                       __EX_TABLE_SECTION                      \
+                       ".word  1b,4b,2b,4b;"                   \
+                       ".previous;"                            \
+               : "=&r"(__gu_err)                               \
+               : "r"(&__gu_val), "r"(__gu_ptr), "i"(-EFAULT)   \
+               );                                              \
+})
+
+/**
+ * put_user: - Write a simple value into user space.
+ * @x:   Value to copy to user space.
+ * @ptr: Destination address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple value from kernel space to user
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and @x must be assignable
+ * to the result of dereferencing @ptr.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ */
+
 #define __put_user(x, ptr)                                             \
 ({                                                                     \
        __typeof__(*(ptr)) volatile __gu_val = (x);                     \
@@ -195,7 +275,7 @@ extern long strnlen_user(const char *src, long count);
        case 1:                                                         \
                __put_user_asm("sb", (ptr), __gu_val, __gu_err);        \
                break;                                                  \
-       case 2:                                                         \
+       case 2:                                                         \
                __put_user_asm("sh", (ptr), __gu_val, __gu_err);        \
                break;                                                  \
        case 4:                                                         \
@@ -205,121 +285,82 @@ extern long strnlen_user(const char *src, long count);
                __put_user_asm_8((ptr), __gu_val, __gu_err);            \
                break;                                                  \
        default:                                                        \
-               __gu_err = -EINVAL;                                     \
+               /*__gu_err = -EINVAL;*/ __gu_err = __user_bad();        \
        }                                                               \
        __gu_err;                                                       \
 })
 
-#define __put_user_asm_8(__gu_ptr, __gu_val, __gu_err) \
-({                                                     \
-__asm__ __volatile__ ("        lwi     %0, %1, 0;              \
-               1:      swi     %0, %2, 0;              \
-                       lwi     %0, %1, 4;              \
-               2:      swi     %0, %2, 4;              \
-                       addk    %0,r0,r0;               \
-               3:                                      \
-               .section .fixup,\"ax\";                 \
-               4:      brid    3b;                     \
-                       addik   %0, r0, %3;             \
-               .previous;                              \
-               .section __ex_table,\"a\";              \
-               .word   1b,4b,2b,4b;                    \
-               .previous;"                             \
-       : "=&r"(__gu_err)                               \
-       : "r"(&__gu_val),                               \
-       "r"(__gu_ptr), "i"(-EFAULT)                     \
-       );                                              \
-})
+#ifndef CONFIG_MMU
 
-#define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err)     \
-({                                                             \
-       __asm__ __volatile__ (                                  \
-                       "1:"    insn    " %1, %2, r0;           \
-                               addk    %0, r0, r0;             \
-                       2:                                      \
-                       .section .fixup,\"ax\";                 \
-                       3:      brid    2b;                     \
-                               addik   %0, r0, %3;             \
-                       .previous;                              \
-                       .section __ex_table,\"a\";              \
-                       .word   1b,3b;                          \
-                       .previous;"                             \
-               : "=r"(__gu_err)                                \
-               : "r"(__gu_val), "r"(__gu_ptr), "i"(-EFAULT)    \
-       );                                                      \
-})
+#define put_user(x, ptr)       __put_user((x), (ptr))
 
-/*
- * Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail.
- */
-static inline int clear_user(char *to, int size)
-{
-       if (size && access_ok(VERIFY_WRITE, to, size)) {
-               __asm__ __volatile__ ("                         \
-                               1:                              \
-                                       sb      r0, %2, r0;     \
-                                       addik   %0, %0, -1;     \
-                                       bneid   %0, 1b;         \
-                                       addik   %2, %2, 1;      \
-                               2:                              \
-                               .section __ex_table,\"a\";      \
-                               .word   1b,2b;                  \
-                               .section .text;"                \
-                       : "=r"(size)                            \
-                       : "0"(size), "r"(to)
-               );
-       }
-       return size;
-}
+#else /* CONFIG_MMU */
 
-#define __copy_from_user(to, from, n)  copy_from_user((to), (from), (n))
+#define put_user(x, ptr)                                               \
+({                                                                     \
+       access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr)))                  \
+               ? __put_user((x), (ptr)) : -EFAULT;                     \
+})
+#endif /* CONFIG_MMU */
+
+/* copy_to_from_user */
+#define __copy_from_user(to, from, n)  \
+       __copy_tofrom_user((__force void __user *)(to), \
+                               (void __user *)(from), (n))
 #define __copy_from_user_inatomic(to, from, n) \
                copy_from_user((to), (from), (n))
 
-#define copy_to_user(to, from, n)                                      \
-       (access_ok(VERIFY_WRITE, (to), (n)) ?                           \
-               __copy_tofrom_user((void __user *)(to),                 \
-                       (__force const void __user *)(from), (n))       \
-               : -EFAULT)
+static inline long copy_from_user(void *to,
+               const void __user *from, unsigned long n)
+{
+       might_sleep();
+       if (access_ok(VERIFY_READ, from, n))
+               return __copy_from_user(to, from, n);
+       return n;
+}
 
-#define __copy_to_user(to, from, n)    copy_to_user((to), (from), (n))
+#define __copy_to_user(to, from, n)    \
+               __copy_tofrom_user((void __user *)(to), \
+                       (__force const void __user *)(from), (n))
 #define __copy_to_user_inatomic(to, from, n)   copy_to_user((to), (from), (n))
 
-#define copy_from_user(to, from, n)                                    \
-       (access_ok(VERIFY_READ, (from), (n)) ?                          \
-               __copy_tofrom_user((__force void __user *)(to),         \
-                       (void __user *)(from), (n))                     \
-               : -EFAULT)
+static inline long copy_to_user(void __user *to,
+               const void *from, unsigned long n)
+{
+       might_sleep();
+       if (access_ok(VERIFY_WRITE, to, n))
+               return __copy_to_user(to, from, n);
+       return n;
+}
 
+/*
+ * Copy a null terminated string from userspace.
+ */
 extern int __strncpy_user(char *to, const char __user *from, int len);
-extern int __strnlen_user(const char __user *sstr, int len);
 
-#define strncpy_from_user(to, from, len)       \
-               (access_ok(VERIFY_READ, from, 1) ?      \
-                       __strncpy_user(to, from, len) : -EFAULT)
-#define strnlen_user(str, len) \
-               (access_ok(VERIFY_READ, str, 1) ? __strnlen_user(str, len) : 0)
+#define __strncpy_from_user    __strncpy_user
 
-#endif /* CONFIG_MMU */
-
-extern unsigned long __copy_tofrom_user(void __user *to,
-               const void __user *from, unsigned long size);
+static inline long
+strncpy_from_user(char *dst, const char __user *src, long count)
+{
+       if (!access_ok(VERIFY_READ, src, 1))
+               return -EFAULT;
+       return __strncpy_from_user(dst, src, count);
+}
 
 /*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue. No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
+ * Return the size of a string (including the ending 0)
  *
- * All the routines below use bits of fixup code that are out of line
- * with the main instruction path. This means when everything is well,
- * we don't even have to jump over them. Further, they do not intrude
- * on our cache or tlb entries.
+ * Return 0 on exception, a value greater than N if too long
  */
-struct exception_table_entry {
-       unsigned long insn, fixup;
-};
+extern int __strnlen_user(const char __user *sstr, int len);
+
+static inline long strnlen_user(const char __user *src, long n)
+{
+       if (!access_ok(VERIFY_READ, src, 1))
+               return 0;
+       return __strnlen_user(src, n);
+}
 
 #endif  /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
index b1084974fccdb4f49046113b479eb160fd961ed8..4d5b0311601b9cab2171384d69a8b49332ed8c9b 100644 (file)
@@ -37,7 +37,7 @@ static inline void __dma_sync_page(unsigned long paddr, unsigned long offset,
 
 static unsigned long get_dma_direct_offset(struct device *dev)
 {
-       if (dev)
+       if (likely(dev))
                return (unsigned long)dev->archdata.dma_data;
 
        return PCI_DRAM_OFFSET; /* FIXME Not sure if is correct */
index cb7815cfe5ab7d74418f5a4722e7b7854903959e..da6a5f5dc76624797af0dd60a577f8689637f5e1 100644 (file)
@@ -51,6 +51,12 @@ swapper_pg_dir:
 
        .text
 ENTRY(_start)
+#if CONFIG_KERNEL_BASE_ADDR == 0
+       brai    TOPHYS(real_start)
+       .org    0x100
+real_start:
+#endif
+
        mfs     r1, rmsr
        andi    r1, r1, ~2
        mts     rmsr, r1
@@ -99,8 +105,8 @@ no_fdt_arg:
        tophys(r4,r4)                   /* convert to phys address */
        ori     r3, r0, COMMAND_LINE_SIZE - 1 /* number of loops */
 _copy_command_line:
-       lbu     r2, r5, r6 /* r7=r5+r6 - r5 contain pointer to command line */
-       sb      r2, r4, r6              /* addr[r4+r6]= r7*/
+       lbu     r2, r5, r6 /* r2=r5+r6 - r5 contain pointer to command line */
+       sb      r2, r4, r6              /* addr[r4+r6]= r2*/
        addik   r6, r6, 1               /* increment counting */
        bgtid   r3, _copy_command_line  /* loop for all entries       */
        addik   r3, r3, -1              /* descrement loop */
@@ -128,7 +134,7 @@ _copy_bram:
         * virtual to physical.
         */
        nop
-       addik   r3, r0, 63              /* Invalidate all TLB entries */
+       addik   r3, r0, MICROBLAZE_TLB_SIZE -1  /* Invalidate all TLB entries */
 _invalidate:
        mts     rtlbx, r3
        mts     rtlbhi, r0                      /* flush: ensure V is clear   */
index 2b86c03aa84187cb5857974fba2cb949e349ce93..995a2123635bc2dbb0d9121e500e0dc6ead4494c 100644 (file)
@@ -313,13 +313,13 @@ _hw_exception_handler:
        mfs     r5, rmsr;
        nop
        swi     r5, r1, 0;
-       mfs     r3, resr
+       mfs     r4, resr
        nop
-       mfs     r4, rear;
+       mfs     r3, rear;
        nop
 
 #ifndef CONFIG_MMU
-       andi    r5, r3, 0x1000;         /* Check ESR[DS] */
+       andi    r5, r4, 0x1000;         /* Check ESR[DS] */
        beqi    r5, not_in_delay_slot;  /* Branch if ESR[DS] not set */
        mfs     r17, rbtr;      /* ESR[DS] set - return address in BTR */
        nop
@@ -327,13 +327,14 @@ not_in_delay_slot:
        swi     r17, r1, PT_R17
 #endif
 
-       andi    r5, r3, 0x1F;           /* Extract ESR[EXC] */
+       andi    r5, r4, 0x1F;           /* Extract ESR[EXC] */
 
 #ifdef CONFIG_MMU
        /* Calculate exception vector offset = r5 << 2 */
        addk    r6, r5, r5; /* << 1 */
        addk    r6, r6, r6; /* << 2 */
 
+#ifdef DEBUG
 /* counting which exception happen */
        lwi     r5, r0, 0x200 + TOPHYS(r0_ram)
        addi    r5, r5, 1
@@ -341,6 +342,7 @@ not_in_delay_slot:
        lwi     r5, r6, 0x200 + TOPHYS(r0_ram)
        addi    r5, r5, 1
        swi     r5, r6, 0x200 + TOPHYS(r0_ram)
+#endif
 /* end */
        /* Load the HW Exception vector */
        lwi     r6, r6, TOPHYS(_MB_HW_ExceptionVectorTable)
@@ -376,7 +378,7 @@ handle_other_ex: /* Handle Other exceptions here */
        swi     r18, r1, PT_R18
 
        or      r5, r1, r0
-       andi    r6, r3, 0x1F; /* Load ESR[EC] */
+       andi    r6, r4, 0x1F; /* Load ESR[EC] */
        lwi     r7, r0, PER_CPU(KM) /* MS: saving current kernel mode to regs */
        swi     r7, r1, PT_MODE
        mfs     r7, rfsr
@@ -426,11 +428,11 @@ handle_other_ex: /* Handle Other exceptions here */
  */
 handle_unaligned_ex:
        /* Working registers already saved: R3, R4, R5, R6
-        *  R3 = ESR
-        *  R4 = EAR
+        *  R4 = ESR
+        *  R3 = EAR
         */
 #ifdef CONFIG_MMU
-       andi    r6, r3, 0x1000                  /* Check ESR[DS] */
+       andi    r6, r4, 0x1000                  /* Check ESR[DS] */
        beqi    r6, _no_delayslot               /* Branch if ESR[DS] not set */
        mfs     r17, rbtr;      /* ESR[DS] set - return address in BTR */
        nop
@@ -439,7 +441,7 @@ _no_delayslot:
        RESTORE_STATE;
        bri     unaligned_data_trap
 #endif
-       andi    r6, r3, 0x3E0; /* Mask and extract the register operand */
+       andi    r6, r4, 0x3E0; /* Mask and extract the register operand */
        srl     r6, r6; /* r6 >> 5 */
        srl     r6, r6;
        srl     r6, r6;
@@ -448,33 +450,33 @@ _no_delayslot:
        /* Store the register operand in a temporary location */
        sbi     r6, r0, TOPHYS(ex_reg_op);
 
-       andi    r6, r3, 0x400; /* Extract ESR[S] */
+       andi    r6, r4, 0x400; /* Extract ESR[S] */
        bnei    r6, ex_sw;
 ex_lw:
-       andi    r6, r3, 0x800; /* Extract ESR[W] */
+       andi    r6, r4, 0x800; /* Extract ESR[W] */
        beqi    r6, ex_lhw;
-       lbui    r5, r4, 0; /* Exception address in r4 */
+       lbui    r5, r3, 0; /* Exception address in r3 */
        /* Load a word, byte-by-byte from destination address
                and save it in tmp space */
        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_0);
-       lbui    r5, r4, 1;
+       lbui    r5, r3, 1;
        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_1);
-       lbui    r5, r4, 2;
+       lbui    r5, r3, 2;
        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_2);
-       lbui    r5, r4, 3;
+       lbui    r5, r3, 3;
        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_3);
-       /* Get the destination register value into r3 */
-       lwi     r3, r0, TOPHYS(ex_tmp_data_loc_0);
+       /* Get the destination register value into r4 */
+       lwi     r4, r0, TOPHYS(ex_tmp_data_loc_0);
        bri     ex_lw_tail;
 ex_lhw:
-       lbui    r5, r4, 0; /* Exception address in r4 */
+       lbui    r5, r3, 0; /* Exception address in r3 */
        /* Load a half-word, byte-by-byte from destination
                address and save it in tmp space */
        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_0);
-       lbui    r5, r4, 1;
+       lbui    r5, r3, 1;
        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_1);
-       /* Get the destination register value into r3 */
-       lhui    r3, r0, TOPHYS(ex_tmp_data_loc_0);
+       /* Get the destination register value into r4 */
+       lhui    r4, r0, TOPHYS(ex_tmp_data_loc_0);
 ex_lw_tail:
        /* Get the destination register number into r5 */
        lbui    r5, r0, TOPHYS(ex_reg_op);
@@ -502,25 +504,25 @@ ex_sw_tail:
        andi    r6, r6, 0x800; /* Extract ESR[W] */
        beqi    r6, ex_shw;
        /* Get the word - delay slot */
-       swi     r3, r0, TOPHYS(ex_tmp_data_loc_0);
+       swi     r4, r0, TOPHYS(ex_tmp_data_loc_0);
        /* Store the word, byte-by-byte into destination address */
-       lbui    r3, r0, TOPHYS(ex_tmp_data_loc_0);
-       sbi     r3, r4, 0;
-       lbui    r3, r0, TOPHYS(ex_tmp_data_loc_1);
-       sbi     r3, r4, 1;
-       lbui    r3, r0, TOPHYS(ex_tmp_data_loc_2);
-       sbi     r3, r4, 2;
-       lbui    r3, r0, TOPHYS(ex_tmp_data_loc_3);
-       sbi     r3, r4, 3;
+       lbui    r4, r0, TOPHYS(ex_tmp_data_loc_0);
+       sbi     r4, r3, 0;
+       lbui    r4, r0, TOPHYS(ex_tmp_data_loc_1);
+       sbi     r4, r3, 1;
+       lbui    r4, r0, TOPHYS(ex_tmp_data_loc_2);
+       sbi     r4, r3, 2;
+       lbui    r4, r0, TOPHYS(ex_tmp_data_loc_3);
+       sbi     r4, r3, 3;
        bri     ex_handler_done;
 
 ex_shw:
        /* Store the lower half-word, byte-by-byte into destination address */
-       swi     r3, r0, TOPHYS(ex_tmp_data_loc_0);
-       lbui    r3, r0, TOPHYS(ex_tmp_data_loc_2);
-       sbi     r3, r4, 0;
-       lbui    r3, r0, TOPHYS(ex_tmp_data_loc_3);
-       sbi     r3, r4, 1;
+       swi     r4, r0, TOPHYS(ex_tmp_data_loc_0);
+       lbui    r4, r0, TOPHYS(ex_tmp_data_loc_2);
+       sbi     r4, r3, 0;
+       lbui    r4, r0, TOPHYS(ex_tmp_data_loc_3);
+       sbi     r4, r3, 1;
 ex_sw_end: /* Exception handling of store word, ends. */
 
 ex_handler_done:
@@ -560,21 +562,16 @@ ex_handler_done:
                 */
                mfs     r11, rpid
                nop
-               bri     4
-               mfs     r3, rear                /* Get faulting address */
-               nop
                /* If we are faulting a kernel address, we have to use the
                 * kernel page tables.
                 */
-               ori     r4, r0, CONFIG_KERNEL_START
-               cmpu    r4, r3, r4
-               bgti    r4, ex3
+               ori     r5, r0, CONFIG_KERNEL_START
+               cmpu    r5, r3, r5
+               bgti    r5, ex3
                /* First, check if it was a zone fault (which means a user
                 * tried to access a kernel or read-protected page - always
                 * a SEGV). All other faults here must be stores, so no
                 * need to check ESR_S as well. */
-               mfs     r4, resr
-               nop
                andi    r4, r4, 0x800           /* ESR_Z - zone protection */
                bnei    r4, ex2
 
@@ -589,8 +586,6 @@ ex_handler_done:
                 * tried to access a kernel or read-protected page - always
                 * a SEGV). All other faults here must be stores, so no
                 * need to check ESR_S as well. */
-               mfs     r4, resr
-               nop
                andi    r4, r4, 0x800           /* ESR_Z */
                bnei    r4, ex2
                /* get current task address */
@@ -665,8 +660,6 @@ ex_handler_done:
                 * R3 = ESR
                 */
 
-               mfs     r3, rear                /* Get faulting address */
-               nop
                RESTORE_STATE;
                bri     page_fault_instr_trap
 
@@ -677,18 +670,15 @@ ex_handler_done:
         */
        handle_data_tlb_miss_exception:
                /* Working registers already saved: R3, R4, R5, R6
-                * R3 = ESR
+                * R3 = EAR, R4 = ESR
                 */
                mfs     r11, rpid
                nop
-               bri     4
-               mfs     r3, rear                /* Get faulting address */
-               nop
 
                /* If we are faulting a kernel address, we have to use the
                 * kernel page tables. */
-               ori     r4, r0, CONFIG_KERNEL_START
-               cmpu    r4, r3, r4
+               ori     r6, r0, CONFIG_KERNEL_START
+               cmpu    r4, r3, r6
                bgti    r4, ex5
                ori     r4, r0, swapper_pg_dir
                mts     rpid, r0                /* TLB will have 0 TID */
@@ -731,9 +721,8 @@ ex_handler_done:
                 * Many of these bits are software only. Bits we don't set
                 * here we (properly should) assume have the appropriate value.
                 */
+               brid    finish_tlb_load
                andni   r4, r4, 0x0ce2          /* Make sure 20, 21 are zero */
-
-               bri     finish_tlb_load
        ex7:
                /* The bailout. Restore registers to pre-exception conditions
                 * and call the heavyweights to help us out.
@@ -754,9 +743,6 @@ ex_handler_done:
                 */
                mfs     r11, rpid
                nop
-               bri     4
-               mfs     r3, rear                /* Get faulting address */
-               nop
 
                /* If we are faulting a kernel address, we have to use the
                 * kernel page tables.
@@ -792,7 +778,7 @@ ex_handler_done:
                lwi     r4, r5, 0               /* Get Linux PTE */
 
                andi    r6, r4, _PAGE_PRESENT
-               beqi    r6, ex7
+               beqi    r6, ex10
 
                ori     r4, r4, _PAGE_ACCESSED
                swi     r4, r5, 0
@@ -805,9 +791,8 @@ ex_handler_done:
                 * Many of these bits are software only. Bits we don't set
                 * here we (properly should) assume have the appropriate value.
                 */
+               brid    finish_tlb_load
                andni   r4, r4, 0x0ce2          /* Make sure 20, 21 are zero */
-
-               bri     finish_tlb_load
        ex10:
                /* The bailout. Restore registers to pre-exception conditions
                 * and call the heavyweights to help us out.
@@ -837,9 +822,9 @@ ex_handler_done:
                andi    r5, r5, (MICROBLAZE_TLB_SIZE-1)
                ori     r6, r0, 1
                cmp     r31, r5, r6
-               blti    r31, sem
+               blti    r31, ex12
                addik   r5, r6, 1
-       sem:
+       ex12:
                /* MS: save back current TLB index */
                swi     r5, r0, TOPHYS(tlb_index)
 
@@ -859,7 +844,6 @@ ex_handler_done:
                nop
 
                /* Done...restore registers and get out of here. */
-       ex12:
                mts     rpid, r11
                nop
                bri 4
index df16c6287a8e54b1ca8e36a10c6f2fe2875d9ff2..7cf86498326cc4eafc0db81a8de13ff06bc654bc 100644 (file)
  * We avoid flushing the pinned 0, 1 and possibly 2 entries.
  */
 .globl _tlbia;
+.type  _tlbia, @function
 .align 4;
 _tlbia:
-       addik   r12, r0, 63 /* flush all entries (63 - 3) */
+       addik   r12, r0, MICROBLAZE_TLB_SIZE - 1 /* flush all entries (63 - 3) */
        /* isync */
 _tlbia_1:
        mts     rtlbx, r12
@@ -41,11 +42,13 @@ _tlbia_1:
        /* sync */
        rtsd    r15, 8
        nop
+       .size  _tlbia, . - _tlbia
 
 /*
  * Flush MMU TLB for a particular address (in r5)
  */
 .globl _tlbie;
+.type  _tlbie, @function
 .align 4;
 _tlbie:
        mts     rtlbsx, r5 /* look up the address in TLB */
@@ -59,17 +62,20 @@ _tlbie_1:
        rtsd    r15, 8
        nop
 
+       .size  _tlbie, . - _tlbie
+
 /*
  * Allocate TLB entry for early console
  */
 .globl early_console_reg_tlb_alloc;
+.type  early_console_reg_tlb_alloc, @function
 .align 4;
 early_console_reg_tlb_alloc:
        /*
         * Load a TLB entry for the UART, so that microblaze_progress() can use
         * the UARTs nice and early.  We use a 4k real==virtual mapping.
         */
-       ori     r4, r0, 63
+       ori     r4, r0, MICROBLAZE_TLB_SIZE - 1
        mts     rtlbx, r4 /* TLB slot 2 */
 
        or      r4,r5,r0
@@ -86,6 +92,8 @@ early_console_reg_tlb_alloc:
        rtsd    r15, 8
        nop
 
+       .size  early_console_reg_tlb_alloc, . - early_console_reg_tlb_alloc
+
 /*
  * Copy a whole page (4096 bytes).
  */
@@ -104,6 +112,7 @@ early_console_reg_tlb_alloc:
 #define DCACHE_LINE_BYTES (4 * 4)
 
 .globl copy_page;
+.type  copy_page, @function
 .align 4;
 copy_page:
        ori     r11, r0, (PAGE_SIZE/DCACHE_LINE_BYTES) - 1
@@ -118,3 +127,5 @@ _copy_page_loop:
        addik   r11, r11, -1
        rtsd    r15, 8
        nop
+
+       .size  copy_page, . - copy_page
index 812f1bf06c9e5cbfb2a88222974e2931d20f9a24..09bed44dfcd35a5f2300405f9e208982e7208798 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/bitops.h>
 #include <asm/system.h>
 #include <asm/pgalloc.h>
+#include <asm/uaccess.h> /* for USER_DS macros */
 #include <asm/cacheflush.h>
 
 void show_regs(struct pt_regs *regs)
@@ -74,7 +75,10 @@ __setup("hlt", hlt_setup);
 
 void default_idle(void)
 {
-       if (!hlt_counter) {
+       if (likely(hlt_counter)) {
+               while (!need_resched())
+                       cpu_relax();
+       } else {
                clear_thread_flag(TIF_POLLING_NRFLAG);
                smp_mb__after_clear_bit();
                local_irq_disable();
@@ -82,9 +86,7 @@ void default_idle(void)
                        cpu_sleep();
                local_irq_enable();
                set_thread_flag(TIF_POLLING_NRFLAG);
-       } else
-               while (!need_resched())
-                       cpu_relax();
+       }
 }
 
 void cpu_idle(void)
index f974ec7aa357e5b363c9c6a116ff9e0eee5ccee1..17c98dbcec888f698e2c038eee317ddef7e1f7da 100644 (file)
@@ -92,6 +92,12 @@ inline unsigned get_romfs_len(unsigned *addr)
 }
 #endif /* CONFIG_MTD_UCLINUX_EBSS */
 
+#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
+#define eprintk early_printk
+#else
+#define eprintk printk
+#endif
+
 void __init machine_early_init(const char *cmdline, unsigned int ram,
                unsigned int fdt, unsigned int msr)
 {
@@ -139,32 +145,32 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
        setup_early_printk(NULL);
 #endif
 
-       early_printk("Ramdisk addr 0x%08x, ", ram);
+       eprintk("Ramdisk addr 0x%08x, ", ram);
        if (fdt)
-               early_printk("FDT at 0x%08x\n", fdt);
+               eprintk("FDT at 0x%08x\n", fdt);
        else
-               early_printk("Compiled-in FDT at 0x%08x\n",
+               eprintk("Compiled-in FDT at 0x%08x\n",
                                        (unsigned int)_fdt_start);
 
 #ifdef CONFIG_MTD_UCLINUX
-       early_printk("Found romfs @ 0x%08x (0x%08x)\n",
+       eprintk("Found romfs @ 0x%08x (0x%08x)\n",
                        romfs_base, romfs_size);
-       early_printk("#### klimit %p ####\n", old_klimit);
+       eprintk("#### klimit %p ####\n", old_klimit);
        BUG_ON(romfs_size < 0); /* What else can we do? */
 
-       early_printk("Moved 0x%08x bytes from 0x%08x to 0x%08x\n",
+       eprintk("Moved 0x%08x bytes from 0x%08x to 0x%08x\n",
                        romfs_size, romfs_base, (unsigned)&_ebss);
 
-       early_printk("New klimit: 0x%08x\n", (unsigned)klimit);
+       eprintk("New klimit: 0x%08x\n", (unsigned)klimit);
 #endif
 
 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
        if (msr)
-               early_printk("!!!Your kernel has setup MSR instruction but "
+               eprintk("!!!Your kernel has setup MSR instruction but "
                                "CPU don't have it %d\n", msr);
 #else
        if (!msr)
-               early_printk("!!!Your kernel not setup MSR instruction but "
+               eprintk("!!!Your kernel not setup MSR instruction but "
                                "CPU have it %d\n", msr);
 #endif
 
index eaaaf805f31b6d32039376df4f0e9ffdec777b5d..5e4570ef515c5fd97937596814d7b8d9ee321d0c 100644 (file)
@@ -22,13 +22,11 @@ void trap_init(void)
        __enable_hw_exceptions();
 }
 
-static int kstack_depth_to_print = 24;
+static unsigned long kstack_depth_to_print = 24;
 
 static int __init kstack_setup(char *s)
 {
-       kstack_depth_to_print = strict_strtoul(s, 0, NULL);
-
-       return 1;
+       return !strict_strtoul(s, 0, &kstack_depth_to_print);
 }
 __setup("kstack=", kstack_setup);
 
index b579db068c06fd3346a1458879145ef8f50063b3..4dfe47d3cd916e51ad21e25eb674afea71ff8551 100644 (file)
@@ -10,5 +10,4 @@ else
 lib-y += memcpy.o memmove.o
 endif
 
-lib-$(CONFIG_NO_MMU) += uaccess.o
-lib-$(CONFIG_MMU) += uaccess_old.o
+lib-y += uaccess_old.o
index 02e3ab4eddf3a2a29c742cf6d5b44ca9fe7bc1e0..fdc48bb065d89fe3b2443ef054d1a6ece3744b54 100644 (file)
@@ -30,8 +30,9 @@
  */
 
 #include <linux/linkage.h>
-
+       .text
        .globl  memcpy
+       .type  memcpy, @function
        .ent    memcpy
 
 memcpy:
@@ -345,9 +346,11 @@ a_done:
        rtsd    r15, 8
        nop
 
+.size  memcpy, . - memcpy
 .end memcpy
 /*----------------------------------------------------------------------------*/
        .globl  memmove
+       .type  memmove, @function
        .ent    memmove
 
 memmove:
@@ -659,4 +662,5 @@ d_done:
        rtsd    r15, 8
        nop
 
+.size  memmove, . - memmove
 .end memmove
index cc2108b6b2602180dc11fbb559d4b090359ef35c..014bac92bdff74553595280c0be125a7b17cfcfb 100644 (file)
@@ -53,7 +53,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
        const uint32_t *i_src;
        uint32_t *i_dst;
 
-       if (c >= 4) {
+       if (likely(c >= 4)) {
                unsigned  value, buf_hold;
 
                /* Align the dstination to a word boundry. */
index 4df851d41a2966f992c09ec8f571fe4fd2f0eee2..ecfb663e1fc159dc33a922b894910f4912d6ed09 100644 (file)
 #ifdef __HAVE_ARCH_MEMSET
 void *memset(void *v_src, int c, __kernel_size_t n)
 {
-
        char *src = v_src;
 #ifdef CONFIG_OPT_LIB_FUNCTION
        uint32_t *i_src;
-       uint32_t w32;
+       uint32_t w32 = 0;
 #endif
        /* Truncate c to 8 bits */
        c = (c & 0xFF);
 
 #ifdef CONFIG_OPT_LIB_FUNCTION
-       /* Make a repeating word out of it */
-       w32 = c;
-       w32 |= w32 << 8;
-       w32 |= w32 << 16;
+       if (unlikely(c)) {
+               /* Make a repeating word out of it */
+               w32 = c;
+               w32 |= w32 << 8;
+               w32 |= w32 << 16;
+       }
 
-       if (n >= 4) {
+       if (likely(n >= 4)) {
                /* Align the destination to a word boundary */
                /* This is done in an endian independant manner */
                switch ((unsigned) src & 3) {
diff --git a/arch/microblaze/lib/uaccess.c b/arch/microblaze/lib/uaccess.c
deleted file mode 100644 (file)
index a853fe0..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/string.h>
-#include <asm/uaccess.h>
-
-#include <asm/bug.h>
-
-long strnlen_user(const char __user *src, long count)
-{
-       return strlen(src) + 1;
-}
-
-#define __do_strncpy_from_user(dst, src, count, res)                   \
-       do {                                                            \
-               char *tmp;                                              \
-               strncpy(dst, src, count);                               \
-               for (tmp = dst; *tmp && count > 0; tmp++, count--)      \
-                       ;                                               \
-               res = (tmp - dst);                                      \
-       } while (0)
-
-long __strncpy_from_user(char *dst, const char __user *src, long count)
-{
-       long res;
-       __do_strncpy_from_user(dst, src, count, res);
-       return res;
-}
-
-long strncpy_from_user(char *dst, const char __user *src, long count)
-{
-       long res = -EFAULT;
-       if (access_ok(VERIFY_READ, src, 1))
-               __do_strncpy_from_user(dst, src, count, res);
-       return res;
-}
-
-unsigned long __copy_tofrom_user(void __user *to,
-               const void __user *from, unsigned long size)
-{
-       memcpy(to, from, size);
-       return 0;
-}
index 67f991c14b8a5f24edcd5aa660555368cc3259e6..5810cec54a7a36e356d5c48b4ad29923ee0829e4 100644 (file)
@@ -22,6 +22,7 @@
 
        .text
 .globl __strncpy_user;
+.type  __strncpy_user, @function
 .align 4;
 __strncpy_user:
 
@@ -50,7 +51,7 @@ __strncpy_user:
 3:
        rtsd    r15,8
        nop
-
+       .size   __strncpy_user, . - __strncpy_user
 
        .section        .fixup, "ax"
        .align  2
@@ -72,6 +73,7 @@ __strncpy_user:
 
        .text
 .globl __strnlen_user;
+.type  __strnlen_user, @function
 .align 4;
 __strnlen_user:
        addik   r3,r6,0
@@ -90,7 +92,7 @@ __strnlen_user:
 3:
        rtsd    r15,8
        nop
-
+       .size   __strnlen_user, . - __strnlen_user
 
        .section        .fixup,"ax"
 4:
@@ -108,6 +110,7 @@ __strnlen_user:
  */
        .text
 .globl __copy_tofrom_user;
+.type  __copy_tofrom_user, @function
 .align 4;
 __copy_tofrom_user:
        /*
@@ -116,20 +119,34 @@ __copy_tofrom_user:
         * r7, r3 - count
         * r4 - tempval
         */
-       addik   r3,r7,0
-       beqi    r3,3f
-1:
-       lbu     r4,r6,r0
-       addik   r6,r6,1
-2:
-       sb      r4,r5,r0
-       addik   r3,r3,-1
-       bneid   r3,1b
-       addik   r5,r5,1         /* delay slot */
+       beqid   r7, 3f /* zero size is not likely */
+       andi    r3, r7, 0x3 /* filter add count */
+       bneid   r3, 4f /* if is odd value then byte copying */
+       or      r3, r5, r6 /* find if is any to/from unaligned */
+       andi    r3, r3, 0x3 /* mask unaligned */
+       bneid   r3, 1f /* it is unaligned -> then jump */
+       or      r3, r0, r0
+
+/* at least one 4 byte copy */
+5:     lw      r4, r6, r3
+6:     sw      r4, r5, r3
+       addik   r7, r7, -4
+       bneid   r7, 5b
+       addik   r3, r3, 4
+       addik   r3, r7, 0
+       rtsd    r15, 8
+       nop
+4:     or      r3, r0, r0
+1:     lbu     r4,r6,r3
+2:     sb      r4,r5,r3
+       addik   r7,r7,-1
+       bneid   r7,1b
+       addik   r3,r3,1         /* delay slot */
 3:
+       addik   r3,r7,0
        rtsd    r15,8
        nop
-
+       .size   __copy_tofrom_user, . - __copy_tofrom_user
 
        .section        __ex_table,"a"
-       .word   1b,3b,2b,3b
+       .word   1b,3b,2b,3b,5b,3b,6b,3b
index d9d249a66ff2eda43688483cb1cab0aba3434de9..7af87f4b2c2c73a86ff88d023e5ddfee342d6240 100644 (file)
@@ -106,7 +106,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
        regs->esr = error_code;
 
        /* On a kernel SLB miss we can only check for a valid exception entry */
-       if (kernel_mode(regs) && (address >= TASK_SIZE)) {
+       if (unlikely(kernel_mode(regs) && (address >= TASK_SIZE))) {
                printk(KERN_WARNING "kernel task_size exceed");
                _exception(SIGSEGV, regs, code, address);
        }
@@ -122,7 +122,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
        }
 #endif /* CONFIG_KGDB */
 
-       if (in_atomic() || !mm) {
+       if (unlikely(in_atomic() || !mm)) {
                if (kernel_mode(regs))
                        goto bad_area_nosemaphore;
 
@@ -150,7 +150,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
         * source.  If this is invalid we can skip the address space check,
         * thus avoiding the deadlock.
         */
-       if (!down_read_trylock(&mm->mmap_sem)) {
+       if (unlikely(!down_read_trylock(&mm->mmap_sem))) {
                if (kernel_mode(regs) && !search_exception_tables(regs->pc))
                        goto bad_area_nosemaphore;
 
@@ -158,16 +158,16 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
        }
 
        vma = find_vma(mm, address);
-       if (!vma)
+       if (unlikely(!vma))
                goto bad_area;
 
        if (vma->vm_start <= address)
                goto good_area;
 
-       if (!(vma->vm_flags & VM_GROWSDOWN))
+       if (unlikely(!(vma->vm_flags & VM_GROWSDOWN)))
                goto bad_area;
 
-       if (!is_write)
+       if (unlikely(!is_write))
                goto bad_area;
 
        /*
@@ -179,7 +179,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
         * before setting the user r1.  Thus we allow the stack to
         * expand to 1MB without further checks.
         */
-       if (address + 0x100000 < vma->vm_end) {
+       if (unlikely(address + 0x100000 < vma->vm_end)) {
 
                /* get user regs even if this fault is in kernel mode */
                struct pt_regs *uregs = current->thread.regs;
@@ -209,15 +209,15 @@ good_area:
        code = SEGV_ACCERR;
 
        /* a write */
-       if (is_write) {
-               if (!(vma->vm_flags & VM_WRITE))
+       if (unlikely(is_write)) {
+               if (unlikely(!(vma->vm_flags & VM_WRITE)))
                        goto bad_area;
        /* a read */
        } else {
                /* protection fault */
-               if (error_code & 0x08000000)
+               if (unlikely(error_code & 0x08000000))
                        goto bad_area;
-               if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+               if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC))))
                        goto bad_area;
        }
 
@@ -235,7 +235,7 @@ survive:
                        goto do_sigbus;
                BUG();
        }
-       if (fault & VM_FAULT_MAJOR)
+       if (unlikely(fault & VM_FAULT_MAJOR))
                current->maj_flt++;
        else
                current->min_flt++;
index 1608e2e1a44abcb553a82b73b18d6bacef94556f..40bc10ede097af357a83b6e306fb2cb496ba2139 100644 (file)
@@ -165,7 +165,6 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
        for (addr = begin; addr < end; addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
                init_page_count(virt_to_page(addr));
-               memset((void *)addr, 0xcc, PAGE_SIZE);
                free_page(addr);
                totalram_pages++;
        }
@@ -208,14 +207,6 @@ void __init mem_init(void)
 }
 
 #ifndef CONFIG_MMU
-/* Check against bounds of physical memory */
-int ___range_ok(unsigned long addr, unsigned long size)
-{
-       return ((addr < memory_start) ||
-               ((addr + size) > memory_end));
-}
-EXPORT_SYMBOL(___range_ok);
-
 int page_is_ram(unsigned long pfn)
 {
        return __range_ok(pfn, 0);
index 63a6fd07c48fc611ea79b7c0895750b1f7dcdbce..d31312cde6eac9adcb431825c44134507cd54cbb 100644 (file)
@@ -154,7 +154,7 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
                err = 0;
                set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT,
                                __pgprot(flags)));
-               if (mem_init_done)
+               if (unlikely(mem_init_done))
                        flush_HPTE(0, va, pmd_val(*pd));
                        /* flush_HPTE(0, va, pg); */
        }
index c1b475a941eb9d08a272f6b378cfdfa7d14cdf9c..a9b91ed3d4b9e17ae8494e17ba498d19aa43a89c 100644 (file)
@@ -28,6 +28,7 @@
 #define PPC_LLARX(t, a, b, eh) PPC_LDARX(t, a, b, eh)
 #define PPC_STLCX      stringify_in_c(stdcx.)
 #define PPC_CNTLZL     stringify_in_c(cntlzd)
+#define PPC_LR_STKOFF  16
 
 /* Move to CR, single-entry optimized version. Only available
  * on POWER4 and later.
@@ -51,6 +52,7 @@
 #define PPC_STLCX      stringify_in_c(stwcx.)
 #define PPC_CNTLZL     stringify_in_c(cntlzw)
 #define PPC_MTOCRF     stringify_in_c(mtcrf)
+#define PPC_LR_STKOFF  4
 
 #endif
 
index 2d29752cbe169ea9398fbd1381cd9eff64ec28c8..b485a87c94e13b624fb2ab969e753679977ae4f9 100644 (file)
@@ -127,3 +127,31 @@ _GLOBAL(__setup_cpu_power7)
 _GLOBAL(__restore_cpu_power7)
        /* place holder */
        blr
+
+#ifdef CONFIG_EVENT_TRACING
+/*
+ * Get a minimal set of registers for our caller's nth caller.
+ * r3 = regs pointer, r5 = n.
+ *
+ * We only get R1 (stack pointer), NIP (next instruction pointer)
+ * and LR (link register).  These are all we can get in the
+ * general case without doing complicated stack unwinding, but
+ * fortunately they are enough to do a stack backtrace, which
+ * is all we need them for.
+ */
+_GLOBAL(perf_arch_fetch_caller_regs)
+       mr      r6,r1
+       cmpwi   r5,0
+       mflr    r4
+       ble     2f
+       mtctr   r5
+1:     PPC_LL  r6,0(r6)
+       bdnz    1b
+       PPC_LL  r4,PPC_LR_STKOFF(r6)
+2:     PPC_LL  r7,0(r6)
+       PPC_LL  r7,PPC_LR_STKOFF(r7)
+       PPC_STL r6,GPR1-STACK_FRAME_OVERHEAD(r3)
+       PPC_STL r4,_NIP-STACK_FRAME_OVERHEAD(r3)
+       PPC_STL r7,_LINK-STACK_FRAME_OVERHEAD(r3)
+       blr
+#endif /* CONFIG_EVENT_TRACING */
index a97d695258297af2b9de00dfd0e42e7dc1767ff4..14e0479d3888eb8d5178fd0f0f4c851dc37ebdf4 100644 (file)
@@ -24,8 +24,8 @@
 /* Symbols defined by linker scripts */
 extern char input_data[];
 extern int input_len;
-extern int _text;
-extern int _end;
+extern char _text, _end;
+extern char _bss, _ebss;
 
 static void error(char *m);
 
@@ -129,12 +129,12 @@ unsigned long decompress_kernel(void)
        unsigned long output_addr;
        unsigned char *output;
 
+       check_ipl_parmblock((void *) 0, (unsigned long) output + SZ__bss_start);
+       memset(&_bss, 0, &_ebss - &_bss);
        free_mem_ptr = (unsigned long)&_end;
        free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
        output = (unsigned char *) ((free_mem_end_ptr + 4095UL) & -4096UL);
 
-       check_ipl_parmblock((void *) 0, (unsigned long) output + SZ__bss_start);
-
 #ifdef CONFIG_BLK_DEV_INITRD
        /*
         * Move the initrd right behind the end of the decompressed
index 67ee6c3c6bb3aa352484c94449c135315b0763ec..1741c1556a4e975ccc9fa7c655f45bb91fd0a530 100644 (file)
@@ -110,6 +110,7 @@ extern void pfault_fini(void);
 #endif /* CONFIG_PFAULT */
 
 extern void cmma_init(void);
+extern int memcpy_real(void *, void *, size_t);
 
 #define finish_arch_switch(prev) do {                                       \
        set_fs(current->thread.mm_segment);                                  \
@@ -218,8 +219,8 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
                        "       l       %0,%2\n"
                        "0:     nr      %0,%5\n"
                        "       lr      %1,%0\n"
-                       "       or      %0,%2\n"
-                       "       or      %1,%3\n"
+                       "       or      %0,%3\n"
+                       "       or      %1,%4\n"
                        "       cs      %0,%1,%2\n"
                        "       jnl     1f\n"
                        "       xr      %1,%0\n"
@@ -239,8 +240,8 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
                        "       l       %0,%2\n"
                        "0:     nr      %0,%5\n"
                        "       lr      %1,%0\n"
-                       "       or      %0,%2\n"
-                       "       or      %1,%3\n"
+                       "       or      %0,%3\n"
+                       "       or      %1,%4\n"
                        "       cs      %0,%1,%2\n"
                        "       jnl     1f\n"
                        "       xr      %1,%0\n"
index ca4a62bd862fc8507966c1efdf64e41cae6efe20..9d1f76702d47acd67d3114c49057f363e7133d6d 100644 (file)
@@ -517,7 +517,10 @@ startup:
        lhi     %r1,2                   # mode 2 = esame (dump)
        sigp    %r1,%r0,0x12            # switch to esame mode
        sam64                           # switch to 64 bit mode
+       larl    %r13,4f
+       lmh     %r0,%r15,0(%r13)        # clear high-order half
        jg      startup_continue
+4:     .fill   16,4,0x0
 #else
        mvi     __LC_AR_MODE_ID,0       # set ESA flag (mode 0)
        l       %r13,4f-.LPG0(%r13)
index 39580e768658e0b23f76587b6fb59e5c000936f1..1f70970de0aa2b0fae5f0c428475e21e82d73100 100644 (file)
@@ -21,7 +21,6 @@ startup_continue:
        larl    %r1,sched_clock_base_cc
        mvc     0(8,%r1),__LC_LAST_UPDATE_CLOCK
        larl    %r13,.LPG1              # get base
-       lmh     %r0,%r15,.Lzero64-.LPG1(%r13)   # clear high-order half
        lctlg   %c0,%c15,.Lctl-.LPG1(%r13)      # load control registers
        lg      %r12,.Lparmaddr-.LPG1(%r13)     # pointer to parameter area
                                        # move IPL device to lowcore
@@ -67,7 +66,6 @@ startup_continue:
 .L4malign:.quad 0xffffffffffc00000
 .Lscan2g:.quad 0x80000000 + 0x20000 - 8        # 2GB + 128K - 8
 .Lnop: .long   0x07000700
-.Lzero64:.fill 16,4,0x0
 .Lparmaddr:
        .quad   PARMAREA
        .align  64
index 77a63ae419f00c8196a5e8cc944ac6224795ad2f..ba363d99de43769100fe082cf9a97ef36aa3a0c5 100644 (file)
@@ -401,7 +401,7 @@ setup_lowcore(void)
         * Setup lowcore for boot cpu
         */
        BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);
-       lc = __alloc_bootmem(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
+       lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
        lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
        lc->restart_psw.addr =
                PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
@@ -433,7 +433,7 @@ setup_lowcore(void)
 #ifndef CONFIG_64BIT
        if (MACHINE_HAS_IEEE) {
                lc->extended_save_area_addr = (__u32)
-                       __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
+                       __alloc_bootmem_low(PAGE_SIZE, PAGE_SIZE, 0);
                /* enable extended save area */
                __ctl_set_bit(14, 29);
        }
index 29f65bce55e1bea4cac1e9c00297a0fb7eda371a..d7d24fc3d6b73de8ebdee72126cb9b0f91db16e0 100644 (file)
@@ -292,9 +292,9 @@ static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
        zfcpdump_save_areas[cpu] = kmalloc(sizeof(struct save_area), GFP_KERNEL);
        while (raw_sigp(phy_cpu, sigp_stop_and_store_status) == sigp_busy)
                cpu_relax();
-       memcpy(zfcpdump_save_areas[cpu],
-              (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
-              sizeof(struct save_area));
+       memcpy_real(zfcpdump_save_areas[cpu],
+                   (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
+                   sizeof(struct save_area));
 }
 
 struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
index 81756271dc44a51848f26f93bab6c5b2a066982a..a8c2af8c650fabd9c96a4f9efaf3c0c4f530f294 100644 (file)
@@ -59,3 +59,29 @@ long probe_kernel_write(void *dst, void *src, size_t size)
        }
        return copied < 0 ? -EFAULT : 0;
 }
+
+int memcpy_real(void *dest, void *src, size_t count)
+{
+       register unsigned long _dest asm("2") = (unsigned long) dest;
+       register unsigned long _len1 asm("3") = (unsigned long) count;
+       register unsigned long _src  asm("4") = (unsigned long) src;
+       register unsigned long _len2 asm("5") = (unsigned long) count;
+       unsigned long flags;
+       int rc = -EFAULT;
+
+       if (!count)
+               return 0;
+       flags = __raw_local_irq_stnsm(0xf8UL);
+       asm volatile (
+               "0:     mvcle   %1,%2,0x0\n"
+               "1:     jo      0b\n"
+               "       lhi     %0,0x0\n"
+               "2:\n"
+               EX_TABLE(1b,2b)
+               : "+d" (rc), "+d" (_dest), "+d" (_src), "+d" (_len1),
+                 "+d" (_len2), "=m" (*((long *) dest))
+               : "m" (*((long *) src))
+               : "cc", "memory");
+       __raw_local_irq_ssm(flags);
+       return rc;
+}
index 39ed8722d11ad0b12469e6d17d4a98b671328634..6c13b92742e8de0d6410fbf0e3fc9553852d5e75 100644 (file)
@@ -836,6 +836,8 @@ static void __init sh_eth_init(struct sh_eth_plat_data *pd)
                pd->mac_addr[i] = mac_read(a, 0x10 + i);
                msleep(10);
        }
+
+       i2c_put_adapter(a);
 }
 #else
 static void __init sh_eth_init(struct sh_eth_plat_data *pd)
index 66cdbc3c7af9d0ae5e131099da29221fc997b8fd..ccaa290e9aba1cb29222cde90819cecb2f246cc6 100644 (file)
  * and change SW41 to use 720p
  */
 
+/*
+ * about sound
+ *
+ * This setup.c supports FSI slave mode.
+ * Please change J20, J21, J22 pin to 1-2 connection.
+ */
+
 /* Heartbeat */
 static struct resource heartbeat_resource = {
        .start  = PA_LED,
@@ -276,6 +283,7 @@ static struct clk fsimcka_clk = {
        .rate           = 0, /* unknown */
 };
 
+/* change J20, J21, J22 pin to 1-2 connection to use slave mode */
 struct sh_fsi_platform_info fsi_info = {
        .porta_flags = SH_FSI_BRS_INV |
                       SH_FSI_OUT_SLAVE_MODE |
index 18e3356406f3cfa071794aa62901753bc4399d40..6041c66dd10ee1c22bc961262358c4dc9b3bdddb 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.33-rc2
-# Mon Jan  4 11:20:36 2010
+# Linux kernel version: 2.6.34-rc2
+# Mon Mar 29 02:21:58 2010
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
@@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_IRQ_PER_CPU=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
@@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_ARCH_HAS_DEFAULT_IDLE=y
 CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
 CONFIG_DMA_NONCOHERENT=y
+CONFIG_NEED_DMA_MAP_STATE=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 CONFIG_CONSTRUCTORS=y
 
@@ -47,9 +48,11 @@ CONFIG_LOCALVERSION=""
 CONFIG_HAVE_KERNEL_GZIP=y
 CONFIG_HAVE_KERNEL_BZIP2=y
 CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
 CONFIG_KERNEL_GZIP=y
 # CONFIG_KERNEL_BZIP2 is not set
 # CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
@@ -71,14 +74,8 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_TREE_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_GROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
@@ -107,7 +104,7 @@ CONFIG_PERF_USE_VMALLOC=y
 #
 # Kernel Performance Events And Counters
 #
-# CONFIG_PERF_EVENTS is not set
+CONFIG_PERF_EVENTS=y
 # CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_COMPAT_BRK=y
@@ -116,13 +113,13 @@ CONFIG_SLAB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
 CONFIG_HAVE_OPROFILE=y
-CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_HAVE_CLK=y
 CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
 
 #
 # GCOV-based kernel profiling
@@ -234,12 +231,12 @@ CONFIG_CPU_SUBTYPE_SH7724=y
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
-CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_FORCE_MAX_ZONEORDER=12
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x10000000
 CONFIG_29BIT=y
-# CONFIG_PMB_ENABLE is not set
-# CONFIG_X2TLB is not set
+# CONFIG_PMB is not set
+CONFIG_X2TLB=y
 CONFIG_VSYSCALL=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
@@ -247,6 +244,8 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y
 CONFIG_MAX_ACTIVE_REGIONS=1
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_IOREMAP_FIXED=y
+CONFIG_UNCACHED_MAPPING=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
@@ -262,7 +261,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
-CONFIG_NR_QUICK=2
+CONFIG_NR_QUICK=1
 # CONFIG_KSM is not set
 CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
@@ -337,7 +336,6 @@ CONFIG_SECCOMP=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
-# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
@@ -347,7 +345,7 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
 CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_OVERWRITE=y
 # CONFIG_CMDLINE_EXTEND is not set
-CONFIG_CMDLINE="console=tty0, console=ttySC0,115200 root=/dev/nfs ip=dhcp mem=120M memchunk.vpu=4m"
+CONFIG_CMDLINE="console=tty0, console=ttySC0,115200 root=/dev/nfs ip=dhcp mem=248M memchunk.vpu=8m memchunk.veu0=4m"
 
 #
 # Bus options
@@ -373,6 +371,7 @@ CONFIG_SUSPEND=y
 CONFIG_SUSPEND_FREEZER=y
 # CONFIG_HIBERNATION is not set
 CONFIG_PM_RUNTIME=y
+CONFIG_PM_OPS=y
 # CONFIG_CPU_IDLE is not set
 CONFIG_NET=y
 
@@ -380,7 +379,6 @@ CONFIG_NET=y
 # Networking options
 #
 CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -445,7 +443,45 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_CAN is not set
-# CONFIG_IRDA is not set
+CONFIG_IRDA=y
+
+#
+# IrDA protocols
+#
+# CONFIG_IRLAN is not set
+# CONFIG_IRCOMM is not set
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+CONFIG_SH_SIR=y
+# CONFIG_KINGSUN_DONGLE is not set
+# CONFIG_KSDAZZLE_DONGLE is not set
+# CONFIG_KS959_DONGLE is not set
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+# CONFIG_MCS_FIR is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
 CONFIG_WIRELESS=y
@@ -556,6 +592,7 @@ CONFIG_MTD_NAND_IDS=y
 # CONFIG_MTD_NAND_NANDSIM is not set
 # CONFIG_MTD_NAND_PLATFORM is not set
 # CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_NAND_SH_FLCTL is not set
 # CONFIG_MTD_ONENAND is not set
 
 #
@@ -597,6 +634,7 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_ISL29003 is not set
+# CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_DS1682 is not set
 # CONFIG_TI_DAC7512 is not set
 # CONFIG_C2PORT is not set
@@ -616,6 +654,7 @@ CONFIG_HAVE_IDE=y
 #
 # SCSI device support
 #
+CONFIG_SCSI_MOD=y
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_DMA=y
@@ -768,7 +807,29 @@ CONFIG_KEYBOARD_SH_KEYSC=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+CONFIG_TOUCHSCREEN_TSC2007=y
+# CONFIG_TOUCHSCREEN_W90X900 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -802,10 +863,10 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=6
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_IPMI_HANDLER is not set
 CONFIG_HW_RANDOM=y
 # CONFIG_HW_RANDOM_TIMERIOMEM is not set
@@ -830,6 +891,7 @@ CONFIG_I2C_HELPER_AUTO=y
 # CONFIG_I2C_OCORES is not set
 CONFIG_I2C_SH_MOBILE=y
 # CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
 
 #
 # External I2C/SMBus adapter drivers
@@ -843,15 +905,9 @@ CONFIG_I2C_SH_MOBILE=y
 #
 # CONFIG_I2C_PCA_PLATFORM is not set
 # CONFIG_I2C_STUB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
 CONFIG_SPI=y
 CONFIG_SPI_MASTER=y
 
@@ -882,13 +938,16 @@ CONFIG_GPIOLIB=y
 #
 # Memory mapped GPIO expanders:
 #
+# CONFIG_GPIO_IT8761E is not set
 
 #
 # I2C GPIO expanders:
 #
+# CONFIG_GPIO_MAX7300 is not set
 # CONFIG_GPIO_MAX732X is not set
 # CONFIG_GPIO_PCA953X is not set
 # CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
 
 #
 # PCI GPIO expanders:
@@ -919,23 +978,26 @@ CONFIG_SSB_POSSIBLE=y
 #
 # Multifunction device drivers
 #
-# CONFIG_MFD_CORE is not set
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_88PM860X is not set
 # CONFIG_MFD_SM501 is not set
-# CONFIG_MFD_SH_MOBILE_SDHI is not set
+CONFIG_MFD_SH_MOBILE_SDHI=y
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
 # CONFIG_TPS65010 is not set
 # CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_MAX8925 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_MFD_MC13783 is not set
 # CONFIG_AB3100_CORE is not set
 # CONFIG_EZX_PCAP is not set
-# CONFIG_MFD_88PM8607 is not set
 # CONFIG_AB4500_CORE is not set
 # CONFIG_REGULATOR is not set
 CONFIG_MEDIA_SUPPORT=y
@@ -985,10 +1047,10 @@ CONFIG_SOC_CAMERA=y
 # CONFIG_SOC_CAMERA_MT9M001 is not set
 # CONFIG_SOC_CAMERA_MT9M111 is not set
 # CONFIG_SOC_CAMERA_MT9T031 is not set
-# CONFIG_SOC_CAMERA_MT9T112 is not set
+CONFIG_SOC_CAMERA_MT9T112=y
 # CONFIG_SOC_CAMERA_MT9V022 is not set
 # CONFIG_SOC_CAMERA_RJ54N1 is not set
-# CONFIG_SOC_CAMERA_TW9910 is not set
+CONFIG_SOC_CAMERA_TW9910=y
 # CONFIG_SOC_CAMERA_PLATFORM is not set
 # CONFIG_SOC_CAMERA_OV772X is not set
 # CONFIG_SOC_CAMERA_OV9640 is not set
@@ -1001,6 +1063,7 @@ CONFIG_RADIO_ADAPTERS=y
 # CONFIG_RADIO_SI470X is not set
 # CONFIG_USB_MR800 is not set
 # CONFIG_RADIO_TEA5764 is not set
+# CONFIG_RADIO_SAA7706H is not set
 # CONFIG_RADIO_TEF6862 is not set
 # CONFIG_DAB is not set
 
@@ -1034,6 +1097,7 @@ CONFIG_FB_DEFERRED_IO=y
 #
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_SH_MOBILE_LCDC=y
+# CONFIG_FB_TMIO is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
 # CONFIG_FB_MB862XX is not set
@@ -1062,7 +1126,46 @@ CONFIG_LOGO=y
 # CONFIG_LOGO_SUPERH_MONO is not set
 # CONFIG_LOGO_SUPERH_VGA16 is not set
 CONFIG_LOGO_SUPERH_CLUT224=y
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_SEQ_DUMMY=y
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_SEQUENCER_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SUPERH=y
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+
+#
+# SoC Audio support for SuperH
+#
+CONFIG_SND_SOC_SH4_FSI=y
+# CONFIG_SND_FSI_AK4642 is not set
+CONFIG_SND_FSI_DA7210=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_DA7210=y
+# CONFIG_SOUND_PRIME is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 # CONFIG_HIDRAW is not set
@@ -1077,6 +1180,7 @@ CONFIG_USB_HID=y
 #
 # Special HID drivers
 #
+# CONFIG_HID_3M_PCT is not set
 # CONFIG_HID_A4TECH is not set
 # CONFIG_HID_APPLE is not set
 # CONFIG_HID_BELKIN is not set
@@ -1091,12 +1195,16 @@ CONFIG_USB_HID=y
 # CONFIG_HID_KENSINGTON is not set
 # CONFIG_HID_LOGITECH is not set
 # CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MOSART is not set
 # CONFIG_HID_MONTEREY is not set
 # CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
 # CONFIG_HID_PANTHERLORD is not set
 # CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_QUANTA is not set
 # CONFIG_HID_SAMSUNG is not set
 # CONFIG_HID_SONY is not set
+# CONFIG_HID_STANTUM is not set
 # CONFIG_HID_SUNPLUS is not set
 # CONFIG_HID_GREENASIA is not set
 # CONFIG_HID_SMARTJOYPLUS is not set
@@ -1136,6 +1244,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_SL811_HCD is not set
 CONFIG_USB_R8A66597_HCD=y
 # CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
 
 #
 # USB Device Class drivers
@@ -1188,7 +1297,6 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1200,8 +1308,45 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
-# CONFIG_USB_VST is not set
-# CONFIG_USB_GADGET is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+CONFIG_USB_GADGET_R8A66597=y
+CONFIG_USB_R8A66597=y
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_NOKIA is not set
+# CONFIG_USB_G_MULTI is not set
 
 #
 # OTG and related infrastructure
@@ -1224,10 +1369,8 @@ CONFIG_MMC_BLOCK_BOUNCE=y
 # MMC/SD/SDIO Host Controller Drivers
 #
 # CONFIG_MMC_SDHCI is not set
-# CONFIG_MMC_AT91 is not set
-# CONFIG_MMC_ATMELMCI is not set
 CONFIG_MMC_SPI=y
-# CONFIG_MMC_TMIO is not set
+CONFIG_MMC_TMIO=y
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
@@ -1253,10 +1396,10 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_DS1374 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
 # CONFIG_RTC_DRV_MAX6900 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
+CONFIG_RTC_DRV_RS5C372=y
 # CONFIG_RTC_DRV_ISL1208 is not set
 # CONFIG_RTC_DRV_X1205 is not set
-CONFIG_RTC_DRV_PCF8563=y
+# CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_BQ32K is not set
@@ -1303,8 +1446,6 @@ CONFIG_RTC_DRV_PCF8563=y
 CONFIG_UIO=y
 # CONFIG_UIO_PDRV is not set
 CONFIG_UIO_PDRV_GENIRQ=y
-# CONFIG_UIO_SMX is not set
-# CONFIG_UIO_SERCOS3 is not set
 
 #
 # TI VLYNQ
@@ -1390,6 +1531,7 @@ CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_UBIFS_FS is not set
+# CONFIG_LOGFS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1418,6 +1560,7 @@ CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
+# CONFIG_CEPH_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1487,6 +1630,7 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LKDTM is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_HAVE_FUNCTION_TRACER=y
@@ -1618,7 +1762,7 @@ CONFIG_CRYPTO_HW=y
 #
 CONFIG_BITREVERSE=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
-# CONFIG_CRC_CCITT is not set
+CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
 CONFIG_CRC_T10DIF=y
 CONFIG_CRC_ITU_T=y
index ac04255022b69548e6f71f07f0502e97664c881f..ce830faeebbf50705e1ba1126b240ea274bbd77c 100644 (file)
@@ -211,7 +211,9 @@ extern void __kernel_vsyscall;
 
 #define VSYSCALL_AUX_ENT                                       \
        if (vdso_enabled)                                       \
-               NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE);
+               NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE);        \
+       else                                                    \
+               NEW_AUX_ENT(AT_IGNORE, 0);
 #else
 #define VSYSCALL_AUX_ENT
 #endif /* CONFIG_VSYSCALL */
@@ -219,7 +221,7 @@ extern void __kernel_vsyscall;
 #ifdef CONFIG_SH_FPU
 #define FPU_AUX_ENT    NEW_AUX_ENT(AT_FPUCW, FPSCR_INIT)
 #else
-#define FPU_AUX_ENT
+#define FPU_AUX_ENT    NEW_AUX_ENT(AT_IGNORE, 0)
 #endif
 
 extern int l1i_cache_shape, l1d_cache_shape, l2_cache_shape;
index 03ea75c5315d4887380d996624e153e603d486df..5963124c1d4ad0f105605e139ea6f1e7d55cc845 100644 (file)
@@ -19,6 +19,8 @@
 
 #define MMUCR          0xFF000010      /* MMU Control Register */
 
+#define MMU_ITLB_ADDRESS_ARRAY  0xF2000000
+#define MMU_ITLB_ADDRESS_ARRAY2        0xF2800000
 #define MMU_UTLB_ADDRESS_ARRAY 0xF6000000
 #define MMU_UTLB_ADDRESS_ARRAY2        0xF6800000
 #define MMU_PAGE_ASSOC_BIT     0x80
@@ -28,6 +30,8 @@
 #define MMUCR_URB              0x00FC0000
 #define MMUCR_URB_SHIFT                18
 #define MMUCR_URB_NENTRIES     64
+#define MMUCR_URC              0x0000FC00
+#define MMUCR_URC_SHIFT                10
 
 #if defined(CONFIG_32BIT) && defined(CONFIG_CPU_SUBTYPE_ST40)
 #define MMUCR_SE               (1 << 4)
index 7672301d0c70917da242ce4e398fa5d4b84712f9..7f62b9380938203ad6d25a221db7c44424b1c46f 100644 (file)
 #define WTCNT          0xffcc0000 /*WDTST*/
 #define WTST           WTCNT
 #define WTBST          0xffcc0008 /*WDTBST*/
+/* Register definitions */
+#elif  defined(CONFIG_CPU_SUBTYPE_SH7722) || \
+       defined(CONFIG_CPU_SUBTYPE_SH7723) || \
+       defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define WTCNT          0xa4520000
+#define WTCSR          0xa4520004
 #else
 /* Register definitions */
 #define WTCNT          0xffc00008
index dce4f3ff09324f8340327379bac3ea49d6df0878..0fffacea6ed96aebda4c692ace9b1185468d74b5 100644 (file)
@@ -48,7 +48,7 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy,
                return -ENODEV;
 
        cpus_allowed = current->cpus_allowed;
-       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
        BUG_ON(smp_processor_id() != cpu);
 
@@ -66,7 +66,7 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy,
        freqs.flags     = 0;
 
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-       set_cpus_allowed(current, cpus_allowed);
+       set_cpus_allowed_ptr(current, &cpus_allowed);
        clk_set_rate(cpuclk, freq);
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
index bd1c497280a66b927b1b07e8eaa4817fd278920a..94739ee7aa74e8fc15baf1cea62adbef568beeb0 100644 (file)
@@ -727,7 +727,7 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
                           unsigned char *end, struct module *mod)
 {
        struct rb_node **rb_node = &cie_root.rb_node;
-       struct rb_node *parent;
+       struct rb_node *parent = *rb_node;
        struct dwarf_cie *cie;
        unsigned long flags;
        int count;
@@ -856,7 +856,7 @@ static int dwarf_parse_fde(void *entry, u32 entry_type,
                           unsigned char *end, struct module *mod)
 {
        struct rb_node **rb_node = &fde_root.rb_node;
-       struct rb_node *parent;
+       struct rb_node *parent = *rb_node;
        struct dwarf_fde *fde;
        struct dwarf_cie *cie;
        unsigned long flags;
index 0fd7b41f0a2242c0e6a59e4e00048f7bd7f01c25..273f890b17ae3eb0fd643473e3a62b775cb8f51a 100644 (file)
@@ -112,7 +112,7 @@ void cpu_idle(void)
        }
 }
 
-void __cpuinit select_idle_routine(void)
+void __init select_idle_routine(void)
 {
        /*
         * If a platform has set its own idle routine, leave it alone.
index 9f253e9cce01283315f000d11d7ffc08427734d3..81b6de41ae5d1c3bfb87c340acee5291a499a036 100644 (file)
@@ -315,7 +315,7 @@ void hw_perf_disable(void)
        sh_pmu->disable_all();
 }
 
-int register_sh_pmu(struct sh_pmu *pmu)
+int __cpuinit register_sh_pmu(struct sh_pmu *pmu)
 {
        if (sh_pmu)
                return -EBUSY;
index c90957a459ac9f59bf85d82f68b2c6caba917071..c0d40f671ecd6145cc31ed238b806e2ac671136f 100644 (file)
@@ -504,13 +504,6 @@ out:
        return error;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-extern void interruptible_sleep_on(wait_queue_head_t *q);
-
-#define mid_sched      ((unsigned long) interruptible_sleep_on)
-
 #ifdef CONFIG_FRAME_POINTER
 static int in_sh64_switch_to(unsigned long pc)
 {
index df3ab5811074f0bfcada56897092f9eeaed937e1..cbf1dd5372b2d223f399ab884fd46bfbd83246d1 100644 (file)
@@ -9,6 +9,7 @@
  * for more details.
  */
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <asm/dwarf.h>
 
 #ifdef CONFIG_DWARF_UNWINDER
@@ -52,3 +53,5 @@ void *return_address(unsigned int depth)
 }
 
 #endif
+
+EXPORT_SYMBOL_GPL(return_address);
index e124cf7008df46ed2e6de79f450901bd4161fbc5..002cc612deef5ce9c93499e8a2ea4043050eb189 100644 (file)
@@ -69,6 +69,7 @@ asmlinkage void __cpuinit start_secondary(void)
        unsigned int cpu;
        struct mm_struct *mm = &init_mm;
 
+       enable_mmu();
        atomic_inc(&mm->mm_count);
        atomic_inc(&mm->mm_users);
        current->active_mm = mm;
index a4662e2782c3fd84c8743dfb56394fdce971fe95..3cc21933063bf7485a8b0cf2836ef560b54da74d 100644 (file)
@@ -323,6 +323,7 @@ static void __clear_pmb_entry(struct pmb_entry *pmbe)
        writel_uncached(data_val & ~PMB_V, data);
 }
 
+#ifdef CONFIG_PM
 static void set_pmb_entry(struct pmb_entry *pmbe)
 {
        unsigned long flags;
@@ -331,6 +332,7 @@ static void set_pmb_entry(struct pmb_entry *pmbe)
        __set_pmb_entry(pmbe);
        spin_unlock_irqrestore(&pmbe->lock, flags);
 }
+#endif /* CONFIG_PM */
 
 int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
                     unsigned long size, pgprot_t prot)
@@ -802,7 +804,7 @@ void __init pmb_init(void)
        writel_uncached(0, PMB_IRMCR);
 
        /* Flush out the TLB */
-       __raw_writel(__raw_readl(MMUCR) | MMUCR_TI, MMUCR);
+       local_flush_tlb_all();
        ctrl_barrier();
 }
 
index 32dc674c550c12ec2424adaf46c5856b90a0ea72..b71db6af806088b1d3d84dd4a214b139e44a8700 100644 (file)
@@ -73,5 +73,35 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page)
        jump_to_uncached();
        __raw_writel(page, MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT);
        __raw_writel(asid, MMU_UTLB_ADDRESS_ARRAY2 | MMU_PAGE_ASSOC_BIT);
+       __raw_writel(page, MMU_ITLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT);
+       __raw_writel(asid, MMU_ITLB_ADDRESS_ARRAY2 | MMU_PAGE_ASSOC_BIT);
        back_to_cached();
 }
+
+void local_flush_tlb_all(void)
+{
+       unsigned long flags, status;
+       int i;
+
+       /*
+        * Flush all the TLB.
+        */
+       local_irq_save(flags);
+       jump_to_uncached();
+
+       status = __raw_readl(MMUCR);
+       status = ((status & MMUCR_URB) >> MMUCR_URB_SHIFT);
+
+       if (status == 0)
+               status = MMUCR_URB_NENTRIES;
+
+       for (i = 0; i < status; i++)
+               __raw_writel(0x0, MMU_UTLB_ADDRESS_ARRAY | (i << 8));
+
+       for (i = 0; i < 4; i++)
+               __raw_writel(0x0, MMU_ITLB_ADDRESS_ARRAY | (i << 8));
+
+       back_to_cached();
+       ctrl_barrier();
+       local_irq_restore(flags);
+}
index 4f5f7cbdd508e7e9f1e87f4f5404eab538118281..7a940dbfc2e9d0ecccf71c342b816a9f7bebf577 100644 (file)
@@ -77,3 +77,22 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page)
        for (i = 0; i < ways; i++)
                __raw_writel(data, addr + (i << 8));
 }
+
+void local_flush_tlb_all(void)
+{
+       unsigned long flags, status;
+
+       /*
+        * Flush all the TLB.
+        *
+        * Write to the MMU control register's bit:
+        *      TF-bit for SH-3, TI-bit for SH-4.
+        *      It's same position, bit #2.
+        */
+       local_irq_save(flags);
+       status = __raw_readl(MMUCR);
+       status |= 0x04;
+       __raw_writel(status, MMUCR);
+       ctrl_barrier();
+       local_irq_restore(flags);
+}
index ccac77f504a8532192d063ef2d423b4c4a613948..cfdf7930d2946723262ea5eaf1d1b3f1595eef2e 100644 (file)
@@ -80,3 +80,31 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page)
        __raw_writel(data, addr);
        back_to_cached();
 }
+
+void local_flush_tlb_all(void)
+{
+       unsigned long flags, status;
+       int i;
+
+       /*
+        * Flush all the TLB.
+        */
+       local_irq_save(flags);
+       jump_to_uncached();
+
+       status = __raw_readl(MMUCR);
+       status = ((status & MMUCR_URB) >> MMUCR_URB_SHIFT);
+
+       if (status == 0)
+               status = MMUCR_URB_NENTRIES;
+
+       for (i = 0; i < status; i++)
+               __raw_writel(0x0, MMU_UTLB_ADDRESS_ARRAY | (i << 8));
+
+       for (i = 0; i < 4; i++)
+               __raw_writel(0x0, MMU_ITLB_ADDRESS_ARRAY | (i << 8));
+
+       back_to_cached();
+       ctrl_barrier();
+       local_irq_restore(flags);
+}
index bb5b9098956d9157c2d1bf7c4166b20990bd99a0..c92ce20db39bf478dd6db83a0c3ed6dc430ca027 100644 (file)
@@ -24,13 +24,9 @@ void tlb_wire_entry(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
 
        local_irq_save(flags);
 
-       /* Load the entry into the TLB */
-       __update_tlb(vma, addr, pte);
-
-       /* ... and wire it up. */
        status = __raw_readl(MMUCR);
        urb = (status & MMUCR_URB) >> MMUCR_URB_SHIFT;
-       status &= ~MMUCR_URB;
+       status &= ~MMUCR_URC;
 
        /*
         * Make sure we're not trying to wire the last TLB entry slot.
@@ -39,7 +35,23 @@ void tlb_wire_entry(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
 
        urb = urb % MMUCR_URB_NENTRIES;
 
+       /*
+        * Insert this entry into the highest non-wired TLB slot (via
+        * the URC field).
+        */
+       status |= (urb << MMUCR_URC_SHIFT);
+       __raw_writel(status, MMUCR);
+       ctrl_barrier();
+
+       /* Load the entry into the TLB */
+       __update_tlb(vma, addr, pte);
+
+       /* ... and wire it up. */
+       status = __raw_readl(MMUCR);
+
+       status &= ~MMUCR_URB;
        status |= (urb << MMUCR_URB_SHIFT);
+
        __raw_writel(status, MMUCR);
        ctrl_barrier();
 
index 004bb3f25b5f5f7e080505e967fea140328d480b..3fbe03ce8fe3a665768516dd4e341e783e164e69 100644 (file)
@@ -119,22 +119,3 @@ void local_flush_tlb_mm(struct mm_struct *mm)
                local_irq_restore(flags);
        }
 }
-
-void local_flush_tlb_all(void)
-{
-       unsigned long flags, status;
-
-       /*
-        * Flush all the TLB.
-        *
-        * Write to the MMU control register's bit:
-        *      TF-bit for SH-3, TI-bit for SH-4.
-        *      It's same position, bit #2.
-        */
-       local_irq_save(flags);
-       status = __raw_readl(MMUCR);
-       status |= 0x04;
-       __raw_writel(status, MMUCR);
-       ctrl_barrier();
-       local_irq_restore(flags);
-}
index 39327d6a57eb3b60b50d5bd47473c9f14223581c..a232e9e1f4e515d19e8f089872a797c746241777 100644 (file)
@@ -53,8 +53,8 @@ struct stat {
        ino_t           st_ino;
        mode_t          st_mode;
        short           st_nlink;
-       uid16_t         st_uid;
-       gid16_t         st_gid;
+       unsigned short  st_uid;
+       unsigned short  st_gid;
        unsigned short  st_rdev;
        off_t           st_size;
        time_t          st_atime;
index 68cb9b42088f2e36a6dc28fca5ce64e6619e7d74..e2771939341d538111417aa518d5c2c9cf249b25 100644 (file)
@@ -1337,7 +1337,7 @@ static void perf_callchain_user_32(struct pt_regs *regs,
        callchain_store(entry, PERF_CONTEXT_USER);
        callchain_store(entry, regs->tpc);
 
-       ufp = regs->u_regs[UREG_I6];
+       ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
        do {
                struct sparc_stackf32 *usf, sf;
                unsigned long pc;
index ca39c606fe8e41d90506c574f5ed23c8f89d147d..1eb8b00aed75f293b5df18076e1fc3b81b2cf9c7 100644 (file)
@@ -107,12 +107,12 @@ static unsigned long run_on_cpu(unsigned long cpu,
        unsigned long ret;
 
        /* should return -EINVAL to userspace */
-       if (set_cpus_allowed(current, cpumask_of_cpu(cpu)))
+       if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
                return 0;
 
        ret = func(arg);
 
-       set_cpus_allowed(current, old_affinity);
+       set_cpus_allowed_ptr(current, &old_affinity);
 
        return ret;
 }
index 791c15138f3a4abf3cb368e12041fcd7f304842c..8f982b76c71259e7a28f1f1551629eb397023a31 100644 (file)
@@ -238,12 +238,12 @@ static unsigned int us2e_freq_get(unsigned int cpu)
                return 0;
 
        cpus_allowed = current->cpus_allowed;
-       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
        clock_tick = sparc64_get_clock_tick(cpu) / 1000;
        estar = read_hbreg(HBIRD_ESTAR_MODE_ADDR);
 
-       set_cpus_allowed(current, cpus_allowed);
+       set_cpus_allowed_ptr(current, &cpus_allowed);
 
        return clock_tick / estar_to_divisor(estar);
 }
@@ -259,7 +259,7 @@ static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index)
                return;
 
        cpus_allowed = current->cpus_allowed;
-       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
        new_freq = clock_tick = sparc64_get_clock_tick(cpu) / 1000;
        new_bits = index_to_estar_mode(index);
@@ -281,7 +281,7 @@ static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index)
 
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
-       set_cpus_allowed(current, cpus_allowed);
+       set_cpus_allowed_ptr(current, &cpus_allowed);
 }
 
 static int us2e_freq_target(struct cpufreq_policy *policy,
index 365b6464e2ce20037e27af6023aa330ba6380612..f35d1e794548eb8541bee5198f4a353f346d1e3e 100644 (file)
@@ -86,12 +86,12 @@ static unsigned int us3_freq_get(unsigned int cpu)
                return 0;
 
        cpus_allowed = current->cpus_allowed;
-       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
        reg = read_safari_cfg();
        ret = get_current_freq(cpu, reg);
 
-       set_cpus_allowed(current, cpus_allowed);
+       set_cpus_allowed_ptr(current, &cpus_allowed);
 
        return ret;
 }
@@ -106,7 +106,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)
                return;
 
        cpus_allowed = current->cpus_allowed;
-       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
        new_freq = sparc64_get_clock_tick(cpu) / 1000;
        switch (index) {
@@ -140,7 +140,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)
 
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
-       set_cpus_allowed(current, cpus_allowed);
+       set_cpus_allowed_ptr(current, &cpus_allowed);
 }
 
 static int us3_freq_target(struct cpufreq_policy *policy,
index 635f03bb499528ff7905b3b96f112a910d4c57e3..d07b44f7d1dc014b3d1cb77e49138ef5f97f5d24 100644 (file)
@@ -82,6 +82,9 @@ enum fixed_addresses {
 #endif
        FIX_DBGP_BASE,
        FIX_EARLYCON_MEM_BASE,
+#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+       FIX_OHCI1394_BASE,
+#endif
 #ifdef CONFIG_X86_LOCAL_APIC
        FIX_APIC_BASE,  /* local (CPU) APIC) -- required for SMP or not */
 #endif
@@ -132,9 +135,6 @@ enum fixed_addresses {
           (__end_of_permanent_fixed_addresses & (TOTAL_FIX_BTMAPS - 1))
         : __end_of_permanent_fixed_addresses,
        FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
-       FIX_OHCI1394_BASE,
-#endif
 #ifdef CONFIG_X86_32
        FIX_WP_TEST,
 #endif
index a929c9ede33d55db556e5fc603facb61b39d5d68..46c0fe05f230112b5aa5e176d4292e56526f8279 100644 (file)
@@ -133,6 +133,7 @@ extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void);
 
 typedef int vector_irq_t[NR_VECTORS];
 DECLARE_PER_CPU(vector_irq_t, vector_irq);
+extern void setup_vector_irq(int cpu);
 
 #ifdef CONFIG_X86_IO_APIC
 extern void lock_vector_lock(void);
index 1cd58cdbc03f2e97dee6983b5a8ea2ebef7d0061..4604e6a54d36eb2fe13fdc88b432d6c018252087 100644 (file)
 #define MSR_AMD64_PATCH_LEVEL          0x0000008b
 #define MSR_AMD64_NB_CFG               0xc001001f
 #define MSR_AMD64_PATCH_LOADER         0xc0010020
+#define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
+#define MSR_AMD64_OSVW_STATUS          0xc0010141
 #define MSR_AMD64_IBSFETCHCTL          0xc0011030
 #define MSR_AMD64_IBSFETCHLINAD                0xc0011031
 #define MSR_AMD64_IBSFETCHPHYSAD       0xc0011032
index e4e0ddcb1546bde04f0d01675756622b9d2434bd..463de9a858adb2e86399715c90e4e14b266acbc5 100644 (file)
@@ -1268,6 +1268,14 @@ void __setup_vector_irq(int cpu)
        /* Mark the inuse vectors */
        for_each_irq_desc(irq, desc) {
                cfg = desc->chip_data;
+
+               /*
+                * If it is a legacy IRQ handled by the legacy PIC, this cpu
+                * will be part of the irq_cfg's domain.
+                */
+               if (irq < legacy_pic->nr_legacy_irqs && !IO_APIC_IRQ(irq))
+                       cpumask_set_cpu(cpu, cfg->domain);
+
                if (!cpumask_test_cpu(cpu, cfg->domain))
                        continue;
                vector = cfg->vector;
index 573458f1caf23c91ab39930fc0613cf78d27d55f..b87e0b6970cbc363d2a6c4b233796416176ba09e 100644 (file)
@@ -348,10 +348,12 @@ static void amd_pmu_cpu_offline(int cpu)
 
        raw_spin_lock(&amd_nb_lock);
 
-       if (--cpuhw->amd_nb->refcnt == 0)
-               kfree(cpuhw->amd_nb);
+       if (cpuhw->amd_nb) {
+               if (--cpuhw->amd_nb->refcnt == 0)
+                       kfree(cpuhw->amd_nb);
 
-       cpuhw->amd_nb = NULL;
+               cpuhw->amd_nb = NULL;
+       }
 
        raw_spin_unlock(&amd_nb_lock);
 }
index adedeef1dedcad654c9955c88c677709fec22f6c..b2e2460373920128697e5bf7e93e3ca708de64ca 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/init.h>
 #include <linux/start_kernel.h>
+#include <linux/mm.h>
 
 #include <asm/setup.h>
 #include <asm/sections.h>
@@ -44,9 +45,10 @@ void __init i386_start_kernel(void)
 #ifdef CONFIG_BLK_DEV_INITRD
        /* Reserve INITRD */
        if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
+               /* Assume only end is not page aligned */
                u64 ramdisk_image = boot_params.hdr.ramdisk_image;
                u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
-               u64 ramdisk_end   = ramdisk_image + ramdisk_size;
+               u64 ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);
                reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
        }
 #endif
index b5a9896ca1e74be8805c4f5384ffc8d50f6589b6..7147143fd614e429392741ae13ce5577c7be5364 100644 (file)
@@ -103,9 +103,10 @@ void __init x86_64_start_reservations(char *real_mode_data)
 #ifdef CONFIG_BLK_DEV_INITRD
        /* Reserve INITRD */
        if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
+               /* Assume only end is not page aligned */
                unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
                unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
-               unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
+               unsigned long ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);
                reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
        }
 #endif
index ef257fc2921b1a0ed133493d53186e3b064e2529..f01d390f9c5be3dde9e1dcacb43bce8c2ba3f09b 100644 (file)
@@ -141,6 +141,28 @@ void __init init_IRQ(void)
        x86_init.irqs.intr_init();
 }
 
+/*
+ * Setup the vector to irq mappings.
+ */
+void setup_vector_irq(int cpu)
+{
+#ifndef CONFIG_X86_IO_APIC
+       int irq;
+
+       /*
+        * On most of the platforms, legacy PIC delivers the interrupts on the
+        * boot cpu. But there are certain platforms where PIC interrupts are
+        * delivered to multiple cpu's. If the legacy IRQ is handled by the
+        * legacy PIC, for the new cpu that is coming online, setup the static
+        * legacy vector to irq mapping:
+        */
+       for (irq = 0; irq < legacy_pic->nr_legacy_irqs; irq++)
+               per_cpu(vector_irq, cpu)[IRQ0_VECTOR + irq] = irq;
+#endif
+
+       __setup_vector_irq(cpu);
+}
+
 static void __init smp_intr_init(void)
 {
 #ifdef CONFIG_SMP
index ad9540676fccb7138917dc6520cdf88dd95b10f8..28ad9f4d8b94aa9743386f3f76f8f2e9634f6b10 100644 (file)
@@ -526,21 +526,37 @@ static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
 }
 
 /*
- * Check for AMD CPUs, which have potentially C1E support
+ * Check for AMD CPUs, where APIC timer interrupt does not wake up CPU from C1e.
+ * For more information see
+ * - Erratum #400 for NPT family 0xf and family 0x10 CPUs
+ * - Erratum #365 for family 0x11 (not affected because C1e not in use)
  */
 static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c)
 {
+       u64 val;
        if (c->x86_vendor != X86_VENDOR_AMD)
-               return 0;
-
-       if (c->x86 < 0x0F)
-               return 0;
+               goto no_c1e_idle;
 
        /* Family 0x0f models < rev F do not have C1E */
-       if (c->x86 == 0x0f && c->x86_model < 0x40)
-               return 0;
+       if (c->x86 == 0x0F && c->x86_model >= 0x40)
+               return 1;
 
-       return 1;
+       if (c->x86 == 0x10) {
+               /*
+                * check OSVW bit for CPUs that are not affected
+                * by erratum #400
+                */
+               rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val);
+               if (val >= 2) {
+                       rdmsrl(MSR_AMD64_OSVW_STATUS, val);
+                       if (!(val & BIT(1)))
+                               goto no_c1e_idle;
+               }
+               return 1;
+       }
+
+no_c1e_idle:
+       return 0;
 }
 
 static cpumask_var_t c1e_mask;
index 5d7ba1a449bde18735d58777f3f510c04eaa5280..d76e18570c60ec5b8c7e28685a3fe69751d6c575 100644 (file)
@@ -314,16 +314,17 @@ static void __init reserve_brk(void)
 #define MAX_MAP_CHUNK  (NR_FIX_BTMAPS << PAGE_SHIFT)
 static void __init relocate_initrd(void)
 {
-
+       /* Assume only end is not page aligned */
        u64 ramdisk_image = boot_params.hdr.ramdisk_image;
        u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
+       u64 area_size     = PAGE_ALIGN(ramdisk_size);
        u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
        u64 ramdisk_here;
        unsigned long slop, clen, mapaddr;
        char *p, *q;
 
        /* We need to move the initrd down into lowmem */
-       ramdisk_here = find_e820_area(0, end_of_lowmem, ramdisk_size,
+       ramdisk_here = find_e820_area(0, end_of_lowmem, area_size,
                                         PAGE_SIZE);
 
        if (ramdisk_here == -1ULL)
@@ -332,7 +333,7 @@ static void __init relocate_initrd(void)
 
        /* Note: this includes all the lowmem currently occupied by
           the initrd, we rely on that fact to keep the data intact. */
-       reserve_early(ramdisk_here, ramdisk_here + ramdisk_size,
+       reserve_early(ramdisk_here, ramdisk_here + area_size,
                         "NEW RAMDISK");
        initrd_start = ramdisk_here + PAGE_OFFSET;
        initrd_end   = initrd_start + ramdisk_size;
@@ -376,9 +377,10 @@ static void __init relocate_initrd(void)
 
 static void __init reserve_initrd(void)
 {
+       /* Assume only end is not page aligned */
        u64 ramdisk_image = boot_params.hdr.ramdisk_image;
        u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
-       u64 ramdisk_end   = ramdisk_image + ramdisk_size;
+       u64 ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);
        u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
 
        if (!boot_params.hdr.type_of_loader ||
index a02e80c3c54bedbfdcb05d8741461d0abdc6fe9d..06d98ae5a80245ad4351c90bbff28d31ddfd2245 100644 (file)
@@ -247,7 +247,7 @@ static void __cpuinit smp_callin(void)
        /*
         * Need to setup vector mappings before we enable interrupts.
         */
-       __setup_vector_irq(smp_processor_id());
+       setup_vector_irq(smp_processor_id());
        /*
         * Get our bogomips.
         *
index 44879df55696407556d711b69b0f83fdc311f7f0..2cc249718c46e47ca28dd9e48ff1691a3c39d185 100644 (file)
@@ -291,8 +291,8 @@ SECTIONS
        .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
                __smp_locks = .;
                *(.smp_locks)
-               __smp_locks_end = .;
                . = ALIGN(PAGE_SIZE);
+               __smp_locks_end = .;
        }
 
 #ifdef CONFIG_X86_64
index e71c5cbc8f3561f6ce701582377749155af587b8..452ee5b8f30909fae2da150dcbd3cf4eaa67fa08 100644 (file)
@@ -331,11 +331,23 @@ int devmem_is_allowed(unsigned long pagenr)
 
 void free_init_pages(char *what, unsigned long begin, unsigned long end)
 {
-       unsigned long addr = begin;
+       unsigned long addr;
+       unsigned long begin_aligned, end_aligned;
 
-       if (addr >= end)
+       /* Make sure boundaries are page aligned */
+       begin_aligned = PAGE_ALIGN(begin);
+       end_aligned   = end & PAGE_MASK;
+
+       if (WARN_ON(begin_aligned != begin || end_aligned != end)) {
+               begin = begin_aligned;
+               end   = end_aligned;
+       }
+
+       if (begin >= end)
                return;
 
+       addr = begin;
+
        /*
         * If debugging page accesses then do not free this memory but
         * mark them not present - any buggy init-section access will
@@ -343,7 +355,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
         */
 #ifdef CONFIG_DEBUG_PAGEALLOC
        printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
-               begin, PAGE_ALIGN(end));
+               begin, end);
        set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
 #else
        /*
@@ -358,8 +370,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
        for (; addr < end; addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
                init_page_count(virt_to_page(addr));
-               memset((void *)(addr & ~(PAGE_SIZE-1)),
-                       POISON_FREE_INITMEM, PAGE_SIZE);
+               memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
                free_page(addr);
                totalram_pages++;
        }
@@ -376,6 +387,15 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-       free_init_pages("initrd memory", start, end);
+       /*
+        * end could be not aligned, and We can not align that,
+        * decompresser could be confused by aligned initrd_end
+        * We already reserve the end partial page before in
+        *   - i386_start_kernel()
+        *   - x86_64_start_kernel()
+        *   - relocate_initrd()
+        * So here We can do PAGE_ALIGN() safely to get partial page to be freed
+        */
+       free_init_pages("initrd memory", start, PAGE_ALIGN(end));
 }
 #endif
index 6e22454bfaa6d51e4f22ce9eb5c379e1770319d6..e31160216efb382c0541dd838298c59d7702ac55 100644 (file)
@@ -122,8 +122,8 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
        struct acpi_resource_address64 addr;
        acpi_status status;
        unsigned long flags;
-       struct resource *root;
-       u64 start, end;
+       struct resource *root, *conflict;
+       u64 start, end, max_len;
 
        status = resource_to_addr(acpi_res, &addr);
        if (!ACPI_SUCCESS(status))
@@ -140,6 +140,17 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
        } else
                return AE_OK;
 
+       max_len = addr.maximum - addr.minimum + 1;
+       if (addr.address_length > max_len) {
+               dev_printk(KERN_DEBUG, &info->bridge->dev,
+                          "host bridge window length %#llx doesn't fit in "
+                          "%#llx-%#llx, trimming\n",
+                          (unsigned long long) addr.address_length,
+                          (unsigned long long) addr.minimum,
+                          (unsigned long long) addr.maximum);
+               addr.address_length = max_len;
+       }
+
        start = addr.minimum + addr.translation_offset;
        end = start + addr.address_length - 1;
 
@@ -157,9 +168,12 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
                return AE_OK;
        }
 
-       if (insert_resource(root, res)) {
+       conflict = insert_resource_conflict(root, res);
+       if (conflict) {
                dev_err(&info->bridge->dev,
-                       "can't allocate host bridge window %pR\n", res);
+                       "address space collision: host bridge window %pR "
+                       "conflicts with %s %pR\n",
+                       res, conflict->name, conflict);
        } else {
                pci_bus_add_resource(info->bus, res, 0);
                info->res_num++;
index dece3eb9c90639731811f8bc4bd7139d51a7fd69..46fd43f791037cb318b6de9405435f434f84065b 100644 (file)
@@ -127,9 +127,6 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
                                        continue;
                                if (!r->start ||
                                    pci_claim_resource(dev, idx) < 0) {
-                                       dev_info(&dev->dev,
-                                                "can't reserve window %pR\n",
-                                                r);
                                        /*
                                         * Something is wrong with the region.
                                         * Invalidate the resource to prevent
@@ -181,8 +178,6 @@ static void __init pcibios_allocate_resources(int pass)
                                        "BAR %d: reserving %pr (d=%d, p=%d)\n",
                                        idx, r, disabled, pass);
                                if (pci_claim_resource(dev, idx) < 0) {
-                                       dev_info(&dev->dev,
-                                                "can't reserve %pR\n", r);
                                        /* We'll assign a new address later */
                                        r->end -= r->start;
                                        r->start = 0;
index fb7fc24fe72725817ee38e970dc9b90f07998522..189cbc2585fa1cf51ca2ee45615b5f2176c85197 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/acpi.h>
 #include <linux/signal.h>
 #include <linux/kthread.h>
+#include <linux/dmi.h>
 
 #include <acpi/acpi_drivers.h>
 
@@ -1032,6 +1033,41 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
        list_add_tail(&id->list, &device->pnp.ids);
 }
 
+/*
+ * Old IBM workstations have a DSDT bug wherein the SMBus object
+ * lacks the SMBUS01 HID and the methods do not have the necessary "_"
+ * prefix.  Work around this.
+ */
+static int acpi_ibm_smbus_match(struct acpi_device *device)
+{
+       acpi_handle h_dummy;
+       struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
+       int result;
+
+       if (!dmi_name_in_vendors("IBM"))
+               return -ENODEV;
+
+       /* Look for SMBS object */
+       result = acpi_get_name(device->handle, ACPI_SINGLE_NAME, &path);
+       if (result)
+               return result;
+
+       if (strcmp("SMBS", path.pointer)) {
+               result = -ENODEV;
+               goto out;
+       }
+
+       /* Does it have the necessary (but misnamed) methods? */
+       result = -ENODEV;
+       if (ACPI_SUCCESS(acpi_get_handle(device->handle, "SBI", &h_dummy)) &&
+           ACPI_SUCCESS(acpi_get_handle(device->handle, "SBR", &h_dummy)) &&
+           ACPI_SUCCESS(acpi_get_handle(device->handle, "SBW", &h_dummy)))
+               result = 0;
+out:
+       kfree(path.pointer);
+       return result;
+}
+
 static void acpi_device_set_id(struct acpi_device *device)
 {
        acpi_status status;
@@ -1082,6 +1118,8 @@ static void acpi_device_set_id(struct acpi_device *device)
                        acpi_add_id(device, ACPI_BAY_HID);
                else if (ACPI_SUCCESS(acpi_dock_match(device)))
                        acpi_add_id(device, ACPI_DOCK_HID);
+               else if (!acpi_ibm_smbus_match(device))
+                       acpi_add_id(device, ACPI_SMBUS_IBM_HID);
 
                break;
        case ACPI_BUS_TYPE_POWER:
index 561dec2481cb2da91bed31b037edc31e2301b57b..277477251a864812dcdabc1f0efcf0d7d76a459a 100644 (file)
@@ -1667,6 +1667,7 @@ unsigned int ata_sff_host_intr(struct ata_port *ap,
 {
        struct ata_eh_info *ehi = &ap->link.eh_info;
        u8 status, host_stat = 0;
+       bool bmdma_stopped = false;
 
        VPRINTK("ata%u: protocol %d task_state %d\n",
                ap->print_id, qc->tf.protocol, ap->hsm_task_state);
@@ -1699,6 +1700,7 @@ unsigned int ata_sff_host_intr(struct ata_port *ap,
 
                        /* before we do anything else, clear DMA-Start bit */
                        ap->ops->bmdma_stop(qc);
+                       bmdma_stopped = true;
 
                        if (unlikely(host_stat & ATA_DMA_ERR)) {
                                /* error when transfering data to/from memory */
@@ -1716,8 +1718,14 @@ unsigned int ata_sff_host_intr(struct ata_port *ap,
 
        /* check main status, clearing INTRQ if needed */
        status = ata_sff_irq_status(ap);
-       if (status & ATA_BUSY)
-               goto idle_irq;
+       if (status & ATA_BUSY) {
+               if (bmdma_stopped) {
+                       /* BMDMA engine is already stopped, we're screwed */
+                       qc->err_mask |= AC_ERR_HSM;
+                       ap->hsm_task_state = HSM_ST_ERR;
+               } else
+                       goto idle_irq;
+       }
 
        /* ack bmdma irq events */
        ap->ops->sff_irq_clear(ap);
@@ -1762,13 +1770,16 @@ EXPORT_SYMBOL_GPL(ata_sff_host_intr);
 irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
 {
        struct ata_host *host = dev_instance;
+       bool retried = false;
        unsigned int i;
-       unsigned int handled = 0, polling = 0;
+       unsigned int handled, idle, polling;
        unsigned long flags;
 
        /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
        spin_lock_irqsave(&host->lock, flags);
 
+retry:
+       handled = idle = polling = 0;
        for (i = 0; i < host->n_ports; i++) {
                struct ata_port *ap = host->ports[i];
                struct ata_queued_cmd *qc;
@@ -1782,7 +1793,8 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
                                handled |= ata_sff_host_intr(ap, qc);
                        else
                                polling |= 1 << i;
-               }
+               } else
+                       idle |= 1 << i;
        }
 
        /*
@@ -1790,7 +1802,9 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
         * asserting IRQ line, nobody cared will ensue.  Check IRQ
         * pending status if available and clear spurious IRQ.
         */
-       if (!handled) {
+       if (!handled && !retried) {
+               bool retry = false;
+
                for (i = 0; i < host->n_ports; i++) {
                        struct ata_port *ap = host->ports[i];
 
@@ -1805,8 +1819,23 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
                                ata_port_printk(ap, KERN_INFO,
                                                "clearing spurious IRQ\n");
 
-                       ap->ops->sff_check_status(ap);
-                       ap->ops->sff_irq_clear(ap);
+                       if (idle & (1 << i)) {
+                               ap->ops->sff_check_status(ap);
+                               ap->ops->sff_irq_clear(ap);
+                       } else {
+                               /* clear INTRQ and check if BUSY cleared */
+                               if (!(ap->ops->sff_check_status(ap) & ATA_BUSY))
+                                       retry |= true;
+                               /*
+                                * With command in flight, we can't do
+                                * sff_irq_clear() w/o racing with completion.
+                                */
+                       }
+               }
+
+               if (retry) {
+                       retried = true;
+                       goto retry;
                }
        }
 
index 3059ec017de3fde4c4f2100d99da286ccdf93836..c59b40710fbd2f42867328eb1261768ad80fa32b 100644 (file)
@@ -576,6 +576,10 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
                        u8 rev = isa->revision;
                        pci_dev_put(isa);
 
+                       if ((id->device == 0x0415 || id->device == 0x3164) &&
+                           (config->id != id->device))
+                               continue;
+
                        if (rev >= config->rev_min && rev <= config->rev_max)
                                break;
                }
@@ -677,6 +681,7 @@ static const struct pci_device_id via[] = {
        { PCI_VDEVICE(VIA, 0x3164), },
        { PCI_VDEVICE(VIA, 0x5324), },
        { PCI_VDEVICE(VIA, 0xC409), VIA_IDFLAG_SINGLE },
+       { PCI_VDEVICE(VIA, 0x9001), VIA_IDFLAG_SINGLE },
 
        { },
 };
index d477f4dc5e514b202aaaa1efe0a6b20b3eeb62e3..941fcb87e52a12765df2aaa2e2ab21267693af9f 100644 (file)
@@ -439,8 +439,23 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
        if (dev->bus && dev->bus->pm) {
                pm_dev_dbg(dev, state, "EARLY ");
                error = pm_noirq_op(dev, dev->bus->pm, state);
+               if (error)
+                       goto End;
        }
 
+       if (dev->type && dev->type->pm) {
+               pm_dev_dbg(dev, state, "EARLY type ");
+               error = pm_noirq_op(dev, dev->type->pm, state);
+               if (error)
+                       goto End;
+       }
+
+       if (dev->class && dev->class->pm) {
+               pm_dev_dbg(dev, state, "EARLY class ");
+               error = pm_noirq_op(dev, dev->class->pm, state);
+       }
+
+End:
        TRACE_RESUME(error);
        return error;
 }
@@ -735,10 +750,26 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
 {
        int error = 0;
 
+       if (dev->class && dev->class->pm) {
+               pm_dev_dbg(dev, state, "LATE class ");
+               error = pm_noirq_op(dev, dev->class->pm, state);
+               if (error)
+                       goto End;
+       }
+
+       if (dev->type && dev->type->pm) {
+               pm_dev_dbg(dev, state, "LATE type ");
+               error = pm_noirq_op(dev, dev->type->pm, state);
+               if (error)
+                       goto End;
+       }
+
        if (dev->bus && dev->bus->pm) {
                pm_dev_dbg(dev, state, "LATE ");
                error = pm_noirq_op(dev, dev->bus->pm, state);
        }
+
+End:
        return error;
 }
 
index a3e10dc7cc25ff375674a79c510effbcdfc452f9..b78d5c381efe77d3947d7e3704d3b55111e0ceb8 100644 (file)
@@ -97,6 +97,9 @@ EXPORT_SYMBOL(intel_agp_enabled);
 #define IS_PINEVIEW (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
 
+#define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
+               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
+
 #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
@@ -107,8 +110,7 @@ EXPORT_SYMBOL(intel_agp_enabled);
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
-               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
-               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
+               IS_SNB)
 
 extern int agp_memory_reserved;
 
@@ -175,6 +177,10 @@ extern int agp_memory_reserved;
 #define SNB_GMCH_GMS_STOLEN_448M       (0xe << 3)
 #define SNB_GMCH_GMS_STOLEN_480M       (0xf << 3)
 #define SNB_GMCH_GMS_STOLEN_512M       (0x10 << 3)
+#define SNB_GTT_SIZE_0M                        (0 << 8)
+#define SNB_GTT_SIZE_1M                        (1 << 8)
+#define SNB_GTT_SIZE_2M                        (2 << 8)
+#define SNB_GTT_SIZE_MASK              (3 << 8)
 
 static const struct aper_size_info_fixed intel_i810_sizes[] =
 {
@@ -1200,6 +1206,9 @@ static void intel_i9xx_setup_flush(void)
        if (intel_private.ifp_resource.start)
                return;
 
+       if (IS_SNB)
+               return;
+
        /* setup a resource for this object */
        intel_private.ifp_resource.name = "Intel Flush Page";
        intel_private.ifp_resource.flags = IORESOURCE_MEM;
@@ -1438,6 +1447,8 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
 
 static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
 {
+       u16 snb_gmch_ctl;
+
        switch (agp_bridge->dev->device) {
        case PCI_DEVICE_ID_INTEL_GM45_HB:
        case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB:
@@ -1449,9 +1460,26 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
        case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB:
        case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB:
        case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
+               *gtt_offset = *gtt_size = MB(2);
+               break;
        case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
        case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
-               *gtt_offset = *gtt_size = MB(2);
+               *gtt_offset = MB(2);
+
+               pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
+               switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) {
+               default:
+               case SNB_GTT_SIZE_0M:
+                       printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl);
+                       *gtt_size = MB(0);
+                       break;
+               case SNB_GTT_SIZE_1M:
+                       *gtt_size = MB(1);
+                       break;
+               case SNB_GTT_SIZE_2M:
+                       *gtt_size = MB(2);
+                       break;
+               }
                break;
        default:
                *gtt_offset = *gtt_size = KB(512);
index a42c466f7092e2f519f8428be2669ab964a56575..6da962c9b21c880262a883db546ea1c8c7a99764 100644 (file)
@@ -1423,6 +1423,8 @@ static void release_one_tty(struct work_struct *work)
        list_del_init(&tty->tty_files);
        file_list_unlock();
 
+       put_pid(tty->pgrp);
+       put_pid(tty->session);
        free_tty_struct(tty);
 }
 
index f404ccfc9c20992f342eb366dd21231642d078ea..44288ce0cb45520b144d9eec98a942c7812025c7 100644 (file)
@@ -681,6 +681,10 @@ static void resize_console(struct port *port)
        struct virtio_device *vdev;
        struct winsize ws;
 
+       /* The port could have been hot-unplugged */
+       if (!port)
+               return;
+
        vdev = port->portdev->vdev;
        if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) {
                vdev->config->get(vdev,
@@ -947,11 +951,18 @@ static void handle_control_message(struct ports_device *portdev,
                 */
                err = sysfs_create_group(&port->dev->kobj,
                                         &port_attribute_group);
-               if (err)
+               if (err) {
                        dev_err(port->dev,
                                "Error %d creating sysfs device attributes\n",
                                err);
-
+               } else {
+                       /*
+                        * Generate a udev event so that appropriate
+                        * symlinks can be created based on udev
+                        * rules.
+                        */
+                       kobject_uevent(&port->dev->kobj, KOBJ_CHANGE);
+               }
                break;
        case VIRTIO_CONSOLE_PORT_REMOVE:
                /*
index 8fc91a019620d57fab83e04ed34fac8d826f0e32..f5b6d9fe4def622c3a39cd872429a9dcf34ef57f 100644 (file)
@@ -316,7 +316,12 @@ void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors)
                if (regs->nbsh & K8_NBSH_ERR_CPU_VAL)
                        pr_cont(", core: %u\n", (u8)(regs->nbsh & 0xf));
        } else {
-               pr_cont(", core: %d\n", fls((regs->nbsh & 0xf) - 1));
+               u8 assoc_cpus = regs->nbsh & 0xf;
+
+               if (assoc_cpus > 0)
+                       pr_cont(", core: %d", fls(assoc_cpus) - 1);
+
+               pr_cont("\n");
        }
 
        pr_emerg("%s.\n", EXT_ERR_MSG(xec));
index 5db0518c66da687068c5ede57bce232fb4463283..882472d1e144a01cb9ab54b9df1c23274335cc0c 100644 (file)
@@ -126,97 +126,74 @@ int fw_csr_string(const u32 *directory, int key, char *buf, size_t size)
 }
 EXPORT_SYMBOL(fw_csr_string);
 
-static bool is_fw_unit(struct device *dev);
-
-static int match_unit_directory(const u32 *directory, u32 match_flags,
-                               const struct ieee1394_device_id *id)
+static void get_ids(const u32 *directory, int *id)
 {
        struct fw_csr_iterator ci;
-       int key, value, match;
+       int key, value;
 
-       match = 0;
        fw_csr_iterator_init(&ci, directory);
        while (fw_csr_iterator_next(&ci, &key, &value)) {
-               if (key == CSR_VENDOR && value == id->vendor_id)
-                       match |= IEEE1394_MATCH_VENDOR_ID;
-               if (key == CSR_MODEL && value == id->model_id)
-                       match |= IEEE1394_MATCH_MODEL_ID;
-               if (key == CSR_SPECIFIER_ID && value == id->specifier_id)
-                       match |= IEEE1394_MATCH_SPECIFIER_ID;
-               if (key == CSR_VERSION && value == id->version)
-                       match |= IEEE1394_MATCH_VERSION;
+               switch (key) {
+               case CSR_VENDOR:        id[0] = value; break;
+               case CSR_MODEL:         id[1] = value; break;
+               case CSR_SPECIFIER_ID:  id[2] = value; break;
+               case CSR_VERSION:       id[3] = value; break;
+               }
        }
+}
+
+static void get_modalias_ids(struct fw_unit *unit, int *id)
+{
+       get_ids(&fw_parent_device(unit)->config_rom[5], id);
+       get_ids(unit->directory, id);
+}
+
+static bool match_ids(const struct ieee1394_device_id *id_table, int *id)
+{
+       int match = 0;
+
+       if (id[0] == id_table->vendor_id)
+               match |= IEEE1394_MATCH_VENDOR_ID;
+       if (id[1] == id_table->model_id)
+               match |= IEEE1394_MATCH_MODEL_ID;
+       if (id[2] == id_table->specifier_id)
+               match |= IEEE1394_MATCH_SPECIFIER_ID;
+       if (id[3] == id_table->version)
+               match |= IEEE1394_MATCH_VERSION;
 
-       return (match & match_flags) == match_flags;
+       return (match & id_table->match_flags) == id_table->match_flags;
 }
 
+static bool is_fw_unit(struct device *dev);
+
 static int fw_unit_match(struct device *dev, struct device_driver *drv)
 {
-       struct fw_unit *unit = fw_unit(dev);
-       struct fw_device *device;
-       const struct ieee1394_device_id *id;
+       const struct ieee1394_device_id *id_table =
+                       container_of(drv, struct fw_driver, driver)->id_table;
+       int id[] = {0, 0, 0, 0};
 
        /* We only allow binding to fw_units. */
        if (!is_fw_unit(dev))
                return 0;
 
-       device = fw_parent_device(unit);
-       id = container_of(drv, struct fw_driver, driver)->id_table;
+       get_modalias_ids(fw_unit(dev), id);
 
-       for (; id->match_flags != 0; id++) {
-               if (match_unit_directory(unit->directory, id->match_flags, id))
+       for (; id_table->match_flags != 0; id_table++)
+               if (match_ids(id_table, id))
                        return 1;
 
-               /* Also check vendor ID in the root directory. */
-               if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
-                   match_unit_directory(&device->config_rom[5],
-                               IEEE1394_MATCH_VENDOR_ID, id) &&
-                   match_unit_directory(unit->directory, id->match_flags
-                               & ~IEEE1394_MATCH_VENDOR_ID, id))
-                       return 1;
-       }
-
        return 0;
 }
 
 static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
 {
-       struct fw_device *device = fw_parent_device(unit);
-       struct fw_csr_iterator ci;
+       int id[] = {0, 0, 0, 0};
 
-       int key, value;
-       int vendor = 0;
-       int model = 0;
-       int specifier_id = 0;
-       int version = 0;
-
-       fw_csr_iterator_init(&ci, &device->config_rom[5]);
-       while (fw_csr_iterator_next(&ci, &key, &value)) {
-               switch (key) {
-               case CSR_VENDOR:
-                       vendor = value;
-                       break;
-               case CSR_MODEL:
-                       model = value;
-                       break;
-               }
-       }
-
-       fw_csr_iterator_init(&ci, unit->directory);
-       while (fw_csr_iterator_next(&ci, &key, &value)) {
-               switch (key) {
-               case CSR_SPECIFIER_ID:
-                       specifier_id = value;
-                       break;
-               case CSR_VERSION:
-                       version = value;
-                       break;
-               }
-       }
+       get_modalias_ids(unit, id);
 
        return snprintf(buffer, buffer_size,
                        "ieee1394:ven%08Xmo%08Xsp%08Xver%08X",
-                       vendor, model, specifier_id, version);
+                       id[0], id[1], id[2], id[3]);
 }
 
 static int fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env)
index 1c0b504a42f3068e852fa1b7423ee5c37bfb0abd..99c20f1b613ab65f7ea6349647d47b1a4803a222 100644 (file)
@@ -331,8 +331,9 @@ void fw_iso_resource_manage(struct fw_card *card, int generation,
        if (ret < 0)
                *bandwidth = 0;
 
-       if (allocate && ret < 0 && c >= 0) {
-               deallocate_channel(card, irm_id, generation, c, buffer);
+       if (allocate && ret < 0) {
+               if (c >= 0)
+                       deallocate_channel(card, irm_id, generation, c, buffer);
                *channel = ret;
        }
 }
index 75dc6988cffd5d174ae8eb5445b5ce8744e0f4b0..e33917bf97d28eb803699e46f4dfb46860ec1b45 100644 (file)
@@ -231,6 +231,8 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
 
 static char ohci_driver_name[] = KBUILD_MODNAME;
 
+#define PCI_DEVICE_ID_TI_TSB12LV22     0x8009
+
 #define QUIRK_CYCLE_TIMER              1
 #define QUIRK_RESET_PACKET             2
 #define QUIRK_BE_HEADERS               4
@@ -239,6 +241,8 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 static const struct {
        unsigned short vendor, device, flags;
 } ohci_quirks[] = {
+       {PCI_VENDOR_ID_TI,      PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER |
+                                                           QUIRK_RESET_PACKET},
        {PCI_VENDOR_ID_TI,      PCI_ANY_ID,     QUIRK_RESET_PACKET},
        {PCI_VENDOR_ID_AL,      PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
        {PCI_VENDOR_ID_NEC,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
index c9bced55f82bc501288d90f8d5536b27e6e9a848..4a7d662ff9b71cf32cf5b3cb031c7ea36d5714f7 100644 (file)
@@ -242,3 +242,7 @@ int __devexit __max730x_remove(struct device *dev)
        return ret;
 }
 EXPORT_SYMBOL_GPL(__max730x_remove);
+
+MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX730x GPIO-Expanders, generic parts");
index f2aaf39be3981944fefc63a23fd8edcc9e3a614f..51103aa469f8c1bf773859e6176a004076a70e9a 100644 (file)
@@ -104,6 +104,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
        if (connector->status == connector_status_disconnected) {
                DRM_DEBUG_KMS("%s is disconnected\n",
                          drm_get_connector_name(connector));
+               drm_mode_connector_update_edid_property(connector, NULL);
                goto prune;
        }
 
index f97e7c42ac8e1f7bdf53573e491feb0a80f2989f..7e608f4a0df95563e81e40d3efbaa57903fadbba 100644 (file)
@@ -707,15 +707,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
        mode->vsync_end = mode->vsync_start + vsync_pulse_width;
        mode->vtotal = mode->vdisplay + vblank;
 
-       /* perform the basic check for the detailed timing */
-       if (mode->hsync_end > mode->htotal ||
-               mode->vsync_end > mode->vtotal) {
-               drm_mode_destroy(dev, mode);
-               DRM_DEBUG_KMS("Incorrect detailed timing. "
-                               "Sync is beyond the blank.\n");
-               return NULL;
-       }
-
        /* Some EDIDs have bogus h/vtotal values */
        if (mode->hsync_end > mode->htotal)
                mode->htotal = mode->hsync_end + 1;
index 50549703584f5b7d91c54d24f037dfa5d26f5ebc..99487237111d152c2748edf1662bcf7187379883 100644 (file)
@@ -283,6 +283,8 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
        .help_msg = "force-fb(V)",
        .action_msg = "Restore framebuffer console",
 };
+#else
+static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
 #endif
 
 static void drm_fb_helper_on(struct fb_info *info)
index 08d14df3bb422d41bd561eea171d4cd91a662a3e..4804872f8b19e637a113b7dc923d5343a3ccb56b 100644 (file)
@@ -140,14 +140,16 @@ int drm_open(struct inode *inode, struct file *filp)
                spin_unlock(&dev->count_lock);
        }
 out:
-       mutex_lock(&dev->struct_mutex);
-       if (minor->type == DRM_MINOR_LEGACY) {
-               BUG_ON((dev->dev_mapping != NULL) &&
-                       (dev->dev_mapping != inode->i_mapping));
-               if (dev->dev_mapping == NULL)
-                       dev->dev_mapping = inode->i_mapping;
+       if (!retcode) {
+               mutex_lock(&dev->struct_mutex);
+               if (minor->type == DRM_MINOR_LEGACY) {
+                       if (dev->dev_mapping == NULL)
+                               dev->dev_mapping = inode->i_mapping;
+                       else if (dev->dev_mapping != inode->i_mapping)
+                               retcode = -ENODEV;
+               }
+               mutex_unlock(&dev->struct_mutex);
        }
-       mutex_unlock(&dev->struct_mutex);
 
        return retcode;
 }
index 8bfc0bbf13e658fd050457c87cfa57f3c8857e8f..a9f8589490cf14d989eab8ca7c9bdd5cd6ec054d 100644 (file)
@@ -1881,29 +1881,29 @@ struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
        DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
-       DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
-       DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
-       DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
-       DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 0),
-       DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
-       DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
-       DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
-       DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
-       DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
-       DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
-       DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, 0),
-       DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW),
-       DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
index 1b2e95455c05d0cce04d17483c7bd4ff9f218fe0..4b26919abdb27b2645f58de590a19a44f2192908 100644 (file)
@@ -139,12 +139,12 @@ const static struct intel_device_info intel_ironlake_m_info = {
 
 const static struct intel_device_info intel_sandybridge_d_info = {
        .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
-       .has_hotplug = 1,
+       .has_hotplug = 1, .is_gen6 = 1,
 };
 
 const static struct intel_device_info intel_sandybridge_m_info = {
        .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1,
-       .has_hotplug = 1,
+       .has_hotplug = 1, .is_gen6 = 1,
 };
 
 const static struct pci_device_id pciidlist[] = {
index 979439cfb827998f9301a1bcee3626957828c268..aba8260fbc5ed6cb7510a22dd961681d02ccaa6d 100644 (file)
@@ -205,6 +205,7 @@ struct intel_device_info {
        u8 is_g4x : 1;
        u8 is_pineview : 1;
        u8 is_ironlake : 1;
+       u8 is_gen6 : 1;
        u8 has_fbc : 1;
        u8 has_rc6 : 1;
        u8 has_pipe_cxsr : 1;
@@ -1084,6 +1085,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 #define IS_IRONLAKE_M(dev)     ((dev)->pci_device == 0x0046)
 #define IS_IRONLAKE(dev)       (INTEL_INFO(dev)->is_ironlake)
 #define IS_I9XX(dev)           (INTEL_INFO(dev)->is_i9xx)
+#define IS_GEN6(dev)           (INTEL_INFO(dev)->is_gen6)
 #define IS_MOBILE(dev)         (INTEL_INFO(dev)->is_mobile)
 
 #define IS_GEN3(dev)   (IS_I915G(dev) ||                       \
@@ -1107,8 +1109,6 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
 #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
 
-#define IS_GEN6(dev)   ((dev)->pci_device == 0x0102)
-
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
  * rows, which changed the alignment requirements and fence programming.
  */
index fba37e9f775d6fefdacaacfd0bd0868f6075328f..933e865a89297e452ab2d93b3ee1ec09ab6068d4 100644 (file)
@@ -1466,9 +1466,6 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
                obj_priv->dirty = 0;
 
        for (i = 0; i < page_count; i++) {
-               if (obj_priv->pages[i] == NULL)
-                       break;
-
                if (obj_priv->dirty)
                        set_page_dirty(obj_priv->pages[i]);
 
@@ -2227,11 +2224,6 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
                                seqno = i915_add_request(dev, NULL, obj->write_domain);
                                if (seqno == 0)
                                        return -ENOMEM;
-
-                               ret = i915_wait_request(dev, seqno);
-                               if (ret)
-                                       return ret;
-
                                continue;
                        }
                }
@@ -2256,7 +2248,6 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
        struct address_space *mapping;
        struct inode *inode;
        struct page *page;
-       int ret;
 
        if (obj_priv->pages_refcount++ != 0)
                return 0;
@@ -2279,11 +2270,9 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
                                           mapping_gfp_mask (mapping) |
                                           __GFP_COLD |
                                           gfpmask);
-               if (IS_ERR(page)) {
-                       ret = PTR_ERR(page);
-                       i915_gem_object_put_pages(obj);
-                       return ret;
-               }
+               if (IS_ERR(page))
+                       goto err_pages;
+
                obj_priv->pages[i] = page;
        }
 
@@ -2291,6 +2280,15 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
                i915_gem_object_do_bit_17_swizzle(obj);
 
        return 0;
+
+err_pages:
+       while (i--)
+               page_cache_release(obj_priv->pages[i]);
+
+       drm_free_large(obj_priv->pages);
+       obj_priv->pages = NULL;
+       obj_priv->pages_refcount--;
+       return PTR_ERR(page);
 }
 
 static void sandybridge_write_fence_reg(struct drm_i915_fence_reg *reg)
@@ -4730,6 +4728,11 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
                        ring->space += ring->Size;
        }
 
+       if (IS_I9XX(dev) && !IS_GEN3(dev)) {
+               I915_WRITE(MI_MODE,
+                          (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH);
+       }
+
        return 0;
 }
 
index b5c55d88ff76f260f87a0dc64b140739dcc7ec4f..c01c878e51baf3ff206388c32312f685a73156f5 100644 (file)
@@ -325,9 +325,12 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
                 * need to ensure that any fence register is cleared.
                 */
                if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
-                   ret = i915_gem_object_unbind(obj);
+                       ret = i915_gem_object_unbind(obj);
+               else if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
+                       ret = i915_gem_object_put_fence_reg(obj);
                else
-                   ret = i915_gem_object_put_fence_reg(obj);
+                       i915_gem_release_mmap(obj);
+
                if (ret != 0) {
                        WARN(ret != -ERESTARTSYS,
                             "failed to reset object for tiling switch");
index 3d59862c7ccd01d9c14904c97ef1b4853c9a22b8..cbbf59f56dfa93c23008e4c98d0b38353a65a6a7 100644 (file)
 #define INSTDONE       0x02090
 #define NOPID          0x02094
 #define HWSTAM         0x02098
+
+#define MI_MODE                0x0209c
+# define VS_TIMER_DISPATCH                             (1 << 6)
+
 #define SCPD0          0x0209c /* 915+ only */
 #define IER            0x020a0
 #define IIR            0x020a4
 #define   FBC_CTL_PERIODIC     (1<<30)
 #define   FBC_CTL_INTERVAL_SHIFT (16)
 #define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
-#define   FBC_C3_IDLE          (1<<13)
+#define   FBC_CTL_C3_IDLE      (1<<13)
 #define   FBC_CTL_STRIDE_SHIFT (5)
 #define   FBC_CTL_FENCENO      (1<<0)
 #define FBC_COMMAND            0x0320c
 #define DISPLAY_PORT_PLL_BIOS_1         0x46010
 #define DISPLAY_PORT_PLL_BIOS_2         0x46014
 
+#define PCH_DSPCLK_GATE_D      0x42020
+# define DPFDUNIT_CLOCK_GATE_DISABLE           (1 << 7)
+# define DPARBUNIT_CLOCK_GATE_DISABLE          (1 << 5)
+
+#define PCH_3DCGDIS0           0x46020
+# define MARIUNIT_CLOCK_GATE_DISABLE           (1 << 18)
+# define SVSMUNIT_CLOCK_GATE_DISABLE           (1 << 1)
+
 #define FDI_PLL_FREQ_CTL        0x46030
 #define  FDI_PLL_FREQ_CHANGE_REQUEST    (1<<24)
 #define  FDI_PLL_FREQ_LOCK_LIMIT_MASK   0xfff00
index 70c9d4ba7042b57dc677a9e2fcbcf03a6abe5e4e..f9ba452f0cbf2479649e7dbe947accdeed070f30 100644 (file)
@@ -417,8 +417,9 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
        edp = find_section(bdb, BDB_EDP);
        if (!edp) {
                if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) {
-                       DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported,\
-                                      assume 18bpp panel color depth.\n");
+                       DRM_DEBUG_KMS("No eDP BDB found but eDP panel "
+                                     "supported, assume 18bpp panel color "
+                                     "depth.\n");
                        dev_priv->edp_bpp = 18;
                }
                return;
index 9cd6de5f99061a2916af6d453dd46e2de2ea11fe..58fc7fa0eb1d6feb3854b804761c63b5302af206 100644 (file)
@@ -1032,7 +1032,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        /* enable it... */
        fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
        if (IS_I945GM(dev))
-               fbc_ctl |= FBC_C3_IDLE; /* 945 needs special SR handling */
+               fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
        fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
        fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
        if (obj_priv->tiling_mode != I915_TILING_NONE)
@@ -4717,6 +4717,20 @@ void intel_init_clock_gating(struct drm_device *dev)
         * specs, but enable as much else as we can.
         */
        if (HAS_PCH_SPLIT(dev)) {
+               uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+
+               if (IS_IRONLAKE(dev)) {
+                       /* Required for FBC */
+                       dspclk_gate |= DPFDUNIT_CLOCK_GATE_DISABLE;
+                       /* Required for CxSR */
+                       dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE;
+
+                       I915_WRITE(PCH_3DCGDIS0,
+                                  MARIUNIT_CLOCK_GATE_DISABLE |
+                                  SVSMUNIT_CLOCK_GATE_DISABLE);
+               }
+
+               I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
                return;
        } else if (IS_G4X(dev)) {
                uint32_t dspclk_gate;
index 14e516fdc2dd5c71b69f403bf184450171f3f185..2b3fa7a3c0285edc2d59a80fc120802f42a4bb0f 100644 (file)
@@ -607,53 +607,6 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
        I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control);
 }
 
-/* Some lid devices report incorrect lid status, assume they're connected */
-static const struct dmi_system_id bad_lid_status[] = {
-       {
-               .ident = "Compaq nx9020",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                       DMI_MATCH(DMI_BOARD_NAME, "3084"),
-               },
-       },
-       {
-               .ident = "Samsung SX20S",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
-                       DMI_MATCH(DMI_BOARD_NAME, "SX20S"),
-               },
-       },
-       {
-               .ident = "Aspire One",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"),
-               },
-       },
-       {
-               .ident = "Aspire 1810T",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1810T"),
-               },
-       },
-       {
-               .ident = "PC-81005",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "MALATA"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "PC-81005"),
-               },
-       },
-       {
-               .ident = "Clevo M5x0N",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
-                       DMI_MATCH(DMI_BOARD_NAME, "M5x0N"),
-               },
-       },
-       { }
-};
-
 /**
  * Detect the LVDS connection.
  *
@@ -669,12 +622,9 @@ static enum drm_connector_status intel_lvds_detect(struct drm_connector *connect
        /* ACPI lid methods were generally unreliable in this generation, so
         * don't even bother.
         */
-       if (IS_GEN2(dev))
+       if (IS_GEN2(dev) || IS_GEN3(dev))
                return connector_status_connected;
 
-       if (!dmi_check_system(bad_lid_status) && !acpi_lid_open())
-               status = connector_status_disconnected;
-
        return status;
 }
 
index d355d1d527e766438a3a177218eed2dbb9210a7d..60595fc26fdd3511d0b9ec7d0d5336a0c5a3a4f3 100644 (file)
@@ -1068,14 +1068,18 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 
        drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
                         DRM_MODE_OBJECT_CRTC);
-       if (!drmmode_obj)
-               return -ENOENT;
+       if (!drmmode_obj) {
+               ret = -ENOENT;
+               goto out_free;
+       }
        crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
 
        new_bo = drm_gem_object_lookup(dev, file_priv,
                        put_image_rec->bo_handle);
-       if (!new_bo)
-               return -ENOENT;
+       if (!new_bo) {
+               ret = -ENOENT;
+               goto out_free;
+       }
 
        mutex_lock(&dev->mode_config.mutex);
        mutex_lock(&dev->struct_mutex);
@@ -1165,6 +1169,7 @@ out_unlock:
        mutex_unlock(&dev->struct_mutex);
        mutex_unlock(&dev->mode_config.mutex);
        drm_gem_object_unreference_unlocked(new_bo);
+out_free:
        kfree(params);
 
        return ret;
index 32db806f3b5aa53e82a25797c271b8f4ca8fa2c0..7f0d807a0d0d4f1bc220ef59ca02ce917aa0dfde 100644 (file)
@@ -12,7 +12,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
              nouveau_dp.o nouveau_grctx.o \
              nv04_timer.o \
              nv04_mc.o nv40_mc.o nv50_mc.o \
-             nv04_fb.o nv10_fb.o nv40_fb.o \
+             nv04_fb.o nv10_fb.o nv40_fb.o nv50_fb.o \
              nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
              nv04_graph.o nv10_graph.o nv20_graph.o \
              nv40_graph.o nv50_graph.o \
index 75bceee76044e8ab25b6035e690e09fa3e29f850..b5a9336a2e88f58d3e90129c631262896f0f163b 100644 (file)
@@ -5210,6 +5210,21 @@ divine_connector_type(struct nvbios *bios, int index)
        return type;
 }
 
+static void
+apply_dcb_connector_quirks(struct nvbios *bios, int idx)
+{
+       struct dcb_connector_table_entry *cte = &bios->dcb.connector.entry[idx];
+       struct drm_device *dev = bios->dev;
+
+       /* Gigabyte NX85T */
+       if ((dev->pdev->device == 0x0421) &&
+           (dev->pdev->subsystem_vendor == 0x1458) &&
+           (dev->pdev->subsystem_device == 0x344c)) {
+               if (cte->type == DCB_CONNECTOR_HDMI_1)
+                       cte->type = DCB_CONNECTOR_DVI_I;
+       }
+}
+
 static void
 parse_dcb_connector_table(struct nvbios *bios)
 {
@@ -5238,13 +5253,14 @@ parse_dcb_connector_table(struct nvbios *bios)
        entry = conntab + conntab[1];
        cte = &ct->entry[0];
        for (i = 0; i < conntab[2]; i++, entry += conntab[3], cte++) {
+               cte->index = i;
                if (conntab[3] == 2)
                        cte->entry = ROM16(entry[0]);
                else
                        cte->entry = ROM32(entry[0]);
 
                cte->type  = (cte->entry & 0x000000ff) >> 0;
-               cte->index = (cte->entry & 0x00000f00) >> 8;
+               cte->index2 = (cte->entry & 0x00000f00) >> 8;
                switch (cte->entry & 0x00033000) {
                case 0x00001000:
                        cte->gpio_tag = 0x07;
@@ -5266,6 +5282,8 @@ parse_dcb_connector_table(struct nvbios *bios)
                if (cte->type == 0xff)
                        continue;
 
+               apply_dcb_connector_quirks(bios, i);
+
                NV_INFO(dev, "  %d: 0x%08x: type 0x%02x idx %d tag 0x%02x\n",
                        i, cte->entry, cte->type, cte->index, cte->gpio_tag);
 
@@ -5287,10 +5305,16 @@ parse_dcb_connector_table(struct nvbios *bios)
                        break;
                default:
                        cte->type = divine_connector_type(bios, cte->index);
-                       NV_WARN(dev, "unknown type, using 0x%02x", cte->type);
+                       NV_WARN(dev, "unknown type, using 0x%02x\n", cte->type);
                        break;
                }
 
+               if (nouveau_override_conntype) {
+                       int type = divine_connector_type(bios, cte->index);
+                       if (type != cte->type)
+                               NV_WARN(dev, " -> type 0x%02x\n", cte->type);
+               }
+
        }
 }
 
index 9f688aa9a65559cb3c1febd4183e8c15b8032396..4f88e6924d272846eff330a9a84307aa05fa3dc7 100644 (file)
@@ -72,9 +72,10 @@ enum dcb_connector_type {
 };
 
 struct dcb_connector_table_entry {
+       uint8_t index;
        uint32_t entry;
        enum dcb_connector_type type;
-       uint8_t index;
+       uint8_t index2;
        uint8_t gpio_tag;
 };
 
index 028719fddf761e94b1f1ae44ef50f5fc860e2813..026612471c92de827d52f30b2e183e0253843c42 100644 (file)
@@ -439,8 +439,7 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
 
        switch (bo->mem.mem_type) {
        case TTM_PL_VRAM:
-               nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT |
-                                        TTM_PL_FLAG_SYSTEM);
+               nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT);
                break;
        default:
                nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_SYSTEM);
index 24327f468c4b864b459fc0af3034c6548c2d3840..14afe1e47e57dff81a70dadada1bac8ec9f88c8d 100644 (file)
@@ -302,7 +302,7 @@ nouveau_connector_detect(struct drm_connector *connector)
 
 detect_analog:
        nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
-       if (!nv_encoder)
+       if (!nv_encoder && !nouveau_tv_disable)
                nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
        if (nv_encoder) {
                struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
index c8482a108a7801c321875ecbf5ff4e041563d3e9..65c441a1999facfeeb3b9ca191198fad732583d8 100644 (file)
@@ -190,6 +190,11 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
        nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8);
 
        chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max;
+
+       DRM_MEMORYBARRIER();
+       /* Flush writes. */
+       nouveau_bo_rd32(pb, 0);
+
        nvchan_wr32(chan, 0x8c, chan->dma.ib_put);
        chan->dma.ib_free--;
 }
index 30cc09e8a709383a458baab1d77ff89ca84de9da..1de974acbc656a1dc195df0e7f6b57f52f9c0d37 100644 (file)
@@ -83,6 +83,14 @@ MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
 int nouveau_nofbaccel = 0;
 module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
 
+MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type");
+int nouveau_override_conntype = 0;
+module_param_named(override_conntype, nouveau_override_conntype, int, 0400);
+
+MODULE_PARM_DESC(tv_disable, "Disable TV-out detection\n");
+int nouveau_tv_disable = 0;
+module_param_named(tv_disable, nouveau_tv_disable, int, 0400);
+
 MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
                 "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
                 "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
@@ -154,9 +162,11 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
        if (pm_state.event == PM_EVENT_PRETHAW)
                return 0;
 
+       NV_INFO(dev, "Disabling fbcon acceleration...\n");
        fbdev_flags = dev_priv->fbdev_info->flags;
        dev_priv->fbdev_info->flags |= FBINFO_HWACCEL_DISABLED;
 
+       NV_INFO(dev, "Unpinning framebuffer(s)...\n");
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_framebuffer *nouveau_fb;
 
index 4b9aaf2a8d0f0052bbafd498998e2c71b1e38434..d8b559011777a2094187d93a7dc836f80122ec16 100644 (file)
@@ -681,6 +681,7 @@ extern int nouveau_uscript_tmds;
 extern int nouveau_vram_pushbuf;
 extern int nouveau_vram_notify;
 extern int nouveau_fbpercrtc;
+extern int nouveau_tv_disable;
 extern char *nouveau_tv_norm;
 extern int nouveau_reg_debug;
 extern char *nouveau_vbios;
@@ -688,6 +689,7 @@ extern int nouveau_ctxfw;
 extern int nouveau_ignorelid;
 extern int nouveau_nofbaccel;
 extern int nouveau_noaccel;
+extern int nouveau_override_conntype;
 
 extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state);
 extern int nouveau_pci_resume(struct pci_dev *pdev);
@@ -926,6 +928,10 @@ extern void nv40_fb_takedown(struct drm_device *);
 extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t,
                                      uint32_t, uint32_t);
 
+/* nv50_fb.c */
+extern int  nv50_fb_init(struct drm_device *);
+extern void nv50_fb_takedown(struct drm_device *);
+
 /* nv04_fifo.c */
 extern int  nv04_fifo_init(struct drm_device *);
 extern void nv04_fifo_disable(struct drm_device *);
index 95220ddebb45a0f1880e3b200e161480588a9133..2bd59a92fee50439ddd892c96f839f909af50bf2 100644 (file)
@@ -311,6 +311,31 @@ nouveau_print_bitfield_names_(uint32_t value,
 #define nouveau_print_bitfield_names(val, namelist) \
        nouveau_print_bitfield_names_((val), (namelist), ARRAY_SIZE(namelist))
 
+struct nouveau_enum_names {
+       uint32_t value;
+       const char *name;
+};
+
+static void
+nouveau_print_enum_names_(uint32_t value,
+                               const struct nouveau_enum_names *namelist,
+                               const int namelist_len)
+{
+       /*
+        * Caller must have already printed the KERN_* log level for us.
+        * Also the caller is responsible for adding the newline.
+        */
+       int i;
+       for (i = 0; i < namelist_len; ++i) {
+               if (value == namelist[i].value) {
+                       printk("%s", namelist[i].name);
+                       return;
+               }
+       }
+       printk("unknown value 0x%08x", value);
+}
+#define nouveau_print_enum_names(val, namelist) \
+       nouveau_print_enum_names_((val), (namelist), ARRAY_SIZE(namelist))
 
 static int
 nouveau_graph_chid_from_grctx(struct drm_device *dev)
@@ -427,14 +452,16 @@ nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id,
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        uint32_t nsource = trap->nsource, nstatus = trap->nstatus;
 
-       NV_INFO(dev, "%s - nSource:", id);
-       nouveau_print_bitfield_names(nsource, nsource_names);
-       printk(", nStatus:");
-       if (dev_priv->card_type < NV_10)
-               nouveau_print_bitfield_names(nstatus, nstatus_names);
-       else
-               nouveau_print_bitfield_names(nstatus, nstatus_names_nv10);
-       printk("\n");
+       if (dev_priv->card_type < NV_50) {
+               NV_INFO(dev, "%s - nSource:", id);
+               nouveau_print_bitfield_names(nsource, nsource_names);
+               printk(", nStatus:");
+               if (dev_priv->card_type < NV_10)
+                       nouveau_print_bitfield_names(nstatus, nstatus_names);
+               else
+                       nouveau_print_bitfield_names(nstatus, nstatus_names_nv10);
+               printk("\n");
+       }
 
        NV_INFO(dev, "%s - Ch %d/%d Class 0x%04x Mthd 0x%04x "
                                        "Data 0x%08x:0x%08x\n",
@@ -577,28 +604,503 @@ nouveau_pgraph_irq_handler(struct drm_device *dev)
        nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
 }
 
+static void
+nv50_pfb_vm_trap(struct drm_device *dev, int display, const char *name)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t trap[6];
+       int i, ch;
+       uint32_t idx = nv_rd32(dev, 0x100c90);
+       if (idx & 0x80000000) {
+               idx &= 0xffffff;
+               if (display) {
+                       for (i = 0; i < 6; i++) {
+                               nv_wr32(dev, 0x100c90, idx | i << 24);
+                               trap[i] = nv_rd32(dev, 0x100c94);
+                       }
+                       for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) {
+                               struct nouveau_channel *chan = dev_priv->fifos[ch];
+
+                               if (!chan || !chan->ramin)
+                                       continue;
+
+                               if (trap[1] == chan->ramin->instance >> 12)
+                                       break;
+                       }
+                       NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x %08x channel %d\n",
+                                       name, (trap[5]&0x100?"read":"write"),
+                                       trap[5]&0xff, trap[4]&0xffff,
+                                       trap[3]&0xffff, trap[0], trap[2], ch);
+               }
+               nv_wr32(dev, 0x100c90, idx | 0x80000000);
+       } else if (display) {
+               NV_INFO(dev, "%s - no VM fault?\n", name);
+       }
+}
+
+static struct nouveau_enum_names nv50_mp_exec_error_names[] =
+{
+       { 3, "STACK_UNDERFLOW" },
+       { 4, "QUADON_ACTIVE" },
+       { 8, "TIMEOUT" },
+       { 0x10, "INVALID_OPCODE" },
+       { 0x40, "BREAKPOINT" },
+};
+
+static void
+nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t units = nv_rd32(dev, 0x1540);
+       uint32_t addr, mp10, status, pc, oplow, ophigh;
+       int i;
+       int mps = 0;
+       for (i = 0; i < 4; i++) {
+               if (!(units & 1 << (i+24)))
+                       continue;
+               if (dev_priv->chipset < 0xa0)
+                       addr = 0x408200 + (tpid << 12) + (i << 7);
+               else
+                       addr = 0x408100 + (tpid << 11) + (i << 7);
+               mp10 = nv_rd32(dev, addr + 0x10);
+               status = nv_rd32(dev, addr + 0x14);
+               if (!status)
+                       continue;
+               if (display) {
+                       nv_rd32(dev, addr + 0x20);
+                       pc = nv_rd32(dev, addr + 0x24);
+                       oplow = nv_rd32(dev, addr + 0x70);
+                       ophigh= nv_rd32(dev, addr + 0x74);
+                       NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - "
+                                       "TP %d MP %d: ", tpid, i);
+                       nouveau_print_enum_names(status,
+                                       nv50_mp_exec_error_names);
+                       printk(" at %06x warp %d, opcode %08x %08x\n",
+                                       pc&0xffffff, pc >> 24,
+                                       oplow, ophigh);
+               }
+               nv_wr32(dev, addr + 0x10, mp10);
+               nv_wr32(dev, addr + 0x14, 0);
+               mps++;
+       }
+       if (!mps && display)
+               NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: "
+                               "No MPs claiming errors?\n", tpid);
+}
+
+static void
+nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
+               uint32_t ustatus_new, int display, const char *name)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int tps = 0;
+       uint32_t units = nv_rd32(dev, 0x1540);
+       int i, r;
+       uint32_t ustatus_addr, ustatus;
+       for (i = 0; i < 16; i++) {
+               if (!(units & (1 << i)))
+                       continue;
+               if (dev_priv->chipset < 0xa0)
+                       ustatus_addr = ustatus_old + (i << 12);
+               else
+                       ustatus_addr = ustatus_new + (i << 11);
+               ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff;
+               if (!ustatus)
+                       continue;
+               tps++;
+               switch (type) {
+               case 6: /* texture error... unknown for now */
+                       nv50_pfb_vm_trap(dev, display, name);
+                       if (display) {
+                               NV_ERROR(dev, "magic set %d:\n", i);
+                               for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
+                                       NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
+                                               nv_rd32(dev, r));
+                       }
+                       break;
+               case 7: /* MP error */
+                       if (ustatus & 0x00010000) {
+                               nv50_pgraph_mp_trap(dev, i, display);
+                               ustatus &= ~0x00010000;
+                       }
+                       break;
+               case 8: /* TPDMA error */
+                       {
+                       uint32_t e0c = nv_rd32(dev, ustatus_addr + 4);
+                       uint32_t e10 = nv_rd32(dev, ustatus_addr + 8);
+                       uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc);
+                       uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10);
+                       uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14);
+                       uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18);
+                       uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c);
+                       nv50_pfb_vm_trap(dev, display, name);
+                       /* 2d engine destination */
+                       if (ustatus & 0x00000010) {
+                               if (display) {
+                                       NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n",
+                                                       i, e14, e10);
+                                       NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+                                                       i, e0c, e18, e1c, e20, e24);
+                               }
+                               ustatus &= ~0x00000010;
+                       }
+                       /* Render target */
+                       if (ustatus & 0x00000040) {
+                               if (display) {
+                                       NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n",
+                                                       i, e14, e10);
+                                       NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+                                                       i, e0c, e18, e1c, e20, e24);
+                               }
+                               ustatus &= ~0x00000040;
+                       }
+                       /* CUDA memory: l[], g[] or stack. */
+                       if (ustatus & 0x00000080) {
+                               if (display) {
+                                       if (e18 & 0x80000000) {
+                                               /* g[] read fault? */
+                                               NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n",
+                                                               i, e14, e10 | ((e18 >> 24) & 0x1f));
+                                               e18 &= ~0x1f000000;
+                                       } else if (e18 & 0xc) {
+                                               /* g[] write fault? */
+                                               NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n",
+                                                               i, e14, e10 | ((e18 >> 7) & 0x1f));
+                                               e18 &= ~0x00000f80;
+                                       } else {
+                                               NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n",
+                                                               i, e14, e10);
+                                       }
+                                       NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+                                                       i, e0c, e18, e1c, e20, e24);
+                               }
+                               ustatus &= ~0x00000080;
+                       }
+                       }
+                       break;
+               }
+               if (ustatus) {
+                       if (display)
+                               NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus);
+               }
+               nv_wr32(dev, ustatus_addr, 0xc0000000);
+       }
+
+       if (!tps && display)
+               NV_INFO(dev, "%s - No TPs claiming errors?\n", name);
+}
+
+static void
+nv50_pgraph_trap_handler(struct drm_device *dev)
+{
+       struct nouveau_pgraph_trap trap;
+       uint32_t status = nv_rd32(dev, 0x400108);
+       uint32_t ustatus;
+       int display = nouveau_ratelimit();
+
+
+       if (!status && display) {
+               nouveau_graph_trap_info(dev, &trap);
+               nouveau_graph_dump_trap_info(dev, "PGRAPH_TRAP", &trap);
+               NV_INFO(dev, "PGRAPH_TRAP - no units reporting traps?\n");
+       }
+
+       /* DISPATCH: Relays commands to other units and handles NOTIFY,
+        * COND, QUERY. If you get a trap from it, the command is still stuck
+        * in DISPATCH and you need to do something about it. */
+       if (status & 0x001) {
+               ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff;
+               if (!ustatus && display) {
+                       NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n");
+               }
+
+               /* Known to be triggered by screwed up NOTIFY and COND... */
+               if (ustatus & 0x00000001) {
+                       nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT");
+                       nv_wr32(dev, 0x400500, 0);
+                       if (nv_rd32(dev, 0x400808) & 0x80000000) {
+                               if (display) {
+                                       if (nouveau_graph_trapped_channel(dev, &trap.channel))
+                                               trap.channel = -1;
+                                       trap.class = nv_rd32(dev, 0x400814);
+                                       trap.mthd = nv_rd32(dev, 0x400808) & 0x1ffc;
+                                       trap.subc = (nv_rd32(dev, 0x400808) >> 16) & 0x7;
+                                       trap.data = nv_rd32(dev, 0x40080c);
+                                       trap.data2 = nv_rd32(dev, 0x400810);
+                                       nouveau_graph_dump_trap_info(dev,
+                                                       "PGRAPH_TRAP_DISPATCH_FAULT", &trap);
+                                       NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400808: %08x\n", nv_rd32(dev, 0x400808));
+                                       NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400848: %08x\n", nv_rd32(dev, 0x400848));
+                               }
+                               nv_wr32(dev, 0x400808, 0);
+                       } else if (display) {
+                               NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - No stuck command?\n");
+                       }
+                       nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3);
+                       nv_wr32(dev, 0x400848, 0);
+                       ustatus &= ~0x00000001;
+               }
+               if (ustatus & 0x00000002) {
+                       nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY");
+                       nv_wr32(dev, 0x400500, 0);
+                       if (nv_rd32(dev, 0x40084c) & 0x80000000) {
+                               if (display) {
+                                       if (nouveau_graph_trapped_channel(dev, &trap.channel))
+                                               trap.channel = -1;
+                                       trap.class = nv_rd32(dev, 0x400814);
+                                       trap.mthd = nv_rd32(dev, 0x40084c) & 0x1ffc;
+                                       trap.subc = (nv_rd32(dev, 0x40084c) >> 16) & 0x7;
+                                       trap.data = nv_rd32(dev, 0x40085c);
+                                       trap.data2 = 0;
+                                       nouveau_graph_dump_trap_info(dev,
+                                                       "PGRAPH_TRAP_DISPATCH_QUERY", &trap);
+                                       NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - 40084c: %08x\n", nv_rd32(dev, 0x40084c));
+                               }
+                               nv_wr32(dev, 0x40084c, 0);
+                       } else if (display) {
+                               NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - No stuck command?\n");
+                       }
+                       ustatus &= ~0x00000002;
+               }
+               if (ustatus && display)
+                       NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - Unhandled ustatus 0x%08x\n", ustatus);
+               nv_wr32(dev, 0x400804, 0xc0000000);
+               nv_wr32(dev, 0x400108, 0x001);
+               status &= ~0x001;
+       }
+
+       /* TRAPs other than dispatch use the "normal" trap regs. */
+       if (status && display) {
+               nouveau_graph_trap_info(dev, &trap);
+               nouveau_graph_dump_trap_info(dev,
+                               "PGRAPH_TRAP", &trap);
+       }
+
+       /* M2MF: Memory to memory copy engine. */
+       if (status & 0x002) {
+               ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff;
+               if (!ustatus && display) {
+                       NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n");
+               }
+               if (ustatus & 0x00000001) {
+                       nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY");
+                       ustatus &= ~0x00000001;
+               }
+               if (ustatus & 0x00000002) {
+                       nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN");
+                       ustatus &= ~0x00000002;
+               }
+               if (ustatus & 0x00000004) {
+                       nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT");
+                       ustatus &= ~0x00000004;
+               }
+               NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n",
+                               nv_rd32(dev, 0x406804),
+                               nv_rd32(dev, 0x406808),
+                               nv_rd32(dev, 0x40680c),
+                               nv_rd32(dev, 0x406810));
+               if (ustatus && display)
+                       NV_INFO(dev, "PGRAPH_TRAP_M2MF - Unhandled ustatus 0x%08x\n", ustatus);
+               /* No sane way found yet -- just reset the bugger. */
+               nv_wr32(dev, 0x400040, 2);
+               nv_wr32(dev, 0x400040, 0);
+               nv_wr32(dev, 0x406800, 0xc0000000);
+               nv_wr32(dev, 0x400108, 0x002);
+               status &= ~0x002;
+       }
+
+       /* VFETCH: Fetches data from vertex buffers. */
+       if (status & 0x004) {
+               ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff;
+               if (!ustatus && display) {
+                       NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n");
+               }
+               if (ustatus & 0x00000001) {
+                       nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT");
+                       NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n",
+                                       nv_rd32(dev, 0x400c00),
+                                       nv_rd32(dev, 0x400c08),
+                                       nv_rd32(dev, 0x400c0c),
+                                       nv_rd32(dev, 0x400c10));
+                       ustatus &= ~0x00000001;
+               }
+               if (ustatus && display)
+                       NV_INFO(dev, "PGRAPH_TRAP_VFETCH - Unhandled ustatus 0x%08x\n", ustatus);
+               nv_wr32(dev, 0x400c04, 0xc0000000);
+               nv_wr32(dev, 0x400108, 0x004);
+               status &= ~0x004;
+       }
+
+       /* STRMOUT: DirectX streamout / OpenGL transform feedback. */
+       if (status & 0x008) {
+               ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff;
+               if (!ustatus && display) {
+                       NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n");
+               }
+               if (ustatus & 0x00000001) {
+                       nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT");
+                       NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n",
+                                       nv_rd32(dev, 0x401804),
+                                       nv_rd32(dev, 0x401808),
+                                       nv_rd32(dev, 0x40180c),
+                                       nv_rd32(dev, 0x401810));
+                       ustatus &= ~0x00000001;
+               }
+               if (ustatus && display)
+                       NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - Unhandled ustatus 0x%08x\n", ustatus);
+               /* No sane way found yet -- just reset the bugger. */
+               nv_wr32(dev, 0x400040, 0x80);
+               nv_wr32(dev, 0x400040, 0);
+               nv_wr32(dev, 0x401800, 0xc0000000);
+               nv_wr32(dev, 0x400108, 0x008);
+               status &= ~0x008;
+       }
+
+       /* CCACHE: Handles code and c[] caches and fills them. */
+       if (status & 0x010) {
+               ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff;
+               if (!ustatus && display) {
+                       NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n");
+               }
+               if (ustatus & 0x00000001) {
+                       nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT");
+                       NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n",
+                                       nv_rd32(dev, 0x405800),
+                                       nv_rd32(dev, 0x405804),
+                                       nv_rd32(dev, 0x405808),
+                                       nv_rd32(dev, 0x40580c),
+                                       nv_rd32(dev, 0x405810),
+                                       nv_rd32(dev, 0x405814),
+                                       nv_rd32(dev, 0x40581c));
+                       ustatus &= ~0x00000001;
+               }
+               if (ustatus && display)
+                       NV_INFO(dev, "PGRAPH_TRAP_CCACHE - Unhandled ustatus 0x%08x\n", ustatus);
+               nv_wr32(dev, 0x405018, 0xc0000000);
+               nv_wr32(dev, 0x400108, 0x010);
+               status &= ~0x010;
+       }
+
+       /* Unknown, not seen yet... 0x402000 is the only trap status reg
+        * remaining, so try to handle it anyway. Perhaps related to that
+        * unknown DMA slot on tesla? */
+       if (status & 0x20) {
+               nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04");
+               ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff;
+               if (display)
+                       NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus);
+               nv_wr32(dev, 0x402000, 0xc0000000);
+               /* no status modifiction on purpose */
+       }
+
+       /* TEXTURE: CUDA texturing units */
+       if (status & 0x040) {
+               nv50_pgraph_tp_trap (dev, 6, 0x408900, 0x408600, display,
+                               "PGRAPH_TRAP_TEXTURE");
+               nv_wr32(dev, 0x400108, 0x040);
+               status &= ~0x040;
+       }
+
+       /* MP: CUDA execution engines. */
+       if (status & 0x080) {
+               nv50_pgraph_tp_trap (dev, 7, 0x408314, 0x40831c, display,
+                               "PGRAPH_TRAP_MP");
+               nv_wr32(dev, 0x400108, 0x080);
+               status &= ~0x080;
+       }
+
+       /* TPDMA:  Handles TP-initiated uncached memory accesses:
+        * l[], g[], stack, 2d surfaces, render targets. */
+       if (status & 0x100) {
+               nv50_pgraph_tp_trap (dev, 8, 0x408e08, 0x408708, display,
+                               "PGRAPH_TRAP_TPDMA");
+               nv_wr32(dev, 0x400108, 0x100);
+               status &= ~0x100;
+       }
+
+       if (status) {
+               if (display)
+                       NV_INFO(dev, "PGRAPH_TRAP - Unknown trap 0x%08x\n",
+                               status);
+               nv_wr32(dev, 0x400108, status);
+       }
+}
+
+/* There must be a *lot* of these. Will take some time to gather them up. */
+static struct nouveau_enum_names nv50_data_error_names[] =
+{
+       { 4,    "INVALID_VALUE" },
+       { 5,    "INVALID_ENUM" },
+       { 8,    "INVALID_OBJECT" },
+       { 0xc,  "INVALID_BITFIELD" },
+       { 0x28, "MP_NO_REG_SPACE" },
+       { 0x2b, "MP_BLOCK_SIZE_MISMATCH" },
+};
+
 static void
 nv50_pgraph_irq_handler(struct drm_device *dev)
 {
+       struct nouveau_pgraph_trap trap;
+       int unhandled = 0;
        uint32_t status;
 
        while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
-               uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
-
+               /* NOTIFY: You've set a NOTIFY an a command and it's done. */
                if (status & 0x00000001) {
-                       nouveau_pgraph_intr_notify(dev, nsource);
+                       nouveau_graph_trap_info(dev, &trap);
+                       if (nouveau_ratelimit())
+                               nouveau_graph_dump_trap_info(dev,
+                                               "PGRAPH_NOTIFY", &trap);
                        status &= ~0x00000001;
                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001);
                }
 
-               if (status & 0x00000010) {
-                       nouveau_pgraph_intr_error(dev, nsource |
-                                       NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD);
+               /* COMPUTE_QUERY: Purpose and exact cause unknown, happens
+                * when you write 0x200 to 0x50c0 method 0x31c. */
+               if (status & 0x00000002) {
+                       nouveau_graph_trap_info(dev, &trap);
+                       if (nouveau_ratelimit())
+                               nouveau_graph_dump_trap_info(dev,
+                                               "PGRAPH_COMPUTE_QUERY", &trap);
+                       status &= ~0x00000002;
+                       nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000002);
+               }
 
+               /* Unknown, never seen: 0x4 */
+
+               /* ILLEGAL_MTHD: You used a wrong method for this class. */
+               if (status & 0x00000010) {
+                       nouveau_graph_trap_info(dev, &trap);
+                       if (nouveau_pgraph_intr_swmthd(dev, &trap))
+                               unhandled = 1;
+                       if (unhandled && nouveau_ratelimit())
+                               nouveau_graph_dump_trap_info(dev,
+                                               "PGRAPH_ILLEGAL_MTHD", &trap);
                        status &= ~0x00000010;
                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010);
                }
 
+               /* ILLEGAL_CLASS: You used a wrong class. */
+               if (status & 0x00000020) {
+                       nouveau_graph_trap_info(dev, &trap);
+                       if (nouveau_ratelimit())
+                               nouveau_graph_dump_trap_info(dev,
+                                               "PGRAPH_ILLEGAL_CLASS", &trap);
+                       status &= ~0x00000020;
+                       nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000020);
+               }
+
+               /* DOUBLE_NOTIFY: You tried to set a NOTIFY on another NOTIFY. */
+               if (status & 0x00000040) {
+                       nouveau_graph_trap_info(dev, &trap);
+                       if (nouveau_ratelimit())
+                               nouveau_graph_dump_trap_info(dev,
+                                               "PGRAPH_DOUBLE_NOTIFY", &trap);
+                       status &= ~0x00000040;
+                       nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000040);
+               }
+
+               /* CONTEXT_SWITCH: PGRAPH needs us to load a new context */
                if (status & 0x00001000) {
                        nv_wr32(dev, 0x400500, 0x00000000);
                        nv_wr32(dev, NV03_PGRAPH_INTR,
@@ -613,49 +1115,59 @@ nv50_pgraph_irq_handler(struct drm_device *dev)
                        status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
                }
 
-               if (status & 0x00100000) {
-                       nouveau_pgraph_intr_error(dev, nsource |
-                                       NV03_PGRAPH_NSOURCE_DATA_ERROR);
+               /* BUFFER_NOTIFY: Your m2mf transfer finished */
+               if (status & 0x00010000) {
+                       nouveau_graph_trap_info(dev, &trap);
+                       if (nouveau_ratelimit())
+                               nouveau_graph_dump_trap_info(dev,
+                                               "PGRAPH_BUFFER_NOTIFY", &trap);
+                       status &= ~0x00010000;
+                       nv_wr32(dev, NV03_PGRAPH_INTR, 0x00010000);
+               }
 
+               /* DATA_ERROR: Invalid value for this method, or invalid
+                * state in current PGRAPH context for this operation */
+               if (status & 0x00100000) {
+                       nouveau_graph_trap_info(dev, &trap);
+                       if (nouveau_ratelimit()) {
+                               nouveau_graph_dump_trap_info(dev,
+                                               "PGRAPH_DATA_ERROR", &trap);
+                               NV_INFO (dev, "PGRAPH_DATA_ERROR - ");
+                               nouveau_print_enum_names(nv_rd32(dev, 0x400110),
+                                               nv50_data_error_names);
+                               printk("\n");
+                       }
                        status &= ~0x00100000;
                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000);
                }
 
+               /* TRAP: Something bad happened in the middle of command
+                * execution.  Has a billion types, subtypes, and even
+                * subsubtypes. */
                if (status & 0x00200000) {
-                       int r;
-
-                       nouveau_pgraph_intr_error(dev, nsource |
-                                       NV03_PGRAPH_NSOURCE_PROTECTION_ERROR);
-
-                       NV_ERROR(dev, "magic set 1:\n");
-                       for (r = 0x408900; r <= 0x408910; r += 4)
-                               NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
-                                       nv_rd32(dev, r));
-                       nv_wr32(dev, 0x408900,
-                               nv_rd32(dev, 0x408904) | 0xc0000000);
-                       for (r = 0x408e08; r <= 0x408e24; r += 4)
-                               NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
-                                                       nv_rd32(dev, r));
-                       nv_wr32(dev, 0x408e08,
-                               nv_rd32(dev, 0x408e08) | 0xc0000000);
-
-                       NV_ERROR(dev, "magic set 2:\n");
-                       for (r = 0x409900; r <= 0x409910; r += 4)
-                               NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
-                                       nv_rd32(dev, r));
-                       nv_wr32(dev, 0x409900,
-                               nv_rd32(dev, 0x409904) | 0xc0000000);
-                       for (r = 0x409e08; r <= 0x409e24; r += 4)
-                               NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
-                                       nv_rd32(dev, r));
-                       nv_wr32(dev, 0x409e08,
-                               nv_rd32(dev, 0x409e08) | 0xc0000000);
-
+                       nv50_pgraph_trap_handler(dev);
                        status &= ~0x00200000;
-                       nv_wr32(dev, NV03_PGRAPH_NSOURCE, nsource);
                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000);
                }
 
+               /* Unknown, never seen: 0x00400000 */
+
+               /* SINGLE_STEP: Happens on every method if you turned on
+                * single stepping in 40008c */
+               if (status & 0x01000000) {
+                       nouveau_graph_trap_info(dev, &trap);
+                       if (nouveau_ratelimit())
+                               nouveau_graph_dump_trap_info(dev,
+                                               "PGRAPH_SINGLE_STEP", &trap);
+                       status &= ~0x01000000;
+                       nv_wr32(dev, NV03_PGRAPH_INTR, 0x01000000);
+               }
+
+               /* 0x02000000 happens when you pause a ctxprog...
+                * but the only way this can happen that I know is by
+                * poking the relevant MMIO register, and we don't
+                * do that. */
+
                if (status) {
                        NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n",
                                status);
@@ -672,7 +1184,8 @@ nv50_pgraph_irq_handler(struct drm_device *dev)
        }
 
        nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
-       nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
+       if (nv_rd32(dev, 0x400824) & (1 << 31))
+               nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
 }
 
 static void
index eb8f084d5f537ec4edeb2444b992763e15549ade..58b46807de23a99ea31e5b874db84199a14ab9cf 100644 (file)
@@ -35,7 +35,6 @@
 #include "nouveau_drm.h"
 #include "nv50_display.h"
 
-static int nouveau_stub_init(struct drm_device *dev) { return 0; }
 static void nouveau_stub_takedown(struct drm_device *dev) {}
 
 static int nouveau_init_engine_ptrs(struct drm_device *dev)
@@ -277,8 +276,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->timer.init              = nv04_timer_init;
                engine->timer.read              = nv04_timer_read;
                engine->timer.takedown          = nv04_timer_takedown;
-               engine->fb.init                 = nouveau_stub_init;
-               engine->fb.takedown             = nouveau_stub_takedown;
+               engine->fb.init                 = nv50_fb_init;
+               engine->fb.takedown             = nv50_fb_takedown;
                engine->graph.grclass           = nv50_graph_grclass;
                engine->graph.init              = nv50_graph_init;
                engine->graph.takedown          = nv50_graph_takedown;
index a1d1ebb073d930e64342847ebd0a6add0ec0bc03..eba687f1099e24fcb164eb7a3f3e18550acc0508 100644 (file)
@@ -230,9 +230,9 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
        struct drm_framebuffer *fb = crtc->fb;
 
        /* Calculate our timings */
-       int horizDisplay        = (mode->crtc_hdisplay >> 3)    - 1;
-       int horizStart          = (mode->crtc_hsync_start >> 3)         - 1;
-       int horizEnd            = (mode->crtc_hsync_end >> 3)   - 1;
+       int horizDisplay        = (mode->crtc_hdisplay >> 3)            - 1;
+       int horizStart          = (mode->crtc_hsync_start >> 3)         + 1;
+       int horizEnd            = (mode->crtc_hsync_end >> 3)           + 1;
        int horizTotal          = (mode->crtc_htotal >> 3)              - 5;
        int horizBlankStart     = (mode->crtc_hdisplay >> 3)            - 1;
        int horizBlankEnd       = (mode->crtc_htotal >> 3)              - 1;
index 3da90c2c4e634910eba368bdb691bf9684cd5b95..813b25cec7269a6ff5e1ec5ec5aeb2875480dcb3 100644 (file)
@@ -118,8 +118,8 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
                return;
        }
 
-       width = ALIGN(image->width, 32);
-       dsize = (width * image->height) >> 5;
+       width = ALIGN(image->width, 8);
+       dsize = ALIGN(width * image->height, 32) >> 5;
 
        if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
            info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -136,8 +136,8 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
                         ((image->dx + image->width) & 0xffff));
        OUT_RING(chan, bg);
        OUT_RING(chan, fg);
-       OUT_RING(chan, (image->height << 16) | image->width);
        OUT_RING(chan, (image->height << 16) | width);
+       OUT_RING(chan, (image->height << 16) | image->width);
        OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
 
        while (dsize) {
index 61a89f2dc5535ecf1d74f08b9c342727997c1766..fac6c88a2b1f1042b88720c853ba466fd7807c8b 100644 (file)
@@ -522,8 +522,8 @@ int nv50_display_create(struct drm_device *dev)
        }
 
        for (i = 0 ; i < dcb->connector.entries; i++) {
-               if (i != 0 && dcb->connector.entry[i].index ==
-                             dcb->connector.entry[i - 1].index)
+               if (i != 0 && dcb->connector.entry[i].index2 ==
+                             dcb->connector.entry[i - 1].index2)
                        continue;
                nouveau_connector_create(dev, &dcb->connector.entry[i]);
        }
diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c
new file mode 100644 (file)
index 0000000..a95e694
--- /dev/null
@@ -0,0 +1,32 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+int
+nv50_fb_init(struct drm_device *dev)
+{
+       /* This is needed to get meaningful information from 100c90
+        * on traps. No idea what these values mean exactly. */
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       switch (dev_priv->chipset) {
+       case 0x50:
+               nv_wr32(dev, 0x100c90, 0x0707ff);
+               break;
+       case 0xa5:
+       case 0xa8:
+               nv_wr32(dev, 0x100c90, 0x0d0fff);
+               break;
+       default:
+               nv_wr32(dev, 0x100c90, 0x1d07ff);
+               break;
+       }
+
+       return 0;
+}
+
+void
+nv50_fb_takedown(struct drm_device *dev)
+{
+}
index 993c7126fbded104b6ed3a16cac2e5f07f757474..25a3cd8794f919991ab0ed717e129557eafaad55 100644 (file)
@@ -233,7 +233,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
        BEGIN_RING(chan, NvSub2D, 0x0808, 3);
        OUT_RING(chan, 0);
        OUT_RING(chan, 0);
-       OUT_RING(chan, 0);
+       OUT_RING(chan, 1);
        BEGIN_RING(chan, NvSub2D, 0x081c, 1);
        OUT_RING(chan, 1);
        BEGIN_RING(chan, NvSub2D, 0x0840, 4);
index 857a09671a394c80a534d350b659261d8f56c223..c62b33a02f889431fc6cde830138d16e3f0c6f40 100644 (file)
@@ -56,6 +56,10 @@ nv50_graph_init_intr(struct drm_device *dev)
 static void
 nv50_graph_init_regs__nv(struct drm_device *dev)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t units = nv_rd32(dev, 0x1540);
+       int i;
+
        NV_DEBUG(dev, "\n");
 
        nv_wr32(dev, 0x400804, 0xc0000000);
@@ -65,6 +69,20 @@ nv50_graph_init_regs__nv(struct drm_device *dev)
        nv_wr32(dev, 0x405018, 0xc0000000);
        nv_wr32(dev, 0x402000, 0xc0000000);
 
+       for (i = 0; i < 16; i++) {
+               if (units & 1 << i) {
+                       if (dev_priv->chipset < 0xa0) {
+                               nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000);
+                               nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000);
+                               nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000);
+                       } else {
+                               nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000);
+                               nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000);
+                               nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000);
+                       }
+               }
+       }
+
        nv_wr32(dev, 0x400108, 0xffffffff);
 
        nv_wr32(dev, 0x400824, 0x00004000);
@@ -229,10 +247,6 @@ nv50_graph_create_context(struct nouveau_channel *chan)
                nouveau_grctx_vals_load(dev, ctx);
        }
        nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12);
-       if ((dev_priv->chipset & 0xf0) == 0xa0)
-               nv_wo32(dev, ctx, 0x00004/4, 0x00000000);
-       else
-               nv_wo32(dev, ctx, 0x0011c/4, 0x00000000);
        dev_priv->engine.instmem.finish_access(dev);
 
        return 0;
index d105fcd42ca0d06febbed6db006b254928f8521e..546b31949a3079a8a8b4c82ab5d5534498437532 100644 (file)
@@ -64,6 +64,9 @@
 #define CP_FLAG_ALWAYS                ((2 * 32) + 13)
 #define CP_FLAG_ALWAYS_FALSE          0
 #define CP_FLAG_ALWAYS_TRUE           1
+#define CP_FLAG_INTR                  ((2 * 32) + 15)
+#define CP_FLAG_INTR_NOT_PENDING      0
+#define CP_FLAG_INTR_PENDING          1
 
 #define CP_CTX                   0x00100000
 #define CP_CTX_COUNT             0x000f0000
@@ -214,6 +217,8 @@ nv50_grctx_init(struct nouveau_grctx *ctx)
        cp_name(ctx, cp_setup_save);
        cp_set (ctx, UNK1D, SET);
        cp_wait(ctx, STATUS, BUSY);
+       cp_wait(ctx, INTR, PENDING);
+       cp_bra (ctx, STATUS, BUSY, cp_setup_save);
        cp_set (ctx, UNK01, SET);
        cp_set (ctx, SWAP_DIRECTION, SAVE);
 
@@ -269,7 +274,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
        int offset, base;
        uint32_t units = nv_rd32 (ctx->dev, 0x1540);
 
-       /* 0800 */
+       /* 0800: DISPATCH */
        cp_ctx(ctx, 0x400808, 7);
        gr_def(ctx, 0x400814, 0x00000030);
        cp_ctx(ctx, 0x400834, 0x32);
@@ -300,7 +305,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
                gr_def(ctx, 0x400b20, 0x0001629d);
        }
 
-       /* 0C00 */
+       /* 0C00: VFETCH */
        cp_ctx(ctx, 0x400c08, 0x2);
        gr_def(ctx, 0x400c08, 0x0000fe0c);
 
@@ -326,7 +331,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
        cp_ctx(ctx, 0x401540, 0x5);
        gr_def(ctx, 0x401550, 0x00001018);
 
-       /* 1800 */
+       /* 1800: STREAMOUT */
        cp_ctx(ctx, 0x401814, 0x1);
        gr_def(ctx, 0x401814, 0x000000ff);
        if (dev_priv->chipset == 0x50) {
@@ -641,7 +646,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
        if (dev_priv->chipset == 0x50)
                cp_ctx(ctx, 0x4063e0, 0x1);
 
-       /* 6800 */
+       /* 6800: M2MF */
        if (dev_priv->chipset < 0x90) {
                cp_ctx(ctx, 0x406814, 0x2b);
                gr_def(ctx, 0x406818, 0x00000f80);
index ed38262d9985e326e4bdffceb0fca5ea865e3362..3c91312dea9a00d8aa93b097d2d5d476487fb2d8 100644 (file)
@@ -50,7 +50,7 @@ $(obj)/r600_cs.o: $(obj)/r600_reg_safe.h
 radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
        radeon_irq.o r300_cmdbuf.o r600_cp.o
 # add KMS driver
-radeon-y += radeon_device.o radeon_kms.o \
+radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
        radeon_atombios.o radeon_agp.o atombios_crtc.o radeon_combios.o \
        atom.o radeon_fence.o radeon_ttm.o radeon_object.o radeon_gart.o \
        radeon_legacy_crtc.o radeon_legacy_encoders.o radeon_connectors.o \
index d75788feac6c6a64fe042e0e7d3e4a446d8b2e26..247f8ee7e9400294c4d1025d28a33285bc2530dc 100644 (file)
 
 typedef struct {
        struct atom_context *ctx;
-
        uint32_t *ps, *ws;
        int ps_shift;
        uint16_t start;
+       unsigned last_jump;
+       unsigned long last_jump_jiffies;
+       bool abort;
 } atom_exec_context;
 
 int atom_debug = 0;
-static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params);
-void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params);
+static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params);
+int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params);
 
 static uint32_t atom_arg_mask[8] =
     { 0xFFFFFFFF, 0xFFFF, 0xFFFF00, 0xFFFF0000, 0xFF, 0xFF00, 0xFF0000,
@@ -604,12 +606,17 @@ static void atom_op_beep(atom_exec_context *ctx, int *ptr, int arg)
 static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg)
 {
        int idx = U8((*ptr)++);
+       int r = 0;
+
        if (idx < ATOM_TABLE_NAMES_CNT)
                SDEBUG("   table: %d (%s)\n", idx, atom_table_names[idx]);
        else
                SDEBUG("   table: %d\n", idx);
        if (U16(ctx->ctx->cmd_table + 4 + 2 * idx))
-               atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
+               r = atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
+       if (r) {
+               ctx->abort = true;
+       }
 }
 
 static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg)
@@ -673,6 +680,8 @@ static void atom_op_eot(atom_exec_context *ctx, int *ptr, int arg)
 static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg)
 {
        int execute = 0, target = U16(*ptr);
+       unsigned long cjiffies;
+
        (*ptr) += 2;
        switch (arg) {
        case ATOM_COND_ABOVE:
@@ -700,8 +709,25 @@ static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg)
        if (arg != ATOM_COND_ALWAYS)
                SDEBUG("   taken: %s\n", execute ? "yes" : "no");
        SDEBUG("   target: 0x%04X\n", target);
-       if (execute)
+       if (execute) {
+               if (ctx->last_jump == (ctx->start + target)) {
+                       cjiffies = jiffies;
+                       if (time_after(cjiffies, ctx->last_jump_jiffies)) {
+                               cjiffies -= ctx->last_jump_jiffies;
+                               if ((jiffies_to_msecs(cjiffies) > 1000)) {
+                                       DRM_ERROR("atombios stuck in loop for more than 1sec aborting\n");
+                                       ctx->abort = true;
+                               }
+                       } else {
+                               /* jiffies wrap around we will just wait a little longer */
+                               ctx->last_jump_jiffies = jiffies;
+                       }
+               } else {
+                       ctx->last_jump = ctx->start + target;
+                       ctx->last_jump_jiffies = jiffies;
+               }
                *ptr = ctx->start + target;
+       }
 }
 
 static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg)
@@ -1104,7 +1130,7 @@ static struct {
        atom_op_shr, ATOM_ARG_MC}, {
 atom_op_debug, 0},};
 
-static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params)
+static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params)
 {
        int base = CU16(ctx->cmd_table + 4 + 2 * index);
        int len, ws, ps, ptr;
@@ -1112,7 +1138,7 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
        atom_exec_context ectx;
 
        if (!base)
-               return;
+               return -EINVAL;
 
        len = CU16(base + ATOM_CT_SIZE_PTR);
        ws = CU8(base + ATOM_CT_WS_PTR);
@@ -1125,6 +1151,8 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
        ectx.ps_shift = ps / 4;
        ectx.start = base;
        ectx.ps = params;
+       ectx.abort = false;
+       ectx.last_jump = 0;
        if (ws)
                ectx.ws = kzalloc(4 * ws, GFP_KERNEL);
        else
@@ -1137,6 +1165,11 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
                        SDEBUG("%s @ 0x%04X\n", atom_op_names[op], ptr - 1);
                else
                        SDEBUG("[%d] @ 0x%04X\n", op, ptr - 1);
+               if (ectx.abort) {
+                       DRM_ERROR("atombios stuck executing %04X (len %d, WS %d, PS %d) @ 0x%04X\n",
+                               base, len, ws, ps, ptr - 1);
+                       return -EINVAL;
+               }
 
                if (op < ATOM_OP_CNT && op > 0)
                        opcode_table[op].func(&ectx, &ptr,
@@ -1152,10 +1185,13 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
 
        if (ws)
                kfree(ectx.ws);
+       return 0;
 }
 
-void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
+int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
 {
+       int r;
+
        mutex_lock(&ctx->mutex);
        /* reset reg block */
        ctx->reg_block = 0;
@@ -1163,8 +1199,9 @@ void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
        ctx->fb_base = 0;
        /* reset io mode */
        ctx->io_mode = ATOM_IO_MM;
-       atom_execute_table_locked(ctx, index, params);
+       r = atom_execute_table_locked(ctx, index, params);
        mutex_unlock(&ctx->mutex);
+       return r;
 }
 
 static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
@@ -1248,9 +1285,7 @@ int atom_asic_init(struct atom_context *ctx)
 
        if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT))
                return 1;
-       atom_execute_table(ctx, ATOM_CMD_INIT, ps);
-
-       return 0;
+       return atom_execute_table(ctx, ATOM_CMD_INIT, ps);
 }
 
 void atom_destroy(struct atom_context *ctx)
@@ -1260,12 +1295,16 @@ void atom_destroy(struct atom_context *ctx)
        kfree(ctx);
 }
 
-void atom_parse_data_header(struct atom_context *ctx, int index,
+bool atom_parse_data_header(struct atom_context *ctx, int index,
                            uint16_t * size, uint8_t * frev, uint8_t * crev,
                            uint16_t * data_start)
 {
        int offset = index * 2 + 4;
        int idx = CU16(ctx->data_table + offset);
+       u16 *mdt = (u16 *)(ctx->bios + ctx->data_table + 4);
+
+       if (!mdt[index])
+               return false;
 
        if (size)
                *size = CU16(idx);
@@ -1274,38 +1313,42 @@ void atom_parse_data_header(struct atom_context *ctx, int index,
        if (crev)
                *crev = CU8(idx + 3);
        *data_start = idx;
-       return;
+       return true;
 }
 
-void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev,
+bool atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev,
                           uint8_t * crev)
 {
        int offset = index * 2 + 4;
        int idx = CU16(ctx->cmd_table + offset);
+       u16 *mct = (u16 *)(ctx->bios + ctx->cmd_table + 4);
+
+       if (!mct[index])
+               return false;
 
        if (frev)
                *frev = CU8(idx + 2);
        if (crev)
                *crev = CU8(idx + 3);
-       return;
+       return true;
 }
 
 int atom_allocate_fb_scratch(struct atom_context *ctx)
 {
        int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware);
        uint16_t data_offset;
-       int usage_bytes;
+       int usage_bytes = 0;
        struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage;
 
-       atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
+       if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
+               firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
 
-       firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
+               DRM_DEBUG("atom firmware requested %08x %dkb\n",
+                         firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware,
+                         firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
 
-       DRM_DEBUG("atom firmware requested %08x %dkb\n",
-                 firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware,
-                 firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
-
-       usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
+               usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
+       }
        if (usage_bytes == 0)
                usage_bytes = 20 * 1024;
        /* allocate some scratch memory */
index bc73781423a17599fadf9e2bfa1bca556b5504ca..cd1b64ab5ca7c0c4b24e29bd4dd04e8b52387b16 100644 (file)
@@ -140,11 +140,13 @@ struct atom_context {
 extern int atom_debug;
 
 struct atom_context *atom_parse(struct card_info *, void *);
-void atom_execute_table(struct atom_context *, int, uint32_t *);
+int atom_execute_table(struct atom_context *, int, uint32_t *);
 int atom_asic_init(struct atom_context *);
 void atom_destroy(struct atom_context *);
-void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start);
-void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev);
+bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size,
+                           uint8_t *frev, uint8_t *crev, uint16_t *data_start);
+bool atom_parse_cmd_header(struct atom_context *ctx, int index,
+                          uint8_t *frev, uint8_t *crev);
 int atom_allocate_fb_scratch(struct atom_context *ctx);
 #include "atom-types.h"
 #include "atombios.h"
index dd9fdf560611521aeb49d52f90da3fc3a59290df..fd4ef6d1884968345dcf0debbd70161fc31b3b4a 100644 (file)
@@ -353,12 +353,55 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+static void atombios_disable_ss(struct drm_crtc *crtc)
+{
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       u32 ss_cntl;
+
+       if (ASIC_IS_DCE4(rdev)) {
+               switch (radeon_crtc->pll_id) {
+               case ATOM_PPLL1:
+                       ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL);
+                       ss_cntl &= ~EVERGREEN_PxPLL_SS_EN;
+                       WREG32(EVERGREEN_P1PLL_SS_CNTL, ss_cntl);
+                       break;
+               case ATOM_PPLL2:
+                       ss_cntl = RREG32(EVERGREEN_P2PLL_SS_CNTL);
+                       ss_cntl &= ~EVERGREEN_PxPLL_SS_EN;
+                       WREG32(EVERGREEN_P2PLL_SS_CNTL, ss_cntl);
+                       break;
+               case ATOM_DCPLL:
+               case ATOM_PPLL_INVALID:
+                       return;
+               }
+       } else if (ASIC_IS_AVIVO(rdev)) {
+               switch (radeon_crtc->pll_id) {
+               case ATOM_PPLL1:
+                       ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
+                       ss_cntl &= ~1;
+                       WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl);
+                       break;
+               case ATOM_PPLL2:
+                       ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL);
+                       ss_cntl &= ~1;
+                       WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl);
+                       break;
+               case ATOM_DCPLL:
+               case ATOM_PPLL_INVALID:
+                       return;
+               }
+       }
+}
+
+
 union atom_enable_ss {
        ENABLE_LVDS_SS_PARAMETERS legacy;
        ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1;
 };
 
-static void atombios_set_ss(struct drm_crtc *crtc, int enable)
+static void atombios_enable_ss(struct drm_crtc *crtc)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
@@ -387,9 +430,9 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable)
                                        step = dig->ss->step;
                                        delay = dig->ss->delay;
                                        range = dig->ss->range;
-                               } else if (enable)
+                               } else
                                        return;
-                       } else if (enable)
+                       } else
                                return;
                        break;
                }
@@ -406,13 +449,13 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable)
                args.v1.ucSpreadSpectrumDelay = delay;
                args.v1.ucSpreadSpectrumRange = range;
                args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-               args.v1.ucEnable = enable;
+               args.v1.ucEnable = ATOM_ENABLE;
        } else {
                args.legacy.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
                args.legacy.ucSpreadSpectrumType = type;
                args.legacy.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2;
                args.legacy.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4;
-               args.legacy.ucEnable = enable;
+               args.legacy.ucEnable = ATOM_ENABLE;
        }
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
@@ -478,11 +521,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
                                if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
                                        adjusted_clock = mode->clock * 2;
-                               /* LVDS PLL quirks */
-                               if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
-                                       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-                                       pll->algo = dig->pll_algo;
-                               }
                        } else {
                                if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
                                        pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
@@ -503,8 +541,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                int index;
 
                index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
-               atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
-                                     &crev);
+               if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
+                                          &crev))
+                       return adjusted_clock;
 
                memset(&args, 0, sizeof(args));
 
@@ -542,11 +581,16 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                        }
                                } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
                                        /* may want to enable SS on DP/eDP eventually */
-                                       args.v3.sInput.ucDispPllConfig |=
-                                               DISPPLL_CONFIG_SS_ENABLE;
-                                       if (mode->clock > 165000)
+                                       /*args.v3.sInput.ucDispPllConfig |=
+                                               DISPPLL_CONFIG_SS_ENABLE;*/
+                                       if (encoder_mode == ATOM_ENCODER_MODE_DP)
                                                args.v3.sInput.ucDispPllConfig |=
-                                                       DISPPLL_CONFIG_DUAL_LINK;
+                                                       DISPPLL_CONFIG_COHERENT_MODE;
+                                       else {
+                                               if (mode->clock > 165000)
+                                                       args.v3.sInput.ucDispPllConfig |=
+                                                               DISPPLL_CONFIG_DUAL_LINK;
+                                       }
                                }
                                atom_execute_table(rdev->mode_info.atom_context,
                                                   index, (uint32_t *)&args);
@@ -592,8 +636,9 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc)
        memset(&args, 0, sizeof(args));
 
        index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
-       atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
-                             &crev);
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
+                                  &crev))
+               return;
 
        switch (frev) {
        case 1:
@@ -667,8 +712,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                           &ref_div, &post_div);
 
        index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
-       atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
-                             &crev);
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
+                                  &crev))
+               return;
 
        switch (frev) {
        case 1:
@@ -1083,15 +1129,12 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
 
        /* TODO color tiling */
 
-       /* pick pll */
-       radeon_crtc->pll_id = radeon_atom_pick_pll(crtc);
-
-       atombios_set_ss(crtc, 0);
+       atombios_disable_ss(crtc);
        /* always set DCPLL */
        if (ASIC_IS_DCE4(rdev))
                atombios_crtc_set_dcpll(crtc);
        atombios_crtc_set_pll(crtc, adjusted_mode);
-       atombios_set_ss(crtc, 1);
+       atombios_enable_ss(crtc);
 
        if (ASIC_IS_DCE4(rdev))
                atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
@@ -1120,6 +1163,11 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
 
 static void atombios_crtc_prepare(struct drm_crtc *crtc)
 {
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+
+       /* pick pll */
+       radeon_crtc->pll_id = radeon_atom_pick_pll(crtc);
+
        atombios_lock_crtc(crtc, ATOM_ENABLE);
        atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 }
index 8a133bda00a25b092e764f1eec2bca80c57cb569..28b31c64f48dd4eee064356c1d8a2bd840165f0d 100644 (file)
@@ -745,14 +745,14 @@ void dp_link_train(struct drm_encoder *encoder,
                          >> DP_TRAIN_PRE_EMPHASIS_SHIFT);
 
        /* disable the training pattern on the sink */
+       dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE);
+
+       /* disable the training pattern on the source */
        if (ASIC_IS_DCE4(rdev))
                atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
        else
                radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE,
                                          dig_connector->dp_clock, enc_id, 0);
-
-       radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE,
-                                 dig_connector->dp_clock, enc_id, 0);
 }
 
 int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
index bd2e7aa85c1d66e710b1b6f97c7652b941db6d34..647a0efdc353a94efcc3d054ac607d586d24111f 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/platform_device.h>
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "radeon_drm.h"
 #include "rv770d.h"
 #include "atom.h"
@@ -436,7 +437,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
 
 int evergreen_mc_init(struct radeon_device *rdev)
 {
-       fixed20_12 a;
        u32 tmp;
        int chansize, numchan;
 
@@ -481,12 +481,8 @@ int evergreen_mc_init(struct radeon_device *rdev)
                rdev->mc.real_vram_size = rdev->mc.aper_size;
        }
        r600_vram_gtt_location(rdev, &rdev->mc);
-       /* FIXME: we should enforce default clock in case GPU is not in
-        * default setup
-        */
-       a.full = rfixed_const(100);
-       rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
-       rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+       radeon_update_bandwidth_info(rdev);
+
        return 0;
 }
 
@@ -746,6 +742,7 @@ int evergreen_init(struct radeon_device *rdev)
 
 void evergreen_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        evergreen_suspend(rdev);
 #if 0
        r600_blit_fini(rdev);
index 91eb762eb3f918625f3b17f0a8360551d628480e..3ae51ada1abf1dd35aaa5e44586589c705405b4f 100644 (file)
@@ -31,6 +31,7 @@
 #include "radeon_drm.h"
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "r100d.h"
 #include "rs100d.h"
 #include "rv200d.h"
@@ -235,9 +236,9 @@ int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 
 void r100_pci_gart_fini(struct radeon_device *rdev)
 {
+       radeon_gart_fini(rdev);
        r100_pci_gart_disable(rdev);
        radeon_gart_table_ram_free(rdev);
-       radeon_gart_fini(rdev);
 }
 
 int r100_irq_set(struct radeon_device *rdev)
@@ -312,10 +313,12 @@ int r100_irq_process(struct radeon_device *rdev)
                /* Vertical blank interrupts */
                if (status & RADEON_CRTC_VBLANK_STAT) {
                        drm_handle_vblank(rdev->ddev, 0);
+                       rdev->pm.vblank_sync = true;
                        wake_up(&rdev->irq.vblank_queue);
                }
                if (status & RADEON_CRTC2_VBLANK_STAT) {
                        drm_handle_vblank(rdev->ddev, 1);
+                       rdev->pm.vblank_sync = true;
                        wake_up(&rdev->irq.vblank_queue);
                }
                if (status & RADEON_FP_DETECT_STAT) {
@@ -741,6 +744,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
        udelay(10);
        rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
        rdev->cp.wptr = RREG32(RADEON_CP_RB_WPTR);
+       /* protect against crazy HW on resume */
+       rdev->cp.wptr &= rdev->cp.ptr_mask;
        /* Set cp mode to bus mastering & enable cp*/
        WREG32(RADEON_CP_CSQ_MODE,
               REG_SET(RADEON_INDIRECT2_START, indirect2_start) |
@@ -1804,6 +1809,7 @@ void r100_set_common_regs(struct radeon_device *rdev)
 {
        struct drm_device *dev = rdev->ddev;
        bool force_dac2 = false;
+       u32 tmp;
 
        /* set these so they don't interfere with anything */
        WREG32(RADEON_OV0_SCALE_CNTL, 0);
@@ -1875,6 +1881,12 @@ void r100_set_common_regs(struct radeon_device *rdev)
                WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
                WREG32(RADEON_DAC_CNTL2, dac2_cntl);
        }
+
+       /* switch PM block to ACPI mode */
+       tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL);
+       tmp &= ~RADEON_PM_MODE_SEL;
+       WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp);
+
 }
 
 /*
@@ -2022,6 +2034,7 @@ void r100_mc_init(struct radeon_device *rdev)
        radeon_vram_location(rdev, &rdev->mc, base);
        if (!(rdev->flags & RADEON_IS_AGP))
                radeon_gtt_location(rdev, &rdev->mc);
+       radeon_update_bandwidth_info(rdev);
 }
 
 
@@ -2385,6 +2398,8 @@ void r100_bandwidth_update(struct radeon_device *rdev)
        uint32_t pixel_bytes1 = 0;
        uint32_t pixel_bytes2 = 0;
 
+       radeon_update_display_priority(rdev);
+
        if (rdev->mode_info.crtcs[0]->base.enabled) {
                mode1 = &rdev->mode_info.crtcs[0]->base.mode;
                pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
@@ -2413,11 +2428,8 @@ void r100_bandwidth_update(struct radeon_device *rdev)
        /*
         * determine is there is enough bw for current mode
         */
-       mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
-       temp_ff.full = rfixed_const(100);
-       mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
-       sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
-       sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
+       sclk_ff = rdev->pm.sclk;
+       mclk_ff = rdev->pm.mclk;
 
        temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
        temp_ff.full = rfixed_const(temp);
@@ -3440,6 +3452,7 @@ int r100_suspend(struct radeon_device *rdev)
 
 void r100_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index 1146c9909c2c11457f583edf73e8b5c31e0ab5b1..85617c3112127e09bd23442d6b84566ac99a29bd 100644 (file)
@@ -30,6 +30,7 @@
 #include "radeon_drm.h"
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 
 #include "r100d.h"
 #include "r200_reg_safe.h"
index 4cef90cd74e5176fe01b41b37eb38d1050db1fb4..1023eeb658722b28b88b89678aed62178dc3aa7d 100644 (file)
@@ -30,6 +30,7 @@
 #include "drm.h"
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "radeon_drm.h"
 #include "r100_track.h"
 #include "r300d.h"
@@ -164,9 +165,9 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev)
 
 void rv370_pcie_gart_fini(struct radeon_device *rdev)
 {
+       radeon_gart_fini(rdev);
        rv370_pcie_gart_disable(rdev);
        radeon_gart_table_vram_free(rdev);
-       radeon_gart_fini(rdev);
 }
 
 void r300_fence_ring_emit(struct radeon_device *rdev,
@@ -481,6 +482,7 @@ void r300_mc_init(struct radeon_device *rdev)
        radeon_vram_location(rdev, &rdev->mc, base);
        if (!(rdev->flags & RADEON_IS_AGP))
                radeon_gtt_location(rdev, &rdev->mc);
+       radeon_update_bandwidth_info(rdev);
 }
 
 void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes)
@@ -1334,6 +1336,7 @@ int r300_suspend(struct radeon_device *rdev)
 
 void r300_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index c7593b8f58eeaf61d41c8860fc0f74306071564e..0b8603ca6974fe4d243fa7c474488829d824411a 100644 (file)
@@ -29,6 +29,7 @@
 #include "drmP.h"
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "atom.h"
 #include "r100d.h"
 #include "r420d.h"
@@ -266,6 +267,7 @@ int r420_suspend(struct radeon_device *rdev)
 
 void r420_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index 2b8a5dd1351672bbacbf260d33441910514ff7a9..3c44b8d393180283c71f566656b2edc78d0017bb 100644 (file)
@@ -27,6 +27,7 @@
  */
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "atom.h"
 #include "r520d.h"
 
@@ -121,19 +122,13 @@ static void r520_vram_get_type(struct radeon_device *rdev)
 
 void r520_mc_init(struct radeon_device *rdev)
 {
-       fixed20_12 a;
 
        r520_vram_get_type(rdev);
        r100_vram_init_sizes(rdev);
        radeon_vram_location(rdev, &rdev->mc, 0);
        if (!(rdev->flags & RADEON_IS_AGP))
                radeon_gtt_location(rdev, &rdev->mc);
-       /* FIXME: we should enforce default clock in case GPU is not in
-        * default setup
-        */
-       a.full = rfixed_const(100);
-       rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
-       rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+       radeon_update_bandwidth_info(rdev);
 }
 
 void r520_mc_program(struct radeon_device *rdev)
index c52290197292a1a958d05dcd3896587055542b8b..5509354c7c8946e27f4f84edfa1fee80e42c8cee 100644 (file)
@@ -31,6 +31,7 @@
 #include "drmP.h"
 #include "radeon_drm.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "radeon_mode.h"
 #include "r600d.h"
 #include "atom.h"
@@ -491,9 +492,9 @@ void r600_pcie_gart_disable(struct radeon_device *rdev)
 
 void r600_pcie_gart_fini(struct radeon_device *rdev)
 {
+       radeon_gart_fini(rdev);
        r600_pcie_gart_disable(rdev);
        radeon_gart_table_vram_free(rdev);
-       radeon_gart_fini(rdev);
 }
 
 void r600_agp_enable(struct radeon_device *rdev)
@@ -675,7 +676,6 @@ void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
 
 int r600_mc_init(struct radeon_device *rdev)
 {
-       fixed20_12 a;
        u32 tmp;
        int chansize, numchan;
 
@@ -719,14 +719,10 @@ int r600_mc_init(struct radeon_device *rdev)
                rdev->mc.real_vram_size = rdev->mc.aper_size;
        }
        r600_vram_gtt_location(rdev, &rdev->mc);
-       /* FIXME: we should enforce default clock in case GPU is not in
-        * default setup
-        */
-       a.full = rfixed_const(100);
-       rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
-       rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+
        if (rdev->flags & RADEON_IS_IGP)
                rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+       radeon_update_bandwidth_info(rdev);
        return 0;
 }
 
@@ -1132,6 +1128,7 @@ void r600_gpu_init(struct radeon_device *rdev)
        /* Setup pipes */
        WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable);
        WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
+       WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
 
        tmp = R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8);
        WREG32(VGT_OUT_DEALLOC_CNTL, (tmp * 4) & DEALLOC_DIST_MASK);
@@ -2119,6 +2116,7 @@ int r600_init(struct radeon_device *rdev)
 
 void r600_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_audio_fini(rdev);
        r600_blit_fini(rdev);
        r600_cp_fini(rdev);
@@ -2398,19 +2396,19 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev)
                WREG32(DC_HPD4_INT_CONTROL, tmp);
                if (ASIC_IS_DCE32(rdev)) {
                        tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-                       WREG32(DC_HPD5_INT_CONTROL, 0);
+                       WREG32(DC_HPD5_INT_CONTROL, tmp);
                        tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-                       WREG32(DC_HPD6_INT_CONTROL, 0);
+                       WREG32(DC_HPD6_INT_CONTROL, tmp);
                }
        } else {
                WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
                WREG32(DACB_AUTODETECT_INT_CONTROL, 0);
                tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
-               WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, 0);
+               WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
                tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
-               WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, 0);
+               WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
                tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
-               WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, 0);
+               WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp);
        }
 }
 
@@ -2765,6 +2763,7 @@ restart_ih:
                        case 0: /* D1 vblank */
                                if (disp_int & LB_D1_VBLANK_INTERRUPT) {
                                        drm_handle_vblank(rdev->ddev, 0);
+                                       rdev->pm.vblank_sync = true;
                                        wake_up(&rdev->irq.vblank_queue);
                                        disp_int &= ~LB_D1_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D1 vblank\n");
@@ -2786,6 +2785,7 @@ restart_ih:
                        case 0: /* D2 vblank */
                                if (disp_int & LB_D2_VBLANK_INTERRUPT) {
                                        drm_handle_vblank(rdev->ddev, 1);
+                                       rdev->pm.vblank_sync = true;
                                        wake_up(&rdev->irq.vblank_queue);
                                        disp_int &= ~LB_D2_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D2 vblank\n");
@@ -2834,14 +2834,14 @@ restart_ih:
                                break;
                        case 10:
                                if (disp_int_cont2 & DC_HPD5_INTERRUPT) {
-                                       disp_int_cont &= ~DC_HPD5_INTERRUPT;
+                                       disp_int_cont2 &= ~DC_HPD5_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD5\n");
                                }
                                break;
                        case 12:
                                if (disp_int_cont2 & DC_HPD6_INTERRUPT) {
-                                       disp_int_cont &= ~DC_HPD6_INTERRUPT;
+                                       disp_int_cont2 &= ~DC_HPD6_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD6\n");
                                }
index db928016d034cc1e5fce5eba0718cc1a45dc3c0a..dac7042b797e031b47a049f1a09a6be853bfec02 100644 (file)
@@ -181,41 +181,6 @@ int r600_audio_init(struct radeon_device *rdev)
        return 0;
 }
 
-/*
- * determin how the encoders and audio interface is wired together
- */
-int r600_audio_tmds_index(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct drm_encoder *other;
-
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-               return 0;
-
-       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-               /* special case check if an TMDS1 is present */
-               list_for_each_entry(other, &dev->mode_config.encoder_list, head) {
-                       if (to_radeon_encoder(other)->encoder_id ==
-                               ENCODER_OBJECT_ID_INTERNAL_TMDS1)
-                               return 1;
-               }
-               return 0;
-
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               return 1;
-
-       default:
-               DRM_ERROR("Unsupported encoder type 0x%02X\n",
-                         radeon_encoder->encoder_id);
-               return -1;
-       }
-}
-
 /*
  * atach the audio codec to the clock source of the encoder
  */
@@ -224,6 +189,7 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock)
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        int base_rate = 48000;
 
        switch (radeon_encoder->encoder_id) {
@@ -231,32 +197,34 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock)
        case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
                WREG32_P(R600_AUDIO_TIMING, 0, ~0x301);
                break;
-
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
                WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301);
                break;
-
        default:
                DRM_ERROR("Unsupported encoder type 0x%02X\n",
                          radeon_encoder->encoder_id);
                return;
        }
 
-       switch (r600_audio_tmds_index(encoder)) {
+       switch (dig->dig_encoder) {
        case 0:
-               WREG32(R600_AUDIO_PLL1_MUL, base_rate*50);
-               WREG32(R600_AUDIO_PLL1_DIV, clock*100);
+               WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50);
+               WREG32(R600_AUDIO_PLL1_DIV, clock * 100);
                WREG32(R600_AUDIO_CLK_SRCSEL, 0);
                break;
 
        case 1:
-               WREG32(R600_AUDIO_PLL2_MUL, base_rate*50);
-               WREG32(R600_AUDIO_PLL2_DIV, clock*100);
+               WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50);
+               WREG32(R600_AUDIO_PLL2_DIV, clock * 100);
                WREG32(R600_AUDIO_CLK_SRCSEL, 1);
                break;
+       default:
+               dev_err(rdev->dev, "Unsupported DIG on encoder 0x%02X\n",
+                         radeon_encoder->encoder_id);
+               return;
        }
 }
 
index a112c59f9d824988a8f0a399380c4041eace903d..0271b53fa2ddb0b49f7c99539287827d38197fb7 100644 (file)
@@ -1,7 +1,42 @@
+/*
+ * Copyright 2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     Alex Deucher <alexander.deucher@amd.com>
+ */
 
 #include <linux/types.h>
 #include <linux/kernel.h>
 
+/*
+ * R6xx+ cards need to use the 3D engine to blit data which requires
+ * quite a bit of hw state setup.  Rather than pull the whole 3D driver
+ * (which normally generates the 3D state) into the DRM, we opt to use
+ * statically generated state tables.  The regsiter state and shaders
+ * were hand generated to support blitting functionality.  See the 3D
+ * driver or documentation for descriptions of the registers and
+ * shader instructions.
+ */
+
 const u32 r6xx_default_state[] =
 {
        0xc0002400,
index 40416c068d9f431491f85acba93462839700d22b..68e6f434930908a8ed4c1a48f702b904206f5c64 100644 (file)
@@ -1548,10 +1548,13 @@ static void r700_gfx_init(struct drm_device *dev,
 
        RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
        RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
+       RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
 
        RADEON_WRITE(R700_CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
        RADEON_WRITE(R700_CGTS_SYS_TCC_DISABLE, 0);
        RADEON_WRITE(R700_CGTS_TCC_DISABLE, 0);
+       RADEON_WRITE(R700_CGTS_USER_SYS_TCC_DISABLE, 0);
+       RADEON_WRITE(R700_CGTS_USER_TCC_DISABLE, 0);
 
        num_qd_pipes =
                R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8);
index cd2c63bce50172f6136dbeb64abfe69254e2d122..c39c1bc13016075f2bd7151937b3faadc2bf0143 100644 (file)
@@ -45,6 +45,7 @@ struct r600_cs_track {
        u32                     nbanks;
        u32                     npipes;
        /* value we track */
+       u32                     sq_config;
        u32                     nsamples;
        u32                     cb_color_base_last[8];
        struct radeon_bo        *cb_color_bo[8];
@@ -141,6 +142,8 @@ static void r600_cs_track_init(struct r600_cs_track *track)
 {
        int i;
 
+       /* assume DX9 mode */
+       track->sq_config = DX9_CONSTS;
        for (i = 0; i < 8; i++) {
                track->cb_color_base_last[i] = 0;
                track->cb_color_size[i] = 0;
@@ -715,6 +718,9 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
                tmp =radeon_get_ib_value(p, idx);
                ib[idx] = 0;
                break;
+       case SQ_CONFIG:
+               track->sq_config = radeon_get_ib_value(p, idx);
+               break;
        case R_028800_DB_DEPTH_CONTROL:
                track->db_depth_control = radeon_get_ib_value(p, idx);
                break;
@@ -869,6 +875,54 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
        case SQ_PGM_START_VS:
        case SQ_PGM_START_GS:
        case SQ_PGM_START_PS:
+       case SQ_ALU_CONST_CACHE_GS_0:
+       case SQ_ALU_CONST_CACHE_GS_1:
+       case SQ_ALU_CONST_CACHE_GS_2:
+       case SQ_ALU_CONST_CACHE_GS_3:
+       case SQ_ALU_CONST_CACHE_GS_4:
+       case SQ_ALU_CONST_CACHE_GS_5:
+       case SQ_ALU_CONST_CACHE_GS_6:
+       case SQ_ALU_CONST_CACHE_GS_7:
+       case SQ_ALU_CONST_CACHE_GS_8:
+       case SQ_ALU_CONST_CACHE_GS_9:
+       case SQ_ALU_CONST_CACHE_GS_10:
+       case SQ_ALU_CONST_CACHE_GS_11:
+       case SQ_ALU_CONST_CACHE_GS_12:
+       case SQ_ALU_CONST_CACHE_GS_13:
+       case SQ_ALU_CONST_CACHE_GS_14:
+       case SQ_ALU_CONST_CACHE_GS_15:
+       case SQ_ALU_CONST_CACHE_PS_0:
+       case SQ_ALU_CONST_CACHE_PS_1:
+       case SQ_ALU_CONST_CACHE_PS_2:
+       case SQ_ALU_CONST_CACHE_PS_3:
+       case SQ_ALU_CONST_CACHE_PS_4:
+       case SQ_ALU_CONST_CACHE_PS_5:
+       case SQ_ALU_CONST_CACHE_PS_6:
+       case SQ_ALU_CONST_CACHE_PS_7:
+       case SQ_ALU_CONST_CACHE_PS_8:
+       case SQ_ALU_CONST_CACHE_PS_9:
+       case SQ_ALU_CONST_CACHE_PS_10:
+       case SQ_ALU_CONST_CACHE_PS_11:
+       case SQ_ALU_CONST_CACHE_PS_12:
+       case SQ_ALU_CONST_CACHE_PS_13:
+       case SQ_ALU_CONST_CACHE_PS_14:
+       case SQ_ALU_CONST_CACHE_PS_15:
+       case SQ_ALU_CONST_CACHE_VS_0:
+       case SQ_ALU_CONST_CACHE_VS_1:
+       case SQ_ALU_CONST_CACHE_VS_2:
+       case SQ_ALU_CONST_CACHE_VS_3:
+       case SQ_ALU_CONST_CACHE_VS_4:
+       case SQ_ALU_CONST_CACHE_VS_5:
+       case SQ_ALU_CONST_CACHE_VS_6:
+       case SQ_ALU_CONST_CACHE_VS_7:
+       case SQ_ALU_CONST_CACHE_VS_8:
+       case SQ_ALU_CONST_CACHE_VS_9:
+       case SQ_ALU_CONST_CACHE_VS_10:
+       case SQ_ALU_CONST_CACHE_VS_11:
+       case SQ_ALU_CONST_CACHE_VS_12:
+       case SQ_ALU_CONST_CACHE_VS_13:
+       case SQ_ALU_CONST_CACHE_VS_14:
+       case SQ_ALU_CONST_CACHE_VS_15:
                r = r600_cs_packet_next_reloc(p, &reloc);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
@@ -1226,13 +1280,15 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                }
                break;
        case PACKET3_SET_ALU_CONST:
-               start_reg = (idx_value << 2) + PACKET3_SET_ALU_CONST_OFFSET;
-               end_reg = 4 * pkt->count + start_reg - 4;
-               if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) ||
-                   (start_reg >= PACKET3_SET_ALU_CONST_END) ||
-                   (end_reg >= PACKET3_SET_ALU_CONST_END)) {
-                       DRM_ERROR("bad SET_ALU_CONST\n");
-                       return -EINVAL;
+               if (track->sq_config & DX9_CONSTS) {
+                       start_reg = (idx_value << 2) + PACKET3_SET_ALU_CONST_OFFSET;
+                       end_reg = 4 * pkt->count + start_reg - 4;
+                       if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) ||
+                           (start_reg >= PACKET3_SET_ALU_CONST_END) ||
+                           (end_reg >= PACKET3_SET_ALU_CONST_END)) {
+                               DRM_ERROR("bad SET_ALU_CONST\n");
+                               return -EINVAL;
+                       }
                }
                break;
        case PACKET3_SET_BOOL_CONST:
index fcc949df0e5d26ac8b3271b24549e88d6524a39b..029fa1406d1d43b3a8a99708fa117d324be5adb8 100644 (file)
@@ -42,13 +42,13 @@ enum r600_hdmi_color_format {
  */
 enum r600_hdmi_iec_status_bits {
        AUDIO_STATUS_DIG_ENABLE   = 0x01,
-       AUDIO_STATUS_V      = 0x02,
-       AUDIO_STATUS_VCFG        = 0x04,
+       AUDIO_STATUS_V            = 0x02,
+       AUDIO_STATUS_VCFG         = 0x04,
        AUDIO_STATUS_EMPHASIS     = 0x08,
        AUDIO_STATUS_COPYRIGHT    = 0x10,
        AUDIO_STATUS_NONAUDIO     = 0x20,
        AUDIO_STATUS_PROFESSIONAL = 0x40,
-       AUDIO_STATUS_LEVEL      = 0x80
+       AUDIO_STATUS_LEVEL        = 0x80
 };
 
 struct {
@@ -85,7 +85,7 @@ struct {
 static void r600_hdmi_calc_CTS(uint32_t clock, int *CTS, int N, int freq)
 {
        if (*CTS == 0)
-               *CTS = clock*N/(128*freq)*1000;
+               *CTS = clock * N / (128 * freq) * 1000;
        DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n",
                  N, *CTS, freq);
 }
@@ -131,11 +131,11 @@ static void r600_hdmi_infoframe_checksum(uint8_t packetType,
                                         uint8_t length,
                                         uint8_t *frame)
 {
-    int i;
-    frame[0] = packetType + versionNumber + length;
-    for (i = 1; i <= length; i++)
-       frame[0] += frame[i];
-    frame[0] = 0x100 - frame[0];
+       int i;
+       frame[0] = packetType + versionNumber + length;
+       for (i = 1; i <= length; i++)
+               frame[0] += frame[i];
+       frame[0] = 0x100 - frame[0];
 }
 
 /*
@@ -417,90 +417,141 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
        WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000);
 }
 
-/*
- * enable/disable the HDMI engine
- */
-void r600_hdmi_enable(struct drm_encoder *encoder, int enable)
+static int r600_hdmi_find_free_block(struct drm_device *dev)
+{
+       struct radeon_device *rdev = dev->dev_private;
+       struct drm_encoder *encoder;
+       struct radeon_encoder *radeon_encoder;
+       bool free_blocks[3] = { true, true, true };
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               radeon_encoder = to_radeon_encoder(encoder);
+               switch (radeon_encoder->hdmi_offset) {
+               case R600_HDMI_BLOCK1:
+                       free_blocks[0] = false;
+                       break;
+               case R600_HDMI_BLOCK2:
+                       free_blocks[1] = false;
+                       break;
+               case R600_HDMI_BLOCK3:
+                       free_blocks[2] = false;
+                       break;
+               }
+       }
+
+       if (rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690) {
+               return free_blocks[0] ? R600_HDMI_BLOCK1 : 0;
+       } else if (rdev->family >= CHIP_R600) {
+               if (free_blocks[0])
+                       return R600_HDMI_BLOCK1;
+               else if (free_blocks[1])
+                       return R600_HDMI_BLOCK2;
+       }
+       return 0;
+}
+
+static void r600_hdmi_assign_block(struct drm_encoder *encoder)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 
-       if (!offset)
+       if (!dig) {
+               dev_err(rdev->dev, "Enabling HDMI on non-dig encoder\n");
                return;
+       }
 
-       DRM_DEBUG("%s HDMI interface @ 0x%04X\n", enable ? "Enabling" : "Disabling", offset);
-
-       /* some version of atombios ignore the enable HDMI flag
-        * so enabling/disabling HDMI was moved here for TMDS1+2 */
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-               WREG32_P(AVIVO_TMDSA_CNTL, enable ? 0x4 : 0x0, ~0x4);
-               WREG32(offset+R600_HDMI_ENABLE, enable ? 0x101 : 0x0);
-               break;
-
-       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-               WREG32_P(AVIVO_LVTMA_CNTL, enable ? 0x4 : 0x0, ~0x4);
-               WREG32(offset+R600_HDMI_ENABLE, enable ? 0x105 : 0x0);
-               break;
-
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               /* This part is doubtfull in my opinion */
-               WREG32(offset+R600_HDMI_ENABLE, enable ? 0x110 : 0x0);
-               break;
-
-       default:
-               DRM_ERROR("unknown HDMI output type\n");
-               break;
+       if (ASIC_IS_DCE4(rdev)) {
+               /* TODO */
+       } else if (ASIC_IS_DCE3(rdev)) {
+               radeon_encoder->hdmi_offset = dig->dig_encoder ?
+                       R600_HDMI_BLOCK3 : R600_HDMI_BLOCK1;
+               if (ASIC_IS_DCE32(rdev))
+                       radeon_encoder->hdmi_config_offset = dig->dig_encoder ?
+                               R600_HDMI_CONFIG2 : R600_HDMI_CONFIG1;
+       } else if (rdev->family >= CHIP_R600) {
+               radeon_encoder->hdmi_offset = r600_hdmi_find_free_block(dev);
        }
 }
 
 /*
- * determin at which register offset the HDMI encoder is
+ * enable the HDMI engine
  */
-void r600_hdmi_init(struct drm_encoder *encoder)
+void r600_hdmi_enable(struct drm_encoder *encoder)
 {
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-               radeon_encoder->hdmi_offset = R600_HDMI_TMDS1;
-               break;
-
-       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-               switch (r600_audio_tmds_index(encoder)) {
-               case 0:
-                       radeon_encoder->hdmi_offset = R600_HDMI_TMDS1;
+       if (!radeon_encoder->hdmi_offset) {
+               r600_hdmi_assign_block(encoder);
+               if (!radeon_encoder->hdmi_offset) {
+                       dev_warn(rdev->dev, "Could not find HDMI block for "
+                               "0x%x encoder\n", radeon_encoder->encoder_id);
+                       return;
+               }
+       }
+
+       if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) {
+               WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1);
+       } else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
+               int offset = radeon_encoder->hdmi_offset;
+               switch (radeon_encoder->encoder_id) {
+               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+                       WREG32_P(AVIVO_TMDSA_CNTL, 0x4, ~0x4);
+                       WREG32(offset + R600_HDMI_ENABLE, 0x101);
                        break;
-               case 1:
-                       radeon_encoder->hdmi_offset = R600_HDMI_TMDS2;
+               case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+                       WREG32_P(AVIVO_LVTMA_CNTL, 0x4, ~0x4);
+                       WREG32(offset + R600_HDMI_ENABLE, 0x105);
                        break;
                default:
-                       radeon_encoder->hdmi_offset = 0;
+                       dev_err(rdev->dev, "Unknown HDMI output type\n");
                        break;
                }
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-               radeon_encoder->hdmi_offset = R600_HDMI_TMDS2;
-               break;
+       }
 
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               radeon_encoder->hdmi_offset = R600_HDMI_DIG;
-               break;
+       DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
+               radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
+}
 
-       default:
-               radeon_encoder->hdmi_offset = 0;
-               break;
+/*
+ * disable the HDMI engine
+ */
+void r600_hdmi_disable(struct drm_encoder *encoder)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+       if (!radeon_encoder->hdmi_offset) {
+               dev_err(rdev->dev, "Disabling not enabled HDMI\n");
+               return;
        }
 
-       DRM_DEBUG("using HDMI engine at offset 0x%04X for encoder 0x%x\n",
-                 radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
+       DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n",
+               radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
+
+       if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) {
+               WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1);
+       } else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
+               int offset = radeon_encoder->hdmi_offset;
+               switch (radeon_encoder->encoder_id) {
+               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+                       WREG32_P(AVIVO_TMDSA_CNTL, 0, ~0x4);
+                       WREG32(offset + R600_HDMI_ENABLE, 0);
+                       break;
+               case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+                       WREG32_P(AVIVO_LVTMA_CNTL, 0, ~0x4);
+                       WREG32(offset + R600_HDMI_ENABLE, 0);
+                       break;
+               default:
+                       dev_err(rdev->dev, "Unknown HDMI output type\n");
+                       break;
+               }
+       }
 
-       /* TODO: make this configureable */
-       radeon_encoder->hdmi_audio_workaround = 0;
+       radeon_encoder->hdmi_offset = 0;
+       radeon_encoder->hdmi_config_offset = 0;
 }
index d0e28ffdeda9400564ce40cea7a22e7fca2533f5..7b1d22370f6e2bc2fb78521b3a8e61aa49e8d44f 100644 (file)
 #define R600_AUDIO_STATUS_BITS            0x73d8
 
 /* HDMI base register addresses */
-#define R600_HDMI_TMDS1                   0x7400
-#define R600_HDMI_TMDS2                   0x7700
-#define R600_HDMI_DIG                     0x7800
+#define R600_HDMI_BLOCK1                  0x7400
+#define R600_HDMI_BLOCK2                  0x7700
+#define R600_HDMI_BLOCK3                  0x7800
 
 /* HDMI registers */
 #define R600_HDMI_ENABLE           0x00
 #define R600_HDMI_AUDIO_DEBUG_2    0xe8
 #define R600_HDMI_AUDIO_DEBUG_3    0xec
 
+/* HDMI additional config base register addresses */
+#define R600_HDMI_CONFIG1                 0x7600
+#define R600_HDMI_CONFIG2                 0x7a00
+
 #endif
index 5b2e4d44282394ba85598c2ae6a91bd7ffc42b79..59c1f8793e608df971466a9545ccc32c81e529fd 100644 (file)
 #define CB_COLOR0_FRAG                                  0x280e0
 #define CB_COLOR0_MASK                                  0x28100
 
+#define SQ_ALU_CONST_CACHE_PS_0                                0x28940
+#define SQ_ALU_CONST_CACHE_PS_1                                0x28944
+#define SQ_ALU_CONST_CACHE_PS_2                                0x28948
+#define SQ_ALU_CONST_CACHE_PS_3                                0x2894c
+#define SQ_ALU_CONST_CACHE_PS_4                                0x28950
+#define SQ_ALU_CONST_CACHE_PS_5                                0x28954
+#define SQ_ALU_CONST_CACHE_PS_6                                0x28958
+#define SQ_ALU_CONST_CACHE_PS_7                                0x2895c
+#define SQ_ALU_CONST_CACHE_PS_8                                0x28960
+#define SQ_ALU_CONST_CACHE_PS_9                                0x28964
+#define SQ_ALU_CONST_CACHE_PS_10                       0x28968
+#define SQ_ALU_CONST_CACHE_PS_11                       0x2896c
+#define SQ_ALU_CONST_CACHE_PS_12                       0x28970
+#define SQ_ALU_CONST_CACHE_PS_13                       0x28974
+#define SQ_ALU_CONST_CACHE_PS_14                       0x28978
+#define SQ_ALU_CONST_CACHE_PS_15                       0x2897c
+#define SQ_ALU_CONST_CACHE_VS_0                                0x28980
+#define SQ_ALU_CONST_CACHE_VS_1                                0x28984
+#define SQ_ALU_CONST_CACHE_VS_2                                0x28988
+#define SQ_ALU_CONST_CACHE_VS_3                                0x2898c
+#define SQ_ALU_CONST_CACHE_VS_4                                0x28990
+#define SQ_ALU_CONST_CACHE_VS_5                                0x28994
+#define SQ_ALU_CONST_CACHE_VS_6                                0x28998
+#define SQ_ALU_CONST_CACHE_VS_7                                0x2899c
+#define SQ_ALU_CONST_CACHE_VS_8                                0x289a0
+#define SQ_ALU_CONST_CACHE_VS_9                                0x289a4
+#define SQ_ALU_CONST_CACHE_VS_10                       0x289a8
+#define SQ_ALU_CONST_CACHE_VS_11                       0x289ac
+#define SQ_ALU_CONST_CACHE_VS_12                       0x289b0
+#define SQ_ALU_CONST_CACHE_VS_13                       0x289b4
+#define SQ_ALU_CONST_CACHE_VS_14                       0x289b8
+#define SQ_ALU_CONST_CACHE_VS_15                       0x289bc
+#define SQ_ALU_CONST_CACHE_GS_0                                0x289c0
+#define SQ_ALU_CONST_CACHE_GS_1                                0x289c4
+#define SQ_ALU_CONST_CACHE_GS_2                                0x289c8
+#define SQ_ALU_CONST_CACHE_GS_3                                0x289cc
+#define SQ_ALU_CONST_CACHE_GS_4                                0x289d0
+#define SQ_ALU_CONST_CACHE_GS_5                                0x289d4
+#define SQ_ALU_CONST_CACHE_GS_6                                0x289d8
+#define SQ_ALU_CONST_CACHE_GS_7                                0x289dc
+#define SQ_ALU_CONST_CACHE_GS_8                                0x289e0
+#define SQ_ALU_CONST_CACHE_GS_9                                0x289e4
+#define SQ_ALU_CONST_CACHE_GS_10                       0x289e8
+#define SQ_ALU_CONST_CACHE_GS_11                       0x289ec
+#define SQ_ALU_CONST_CACHE_GS_12                       0x289f0
+#define SQ_ALU_CONST_CACHE_GS_13                       0x289f4
+#define SQ_ALU_CONST_CACHE_GS_14                       0x289f8
+#define SQ_ALU_CONST_CACHE_GS_15                       0x289fc
+
 #define        CONFIG_MEMSIZE                                  0x5428
 #define CONFIG_CNTL                                    0x5424
 #define        CP_STAT                                         0x8680
index 829e26e8a4bb877f43dc2b8f12646e5d840753cb..034218c3dbbbb11d8248606074debc81fe42df8b 100644 (file)
@@ -91,6 +91,8 @@ extern int radeon_tv;
 extern int radeon_new_pll;
 extern int radeon_dynpm;
 extern int radeon_audio;
+extern int radeon_disp_priority;
+extern int radeon_hw_i2c;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -168,6 +170,7 @@ struct radeon_clock {
  * Power management
  */
 int radeon_pm_init(struct radeon_device *rdev);
+void radeon_pm_fini(struct radeon_device *rdev);
 void radeon_pm_compute_clocks(struct radeon_device *rdev);
 void radeon_combios_get_power_modes(struct radeon_device *rdev);
 void radeon_atombios_get_power_modes(struct radeon_device *rdev);
@@ -687,6 +690,7 @@ struct radeon_pm {
        bool                    downclocked;
        int                     active_crtcs;
        int                     req_vblank;
+       bool                    vblank_sync;
        fixed20_12              max_bandwidth;
        fixed20_12              igp_sideport_mclk;
        fixed20_12              igp_system_mclk;
@@ -697,6 +701,7 @@ struct radeon_pm {
        fixed20_12              ht_bandwidth;
        fixed20_12              core_bandwidth;
        fixed20_12              sclk;
+       fixed20_12              mclk;
        fixed20_12              needed_bandwidth;
        /* XXX: use a define for num power modes */
        struct radeon_power_state power_state[8];
@@ -707,6 +712,7 @@ struct radeon_pm {
        struct radeon_power_state *requested_power_state;
        struct radeon_pm_clock_info *requested_clock_mode;
        struct radeon_power_state *default_power_state;
+       struct radeon_i2c_chan *i2c_bus;
 };
 
 
@@ -729,8 +735,6 @@ int radeon_debugfs_add_files(struct radeon_device *rdev,
                             struct drm_info_list *files,
                             unsigned nfiles);
 int radeon_debugfs_fence_init(struct radeon_device *rdev);
-int r100_debugfs_rbbm_init(struct radeon_device *rdev);
-int r100_debugfs_cp_init(struct radeon_device *rdev);
 
 
 /*
@@ -782,7 +786,7 @@ struct radeon_asic {
        int (*set_surface_reg)(struct radeon_device *rdev, int reg,
                               uint32_t tiling_flags, uint32_t pitch,
                               uint32_t offset, uint32_t obj_size);
-       int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
+       void (*clear_surface_reg)(struct radeon_device *rdev, int reg);
        void (*bandwidth_update)(struct radeon_device *rdev);
        void (*hpd_init)(struct radeon_device *rdev);
        void (*hpd_fini)(struct radeon_device *rdev);
@@ -862,6 +866,12 @@ union radeon_asic_config {
        struct rv770_asic       rv770;
 };
 
+/*
+ * asic initizalization from radeon_asic.c
+ */
+void radeon_agp_disable(struct radeon_device *rdev);
+int radeon_asic_init(struct radeon_device *rdev);
+
 
 /*
  * IOCTL.
@@ -1172,6 +1182,8 @@ extern void radeon_gart_restore(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
 extern void radeon_modeset_fini(struct radeon_device *rdev);
 extern bool radeon_card_posted(struct radeon_device *rdev);
+extern void radeon_update_bandwidth_info(struct radeon_device *rdev);
+extern void radeon_update_display_priority(struct radeon_device *rdev);
 extern bool radeon_boot_test_post_card(struct radeon_device *rdev);
 extern int radeon_clocks_init(struct radeon_device *rdev);
 extern void radeon_clocks_fini(struct radeon_device *rdev);
@@ -1188,51 +1200,6 @@ extern int radeon_resume_kms(struct drm_device *dev);
 extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state);
 
 /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
-struct r100_mc_save {
-       u32     GENMO_WT;
-       u32     CRTC_EXT_CNTL;
-       u32     CRTC_GEN_CNTL;
-       u32     CRTC2_GEN_CNTL;
-       u32     CUR_OFFSET;
-       u32     CUR2_OFFSET;
-};
-extern void r100_cp_disable(struct radeon_device *rdev);
-extern int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
-extern void r100_cp_fini(struct radeon_device *rdev);
-extern void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
-extern int r100_pci_gart_init(struct radeon_device *rdev);
-extern void r100_pci_gart_fini(struct radeon_device *rdev);
-extern int r100_pci_gart_enable(struct radeon_device *rdev);
-extern void r100_pci_gart_disable(struct radeon_device *rdev);
-extern int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
-extern int r100_debugfs_mc_info_init(struct radeon_device *rdev);
-extern int r100_gui_wait_for_idle(struct radeon_device *rdev);
-extern void r100_ib_fini(struct radeon_device *rdev);
-extern int r100_ib_init(struct radeon_device *rdev);
-extern void r100_irq_disable(struct radeon_device *rdev);
-extern int r100_irq_set(struct radeon_device *rdev);
-extern void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save);
-extern void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save);
-extern void r100_vram_init_sizes(struct radeon_device *rdev);
-extern void r100_wb_disable(struct radeon_device *rdev);
-extern void r100_wb_fini(struct radeon_device *rdev);
-extern int r100_wb_init(struct radeon_device *rdev);
-extern void r100_hdp_reset(struct radeon_device *rdev);
-extern int r100_rb2d_reset(struct radeon_device *rdev);
-extern int r100_cp_reset(struct radeon_device *rdev);
-extern void r100_vga_render_disable(struct radeon_device *rdev);
-extern int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
-                                               struct radeon_cs_packet *pkt,
-                                               struct radeon_bo *robj);
-extern int r100_cs_parse_packet0(struct radeon_cs_parser *p,
-                               struct radeon_cs_packet *pkt,
-                               const unsigned *auth, unsigned n,
-                               radeon_packet0_check_t check);
-extern int r100_cs_packet_parse(struct radeon_cs_parser *p,
-                               struct radeon_cs_packet *pkt,
-                               unsigned idx);
-extern void r100_enable_bm(struct radeon_device *rdev);
-extern void r100_set_common_regs(struct radeon_device *rdev);
 
 /* rv200,rv250,rv280 */
 extern void r200_set_safe_registers(struct radeon_device *rdev);
@@ -1322,7 +1289,8 @@ extern int r600_audio_tmds_index(struct drm_encoder *encoder);
 extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
 extern void r600_audio_fini(struct radeon_device *rdev);
 extern void r600_hdmi_init(struct drm_encoder *encoder);
-extern void r600_hdmi_enable(struct drm_encoder *encoder, int enable);
+extern void r600_hdmi_enable(struct drm_encoder *encoder);
+extern void r600_hdmi_disable(struct drm_encoder *encoder);
 extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
 extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
 extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
new file mode 100644 (file)
index 0000000..a4b4bc9
--- /dev/null
@@ -0,0 +1,772 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+
+#include <linux/console.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/radeon_drm.h>
+#include <linux/vgaarb.h>
+#include <linux/vga_switcheroo.h>
+#include "radeon_reg.h"
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "atom.h"
+
+/*
+ * Registers accessors functions.
+ */
+static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+       DRM_ERROR("Invalid callback to read register 0x%04X\n", reg);
+       BUG_ON(1);
+       return 0;
+}
+
+static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+       DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n",
+                 reg, v);
+       BUG_ON(1);
+}
+
+static void radeon_register_accessor_init(struct radeon_device *rdev)
+{
+       rdev->mc_rreg = &radeon_invalid_rreg;
+       rdev->mc_wreg = &radeon_invalid_wreg;
+       rdev->pll_rreg = &radeon_invalid_rreg;
+       rdev->pll_wreg = &radeon_invalid_wreg;
+       rdev->pciep_rreg = &radeon_invalid_rreg;
+       rdev->pciep_wreg = &radeon_invalid_wreg;
+
+       /* Don't change order as we are overridding accessor. */
+       if (rdev->family < CHIP_RV515) {
+               rdev->pcie_reg_mask = 0xff;
+       } else {
+               rdev->pcie_reg_mask = 0x7ff;
+       }
+       /* FIXME: not sure here */
+       if (rdev->family <= CHIP_R580) {
+               rdev->pll_rreg = &r100_pll_rreg;
+               rdev->pll_wreg = &r100_pll_wreg;
+       }
+       if (rdev->family >= CHIP_R420) {
+               rdev->mc_rreg = &r420_mc_rreg;
+               rdev->mc_wreg = &r420_mc_wreg;
+       }
+       if (rdev->family >= CHIP_RV515) {
+               rdev->mc_rreg = &rv515_mc_rreg;
+               rdev->mc_wreg = &rv515_mc_wreg;
+       }
+       if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) {
+               rdev->mc_rreg = &rs400_mc_rreg;
+               rdev->mc_wreg = &rs400_mc_wreg;
+       }
+       if (rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
+               rdev->mc_rreg = &rs690_mc_rreg;
+               rdev->mc_wreg = &rs690_mc_wreg;
+       }
+       if (rdev->family == CHIP_RS600) {
+               rdev->mc_rreg = &rs600_mc_rreg;
+               rdev->mc_wreg = &rs600_mc_wreg;
+       }
+       if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_RV740)) {
+               rdev->pciep_rreg = &r600_pciep_rreg;
+               rdev->pciep_wreg = &r600_pciep_wreg;
+       }
+}
+
+
+/* helper to disable agp */
+void radeon_agp_disable(struct radeon_device *rdev)
+{
+       rdev->flags &= ~RADEON_IS_AGP;
+       if (rdev->family >= CHIP_R600) {
+               DRM_INFO("Forcing AGP to PCIE mode\n");
+               rdev->flags |= RADEON_IS_PCIE;
+       } else if (rdev->family >= CHIP_RV515 ||
+                       rdev->family == CHIP_RV380 ||
+                       rdev->family == CHIP_RV410 ||
+                       rdev->family == CHIP_R423) {
+               DRM_INFO("Forcing AGP to PCIE mode\n");
+               rdev->flags |= RADEON_IS_PCIE;
+               rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
+               rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
+       } else {
+               DRM_INFO("Forcing AGP to PCI mode\n");
+               rdev->flags |= RADEON_IS_PCI;
+               rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
+               rdev->asic->gart_set_page = &r100_pci_gart_set_page;
+       }
+       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+}
+
+/*
+ * ASIC
+ */
+static struct radeon_asic r100_asic = {
+       .init = &r100_init,
+       .fini = &r100_fini,
+       .suspend = &r100_suspend,
+       .resume = &r100_resume,
+       .vga_set_state = &r100_vga_set_state,
+       .gpu_reset = &r100_gpu_reset,
+       .gart_tlb_flush = &r100_pci_gart_tlb_flush,
+       .gart_set_page = &r100_pci_gart_set_page,
+       .cp_commit = &r100_cp_commit,
+       .ring_start = &r100_ring_start,
+       .ring_test = &r100_ring_test,
+       .ring_ib_execute = &r100_ring_ib_execute,
+       .irq_set = &r100_irq_set,
+       .irq_process = &r100_irq_process,
+       .get_vblank_counter = &r100_get_vblank_counter,
+       .fence_ring_emit = &r100_fence_ring_emit,
+       .cs_parse = &r100_cs_parse,
+       .copy_blit = &r100_copy_blit,
+       .copy_dma = NULL,
+       .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_legacy_get_engine_clock,
+       .set_engine_clock = &radeon_legacy_set_engine_clock,
+       .get_memory_clock = &radeon_legacy_get_memory_clock,
+       .set_memory_clock = NULL,
+       .get_pcie_lanes = NULL,
+       .set_pcie_lanes = NULL,
+       .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r100_bandwidth_update,
+       .hpd_init = &r100_hpd_init,
+       .hpd_fini = &r100_hpd_fini,
+       .hpd_sense = &r100_hpd_sense,
+       .hpd_set_polarity = &r100_hpd_set_polarity,
+       .ioctl_wait_idle = NULL,
+};
+
+static struct radeon_asic r200_asic = {
+       .init = &r100_init,
+       .fini = &r100_fini,
+       .suspend = &r100_suspend,
+       .resume = &r100_resume,
+       .vga_set_state = &r100_vga_set_state,
+       .gpu_reset = &r100_gpu_reset,
+       .gart_tlb_flush = &r100_pci_gart_tlb_flush,
+       .gart_set_page = &r100_pci_gart_set_page,
+       .cp_commit = &r100_cp_commit,
+       .ring_start = &r100_ring_start,
+       .ring_test = &r100_ring_test,
+       .ring_ib_execute = &r100_ring_ib_execute,
+       .irq_set = &r100_irq_set,
+       .irq_process = &r100_irq_process,
+       .get_vblank_counter = &r100_get_vblank_counter,
+       .fence_ring_emit = &r100_fence_ring_emit,
+       .cs_parse = &r100_cs_parse,
+       .copy_blit = &r100_copy_blit,
+       .copy_dma = &r200_copy_dma,
+       .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_legacy_get_engine_clock,
+       .set_engine_clock = &radeon_legacy_set_engine_clock,
+       .get_memory_clock = &radeon_legacy_get_memory_clock,
+       .set_memory_clock = NULL,
+       .set_pcie_lanes = NULL,
+       .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r100_bandwidth_update,
+       .hpd_init = &r100_hpd_init,
+       .hpd_fini = &r100_hpd_fini,
+       .hpd_sense = &r100_hpd_sense,
+       .hpd_set_polarity = &r100_hpd_set_polarity,
+       .ioctl_wait_idle = NULL,
+};
+
+static struct radeon_asic r300_asic = {
+       .init = &r300_init,
+       .fini = &r300_fini,
+       .suspend = &r300_suspend,
+       .resume = &r300_resume,
+       .vga_set_state = &r100_vga_set_state,
+       .gpu_reset = &r300_gpu_reset,
+       .gart_tlb_flush = &r100_pci_gart_tlb_flush,
+       .gart_set_page = &r100_pci_gart_set_page,
+       .cp_commit = &r100_cp_commit,
+       .ring_start = &r300_ring_start,
+       .ring_test = &r100_ring_test,
+       .ring_ib_execute = &r100_ring_ib_execute,
+       .irq_set = &r100_irq_set,
+       .irq_process = &r100_irq_process,
+       .get_vblank_counter = &r100_get_vblank_counter,
+       .fence_ring_emit = &r300_fence_ring_emit,
+       .cs_parse = &r300_cs_parse,
+       .copy_blit = &r100_copy_blit,
+       .copy_dma = &r200_copy_dma,
+       .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_legacy_get_engine_clock,
+       .set_engine_clock = &radeon_legacy_set_engine_clock,
+       .get_memory_clock = &radeon_legacy_get_memory_clock,
+       .set_memory_clock = NULL,
+       .get_pcie_lanes = &rv370_get_pcie_lanes,
+       .set_pcie_lanes = &rv370_set_pcie_lanes,
+       .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r100_bandwidth_update,
+       .hpd_init = &r100_hpd_init,
+       .hpd_fini = &r100_hpd_fini,
+       .hpd_sense = &r100_hpd_sense,
+       .hpd_set_polarity = &r100_hpd_set_polarity,
+       .ioctl_wait_idle = NULL,
+};
+
+static struct radeon_asic r300_asic_pcie = {
+       .init = &r300_init,
+       .fini = &r300_fini,
+       .suspend = &r300_suspend,
+       .resume = &r300_resume,
+       .vga_set_state = &r100_vga_set_state,
+       .gpu_reset = &r300_gpu_reset,
+       .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
+       .gart_set_page = &rv370_pcie_gart_set_page,
+       .cp_commit = &r100_cp_commit,
+       .ring_start = &r300_ring_start,
+       .ring_test = &r100_ring_test,
+       .ring_ib_execute = &r100_ring_ib_execute,
+       .irq_set = &r100_irq_set,
+       .irq_process = &r100_irq_process,
+       .get_vblank_counter = &r100_get_vblank_counter,
+       .fence_ring_emit = &r300_fence_ring_emit,
+       .cs_parse = &r300_cs_parse,
+       .copy_blit = &r100_copy_blit,
+       .copy_dma = &r200_copy_dma,
+       .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_legacy_get_engine_clock,
+       .set_engine_clock = &radeon_legacy_set_engine_clock,
+       .get_memory_clock = &radeon_legacy_get_memory_clock,
+       .set_memory_clock = NULL,
+       .set_pcie_lanes = &rv370_set_pcie_lanes,
+       .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r100_bandwidth_update,
+       .hpd_init = &r100_hpd_init,
+       .hpd_fini = &r100_hpd_fini,
+       .hpd_sense = &r100_hpd_sense,
+       .hpd_set_polarity = &r100_hpd_set_polarity,
+       .ioctl_wait_idle = NULL,
+};
+
+static struct radeon_asic r420_asic = {
+       .init = &r420_init,
+       .fini = &r420_fini,
+       .suspend = &r420_suspend,
+       .resume = &r420_resume,
+       .vga_set_state = &r100_vga_set_state,
+       .gpu_reset = &r300_gpu_reset,
+       .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
+       .gart_set_page = &rv370_pcie_gart_set_page,
+       .cp_commit = &r100_cp_commit,
+       .ring_start = &r300_ring_start,
+       .ring_test = &r100_ring_test,
+       .ring_ib_execute = &r100_ring_ib_execute,
+       .irq_set = &r100_irq_set,
+       .irq_process = &r100_irq_process,
+       .get_vblank_counter = &r100_get_vblank_counter,
+       .fence_ring_emit = &r300_fence_ring_emit,
+       .cs_parse = &r300_cs_parse,
+       .copy_blit = &r100_copy_blit,
+       .copy_dma = &r200_copy_dma,
+       .copy = &r100_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,
+       .set_memory_clock = &radeon_atom_set_memory_clock,
+       .get_pcie_lanes = &rv370_get_pcie_lanes,
+       .set_pcie_lanes = &rv370_set_pcie_lanes,
+       .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r100_bandwidth_update,
+       .hpd_init = &r100_hpd_init,
+       .hpd_fini = &r100_hpd_fini,
+       .hpd_sense = &r100_hpd_sense,
+       .hpd_set_polarity = &r100_hpd_set_polarity,
+       .ioctl_wait_idle = NULL,
+};
+
+static struct radeon_asic rs400_asic = {
+       .init = &rs400_init,
+       .fini = &rs400_fini,
+       .suspend = &rs400_suspend,
+       .resume = &rs400_resume,
+       .vga_set_state = &r100_vga_set_state,
+       .gpu_reset = &r300_gpu_reset,
+       .gart_tlb_flush = &rs400_gart_tlb_flush,
+       .gart_set_page = &rs400_gart_set_page,
+       .cp_commit = &r100_cp_commit,
+       .ring_start = &r300_ring_start,
+       .ring_test = &r100_ring_test,
+       .ring_ib_execute = &r100_ring_ib_execute,
+       .irq_set = &r100_irq_set,
+       .irq_process = &r100_irq_process,
+       .get_vblank_counter = &r100_get_vblank_counter,
+       .fence_ring_emit = &r300_fence_ring_emit,
+       .cs_parse = &r300_cs_parse,
+       .copy_blit = &r100_copy_blit,
+       .copy_dma = &r200_copy_dma,
+       .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_legacy_get_engine_clock,
+       .set_engine_clock = &radeon_legacy_set_engine_clock,
+       .get_memory_clock = &radeon_legacy_get_memory_clock,
+       .set_memory_clock = NULL,
+       .get_pcie_lanes = NULL,
+       .set_pcie_lanes = NULL,
+       .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r100_bandwidth_update,
+       .hpd_init = &r100_hpd_init,
+       .hpd_fini = &r100_hpd_fini,
+       .hpd_sense = &r100_hpd_sense,
+       .hpd_set_polarity = &r100_hpd_set_polarity,
+       .ioctl_wait_idle = NULL,
+};
+
+static struct radeon_asic rs600_asic = {
+       .init = &rs600_init,
+       .fini = &rs600_fini,
+       .suspend = &rs600_suspend,
+       .resume = &rs600_resume,
+       .vga_set_state = &r100_vga_set_state,
+       .gpu_reset = &r300_gpu_reset,
+       .gart_tlb_flush = &rs600_gart_tlb_flush,
+       .gart_set_page = &rs600_gart_set_page,
+       .cp_commit = &r100_cp_commit,
+       .ring_start = &r300_ring_start,
+       .ring_test = &r100_ring_test,
+       .ring_ib_execute = &r100_ring_ib_execute,
+       .irq_set = &rs600_irq_set,
+       .irq_process = &rs600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
+       .fence_ring_emit = &r300_fence_ring_emit,
+       .cs_parse = &r300_cs_parse,
+       .copy_blit = &r100_copy_blit,
+       .copy_dma = &r200_copy_dma,
+       .copy = &r100_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,
+       .set_memory_clock = &radeon_atom_set_memory_clock,
+       .get_pcie_lanes = NULL,
+       .set_pcie_lanes = NULL,
+       .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &rs600_bandwidth_update,
+       .hpd_init = &rs600_hpd_init,
+       .hpd_fini = &rs600_hpd_fini,
+       .hpd_sense = &rs600_hpd_sense,
+       .hpd_set_polarity = &rs600_hpd_set_polarity,
+       .ioctl_wait_idle = NULL,
+};
+
+static struct radeon_asic rs690_asic = {
+       .init = &rs690_init,
+       .fini = &rs690_fini,
+       .suspend = &rs690_suspend,
+       .resume = &rs690_resume,
+       .vga_set_state = &r100_vga_set_state,
+       .gpu_reset = &r300_gpu_reset,
+       .gart_tlb_flush = &rs400_gart_tlb_flush,
+       .gart_set_page = &rs400_gart_set_page,
+       .cp_commit = &r100_cp_commit,
+       .ring_start = &r300_ring_start,
+       .ring_test = &r100_ring_test,
+       .ring_ib_execute = &r100_ring_ib_execute,
+       .irq_set = &rs600_irq_set,
+       .irq_process = &rs600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
+       .fence_ring_emit = &r300_fence_ring_emit,
+       .cs_parse = &r300_cs_parse,
+       .copy_blit = &r100_copy_blit,
+       .copy_dma = &r200_copy_dma,
+       .copy = &r200_copy_dma,
+       .get_engine_clock = &radeon_atom_get_engine_clock,
+       .set_engine_clock = &radeon_atom_set_engine_clock,
+       .get_memory_clock = &radeon_atom_get_memory_clock,
+       .set_memory_clock = &radeon_atom_set_memory_clock,
+       .get_pcie_lanes = NULL,
+       .set_pcie_lanes = NULL,
+       .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &rs690_bandwidth_update,
+       .hpd_init = &rs600_hpd_init,
+       .hpd_fini = &rs600_hpd_fini,
+       .hpd_sense = &rs600_hpd_sense,
+       .hpd_set_polarity = &rs600_hpd_set_polarity,
+       .ioctl_wait_idle = NULL,
+};
+
+static struct radeon_asic rv515_asic = {
+       .init = &rv515_init,
+       .fini = &rv515_fini,
+       .suspend = &rv515_suspend,
+       .resume = &rv515_resume,
+       .vga_set_state = &r100_vga_set_state,
+       .gpu_reset = &rv515_gpu_reset,
+       .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
+       .gart_set_page = &rv370_pcie_gart_set_page,
+       .cp_commit = &r100_cp_commit,
+       .ring_start = &rv515_ring_start,
+       .ring_test = &r100_ring_test,
+       .ring_ib_execute = &r100_ring_ib_execute,
+       .irq_set = &rs600_irq_set,
+       .irq_process = &rs600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
+       .fence_ring_emit = &r300_fence_ring_emit,
+       .cs_parse = &r300_cs_parse,
+       .copy_blit = &r100_copy_blit,
+       .copy_dma = &r200_copy_dma,
+       .copy = &r100_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,
+       .set_memory_clock = &radeon_atom_set_memory_clock,
+       .get_pcie_lanes = &rv370_get_pcie_lanes,
+       .set_pcie_lanes = &rv370_set_pcie_lanes,
+       .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &rv515_bandwidth_update,
+       .hpd_init = &rs600_hpd_init,
+       .hpd_fini = &rs600_hpd_fini,
+       .hpd_sense = &rs600_hpd_sense,
+       .hpd_set_polarity = &rs600_hpd_set_polarity,
+       .ioctl_wait_idle = NULL,
+};
+
+static struct radeon_asic r520_asic = {
+       .init = &r520_init,
+       .fini = &rv515_fini,
+       .suspend = &rv515_suspend,
+       .resume = &r520_resume,
+       .vga_set_state = &r100_vga_set_state,
+       .gpu_reset = &rv515_gpu_reset,
+       .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
+       .gart_set_page = &rv370_pcie_gart_set_page,
+       .cp_commit = &r100_cp_commit,
+       .ring_start = &rv515_ring_start,
+       .ring_test = &r100_ring_test,
+       .ring_ib_execute = &r100_ring_ib_execute,
+       .irq_set = &rs600_irq_set,
+       .irq_process = &rs600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
+       .fence_ring_emit = &r300_fence_ring_emit,
+       .cs_parse = &r300_cs_parse,
+       .copy_blit = &r100_copy_blit,
+       .copy_dma = &r200_copy_dma,
+       .copy = &r100_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,
+       .set_memory_clock = &radeon_atom_set_memory_clock,
+       .get_pcie_lanes = &rv370_get_pcie_lanes,
+       .set_pcie_lanes = &rv370_set_pcie_lanes,
+       .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &rv515_bandwidth_update,
+       .hpd_init = &rs600_hpd_init,
+       .hpd_fini = &rs600_hpd_fini,
+       .hpd_sense = &rs600_hpd_sense,
+       .hpd_set_polarity = &rs600_hpd_set_polarity,
+       .ioctl_wait_idle = NULL,
+};
+
+static struct radeon_asic r600_asic = {
+       .init = &r600_init,
+       .fini = &r600_fini,
+       .suspend = &r600_suspend,
+       .resume = &r600_resume,
+       .cp_commit = &r600_cp_commit,
+       .vga_set_state = &r600_vga_set_state,
+       .gpu_reset = &r600_gpu_reset,
+       .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
+       .gart_set_page = &rs600_gart_set_page,
+       .ring_test = &r600_ring_test,
+       .ring_ib_execute = &r600_ring_ib_execute,
+       .irq_set = &r600_irq_set,
+       .irq_process = &r600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
+       .fence_ring_emit = &r600_fence_ring_emit,
+       .cs_parse = &r600_cs_parse,
+       .copy_blit = &r600_copy_blit,
+       .copy_dma = &r600_copy_blit,
+       .copy = &r600_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,
+       .set_memory_clock = &radeon_atom_set_memory_clock,
+       .get_pcie_lanes = &rv370_get_pcie_lanes,
+       .set_pcie_lanes = NULL,
+       .set_clock_gating = NULL,
+       .set_surface_reg = r600_set_surface_reg,
+       .clear_surface_reg = r600_clear_surface_reg,
+       .bandwidth_update = &rv515_bandwidth_update,
+       .hpd_init = &r600_hpd_init,
+       .hpd_fini = &r600_hpd_fini,
+       .hpd_sense = &r600_hpd_sense,
+       .hpd_set_polarity = &r600_hpd_set_polarity,
+       .ioctl_wait_idle = r600_ioctl_wait_idle,
+};
+
+static struct radeon_asic rs780_asic = {
+       .init = &r600_init,
+       .fini = &r600_fini,
+       .suspend = &r600_suspend,
+       .resume = &r600_resume,
+       .cp_commit = &r600_cp_commit,
+       .vga_set_state = &r600_vga_set_state,
+       .gpu_reset = &r600_gpu_reset,
+       .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
+       .gart_set_page = &rs600_gart_set_page,
+       .ring_test = &r600_ring_test,
+       .ring_ib_execute = &r600_ring_ib_execute,
+       .irq_set = &r600_irq_set,
+       .irq_process = &r600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
+       .fence_ring_emit = &r600_fence_ring_emit,
+       .cs_parse = &r600_cs_parse,
+       .copy_blit = &r600_copy_blit,
+       .copy_dma = &r600_copy_blit,
+       .copy = &r600_copy_blit,
+       .get_engine_clock = &radeon_atom_get_engine_clock,
+       .set_engine_clock = &radeon_atom_set_engine_clock,
+       .get_memory_clock = NULL,
+       .set_memory_clock = NULL,
+       .get_pcie_lanes = NULL,
+       .set_pcie_lanes = NULL,
+       .set_clock_gating = NULL,
+       .set_surface_reg = r600_set_surface_reg,
+       .clear_surface_reg = r600_clear_surface_reg,
+       .bandwidth_update = &rs690_bandwidth_update,
+       .hpd_init = &r600_hpd_init,
+       .hpd_fini = &r600_hpd_fini,
+       .hpd_sense = &r600_hpd_sense,
+       .hpd_set_polarity = &r600_hpd_set_polarity,
+       .ioctl_wait_idle = r600_ioctl_wait_idle,
+};
+
+static struct radeon_asic rv770_asic = {
+       .init = &rv770_init,
+       .fini = &rv770_fini,
+       .suspend = &rv770_suspend,
+       .resume = &rv770_resume,
+       .cp_commit = &r600_cp_commit,
+       .gpu_reset = &rv770_gpu_reset,
+       .vga_set_state = &r600_vga_set_state,
+       .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
+       .gart_set_page = &rs600_gart_set_page,
+       .ring_test = &r600_ring_test,
+       .ring_ib_execute = &r600_ring_ib_execute,
+       .irq_set = &r600_irq_set,
+       .irq_process = &r600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
+       .fence_ring_emit = &r600_fence_ring_emit,
+       .cs_parse = &r600_cs_parse,
+       .copy_blit = &r600_copy_blit,
+       .copy_dma = &r600_copy_blit,
+       .copy = &r600_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,
+       .set_memory_clock = &radeon_atom_set_memory_clock,
+       .get_pcie_lanes = &rv370_get_pcie_lanes,
+       .set_pcie_lanes = NULL,
+       .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r600_set_surface_reg,
+       .clear_surface_reg = r600_clear_surface_reg,
+       .bandwidth_update = &rv515_bandwidth_update,
+       .hpd_init = &r600_hpd_init,
+       .hpd_fini = &r600_hpd_fini,
+       .hpd_sense = &r600_hpd_sense,
+       .hpd_set_polarity = &r600_hpd_set_polarity,
+       .ioctl_wait_idle = r600_ioctl_wait_idle,
+};
+
+static struct radeon_asic evergreen_asic = {
+       .init = &evergreen_init,
+       .fini = &evergreen_fini,
+       .suspend = &evergreen_suspend,
+       .resume = &evergreen_resume,
+       .cp_commit = NULL,
+       .gpu_reset = &evergreen_gpu_reset,
+       .vga_set_state = &r600_vga_set_state,
+       .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
+       .gart_set_page = &rs600_gart_set_page,
+       .ring_test = NULL,
+       .ring_ib_execute = NULL,
+       .irq_set = NULL,
+       .irq_process = NULL,
+       .get_vblank_counter = NULL,
+       .fence_ring_emit = NULL,
+       .cs_parse = NULL,
+       .copy_blit = NULL,
+       .copy_dma = NULL,
+       .copy = NULL,
+       .get_engine_clock = &radeon_atom_get_engine_clock,
+       .set_engine_clock = &radeon_atom_set_engine_clock,
+       .get_memory_clock = &radeon_atom_get_memory_clock,
+       .set_memory_clock = &radeon_atom_set_memory_clock,
+       .set_pcie_lanes = NULL,
+       .set_clock_gating = NULL,
+       .set_surface_reg = r600_set_surface_reg,
+       .clear_surface_reg = r600_clear_surface_reg,
+       .bandwidth_update = &evergreen_bandwidth_update,
+       .hpd_init = &evergreen_hpd_init,
+       .hpd_fini = &evergreen_hpd_fini,
+       .hpd_sense = &evergreen_hpd_sense,
+       .hpd_set_polarity = &evergreen_hpd_set_polarity,
+};
+
+int radeon_asic_init(struct radeon_device *rdev)
+{
+       radeon_register_accessor_init(rdev);
+       switch (rdev->family) {
+       case CHIP_R100:
+       case CHIP_RV100:
+       case CHIP_RS100:
+       case CHIP_RV200:
+       case CHIP_RS200:
+               rdev->asic = &r100_asic;
+               break;
+       case CHIP_R200:
+       case CHIP_RV250:
+       case CHIP_RS300:
+       case CHIP_RV280:
+               rdev->asic = &r200_asic;
+               break;
+       case CHIP_R300:
+       case CHIP_R350:
+       case CHIP_RV350:
+       case CHIP_RV380:
+               if (rdev->flags & RADEON_IS_PCIE)
+                       rdev->asic = &r300_asic_pcie;
+               else
+                       rdev->asic = &r300_asic;
+               break;
+       case CHIP_R420:
+       case CHIP_R423:
+       case CHIP_RV410:
+               rdev->asic = &r420_asic;
+               break;
+       case CHIP_RS400:
+       case CHIP_RS480:
+               rdev->asic = &rs400_asic;
+               break;
+       case CHIP_RS600:
+               rdev->asic = &rs600_asic;
+               break;
+       case CHIP_RS690:
+       case CHIP_RS740:
+               rdev->asic = &rs690_asic;
+               break;
+       case CHIP_RV515:
+               rdev->asic = &rv515_asic;
+               break;
+       case CHIP_R520:
+       case CHIP_RV530:
+       case CHIP_RV560:
+       case CHIP_RV570:
+       case CHIP_R580:
+               rdev->asic = &r520_asic;
+               break;
+       case CHIP_R600:
+       case CHIP_RV610:
+       case CHIP_RV630:
+       case CHIP_RV620:
+       case CHIP_RV635:
+       case CHIP_RV670:
+               rdev->asic = &r600_asic;
+               break;
+       case CHIP_RS780:
+       case CHIP_RS880:
+               rdev->asic = &rs780_asic;
+               break;
+       case CHIP_RV770:
+       case CHIP_RV730:
+       case CHIP_RV710:
+       case CHIP_RV740:
+               rdev->asic = &rv770_asic;
+               break;
+       case CHIP_CEDAR:
+       case CHIP_REDWOOD:
+       case CHIP_JUNIPER:
+       case CHIP_CYPRESS:
+       case CHIP_HEMLOCK:
+               rdev->asic = &evergreen_asic;
+               break;
+       default:
+               /* FIXME: not supported yet */
+               return -EINVAL;
+       }
+
+       if (rdev->flags & RADEON_IS_IGP) {
+               rdev->asic->get_memory_clock = NULL;
+               rdev->asic->set_memory_clock = NULL;
+       }
+
+       /* set the number of crtcs */
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               rdev->num_crtc = 1;
+       else {
+               if (ASIC_IS_DCE4(rdev))
+                       rdev->num_crtc = 6;
+               else
+                       rdev->num_crtc = 2;
+       }
+
+       return 0;
+}
+
+/*
+ * Wrapper around modesetting bits. Move to radeon_clocks.c?
+ */
+int radeon_clocks_init(struct radeon_device *rdev)
+{
+       int r;
+
+       r = radeon_static_clocks_init(rdev->ddev);
+       if (r) {
+               return r;
+       }
+       DRM_INFO("Clocks initialized !\n");
+       return 0;
+}
+
+void radeon_clocks_fini(struct radeon_device *rdev)
+{
+}
index d3a157b2bcb73ab51e1d68d0430c65a9916a70b0..a0b8280663d1ba9d17dd6252cce1274d73b7181d 100644 (file)
@@ -45,10 +45,18 @@ void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
 /*
  * r100,rv100,rs100,rv200,rs200
  */
-extern int r100_init(struct radeon_device *rdev);
-extern void r100_fini(struct radeon_device *rdev);
-extern int r100_suspend(struct radeon_device *rdev);
-extern int r100_resume(struct radeon_device *rdev);
+struct r100_mc_save {
+       u32     GENMO_WT;
+       u32     CRTC_EXT_CNTL;
+       u32     CRTC_GEN_CNTL;
+       u32     CRTC2_GEN_CNTL;
+       u32     CUR_OFFSET;
+       u32     CUR2_OFFSET;
+};
+int r100_init(struct radeon_device *rdev);
+void r100_fini(struct radeon_device *rdev);
+int r100_suspend(struct radeon_device *rdev);
+int r100_resume(struct radeon_device *rdev);
 uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
 void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void r100_vga_set_state(struct radeon_device *rdev, bool state);
@@ -73,7 +81,7 @@ int r100_copy_blit(struct radeon_device *rdev,
 int r100_set_surface_reg(struct radeon_device *rdev, int reg,
                         uint32_t tiling_flags, uint32_t pitch,
                         uint32_t offset, uint32_t obj_size);
-int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
+void r100_clear_surface_reg(struct radeon_device *rdev, int reg);
 void r100_bandwidth_update(struct radeon_device *rdev);
 void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int r100_ring_test(struct radeon_device *rdev);
@@ -82,44 +90,42 @@ void r100_hpd_fini(struct radeon_device *rdev);
 bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
 void r100_hpd_set_polarity(struct radeon_device *rdev,
                           enum radeon_hpd_id hpd);
-
-static struct radeon_asic r100_asic = {
-       .init = &r100_init,
-       .fini = &r100_fini,
-       .suspend = &r100_suspend,
-       .resume = &r100_resume,
-       .vga_set_state = &r100_vga_set_state,
-       .gpu_reset = &r100_gpu_reset,
-       .gart_tlb_flush = &r100_pci_gart_tlb_flush,
-       .gart_set_page = &r100_pci_gart_set_page,
-       .cp_commit = &r100_cp_commit,
-       .ring_start = &r100_ring_start,
-       .ring_test = &r100_ring_test,
-       .ring_ib_execute = &r100_ring_ib_execute,
-       .irq_set = &r100_irq_set,
-       .irq_process = &r100_irq_process,
-       .get_vblank_counter = &r100_get_vblank_counter,
-       .fence_ring_emit = &r100_fence_ring_emit,
-       .cs_parse = &r100_cs_parse,
-       .copy_blit = &r100_copy_blit,
-       .copy_dma = NULL,
-       .copy = &r100_copy_blit,
-       .get_engine_clock = &radeon_legacy_get_engine_clock,
-       .set_engine_clock = &radeon_legacy_set_engine_clock,
-       .get_memory_clock = &radeon_legacy_get_memory_clock,
-       .set_memory_clock = NULL,
-       .get_pcie_lanes = NULL,
-       .set_pcie_lanes = NULL,
-       .set_clock_gating = &radeon_legacy_set_clock_gating,
-       .set_surface_reg = r100_set_surface_reg,
-       .clear_surface_reg = r100_clear_surface_reg,
-       .bandwidth_update = &r100_bandwidth_update,
-       .hpd_init = &r100_hpd_init,
-       .hpd_fini = &r100_hpd_fini,
-       .hpd_sense = &r100_hpd_sense,
-       .hpd_set_polarity = &r100_hpd_set_polarity,
-       .ioctl_wait_idle = NULL,
-};
+int r100_debugfs_rbbm_init(struct radeon_device *rdev);
+int r100_debugfs_cp_init(struct radeon_device *rdev);
+void r100_cp_disable(struct radeon_device *rdev);
+int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
+void r100_cp_fini(struct radeon_device *rdev);
+int r100_pci_gart_init(struct radeon_device *rdev);
+void r100_pci_gart_fini(struct radeon_device *rdev);
+int r100_pci_gart_enable(struct radeon_device *rdev);
+void r100_pci_gart_disable(struct radeon_device *rdev);
+int r100_debugfs_mc_info_init(struct radeon_device *rdev);
+int r100_gui_wait_for_idle(struct radeon_device *rdev);
+void r100_ib_fini(struct radeon_device *rdev);
+int r100_ib_init(struct radeon_device *rdev);
+void r100_irq_disable(struct radeon_device *rdev);
+void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save);
+void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save);
+void r100_vram_init_sizes(struct radeon_device *rdev);
+void r100_wb_disable(struct radeon_device *rdev);
+void r100_wb_fini(struct radeon_device *rdev);
+int r100_wb_init(struct radeon_device *rdev);
+void r100_hdp_reset(struct radeon_device *rdev);
+int r100_rb2d_reset(struct radeon_device *rdev);
+int r100_cp_reset(struct radeon_device *rdev);
+void r100_vga_render_disable(struct radeon_device *rdev);
+int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
+                                        struct radeon_cs_packet *pkt,
+                                        struct radeon_bo *robj);
+int r100_cs_parse_packet0(struct radeon_cs_parser *p,
+                         struct radeon_cs_packet *pkt,
+                         const unsigned *auth, unsigned n,
+                         radeon_packet0_check_t check);
+int r100_cs_packet_parse(struct radeon_cs_parser *p,
+                        struct radeon_cs_packet *pkt,
+                        unsigned idx);
+void r100_enable_bm(struct radeon_device *rdev);
+void r100_set_common_regs(struct radeon_device *rdev);
 
 /*
  * r200,rv250,rs300,rv280
@@ -129,43 +135,6 @@ extern int r200_copy_dma(struct radeon_device *rdev,
                        uint64_t dst_offset,
                        unsigned num_pages,
                        struct radeon_fence *fence);
-static struct radeon_asic r200_asic = {
-       .init = &r100_init,
-       .fini = &r100_fini,
-       .suspend = &r100_suspend,
-       .resume = &r100_resume,
-       .vga_set_state = &r100_vga_set_state,
-       .gpu_reset = &r100_gpu_reset,
-       .gart_tlb_flush = &r100_pci_gart_tlb_flush,
-       .gart_set_page = &r100_pci_gart_set_page,
-       .cp_commit = &r100_cp_commit,
-       .ring_start = &r100_ring_start,
-       .ring_test = &r100_ring_test,
-       .ring_ib_execute = &r100_ring_ib_execute,
-       .irq_set = &r100_irq_set,
-       .irq_process = &r100_irq_process,
-       .get_vblank_counter = &r100_get_vblank_counter,
-       .fence_ring_emit = &r100_fence_ring_emit,
-       .cs_parse = &r100_cs_parse,
-       .copy_blit = &r100_copy_blit,
-       .copy_dma = &r200_copy_dma,
-       .copy = &r100_copy_blit,
-       .get_engine_clock = &radeon_legacy_get_engine_clock,
-       .set_engine_clock = &radeon_legacy_set_engine_clock,
-       .get_memory_clock = &radeon_legacy_get_memory_clock,
-       .set_memory_clock = NULL,
-       .set_pcie_lanes = NULL,
-       .set_clock_gating = &radeon_legacy_set_clock_gating,
-       .set_surface_reg = r100_set_surface_reg,
-       .clear_surface_reg = r100_clear_surface_reg,
-       .bandwidth_update = &r100_bandwidth_update,
-       .hpd_init = &r100_hpd_init,
-       .hpd_fini = &r100_hpd_fini,
-       .hpd_sense = &r100_hpd_sense,
-       .hpd_set_polarity = &r100_hpd_set_polarity,
-       .ioctl_wait_idle = NULL,
-};
-
 
 /*
  * r300,r350,rv350,rv380
@@ -186,82 +155,6 @@ extern void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v
 extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern int rv370_get_pcie_lanes(struct radeon_device *rdev);
 
-static struct radeon_asic r300_asic = {
-       .init = &r300_init,
-       .fini = &r300_fini,
-       .suspend = &r300_suspend,
-       .resume = &r300_resume,
-       .vga_set_state = &r100_vga_set_state,
-       .gpu_reset = &r300_gpu_reset,
-       .gart_tlb_flush = &r100_pci_gart_tlb_flush,
-       .gart_set_page = &r100_pci_gart_set_page,
-       .cp_commit = &r100_cp_commit,
-       .ring_start = &r300_ring_start,
-       .ring_test = &r100_ring_test,
-       .ring_ib_execute = &r100_ring_ib_execute,
-       .irq_set = &r100_irq_set,
-       .irq_process = &r100_irq_process,
-       .get_vblank_counter = &r100_get_vblank_counter,
-       .fence_ring_emit = &r300_fence_ring_emit,
-       .cs_parse = &r300_cs_parse,
-       .copy_blit = &r100_copy_blit,
-       .copy_dma = &r200_copy_dma,
-       .copy = &r100_copy_blit,
-       .get_engine_clock = &radeon_legacy_get_engine_clock,
-       .set_engine_clock = &radeon_legacy_set_engine_clock,
-       .get_memory_clock = &radeon_legacy_get_memory_clock,
-       .set_memory_clock = NULL,
-       .get_pcie_lanes = &rv370_get_pcie_lanes,
-       .set_pcie_lanes = &rv370_set_pcie_lanes,
-       .set_clock_gating = &radeon_legacy_set_clock_gating,
-       .set_surface_reg = r100_set_surface_reg,
-       .clear_surface_reg = r100_clear_surface_reg,
-       .bandwidth_update = &r100_bandwidth_update,
-       .hpd_init = &r100_hpd_init,
-       .hpd_fini = &r100_hpd_fini,
-       .hpd_sense = &r100_hpd_sense,
-       .hpd_set_polarity = &r100_hpd_set_polarity,
-       .ioctl_wait_idle = NULL,
-};
-
-
-static struct radeon_asic r300_asic_pcie = {
-       .init = &r300_init,
-       .fini = &r300_fini,
-       .suspend = &r300_suspend,
-       .resume = &r300_resume,
-       .vga_set_state = &r100_vga_set_state,
-       .gpu_reset = &r300_gpu_reset,
-       .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
-       .gart_set_page = &rv370_pcie_gart_set_page,
-       .cp_commit = &r100_cp_commit,
-       .ring_start = &r300_ring_start,
-       .ring_test = &r100_ring_test,
-       .ring_ib_execute = &r100_ring_ib_execute,
-       .irq_set = &r100_irq_set,
-       .irq_process = &r100_irq_process,
-       .get_vblank_counter = &r100_get_vblank_counter,
-       .fence_ring_emit = &r300_fence_ring_emit,
-       .cs_parse = &r300_cs_parse,
-       .copy_blit = &r100_copy_blit,
-       .copy_dma = &r200_copy_dma,
-       .copy = &r100_copy_blit,
-       .get_engine_clock = &radeon_legacy_get_engine_clock,
-       .set_engine_clock = &radeon_legacy_set_engine_clock,
-       .get_memory_clock = &radeon_legacy_get_memory_clock,
-       .set_memory_clock = NULL,
-       .set_pcie_lanes = &rv370_set_pcie_lanes,
-       .set_clock_gating = &radeon_legacy_set_clock_gating,
-       .set_surface_reg = r100_set_surface_reg,
-       .clear_surface_reg = r100_clear_surface_reg,
-       .bandwidth_update = &r100_bandwidth_update,
-       .hpd_init = &r100_hpd_init,
-       .hpd_fini = &r100_hpd_fini,
-       .hpd_sense = &r100_hpd_sense,
-       .hpd_set_polarity = &r100_hpd_set_polarity,
-       .ioctl_wait_idle = NULL,
-};
-
 /*
  * r420,r423,rv410
  */
@@ -269,44 +162,6 @@ extern int r420_init(struct radeon_device *rdev);
 extern void r420_fini(struct radeon_device *rdev);
 extern int r420_suspend(struct radeon_device *rdev);
 extern int r420_resume(struct radeon_device *rdev);
-static struct radeon_asic r420_asic = {
-       .init = &r420_init,
-       .fini = &r420_fini,
-       .suspend = &r420_suspend,
-       .resume = &r420_resume,
-       .vga_set_state = &r100_vga_set_state,
-       .gpu_reset = &r300_gpu_reset,
-       .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
-       .gart_set_page = &rv370_pcie_gart_set_page,
-       .cp_commit = &r100_cp_commit,
-       .ring_start = &r300_ring_start,
-       .ring_test = &r100_ring_test,
-       .ring_ib_execute = &r100_ring_ib_execute,
-       .irq_set = &r100_irq_set,
-       .irq_process = &r100_irq_process,
-       .get_vblank_counter = &r100_get_vblank_counter,
-       .fence_ring_emit = &r300_fence_ring_emit,
-       .cs_parse = &r300_cs_parse,
-       .copy_blit = &r100_copy_blit,
-       .copy_dma = &r200_copy_dma,
-       .copy = &r100_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,
-       .set_memory_clock = &radeon_atom_set_memory_clock,
-       .get_pcie_lanes = &rv370_get_pcie_lanes,
-       .set_pcie_lanes = &rv370_set_pcie_lanes,
-       .set_clock_gating = &radeon_atom_set_clock_gating,
-       .set_surface_reg = r100_set_surface_reg,
-       .clear_surface_reg = r100_clear_surface_reg,
-       .bandwidth_update = &r100_bandwidth_update,
-       .hpd_init = &r100_hpd_init,
-       .hpd_fini = &r100_hpd_fini,
-       .hpd_sense = &r100_hpd_sense,
-       .hpd_set_polarity = &r100_hpd_set_polarity,
-       .ioctl_wait_idle = NULL,
-};
-
 
 /*
  * rs400,rs480
@@ -319,44 +174,6 @@ void rs400_gart_tlb_flush(struct radeon_device *rdev);
 int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
 uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
-static struct radeon_asic rs400_asic = {
-       .init = &rs400_init,
-       .fini = &rs400_fini,
-       .suspend = &rs400_suspend,
-       .resume = &rs400_resume,
-       .vga_set_state = &r100_vga_set_state,
-       .gpu_reset = &r300_gpu_reset,
-       .gart_tlb_flush = &rs400_gart_tlb_flush,
-       .gart_set_page = &rs400_gart_set_page,
-       .cp_commit = &r100_cp_commit,
-       .ring_start = &r300_ring_start,
-       .ring_test = &r100_ring_test,
-       .ring_ib_execute = &r100_ring_ib_execute,
-       .irq_set = &r100_irq_set,
-       .irq_process = &r100_irq_process,
-       .get_vblank_counter = &r100_get_vblank_counter,
-       .fence_ring_emit = &r300_fence_ring_emit,
-       .cs_parse = &r300_cs_parse,
-       .copy_blit = &r100_copy_blit,
-       .copy_dma = &r200_copy_dma,
-       .copy = &r100_copy_blit,
-       .get_engine_clock = &radeon_legacy_get_engine_clock,
-       .set_engine_clock = &radeon_legacy_set_engine_clock,
-       .get_memory_clock = &radeon_legacy_get_memory_clock,
-       .set_memory_clock = NULL,
-       .get_pcie_lanes = NULL,
-       .set_pcie_lanes = NULL,
-       .set_clock_gating = &radeon_legacy_set_clock_gating,
-       .set_surface_reg = r100_set_surface_reg,
-       .clear_surface_reg = r100_clear_surface_reg,
-       .bandwidth_update = &r100_bandwidth_update,
-       .hpd_init = &r100_hpd_init,
-       .hpd_fini = &r100_hpd_fini,
-       .hpd_sense = &r100_hpd_sense,
-       .hpd_set_polarity = &r100_hpd_set_polarity,
-       .ioctl_wait_idle = NULL,
-};
-
 
 /*
  * rs600.
@@ -379,45 +196,6 @@ bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
 void rs600_hpd_set_polarity(struct radeon_device *rdev,
                            enum radeon_hpd_id hpd);
 
-static struct radeon_asic rs600_asic = {
-       .init = &rs600_init,
-       .fini = &rs600_fini,
-       .suspend = &rs600_suspend,
-       .resume = &rs600_resume,
-       .vga_set_state = &r100_vga_set_state,
-       .gpu_reset = &r300_gpu_reset,
-       .gart_tlb_flush = &rs600_gart_tlb_flush,
-       .gart_set_page = &rs600_gart_set_page,
-       .cp_commit = &r100_cp_commit,
-       .ring_start = &r300_ring_start,
-       .ring_test = &r100_ring_test,
-       .ring_ib_execute = &r100_ring_ib_execute,
-       .irq_set = &rs600_irq_set,
-       .irq_process = &rs600_irq_process,
-       .get_vblank_counter = &rs600_get_vblank_counter,
-       .fence_ring_emit = &r300_fence_ring_emit,
-       .cs_parse = &r300_cs_parse,
-       .copy_blit = &r100_copy_blit,
-       .copy_dma = &r200_copy_dma,
-       .copy = &r100_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,
-       .set_memory_clock = &radeon_atom_set_memory_clock,
-       .get_pcie_lanes = NULL,
-       .set_pcie_lanes = NULL,
-       .set_clock_gating = &radeon_atom_set_clock_gating,
-       .set_surface_reg = r100_set_surface_reg,
-       .clear_surface_reg = r100_clear_surface_reg,
-       .bandwidth_update = &rs600_bandwidth_update,
-       .hpd_init = &rs600_hpd_init,
-       .hpd_fini = &rs600_hpd_fini,
-       .hpd_sense = &rs600_hpd_sense,
-       .hpd_set_polarity = &rs600_hpd_set_polarity,
-       .ioctl_wait_idle = NULL,
-};
-
-
 /*
  * rs690,rs740
  */
@@ -428,44 +206,6 @@ int rs690_suspend(struct radeon_device *rdev);
 uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void rs690_bandwidth_update(struct radeon_device *rdev);
-static struct radeon_asic rs690_asic = {
-       .init = &rs690_init,
-       .fini = &rs690_fini,
-       .suspend = &rs690_suspend,
-       .resume = &rs690_resume,
-       .vga_set_state = &r100_vga_set_state,
-       .gpu_reset = &r300_gpu_reset,
-       .gart_tlb_flush = &rs400_gart_tlb_flush,
-       .gart_set_page = &rs400_gart_set_page,
-       .cp_commit = &r100_cp_commit,
-       .ring_start = &r300_ring_start,
-       .ring_test = &r100_ring_test,
-       .ring_ib_execute = &r100_ring_ib_execute,
-       .irq_set = &rs600_irq_set,
-       .irq_process = &rs600_irq_process,
-       .get_vblank_counter = &rs600_get_vblank_counter,
-       .fence_ring_emit = &r300_fence_ring_emit,
-       .cs_parse = &r300_cs_parse,
-       .copy_blit = &r100_copy_blit,
-       .copy_dma = &r200_copy_dma,
-       .copy = &r200_copy_dma,
-       .get_engine_clock = &radeon_atom_get_engine_clock,
-       .set_engine_clock = &radeon_atom_set_engine_clock,
-       .get_memory_clock = &radeon_atom_get_memory_clock,
-       .set_memory_clock = &radeon_atom_set_memory_clock,
-       .get_pcie_lanes = NULL,
-       .set_pcie_lanes = NULL,
-       .set_clock_gating = &radeon_atom_set_clock_gating,
-       .set_surface_reg = r100_set_surface_reg,
-       .clear_surface_reg = r100_clear_surface_reg,
-       .bandwidth_update = &rs690_bandwidth_update,
-       .hpd_init = &rs600_hpd_init,
-       .hpd_fini = &rs600_hpd_fini,
-       .hpd_sense = &rs600_hpd_sense,
-       .hpd_set_polarity = &rs600_hpd_set_polarity,
-       .ioctl_wait_idle = NULL,
-};
-
 
 /*
  * rv515
@@ -481,87 +221,12 @@ void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void rv515_bandwidth_update(struct radeon_device *rdev);
 int rv515_resume(struct radeon_device *rdev);
 int rv515_suspend(struct radeon_device *rdev);
-static struct radeon_asic rv515_asic = {
-       .init = &rv515_init,
-       .fini = &rv515_fini,
-       .suspend = &rv515_suspend,
-       .resume = &rv515_resume,
-       .vga_set_state = &r100_vga_set_state,
-       .gpu_reset = &rv515_gpu_reset,
-       .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
-       .gart_set_page = &rv370_pcie_gart_set_page,
-       .cp_commit = &r100_cp_commit,
-       .ring_start = &rv515_ring_start,
-       .ring_test = &r100_ring_test,
-       .ring_ib_execute = &r100_ring_ib_execute,
-       .irq_set = &rs600_irq_set,
-       .irq_process = &rs600_irq_process,
-       .get_vblank_counter = &rs600_get_vblank_counter,
-       .fence_ring_emit = &r300_fence_ring_emit,
-       .cs_parse = &r300_cs_parse,
-       .copy_blit = &r100_copy_blit,
-       .copy_dma = &r200_copy_dma,
-       .copy = &r100_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,
-       .set_memory_clock = &radeon_atom_set_memory_clock,
-       .get_pcie_lanes = &rv370_get_pcie_lanes,
-       .set_pcie_lanes = &rv370_set_pcie_lanes,
-       .set_clock_gating = &radeon_atom_set_clock_gating,
-       .set_surface_reg = r100_set_surface_reg,
-       .clear_surface_reg = r100_clear_surface_reg,
-       .bandwidth_update = &rv515_bandwidth_update,
-       .hpd_init = &rs600_hpd_init,
-       .hpd_fini = &rs600_hpd_fini,
-       .hpd_sense = &rs600_hpd_sense,
-       .hpd_set_polarity = &rs600_hpd_set_polarity,
-       .ioctl_wait_idle = NULL,
-};
-
 
 /*
  * r520,rv530,rv560,rv570,r580
  */
 int r520_init(struct radeon_device *rdev);
 int r520_resume(struct radeon_device *rdev);
-static struct radeon_asic r520_asic = {
-       .init = &r520_init,
-       .fini = &rv515_fini,
-       .suspend = &rv515_suspend,
-       .resume = &r520_resume,
-       .vga_set_state = &r100_vga_set_state,
-       .gpu_reset = &rv515_gpu_reset,
-       .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
-       .gart_set_page = &rv370_pcie_gart_set_page,
-       .cp_commit = &r100_cp_commit,
-       .ring_start = &rv515_ring_start,
-       .ring_test = &r100_ring_test,
-       .ring_ib_execute = &r100_ring_ib_execute,
-       .irq_set = &rs600_irq_set,
-       .irq_process = &rs600_irq_process,
-       .get_vblank_counter = &rs600_get_vblank_counter,
-       .fence_ring_emit = &r300_fence_ring_emit,
-       .cs_parse = &r300_cs_parse,
-       .copy_blit = &r100_copy_blit,
-       .copy_dma = &r200_copy_dma,
-       .copy = &r100_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,
-       .set_memory_clock = &radeon_atom_set_memory_clock,
-       .get_pcie_lanes = &rv370_get_pcie_lanes,
-       .set_pcie_lanes = &rv370_set_pcie_lanes,
-       .set_clock_gating = &radeon_atom_set_clock_gating,
-       .set_surface_reg = r100_set_surface_reg,
-       .clear_surface_reg = r100_clear_surface_reg,
-       .bandwidth_update = &rv515_bandwidth_update,
-       .hpd_init = &rs600_hpd_init,
-       .hpd_fini = &rs600_hpd_fini,
-       .hpd_sense = &rs600_hpd_sense,
-       .hpd_set_polarity = &rs600_hpd_set_polarity,
-       .ioctl_wait_idle = NULL,
-};
 
 /*
  * r600,rv610,rv630,rv620,rv635,rv670,rs780,rs880
@@ -591,7 +256,7 @@ int r600_gpu_reset(struct radeon_device *rdev);
 int r600_set_surface_reg(struct radeon_device *rdev, int reg,
                         uint32_t tiling_flags, uint32_t pitch,
                         uint32_t offset, uint32_t obj_size);
-int r600_clear_surface_reg(struct radeon_device *rdev, int reg);
+void r600_clear_surface_reg(struct radeon_device *rdev, int reg);
 void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int r600_ring_test(struct radeon_device *rdev);
 int r600_copy_blit(struct radeon_device *rdev,
@@ -604,43 +269,6 @@ void r600_hpd_set_polarity(struct radeon_device *rdev,
                           enum radeon_hpd_id hpd);
 extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo);
 
-static struct radeon_asic r600_asic = {
-       .init = &r600_init,
-       .fini = &r600_fini,
-       .suspend = &r600_suspend,
-       .resume = &r600_resume,
-       .cp_commit = &r600_cp_commit,
-       .vga_set_state = &r600_vga_set_state,
-       .gpu_reset = &r600_gpu_reset,
-       .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
-       .gart_set_page = &rs600_gart_set_page,
-       .ring_test = &r600_ring_test,
-       .ring_ib_execute = &r600_ring_ib_execute,
-       .irq_set = &r600_irq_set,
-       .irq_process = &r600_irq_process,
-       .get_vblank_counter = &rs600_get_vblank_counter,
-       .fence_ring_emit = &r600_fence_ring_emit,
-       .cs_parse = &r600_cs_parse,
-       .copy_blit = &r600_copy_blit,
-       .copy_dma = &r600_copy_blit,
-       .copy = &r600_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,
-       .set_memory_clock = &radeon_atom_set_memory_clock,
-       .get_pcie_lanes = &rv370_get_pcie_lanes,
-       .set_pcie_lanes = NULL,
-       .set_clock_gating = NULL,
-       .set_surface_reg = r600_set_surface_reg,
-       .clear_surface_reg = r600_clear_surface_reg,
-       .bandwidth_update = &rv515_bandwidth_update,
-       .hpd_init = &r600_hpd_init,
-       .hpd_fini = &r600_hpd_fini,
-       .hpd_sense = &r600_hpd_sense,
-       .hpd_set_polarity = &r600_hpd_set_polarity,
-       .ioctl_wait_idle = r600_ioctl_wait_idle,
-};
-
 /*
  * rv770,rv730,rv710,rv740
  */
@@ -650,43 +278,6 @@ int rv770_suspend(struct radeon_device *rdev);
 int rv770_resume(struct radeon_device *rdev);
 int rv770_gpu_reset(struct radeon_device *rdev);
 
-static struct radeon_asic rv770_asic = {
-       .init = &rv770_init,
-       .fini = &rv770_fini,
-       .suspend = &rv770_suspend,
-       .resume = &rv770_resume,
-       .cp_commit = &r600_cp_commit,
-       .gpu_reset = &rv770_gpu_reset,
-       .vga_set_state = &r600_vga_set_state,
-       .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
-       .gart_set_page = &rs600_gart_set_page,
-       .ring_test = &r600_ring_test,
-       .ring_ib_execute = &r600_ring_ib_execute,
-       .irq_set = &r600_irq_set,
-       .irq_process = &r600_irq_process,
-       .get_vblank_counter = &rs600_get_vblank_counter,
-       .fence_ring_emit = &r600_fence_ring_emit,
-       .cs_parse = &r600_cs_parse,
-       .copy_blit = &r600_copy_blit,
-       .copy_dma = &r600_copy_blit,
-       .copy = &r600_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,
-       .set_memory_clock = &radeon_atom_set_memory_clock,
-       .get_pcie_lanes = &rv370_get_pcie_lanes,
-       .set_pcie_lanes = NULL,
-       .set_clock_gating = &radeon_atom_set_clock_gating,
-       .set_surface_reg = r600_set_surface_reg,
-       .clear_surface_reg = r600_clear_surface_reg,
-       .bandwidth_update = &rv515_bandwidth_update,
-       .hpd_init = &r600_hpd_init,
-       .hpd_fini = &r600_hpd_fini,
-       .hpd_sense = &r600_hpd_sense,
-       .hpd_set_polarity = &r600_hpd_set_polarity,
-       .ioctl_wait_idle = r600_ioctl_wait_idle,
-};
-
 /*
  * evergreen
  */
@@ -701,40 +292,4 @@ void evergreen_hpd_fini(struct radeon_device *rdev);
 bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
 void evergreen_hpd_set_polarity(struct radeon_device *rdev,
                                enum radeon_hpd_id hpd);
-
-static struct radeon_asic evergreen_asic = {
-       .init = &evergreen_init,
-       .fini = &evergreen_fini,
-       .suspend = &evergreen_suspend,
-       .resume = &evergreen_resume,
-       .cp_commit = NULL,
-       .gpu_reset = &evergreen_gpu_reset,
-       .vga_set_state = &r600_vga_set_state,
-       .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
-       .gart_set_page = &rs600_gart_set_page,
-       .ring_test = NULL,
-       .ring_ib_execute = NULL,
-       .irq_set = NULL,
-       .irq_process = NULL,
-       .get_vblank_counter = NULL,
-       .fence_ring_emit = NULL,
-       .cs_parse = NULL,
-       .copy_blit = NULL,
-       .copy_dma = NULL,
-       .copy = NULL,
-       .get_engine_clock = &radeon_atom_get_engine_clock,
-       .set_engine_clock = &radeon_atom_set_engine_clock,
-       .get_memory_clock = &radeon_atom_get_memory_clock,
-       .set_memory_clock = &radeon_atom_set_memory_clock,
-       .set_pcie_lanes = NULL,
-       .set_clock_gating = NULL,
-       .set_surface_reg = r600_set_surface_reg,
-       .clear_surface_reg = r600_clear_surface_reg,
-       .bandwidth_update = &evergreen_bandwidth_update,
-       .hpd_init = &evergreen_hpd_init,
-       .hpd_fini = &evergreen_hpd_fini,
-       .hpd_sense = &evergreen_hpd_sense,
-       .hpd_set_polarity = &evergreen_hpd_set_polarity,
-};
-
 #endif
index 93783b15c81d8226d9833c730af74250d8e3fb5e..1fff95505cf5fec08f5506c47e26b8e00866632c 100644 (file)
@@ -75,46 +75,45 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
        memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
        i2c.valid = false;
 
-       atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
-
-       i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
-
-
-       for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
-               gpio = &i2c_info->asGPIO_Info[i];
-
-               if (gpio->sucI2cId.ucAccess == id) {
-                       i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
-                       i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
-                       i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
-                       i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
-                       i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
-                       i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
-                       i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
-                       i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
-                       i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
-                       i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
-                       i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
-                       i2c.en_data_mask = (1 << gpio->ucDataEnShift);
-                       i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
-                       i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
-                       i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
-                       i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
-
-                       if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
-                               i2c.hw_capable = true;
-                       else
-                               i2c.hw_capable = false;
-
-                       if (gpio->sucI2cId.ucAccess == 0xa0)
-                               i2c.mm_i2c = true;
-                       else
-                               i2c.mm_i2c = false;
-
-                       i2c.i2c_id = gpio->sucI2cId.ucAccess;
-
-                       i2c.valid = true;
-                       break;
+       if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
+               i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
+
+               for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
+                       gpio = &i2c_info->asGPIO_Info[i];
+
+                       if (gpio->sucI2cId.ucAccess == id) {
+                               i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
+                               i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
+                               i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
+                               i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
+                               i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
+                               i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
+                               i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
+                               i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
+                               i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
+                               i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
+                               i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
+                               i2c.en_data_mask = (1 << gpio->ucDataEnShift);
+                               i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
+                               i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
+                               i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
+                               i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
+
+                               if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
+                                       i2c.hw_capable = true;
+                               else
+                                       i2c.hw_capable = false;
+
+                               if (gpio->sucI2cId.ucAccess == 0xa0)
+                                       i2c.mm_i2c = true;
+                               else
+                                       i2c.mm_i2c = false;
+
+                               i2c.i2c_id = gpio->sucI2cId.ucAccess;
+
+                               i2c.valid = true;
+                               break;
+                       }
                }
        }
 
@@ -135,20 +134,21 @@ static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rd
        memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
        gpio.valid = false;
 
-       atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset);
+       if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
+               gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
 
-       gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
+               num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
+                       sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
 
-       num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
-
-       for (i = 0; i < num_indices; i++) {
-               pin = &gpio_info->asGPIO_Pin[i];
-               if (id == pin->ucGPIO_ID) {
-                       gpio.id = pin->ucGPIO_ID;
-                       gpio.reg = pin->usGpioPin_AIndex * 4;
-                       gpio.mask = (1 << pin->ucGpioPinBitShift);
-                       gpio.valid = true;
-                       break;
+               for (i = 0; i < num_indices; i++) {
+                       pin = &gpio_info->asGPIO_Pin[i];
+                       if (id == pin->ucGPIO_ID) {
+                               gpio.id = pin->ucGPIO_ID;
+                               gpio.reg = pin->usGpioPin_AIndex * 4;
+                               gpio.mask = (1 << pin->ucGpioPinBitShift);
+                               gpio.valid = true;
+                               break;
+                       }
                }
        }
 
@@ -264,6 +264,8 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
                if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) ||
                    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
                        return false;
+               if (supported_device == ATOM_DEVICE_CRT2_SUPPORT)
+                       *line_mux = 0x90;
        }
 
        /* ASUS HD 3600 XT board lists the DVI port as HDMI */
@@ -395,9 +397,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
        struct radeon_gpio_rec gpio;
        struct radeon_hpd hpd;
 
-       atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
-
-       if (data_offset == 0)
+       if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
                return false;
 
        if (crev < 2)
@@ -449,37 +449,43 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                    GetIndexIntoMasterTable(DATA,
                                                            IntegratedSystemInfo);
 
-                               atom_parse_data_header(ctx, index, &size, &frev,
-                                                      &crev, &igp_offset);
-
-                               if (crev >= 2) {
-                                       igp_obj =
-                                           (ATOM_INTEGRATED_SYSTEM_INFO_V2
-                                            *) (ctx->bios + igp_offset);
-
-                                       if (igp_obj) {
-                                               uint32_t slot_config, ct;
-
-                                               if (con_obj_num == 1)
-                                                       slot_config =
-                                                           igp_obj->
-                                                           ulDDISlot1Config;
-                                               else
-                                                       slot_config =
-                                                           igp_obj->
-                                                           ulDDISlot2Config;
-
-                                               ct = (slot_config >> 16) & 0xff;
-                                               connector_type =
-                                                   object_connector_convert
-                                                   [ct];
-                                               connector_object_id = ct;
-                                               igp_lane_info =
-                                                   slot_config & 0xffff;
+                               if (atom_parse_data_header(ctx, index, &size, &frev,
+                                                          &crev, &igp_offset)) {
+
+                                       if (crev >= 2) {
+                                               igp_obj =
+                                                       (ATOM_INTEGRATED_SYSTEM_INFO_V2
+                                                        *) (ctx->bios + igp_offset);
+
+                                               if (igp_obj) {
+                                                       uint32_t slot_config, ct;
+
+                                                       if (con_obj_num == 1)
+                                                               slot_config =
+                                                                       igp_obj->
+                                                                       ulDDISlot1Config;
+                                                       else
+                                                               slot_config =
+                                                                       igp_obj->
+                                                                       ulDDISlot2Config;
+
+                                                       ct = (slot_config >> 16) & 0xff;
+                                                       connector_type =
+                                                               object_connector_convert
+                                                               [ct];
+                                                       connector_object_id = ct;
+                                                       igp_lane_info =
+                                                               slot_config & 0xffff;
+                                               } else
+                                                       continue;
                                        } else
                                                continue;
-                               } else
-                                       continue;
+                               } else {
+                                       igp_lane_info = 0;
+                                       connector_type =
+                                               object_connector_convert[con_obj_id];
+                                       connector_object_id = con_obj_id;
+                               }
                        } else {
                                igp_lane_info = 0;
                                connector_type =
@@ -627,20 +633,23 @@ static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
                uint8_t frev, crev;
                ATOM_XTMDS_INFO *xtmds;
 
-               atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
-               xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
+               if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) {
+                       xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
 
-               if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
-                       if (connector_type == DRM_MODE_CONNECTOR_DVII)
-                               return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
-                       else
-                               return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
-               } else {
-                       if (connector_type == DRM_MODE_CONNECTOR_DVII)
-                               return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
-                       else
-                               return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
-               }
+                       if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
+                               if (connector_type == DRM_MODE_CONNECTOR_DVII)
+                                       return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
+                               else
+                                       return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
+                       } else {
+                               if (connector_type == DRM_MODE_CONNECTOR_DVII)
+                                       return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
+                               else
+                                       return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
+                       }
+               } else
+                       return supported_devices_connector_object_id_convert
+                               [connector_type];
        } else {
                return supported_devices_connector_object_id_convert
                        [connector_type];
@@ -672,7 +681,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
        int i, j, max_device;
        struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE];
 
-       atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
+       if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
+               return false;
 
        supported_devices =
            (union atom_supported_devices *)(ctx->bios + data_offset);
@@ -865,14 +875,11 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
        struct radeon_pll *mpll = &rdev->clock.mpll;
        uint16_t data_offset;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
-                              &crev, &data_offset);
-
-       firmware_info =
-           (union firmware_info *)(mode_info->atom_context->bios +
-                                   data_offset);
-
-       if (firmware_info) {
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               firmware_info =
+                       (union firmware_info *)(mode_info->atom_context->bios +
+                                               data_offset);
                /* pixel clocks */
                p1pll->reference_freq =
                    le16_to_cpu(firmware_info->info.usReferenceClock);
@@ -887,6 +894,20 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
                p1pll->pll_out_max =
                    le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
 
+               if (crev >= 4) {
+                       p1pll->lcd_pll_out_min =
+                               le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
+                       if (p1pll->lcd_pll_out_min == 0)
+                               p1pll->lcd_pll_out_min = p1pll->pll_out_min;
+                       p1pll->lcd_pll_out_max =
+                               le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
+                       if (p1pll->lcd_pll_out_max == 0)
+                               p1pll->lcd_pll_out_max = p1pll->pll_out_max;
+               } else {
+                       p1pll->lcd_pll_out_min = p1pll->pll_out_min;
+                       p1pll->lcd_pll_out_max = p1pll->pll_out_max;
+               }
+
                if (p1pll->pll_out_min == 0) {
                        if (ASIC_IS_AVIVO(rdev))
                                p1pll->pll_out_min = 64800;
@@ -992,13 +1013,10 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev)
        u8 frev, crev;
        u16 data_offset;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
-                              &crev, &data_offset);
-
-       igp_info = (union igp_info *)(mode_info->atom_context->bios +
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               igp_info = (union igp_info *)(mode_info->atom_context->bios +
                                      data_offset);
-
-       if (igp_info) {
                switch (crev) {
                case 1:
                        if (igp_info->info.ucMemoryType & 0xf0)
@@ -1029,14 +1047,12 @@ bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
        uint16_t maxfreq;
        int i;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
-                              &crev, &data_offset);
-
-       tmds_info =
-           (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
-                                      data_offset);
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               tmds_info =
+                       (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
+                                                  data_offset);
 
-       if (tmds_info) {
                maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
                for (i = 0; i < 4; i++) {
                        tmds->tmds_pll[i].freq =
@@ -1085,13 +1101,11 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
        if (id > ATOM_MAX_SS_ENTRY)
                return NULL;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
-                              &crev, &data_offset);
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               ss_info =
+                       (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
 
-       ss_info =
-           (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
-
-       if (ss_info) {
                ss =
                    kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL);
 
@@ -1114,30 +1128,6 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
        return ss;
 }
 
-static void radeon_atom_apply_lvds_quirks(struct drm_device *dev,
-                                         struct radeon_encoder_atom_dig *lvds)
-{
-
-       /* Toshiba A300-1BU laptop panel doesn't like new pll divider algo */
-       if ((dev->pdev->device == 0x95c4) &&
-           (dev->pdev->subsystem_vendor == 0x1179) &&
-           (dev->pdev->subsystem_device == 0xff50)) {
-               if ((lvds->native_mode.hdisplay == 1280) &&
-                   (lvds->native_mode.vdisplay == 800))
-                       lvds->pll_algo = PLL_ALGO_LEGACY;
-       }
-
-       /* Dell Studio 15 laptop panel doesn't like new pll divider algo */
-       if ((dev->pdev->device == 0x95c4) &&
-           (dev->pdev->subsystem_vendor == 0x1028) &&
-           (dev->pdev->subsystem_device == 0x029f)) {
-               if ((lvds->native_mode.hdisplay == 1280) &&
-                   (lvds->native_mode.vdisplay == 800))
-                       lvds->pll_algo = PLL_ALGO_LEGACY;
-       }
-
-}
-
 union lvds_info {
        struct _ATOM_LVDS_INFO info;
        struct _ATOM_LVDS_INFO_V12 info_12;
@@ -1156,13 +1146,10 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
        uint8_t frev, crev;
        struct radeon_encoder_atom_dig *lvds = NULL;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
-                              &crev, &data_offset);
-
-       lvds_info =
-           (union lvds_info *)(mode_info->atom_context->bios + data_offset);
-
-       if (lvds_info) {
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               lvds_info =
+                       (union lvds_info *)(mode_info->atom_context->bios + data_offset);
                lvds =
                    kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
 
@@ -1220,9 +1207,6 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
                                lvds->pll_algo = PLL_ALGO_LEGACY;
                }
 
-               /* LVDS quirks */
-               radeon_atom_apply_lvds_quirks(dev, lvds);
-
                encoder->native_mode = lvds->native_mode;
        }
        return lvds;
@@ -1241,11 +1225,11 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
        uint8_t bg, dac;
        struct radeon_encoder_primary_dac *p_dac = NULL;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
-
-       dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               dac_info = (struct _COMPASSIONATE_DATA *)
+                       (mode_info->atom_context->bios + data_offset);
 
-       if (dac_info) {
                p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL);
 
                if (!p_dac)
@@ -1270,7 +1254,9 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
        u8 frev, crev;
        u16 data_offset, misc;
 
-       atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset);
+       if (!atom_parse_data_header(mode_info->atom_context, data_index, NULL,
+                                   &frev, &crev, &data_offset))
+               return false;
 
        switch (crev) {
        case 1:
@@ -1362,47 +1348,50 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev)
        struct _ATOM_ANALOG_TV_INFO *tv_info;
        enum radeon_tv_std tv_std = TV_STD_NTSC;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
 
-       tv_info = (struct _ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
+               tv_info = (struct _ATOM_ANALOG_TV_INFO *)
+                       (mode_info->atom_context->bios + data_offset);
 
-       switch (tv_info->ucTV_BootUpDefaultStandard) {
-       case ATOM_TV_NTSC:
-               tv_std = TV_STD_NTSC;
-               DRM_INFO("Default TV standard: NTSC\n");
-               break;
-       case ATOM_TV_NTSCJ:
-               tv_std = TV_STD_NTSC_J;
-               DRM_INFO("Default TV standard: NTSC-J\n");
-               break;
-       case ATOM_TV_PAL:
-               tv_std = TV_STD_PAL;
-               DRM_INFO("Default TV standard: PAL\n");
-               break;
-       case ATOM_TV_PALM:
-               tv_std = TV_STD_PAL_M;
-               DRM_INFO("Default TV standard: PAL-M\n");
-               break;
-       case ATOM_TV_PALN:
-               tv_std = TV_STD_PAL_N;
-               DRM_INFO("Default TV standard: PAL-N\n");
-               break;
-       case ATOM_TV_PALCN:
-               tv_std = TV_STD_PAL_CN;
-               DRM_INFO("Default TV standard: PAL-CN\n");
-               break;
-       case ATOM_TV_PAL60:
-               tv_std = TV_STD_PAL_60;
-               DRM_INFO("Default TV standard: PAL-60\n");
-               break;
-       case ATOM_TV_SECAM:
-               tv_std = TV_STD_SECAM;
-               DRM_INFO("Default TV standard: SECAM\n");
-               break;
-       default:
-               tv_std = TV_STD_NTSC;
-               DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
-               break;
+               switch (tv_info->ucTV_BootUpDefaultStandard) {
+               case ATOM_TV_NTSC:
+                       tv_std = TV_STD_NTSC;
+                       DRM_INFO("Default TV standard: NTSC\n");
+                       break;
+               case ATOM_TV_NTSCJ:
+                       tv_std = TV_STD_NTSC_J;
+                       DRM_INFO("Default TV standard: NTSC-J\n");
+                       break;
+               case ATOM_TV_PAL:
+                       tv_std = TV_STD_PAL;
+                       DRM_INFO("Default TV standard: PAL\n");
+                       break;
+               case ATOM_TV_PALM:
+                       tv_std = TV_STD_PAL_M;
+                       DRM_INFO("Default TV standard: PAL-M\n");
+                       break;
+               case ATOM_TV_PALN:
+                       tv_std = TV_STD_PAL_N;
+                       DRM_INFO("Default TV standard: PAL-N\n");
+                       break;
+               case ATOM_TV_PALCN:
+                       tv_std = TV_STD_PAL_CN;
+                       DRM_INFO("Default TV standard: PAL-CN\n");
+                       break;
+               case ATOM_TV_PAL60:
+                       tv_std = TV_STD_PAL_60;
+                       DRM_INFO("Default TV standard: PAL-60\n");
+                       break;
+               case ATOM_TV_SECAM:
+                       tv_std = TV_STD_SECAM;
+                       DRM_INFO("Default TV standard: SECAM\n");
+                       break;
+               default:
+                       tv_std = TV_STD_NTSC;
+                       DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
+                       break;
+               }
        }
        return tv_std;
 }
@@ -1420,11 +1409,12 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
        uint8_t bg, dac;
        struct radeon_encoder_tv_dac *tv_dac = NULL;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
 
-       dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
+               dac_info = (struct _COMPASSIONATE_DATA *)
+                       (mode_info->atom_context->bios + data_offset);
 
-       if (dac_info) {
                tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
 
                if (!tv_dac)
@@ -1447,6 +1437,30 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
        return tv_dac;
 }
 
+static const char *thermal_controller_names[] = {
+       "NONE",
+       "LM63",
+       "ADM1032",
+       "ADM1030",
+       "MUA6649",
+       "LM64",
+       "F75375",
+       "ASC7512",
+};
+
+static const char *pp_lib_thermal_controller_names[] = {
+       "NONE",
+       "LM63",
+       "ADM1032",
+       "ADM1030",
+       "MUA6649",
+       "LM64",
+       "F75375",
+       "RV6xx",
+       "RV770",
+       "ADT7473",
+};
+
 union power_info {
        struct _ATOM_POWERPLAY_INFO info;
        struct _ATOM_POWERPLAY_INFO_V2 info_2;
@@ -1466,15 +1480,22 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
        struct _ATOM_PPLIB_STATE *power_state;
        int num_modes = 0, i, j;
        int state_index = 0, mode_index = 0;
-
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
-
-       power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
+       struct radeon_i2c_bus_rec i2c_bus;
 
        rdev->pm.default_power_state = NULL;
 
-       if (power_info) {
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
                if (frev < 4) {
+                       /* add the i2c bus for thermal/fan chip */
+                       if (power_info->info.ucOverdriveThermalController > 0) {
+                               DRM_INFO("Possible %s thermal controller at 0x%02x\n",
+                                        thermal_controller_names[power_info->info.ucOverdriveThermalController],
+                                        power_info->info.ucOverdriveControllerAddress >> 1);
+                               i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
+                               rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal");
+                       }
                        num_modes = power_info->info.ucNumOfPowerModeEntries;
                        if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
                                num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
@@ -1684,6 +1705,24 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                }
                        }
                } else if (frev == 4) {
+                       /* add the i2c bus for thermal/fan chip */
+                       /* no support for internal controller yet */
+                       if (power_info->info_4.sThermalController.ucType > 0) {
+                               if ((power_info->info_4.sThermalController.ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) ||
+                                   (power_info->info_4.sThermalController.ucType == ATOM_PP_THERMALCONTROLLER_RV770)) {
+                                       DRM_INFO("Internal thermal controller %s fan control\n",
+                                                (power_info->info_4.sThermalController.ucFanParameters &
+                                                 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+                               } else {
+                                       DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
+                                                pp_lib_thermal_controller_names[power_info->info_4.sThermalController.ucType],
+                                                power_info->info_4.sThermalController.ucI2cAddress >> 1,
+                                                (power_info->info_4.sThermalController.ucFanParameters &
+                                                 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+                                       i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info_4.sThermalController.ucI2cLine);
+                                       rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal");
+                               }
+                       }
                        for (i = 0; i < power_info->info_4.ucNumStates; i++) {
                                mode_index = 0;
                                power_state = (struct _ATOM_PPLIB_STATE *)
index e9ea38ece37558a6bf123b18a982b06ec252872a..2becdeda68a34ae4d94d8102f33d0d87fe6de959 100644 (file)
@@ -531,10 +531,7 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
        case CHIP_RS300:
                switch (ddc_line) {
                case RADEON_GPIO_DVI_DDC:
-                       /* in theory this should be hw capable,
-                        * but it doesn't seem to work
-                        */
-                       i2c.hw_capable = false;
+                       i2c.hw_capable = true;
                        break;
                default:
                        i2c.hw_capable = false;
@@ -633,6 +630,8 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)
                p1pll->reference_div = RBIOS16(pll_info + 0x10);
                p1pll->pll_out_min = RBIOS32(pll_info + 0x12);
                p1pll->pll_out_max = RBIOS32(pll_info + 0x16);
+               p1pll->lcd_pll_out_min = p1pll->pll_out_min;
+               p1pll->lcd_pll_out_max = p1pll->pll_out_max;
 
                if (rev > 9) {
                        p1pll->pll_in_min = RBIOS32(pll_info + 0x36);
index ee0083f982d8ba2a926688e083ea930716e0de91..60d59816b94ff6a4d94784482d2d613a88c56543 100644 (file)
@@ -940,7 +940,7 @@ static void radeon_dp_connector_destroy(struct drm_connector *connector)
        if (radeon_connector->edid)
                kfree(radeon_connector->edid);
        if (radeon_dig_connector->dp_i2c_bus)
-               radeon_i2c_destroy_dp(radeon_dig_connector->dp_i2c_bus);
+               radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus);
        kfree(radeon_connector->con_priv);
        drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
index 70ba02ed77237ba31299a7cbc56694dc3e62d57a..f9b0fe002c0ab7f27430a697f95a841667281e41 100644 (file)
@@ -193,9 +193,11 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
                radeon_bo_list_fence(&parser->validated, parser->ib->fence);
        }
        radeon_bo_list_unreserve(&parser->validated);
-       for (i = 0; i < parser->nrelocs; i++) {
-               if (parser->relocs[i].gobj)
-                       drm_gem_object_unreference_unlocked(parser->relocs[i].gobj);
+       if (parser->relocs != NULL) {
+               for (i = 0; i < parser->nrelocs; i++) {
+                       if (parser->relocs[i].gobj)
+                               drm_gem_object_unreference_unlocked(parser->relocs[i].gobj);
+               }
        }
        kfree(parser->track);
        kfree(parser->relocs);
@@ -243,7 +245,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        }
        r = radeon_cs_parser_relocs(&parser);
        if (r) {
-               DRM_ERROR("Failed to parse relocation !\n");
+               if (r != -ERESTARTSYS)
+                       DRM_ERROR("Failed to parse relocation %d!\n", r);
                radeon_cs_parser_fini(&parser, r);
                mutex_unlock(&rdev->cs_mutex);
                return r;
index e28e4ed5f720d5340c1e23595ca099d1559273c0..60ec47b7164212f911f8029053de9f889ce0cceb 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/vga_switcheroo.h>
 #include "radeon_reg.h"
 #include "radeon.h"
-#include "radeon_asic.h"
 #include "atom.h"
 
 /*
@@ -242,6 +241,36 @@ bool radeon_card_posted(struct radeon_device *rdev)
 
 }
 
+void radeon_update_bandwidth_info(struct radeon_device *rdev)
+{
+       fixed20_12 a;
+       u32 sclk, mclk;
+
+       if (rdev->flags & RADEON_IS_IGP) {
+               sclk = radeon_get_engine_clock(rdev);
+               mclk = rdev->clock.default_mclk;
+
+               a.full = rfixed_const(100);
+               rdev->pm.sclk.full = rfixed_const(sclk);
+               rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+               rdev->pm.mclk.full = rfixed_const(mclk);
+               rdev->pm.mclk.full = rfixed_div(rdev->pm.mclk, a);
+
+               a.full = rfixed_const(16);
+               /* core_bandwidth = sclk(Mhz) * 16 */
+               rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a);
+       } else {
+               sclk = radeon_get_engine_clock(rdev);
+               mclk = radeon_get_memory_clock(rdev);
+
+               a.full = rfixed_const(100);
+               rdev->pm.sclk.full = rfixed_const(sclk);
+               rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+               rdev->pm.mclk.full = rfixed_const(mclk);
+               rdev->pm.mclk.full = rfixed_div(rdev->pm.mclk, a);
+       }
+}
+
 bool radeon_boot_test_post_card(struct radeon_device *rdev)
 {
        if (radeon_card_posted(rdev))
@@ -288,181 +317,6 @@ void radeon_dummy_page_fini(struct radeon_device *rdev)
 }
 
 
-/*
- * Registers accessors functions.
- */
-uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg)
-{
-       DRM_ERROR("Invalid callback to read register 0x%04X\n", reg);
-       BUG_ON(1);
-       return 0;
-}
-
-void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
-{
-       DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n",
-                 reg, v);
-       BUG_ON(1);
-}
-
-void radeon_register_accessor_init(struct radeon_device *rdev)
-{
-       rdev->mc_rreg = &radeon_invalid_rreg;
-       rdev->mc_wreg = &radeon_invalid_wreg;
-       rdev->pll_rreg = &radeon_invalid_rreg;
-       rdev->pll_wreg = &radeon_invalid_wreg;
-       rdev->pciep_rreg = &radeon_invalid_rreg;
-       rdev->pciep_wreg = &radeon_invalid_wreg;
-
-       /* Don't change order as we are overridding accessor. */
-       if (rdev->family < CHIP_RV515) {
-               rdev->pcie_reg_mask = 0xff;
-       } else {
-               rdev->pcie_reg_mask = 0x7ff;
-       }
-       /* FIXME: not sure here */
-       if (rdev->family <= CHIP_R580) {
-               rdev->pll_rreg = &r100_pll_rreg;
-               rdev->pll_wreg = &r100_pll_wreg;
-       }
-       if (rdev->family >= CHIP_R420) {
-               rdev->mc_rreg = &r420_mc_rreg;
-               rdev->mc_wreg = &r420_mc_wreg;
-       }
-       if (rdev->family >= CHIP_RV515) {
-               rdev->mc_rreg = &rv515_mc_rreg;
-               rdev->mc_wreg = &rv515_mc_wreg;
-       }
-       if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) {
-               rdev->mc_rreg = &rs400_mc_rreg;
-               rdev->mc_wreg = &rs400_mc_wreg;
-       }
-       if (rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
-               rdev->mc_rreg = &rs690_mc_rreg;
-               rdev->mc_wreg = &rs690_mc_wreg;
-       }
-       if (rdev->family == CHIP_RS600) {
-               rdev->mc_rreg = &rs600_mc_rreg;
-               rdev->mc_wreg = &rs600_mc_wreg;
-       }
-       if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_RV740)) {
-               rdev->pciep_rreg = &r600_pciep_rreg;
-               rdev->pciep_wreg = &r600_pciep_wreg;
-       }
-}
-
-
-/*
- * ASIC
- */
-int radeon_asic_init(struct radeon_device *rdev)
-{
-       radeon_register_accessor_init(rdev);
-       switch (rdev->family) {
-       case CHIP_R100:
-       case CHIP_RV100:
-       case CHIP_RS100:
-       case CHIP_RV200:
-       case CHIP_RS200:
-               rdev->asic = &r100_asic;
-               break;
-       case CHIP_R200:
-       case CHIP_RV250:
-       case CHIP_RS300:
-       case CHIP_RV280:
-               rdev->asic = &r200_asic;
-               break;
-       case CHIP_R300:
-       case CHIP_R350:
-       case CHIP_RV350:
-       case CHIP_RV380:
-               if (rdev->flags & RADEON_IS_PCIE)
-                       rdev->asic = &r300_asic_pcie;
-               else
-                       rdev->asic = &r300_asic;
-               break;
-       case CHIP_R420:
-       case CHIP_R423:
-       case CHIP_RV410:
-               rdev->asic = &r420_asic;
-               break;
-       case CHIP_RS400:
-       case CHIP_RS480:
-               rdev->asic = &rs400_asic;
-               break;
-       case CHIP_RS600:
-               rdev->asic = &rs600_asic;
-               break;
-       case CHIP_RS690:
-       case CHIP_RS740:
-               rdev->asic = &rs690_asic;
-               break;
-       case CHIP_RV515:
-               rdev->asic = &rv515_asic;
-               break;
-       case CHIP_R520:
-       case CHIP_RV530:
-       case CHIP_RV560:
-       case CHIP_RV570:
-       case CHIP_R580:
-               rdev->asic = &r520_asic;
-               break;
-       case CHIP_R600:
-       case CHIP_RV610:
-       case CHIP_RV630:
-       case CHIP_RV620:
-       case CHIP_RV635:
-       case CHIP_RV670:
-       case CHIP_RS780:
-       case CHIP_RS880:
-               rdev->asic = &r600_asic;
-               break;
-       case CHIP_RV770:
-       case CHIP_RV730:
-       case CHIP_RV710:
-       case CHIP_RV740:
-               rdev->asic = &rv770_asic;
-               break;
-       case CHIP_CEDAR:
-       case CHIP_REDWOOD:
-       case CHIP_JUNIPER:
-       case CHIP_CYPRESS:
-       case CHIP_HEMLOCK:
-               rdev->asic = &evergreen_asic;
-               break;
-       default:
-               /* FIXME: not supported yet */
-               return -EINVAL;
-       }
-
-       if (rdev->flags & RADEON_IS_IGP) {
-               rdev->asic->get_memory_clock = NULL;
-               rdev->asic->set_memory_clock = NULL;
-       }
-
-       return 0;
-}
-
-
-/*
- * Wrapper around modesetting bits.
- */
-int radeon_clocks_init(struct radeon_device *rdev)
-{
-       int r;
-
-       r = radeon_static_clocks_init(rdev->ddev);
-       if (r) {
-               return r;
-       }
-       DRM_INFO("Clocks initialized !\n");
-       return 0;
-}
-
-void radeon_clocks_fini(struct radeon_device *rdev)
-{
-}
-
 /* ATOM accessor methods */
 static uint32_t cail_pll_read(struct card_info *info, uint32_t reg)
 {
@@ -567,29 +421,6 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
                return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }
 
-void radeon_agp_disable(struct radeon_device *rdev)
-{
-       rdev->flags &= ~RADEON_IS_AGP;
-       if (rdev->family >= CHIP_R600) {
-               DRM_INFO("Forcing AGP to PCIE mode\n");
-               rdev->flags |= RADEON_IS_PCIE;
-       } else if (rdev->family >= CHIP_RV515 ||
-                       rdev->family == CHIP_RV380 ||
-                       rdev->family == CHIP_RV410 ||
-                       rdev->family == CHIP_R423) {
-               DRM_INFO("Forcing AGP to PCIE mode\n");
-               rdev->flags |= RADEON_IS_PCIE;
-               rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
-               rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
-       } else {
-               DRM_INFO("Forcing AGP to PCI mode\n");
-               rdev->flags |= RADEON_IS_PCI;
-               rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
-               rdev->asic->gart_set_page = &r100_pci_gart_set_page;
-       }
-       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
-}
-
 void radeon_check_arguments(struct radeon_device *rdev)
 {
        /* vramlimit must be a power of two */
@@ -731,6 +562,14 @@ int radeon_device_init(struct radeon_device *rdev,
                return r;
        radeon_check_arguments(rdev);
 
+       /* all of the newer IGP chips have an internal gart
+        * However some rs4xx report as AGP, so remove that here.
+        */
+       if ((rdev->family >= CHIP_RS400) &&
+           (rdev->flags & RADEON_IS_IGP)) {
+               rdev->flags &= ~RADEON_IS_AGP;
+       }
+
        if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) {
                radeon_agp_disable(rdev);
        }
index ba8d806dcf3939fe91285820793e7b733ffb0541..b8d6728282468c09e56640807c2d8464bdcb5033 100644 (file)
@@ -368,10 +368,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
 
        if (rdev->bios) {
                if (rdev->is_atom_bios) {
-                       if (rdev->family >= CHIP_R600)
+                       ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
+                       if (ret == false)
                                ret = radeon_get_atom_connector_info_from_object_table(dev);
-                       else
-                               ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
                } else {
                        ret = radeon_get_legacy_connector_info_from_bios(dev);
                        if (ret == false)
@@ -469,10 +468,19 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll,
        uint32_t best_error = 0xffffffff;
        uint32_t best_vco_diff = 1;
        uint32_t post_div;
+       u32 pll_out_min, pll_out_max;
 
        DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div);
        freq = freq * 1000;
 
+       if (pll->flags & RADEON_PLL_IS_LCD) {
+               pll_out_min = pll->lcd_pll_out_min;
+               pll_out_max = pll->lcd_pll_out_max;
+       } else {
+               pll_out_min = pll->pll_out_min;
+               pll_out_max = pll->pll_out_max;
+       }
+
        if (pll->flags & RADEON_PLL_USE_REF_DIV)
                min_ref_div = max_ref_div = pll->reference_div;
        else {
@@ -536,10 +544,10 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll,
                                tmp = (uint64_t)pll->reference_freq * feedback_div;
                                vco = radeon_div(tmp, ref_div);
 
-                               if (vco < pll->pll_out_min) {
+                               if (vco < pll_out_min) {
                                        min_feed_div = feedback_div + 1;
                                        continue;
-                               } else if (vco > pll->pll_out_max) {
+                               } else if (vco > pll_out_max) {
                                        max_feed_div = feedback_div;
                                        continue;
                                }
@@ -675,6 +683,15 @@ calc_fb_ref_div(struct radeon_pll *pll,
 {
        fixed20_12 ffreq, max_error, error, pll_out, a;
        u32 vco;
+       u32 pll_out_min, pll_out_max;
+
+       if (pll->flags & RADEON_PLL_IS_LCD) {
+               pll_out_min = pll->lcd_pll_out_min;
+               pll_out_max = pll->lcd_pll_out_max;
+       } else {
+               pll_out_min = pll->pll_out_min;
+               pll_out_max = pll->pll_out_max;
+       }
 
        ffreq.full = rfixed_const(freq);
        /* max_error = ffreq * 0.0025; */
@@ -686,7 +703,7 @@ calc_fb_ref_div(struct radeon_pll *pll,
                        vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac));
                        vco = vco / ((*ref_div) * 10);
 
-                       if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max))
+                       if ((vco < pll_out_min) || (vco > pll_out_max))
                                continue;
 
                        /* pll_out = vco / post_div; */
@@ -714,6 +731,15 @@ static void radeon_compute_pll_new(struct radeon_pll *pll,
 {
        u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0;
        u32 best_freq = 0, vco_frequency;
+       u32 pll_out_min, pll_out_max;
+
+       if (pll->flags & RADEON_PLL_IS_LCD) {
+               pll_out_min = pll->lcd_pll_out_min;
+               pll_out_max = pll->lcd_pll_out_max;
+       } else {
+               pll_out_min = pll->pll_out_min;
+               pll_out_max = pll->pll_out_max;
+       }
 
        /* freq = freq / 10; */
        do_div(freq, 10);
@@ -724,7 +750,7 @@ static void radeon_compute_pll_new(struct radeon_pll *pll,
                        goto done;
 
                vco_frequency = freq * post_div;
-               if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
+               if ((vco_frequency < pll_out_min) || (vco_frequency > pll_out_max))
                        goto done;
 
                if (pll->flags & RADEON_PLL_USE_REF_DIV) {
@@ -749,7 +775,7 @@ static void radeon_compute_pll_new(struct radeon_pll *pll,
                                continue;
 
                        vco_frequency = freq * post_div;
-                       if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
+                       if ((vco_frequency < pll_out_min) || (vco_frequency > pll_out_max))
                                continue;
                        if (pll->flags & RADEON_PLL_USE_REF_DIV) {
                                ref_div = pll->reference_div;
@@ -945,6 +971,23 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
        return 0;
 }
 
+void radeon_update_display_priority(struct radeon_device *rdev)
+{
+       /* adjustment options for the display watermarks */
+       if ((radeon_disp_priority == 0) || (radeon_disp_priority > 2)) {
+               /* set display priority to high for r3xx, rv515 chips
+                * this avoids flickering due to underflow to the
+                * display controllers during heavy acceleration.
+                */
+               if (ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV515))
+                       rdev->disp_priority = 2;
+               else
+                       rdev->disp_priority = 0;
+       } else
+               rdev->disp_priority = radeon_disp_priority;
+
+}
+
 int radeon_modeset_init(struct radeon_device *rdev)
 {
        int i;
@@ -976,15 +1019,6 @@ int radeon_modeset_init(struct radeon_device *rdev)
                radeon_combios_check_hardcoded_edid(rdev);
        }
 
-       if (rdev->flags & RADEON_SINGLE_CRTC)
-               rdev->num_crtc = 1;
-       else {
-               if (ASIC_IS_DCE4(rdev))
-                       rdev->num_crtc = 6;
-               else
-                       rdev->num_crtc = 2;
-       }
-
        /* allocate crtcs */
        for (i = 0; i < rdev->num_crtc; i++) {
                radeon_crtc_init(rdev->ddev, i);
index 6eec0ece6a6ccd6d14e9ae05a2fee63d0879ce41..055a51732dcb7b76a100d79ee2b642de9cc9eefe 100644 (file)
  * KMS wrapper.
  * - 2.0.0 - initial interface
  * - 2.1.0 - add square tiling interface
+ * - 2.2.0 - add r6xx/r7xx const buffer support
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       1
+#define KMS_DRIVER_MINOR       2
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -91,6 +92,8 @@ int radeon_tv = 1;
 int radeon_new_pll = -1;
 int radeon_dynpm = -1;
 int radeon_audio = 1;
+int radeon_disp_priority = 0;
+int radeon_hw_i2c = 0;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -134,6 +137,12 @@ module_param_named(dynpm, radeon_dynpm, int, 0444);
 MODULE_PARM_DESC(audio, "Audio enable (0 = disable)");
 module_param_named(audio, radeon_audio, int, 0444);
 
+MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)");
+module_param_named(disp_priority, radeon_disp_priority, int, 0444);
+
+MODULE_PARM_DESC(hw_i2c, "hw i2c engine enable (0 = disable)");
+module_param_named(hw_i2c, radeon_hw_i2c, int, 0444);
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
index ec55f2b23c2298f39d7b108d183bf52a59ddad34..448eba89d1e62e2dec8089480e951086c7caa2f6 100644 (file)
  * 1.30- Add support for occlusion queries
  * 1.31- Add support for num Z pipes from GET_PARAM
  * 1.32- fixes for rv740 setup
+ * 1.33- Add r6xx/r7xx const buffer support
  */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           32
+#define DRIVER_MINOR           33
 #define DRIVER_PATCHLEVEL      0
 
 enum radeon_cp_microcode_version {
index bc926ea0a530e014c2b075fed8ac35e0a94d04ae..52d6f96f274b2722ec0617cf5420ced519514442 100644 (file)
@@ -302,7 +302,7 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
        }
 
        if (ASIC_IS_DCE3(rdev) &&
-           (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT))) {
+           (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) {
                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
                radeon_dp_set_link_config(connector, mode);
        }
@@ -519,7 +519,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
                break;
        }
 
-       atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
 
        switch (frev) {
        case 1:
@@ -593,7 +594,6 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
        }
 
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-       r600_hdmi_enable(encoder, hdmi_detected);
 }
 
 int
@@ -708,7 +708,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
        struct radeon_connector_atom_dig *dig_connector =
                radeon_get_atom_connector_priv_from_encoder(encoder);
        union dig_encoder_control args;
-       int index = 0, num = 0;
+       int index = 0;
        uint8_t frev, crev;
 
        if (!dig || !dig_connector)
@@ -724,9 +724,9 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
                else
                        index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
        }
-       num = dig->dig_encoder + 1;
 
-       atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
 
        args.v1.ucAction = action;
        args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
@@ -785,7 +785,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
        struct drm_connector *connector;
        struct radeon_connector *radeon_connector;
        union dig_transmitter_control args;
-       int index = 0, num = 0;
+       int index = 0;
        uint8_t frev, crev;
        bool is_dp = false;
        int pll_id = 0;
@@ -814,7 +814,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                }
        }
 
-       atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
 
        args.v1.ucAction = action;
        if (action == ATOM_TRANSMITTER_ACTION_INIT) {
@@ -860,15 +861,12 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                switch (radeon_encoder->encoder_id) {
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
                        args.v3.acConfig.ucTransmitterSel = 0;
-                       num = 0;
                        break;
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
                        args.v3.acConfig.ucTransmitterSel = 1;
-                       num = 1;
                        break;
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
                        args.v3.acConfig.ucTransmitterSel = 2;
-                       num = 2;
                        break;
                }
 
@@ -879,23 +877,19 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                                args.v3.acConfig.fCoherentMode = 1;
                }
        } else if (ASIC_IS_DCE32(rdev)) {
-               if (dig->dig_encoder == 1)
-                       args.v2.acConfig.ucEncoderSel = 1;
+               args.v2.acConfig.ucEncoderSel = dig->dig_encoder;
                if (dig_connector->linkb)
                        args.v2.acConfig.ucLinkSel = 1;
 
                switch (radeon_encoder->encoder_id) {
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
                        args.v2.acConfig.ucTransmitterSel = 0;
-                       num = 0;
                        break;
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
                        args.v2.acConfig.ucTransmitterSel = 1;
-                       num = 1;
                        break;
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
                        args.v2.acConfig.ucTransmitterSel = 2;
-                       num = 2;
                        break;
                }
 
@@ -913,31 +907,25 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                else
                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
 
-               switch (radeon_encoder->encoder_id) {
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-                       if (rdev->flags & RADEON_IS_IGP) {
-                               if (radeon_encoder->pixel_clock > 165000) {
-                                       if (dig_connector->igp_lane_info & 0x3)
-                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
-                                       else if (dig_connector->igp_lane_info & 0xc)
-                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
-                               } else {
-                                       if (dig_connector->igp_lane_info & 0x1)
-                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-                                       else if (dig_connector->igp_lane_info & 0x2)
-                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
-                                       else if (dig_connector->igp_lane_info & 0x4)
-                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
-                                       else if (dig_connector->igp_lane_info & 0x8)
-                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
-                               }
+               if ((rdev->flags & RADEON_IS_IGP) &&
+                   (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
+                       if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
+                               if (dig_connector->igp_lane_info & 0x1)
+                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
+                               else if (dig_connector->igp_lane_info & 0x2)
+                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
+                               else if (dig_connector->igp_lane_info & 0x4)
+                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
+                               else if (dig_connector->igp_lane_info & 0x8)
+                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
+                       } else {
+                               if (dig_connector->igp_lane_info & 0x3)
+                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
+                               else if (dig_connector->igp_lane_info & 0xc)
+                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
                        }
-                       break;
                }
 
-               if (radeon_encoder->pixel_clock > 165000)
-                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
-
                if (dig_connector->linkb)
                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
                else
@@ -948,6 +936,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
                        if (dig->coherent_mode)
                                args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+                       if (radeon_encoder->pixel_clock > 165000)
+                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
                }
        }
 
@@ -1054,16 +1044,25 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        if (is_dig) {
                switch (mode) {
                case DRM_MODE_DPMS_ON:
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
-                       {
+                       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
                                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+
                                dp_link_train(encoder, connector);
+                               if (ASIC_IS_DCE4(rdev))
+                                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON);
                        }
+                       if (!ASIC_IS_DCE4(rdev))
+                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                        break;
                case DRM_MODE_DPMS_STANDBY:
                case DRM_MODE_DPMS_SUSPEND:
                case DRM_MODE_DPMS_OFF:
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+                       if (!ASIC_IS_DCE4(rdev))
+                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+                       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
+                               if (ASIC_IS_DCE4(rdev))
+                                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF);
+                       }
                        break;
                }
        } else {
@@ -1104,7 +1103,8 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
 
        memset(&args, 0, sizeof(args));
 
-       atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
 
        switch (frev) {
        case 1:
@@ -1216,6 +1216,9 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
        }
 
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+       /* update scratch regs with new routing */
+       radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
 }
 
 static void
@@ -1326,19 +1329,9 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
 
-       if (radeon_encoder->active_device &
-           (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
-               struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-               if (dig)
-                       dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
-       }
        radeon_encoder->pixel_clock = adjusted_mode->clock;
 
-       radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
-       atombios_set_encoder_crtc_source(encoder);
-
        if (ASIC_IS_AVIVO(rdev)) {
                if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
                        atombios_yuv_setup(encoder, true);
@@ -1396,9 +1389,10 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
        }
        atombios_apply_encoder_quirks(encoder, adjusted_mode);
 
-       /* XXX */
-       if (!ASIC_IS_DCE4(rdev))
+       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
+               r600_hdmi_enable(encoder);
                r600_hdmi_setmode(encoder, adjusted_mode);
+       }
 }
 
 static bool
@@ -1418,7 +1412,8 @@ atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *conn
 
                memset(&args, 0, sizeof(args));
 
-               atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
+               if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+                       return false;
 
                args.sDacload.ucMisc = 0;
 
@@ -1492,8 +1487,20 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec
 
 static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
 {
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+       if (radeon_encoder->active_device &
+           (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
+               struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+               if (dig)
+                       dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
+       }
+
        radeon_atom_output_lock(encoder, true);
        radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
+       /* this is needed for the pll/ss setup to work correctly in some cases */
+       atombios_set_encoder_crtc_source(encoder);
 }
 
 static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
@@ -1509,6 +1516,8 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
        radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
 
        if (radeon_encoder_is_digital(encoder)) {
+               if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
+                       r600_hdmi_disable(encoder);
                dig = radeon_encoder->enc_priv;
                dig->dig_encoder = -1;
        }
@@ -1659,6 +1668,4 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
                drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
                break;
        }
-
-       r600_hdmi_init(encoder);
 }
index 4ae50c19589fe8b4e4f89304862515416cbe72c5..5def6f5dff38c1f7dfb0357aa5f9f8cc2583576a 100644 (file)
@@ -59,6 +59,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
        return false;
 }
 
+/* bit banging i2c */
 
 static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
 {
@@ -181,13 +182,30 @@ static void set_data(void *i2c_priv, int data)
        WREG32(rec->en_data_reg, val);
 }
 
+static int pre_xfer(struct i2c_adapter *i2c_adap)
+{
+       struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+
+       radeon_i2c_do_lock(i2c, 1);
+
+       return 0;
+}
+
+static void post_xfer(struct i2c_adapter *i2c_adap)
+{
+       struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+
+       radeon_i2c_do_lock(i2c, 0);
+}
+
+/* hw i2c */
+
 static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
 {
-       struct radeon_pll *spll = &rdev->clock.spll;
        u32 sclk = radeon_get_engine_clock(rdev);
        u32 prescale = 0;
-       u32 nm;
-       u8 loop;
+       u32 nm;
+       u8 n, m, loop;
        int i2c_clock;
 
        switch (rdev->family) {
@@ -203,13 +221,15 @@ static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
        case CHIP_R300:
        case CHIP_R350:
        case CHIP_RV350:
-               n = (spll->reference_freq) / (4 * 6);
+               i2c_clock = 60;
+               nm = (sclk * 10) / (i2c_clock * 4);
                for (loop = 1; loop < 255; loop++) {
-                       if ((loop * (loop - 1)) > n)
+                       if ((nm / loop) < loop)
                                break;
                }
-               m = loop - 1;
-               prescale = m | (loop << 8);
+               n = loop - 1;
+               m = loop - 2;
+               prescale = m | (n << 8);
                break;
        case CHIP_RV380:
        case CHIP_RS400:
@@ -217,7 +237,6 @@ static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
        case CHIP_R420:
        case CHIP_R423:
        case CHIP_RV410:
-               sclk = radeon_get_engine_clock(rdev);
                prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
                break;
        case CHIP_RS600:
@@ -232,7 +251,6 @@ static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
        case CHIP_RV570:
        case CHIP_R580:
                i2c_clock = 50;
-               sclk = radeon_get_engine_clock(rdev);
                if (rdev->family == CHIP_R520)
                        prescale = (127 << 8) + ((sclk * 10) / (4 * 127 * i2c_clock));
                else
@@ -291,6 +309,7 @@ static int r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
        prescale = radeon_get_i2c_prescale(rdev);
 
        reg = ((prescale << RADEON_I2C_PRESCALE_SHIFT) |
+              RADEON_I2C_DRIVE_EN |
               RADEON_I2C_START |
               RADEON_I2C_STOP |
               RADEON_I2C_GO);
@@ -757,26 +776,13 @@ done:
        return ret;
 }
 
-static int radeon_sw_i2c_xfer(struct i2c_adapter *i2c_adap,
+static int radeon_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
                              struct i2c_msg *msgs, int num)
-{
-       struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
-       int ret;
-
-       radeon_i2c_do_lock(i2c, 1);
-       ret = i2c_transfer(&i2c->algo.radeon.bit_adapter, msgs, num);
-       radeon_i2c_do_lock(i2c, 0);
-
-       return ret;
-}
-
-static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
-                          struct i2c_msg *msgs, int num)
 {
        struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
        struct radeon_device *rdev = i2c->dev->dev_private;
        struct radeon_i2c_bus_rec *rec = &i2c->rec;
-       int ret;
+       int ret = 0;
 
        switch (rdev->family) {
        case CHIP_R100:
@@ -797,16 +803,12 @@ static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
        case CHIP_RV410:
        case CHIP_RS400:
        case CHIP_RS480:
-               if (rec->hw_capable)
-                       ret = r100_hw_i2c_xfer(i2c_adap, msgs, num);
-               else
-                       ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
+               ret = r100_hw_i2c_xfer(i2c_adap, msgs, num);
                break;
        case CHIP_RS600:
        case CHIP_RS690:
        case CHIP_RS740:
                /* XXX fill in hw i2c implementation */
-               ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
                break;
        case CHIP_RV515:
        case CHIP_R520:
@@ -814,20 +816,16 @@ static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
        case CHIP_RV560:
        case CHIP_RV570:
        case CHIP_R580:
-               if (rec->hw_capable) {
-                       if (rec->mm_i2c)
-                               ret = r100_hw_i2c_xfer(i2c_adap, msgs, num);
-                       else
-                               ret = r500_hw_i2c_xfer(i2c_adap, msgs, num);
-               } else
-                       ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
+               if (rec->mm_i2c)
+                       ret = r100_hw_i2c_xfer(i2c_adap, msgs, num);
+               else
+                       ret = r500_hw_i2c_xfer(i2c_adap, msgs, num);
                break;
        case CHIP_R600:
        case CHIP_RV610:
        case CHIP_RV630:
        case CHIP_RV670:
                /* XXX fill in hw i2c implementation */
-               ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
                break;
        case CHIP_RV620:
        case CHIP_RV635:
@@ -838,7 +836,6 @@ static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
        case CHIP_RV710:
        case CHIP_RV740:
                /* XXX fill in hw i2c implementation */
-               ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
                break;
        case CHIP_CEDAR:
        case CHIP_REDWOOD:
@@ -846,7 +843,6 @@ static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
        case CHIP_CYPRESS:
        case CHIP_HEMLOCK:
                /* XXX fill in hw i2c implementation */
-               ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
                break;
        default:
                DRM_ERROR("i2c: unhandled radeon chip\n");
@@ -857,20 +853,21 @@ static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
        return ret;
 }
 
-static u32 radeon_i2c_func(struct i2c_adapter *adap)
+static u32 radeon_hw_i2c_func(struct i2c_adapter *adap)
 {
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
 static const struct i2c_algorithm radeon_i2c_algo = {
-       .master_xfer = radeon_i2c_xfer,
-       .functionality = radeon_i2c_func,
+       .master_xfer = radeon_hw_i2c_xfer,
+       .functionality = radeon_hw_i2c_func,
 };
 
 struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
                                          struct radeon_i2c_bus_rec *rec,
                                          const char *name)
 {
+       struct radeon_device *rdev = dev->dev_private;
        struct radeon_i2c_chan *i2c;
        int ret;
 
@@ -878,37 +875,43 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
        if (i2c == NULL)
                return NULL;
 
-       /* set the internal bit adapter */
-       i2c->algo.radeon.bit_adapter.owner = THIS_MODULE;
-       i2c_set_adapdata(&i2c->algo.radeon.bit_adapter, i2c);
-       sprintf(i2c->algo.radeon.bit_adapter.name, "Radeon internal i2c bit bus %s", name);
-       i2c->algo.radeon.bit_adapter.algo_data = &i2c->algo.radeon.bit_data;
-       i2c->algo.radeon.bit_data.setsda = set_data;
-       i2c->algo.radeon.bit_data.setscl = set_clock;
-       i2c->algo.radeon.bit_data.getsda = get_data;
-       i2c->algo.radeon.bit_data.getscl = get_clock;
-       i2c->algo.radeon.bit_data.udelay = 20;
-       /* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always
-        * make this, 2 jiffies is a lot more reliable */
-       i2c->algo.radeon.bit_data.timeout = 2;
-       i2c->algo.radeon.bit_data.data = i2c;
-       ret = i2c_bit_add_bus(&i2c->algo.radeon.bit_adapter);
-       if (ret) {
-               DRM_ERROR("Failed to register internal bit i2c %s\n", name);
-               goto out_free;
-       }
-       /* set the radeon i2c adapter */
-       i2c->dev = dev;
        i2c->rec = *rec;
        i2c->adapter.owner = THIS_MODULE;
+       i2c->dev = dev;
        i2c_set_adapdata(&i2c->adapter, i2c);
-       sprintf(i2c->adapter.name, "Radeon i2c %s", name);
-       i2c->adapter.algo_data = &i2c->algo.radeon;
-       i2c->adapter.algo = &radeon_i2c_algo;
-       ret = i2c_add_adapter(&i2c->adapter);
-       if (ret) {
-               DRM_ERROR("Failed to register i2c %s\n", name);
-               goto out_free;
+       if (rec->mm_i2c ||
+           (rec->hw_capable &&
+            radeon_hw_i2c &&
+            ((rdev->family <= CHIP_RS480) ||
+             ((rdev->family >= CHIP_RV515) && (rdev->family <= CHIP_R580))))) {
+               /* set the radeon hw i2c adapter */
+               sprintf(i2c->adapter.name, "Radeon i2c hw bus %s", name);
+               i2c->adapter.algo = &radeon_i2c_algo;
+               ret = i2c_add_adapter(&i2c->adapter);
+               if (ret) {
+                       DRM_ERROR("Failed to register hw i2c %s\n", name);
+                       goto out_free;
+               }
+       } else {
+               /* set the radeon bit adapter */
+               sprintf(i2c->adapter.name, "Radeon i2c bit bus %s", name);
+               i2c->adapter.algo_data = &i2c->algo.bit;
+               i2c->algo.bit.pre_xfer = pre_xfer;
+               i2c->algo.bit.post_xfer = post_xfer;
+               i2c->algo.bit.setsda = set_data;
+               i2c->algo.bit.setscl = set_clock;
+               i2c->algo.bit.getsda = get_data;
+               i2c->algo.bit.getscl = get_clock;
+               i2c->algo.bit.udelay = 20;
+               /* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always
+                * make this, 2 jiffies is a lot more reliable */
+               i2c->algo.bit.timeout = 2;
+               i2c->algo.bit.data = i2c;
+               ret = i2c_bit_add_bus(&i2c->adapter);
+               if (ret) {
+                       DRM_ERROR("Failed to register bit i2c %s\n", name);
+                       goto out_free;
+               }
        }
 
        return i2c;
@@ -953,16 +956,6 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
 {
        if (!i2c)
                return;
-       i2c_del_adapter(&i2c->algo.radeon.bit_adapter);
-       i2c_del_adapter(&i2c->adapter);
-       kfree(i2c);
-}
-
-void radeon_i2c_destroy_dp(struct radeon_i2c_chan *i2c)
-{
-       if (!i2c)
-               return;
-
        i2c_del_adapter(&i2c->adapter);
        kfree(i2c);
 }
index 3cfd60fd00835343f8cacececcb01ba600521133..a212041e8b0b0a5ef0d47d7949f057d38be480ed 100644 (file)
@@ -67,9 +67,10 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
 
        /* Disable *all* interrupts */
        rdev->irq.sw_int = false;
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < rdev->num_crtc; i++)
                rdev->irq.crtc_vblank_int[i] = false;
-       }
+       for (i = 0; i < 6; i++)
+               rdev->irq.hpd[i] = false;
        radeon_irq_set(rdev);
        /* Clear bits */
        radeon_irq_process(rdev);
@@ -95,34 +96,29 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
        }
        /* Disable *all* interrupts */
        rdev->irq.sw_int = false;
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < rdev->num_crtc; i++)
                rdev->irq.crtc_vblank_int[i] = false;
+       for (i = 0; i < 6; i++)
                rdev->irq.hpd[i] = false;
-       }
        radeon_irq_set(rdev);
 }
 
 int radeon_irq_kms_init(struct radeon_device *rdev)
 {
        int r = 0;
-       int num_crtc = 2;
 
-       if (rdev->flags & RADEON_SINGLE_CRTC)
-               num_crtc = 1;
        spin_lock_init(&rdev->irq.sw_lock);
-       r = drm_vblank_init(rdev->ddev, num_crtc);
+       r = drm_vblank_init(rdev->ddev, rdev->num_crtc);
        if (r) {
                return r;
        }
        /* enable msi */
        rdev->msi_enabled = 0;
-       /* MSIs don't seem to work on my rs780;
-        * not sure about rs880 or other rs780s.
-        * Needs more investigation.
+       /* MSIs don't seem to work reliably on all IGP
+        * chips.  Disable MSI on them for now.
         */
        if ((rdev->family >= CHIP_RV380) &&
-           (rdev->family != CHIP_RS780) &&
-           (rdev->family != CHIP_RS880)) {
+           (!(rdev->flags & RADEON_IS_IGP))) {
                int ret = pci_enable_msi(rdev->pdev);
                if (!ret) {
                        rdev->msi_enabled = 1;
index df23d6a01d02297a8ee0832a9f800f48b4ea957c..88865e38fe30a100d2263f5a8db3c51b21a9445c 100644 (file)
@@ -603,6 +603,10 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
                                      ? RADEON_CRTC2_INTERLACE_EN
                                      : 0));
 
+               /* rs4xx chips seem to like to have the crtc enabled when the timing is set */
+               if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480))
+                       crtc2_gen_cntl |= RADEON_CRTC2_EN;
+
                disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
                disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
 
@@ -630,6 +634,10 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
                                    ? RADEON_CRTC_INTERLACE_EN
                                    : 0));
 
+               /* rs4xx chips seem to like to have the crtc enabled when the timing is set */
+               if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480))
+                       crtc_gen_cntl |= RADEON_CRTC_EN;
+
                crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
                crtc_ext_cntl |= (RADEON_XCRT_CNT_EN |
                                  RADEON_CRTC_VSYNC_DIS |
index 417684daef4cb4009057caffb128b6c7533e85c6..f2ed27c8055bc90c0f9004471e063d0e89471801 100644 (file)
 #define NTSC_TV_PLL_N_14 693
 #define NTSC_TV_PLL_P_14 7
 
+#define PAL_TV_PLL_M_14 19
+#define PAL_TV_PLL_N_14 353
+#define PAL_TV_PLL_P_14 5
+
 #define VERT_LEAD_IN_LINES 2
 #define FRAC_BITS 0xe
 #define FRAC_MASK 0x3fff
@@ -205,9 +209,24 @@ static const struct radeon_tv_mode_constants available_tv_modes[] = {
                630627,             /* defRestart */
                347,                /* crtcPLL_N */
                14,                 /* crtcPLL_M */
-                       8,                  /* crtcPLL_postDiv */
+               8,                  /* crtcPLL_postDiv */
                1022,               /* pixToTV */
        },
+       { /* PAL timing for 14 Mhz ref clk */
+               800,                /* horResolution */
+               600,                /* verResolution */
+               TV_STD_PAL,         /* standard */
+               1131,               /* horTotal */
+               742,                /* verTotal */
+               813,                /* horStart */
+               840,                /* horSyncStart */
+               633,                /* verSyncStart */
+               708369,             /* defRestart */
+               211,                /* crtcPLL_N */
+               9,                  /* crtcPLL_M */
+               8,                  /* crtcPLL_postDiv */
+               759,                /* pixToTV */
+       },
 };
 
 #define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes)
@@ -242,7 +261,7 @@ static const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(stru
                if (pll->reference_freq == 2700)
                        const_ptr = &available_tv_modes[1];
                else
-                       const_ptr = &available_tv_modes[1]; /* FIX ME */
+                       const_ptr = &available_tv_modes[3];
        }
        return const_ptr;
 }
@@ -685,9 +704,9 @@ void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
                        n = PAL_TV_PLL_N_27;
                        p = PAL_TV_PLL_P_27;
                } else {
-                       m = PAL_TV_PLL_M_27;
-                       n = PAL_TV_PLL_N_27;
-                       p = PAL_TV_PLL_P_27;
+                       m = PAL_TV_PLL_M_14;
+                       n = PAL_TV_PLL_N_14;
+                       p = PAL_TV_PLL_P_14;
                }
        }
 
index 1702b820aa4d3137e0559d44bd64bc37d8c28d7c..0b8e32776b10930b3dc67266c49a21fce3933a46 100644 (file)
@@ -129,6 +129,7 @@ struct radeon_tmds_pll {
 #define RADEON_PLL_USE_FRAC_FB_DIV      (1 << 10)
 #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
 #define RADEON_PLL_USE_POST_DIV         (1 << 12)
+#define RADEON_PLL_IS_LCD               (1 << 13)
 
 /* pll algo */
 enum radeon_pll_algo {
@@ -149,6 +150,8 @@ struct radeon_pll {
        uint32_t pll_in_max;
        uint32_t pll_out_min;
        uint32_t pll_out_max;
+       uint32_t lcd_pll_out_min;
+       uint32_t lcd_pll_out_max;
        uint32_t best_vco;
 
        /* divider limits */
@@ -170,17 +173,12 @@ struct radeon_pll {
        enum radeon_pll_algo algo;
 };
 
-struct i2c_algo_radeon_data {
-       struct i2c_adapter bit_adapter;
-       struct i2c_algo_bit_data bit_data;
-};
-
 struct radeon_i2c_chan {
        struct i2c_adapter adapter;
        struct drm_device *dev;
        union {
+               struct i2c_algo_bit_data bit;
                struct i2c_algo_dp_aux_data dp;
-               struct i2c_algo_radeon_data radeon;
        } algo;
        struct radeon_i2c_bus_rec rec;
 };
@@ -342,6 +340,7 @@ struct radeon_encoder {
        struct drm_display_mode native_mode;
        void *enc_priv;
        int hdmi_offset;
+       int hdmi_config_offset;
        int hdmi_audio_workaround;
        int hdmi_buffer_status;
 };
@@ -431,7 +430,6 @@ extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
                                                 struct radeon_i2c_bus_rec *rec,
                                                 const char *name);
 extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c);
-extern void radeon_i2c_destroy_dp(struct radeon_i2c_chan *i2c);
 extern void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus,
                                u8 slave_addr,
                                u8 addr,
index fc9d00ac6b15ff68494c437dd758aff4f3214f66..dc7e3f44913869da0a518b44a44237ec75df76e2 100644 (file)
@@ -185,8 +185,10 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
                return 0;
        }
        radeon_ttm_placement_from_domain(bo, domain);
-       /* force to pin into visible video ram */
-       bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
+       if (domain == RADEON_GEM_DOMAIN_VRAM) {
+               /* force to pin into visible video ram */
+               bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
+       }
        for (i = 0; i < bo->placement.num_placement; i++)
                bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
        r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
index d4d1c39a0e99e4e8636dd9e1d095da4473c61e87..a4b57493aa78cca3809558f3a428262f389a7837 100644 (file)
@@ -28,6 +28,7 @@
 #define RADEON_RECLOCK_DELAY_MS 200
 #define RADEON_WAIT_VBLANK_TIMEOUT 200
 
+static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish);
 static void radeon_pm_set_clocks_locked(struct radeon_device *rdev);
 static void radeon_pm_set_clocks(struct radeon_device *rdev);
 static void radeon_pm_idle_work_handler(struct work_struct *work);
@@ -179,6 +180,16 @@ static void radeon_get_power_state(struct radeon_device *rdev,
                 rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
 }
 
+static inline void radeon_sync_with_vblank(struct radeon_device *rdev)
+{
+       if (rdev->pm.active_crtcs) {
+               rdev->pm.vblank_sync = false;
+               wait_event_timeout(
+                       rdev->irq.vblank_queue, rdev->pm.vblank_sync,
+                       msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT));
+       }
+}
+
 static void radeon_set_power_state(struct radeon_device *rdev)
 {
        /* if *_clock_mode are the same, *_power_state are as well */
@@ -189,11 +200,28 @@ static void radeon_set_power_state(struct radeon_device *rdev)
                 rdev->pm.requested_clock_mode->sclk,
                 rdev->pm.requested_clock_mode->mclk,
                 rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
+
        /* set pcie lanes */
+       /* TODO */
+
        /* set voltage */
+       /* TODO */
+
        /* set engine clock */
+       radeon_sync_with_vblank(rdev);
+       radeon_pm_debug_check_in_vbl(rdev, false);
        radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk);
+       radeon_pm_debug_check_in_vbl(rdev, true);
+
+#if 0
        /* set memory clock */
+       if (rdev->asic->set_memory_clock) {
+               radeon_sync_with_vblank(rdev);
+               radeon_pm_debug_check_in_vbl(rdev, false);
+               radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk);
+               radeon_pm_debug_check_in_vbl(rdev, true);
+       }
+#endif
 
        rdev->pm.current_power_state = rdev->pm.requested_power_state;
        rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode;
@@ -229,6 +257,12 @@ int radeon_pm_init(struct radeon_device *rdev)
        return 0;
 }
 
+void radeon_pm_fini(struct radeon_device *rdev)
+{
+       if (rdev->pm.i2c_bus)
+               radeon_i2c_destroy(rdev->pm.i2c_bus);
+}
+
 void radeon_pm_compute_clocks(struct radeon_device *rdev)
 {
        struct drm_device *ddev = rdev->ddev;
@@ -245,7 +279,8 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
        list_for_each_entry(connector,
                &ddev->mode_config.connector_list, head) {
                if (connector->encoder &&
-                       connector->dpms != DRM_MODE_DPMS_OFF) {
+                   connector->encoder->crtc &&
+                   connector->dpms != DRM_MODE_DPMS_OFF) {
                        radeon_crtc = to_radeon_crtc(connector->encoder->crtc);
                        rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
                        ++count;
@@ -333,10 +368,7 @@ static void radeon_pm_set_clocks_locked(struct radeon_device *rdev)
                break;
        }
 
-       /* check if we are in vblank */
-       radeon_pm_debug_check_in_vbl(rdev, false);
        radeon_set_power_state(rdev);
-       radeon_pm_debug_check_in_vbl(rdev, true);
        rdev->pm.planned_action = PM_ACTION_NONE;
 }
 
@@ -353,10 +385,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
                rdev->pm.req_vblank |= (1 << 1);
                drm_vblank_get(rdev->ddev, 1);
        }
-       if (rdev->pm.active_crtcs)
-               wait_event_interruptible_timeout(
-                       rdev->irq.vblank_queue, 0,
-                       msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT));
+       radeon_pm_set_clocks_locked(rdev);
        if (rdev->pm.req_vblank & (1 << 0)) {
                rdev->pm.req_vblank &= ~(1 << 0);
                drm_vblank_put(rdev->ddev, 0);
@@ -366,7 +395,6 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
                drm_vblank_put(rdev->ddev, 1);
        }
 
-       radeon_pm_set_clocks_locked(rdev);
        mutex_unlock(&rdev->cp.mutex);
 }
 
index 5c0dc082d3307752a7dbf7067ea1b98f5cafaafa..eabbc9cf30a72fede242b8b13bd19a8c61508216 100644 (file)
 #       define RADEON_TVPLL_PWRMGT_OFF      (1 << 30)
 #       define RADEON_TVCLK_TURNOFF         (1 << 31)
 #define RADEON_PLL_PWRMGT_CNTL              0x0015 /* PLL */
+#      define RADEON_PM_MODE_SEL           (1 << 13)
 #       define RADEON_TCL_BYPASS_DISABLE    (1 << 20)
 #define RADEON_CLR_CMP_CLR_3D               0x1a24
 #define RADEON_CLR_CMP_CLR_DST              0x15c8
index 8f414a5f520fe50790a1c5037fbbcd13dc94fb32..af0da4ae3f55acb5223f2791940ec90c1db20bce 100644 (file)
@@ -26,20 +26,16 @@ r600 0x9400
 0x00028408 VGT_INDX_OFFSET
 0x00028AA0 VGT_INSTANCE_STEP_RATE_0
 0x00028AA4 VGT_INSTANCE_STEP_RATE_1
-0x000088C0 VGT_LAST_COPY_STATE
 0x00028400 VGT_MAX_VTX_INDX
-0x000088D8 VGT_MC_LAT_CNTL
 0x00028404 VGT_MIN_VTX_INDX
 0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN
 0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX
 0x00008970 VGT_NUM_INDICES
 0x00008974 VGT_NUM_INSTANCES
 0x00028A10 VGT_OUTPUT_PATH_CNTL
-0x00028C5C VGT_OUT_DEALLOC_CNTL
 0x00028A84 VGT_PRIMITIVEID_EN
 0x00008958 VGT_PRIMITIVE_TYPE
 0x00028AB4 VGT_REUSE_OFF
-0x00028C58 VGT_VERTEX_REUSE_BLOCK_CNTL
 0x00028AB8 VGT_VTX_CNT_EN
 0x000088B0 VGT_VTX_VECT_EJECT_REG
 0x00028810 PA_CL_CLIP_CNTL
@@ -280,7 +276,6 @@ r600 0x9400
 0x00028E00 PA_SU_POLY_OFFSET_FRONT_SCALE
 0x00028814 PA_SU_SC_MODE_CNTL
 0x00028C08 PA_SU_VTX_CNTL
-0x00008C00 SQ_CONFIG
 0x00008C04 SQ_GPR_RESOURCE_MGMT_1
 0x00008C08 SQ_GPR_RESOURCE_MGMT_2
 0x00008C10 SQ_STACK_RESOURCE_MGMT_1
@@ -320,18 +315,6 @@ r600 0x9400
 0x000283FC SQ_VTX_SEMANTIC_31
 0x000288E0 SQ_VTX_SEMANTIC_CLEAR
 0x0003CFF4 SQ_VTX_START_INST_LOC
-0x0003C000 SQ_TEX_SAMPLER_WORD0_0
-0x0003C004 SQ_TEX_SAMPLER_WORD1_0
-0x0003C008 SQ_TEX_SAMPLER_WORD2_0
-0x00030000 SQ_ALU_CONSTANT0_0
-0x00030004 SQ_ALU_CONSTANT1_0
-0x00030008 SQ_ALU_CONSTANT2_0
-0x0003000C SQ_ALU_CONSTANT3_0
-0x0003E380 SQ_BOOL_CONST_0
-0x0003E384 SQ_BOOL_CONST_1
-0x0003E388 SQ_BOOL_CONST_2
-0x0003E200 SQ_LOOP_CONST_0
-0x0003E200 SQ_LOOP_CONST_DX10_0
 0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0
 0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1
 0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2
@@ -380,54 +363,6 @@ r600 0x9400
 0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13
 0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14
 0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15
-0x000289C0 SQ_ALU_CONST_CACHE_GS_0
-0x000289C4 SQ_ALU_CONST_CACHE_GS_1
-0x000289C8 SQ_ALU_CONST_CACHE_GS_2
-0x000289CC SQ_ALU_CONST_CACHE_GS_3
-0x000289D0 SQ_ALU_CONST_CACHE_GS_4
-0x000289D4 SQ_ALU_CONST_CACHE_GS_5
-0x000289D8 SQ_ALU_CONST_CACHE_GS_6
-0x000289DC SQ_ALU_CONST_CACHE_GS_7
-0x000289E0 SQ_ALU_CONST_CACHE_GS_8
-0x000289E4 SQ_ALU_CONST_CACHE_GS_9
-0x000289E8 SQ_ALU_CONST_CACHE_GS_10
-0x000289EC SQ_ALU_CONST_CACHE_GS_11
-0x000289F0 SQ_ALU_CONST_CACHE_GS_12
-0x000289F4 SQ_ALU_CONST_CACHE_GS_13
-0x000289F8 SQ_ALU_CONST_CACHE_GS_14
-0x000289FC SQ_ALU_CONST_CACHE_GS_15
-0x00028940 SQ_ALU_CONST_CACHE_PS_0
-0x00028944 SQ_ALU_CONST_CACHE_PS_1
-0x00028948 SQ_ALU_CONST_CACHE_PS_2
-0x0002894C SQ_ALU_CONST_CACHE_PS_3
-0x00028950 SQ_ALU_CONST_CACHE_PS_4
-0x00028954 SQ_ALU_CONST_CACHE_PS_5
-0x00028958 SQ_ALU_CONST_CACHE_PS_6
-0x0002895C SQ_ALU_CONST_CACHE_PS_7
-0x00028960 SQ_ALU_CONST_CACHE_PS_8
-0x00028964 SQ_ALU_CONST_CACHE_PS_9
-0x00028968 SQ_ALU_CONST_CACHE_PS_10
-0x0002896C SQ_ALU_CONST_CACHE_PS_11
-0x00028970 SQ_ALU_CONST_CACHE_PS_12
-0x00028974 SQ_ALU_CONST_CACHE_PS_13
-0x00028978 SQ_ALU_CONST_CACHE_PS_14
-0x0002897C SQ_ALU_CONST_CACHE_PS_15
-0x00028980 SQ_ALU_CONST_CACHE_VS_0
-0x00028984 SQ_ALU_CONST_CACHE_VS_1
-0x00028988 SQ_ALU_CONST_CACHE_VS_2
-0x0002898C SQ_ALU_CONST_CACHE_VS_3
-0x00028990 SQ_ALU_CONST_CACHE_VS_4
-0x00028994 SQ_ALU_CONST_CACHE_VS_5
-0x00028998 SQ_ALU_CONST_CACHE_VS_6
-0x0002899C SQ_ALU_CONST_CACHE_VS_7
-0x000289A0 SQ_ALU_CONST_CACHE_VS_8
-0x000289A4 SQ_ALU_CONST_CACHE_VS_9
-0x000289A8 SQ_ALU_CONST_CACHE_VS_10
-0x000289AC SQ_ALU_CONST_CACHE_VS_11
-0x000289B0 SQ_ALU_CONST_CACHE_VS_12
-0x000289B4 SQ_ALU_CONST_CACHE_VS_13
-0x000289B8 SQ_ALU_CONST_CACHE_VS_14
-0x000289BC SQ_ALU_CONST_CACHE_VS_15
 0x000288D8 SQ_PGM_CF_OFFSET_ES
 0x000288DC SQ_PGM_CF_OFFSET_FS
 0x000288D4 SQ_PGM_CF_OFFSET_GS
@@ -494,12 +429,7 @@ r600 0x9400
 0x00028438 SX_ALPHA_REF
 0x00028410 SX_ALPHA_TEST_CONTROL
 0x00028350 SX_MISC
-0x0000A020 SMX_DC_CTL0
-0x0000A024 SMX_DC_CTL1
-0x0000A028 SMX_DC_CTL2
-0x00009608 TC_CNTL
 0x00009604 TC_INVALIDATE
-0x00009490 TD_CNTL
 0x00009400 TD_FILTER4
 0x00009404 TD_FILTER4_1
 0x00009408 TD_FILTER4_2
@@ -824,14 +754,9 @@ r600 0x9400
 0x00028428 CB_FOG_GREEN
 0x00028424 CB_FOG_RED
 0x00008040 WAIT_UNTIL
-0x00008950 CC_GC_SHADER_PIPE_CONFIG
-0x00008954 GC_USER_SHADER_PIPE_CONFIG
 0x00009714 VC_ENHANCE
 0x00009830 DB_DEBUG
 0x00009838 DB_WATERMARKS
 0x00028D28 DB_SRESULTS_COMPARE_STATE0
 0x00028D44 DB_ALPHA_TO_MASK
-0x00009504 TA_CNTL
 0x00009700 VC_CNTL
-0x00009718 VC_CONFIG
-0x0000A02C SMX_DC_MC_INTF_CTL
index 626d51891ee968613efeffc6612698387b46f1d4..626aaf082b1a9d1c6974afbc354318dcde0b2805 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/seq_file.h>
 #include <drm/drmP.h>
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "rs400d.h"
 
 /* This files gather functions specifics to : rs400,rs480 */
@@ -202,9 +203,9 @@ void rs400_gart_disable(struct radeon_device *rdev)
 
 void rs400_gart_fini(struct radeon_device *rdev)
 {
+       radeon_gart_fini(rdev);
        rs400_gart_disable(rdev);
        radeon_gart_table_ram_free(rdev);
-       radeon_gart_fini(rdev);
 }
 
 int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
@@ -264,6 +265,7 @@ void rs400_mc_init(struct radeon_device *rdev)
        base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
        radeon_vram_location(rdev, &rdev->mc, base);
        radeon_gtt_location(rdev, &rdev->mc);
+       radeon_update_bandwidth_info(rdev);
 }
 
 uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg)
@@ -388,6 +390,8 @@ static int rs400_startup(struct radeon_device *rdev)
 {
        int r;
 
+       r100_set_common_regs(rdev);
+
        rs400_mc_program(rdev);
        /* Resume clock */
        r300_clock_startup(rdev);
@@ -453,6 +457,7 @@ int rs400_suspend(struct radeon_device *rdev)
 
 void rs400_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index 47f046b78c6ba9c19c93a2560179310b92f322d6..abf824c2123d5e0067d822ce6874ffeeb24c4857 100644 (file)
@@ -37,6 +37,7 @@
  */
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "atom.h"
 #include "rs600d.h"
 
@@ -267,9 +268,9 @@ void rs600_gart_disable(struct radeon_device *rdev)
 
 void rs600_gart_fini(struct radeon_device *rdev)
 {
+       radeon_gart_fini(rdev);
        rs600_gart_disable(rdev);
        radeon_gart_table_vram_free(rdev);
-       radeon_gart_fini(rdev);
 }
 
 #define R600_PTE_VALID     (1 << 0)
@@ -392,10 +393,12 @@ int rs600_irq_process(struct radeon_device *rdev)
                /* Vertical blank interrupts */
                if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) {
                        drm_handle_vblank(rdev->ddev, 0);
+                       rdev->pm.vblank_sync = true;
                        wake_up(&rdev->irq.vblank_queue);
                }
                if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) {
                        drm_handle_vblank(rdev->ddev, 1);
+                       rdev->pm.vblank_sync = true;
                        wake_up(&rdev->irq.vblank_queue);
                }
                if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) {
@@ -472,13 +475,38 @@ void rs600_mc_init(struct radeon_device *rdev)
        rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
        base = RREG32_MC(R_000004_MC_FB_LOCATION);
        base = G_000004_MC_FB_START(base) << 16;
+       rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
        radeon_vram_location(rdev, &rdev->mc, base);
        radeon_gtt_location(rdev, &rdev->mc);
+       radeon_update_bandwidth_info(rdev);
 }
 
 void rs600_bandwidth_update(struct radeon_device *rdev)
 {
-       /* FIXME: implement, should this be like rs690 ? */
+       struct drm_display_mode *mode0 = NULL;
+       struct drm_display_mode *mode1 = NULL;
+       u32 d1mode_priority_a_cnt, d2mode_priority_a_cnt;
+       /* FIXME: implement full support */
+
+       radeon_update_display_priority(rdev);
+
+       if (rdev->mode_info.crtcs[0]->base.enabled)
+               mode0 = &rdev->mode_info.crtcs[0]->base.mode;
+       if (rdev->mode_info.crtcs[1]->base.enabled)
+               mode1 = &rdev->mode_info.crtcs[1]->base.mode;
+
+       rs690_line_buffer_adjust(rdev, mode0, mode1);
+
+       if (rdev->disp_priority == 2) {
+               d1mode_priority_a_cnt = RREG32(R_006548_D1MODE_PRIORITY_A_CNT);
+               d2mode_priority_a_cnt = RREG32(R_006D48_D2MODE_PRIORITY_A_CNT);
+               d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);
+               d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);
+               WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
+               WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
+               WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
+               WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
+       }
 }
 
 uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg)
@@ -598,6 +626,7 @@ int rs600_suspend(struct radeon_device *rdev)
 
 void rs600_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index c1c8f5885cbbc0727e484c49972e21790b5d3d74..e52d2695510b7375af024f99cb15083ebbba9c7d 100644 (file)
 #define   G_00016C_INVALIDATE_L1_TLB(x)                (((x) >> 20) & 0x1)
 #define   C_00016C_INVALIDATE_L1_TLB                   0xFFEFFFFF
 
+#define R_006548_D1MODE_PRIORITY_A_CNT               0x006548
+#define   S_006548_D1MODE_PRIORITY_MARK_A(x)           (((x) & 0x7FFF) << 0)
+#define   G_006548_D1MODE_PRIORITY_MARK_A(x)           (((x) >> 0) & 0x7FFF)
+#define   C_006548_D1MODE_PRIORITY_MARK_A              0xFFFF8000
+#define   S_006548_D1MODE_PRIORITY_A_OFF(x)            (((x) & 0x1) << 16)
+#define   G_006548_D1MODE_PRIORITY_A_OFF(x)            (((x) >> 16) & 0x1)
+#define   C_006548_D1MODE_PRIORITY_A_OFF               0xFFFEFFFF
+#define   S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(x)      (((x) & 0x1) << 20)
+#define   G_006548_D1MODE_PRIORITY_A_ALWAYS_ON(x)      (((x) >> 20) & 0x1)
+#define   C_006548_D1MODE_PRIORITY_A_ALWAYS_ON         0xFFEFFFFF
+#define   S_006548_D1MODE_PRIORITY_A_FORCE_MASK(x)     (((x) & 0x1) << 24)
+#define   G_006548_D1MODE_PRIORITY_A_FORCE_MASK(x)     (((x) >> 24) & 0x1)
+#define   C_006548_D1MODE_PRIORITY_A_FORCE_MASK        0xFEFFFFFF
+#define R_00654C_D1MODE_PRIORITY_B_CNT               0x00654C
+#define   S_00654C_D1MODE_PRIORITY_MARK_B(x)           (((x) & 0x7FFF) << 0)
+#define   G_00654C_D1MODE_PRIORITY_MARK_B(x)           (((x) >> 0) & 0x7FFF)
+#define   C_00654C_D1MODE_PRIORITY_MARK_B              0xFFFF8000
+#define   S_00654C_D1MODE_PRIORITY_B_OFF(x)            (((x) & 0x1) << 16)
+#define   G_00654C_D1MODE_PRIORITY_B_OFF(x)            (((x) >> 16) & 0x1)
+#define   C_00654C_D1MODE_PRIORITY_B_OFF               0xFFFEFFFF
+#define   S_00654C_D1MODE_PRIORITY_B_ALWAYS_ON(x)      (((x) & 0x1) << 20)
+#define   G_00654C_D1MODE_PRIORITY_B_ALWAYS_ON(x)      (((x) >> 20) & 0x1)
+#define   C_00654C_D1MODE_PRIORITY_B_ALWAYS_ON         0xFFEFFFFF
+#define   S_00654C_D1MODE_PRIORITY_B_FORCE_MASK(x)     (((x) & 0x1) << 24)
+#define   G_00654C_D1MODE_PRIORITY_B_FORCE_MASK(x)     (((x) >> 24) & 0x1)
+#define   C_00654C_D1MODE_PRIORITY_B_FORCE_MASK        0xFEFFFFFF
+#define R_006D48_D2MODE_PRIORITY_A_CNT               0x006D48
+#define   S_006D48_D2MODE_PRIORITY_MARK_A(x)           (((x) & 0x7FFF) << 0)
+#define   G_006D48_D2MODE_PRIORITY_MARK_A(x)           (((x) >> 0) & 0x7FFF)
+#define   C_006D48_D2MODE_PRIORITY_MARK_A              0xFFFF8000
+#define   S_006D48_D2MODE_PRIORITY_A_OFF(x)            (((x) & 0x1) << 16)
+#define   G_006D48_D2MODE_PRIORITY_A_OFF(x)            (((x) >> 16) & 0x1)
+#define   C_006D48_D2MODE_PRIORITY_A_OFF               0xFFFEFFFF
+#define   S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(x)      (((x) & 0x1) << 20)
+#define   G_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(x)      (((x) >> 20) & 0x1)
+#define   C_006D48_D2MODE_PRIORITY_A_ALWAYS_ON         0xFFEFFFFF
+#define   S_006D48_D2MODE_PRIORITY_A_FORCE_MASK(x)     (((x) & 0x1) << 24)
+#define   G_006D48_D2MODE_PRIORITY_A_FORCE_MASK(x)     (((x) >> 24) & 0x1)
+#define   C_006D48_D2MODE_PRIORITY_A_FORCE_MASK        0xFEFFFFFF
+#define R_006D4C_D2MODE_PRIORITY_B_CNT               0x006D4C
+#define   S_006D4C_D2MODE_PRIORITY_MARK_B(x)           (((x) & 0x7FFF) << 0)
+#define   G_006D4C_D2MODE_PRIORITY_MARK_B(x)           (((x) >> 0) & 0x7FFF)
+#define   C_006D4C_D2MODE_PRIORITY_MARK_B              0xFFFF8000
+#define   S_006D4C_D2MODE_PRIORITY_B_OFF(x)            (((x) & 0x1) << 16)
+#define   G_006D4C_D2MODE_PRIORITY_B_OFF(x)            (((x) >> 16) & 0x1)
+#define   C_006D4C_D2MODE_PRIORITY_B_OFF               0xFFFEFFFF
+#define   S_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON(x)      (((x) & 0x1) << 20)
+#define   G_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON(x)      (((x) >> 20) & 0x1)
+#define   C_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON         0xFFEFFFFF
+#define   S_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x)     (((x) & 0x1) << 24)
+#define   G_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x)     (((x) >> 24) & 0x1)
+#define   C_006D4C_D2MODE_PRIORITY_B_FORCE_MASK        0xFEFFFFFF
+
 #endif
index 83b9174f76f255e9fb488a3fe294a87eb0fafd62..bbf3da790fd59fc7a8a03e65f260487d6fa7bca0 100644 (file)
@@ -27,6 +27,7 @@
  */
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "atom.h"
 #include "rs690d.h"
 
@@ -57,42 +58,57 @@ static void rs690_gpu_init(struct radeon_device *rdev)
        }
 }
 
+union igp_info {
+       struct _ATOM_INTEGRATED_SYSTEM_INFO info;
+       struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_v2;
+};
+
 void rs690_pm_info(struct radeon_device *rdev)
 {
        int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
-       struct _ATOM_INTEGRATED_SYSTEM_INFO *info;
-       struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2;
-       void *ptr;
+       union igp_info *info;
        uint16_t data_offset;
        uint8_t frev, crev;
        fixed20_12 tmp;
 
-       atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
-                              &frev, &crev, &data_offset);
-       ptr = rdev->mode_info.atom_context->bios + data_offset;
-       info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr;
-       info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr;
-       /* Get various system informations from bios */
-       switch (crev) {
-       case 1:
-               tmp.full = rfixed_const(100);
-               rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock);
-               rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
-               rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock));
-               rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock));
-               rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth);
-               break;
-       case 2:
-               tmp.full = rfixed_const(100);
-               rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock);
-               rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
-               rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock);
-               rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
-               rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq);
-               rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp);
-               rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth));
-               break;
-       default:
+       if (atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               info = (union igp_info *)(rdev->mode_info.atom_context->bios + data_offset);
+
+               /* Get various system informations from bios */
+               switch (crev) {
+               case 1:
+                       tmp.full = rfixed_const(100);
+                       rdev->pm.igp_sideport_mclk.full = rfixed_const(info->info.ulBootUpMemoryClock);
+                       rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
+                       rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
+                       rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->info.usFSBClock));
+                       rdev->pm.igp_ht_link_width.full = rfixed_const(info->info.ucHTLinkWidth);
+                       break;
+               case 2:
+                       tmp.full = rfixed_const(100);
+                       rdev->pm.igp_sideport_mclk.full = rfixed_const(info->info_v2.ulBootUpSidePortClock);
+                       rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
+                       rdev->pm.igp_system_mclk.full = rfixed_const(info->info_v2.ulBootUpUMAClock);
+                       rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
+                       rdev->pm.igp_ht_link_clk.full = rfixed_const(info->info_v2.ulHTLinkFreq);
+                       rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp);
+                       rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));
+                       break;
+               default:
+                       tmp.full = rfixed_const(100);
+                       /* We assume the slower possible clock ie worst case */
+                       /* DDR 333Mhz */
+                       rdev->pm.igp_sideport_mclk.full = rfixed_const(333);
+                       /* FIXME: system clock ? */
+                       rdev->pm.igp_system_mclk.full = rfixed_const(100);
+                       rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
+                       rdev->pm.igp_ht_link_clk.full = rfixed_const(200);
+                       rdev->pm.igp_ht_link_width.full = rfixed_const(8);
+                       DRM_ERROR("No integrated system info for your GPU, using safe default\n");
+                       break;
+               }
+       } else {
                tmp.full = rfixed_const(100);
                /* We assume the slower possible clock ie worst case */
                /* DDR 333Mhz */
@@ -103,7 +119,6 @@ void rs690_pm_info(struct radeon_device *rdev)
                rdev->pm.igp_ht_link_clk.full = rfixed_const(200);
                rdev->pm.igp_ht_link_width.full = rfixed_const(8);
                DRM_ERROR("No integrated system info for your GPU, using safe default\n");
-               break;
        }
        /* Compute various bandwidth */
        /* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4  */
@@ -131,7 +146,6 @@ void rs690_pm_info(struct radeon_device *rdev)
 
 void rs690_mc_init(struct radeon_device *rdev)
 {
-       fixed20_12 a;
        u64 base;
 
        rs400_gart_adjust_size(rdev);
@@ -145,18 +159,10 @@ void rs690_mc_init(struct radeon_device *rdev)
        base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
        base = G_000100_MC_FB_START(base) << 16;
        rs690_pm_info(rdev);
-       /* FIXME: we should enforce default clock in case GPU is not in
-        * default setup
-        */
-       a.full = rfixed_const(100);
-       rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
-       rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
-       a.full = rfixed_const(16);
-       /* core_bandwidth = sclk(Mhz) * 16 */
-       rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a);
        rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
        radeon_vram_location(rdev, &rdev->mc, base);
        radeon_gtt_location(rdev, &rdev->mc);
+       radeon_update_bandwidth_info(rdev);
 }
 
 void rs690_line_buffer_adjust(struct radeon_device *rdev,
@@ -394,10 +400,12 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
        struct drm_display_mode *mode1 = NULL;
        struct rs690_watermark wm0;
        struct rs690_watermark wm1;
-       u32 tmp;
+       u32 tmp, d1mode_priority_a_cnt, d2mode_priority_a_cnt;
        fixed20_12 priority_mark02, priority_mark12, fill_rate;
        fixed20_12 a, b;
 
+       radeon_update_display_priority(rdev);
+
        if (rdev->mode_info.crtcs[0]->base.enabled)
                mode0 = &rdev->mode_info.crtcs[0]->base.mode;
        if (rdev->mode_info.crtcs[1]->base.enabled)
@@ -407,7 +415,8 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
         * modes if the user specifies HIGH for displaypriority
         * option.
         */
-       if (rdev->disp_priority == 2) {
+       if ((rdev->disp_priority == 2) &&
+           ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740))) {
                tmp = RREG32_MC(R_000104_MC_INIT_MISC_LAT_TIMER);
                tmp &= C_000104_MC_DISP0R_INIT_LAT;
                tmp &= C_000104_MC_DISP1R_INIT_LAT;
@@ -482,10 +491,16 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
                        priority_mark12.full = 0;
                if (wm1.priority_mark_max.full > priority_mark12.full)
                        priority_mark12.full = wm1.priority_mark_max.full;
-               WREG32(R_006548_D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
-               WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
-               WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
-               WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+               d1mode_priority_a_cnt = rfixed_trunc(priority_mark02);
+               d2mode_priority_a_cnt = rfixed_trunc(priority_mark12);
+               if (rdev->disp_priority == 2) {
+                       d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);
+                       d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);
+               }
+               WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
+               WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
+               WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
+               WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
        } else if (mode0) {
                if (rfixed_trunc(wm0.dbpp) > 64)
                        a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair);
@@ -512,8 +527,11 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
                        priority_mark02.full = 0;
                if (wm0.priority_mark_max.full > priority_mark02.full)
                        priority_mark02.full = wm0.priority_mark_max.full;
-               WREG32(R_006548_D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
-               WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+               d1mode_priority_a_cnt = rfixed_trunc(priority_mark02);
+               if (rdev->disp_priority == 2)
+                       d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);
+               WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
+               WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
                WREG32(R_006D48_D2MODE_PRIORITY_A_CNT,
                        S_006D48_D2MODE_PRIORITY_A_OFF(1));
                WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT,
@@ -544,12 +562,15 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
                        priority_mark12.full = 0;
                if (wm1.priority_mark_max.full > priority_mark12.full)
                        priority_mark12.full = wm1.priority_mark_max.full;
+               d2mode_priority_a_cnt = rfixed_trunc(priority_mark12);
+               if (rdev->disp_priority == 2)
+                       d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);
                WREG32(R_006548_D1MODE_PRIORITY_A_CNT,
                        S_006548_D1MODE_PRIORITY_A_OFF(1));
                WREG32(R_00654C_D1MODE_PRIORITY_B_CNT,
                        S_00654C_D1MODE_PRIORITY_B_OFF(1));
-               WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
-               WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+               WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
+               WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
        }
 }
 
@@ -657,6 +678,7 @@ int rs690_suspend(struct radeon_device *rdev)
 
 void rs690_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index 62d31e7a897f89e3327235d1ab91f671d26d6f8f..36e6398a98aea242520f5772bd556ea9293af48a 100644 (file)
 #define   S_006548_D1MODE_PRIORITY_A_OFF(x)            (((x) & 0x1) << 16)
 #define   G_006548_D1MODE_PRIORITY_A_OFF(x)            (((x) >> 16) & 0x1)
 #define   C_006548_D1MODE_PRIORITY_A_OFF               0xFFFEFFFF
+#define   S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(x)      (((x) & 0x1) << 20)
+#define   G_006548_D1MODE_PRIORITY_A_ALWAYS_ON(x)      (((x) >> 20) & 0x1)
+#define   C_006548_D1MODE_PRIORITY_A_ALWAYS_ON         0xFFEFFFFF
 #define   S_006548_D1MODE_PRIORITY_A_FORCE_MASK(x)     (((x) & 0x1) << 24)
 #define   G_006548_D1MODE_PRIORITY_A_FORCE_MASK(x)     (((x) >> 24) & 0x1)
 #define   C_006548_D1MODE_PRIORITY_A_FORCE_MASK        0xFEFFFFFF
index bea747da123ffef833df17c8d71e9ee1b0c02121..1cf233f7e5163456c38592cbc152cf05ab0694fd 100644 (file)
@@ -29,6 +29,7 @@
 #include "drmP.h"
 #include "rv515d.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "atom.h"
 #include "rv515_reg_safe.h"
 
@@ -279,19 +280,13 @@ static void rv515_vram_get_type(struct radeon_device *rdev)
 
 void rv515_mc_init(struct radeon_device *rdev)
 {
-       fixed20_12 a;
 
        rv515_vram_get_type(rdev);
        r100_vram_init_sizes(rdev);
        radeon_vram_location(rdev, &rdev->mc, 0);
        if (!(rdev->flags & RADEON_IS_AGP))
                radeon_gtt_location(rdev, &rdev->mc);
-       /* FIXME: we should enforce default clock in case GPU is not in
-        * default setup
-        */
-       a.full = rfixed_const(100);
-       rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
-       rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+       radeon_update_bandwidth_info(rdev);
 }
 
 uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg)
@@ -539,6 +534,7 @@ void rv515_set_safe_registers(struct radeon_device *rdev)
 
 void rv515_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
@@ -1020,7 +1016,7 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
        struct drm_display_mode *mode1 = NULL;
        struct rv515_watermark wm0;
        struct rv515_watermark wm1;
-       u32 tmp;
+       u32 tmp, d1mode_priority_a_cnt, d2mode_priority_a_cnt;
        fixed20_12 priority_mark02, priority_mark12, fill_rate;
        fixed20_12 a, b;
 
@@ -1088,10 +1084,16 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
                        priority_mark12.full = 0;
                if (wm1.priority_mark_max.full > priority_mark12.full)
                        priority_mark12.full = wm1.priority_mark_max.full;
-               WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
-               WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
-               WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
-               WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+               d1mode_priority_a_cnt = rfixed_trunc(priority_mark02);
+               d2mode_priority_a_cnt = rfixed_trunc(priority_mark12);
+               if (rdev->disp_priority == 2) {
+                       d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
+                       d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
+               }
+               WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
+               WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
+               WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
+               WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
        } else if (mode0) {
                if (rfixed_trunc(wm0.dbpp) > 64)
                        a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair);
@@ -1118,8 +1120,11 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
                        priority_mark02.full = 0;
                if (wm0.priority_mark_max.full > priority_mark02.full)
                        priority_mark02.full = wm0.priority_mark_max.full;
-               WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
-               WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+               d1mode_priority_a_cnt = rfixed_trunc(priority_mark02);
+               if (rdev->disp_priority == 2)
+                       d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
+               WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
+               WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
                WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
                WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
        } else {
@@ -1148,10 +1153,13 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
                        priority_mark12.full = 0;
                if (wm1.priority_mark_max.full > priority_mark12.full)
                        priority_mark12.full = wm1.priority_mark_max.full;
+               d2mode_priority_a_cnt = rfixed_trunc(priority_mark12);
+               if (rdev->disp_priority == 2)
+                       d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
                WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
                WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
-               WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
-               WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+               WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
+               WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
        }
 }
 
@@ -1161,6 +1169,8 @@ void rv515_bandwidth_update(struct radeon_device *rdev)
        struct drm_display_mode *mode0 = NULL;
        struct drm_display_mode *mode1 = NULL;
 
+       radeon_update_display_priority(rdev);
+
        if (rdev->mode_info.crtcs[0]->base.enabled)
                mode0 = &rdev->mode_info.crtcs[0]->base.mode;
        if (rdev->mode_info.crtcs[1]->base.enabled)
@@ -1170,7 +1180,8 @@ void rv515_bandwidth_update(struct radeon_device *rdev)
         * modes if the user specifies HIGH for displaypriority
         * option.
         */
-       if (rdev->disp_priority == 2) {
+       if ((rdev->disp_priority == 2) &&
+           (rdev->family == CHIP_RV515)) {
                tmp = RREG32_MC(MC_MISC_LAT_TIMER);
                tmp &= ~MC_DISP1R_INIT_LAT_MASK;
                tmp &= ~MC_DISP0R_INIT_LAT_MASK;
index 37887dee12afc48fa999fcf4f828433396604213..9f37d2efb0a99a1639c07784f621e018da8b441f 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/platform_device.h>
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "radeon_drm.h"
 #include "rv770d.h"
 #include "atom.h"
@@ -125,9 +126,9 @@ void rv770_pcie_gart_disable(struct radeon_device *rdev)
 
 void rv770_pcie_gart_fini(struct radeon_device *rdev)
 {
+       radeon_gart_fini(rdev);
        rv770_pcie_gart_disable(rdev);
        radeon_gart_table_vram_free(rdev);
-       radeon_gart_fini(rdev);
 }
 
 
@@ -647,10 +648,13 @@ static void rv770_gpu_init(struct radeon_device *rdev)
 
        WREG32(CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
        WREG32(CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
+       WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
        WREG32(CC_SYS_RB_BACKEND_DISABLE,  cc_rb_backend_disable);
 
        WREG32(CGTS_SYS_TCC_DISABLE, 0);
        WREG32(CGTS_TCC_DISABLE, 0);
+       WREG32(CGTS_USER_SYS_TCC_DISABLE, 0);
+       WREG32(CGTS_USER_TCC_DISABLE, 0);
 
        num_qd_pipes =
                R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8);
@@ -864,7 +868,6 @@ static void rv770_gpu_init(struct radeon_device *rdev)
 
 int rv770_mc_init(struct radeon_device *rdev)
 {
-       fixed20_12 a;
        u32 tmp;
        int chansize, numchan;
 
@@ -908,12 +911,8 @@ int rv770_mc_init(struct radeon_device *rdev)
                rdev->mc.real_vram_size = rdev->mc.aper_size;
        }
        r600_vram_gtt_location(rdev, &rdev->mc);
-       /* FIXME: we should enforce default clock in case GPU is not in
-        * default setup
-        */
-       a.full = rfixed_const(100);
-       rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
-       rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+       radeon_update_bandwidth_info(rdev);
+
        return 0;
 }
 
@@ -1013,6 +1012,13 @@ int rv770_resume(struct radeon_device *rdev)
                DRM_ERROR("radeon: failled testing IB (%d).\n", r);
                return r;
        }
+
+       r = r600_audio_init(rdev);
+       if (r) {
+               dev_err(rdev->dev, "radeon: audio init failed\n");
+               return r;
+       }
+
        return r;
 
 }
@@ -1021,6 +1027,7 @@ int rv770_suspend(struct radeon_device *rdev)
 {
        int r;
 
+       r600_audio_fini(rdev);
        /* FIXME: we should wait for ring to be empty */
        r700_cp_stop(rdev);
        rdev->cp.ready = false;
@@ -1144,11 +1151,19 @@ int rv770_init(struct radeon_device *rdev)
                        }
                }
        }
+
+       r = r600_audio_init(rdev);
+       if (r) {
+               dev_err(rdev->dev, "radeon: audio init failed\n");
+               return r;
+       }
+
        return 0;
 }
 
 void rv770_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_blit_fini(rdev);
        r600_cp_fini(rdev);
        r600_wb_fini(rdev);
index 89c38c49066f2d87a69ecf58d528f2cf209a26af..dd47b2a9a791fc2f539c0df6cf797661570c47dc 100644 (file)
@@ -1425,8 +1425,8 @@ int ttm_bo_global_init(struct ttm_global_reference *ref)
 
        atomic_set(&glob->bo_count, 0);
 
-       kobject_init(&glob->kobj, &ttm_bo_glob_kobj_type);
-       ret = kobject_add(&glob->kobj, ttm_get_kobj(), "buffer_objects");
+       ret = kobject_init_and_add(
+               &glob->kobj, &ttm_bo_glob_kobj_type, ttm_get_kobj(), "buffer_objects");
        if (unlikely(ret != 0))
                kobject_put(&glob->kobj);
        return ret;
index eb143e04d40242a35c99d774f981cdf610979f6b..c40e5f48e9a1ac37048e012c3b4d4de7aa6ed652 100644 (file)
@@ -260,8 +260,8 @@ static int ttm_mem_init_kernel_zone(struct ttm_mem_global *glob,
        zone->used_mem = 0;
        zone->glob = glob;
        glob->zone_kernel = zone;
-       kobject_init(&zone->kobj, &ttm_mem_zone_kobj_type);
-       ret = kobject_add(&zone->kobj, &glob->kobj, zone->name);
+       ret = kobject_init_and_add(
+               &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, zone->name);
        if (unlikely(ret != 0)) {
                kobject_put(&zone->kobj);
                return ret;
@@ -296,8 +296,8 @@ static int ttm_mem_init_highmem_zone(struct ttm_mem_global *glob,
        zone->used_mem = 0;
        zone->glob = glob;
        glob->zone_highmem = zone;
-       kobject_init(&zone->kobj, &ttm_mem_zone_kobj_type);
-       ret = kobject_add(&zone->kobj, &glob->kobj, zone->name);
+       ret = kobject_init_and_add(
+               &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, zone->name);
        if (unlikely(ret != 0)) {
                kobject_put(&zone->kobj);
                return ret;
@@ -343,8 +343,8 @@ static int ttm_mem_init_dma32_zone(struct ttm_mem_global *glob,
        zone->used_mem = 0;
        zone->glob = glob;
        glob->zone_dma32 = zone;
-       kobject_init(&zone->kobj, &ttm_mem_zone_kobj_type);
-       ret = kobject_add(&zone->kobj, &glob->kobj, zone->name);
+       ret = kobject_init_and_add(
+               &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, zone->name);
        if (unlikely(ret != 0)) {
                kobject_put(&zone->kobj);
                return ret;
@@ -365,10 +365,8 @@ int ttm_mem_global_init(struct ttm_mem_global *glob)
        glob->swap_queue = create_singlethread_workqueue("ttm_swap");
        INIT_WORK(&glob->work, ttm_shrink_work);
        init_waitqueue_head(&glob->queue);
-       kobject_init(&glob->kobj, &ttm_mem_glob_kobj_type);
-       ret = kobject_add(&glob->kobj,
-                         ttm_get_kobj(),
-                         "memory_accounting");
+       ret = kobject_init_and_add(
+               &glob->kobj, &ttm_mem_glob_kobj_type, ttm_get_kobj(), "memory_accounting");
        if (unlikely(ret != 0)) {
                kobject_put(&glob->kobj);
                return ret;
index a759170763bb6bc2e878a26834f7aa665dff943e..bab6cd8d8a1e98aad0296b0014c15ac7f6d12717 100644 (file)
  * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
  */
 
-#include <linux/vmalloc.h>
 #include <linux/sched.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
 #include <linux/swap.h>
 #include "drm_cache.h"
+#include "drm_mem_util.h"
 #include "ttm/ttm_module.h"
 #include "ttm/ttm_bo_driver.h"
 #include "ttm/ttm_placement.h"
@@ -43,32 +43,15 @@ static int ttm_tt_swapin(struct ttm_tt *ttm);
 
 /**
  * Allocates storage for pointers to the pages that back the ttm.
- *
- * Uses kmalloc if possible. Otherwise falls back to vmalloc.
  */
 static void ttm_tt_alloc_page_directory(struct ttm_tt *ttm)
 {
-       unsigned long size = ttm->num_pages * sizeof(*ttm->pages);
-       ttm->pages = NULL;
-
-       if (size <= PAGE_SIZE)
-               ttm->pages = kzalloc(size, GFP_KERNEL);
-
-       if (!ttm->pages) {
-               ttm->pages = vmalloc_user(size);
-               if (ttm->pages)
-                       ttm->page_flags |= TTM_PAGE_FLAG_VMALLOC;
-       }
+       ttm->pages = drm_calloc_large(ttm->num_pages, sizeof(*ttm->pages));
 }
 
 static void ttm_tt_free_page_directory(struct ttm_tt *ttm)
 {
-       if (ttm->page_flags & TTM_PAGE_FLAG_VMALLOC) {
-               vfree(ttm->pages);
-               ttm->page_flags &= ~TTM_PAGE_FLAG_VMALLOC;
-       } else {
-               kfree(ttm->pages);
-       }
+       drm_free_large(ttm->pages);
        ttm->pages = NULL;
 }
 
index f20b8bcbef3998cfd447eee2a3e2d8e904827dc8..30ad13344f7b96da384ffff3209dc2683e1e282a 100644 (file)
@@ -1,6 +1,6 @@
 config DRM_VMWGFX
        tristate "DRM driver for VMware Virtual GPU"
-       depends on DRM && PCI
+       depends on DRM && PCI && FB
        select FB_DEFERRED_IO
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
index cab13e8c7d292c7ed93a06b8a58acc6072d50fd3..62416e6baecaf7611e9d536e64ac84e5d98bbad9 100644 (file)
@@ -53,10 +53,13 @@ static int gyration_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 static int gyration_event(struct hid_device *hdev, struct hid_field *field,
                struct hid_usage *usage, __s32 value)
 {
-       struct input_dev *input = field->hidinput->input;
+
+       if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
+               return 0;
 
        if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
                        (usage->hid & 0xff) == 0x82) {
+               struct input_dev *input = field->hidinput->input;
                input_event(input, usage->type, usage->code, 1);
                input_sync(input);
                input_event(input, usage->type, usage->code, 0);
index 928943c7ce9a676aaaaa62e2fdb5652aef4ed16c..e71e0057284e563502367ab455249963edde475f 100644 (file)
@@ -60,6 +60,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
index e4595e6147b420de2a4545d45e498d5d5e886ba4..9be8e1754a0bafdc850e7af7ff0932e8b05e509b 100644 (file)
@@ -217,8 +217,8 @@ config SENSORS_ASC7621
        depends on HWMON && I2C
        help
          If you say yes here you get support for the aSC7621
-         family of SMBus sensors chip found on most Intel X48, X38, 975,
-         965 and 945 desktop boards.  Currently supported chips:
+         family of SMBus sensors chip found on most Intel X38, X48, X58,
+         945, 965 and 975 desktop boards.  Currently supported chips:
          aSC7621
          aSC7621a
 
index 2d7bceeed0bc3daf10a8ae2d58d106d575107eb2..e9b7fbc5a4476b9cfdb2bd01ec58719b097cf7cb 100644 (file)
@@ -228,7 +228,7 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *
                if (err) {
                        dev_warn(dev,
                                 "Unable to access MSR 0xEE, for Tjmax, left"
-                                " at default");
+                                " at default\n");
                } else if (eax & 0x40000000) {
                        tjmax = tjmax_ee;
                }
@@ -466,7 +466,7 @@ static int __init coretemp_init(void)
                           family 6 CPU */
                        if ((c->x86 == 0x6) && (c->x86_model > 0xf))
                                printk(KERN_WARNING DRVNAME ": Unknown CPU "
-                                       "model %x\n", c->x86_model);
+                                       "model 0x%x\n", c->x86_model);
                        continue;
                }
 
index 9de81a4c15a2127b774766bda5244bf519d750cf..612807d9715533b3f03afcdf6738fb79767ee55e 100644 (file)
@@ -1294,7 +1294,7 @@ static int watchdog_close(struct inode *inode, struct file *filp)
 static ssize_t watchdog_write(struct file *filp, const char __user *buf,
        size_t count, loff_t *offset)
 {
-       size_t ret;
+       ssize_t ret;
        struct w83793_data *data = filp->private_data;
 
        if (count) {
index 365e0becaf121f7261cbc31ea2f19596415646d6..388cbdc96db7306280b5d4ab6fcc99871e77b7ca 100644 (file)
@@ -33,6 +33,7 @@ struct acpi_smbus_cmi {
        u8 cap_info:1;
        u8 cap_read:1;
        u8 cap_write:1;
+       struct smbus_methods_t *methods;
 };
 
 static const struct smbus_methods_t smbus_methods = {
@@ -41,10 +42,19 @@ static const struct smbus_methods_t smbus_methods = {
        .mt_sbw  = "_SBW",
 };
 
+/* Some IBM BIOSes omit the leading underscore */
+static const struct smbus_methods_t ibm_smbus_methods = {
+       .mt_info = "SBI_",
+       .mt_sbr  = "SBR_",
+       .mt_sbw  = "SBW_",
+};
+
 static const struct acpi_device_id acpi_smbus_cmi_ids[] = {
-       {"SMBUS01", 0},
+       {"SMBUS01", (kernel_ulong_t)&smbus_methods},
+       {ACPI_SMBUS_IBM_HID, (kernel_ulong_t)&ibm_smbus_methods},
        {"", 0}
 };
+MODULE_DEVICE_TABLE(acpi, acpi_smbus_cmi_ids);
 
 #define ACPI_SMBUS_STATUS_OK                   0x00
 #define ACPI_SMBUS_STATUS_FAIL                 0x07
@@ -150,11 +160,11 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
 
        if (read_write == I2C_SMBUS_READ) {
                protocol |= ACPI_SMBUS_PRTCL_READ;
-               method = smbus_methods.mt_sbr;
+               method = smbus_cmi->methods->mt_sbr;
                input.count = 3;
        } else {
                protocol |= ACPI_SMBUS_PRTCL_WRITE;
-               method = smbus_methods.mt_sbw;
+               method = smbus_cmi->methods->mt_sbw;
                input.count = 5;
        }
 
@@ -290,13 +300,13 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
        union acpi_object *obj;
        acpi_status status;
 
-       if (!strcmp(name, smbus_methods.mt_info)) {
+       if (!strcmp(name, smbus_cmi->methods->mt_info)) {
                status = acpi_evaluate_object(smbus_cmi->handle,
-                                       smbus_methods.mt_info,
+                                       smbus_cmi->methods->mt_info,
                                        NULL, &buffer);
                if (ACPI_FAILURE(status)) {
                        ACPI_ERROR((AE_INFO, "Evaluating %s: %i",
-                                  smbus_methods.mt_info, status));
+                                  smbus_cmi->methods->mt_info, status));
                        return -EIO;
                }
 
@@ -319,9 +329,9 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
 
                kfree(buffer.pointer);
                smbus_cmi->cap_info = 1;
-       } else if (!strcmp(name, smbus_methods.mt_sbr))
+       } else if (!strcmp(name, smbus_cmi->methods->mt_sbr))
                smbus_cmi->cap_read = 1;
-       else if (!strcmp(name, smbus_methods.mt_sbw))
+       else if (!strcmp(name, smbus_cmi->methods->mt_sbw))
                smbus_cmi->cap_write = 1;
        else
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported CMI method: %s\n",
@@ -349,6 +359,7 @@ static acpi_status acpi_smbus_cmi_query_methods(acpi_handle handle, u32 level,
 static int acpi_smbus_cmi_add(struct acpi_device *device)
 {
        struct acpi_smbus_cmi *smbus_cmi;
+       const struct acpi_device_id *id;
 
        smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL);
        if (!smbus_cmi)
@@ -362,6 +373,11 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
        smbus_cmi->cap_read = 0;
        smbus_cmi->cap_write = 0;
 
+       for (id = acpi_smbus_cmi_ids; id->id[0]; id++)
+               if (!strcmp(id->id, acpi_device_hid(device)))
+                       smbus_cmi->methods =
+                               (struct smbus_methods_t *) id->driver_data;
+
        acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1,
                            acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL);
 
index fbedd35feb449194e85fe78ee110ccb5ba101e9f..4c3d1bfec0c5b450fbbe68014e1c15fe9e29c454 100644 (file)
@@ -695,14 +695,8 @@ static int ide_probe_port(ide_hwif_t *hwif)
        if (irqd)
                disable_irq(hwif->irq);
 
-       rc = ide_port_wait_ready(hwif);
-       if (rc == -ENODEV) {
-               printk(KERN_INFO "%s: no devices on the port\n", hwif->name);
-               goto out;
-       } else if (rc == -EBUSY)
-               printk(KERN_ERR "%s: not ready before the probe\n", hwif->name);
-       else
-               rc = -ENODEV;
+       if (ide_port_wait_ready(hwif) == -EBUSY)
+               printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
 
        /*
         * Second drive should only exist if first drive was found,
@@ -713,7 +707,7 @@ static int ide_probe_port(ide_hwif_t *hwif)
                if (drive->dev_flags & IDE_DFLAG_PRESENT)
                        rc = 0;
        }
-out:
+
        /*
         * Use cached IRQ number. It might be (and is...) changed by probe
         * code above
index e65d010b708db1fcff3182d7b87a1ed1e7214f06..48fd4efc90ad284255916bfbec1fe2e62d472e4c 100644 (file)
@@ -110,7 +110,6 @@ struct via82cxxx_dev
 {
        struct via_isa_bridge *via_config;
        unsigned int via_80w;
-       u8 cached_device[2];
 };
 
 /**
@@ -403,66 +402,10 @@ static const struct ide_port_ops via_port_ops = {
        .cable_detect           = via82cxxx_cable_detect,
 };
 
-static void via_write_devctl(ide_hwif_t *hwif, u8 ctl)
-{
-       struct via82cxxx_dev *vdev = hwif->host->host_priv;
-
-       outb(ctl, hwif->io_ports.ctl_addr);
-       outb(vdev->cached_device[hwif->channel], hwif->io_ports.device_addr);
-}
-
-static void __via_dev_select(ide_drive_t *drive, u8 select)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct via82cxxx_dev *vdev = hwif->host->host_priv;
-
-       outb(select, hwif->io_ports.device_addr);
-       vdev->cached_device[hwif->channel] = select;
-}
-
-static void via_dev_select(ide_drive_t *drive)
-{
-       __via_dev_select(drive, drive->select | ATA_DEVICE_OBS);
-}
-
-static void via_tf_load(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct ide_io_ports *io_ports = &hwif->io_ports;
-
-       if (valid & IDE_VALID_FEATURE)
-               outb(tf->feature, io_ports->feature_addr);
-       if (valid & IDE_VALID_NSECT)
-               outb(tf->nsect, io_ports->nsect_addr);
-       if (valid & IDE_VALID_LBAL)
-               outb(tf->lbal, io_ports->lbal_addr);
-       if (valid & IDE_VALID_LBAM)
-               outb(tf->lbam, io_ports->lbam_addr);
-       if (valid & IDE_VALID_LBAH)
-               outb(tf->lbah, io_ports->lbah_addr);
-       if (valid & IDE_VALID_DEVICE)
-               __via_dev_select(drive, tf->device);
-}
-
-const struct ide_tp_ops via_tp_ops = {
-       .exec_command           = ide_exec_command,
-       .read_status            = ide_read_status,
-       .read_altstatus         = ide_read_altstatus,
-       .write_devctl           = via_write_devctl,
-
-       .dev_select             = via_dev_select,
-       .tf_load                = via_tf_load,
-       .tf_read                = ide_tf_read,
-
-       .input_data             = ide_input_data,
-       .output_data            = ide_output_data,
-};
-
 static const struct ide_port_info via82cxxx_chipset __devinitdata = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_via82cxxx,
        .enablebits     = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
-       .tp_ops         = &via_tp_ops,
        .port_ops       = &via_port_ops,
        .host_flags     = IDE_HFLAG_PIO_NO_BLACKLIST |
                          IDE_HFLAG_POST_SET_MODE |
index e5deb15cf40c9ec2a2354375ef174afe83e8e05f..8d1d63a02b341f3084410c67c43bb216e35fa1d9 100644 (file)
@@ -50,7 +50,7 @@ module_param(isdnprot, int, 0);
    handler.
 */
 
-static int avma1cs_config(struct pcmcia_device *link);
+static int avma1cs_config(struct pcmcia_device *link) __devinit ;
 static void avma1cs_release(struct pcmcia_device *link);
 
 /*
@@ -59,7 +59,7 @@ static void avma1cs_release(struct pcmcia_device *link);
    needed to manage one actual PCMCIA card.
 */
 
-static void avma1cs_detach(struct pcmcia_device *p_dev);
+static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit ;
 
 
 /*
@@ -99,7 +99,7 @@ typedef struct local_info_t {
     
 ======================================================================*/
 
-static int avma1cs_probe(struct pcmcia_device *p_dev)
+static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
 {
     local_info_t *local;
 
@@ -140,7 +140,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void avma1cs_detach(struct pcmcia_device *link)
+static void __devexit avma1cs_detach(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link);
        avma1cs_release(link);
@@ -174,7 +174,7 @@ static int avma1cs_configcheck(struct pcmcia_device *p_dev,
 }
 
 
-static int avma1cs_config(struct pcmcia_device *link)
+static int __devinit avma1cs_config(struct pcmcia_device *link)
 {
     local_info_t *dev;
     int i;
@@ -282,7 +282,7 @@ static struct pcmcia_driver avma1cs_driver = {
                .name   = "avma1_cs",
        },
        .probe          = avma1cs_probe,
-       .remove         = avma1cs_detach,
+       .remove         = __devexit_p(avma1cs_detach),
        .id_table       = avma1cs_ids,
 };
 
index c9a30b1c92372373a652f877dad6d62d65dbf19f..c9f2279e21f5f0812a9632f16c15081eb0e77773 100644 (file)
@@ -76,7 +76,7 @@ module_param(protocol, int, 0);
    handler.
 */
 
-static int elsa_cs_config(struct pcmcia_device *link);
+static int elsa_cs_config(struct pcmcia_device *link) __devinit ;
 static void elsa_cs_release(struct pcmcia_device *link);
 
 /*
@@ -85,7 +85,7 @@ static void elsa_cs_release(struct pcmcia_device *link);
    needed to manage one actual PCMCIA card.
 */
 
-static void elsa_cs_detach(struct pcmcia_device *p_dev);
+static void elsa_cs_detach(struct pcmcia_device *p_dev) __devexit;
 
 /*
    A driver needs to provide a dev_node_t structure for each device
@@ -121,7 +121,7 @@ typedef struct local_info_t {
 
 ======================================================================*/
 
-static int elsa_cs_probe(struct pcmcia_device *link)
+static int __devinit elsa_cs_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
 
@@ -166,7 +166,7 @@ static int elsa_cs_probe(struct pcmcia_device *link)
 
 ======================================================================*/
 
-static void elsa_cs_detach(struct pcmcia_device *link)
+static void __devexit elsa_cs_detach(struct pcmcia_device *link)
 {
        local_info_t *info = link->priv;
 
@@ -210,7 +210,7 @@ static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
        return -ENODEV;
 }
 
-static int elsa_cs_config(struct pcmcia_device *link)
+static int __devinit elsa_cs_config(struct pcmcia_device *link)
 {
     local_info_t *dev;
     int i;
@@ -327,7 +327,7 @@ static struct pcmcia_driver elsa_cs_driver = {
                .name   = "elsa_cs",
        },
        .probe          = elsa_cs_probe,
-       .remove         = elsa_cs_detach,
+       .remove         = __devexit_p(elsa_cs_detach),
        .id_table       = elsa_ids,
        .suspend        = elsa_suspend,
        .resume         = elsa_resume,
index 7836ec3c7f86fb723131c10185a1ef432ec12d13..71b3ddef03bb790836d7d5ff63a24e8261329eb0 100644 (file)
@@ -76,7 +76,7 @@ module_param(protocol, int, 0);
    event handler. 
 */
 
-static int sedlbauer_config(struct pcmcia_device *link);
+static int sedlbauer_config(struct pcmcia_device *link) __devinit ;
 static void sedlbauer_release(struct pcmcia_device *link);
 
 /*
@@ -85,7 +85,7 @@ static void sedlbauer_release(struct pcmcia_device *link);
    needed to manage one actual PCMCIA card.
 */
 
-static void sedlbauer_detach(struct pcmcia_device *p_dev);
+static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit;
 
 /*
    You'll also need to prototype all the functions that will actually
@@ -129,7 +129,7 @@ typedef struct local_info_t {
     
 ======================================================================*/
 
-static int sedlbauer_probe(struct pcmcia_device *link)
+static int __devinit sedlbauer_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
 
@@ -177,7 +177,7 @@ static int sedlbauer_probe(struct pcmcia_device *link)
 
 ======================================================================*/
 
-static void sedlbauer_detach(struct pcmcia_device *link)
+static void __devexit sedlbauer_detach(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link);
 
@@ -283,7 +283,7 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 
 
 
-static int sedlbauer_config(struct pcmcia_device *link)
+static int __devinit sedlbauer_config(struct pcmcia_device *link)
 {
     local_info_t *dev = link->priv;
     win_req_t *req;
@@ -441,7 +441,7 @@ static struct pcmcia_driver sedlbauer_driver = {
                .name   = "sedlbauer_cs",
        },
        .probe          = sedlbauer_probe,
-       .remove         = sedlbauer_detach,
+       .remove         = __devexit_p(sedlbauer_detach),
        .id_table       = sedlbauer_ids,
        .suspend        = sedlbauer_suspend,
        .resume         = sedlbauer_resume,
index b0c5976cbdb356c8941d77a0dfc54a166379e4d0..d010a0da8e19bdcc04b8a78e631ba6a05f330a15 100644 (file)
@@ -57,7 +57,7 @@ module_param(protocol, int, 0);
    handler.
 */
 
-static int teles_cs_config(struct pcmcia_device *link);
+static int teles_cs_config(struct pcmcia_device *link) __devinit ;
 static void teles_cs_release(struct pcmcia_device *link);
 
 /*
@@ -66,7 +66,7 @@ static void teles_cs_release(struct pcmcia_device *link);
    needed to manage one actual PCMCIA card.
 */
 
-static void teles_detach(struct pcmcia_device *p_dev);
+static void teles_detach(struct pcmcia_device *p_dev) __devexit ;
 
 /*
    A linked list of "instances" of the teles_cs device.  Each actual
@@ -112,7 +112,7 @@ typedef struct local_info_t {
 
 ======================================================================*/
 
-static int teles_probe(struct pcmcia_device *link)
+static int __devinit teles_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
 
@@ -156,7 +156,7 @@ static int teles_probe(struct pcmcia_device *link)
 
 ======================================================================*/
 
-static void teles_detach(struct pcmcia_device *link)
+static void __devexit teles_detach(struct pcmcia_device *link)
 {
        local_info_t *info = link->priv;
 
@@ -200,7 +200,7 @@ static int teles_cs_configcheck(struct pcmcia_device *p_dev,
        return -ENODEV;
 }
 
-static int teles_cs_config(struct pcmcia_device *link)
+static int __devinit teles_cs_config(struct pcmcia_device *link)
 {
     local_info_t *dev;
     int i;
@@ -319,7 +319,7 @@ static struct pcmcia_driver teles_cs_driver = {
                .name   = "teles_cs",
        },
        .probe          = teles_probe,
-       .remove         = teles_detach,
+       .remove         = __devexit_p(teles_detach),
        .id_table       = teles_ids,
        .suspend        = teles_suspend,
        .resume         = teles_resume,
index b5346b4db91a2021d43c470b09bd53fbdc7a4170..b7a85f46a6c2c913d7dc39b8c563daef27ded8d0 100644 (file)
@@ -912,8 +912,8 @@ struct c2port_device *c2port_device_register(char *name,
 
        c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
                                        "c2port%d", id);
-       if (unlikely(!c2dev->dev)) {
-               ret = -ENOMEM;
+       if (unlikely(IS_ERR(c2dev->dev))) {
+               ret = PTR_ERR(c2dev->dev);
                goto error_device_create;
        }
        dev_set_drvdata(c2dev->dev, c2dev);
index fcb6ec1af173dfe22e3130ef6016f348c3f24858..72450237a0f418e0a41552cbdefd7943545add78 100644 (file)
@@ -295,6 +295,10 @@ static int check_and_rewind_pc(char *put_str, char *arg)
        /* On x86 a breakpoint stop requires it to be decremented */
        if (addr + 1 == kgdbts_regs.ip)
                offset = -1;
+#elif defined(CONFIG_SUPERH)
+       /* On SUPERH a breakpoint stop requires it to be decremented */
+       if (addr + 2 == kgdbts_regs.pc)
+               offset = -2;
 #endif
        if (strcmp(arg, "silent") &&
                instruction_pointer(&kgdbts_regs) + offset != addr) {
@@ -305,6 +309,8 @@ static int check_and_rewind_pc(char *put_str, char *arg)
 #ifdef CONFIG_X86
        /* On x86 adjust the instruction pointer if needed */
        kgdbts_regs.ip += offset;
+#elif defined(CONFIG_SUPERH)
+       kgdbts_regs.pc += offset;
 #endif
        return 0;
 }
index 0eac6c81490462fb640d768edbbdec54659510fa..e041c003db224ca68b001c47ae536337e8ed103f 100644 (file)
@@ -225,7 +225,7 @@ static int mmc_read_ext_csd(struct mmc_card *card)
                        mmc_card_set_blockaddr(card);
        }
 
-       switch (ext_csd[EXT_CSD_CARD_TYPE]) {
+       switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
        case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
                card->ext_csd.hs_max_dtr = 52000000;
                break;
@@ -237,7 +237,6 @@ static int mmc_read_ext_csd(struct mmc_card *card)
                printk(KERN_WARNING "%s: card is mmc v4 but doesn't "
                        "support any high-speed modes.\n",
                        mmc_hostname(card->host));
-               goto out;
        }
 
        if (card->ext_csd.rev >= 3) {
index a1d4188c430b6d1ecc321482bba6f46736e88b4f..e7810b74f3965b55d753d259722ee9bbcff2cd9f 100644 (file)
@@ -449,11 +449,10 @@ ks8695_rx_irq(int irq, void *dev_id)
 }
 
 /**
- *     ks8695_rx - Receive packets  called by NAPI poll method
+ *     ks8695_rx - Receive packets called by NAPI poll method
  *     @ksp: Private data for the KS8695 Ethernet
- *     @budget: The max packets would be receive
+ *     @budget: Number of packets allowed to process
  */
-
 static int ks8695_rx(struct ks8695_priv *ksp, int budget)
 {
        struct net_device *ndev = ksp->ndev;
@@ -461,7 +460,6 @@ static int ks8695_rx(struct ks8695_priv *ksp, int budget)
        int buff_n;
        u32 flags;
        int pktlen;
-       int last_rx_processed = -1;
        int received = 0;
 
        buff_n = ksp->next_rx_desc_read;
@@ -471,6 +469,7 @@ static int ks8695_rx(struct ks8695_priv *ksp, int budget)
                                        cpu_to_le32(RDES_OWN)))) {
                        rmb();
                        flags = le32_to_cpu(ksp->rx_ring[buff_n].status);
+
                        /* Found an SKB which we own, this means we
                         * received a packet
                         */
@@ -533,23 +532,18 @@ rx_failure:
                        ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
 rx_finished:
                        received++;
-                       /* And note this as processed so we can start
-                        * from here next time
-                        */
-                       last_rx_processed = buff_n;
                        buff_n = (buff_n + 1) & MAX_RX_DESC_MASK;
-                       /*And note which RX descriptor we last did */
-                       if (likely(last_rx_processed != -1))
-                               ksp->next_rx_desc_read =
-                                       (last_rx_processed + 1) &
-                                       MAX_RX_DESC_MASK;
        }
+
+       /* And note which RX descriptor we last did */
+       ksp->next_rx_desc_read = buff_n;
+
        /* And refill the buffers */
        ks8695_refill_rxbuffers(ksp);
 
-       /* Kick the RX DMA engine, in case it became
-        *  suspended */
+       /* Kick the RX DMA engine, in case it became suspended */
        ks8695_writereg(ksp, KS8695_DRSC, 0);
+
        return received;
 }
 
index 9ba547069db3c44d13005532e550837ea1bb8350..0ebd8208f606afdaf0f387ad3353ccb7b3d958e8 100644 (file)
@@ -84,7 +84,7 @@
 
 #define ATLX_DRIVER_VERSION "2.1.3"
 MODULE_AUTHOR("Xiong Huang <xiong.huang@atheros.com>, \
-       Chris Snook <csnook@redhat.com>, Jay Cliburn <jcliburn@gmail.com>");
+Chris Snook <csnook@redhat.com>, Jay Cliburn <jcliburn@gmail.com>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(ATLX_DRIVER_VERSION);
 
index 9560d48944ab526a49737b6fcfdb23f668e8af20..51e1065e78977df6f27a06eaf58dcdba64da5502 100644 (file)
@@ -490,7 +490,7 @@ be_test_ddr_dma(struct be_adapter *adapter)
 {
        int ret, i;
        struct be_dma_mem ddrdma_cmd;
-       u64 pattern[2] = {0x5a5a5a5a5a5a5a5a, 0xa5a5a5a5a5a5a5a5};
+       u64 pattern[2] = {0x5a5a5a5a5a5a5a5aULL, 0xa5a5a5a5a5a5a5a5ULL};
 
        ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
        ddrdma_cmd.va = pci_alloc_consistent(adapter->pdev, ddrdma_cmd.size,
index 381887ba677c36b39e422e7f76273a5dbfa4f2ff..a257babd1bb4085c184604c4d0b8dcdbbc59f203 100644 (file)
@@ -246,6 +246,8 @@ static const struct flash_spec flash_5709 = {
 
 MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
 
+static void bnx2_init_napi(struct bnx2 *bp);
+
 static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
 {
        u32 diff;
@@ -6197,6 +6199,7 @@ bnx2_open(struct net_device *dev)
        bnx2_disable_int(bp);
 
        bnx2_setup_int_mode(bp, disable_msi);
+       bnx2_init_napi(bp);
        bnx2_napi_enable(bp);
        rc = bnx2_alloc_mem(bp);
        if (rc)
@@ -7643,9 +7646,11 @@ poll_bnx2(struct net_device *dev)
        int i;
 
        for (i = 0; i < bp->irq_nvecs; i++) {
-               disable_irq(bp->irq_tbl[i].vector);
-               bnx2_interrupt(bp->irq_tbl[i].vector, &bp->bnx2_napi[i]);
-               enable_irq(bp->irq_tbl[i].vector);
+               struct bnx2_irq *irq = &bp->irq_tbl[i];
+
+               disable_irq(irq->vector);
+               irq->handler(irq->vector, &bp->bnx2_napi[i]);
+               enable_irq(irq->vector);
        }
 }
 #endif
@@ -8207,7 +8212,7 @@ bnx2_init_napi(struct bnx2 *bp)
 {
        int i;
 
-       for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
+       for (i = 0; i < bp->irq_nvecs; i++) {
                struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
                int (*poll)(struct napi_struct *, int);
 
@@ -8276,7 +8281,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->ethtool_ops = &bnx2_ethtool_ops;
 
        bp = netdev_priv(dev);
-       bnx2_init_napi(bp);
 
        pci_set_drvdata(pdev, dev);
 
index 430c02267d7e9ec26d3c8b59922d919fc5fedb97..5b92fbff431da316f442386564c52c8ae390e927 100644 (file)
@@ -1235,6 +1235,11 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
                        write_lock_bh(&bond->curr_slave_lock);
                }
        }
+
+       /* resend IGMP joins since all were sent on curr_active_slave */
+       if (bond->params.mode == BOND_MODE_ROUNDROBIN) {
+               bond_resend_igmp_join_requests(bond);
+       }
 }
 
 /**
@@ -4138,22 +4143,41 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
        struct bonding *bond = netdev_priv(bond_dev);
        struct slave *slave, *start_at;
        int i, slave_no, res = 1;
+       struct iphdr *iph = ip_hdr(skb);
 
        read_lock(&bond->lock);
 
        if (!BOND_IS_OK(bond))
                goto out;
-
        /*
-        * Concurrent TX may collide on rr_tx_counter; we accept that
-        * as being rare enough not to justify using an atomic op here
+        * Start with the curr_active_slave that joined the bond as the
+        * default for sending IGMP traffic.  For failover purposes one
+        * needs to maintain some consistency for the interface that will
+        * send the join/membership reports.  The curr_active_slave found
+        * will send all of this type of traffic.
         */
-       slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
+       if ((iph->protocol == htons(IPPROTO_IGMP)) &&
+           (skb->protocol == htons(ETH_P_IP))) {
 
-       bond_for_each_slave(bond, slave, i) {
-               slave_no--;
-               if (slave_no < 0)
-                       break;
+               read_lock(&bond->curr_slave_lock);
+               slave = bond->curr_active_slave;
+               read_unlock(&bond->curr_slave_lock);
+
+               if (!slave)
+                       goto out;
+       } else {
+               /*
+                * Concurrent TX may collide on rr_tx_counter; we accept
+                * that as being rare enough not to justify using an
+                * atomic op here.
+                */
+               slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
+
+               bond_for_each_slave(bond, slave, i) {
+                       slave_no--;
+                       if (slave_no < 0)
+                               break;
+               }
        }
 
        start_at = slave;
index 866905fa4119e5c66d18d56875b7e9525a4713c2..03489864376df7ca060927c3afd3d058b41e088b 100644 (file)
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
 
+#include <asm/bfin_can.h>
 #include <asm/portmux.h>
 
 #define DRV_NAME "bfin_can"
 #define BFIN_CAN_TIMEOUT 100
 #define TX_ECHO_SKB_MAX  1
 
-/*
- * transmit and receive channels
- */
-#define TRANSMIT_CHL            24
-#define RECEIVE_STD_CHL         0
-#define RECEIVE_EXT_CHL         4
-#define RECEIVE_RTR_CHL         8
-#define RECEIVE_EXT_RTR_CHL     12
-#define MAX_CHL_NUMBER          32
-
-/*
- * bfin can registers layout
- */
-struct bfin_can_mask_regs {
-       u16 aml;
-       u16 dummy1;
-       u16 amh;
-       u16 dummy2;
-};
-
-struct bfin_can_channel_regs {
-       u16 data[8];
-       u16 dlc;
-       u16 dummy1;
-       u16 tsv;
-       u16 dummy2;
-       u16 id0;
-       u16 dummy3;
-       u16 id1;
-       u16 dummy4;
-};
-
-struct bfin_can_regs {
-       /*
-        * global control and status registers
-        */
-       u16 mc1;           /* offset 0 */
-       u16 dummy1;
-       u16 md1;           /* offset 4 */
-       u16 rsv1[13];
-       u16 mbtif1;        /* offset 0x20 */
-       u16 dummy2;
-       u16 mbrif1;        /* offset 0x24 */
-       u16 dummy3;
-       u16 mbim1;         /* offset 0x28 */
-       u16 rsv2[11];
-       u16 mc2;           /* offset 0x40 */
-       u16 dummy4;
-       u16 md2;           /* offset 0x44 */
-       u16 dummy5;
-       u16 trs2;          /* offset 0x48 */
-       u16 rsv3[11];
-       u16 mbtif2;        /* offset 0x60 */
-       u16 dummy6;
-       u16 mbrif2;        /* offset 0x64 */
-       u16 dummy7;
-       u16 mbim2;         /* offset 0x68 */
-       u16 rsv4[11];
-       u16 clk;           /* offset 0x80 */
-       u16 dummy8;
-       u16 timing;        /* offset 0x84 */
-       u16 rsv5[3];
-       u16 status;        /* offset 0x8c */
-       u16 dummy9;
-       u16 cec;           /* offset 0x90 */
-       u16 dummy10;
-       u16 gis;           /* offset 0x94 */
-       u16 dummy11;
-       u16 gim;           /* offset 0x98 */
-       u16 rsv6[3];
-       u16 ctrl;          /* offset 0xa0 */
-       u16 dummy12;
-       u16 intr;          /* offset 0xa4 */
-       u16 rsv7[7];
-       u16 esr;           /* offset 0xb4 */
-       u16 rsv8[37];
-
-       /*
-        * channel(mailbox) mask and message registers
-        */
-       struct bfin_can_mask_regs msk[MAX_CHL_NUMBER];    /* offset 0x100 */
-       struct bfin_can_channel_regs chl[MAX_CHL_NUMBER]; /* offset 0x200 */
-};
-
 /*
  * bfin can private data
  */
@@ -163,7 +80,7 @@ static int bfin_can_set_bittiming(struct net_device *dev)
        if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
                timing |= SAM;
 
-       bfin_write16(&reg->clk, clk);
+       bfin_write16(&reg->clock, clk);
        bfin_write16(&reg->timing, timing);
 
        dev_info(dev->dev.parent, "setting CLOCK=0x%04x TIMING=0x%04x\n",
@@ -185,11 +102,11 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
        bfin_write16(&reg->gim, 0);
 
        /* reset can and enter configuration mode */
-       bfin_write16(&reg->ctrl, SRS | CCR);
+       bfin_write16(&reg->control, SRS | CCR);
        SSYNC();
-       bfin_write16(&reg->ctrl, CCR);
+       bfin_write16(&reg->control, CCR);
        SSYNC();
-       while (!(bfin_read16(&reg->ctrl) & CCA)) {
+       while (!(bfin_read16(&reg->control) & CCA)) {
                udelay(10);
                if (--timeout == 0) {
                        dev_err(dev->dev.parent,
@@ -244,7 +161,7 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
        /*
         * leave configuration mode
         */
-       bfin_write16(&reg->ctrl, bfin_read16(&reg->ctrl) & ~CCR);
+       bfin_write16(&reg->control, bfin_read16(&reg->control) & ~CCR);
 
        while (bfin_read16(&reg->status) & CCA) {
                udelay(10);
@@ -726,7 +643,7 @@ static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg)
 
        if (netif_running(dev)) {
                /* enter sleep mode */
-               bfin_write16(&reg->ctrl, bfin_read16(&reg->ctrl) | SMR);
+               bfin_write16(&reg->control, bfin_read16(&reg->control) | SMR);
                SSYNC();
                while (!(bfin_read16(&reg->intr) & SMACK)) {
                        udelay(10);
index 9902b33b716052f7974cad7126b923a3068a27be..2f29c213185113c4d36eb095cc88b1190bef6603 100644 (file)
@@ -261,7 +261,6 @@ struct e1000_adapter {
        /* TX */
        struct e1000_tx_ring *tx_ring;      /* One per active queue */
        unsigned int restart_queue;
-       unsigned long tx_queue_len;
        u32 txd_cmd;
        u32 tx_int_delay;
        u32 tx_abs_int_delay;
index 8be6faee43e6e519519d015dd6c1d63a864d7b05..b15ece26ed8469136df4d40eced1b98839e4acce 100644 (file)
@@ -383,8 +383,6 @@ static void e1000_configure(struct e1000_adapter *adapter)
                adapter->alloc_rx_buf(adapter, ring,
                                      E1000_DESC_UNUSED(ring));
        }
-
-       adapter->tx_queue_len = netdev->tx_queue_len;
 }
 
 int e1000_up(struct e1000_adapter *adapter)
@@ -503,7 +501,6 @@ void e1000_down(struct e1000_adapter *adapter)
        del_timer_sync(&adapter->watchdog_timer);
        del_timer_sync(&adapter->phy_info_timer);
 
-       netdev->tx_queue_len = adapter->tx_queue_len;
        adapter->link_speed = 0;
        adapter->link_duplex = 0;
        netif_carrier_off(netdev);
@@ -2316,19 +2313,15 @@ static void e1000_watchdog(unsigned long data)
                                E1000_CTRL_RFCE) ? "RX" : ((ctrl &
                                E1000_CTRL_TFCE) ? "TX" : "None" )));
 
-                       /* tweak tx_queue_len according to speed/duplex
-                        * and adjust the timeout factor */
-                       netdev->tx_queue_len = adapter->tx_queue_len;
+                       /* adjust timeout factor according to speed/duplex */
                        adapter->tx_timeout_factor = 1;
                        switch (adapter->link_speed) {
                        case SPEED_10:
                                txb2b = false;
-                               netdev->tx_queue_len = 10;
                                adapter->tx_timeout_factor = 16;
                                break;
                        case SPEED_100:
                                txb2b = false;
-                               netdev->tx_queue_len = 100;
                                /* maybe add some timeout factor ? */
                                break;
                        }
index c2ec095d2163980953e0bd4ad464fdb8736a9450..118bdf4835938301b37af18b10a45c206abe2b24 100644 (file)
@@ -279,7 +279,6 @@ struct e1000_adapter {
 
        struct napi_struct napi;
 
-       unsigned long tx_queue_len;
        unsigned int restart_queue;
        u32 txd_cmd;
 
index 88d54d3efcef2ff78bd66bd2cd358c8809c22820..e1cceb6065769bf040027049a6fd90f5291d14cf 100644 (file)
@@ -2289,8 +2289,6 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
        ew32(TCTL, tctl);
 
        e1000e_config_collision_dist(hw);
-
-       adapter->tx_queue_len = adapter->netdev->tx_queue_len;
 }
 
 /**
@@ -2877,7 +2875,6 @@ void e1000e_down(struct e1000_adapter *adapter)
        del_timer_sync(&adapter->watchdog_timer);
        del_timer_sync(&adapter->phy_info_timer);
 
-       netdev->tx_queue_len = adapter->tx_queue_len;
        netif_carrier_off(netdev);
        adapter->link_speed = 0;
        adapter->link_duplex = 0;
@@ -3588,21 +3585,15 @@ static void e1000_watchdog_task(struct work_struct *work)
                                               "link gets many collisions.\n");
                        }
 
-                       /*
-                        * tweak tx_queue_len according to speed/duplex
-                        * and adjust the timeout factor
-                        */
-                       netdev->tx_queue_len = adapter->tx_queue_len;
+                       /* adjust timeout factor according to speed/duplex */
                        adapter->tx_timeout_factor = 1;
                        switch (adapter->link_speed) {
                        case SPEED_10:
                                txb2b = 0;
-                               netdev->tx_queue_len = 10;
                                adapter->tx_timeout_factor = 16;
                                break;
                        case SPEED_100:
                                txb2b = 0;
-                               netdev->tx_queue_len = 100;
                                adapter->tx_timeout_factor = 10;
                                break;
                        }
index b6715553cf173e44bb5dc86be57745ed12009b1b..669de028d44fe19de5e43eae055a5453574e762a 100644 (file)
@@ -2393,6 +2393,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev)
         * as many bytes as needed to align the data properly
         */
        skb_reserve(skb, alignamount);
+       GFAR_CB(skb)->alignamount = alignamount;
 
        return skb;
 }
@@ -2533,13 +2534,13 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
                                newskb = skb;
                        else if (skb) {
                                /*
-                                * We need to reset ->data to what it
+                                * We need to un-reserve() the skb to what it
                                 * was before gfar_new_skb() re-aligned
                                 * it to an RXBUF_ALIGNMENT boundary
                                 * before we put the skb back on the
                                 * recycle list.
                                 */
-                               skb->data = skb->head + NET_SKB_PAD;
+                               skb_reserve(skb, -GFAR_CB(skb)->alignamount);
                                __skb_queue_head(&priv->rx_recycle, skb);
                        }
                } else {
index 3d72dc43dca56bdbaba7a510e4e9cb624aa8044f..17d25e714236f305908670efc53fc0c6ace07a08 100644 (file)
@@ -566,6 +566,12 @@ struct rxfcb {
        u16     vlctl;  /* VLAN control word */
 };
 
+struct gianfar_skb_cb {
+       int alignamount;
+};
+
+#define GFAR_CB(skb) ((struct gianfar_skb_cb *)((skb)->cb))
+
 struct rmon_mib
 {
        u32     tr64;   /* 0x.680 - Transmit and Receive 64-byte Frame Counter */
index 9d7fa2fb85ea0cb9de0b7582da337d03d7b9c917..0bc990ec4a8ed68021d36839de41db16b77ce8e3 100644 (file)
@@ -94,6 +94,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
        case E1000_DEV_ID_82576_FIBER:
        case E1000_DEV_ID_82576_SERDES:
        case E1000_DEV_ID_82576_QUAD_COPPER:
+       case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
        case E1000_DEV_ID_82576_SERDES_QUAD:
                mac->type = e1000_82576;
                break;
index 448005276b26b68bdba25be9606aa41185a7ebe6..82a533f5192a545e5d6d631b2cc671e0bb042a5b 100644 (file)
@@ -41,6 +41,7 @@ struct e1000_hw;
 #define E1000_DEV_ID_82576_FIBER              0x10E6
 #define E1000_DEV_ID_82576_SERDES             0x10E7
 #define E1000_DEV_ID_82576_QUAD_COPPER        0x10E8
+#define E1000_DEV_ID_82576_QUAD_COPPER_ET2    0x1526
 #define E1000_DEV_ID_82576_NS                 0x150A
 #define E1000_DEV_ID_82576_NS_SERDES          0x1518
 #define E1000_DEV_ID_82576_SERDES_QUAD        0x150D
index 2a8a886b37eb698bfed13f145b3e677cf363e9c2..be8d010e40213a7b51616fad0e320464a43c751a 100644 (file)
@@ -1367,7 +1367,8 @@ out:
  *  igb_enable_mng_pass_thru - Enable processing of ARP's
  *  @hw: pointer to the HW structure
  *
- *  Verifies the hardware needs to allow ARPs to be processed by the host.
+ *  Verifies the hardware needs to leave interface enabled so that frames can
+ *  be directed to and from the management interface.
  **/
 bool igb_enable_mng_pass_thru(struct e1000_hw *hw)
 {
@@ -1380,8 +1381,7 @@ bool igb_enable_mng_pass_thru(struct e1000_hw *hw)
 
        manc = rd32(E1000_MANC);
 
-       if (!(manc & E1000_MANC_RCV_TCO_EN) ||
-           !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
+       if (!(manc & E1000_MANC_RCV_TCO_EN))
                goto out;
 
        if (hw->mac.arc_subsystem_valid) {
index a1775705b24c93759daf7d63cf0d02a0fd36f089..3b772b822a5dcc61548c8bc98297c8bd9c47efb6 100644 (file)
@@ -267,7 +267,6 @@ struct igb_adapter {
 
        /* TX */
        struct igb_ring *tx_ring[16];
-       unsigned long tx_queue_len;
        u32 tx_timeout_count;
 
        /* RX */
index 0ed25f059a00732345f34ecbf721a167ed9c1cc2..01c65c7447e1c8dd784534c872a36bfd0a7fe6bc 100644 (file)
@@ -72,6 +72,7 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD), board_82575 },
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER_ET2), board_82575 },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER), board_82575 },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 },
@@ -1104,9 +1105,6 @@ static void igb_configure(struct igb_adapter *adapter)
                struct igb_ring *ring = adapter->rx_ring[i];
                igb_alloc_rx_buffers_adv(ring, igb_desc_unused(ring));
        }
-
-
-       adapter->tx_queue_len = netdev->tx_queue_len;
 }
 
 /**
@@ -1212,7 +1210,6 @@ void igb_down(struct igb_adapter *adapter)
        del_timer_sync(&adapter->watchdog_timer);
        del_timer_sync(&adapter->phy_info_timer);
 
-       netdev->tx_queue_len = adapter->tx_queue_len;
        netif_carrier_off(netdev);
 
        /* record the stats before reset*/
@@ -3105,17 +3102,13 @@ static void igb_watchdog_task(struct work_struct *work)
                               ((ctrl & E1000_CTRL_RFCE) ?  "RX" :
                               ((ctrl & E1000_CTRL_TFCE) ?  "TX" : "None")));
 
-                       /* tweak tx_queue_len according to speed/duplex and
-                        * adjust the timeout factor */
-                       netdev->tx_queue_len = adapter->tx_queue_len;
+                       /* adjust timeout factor according to speed/duplex */
                        adapter->tx_timeout_factor = 1;
                        switch (adapter->link_speed) {
                        case SPEED_10:
-                               netdev->tx_queue_len = 10;
                                adapter->tx_timeout_factor = 14;
                                break;
                        case SPEED_100:
-                               netdev->tx_queue_len = 100;
                                /* maybe add some timeout factor ? */
                                break;
                        }
@@ -3962,7 +3955,7 @@ void igb_update_stats(struct igb_adapter *adapter)
        struct net_device_stats *net_stats = igb_get_stats(adapter->netdev);
        struct e1000_hw *hw = &adapter->hw;
        struct pci_dev *pdev = adapter->pdev;
-       u32 rnbc, reg;
+       u32 reg, mpc;
        u16 phy_tmp;
        int i;
        u64 bytes, packets;
@@ -4020,7 +4013,9 @@ void igb_update_stats(struct igb_adapter *adapter)
        adapter->stats.symerrs += rd32(E1000_SYMERRS);
        adapter->stats.sec += rd32(E1000_SEC);
 
-       adapter->stats.mpc += rd32(E1000_MPC);
+       mpc = rd32(E1000_MPC);
+       adapter->stats.mpc += mpc;
+       net_stats->rx_fifo_errors += mpc;
        adapter->stats.scc += rd32(E1000_SCC);
        adapter->stats.ecol += rd32(E1000_ECOL);
        adapter->stats.mcc += rd32(E1000_MCC);
@@ -4035,9 +4030,7 @@ void igb_update_stats(struct igb_adapter *adapter)
        adapter->stats.gptc += rd32(E1000_GPTC);
        adapter->stats.gotc += rd32(E1000_GOTCL);
        rd32(E1000_GOTCH); /* clear GOTCL */
-       rnbc = rd32(E1000_RNBC);
-       adapter->stats.rnbc += rnbc;
-       net_stats->rx_fifo_errors += rnbc;
+       adapter->stats.rnbc += rd32(E1000_RNBC);
        adapter->stats.ruc += rd32(E1000_RUC);
        adapter->stats.rfc += rd32(E1000_RFC);
        adapter->stats.rjc += rd32(E1000_RJC);
@@ -5109,7 +5102,7 @@ static void igb_receive_skb(struct igb_q_vector *q_vector,
 {
        struct igb_adapter *adapter = q_vector->adapter;
 
-       if (vlan_tag)
+       if (vlan_tag && adapter->vlgrp)
                vlan_gro_receive(&q_vector->napi, adapter->vlgrp,
                                 vlan_tag, skb);
        else
index a1774b29d222093851ce46e29d5871d9cc69e286..debeee2dc717c6f86261c53ea93f46b84a07e9ca 100644 (file)
@@ -198,7 +198,6 @@ struct igbvf_adapter {
        struct igbvf_ring *tx_ring /* One per active queue */
        ____cacheline_aligned_in_smp;
 
-       unsigned long tx_queue_len;
        unsigned int restart_queue;
        u32 txd_cmd;
 
index a77afd8a14bbfd30fed68c02cb1861e6113f50fa..b41037ed8083107a7d736a9a54ebacbd989f0d85 100644 (file)
@@ -1304,8 +1304,6 @@ static void igbvf_configure_tx(struct igbvf_adapter *adapter)
 
        /* enable Report Status bit */
        adapter->txd_cmd |= E1000_ADVTXD_DCMD_RS;
-
-       adapter->tx_queue_len = adapter->netdev->tx_queue_len;
 }
 
 /**
@@ -1524,7 +1522,6 @@ void igbvf_down(struct igbvf_adapter *adapter)
 
        del_timer_sync(&adapter->watchdog_timer);
 
-       netdev->tx_queue_len = adapter->tx_queue_len;
        netif_carrier_off(netdev);
 
        /* record the stats before reset*/
@@ -1857,21 +1854,15 @@ static void igbvf_watchdog_task(struct work_struct *work)
                                                  &adapter->link_duplex);
                        igbvf_print_link_info(adapter);
 
-                       /*
-                        * tweak tx_queue_len according to speed/duplex
-                        * and adjust the timeout factor
-                        */
-                       netdev->tx_queue_len = adapter->tx_queue_len;
+                       /* adjust timeout factor according to speed/duplex */
                        adapter->tx_timeout_factor = 1;
                        switch (adapter->link_speed) {
                        case SPEED_10:
                                txb2b = 0;
-                               netdev->tx_queue_len = 10;
                                adapter->tx_timeout_factor = 16;
                                break;
                        case SPEED_100:
                                txb2b = 0;
-                               netdev->tx_queue_len = 100;
                                /* maybe add some timeout factor ? */
                                break;
                        }
index 19e94ee155a265f09a7560d3e78ae5d796528e31..79c35ae3718c96186898452e286d59d5e0482814 100644 (file)
@@ -204,14 +204,17 @@ enum ixgbe_ring_f_enum {
 #define IXGBE_MAX_FDIR_INDICES 64
 #ifdef IXGBE_FCOE
 #define IXGBE_MAX_FCOE_INDICES  8
+#define MAX_RX_QUEUES (IXGBE_MAX_FDIR_INDICES + IXGBE_MAX_FCOE_INDICES)
+#define MAX_TX_QUEUES (IXGBE_MAX_FDIR_INDICES + IXGBE_MAX_FCOE_INDICES)
+#else
+#define MAX_RX_QUEUES IXGBE_MAX_FDIR_INDICES
+#define MAX_TX_QUEUES IXGBE_MAX_FDIR_INDICES
 #endif /* IXGBE_FCOE */
 struct ixgbe_ring_feature {
        int indices;
        int mask;
 } ____cacheline_internodealigned_in_smp;
 
-#define MAX_RX_QUEUES 128
-#define MAX_TX_QUEUES 128
 
 #define MAX_RX_PACKET_BUFFERS ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) \
                               ? 8 : 1)
index 1f30e163bd9cc2ff904b4349acb3960ff6974035..b405a00817c66f248ac671476f214a7aaffe2f3c 100644 (file)
@@ -39,6 +39,7 @@
 #define IXGBE_82599_MC_TBL_SIZE   128
 #define IXGBE_82599_VFT_TBL_SIZE  128
 
+void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
 s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                                           ixgbe_link_speed speed,
                                           bool autoneg,
@@ -68,7 +69,9 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
        if (hw->phy.multispeed_fiber) {
                /* Set up dual speed SFP+ support */
                mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
+               mac->ops.flap_tx_laser = &ixgbe_flap_tx_laser_multispeed_fiber;
        } else {
+               mac->ops.flap_tx_laser = NULL;
                if ((mac->ops.get_media_type(hw) ==
                     ixgbe_media_type_backplane) &&
                    (hw->phy.smart_speed == ixgbe_smart_speed_auto ||
@@ -412,6 +415,41 @@ s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
        return status;
 }
 
+/**
+ *  ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser
+ *  @hw: pointer to hardware structure
+ *
+ *  When the driver changes the link speeds that it can support,
+ *  it sets autotry_restart to true to indicate that we need to
+ *  initiate a new autotry session with the link partner.  To do
+ *  so, we set the speed then disable and re-enable the tx laser, to
+ *  alert the link partner that it also needs to restart autotry on its
+ *  end.  This is consistent with true clause 37 autoneg, which also
+ *  involves a loss of signal.
+ **/
+void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+{
+       u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+
+       hw_dbg(hw, "ixgbe_flap_tx_laser_multispeed_fiber\n");
+
+       if (hw->mac.autotry_restart) {
+               /* Disable tx laser; allow 100us to go dark per spec */
+               esdp_reg |= IXGBE_ESDP_SDP3;
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+               IXGBE_WRITE_FLUSH(hw);
+               udelay(100);
+
+               /* Enable tx laser; allow 100ms to light up */
+               esdp_reg &= ~IXGBE_ESDP_SDP3;
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+               IXGBE_WRITE_FLUSH(hw);
+               msleep(100);
+
+               hw->mac.autotry_restart = false;
+       }
+}
+
 /**
  *  ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
  *  @hw: pointer to hardware structure
@@ -439,16 +477,6 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
        hw->mac.ops.get_link_capabilities(hw, &phy_link_speed, &negotiation);
        speed &= phy_link_speed;
 
-       /*
-        * When the driver changes the link speeds that it can support,
-        * it sets autotry_restart to true to indicate that we need to
-        * initiate a new autotry session with the link partner.  To do
-        * so, we set the speed then disable and re-enable the tx laser, to
-        * alert the link partner that it also needs to restart autotry on its
-        * end.  This is consistent with true clause 37 autoneg, which also
-        * involves a loss of signal.
-        */
-
        /*
         * Try each speed one by one, highest priority first.  We do this in
         * software because 10gb fiber doesn't support speed autonegotiation.
@@ -466,6 +494,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                /* Set the module link speed */
                esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
                IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+               IXGBE_WRITE_FLUSH(hw);
 
                /* Allow module to change analog characteristics (1G->10G) */
                msleep(40);
@@ -478,19 +507,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                        return status;
 
                /* Flap the tx laser if it has not already been done */
-               if (hw->mac.autotry_restart) {
-                       /* Disable tx laser; allow 100us to go dark per spec */
-                       esdp_reg |= IXGBE_ESDP_SDP3;
-                       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
-                       udelay(100);
-
-                       /* Enable tx laser; allow 2ms to light up per spec */
-                       esdp_reg &= ~IXGBE_ESDP_SDP3;
-                       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
-                       msleep(2);
-
-                       hw->mac.autotry_restart = false;
-               }
+               hw->mac.ops.flap_tx_laser(hw);
 
                /*
                 * Wait for the controller to acquire link.  Per IEEE 802.3ap,
@@ -525,6 +542,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                esdp_reg &= ~IXGBE_ESDP_SDP5;
                esdp_reg |= IXGBE_ESDP_SDP5_DIR;
                IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+               IXGBE_WRITE_FLUSH(hw);
 
                /* Allow module to change analog characteristics (10G->1G) */
                msleep(40);
@@ -537,19 +555,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                        return status;
 
                /* Flap the tx laser if it has not already been done */
-               if (hw->mac.autotry_restart) {
-                       /* Disable tx laser; allow 100us to go dark per spec */
-                       esdp_reg |= IXGBE_ESDP_SDP3;
-                       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
-                       udelay(100);
-
-                       /* Enable tx laser; allow 2ms to light up per spec */
-                       esdp_reg &= ~IXGBE_ESDP_SDP3;
-                       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
-                       msleep(2);
-
-                       hw->mac.autotry_restart = false;
-               }
+               hw->mac.ops.flap_tx_laser(hw);
 
                /* Wait for the link partner to also set speed */
                msleep(100);
index 7949a446e4c7673f2587ec6da3b33c1a06574cae..1959ef76c9622c9d2bc467ab0ef94a5cbf5c812c 100644 (file)
@@ -1853,6 +1853,26 @@ static void ixgbe_diag_test(struct net_device *netdev,
                if (ixgbe_link_test(adapter, &data[4]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
+               if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+                       int i;
+                       for (i = 0; i < adapter->num_vfs; i++) {
+                               if (adapter->vfinfo[i].clear_to_send) {
+                                       netdev_warn(netdev, "%s",
+                                                   "offline diagnostic is not "
+                                                   "supported when VFs are "
+                                                   "present\n");
+                                       data[0] = 1;
+                                       data[1] = 1;
+                                       data[2] = 1;
+                                       data[3] = 1;
+                                       eth_test->flags |= ETH_TEST_FL_FAILED;
+                                       clear_bit(__IXGBE_TESTING,
+                                                 &adapter->state);
+                                       goto skip_ol_tests;
+                               }
+                       }
+               }
+
                if (if_running)
                        /* indicate we're in test mode */
                        dev_close(netdev);
@@ -1908,6 +1928,7 @@ skip_loopback:
 
                clear_bit(__IXGBE_TESTING, &adapter->state);
        }
+skip_ol_tests:
        msleep_interruptible(4 * 1000);
 }
 
index 4123dec0dfb7aa39554624f01b6258579f44f004..9276d5965b0d13271d64e4232cb6e9641e494430 100644 (file)
@@ -202,6 +202,15 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
                addr = sg_dma_address(sg);
                len = sg_dma_len(sg);
                while (len) {
+                       /* max number of buffers allowed in one DDP context */
+                       if (j >= IXGBE_BUFFCNT_MAX) {
+                               netif_err(adapter, drv, adapter->netdev,
+                                         "xid=%x:%d,%d,%d:addr=%llx "
+                                         "not enough descriptors\n",
+                                         xid, i, j, dmacount, (u64)addr);
+                               goto out_noddp_free;
+                       }
+
                        /* get the offset of length of current buffer */
                        thisoff = addr & ((dma_addr_t)bufflen - 1);
                        thislen = min((bufflen - thisoff), len);
@@ -227,20 +236,13 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
                        len -= thislen;
                        addr += thislen;
                        j++;
-                       /* max number of buffers allowed in one DDP context */
-                       if (j > IXGBE_BUFFCNT_MAX) {
-                               DPRINTK(DRV, ERR, "xid=%x:%d,%d,%d:addr=%llx "
-                                       "not enough descriptors\n",
-                                       xid, i, j, dmacount, (u64)addr);
-                               goto out_noddp_free;
-                       }
                }
        }
        /* only the last buffer may have non-full bufflen */
        lastsize = thisoff + thislen;
 
        fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
-       fcbuff |= (j << IXGBE_FCBUFF_BUFFCNT_SHIFT);
+       fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT);
        fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT);
        fcbuff |= (IXGBE_FCBUFF_VALID);
 
@@ -520,6 +522,9 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
        /* Enable L2 eth type filter for FCoE */
        IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FCOE),
                        (ETH_P_FCOE | IXGBE_ETQF_FCOE | IXGBE_ETQF_FILTER_EN));
+       /* Enable L2 eth type filter for FIP */
+       IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FIP),
+                       (ETH_P_FIP | IXGBE_ETQF_FILTER_EN));
        if (adapter->ring_feature[RING_F_FCOE].indices) {
                /* Use multiple rx queues for FCoE by redirection table */
                for (i = 0; i < IXGBE_FCRETA_SIZE; i++) {
@@ -530,6 +535,12 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
                }
                IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, IXGBE_FCRECTL_ENA);
                IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE), 0);
+               fcoe_i = f->mask;
+               fcoe_i &= IXGBE_FCRETA_ENTRY_MASK;
+               fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx;
+               IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FIP),
+                               IXGBE_ETQS_QUEUE_EN |
+                               (fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT));
        } else  {
                /* Use single rx queue for FCoE */
                fcoe_i = f->mask;
@@ -539,6 +550,12 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
                                IXGBE_ETQS_QUEUE_EN |
                                (fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT));
        }
+       /* send FIP frames to the first FCoE queue */
+       fcoe_i = f->mask;
+       fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx;
+       IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FIP),
+                       IXGBE_ETQS_QUEUE_EN |
+                       (fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT));
 
        IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL,
                        IXGBE_FCRXCTRL_FCOELLI |
@@ -614,9 +631,9 @@ int ixgbe_fcoe_enable(struct net_device *netdev)
        netdev->vlan_features |= NETIF_F_FSO;
        netdev->vlan_features |= NETIF_F_FCOE_MTU;
        netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
-       netdev_features_change(netdev);
 
        ixgbe_init_interrupt_scheme(adapter);
+       netdev_features_change(netdev);
 
        if (netif_running(netdev))
                netdev->netdev_ops->ndo_open(netdev);
@@ -660,11 +677,11 @@ int ixgbe_fcoe_disable(struct net_device *netdev)
        netdev->vlan_features &= ~NETIF_F_FSO;
        netdev->vlan_features &= ~NETIF_F_FCOE_MTU;
        netdev->fcoe_ddp_xid = 0;
-       netdev_features_change(netdev);
 
        ixgbe_cleanup_fcoe(adapter);
-
        ixgbe_init_interrupt_scheme(adapter);
+       netdev_features_change(netdev);
+
        if (netif_running(netdev))
                netdev->netdev_ops->ndo_open(netdev);
        rc = 0;
index 684af371462dc32975f955ef0e96ac8063c09b02..0c553f6cb53485e11b875a00aa8d8c3b1d0f1226 100644 (file)
@@ -935,10 +935,12 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                        if (skb->prev)
                                skb = ixgbe_transform_rsc_queue(skb, &(rx_ring->rsc_count));
                        if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
-                               if (IXGBE_RSC_CB(skb)->dma)
+                               if (IXGBE_RSC_CB(skb)->dma) {
                                        pci_unmap_single(pdev, IXGBE_RSC_CB(skb)->dma,
                                                         rx_ring->rx_buf_len,
                                                         PCI_DMA_FROMDEVICE);
+                                       IXGBE_RSC_CB(skb)->dma = 0;
+                               }
                                if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)
                                        rx_ring->rsc_count += skb_shinfo(skb)->nr_frags;
                                else
@@ -3054,6 +3056,14 @@ void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)
        while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
                msleep(1);
        ixgbe_down(adapter);
+       /*
+        * If SR-IOV enabled then wait a bit before bringing the adapter
+        * back up to give the VFs time to respond to the reset.  The
+        * two second wait is based upon the watchdog timer cycle in
+        * the VF driver.
+        */
+       if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+               msleep(2000);
        ixgbe_up(adapter);
        clear_bit(__IXGBE_RESETTING, &adapter->state);
 }
@@ -3126,10 +3136,12 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
                        rx_buffer_info->skb = NULL;
                        do {
                                struct sk_buff *this = skb;
-                               if (IXGBE_RSC_CB(this)->dma)
+                               if (IXGBE_RSC_CB(this)->dma) {
                                        pci_unmap_single(pdev, IXGBE_RSC_CB(this)->dma,
                                                         rx_ring->rx_buf_len,
                                                         PCI_DMA_FROMDEVICE);
+                                       IXGBE_RSC_CB(this)->dma = 0;
+                               }
                                skb = skb->prev;
                                dev_kfree_skb(this);
                        } while (skb);
@@ -3232,13 +3244,15 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
 
        /* disable receive for all VFs and wait one second */
        if (adapter->num_vfs) {
-               for (i = 0 ; i < adapter->num_vfs; i++)
-                       adapter->vfinfo[i].clear_to_send = 0;
-
                /* ping all the active vfs to let them know we are going down */
                ixgbe_ping_all_vfs(adapter);
+
                /* Disable all VFTE/VFRE TX/RX */
                ixgbe_disable_tx_rx(adapter);
+
+               /* Mark all the VFs as inactive */
+               for (i = 0 ; i < adapter->num_vfs; i++)
+                       adapter->vfinfo[i].clear_to_send = 0;
        }
 
        /* disable receives */
@@ -5018,6 +5032,7 @@ static void ixgbe_multispeed_fiber_task(struct work_struct *work)
        autoneg = hw->phy.autoneg_advertised;
        if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
                hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiation);
+       hw->mac.autotry_restart = false;
        if (hw->mac.ops.setup_link)
                hw->mac.ops.setup_link(hw, autoneg, negotiation, true);
        adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
@@ -5633,7 +5648,8 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
 
 #ifdef IXGBE_FCOE
        if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
-           (skb->protocol == htons(ETH_P_FCOE))) {
+           ((skb->protocol == htons(ETH_P_FCOE)) ||
+            (skb->protocol == htons(ETH_P_FIP)))) {
                txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1);
                txq += adapter->ring_feature[RING_F_FCOE].mask;
                return txq;
@@ -5680,18 +5696,25 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
 
        tx_ring = adapter->tx_ring[skb->queue_mapping];
 
-       if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
-           (skb->protocol == htons(ETH_P_FCOE))) {
-               tx_flags |= IXGBE_TX_FLAGS_FCOE;
 #ifdef IXGBE_FCOE
+       if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
 #ifdef CONFIG_IXGBE_DCB
-               tx_flags &= ~(IXGBE_TX_FLAGS_VLAN_PRIO_MASK
-                             << IXGBE_TX_FLAGS_VLAN_SHIFT);
-               tx_flags |= ((adapter->fcoe.up << 13)
-                             << IXGBE_TX_FLAGS_VLAN_SHIFT);
-#endif
+               /* for FCoE with DCB, we force the priority to what
+                * was specified by the switch */
+               if ((skb->protocol == htons(ETH_P_FCOE)) ||
+                   (skb->protocol == htons(ETH_P_FIP))) {
+                       tx_flags &= ~(IXGBE_TX_FLAGS_VLAN_PRIO_MASK
+                                     << IXGBE_TX_FLAGS_VLAN_SHIFT);
+                       tx_flags |= ((adapter->fcoe.up << 13)
+                                    << IXGBE_TX_FLAGS_VLAN_SHIFT);
+               }
 #endif
+               /* flag for FCoE offloads */
+               if (skb->protocol == htons(ETH_P_FCOE))
+                       tx_flags |= IXGBE_TX_FLAGS_FCOE;
        }
+#endif
+
        /* four things can cause us to need a context descriptor */
        if (skb_is_gso(skb) ||
            (skb->ip_summed == CHECKSUM_PARTIAL) ||
@@ -6046,7 +6069,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        indices += min_t(unsigned int, num_possible_cpus(),
                         IXGBE_MAX_FCOE_INDICES);
 #endif
-       indices = min_t(unsigned int, indices, MAX_TX_QUEUES);
        netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), indices);
        if (!netdev) {
                err = -ENOMEM;
@@ -6245,9 +6267,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        case IXGBE_DEV_ID_82599_KX4:
                adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
                                IXGBE_WUFC_MC | IXGBE_WUFC_BC);
-               /* Enable ACPI wakeup in GRC */
-               IXGBE_WRITE_REG(hw, IXGBE_GRC,
-                            (IXGBE_READ_REG(hw, IXGBE_GRC) & ~IXGBE_GRC_APME));
                break;
        default:
                adapter->wol = 0;
@@ -6380,6 +6399,16 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
        del_timer_sync(&adapter->sfp_timer);
        cancel_work_sync(&adapter->watchdog_task);
        cancel_work_sync(&adapter->sfp_task);
+       if (adapter->hw.phy.multispeed_fiber) {
+               struct ixgbe_hw *hw = &adapter->hw;
+               /*
+                * Restart clause 37 autoneg, disable and re-enable
+                * the tx laser, to clear & alert the link partner
+                * that it needs to restart autotry
+                */
+               hw->mac.autotry_restart = true;
+               hw->mac.ops.flap_tx_laser(hw);
+       }
        cancel_work_sync(&adapter->multispeed_fiber_task);
        cancel_work_sync(&adapter->sfp_config_module_task);
        if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
index 2be907466593a6e1c119403981226a6155be869c..4ec6dc1a5b75c06a800d3bc7d61f8c2e6cab7853 100644 (file)
 #define IXGBE_ETQF_FILTER_BCN            1
 #define IXGBE_ETQF_FILTER_FCOE           2
 #define IXGBE_ETQF_FILTER_1588           3
+#define IXGBE_ETQF_FILTER_FIP            4
 /* VLAN Control Bit Masks */
 #define IXGBE_VLNCTRL_VET       0x0000FFFF  /* bits 0-15 */
 #define IXGBE_VLNCTRL_CFI       0x10000000  /* bit 28 */
@@ -2397,6 +2398,7 @@ struct ixgbe_mac_operations {
        s32 (*enable_rx_dma)(struct ixgbe_hw *, u32);
 
        /* Link */
+       void (*flap_tx_laser)(struct ixgbe_hw *);
        s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool);
        s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool);
        s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *,
index 399be0c34c36d8593cc8c513745be26d0448775d..6fdd651abcd104d3484b7bedfeac0cd21942ce55 100644 (file)
@@ -46,22 +46,32 @@ struct ixgbe_stats {
        int sizeof_stat;
        int stat_offset;
        int base_stat_offset;
+       int saved_reset_offset;
 };
 
-#define IXGBEVF_STAT(m, b)  sizeof(((struct ixgbevf_adapter *)0)->m), \
-                           offsetof(struct ixgbevf_adapter, m),      \
-                           offsetof(struct ixgbevf_adapter, b)
+#define IXGBEVF_STAT(m, b, r)  sizeof(((struct ixgbevf_adapter *)0)->m), \
+                           offsetof(struct ixgbevf_adapter, m),         \
+                           offsetof(struct ixgbevf_adapter, b),         \
+                           offsetof(struct ixgbevf_adapter, r)
 static struct ixgbe_stats ixgbe_gstrings_stats[] = {
-       {"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc)},
-       {"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc)},
-       {"rx_bytes", IXGBEVF_STAT(stats.vfgorc, stats.base_vfgorc)},
-       {"tx_bytes", IXGBEVF_STAT(stats.vfgotc, stats.base_vfgotc)},
-       {"tx_busy", IXGBEVF_STAT(tx_busy, zero_base)},
-       {"multicast", IXGBEVF_STAT(stats.vfmprc, stats.base_vfmprc)},
-       {"rx_csum_offload_good", IXGBEVF_STAT(hw_csum_rx_good, zero_base)},
-       {"rx_csum_offload_errors", IXGBEVF_STAT(hw_csum_rx_error, zero_base)},
-       {"tx_csum_offload_ctxt", IXGBEVF_STAT(hw_csum_tx_good, zero_base)},
-       {"rx_header_split", IXGBEVF_STAT(rx_hdr_split, zero_base)},
+       {"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc,
+                                   stats.saved_reset_vfgprc)},
+       {"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc,
+                                   stats.saved_reset_vfgptc)},
+       {"rx_bytes", IXGBEVF_STAT(stats.vfgorc, stats.base_vfgorc,
+                                 stats.saved_reset_vfgorc)},
+       {"tx_bytes", IXGBEVF_STAT(stats.vfgotc, stats.base_vfgotc,
+                                 stats.saved_reset_vfgotc)},
+       {"tx_busy", IXGBEVF_STAT(tx_busy, zero_base, zero_base)},
+       {"multicast", IXGBEVF_STAT(stats.vfmprc, stats.base_vfmprc,
+                                  stats.saved_reset_vfmprc)},
+       {"rx_csum_offload_good", IXGBEVF_STAT(hw_csum_rx_good, zero_base,
+                                             zero_base)},
+       {"rx_csum_offload_errors", IXGBEVF_STAT(hw_csum_rx_error, zero_base,
+                                               zero_base)},
+       {"tx_csum_offload_ctxt", IXGBEVF_STAT(hw_csum_tx_good, zero_base,
+                                             zero_base)},
+       {"rx_header_split", IXGBEVF_STAT(rx_hdr_split, zero_base, zero_base)},
 };
 
 #define IXGBE_QUEUE_STATS_LEN 0
@@ -455,10 +465,14 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev,
                        ixgbe_gstrings_stats[i].stat_offset;
                char *b = (char *)adapter +
                        ixgbe_gstrings_stats[i].base_stat_offset;
+               char *r = (char *)adapter +
+                       ixgbe_gstrings_stats[i].saved_reset_offset;
                data[i] = ((ixgbe_gstrings_stats[i].sizeof_stat ==
                            sizeof(u64)) ? *(u64 *)p : *(u32 *)p) -
                          ((ixgbe_gstrings_stats[i].sizeof_stat ==
-                           sizeof(u64)) ? *(u64 *)b : *(u32 *)b);
+                           sizeof(u64)) ? *(u64 *)b : *(u32 *)b) +
+                         ((ixgbe_gstrings_stats[i].sizeof_stat ==
+                           sizeof(u64)) ? *(u64 *)r : *(u32 *)r);
        }
 }
 
index ca653c49b765ecd44d9b45616bcf91c7e6372d48..1bbbef3ee3f49c3eb72828de449e773f076c1407 100644 (file)
@@ -965,7 +965,7 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data)
 
        if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG)
                mod_timer(&adapter->watchdog_timer,
-                         round_jiffies(jiffies + 10));
+                         round_jiffies(jiffies + 1));
 
        return IRQ_HANDLED;
 }
@@ -1610,6 +1610,44 @@ static inline void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter,
                                (adapter->rx_ring[rxr].count - 1));
 }
 
+static void ixgbevf_save_reset_stats(struct ixgbevf_adapter *adapter)
+{
+       /* Only save pre-reset stats if there are some */
+       if (adapter->stats.vfgprc || adapter->stats.vfgptc) {
+               adapter->stats.saved_reset_vfgprc += adapter->stats.vfgprc -
+                       adapter->stats.base_vfgprc;
+               adapter->stats.saved_reset_vfgptc += adapter->stats.vfgptc -
+                       adapter->stats.base_vfgptc;
+               adapter->stats.saved_reset_vfgorc += adapter->stats.vfgorc -
+                       adapter->stats.base_vfgorc;
+               adapter->stats.saved_reset_vfgotc += adapter->stats.vfgotc -
+                       adapter->stats.base_vfgotc;
+               adapter->stats.saved_reset_vfmprc += adapter->stats.vfmprc -
+                       adapter->stats.base_vfmprc;
+       }
+}
+
+static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+
+       adapter->stats.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC);
+       adapter->stats.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB);
+       adapter->stats.last_vfgorc |=
+               (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32);
+       adapter->stats.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC);
+       adapter->stats.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB);
+       adapter->stats.last_vfgotc |=
+               (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32);
+       adapter->stats.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC);
+
+       adapter->stats.base_vfgprc = adapter->stats.last_vfgprc;
+       adapter->stats.base_vfgorc = adapter->stats.last_vfgorc;
+       adapter->stats.base_vfgptc = adapter->stats.last_vfgptc;
+       adapter->stats.base_vfgotc = adapter->stats.last_vfgotc;
+       adapter->stats.base_vfmprc = adapter->stats.last_vfmprc;
+}
+
 static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
@@ -1656,6 +1694,9 @@ static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
        /* enable transmits */
        netif_tx_start_all_queues(netdev);
 
+       ixgbevf_save_reset_stats(adapter);
+       ixgbevf_init_last_counter_stats(adapter);
+
        /* bring the link up in the watchdog, this could race with our first
         * link up interrupt but shouldn't be a problem */
        adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
@@ -2228,27 +2269,6 @@ out:
        return err;
 }
 
-static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter)
-{
-       struct ixgbe_hw *hw = &adapter->hw;
-
-       adapter->stats.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC);
-       adapter->stats.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB);
-       adapter->stats.last_vfgorc |=
-               (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32);
-       adapter->stats.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC);
-       adapter->stats.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB);
-       adapter->stats.last_vfgotc |=
-               (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32);
-       adapter->stats.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC);
-
-       adapter->stats.base_vfgprc = adapter->stats.last_vfgprc;
-       adapter->stats.base_vfgorc = adapter->stats.last_vfgorc;
-       adapter->stats.base_vfgptc = adapter->stats.last_vfgptc;
-       adapter->stats.base_vfgotc = adapter->stats.last_vfgotc;
-       adapter->stats.base_vfmprc = adapter->stats.last_vfmprc;
-}
-
 #define UPDATE_VF_COUNTER_32bit(reg, last_counter, counter)    \
        {                                                       \
                u32 current_counter = IXGBE_READ_REG(hw, reg);  \
@@ -2399,7 +2419,7 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
                if (!netif_carrier_ok(netdev)) {
                        hw_dbg(&adapter->hw, "NIC Link is Up %s, ",
                               ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) ?
-                               "10 Gbps" : "1 Gbps"));
+                               "10 Gbps\n" : "1 Gbps\n"));
                        netif_carrier_on(netdev);
                        netif_tx_wake_all_queues(netdev);
                } else {
@@ -2416,9 +2436,9 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
                }
        }
 
-pf_has_reset:
        ixgbevf_update_stats(adapter);
 
+pf_has_reset:
        /* Force detection of hung controller every watchdog period */
        adapter->detect_tx_hung = true;
 
@@ -2675,7 +2695,7 @@ static int ixgbevf_open(struct net_device *netdev)
                if (hw->adapter_stopped) {
                        err = IXGBE_ERR_MBX;
                        printk(KERN_ERR "Unable to start - perhaps the PF"
-                              "Driver isn't up yet\n");
+                              " Driver isn't up yet\n");
                        goto err_setup_reset;
                }
        }
@@ -2923,9 +2943,10 @@ static int ixgbevf_tx_map(struct ixgbevf_adapter *adapter,
        struct ixgbevf_tx_buffer *tx_buffer_info;
        unsigned int len;
        unsigned int total = skb->len;
-       unsigned int offset = 0, size, count = 0, i;
+       unsigned int offset = 0, size, count = 0;
        unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
        unsigned int f;
+       int i;
 
        i = tx_ring->next_to_use;
 
@@ -3390,8 +3411,6 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
        /* setup the private structure */
        err = ixgbevf_sw_init(adapter);
 
-       ixgbevf_init_last_counter_stats(adapter);
-
 #ifdef MAX_SKB_FRAGS
        netdev->features = NETIF_F_SG |
                           NETIF_F_IP_CSUM |
@@ -3449,6 +3468,8 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
 
        adapter->netdev_registered = true;
 
+       ixgbevf_init_last_counter_stats(adapter);
+
        /* print the MAC address */
        hw_dbg(hw, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
               netdev->dev_addr[0],
index 799600e927002863c7003b6529ba3c0c758241b9..1f31b052d4b4b788a7e670199b6c16503cfc5b08 100644 (file)
@@ -157,6 +157,12 @@ struct ixgbevf_hw_stats {
        u64 vfgorc;
        u64 vfgotc;
        u64 vfmprc;
+
+       u64 saved_reset_vfgprc;
+       u64 saved_reset_vfgptc;
+       u64 saved_reset_vfgorc;
+       u64 saved_reset_vfgotc;
+       u64 saved_reset_vfmprc;
 };
 
 struct ixgbevf_info {
index 0f31497833df518795f34fadeb4f1f5af85772c6..c0b59a5553849f64b09f156c9ec515bd95382861 100644 (file)
@@ -946,6 +946,8 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx)
                                jme->jme_vlan_rx(skb, jme->vlgrp,
                                        le16_to_cpu(rxdesc->descwb.vlan));
                                NET_STAT(jme).rx_bytes += 4;
+                       } else {
+                               dev_kfree_skb(skb);
                        }
                } else {
                        jme->jme_rx(skb);
@@ -2081,12 +2083,45 @@ jme_tx_timeout(struct net_device *netdev)
        jme_reset_link(jme);
 }
 
+static inline void jme_pause_rx(struct jme_adapter *jme)
+{
+       atomic_dec(&jme->link_changing);
+
+       jme_set_rx_pcc(jme, PCC_OFF);
+       if (test_bit(JME_FLAG_POLL, &jme->flags)) {
+               JME_NAPI_DISABLE(jme);
+       } else {
+               tasklet_disable(&jme->rxclean_task);
+               tasklet_disable(&jme->rxempty_task);
+       }
+}
+
+static inline void jme_resume_rx(struct jme_adapter *jme)
+{
+       struct dynpcc_info *dpi = &(jme->dpi);
+
+       if (test_bit(JME_FLAG_POLL, &jme->flags)) {
+               JME_NAPI_ENABLE(jme);
+       } else {
+               tasklet_hi_enable(&jme->rxclean_task);
+               tasklet_hi_enable(&jme->rxempty_task);
+       }
+       dpi->cur                = PCC_P1;
+       dpi->attempt            = PCC_P1;
+       dpi->cnt                = 0;
+       jme_set_rx_pcc(jme, PCC_P1);
+
+       atomic_inc(&jme->link_changing);
+}
+
 static void
 jme_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
 {
        struct jme_adapter *jme = netdev_priv(netdev);
 
+       jme_pause_rx(jme);
        jme->vlgrp = grp;
+       jme_resume_rx(jme);
 }
 
 static void
index c19db9146a2f38ef44d4a776d0df9f5b39a26e8d..07ad3a457185c3f440c65e9d2a04cb6de1214aa3 100644 (file)
@@ -25,7 +25,7 @@
 #define __JME_H_INCLUDED__
 
 #define DRV_NAME       "jme"
-#define DRV_VERSION    "1.0.5"
+#define DRV_VERSION    "1.0.6"
 #define PFX            DRV_NAME ": "
 
 #define PCI_DEVICE_ID_JMICRON_JMC250   0x0250
index 0573e0bb4444162e5153043532023b82b7a16bb0..13cc1ca261d9cf57905adea50e6c179ea925c6f0 100644 (file)
@@ -976,7 +976,6 @@ static void ks8851_set_rx_mode(struct net_device *dev)
                        crc >>= (32 - 6);  /* get top six bits */
 
                        rxctrl.mchash[crc >> 4] |= (1 << (crc & 0xf));
-                       mcptr = mcptr->next;
                }
 
                rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXPAFMA;
index 0f59099ee72f8d504d314ef41af592d377f58795..6c5327af1bf920e28f7291c7ce9bb47aac8eafde 100644 (file)
@@ -6322,7 +6322,7 @@ static int netdev_set_eeprom(struct net_device *dev,
        int len;
 
        if (eeprom->magic != EEPROM_MAGIC)
-               return 1;
+               return -EINVAL;
 
        len = (eeprom->offset + eeprom->len + 1) / 2;
        for (i = eeprom->offset / 2; i < len; i++)
index 144d2e8804225a16e20f3799eface6c1f8a6f165..0f703838e21ad73b5ad775e35b9984146d60cf5f 100644 (file)
@@ -53,8 +53,8 @@
 
 #define _NETXEN_NIC_LINUX_MAJOR 4
 #define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 72
-#define NETXEN_NIC_LINUX_VERSIONID  "4.0.72"
+#define _NETXEN_NIC_LINUX_SUBVERSION 73
+#define NETXEN_NIC_LINUX_VERSIONID  "4.0.73"
 
 #define NETXEN_VERSION_CODE(a, b, c)   (((a) << 24) + ((b) << 16) + (c))
 #define _major(v)      (((v) >> 24) & 0xff)
index 2a8ef5fc9663b094bcfdfb5fc24c2f4adbff31be..f26e54716c886569f9e30d9a8a5c34d6056b58e6 100644 (file)
@@ -669,13 +669,15 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
                }
                sds_ring->desc_head = (struct status_desc *)addr;
 
-               sds_ring->crb_sts_consumer =
-                       netxen_get_ioaddr(adapter,
-                       recv_crb_registers[port].crb_sts_consumer[ring]);
+               if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+                       sds_ring->crb_sts_consumer =
+                               netxen_get_ioaddr(adapter,
+                               recv_crb_registers[port].crb_sts_consumer[ring]);
 
-               sds_ring->crb_intr_mask =
-                       netxen_get_ioaddr(adapter,
-                       recv_crb_registers[port].sw_int_mask[ring]);
+                       sds_ring->crb_intr_mask =
+                               netxen_get_ioaddr(adapter,
+                               recv_crb_registers[port].sw_int_mask[ring]);
+               }
        }
 
 
index 1c63610ead422a29b4628e525b7c1be37de300dd..7eb925a9f36e3ed6d558841659d02b812b790dd6 100644 (file)
@@ -761,7 +761,7 @@ nx_get_bios_version(struct netxen_adapter *adapter)
        if (adapter->fw_type == NX_UNIFIED_ROMIMAGE) {
                bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off])
                                                + NX_UNI_BIOS_VERSION_OFF));
-               return (bios_ver << 24) + ((bios_ver >> 8) & 0xff00) +
+               return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) +
                                                        (bios_ver >> 24);
        } else
                return cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]);
index 08780ef1c1f885d56b38d9c4ff68b4f790711f58..01808b28d1b6c52fcaced72fe2ab9f6566659c9a 100644 (file)
@@ -604,16 +604,14 @@ netxen_cleanup_pci_map(struct netxen_adapter *adapter)
 static int
 netxen_setup_pci_map(struct netxen_adapter *adapter)
 {
-       void __iomem *mem_ptr0 = NULL;
-       void __iomem *mem_ptr1 = NULL;
-       void __iomem *mem_ptr2 = NULL;
        void __iomem *db_ptr = NULL;
 
        resource_size_t mem_base, db_base;
-       unsigned long mem_len, db_len = 0, pci_len0 = 0;
+       unsigned long mem_len, db_len = 0;
 
        struct pci_dev *pdev = adapter->pdev;
        int pci_func = adapter->ahw.pci_func;
+       struct netxen_hardware_context *ahw = &adapter->ahw;
 
        int err = 0;
 
@@ -630,24 +628,40 @@ netxen_setup_pci_map(struct netxen_adapter *adapter)
 
        /* 128 Meg of memory */
        if (mem_len == NETXEN_PCI_128MB_SIZE) {
-               mem_ptr0 = ioremap(mem_base, FIRST_PAGE_GROUP_SIZE);
-               mem_ptr1 = ioremap(mem_base + SECOND_PAGE_GROUP_START,
+
+               ahw->pci_base0 = ioremap(mem_base, FIRST_PAGE_GROUP_SIZE);
+               ahw->pci_base1 = ioremap(mem_base + SECOND_PAGE_GROUP_START,
                                SECOND_PAGE_GROUP_SIZE);
-               mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START,
+               ahw->pci_base2 = ioremap(mem_base + THIRD_PAGE_GROUP_START,
                                THIRD_PAGE_GROUP_SIZE);
-               pci_len0 = FIRST_PAGE_GROUP_SIZE;
+               if (ahw->pci_base0 == NULL || ahw->pci_base1 == NULL ||
+                                               ahw->pci_base2 == NULL) {
+                       dev_err(&pdev->dev, "failed to map PCI bar 0\n");
+                       err = -EIO;
+                       goto err_out;
+               }
+
+               ahw->pci_len0 = FIRST_PAGE_GROUP_SIZE;
+
        } else if (mem_len == NETXEN_PCI_32MB_SIZE) {
-               mem_ptr1 = ioremap(mem_base, SECOND_PAGE_GROUP_SIZE);
-               mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START -
+
+               ahw->pci_base1 = ioremap(mem_base, SECOND_PAGE_GROUP_SIZE);
+               ahw->pci_base2 = ioremap(mem_base + THIRD_PAGE_GROUP_START -
                        SECOND_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE);
+               if (ahw->pci_base1 == NULL || ahw->pci_base2 == NULL) {
+                       dev_err(&pdev->dev, "failed to map PCI bar 0\n");
+                       err = -EIO;
+                       goto err_out;
+               }
+
        } else if (mem_len == NETXEN_PCI_2MB_SIZE) {
 
-               mem_ptr0 = pci_ioremap_bar(pdev, 0);
-               if (mem_ptr0 == NULL) {
+               ahw->pci_base0 = pci_ioremap_bar(pdev, 0);
+               if (ahw->pci_base0 == NULL) {
                        dev_err(&pdev->dev, "failed to map PCI bar 0\n");
                        return -EIO;
                }
-               pci_len0 = mem_len;
+               ahw->pci_len0 = mem_len;
        } else {
                return -EIO;
        }
@@ -656,11 +670,6 @@ netxen_setup_pci_map(struct netxen_adapter *adapter)
 
        dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
 
-       adapter->ahw.pci_base0 = mem_ptr0;
-       adapter->ahw.pci_len0 = pci_len0;
-       adapter->ahw.pci_base1 = mem_ptr1;
-       adapter->ahw.pci_base2 = mem_ptr2;
-
        if (NX_IS_REVISION_P3P(adapter->ahw.revision_id)) {
                adapter->ahw.ocm_win_crb = netxen_get_ioaddr(adapter,
                        NETXEN_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(pci_func)));
@@ -1246,8 +1255,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        int pci_func_id = PCI_FUNC(pdev->devfn);
        uint8_t revision_id;
 
-       if (pdev->revision >= NX_P3_A0 && pdev->revision < NX_P3_B1) {
-               pr_warning("%s: chip revisions between 0x%x-0x%x"
+       if (pdev->revision >= NX_P3_A0 && pdev->revision <= NX_P3_B1) {
+               pr_warning("%s: chip revisions between 0x%x-0x%x "
                                "will not be enabled.\n",
                                module_name(THIS_MODULE), NX_P3_A0, NX_P3_B1);
                return -ENODEV;
index 776cad2f57150d1ecf209ec7063a0ed393bc3fec..1028fcb91a28d0a6043b373dd7e7543707f878f6 100644 (file)
@@ -1549,6 +1549,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101),
        PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab),
        PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
        PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
        PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
        PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
@@ -1740,7 +1741,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
-       PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "cis/LA-PCM.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("Allied Telesis,K.K", "Ethernet LAN Card", 0x2ad62f3c, 0x9fd2f0a2, "cis/LA-PCM.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "cis/PE520.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID12("PMX   ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"),
index 9d3ebf3e975e0abfe5519bf2cd3371ed9278743d..96740051cdccc74d447a24f4a72d96df3492e7da 100644 (file)
@@ -186,8 +186,13 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
 
 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
-static int rx_copybreak = 200;
-static int use_dac = -1;
+/*
+ * we set our copybreak very high so that we don't have
+ * to allocate 16k frames all the time (see note in
+ * rtl8169_open()
+ */
+static int rx_copybreak = 16383;
+static int use_dac;
 static struct {
        u32 msg_enable;
 } debug = { -1 };
@@ -511,8 +516,7 @@ MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
 module_param(rx_copybreak, int, 0);
 MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
 module_param(use_dac, int, 0);
-MODULE_PARM_DESC(use_dac, "Enable PCI DAC. -1 defaults on for PCI Express only."
-" Unsafe on 32 bit PCI slot.");
+MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
 module_param_named(debug, debug.msg_enable, int, 0);
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
 MODULE_LICENSE("GPL");
@@ -2821,8 +2825,8 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
        spin_lock_irq(&tp->lock);
 
        RTL_W8(Cfg9346, Cfg9346_Unlock);
-       RTL_W32(MAC0, low);
        RTL_W32(MAC4, high);
+       RTL_W32(MAC0, low);
        RTL_W8(Cfg9346, Cfg9346_Lock);
 
        spin_unlock_irq(&tp->lock);
@@ -2974,7 +2978,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        void __iomem *ioaddr;
        unsigned int i;
        int rc;
-       int this_use_dac = use_dac;
 
        if (netif_msg_drv(&debug)) {
                printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
@@ -3040,17 +3043,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        tp->cp_cmd = PCIMulRW | RxChkSum;
 
-       tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-       if (!tp->pcie_cap)
-               netif_info(tp, probe, dev, "no PCI Express capability\n");
-
-       if (this_use_dac < 0)
-               this_use_dac = tp->pcie_cap != 0;
-
        if ((sizeof(dma_addr_t) > 4) &&
-           this_use_dac &&
-           !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-               netif_info(tp, probe, dev, "using 64-bit DMA\n");
+           !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
                tp->cp_cmd |= PCIDAC;
                dev->features |= NETIF_F_HIGHDMA;
        } else {
@@ -3069,6 +3063,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_out_free_res_4;
        }
 
+       tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       if (!tp->pcie_cap)
+               netif_info(tp, probe, dev, "no PCI Express capability\n");
+
        RTL_W16(IntrMask, 0x0000);
 
        /* Soft reset the chip. */
@@ -3224,9 +3222,13 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
 }
 
 static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
-                                 struct net_device *dev)
+                                 unsigned int mtu)
 {
-       unsigned int max_frame = dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
+       unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
+
+       if (max_frame != 16383)
+               printk(KERN_WARNING "WARNING! Changing of MTU on this NIC"
+                       "May lead to frame reception errors!\n");
 
        tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE;
 }
@@ -3238,7 +3240,17 @@ static int rtl8169_open(struct net_device *dev)
        int retval = -ENOMEM;
 
 
-       rtl8169_set_rxbufsize(tp, dev);
+       /*
+        * Note that we use a magic value here, its wierd I know
+        * its done because, some subset of rtl8169 hardware suffers from
+        * a problem in which frames received that are longer than
+        * the size set in RxMaxSize register return garbage sizes
+        * when received.  To avoid this we need to turn off filtering,
+        * which is done by setting a value of 16383 in the RxMaxSize register
+        * and allocating 16k frames to handle the largest possible rx value
+        * thats what the magic math below does.
+        */
+       rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN);
 
        /*
         * Rx and Tx desscriptors needs 256 bytes alignment.
@@ -3891,7 +3903,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
 
        rtl8169_down(dev);
 
-       rtl8169_set_rxbufsize(tp, dev);
+       rtl8169_set_rxbufsize(tp, dev->mtu);
 
        ret = rtl8169_init_ring(dev);
        if (ret < 0)
@@ -4754,8 +4766,8 @@ static void rtl_set_rx_mode(struct net_device *dev)
                mc_filter[1] = swab32(data);
        }
 
-       RTL_W32(MAR0 + 0, mc_filter[0]);
        RTL_W32(MAR0 + 4, mc_filter[1]);
+       RTL_W32(MAR0 + 0, mc_filter[0]);
 
        RTL_W32(RxConfig, tmp);
 
index 0ab05af237e5c78d68d110c40fe3efe55edb07c9..a4f09d490531db40bf5f703b52d868492a1b6ffc 100644 (file)
@@ -851,13 +851,15 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
 
                        if ( !(rdes0 & 0x8000) ||
                                ((db->cr6_data & CR6_PM) && (rxlen>6)) ) {
+                               struct sk_buff *new_skb = NULL;
+
                                skb = rxptr->rx_skb_ptr;
 
                                /* Good packet, send to upper layer */
                                /* Shorst packet used new SKB */
-                               if ( (rxlen < RX_COPY_SIZE) &&
-                                       ( (skb = dev_alloc_skb(rxlen + 2) )
-                                       != NULL) ) {
+                               if ((rxlen < RX_COPY_SIZE) &&
+                                   (((new_skb = dev_alloc_skb(rxlen + 2)) != NULL))) {
+                                       skb = new_skb;
                                        /* size less than COPY_SIZE, allocate a rxlen SKB */
                                        skb_reserve(skb, 2); /* 16byte align */
                                        memcpy(skb_put(skb, rxlen),
index d222d7e2527392a79990de49f909e0330483c871..73f9a31cf94dd364011fdbcea68b19b1b5d008d9 100644 (file)
@@ -1189,9 +1189,21 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
        }
 
        if (csum) {
-               u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
-               skb_push(skb, 4);
-               memcpy(skb->data, &csum_preamble, 4);
+               if (skb->len <= 45) {
+                       /* workaround - hardware tx checksum does not work
+                        * properly with extremely small packets */
+                       long csstart = skb->csum_start - skb_headroom(skb);
+                       __wsum calc = csum_partial(skb->data + csstart,
+                               skb->len - csstart, 0);
+                       *((__sum16 *)(skb->data + csstart
+                               + skb->csum_offset)) = csum_fold(calc);
+
+                       csum = false;
+               } else {
+                       u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
+                       skb_push(skb, 4);
+                       memcpy(skb->data, &csum_preamble, 4);
+               }
        }
 
        skb_push(skb, 4);
index 3a486f3bad3ddd6477c0fa15102e47c668ea3566..bc278d4ee89debb359c4d70ef21e06bfd7479ae3 100644 (file)
@@ -812,7 +812,7 @@ static void set_mii_flow_control(struct velocity_info *vptr)
 
        case FLOW_CNTL_TX_RX:
                MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
-               MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+               MII_REG_BITS_OFF(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
                break;
 
        case FLOW_CNTL_DISABLE:
index b2c8207f7bc17790b55c42e18a70e47f9a40320a..294b486bc3ed2043d09fc679a9ad76983e854286 100644 (file)
@@ -1353,25 +1353,6 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
        return htype;
 }
 
-static bool is_pae(struct sk_buff *skb)
-{
-       struct ieee80211_hdr *hdr;
-       __le16 fc;
-
-       hdr = (struct ieee80211_hdr *)skb->data;
-       fc = hdr->frame_control;
-
-       if (ieee80211_is_data(fc)) {
-               if (ieee80211_is_nullfunc(fc) ||
-                   /* Port Access Entity (IEEE 802.1X) */
-                   (skb->protocol == cpu_to_be16(ETH_P_PAE))) {
-                       return true;
-               }
-       }
-
-       return false;
-}
-
 static int get_hw_crypto_keytype(struct sk_buff *skb)
 {
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1696,7 +1677,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
                        goto tx_done;
                }
 
-               if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && !is_pae(skb)) {
+               if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
                        /*
                         * Try aggregation if it's a unicast data frame
                         * and the destination is HT capable.
index 1ed5206721ecb587688bbd8b463f172e0f5d2de1..8c12311dbb0a5797b1ad28769ce8cec8d28d1319 100644 (file)
@@ -124,7 +124,7 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv,
        if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed)
                priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
        else {
-               IWL_ERR(priv, "free more than tfds_in_queue (%u:%d)\n",
+               IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
                        priv->stations[sta_id].tid[tid].tfds_in_queue,
                        freed);
                priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
index 0ccba57fb9fb9548eaceaf267481af256f9928d3..05e4d68eb4cc3783ccad9a0880114d7cdb0bb5ba 100644 (file)
@@ -466,7 +466,8 @@ out:
 
 void wl1251_debugfs_reset(struct wl1251 *wl)
 {
-       memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
+       if (wl->stats.fw_stats != NULL)
+               memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
        wl->stats.retry_count = 0;
        wl->stats.excessive_retries = 0;
 }
index 40b48f569b1e3daf9c6de0330f4f4f9f2fab4317..9665d6b17a2a234a0ae16a2cf57a0a271c8bc473 100644 (file)
@@ -832,9 +832,8 @@ static inline void dbg_ctrl(struct controller *ctrl)
        for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
                if (!pci_resource_len(pdev, i))
                        continue;
-               ctrl_info(ctrl, "  PCI resource [%d]     : 0x%llx@0x%llx\n",
-                         i, (unsigned long long)pci_resource_len(pdev, i),
-                         (unsigned long long)pci_resource_start(pdev, i));
+               ctrl_info(ctrl, "  PCI resource [%d]     : %pR\n",
+                         i, &pdev->resource[i]);
        }
        ctrl_info(ctrl, "Slot Capabilities      : 0x%08x\n", ctrl->slot_cap);
        ctrl_info(ctrl, "  Physical Slot Number : %d\n", PSN(ctrl));
index 3e0d7b5dd1b904e0e02425f1ea005915cafb2610..fb9fdf4a42bf43acfd5d8a3c6c97bf3663adbbce 100644 (file)
@@ -31,9 +31,9 @@ static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        acpi_status status;
        unsigned long long gsb;
        struct ioapic *ioapic;
-       u64 addr;
        int ret;
        char *type;
+       struct resource *res;
 
        handle = DEVICE_ACPI_HANDLE(&dev->dev);
        if (!handle)
@@ -69,13 +69,12 @@ static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        if (pci_request_region(dev, 0, type))
                goto exit_disable;
 
-       addr = pci_resource_start(dev, 0);
-       if (acpi_register_ioapic(ioapic->handle, addr, ioapic->gsi_base))
+       res = &dev->resource[0];
+       if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base))
                goto exit_release;
 
        pci_set_drvdata(dev, ioapic);
-       dev_info(&dev->dev, "%s at %#llx, GSI %u\n", type, addr,
-                ioapic->gsi_base);
+       dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base);
        return 0;
 
 exit_release:
index cb1dd5f4988c72d533cabefa9b6b540761c294d6..1531f3a498791dd39fb0ce628acd3d09bb67b451 100644 (file)
@@ -2576,18 +2576,17 @@ EXPORT_SYMBOL_GPL(pci_reset_function);
  */
 int pcix_get_max_mmrbc(struct pci_dev *dev)
 {
-       int err, cap;
+       int cap;
        u32 stat;
 
        cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
        if (!cap)
                return -EINVAL;
 
-       err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat);
-       if (err)
+       if (pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat))
                return -EINVAL;
 
-       return (stat & PCI_X_STATUS_MAX_READ) >> 12;
+       return 512 << ((stat & PCI_X_STATUS_MAX_READ) >> 21);
 }
 EXPORT_SYMBOL(pcix_get_max_mmrbc);
 
@@ -2600,18 +2599,17 @@ EXPORT_SYMBOL(pcix_get_max_mmrbc);
  */
 int pcix_get_mmrbc(struct pci_dev *dev)
 {
-       int ret, cap;
-       u32 cmd;
+       int cap;
+       u16 cmd;
 
        cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
        if (!cap)
                return -EINVAL;
 
-       ret = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd);
-       if (!ret)
-               ret = 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2);
+       if (pci_read_config_word(dev, cap + PCI_X_CMD, &cmd))
+               return -EINVAL;
 
-       return ret;
+       return 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2);
 }
 EXPORT_SYMBOL(pcix_get_mmrbc);
 
@@ -2626,28 +2624,27 @@ EXPORT_SYMBOL(pcix_get_mmrbc);
  */
 int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc)
 {
-       int cap, err = -EINVAL;
-       u32 stat, cmd, v, o;
+       int cap;
+       u32 stat, v, o;
+       u16 cmd;
 
        if (mmrbc < 512 || mmrbc > 4096 || !is_power_of_2(mmrbc))
-               goto out;
+               return -EINVAL;
 
        v = ffs(mmrbc) - 10;
 
        cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
        if (!cap)
-               goto out;
+               return -EINVAL;
 
-       err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat);
-       if (err)
-               goto out;
+       if (pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat))
+               return -EINVAL;
 
        if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21)
                return -E2BIG;
 
-       err = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd);
-       if (err)
-               goto out;
+       if (pci_read_config_word(dev, cap + PCI_X_CMD, &cmd))
+               return -EINVAL;
 
        o = (cmd & PCI_X_CMD_MAX_READ) >> 2;
        if (o != v) {
@@ -2657,10 +2654,10 @@ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc)
 
                cmd &= ~PCI_X_CMD_MAX_READ;
                cmd |= v << 2;
-               err = pci_write_config_dword(dev, cap + PCI_X_CMD, cmd);
+               if (pci_write_config_word(dev, cap + PCI_X_CMD, cmd))
+                       return -EIO;
        }
-out:
-       return err;
+       return 0;
 }
 EXPORT_SYMBOL(pcix_set_mmrbc);
 
@@ -3023,7 +3020,6 @@ EXPORT_SYMBOL(pcim_pin_device);
 EXPORT_SYMBOL(pci_disable_device);
 EXPORT_SYMBOL(pci_find_capability);
 EXPORT_SYMBOL(pci_bus_find_capability);
-EXPORT_SYMBOL(pci_register_set_vga_state);
 EXPORT_SYMBOL(pci_release_regions);
 EXPORT_SYMBOL(pci_request_regions);
 EXPORT_SYMBOL(pci_request_regions_exclusive);
index 2a943090a3b7838b3a8fcb86a9caa89dfe611133..882bd8d29fe3c14903282c5c2ec20ea52b8a5347 100644 (file)
@@ -174,14 +174,19 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
        pci_read_config_dword(dev, pos, &sz);
        pci_write_config_dword(dev, pos, l);
 
+       if (!sz)
+               goto fail;      /* BAR not implemented */
+
        /*
         * All bits set in sz means the device isn't working properly.
-        * If the BAR isn't implemented, all bits must be 0.  If it's a
-        * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit
-        * 1 must be clear.
+        * If it's a memory BAR or a ROM, bit 0 must be clear; if it's
+        * an io BAR, bit 1 must be clear.
         */
-       if (!sz || sz == 0xffffffff)
+       if (sz == 0xffffffff) {
+               dev_err(&dev->dev, "reg %x: invalid size %#x; broken device?\n",
+                       pos, sz);
                goto fail;
+       }
 
        /*
         * I don't know how l can have all bits set.  Copied from old code.
@@ -244,13 +249,17 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                                   pos, res);
                }
        } else {
-               sz = pci_size(l, sz, mask);
+               u32 size = pci_size(l, sz, mask);
 
-               if (!sz)
+               if (!size) {
+                       dev_err(&dev->dev, "reg %x: invalid size "
+                               "(l %#x sz %#x mask %#x); broken device?",
+                               pos, l, sz, mask);
                        goto fail;
+               }
 
                res->start = l;
-               res->end = l + sz;
+               res->end = l + size;
 
                dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
        }
@@ -312,7 +321,7 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
                dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);
        } else {
                dev_printk(KERN_DEBUG, &dev->dev,
-                        "  bridge window [io  %04lx - %04lx] reg reading\n",
+                        "  bridge window [io  %#06lx-%#06lx] (disabled)\n",
                                 base, limit);
        }
 }
@@ -336,7 +345,7 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
                dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);
        } else {
                dev_printk(KERN_DEBUG, &dev->dev,
-                       "  bridge window [mem 0x%08lx - 0x%08lx] reg reading\n",
+                       "  bridge window [mem %#010lx-%#010lx] (disabled)\n",
                                         base, limit + 0xfffff);
        }
 }
@@ -387,7 +396,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
                dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);
        } else {
                dev_printk(KERN_DEBUG, &dev->dev,
-                    "  bridge window [mem 0x%08lx - %08lx pref] reg reading\n",
+                    "  bridge window [mem %#010lx-%#010lx pref] (disabled)\n",
                                         base, limit + 0xfffff);
        }
 }
@@ -673,16 +682,20 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
        int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
        u32 buses, i, j = 0;
        u16 bctl;
+       u8 primary, secondary, subordinate;
        int broken = 0;
 
        pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
+       primary = buses & 0xFF;
+       secondary = (buses >> 8) & 0xFF;
+       subordinate = (buses >> 16) & 0xFF;
 
-       dev_dbg(&dev->dev, "scanning behind bridge, config %06x, pass %d\n",
-               buses & 0xffffff, pass);
+       dev_dbg(&dev->dev, "scanning [bus %02x-%02x] behind bridge, pass %d\n",
+               secondary, subordinate, pass);
 
        /* Check if setup is sensible at all */
        if (!pass &&
-           ((buses & 0xff) != bus->number || ((buses >> 8) & 0xff) <= bus->number)) {
+           (primary != bus->number || secondary <= bus->number)) {
                dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n");
                broken = 1;
        }
@@ -693,15 +706,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
        pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
                              bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);
 
-       if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus && !broken) {
-               unsigned int cmax, busnr;
+       if ((secondary || subordinate) && !pcibios_assign_all_busses() &&
+           !is_cardbus && !broken) {
+               unsigned int cmax;
                /*
                 * Bus already configured by firmware, process it in the first
                 * pass and just note the configuration.
                 */
                if (pass)
                        goto out;
-               busnr = (buses >> 8) & 0xFF;
 
                /*
                 * If we already got to this bus through a different bridge,
@@ -710,13 +723,13 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
                 * However, we continue to descend down the hierarchy and
                 * scan remaining child buses.
                 */
-               child = pci_find_bus(pci_domain_nr(bus), busnr);
+               child = pci_find_bus(pci_domain_nr(bus), secondary);
                if (!child) {
-                       child = pci_add_new_bus(bus, dev, busnr);
+                       child = pci_add_new_bus(bus, dev, secondary);
                        if (!child)
                                goto out;
-                       child->primary = buses & 0xFF;
-                       child->subordinate = (buses >> 16) & 0xFF;
+                       child->primary = primary;
+                       child->subordinate = subordinate;
                        child->bridge_ctl = bctl;
                }
 
index 81d19d5683ace216b2edd8728c0bde78f3fccf31..27c0e6eb7136030b8c419e91e2c3dae595322a0c 100644 (file)
@@ -368,8 +368,9 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
                bus_region.end = res->end;
                pcibios_bus_to_resource(dev, res, &bus_region);
 
-               pci_claim_resource(dev, nr);
-               dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name);
+               if (pci_claim_resource(dev, nr) == 0)
+                       dev_info(&dev->dev, "quirk: %pR claimed by %s\n",
+                                res, name);
        }
 }      
 
@@ -1977,11 +1978,25 @@ static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
        /*
         * Disable PCI Bus Parking and PCI Master read caching on CX700
         * which causes unspecified timing errors with a VT6212L on the PCI
-        * bus leading to USB2.0 packet loss. The defaults are that these
-        * features are turned off but some BIOSes turn them on.
+        * bus leading to USB2.0 packet loss.
+        *
+        * This quirk is only enabled if a second (on the external PCI bus)
+        * VT6212L is found -- the CX700 core itself also contains a USB
+        * host controller with the same PCI ID as the VT6212L.
         */
 
+       /* Count VT6212L instances */
+       struct pci_dev *p = pci_get_device(PCI_VENDOR_ID_VIA,
+               PCI_DEVICE_ID_VIA_8235_USB_2, NULL);
        uint8_t b;
+
+       /* p should contain the first (internal) VT6212L -- see if we have
+          an external one by searching again */
+       p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, p);
+       if (!p)
+               return;
+       pci_dev_put(p);
+
        if (pci_read_config_byte(dev, 0x76, &b) == 0) {
                if (b & 0x40) {
                        /* Turn off PCI Bus Parking */
@@ -2008,7 +2023,7 @@ static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
                }
        }
 }
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching);
 
 /*
  * For Broadcom 5706, 5708, 5709 rev. A nics, any read beyond the
@@ -2108,6 +2123,10 @@ static void __devinit quirk_disable_msi(struct pci_dev *dev)
        }
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9602, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK, 0x9602, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AI, 0x9602, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi);
 
 /* Go through the list of Hypertransport capabilities and
  * return 1 if a HT MSI capability is found and enabled */
index 7d678bb15ffb30daed8bebf18d1ef5642a30a13b..17bed18d24ad10eb021e7d3148f8456ff5fe2277 100644 (file)
@@ -93,8 +93,7 @@ void pci_update_resource(struct pci_dev *dev, int resno)
 int pci_claim_resource(struct pci_dev *dev, int resource)
 {
        struct resource *res = &dev->resource[resource];
-       struct resource *root;
-       int err;
+       struct resource *root, *conflict;
 
        root = pci_find_parent_resource(dev, res);
        if (!root) {
@@ -103,12 +102,15 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
                return -EINVAL;
        }
 
-       err = request_resource(root, res);
-       if (err)
+       conflict = request_resource_conflict(root, res);
+       if (conflict) {
                dev_err(&dev->dev,
-                       "address space collision: %pR already in use\n", res);
+                       "address space collision: %pR conflicts with %s %pR\n",
+                       res, conflict->name, conflict);
+               return -EBUSY;
+       }
 
-       return err;
+       return 0;
 }
 EXPORT_SYMBOL(pci_claim_resource);
 
index 5d228071ec69b938fb860ef51470c3adc3ea8025..fb904f444d900563601fd073199b6bb1a4cf65c8 100644 (file)
@@ -361,7 +361,6 @@ static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
        struct at91_cf_socket   *cf = platform_get_drvdata(pdev);
        struct at91_cf_data     *board = cf->board;
 
-       pcmcia_socket_dev_suspend(&pdev->dev);
        if (device_may_wakeup(&pdev->dev)) {
                enable_irq_wake(board->det_pin);
                if (board->irq_pin)
@@ -381,7 +380,6 @@ static int at91_cf_resume(struct platform_device *pdev)
                        disable_irq_wake(board->irq_pin);
        }
 
-       pcmcia_socket_dev_resume(&pdev->dev);
        return 0;
 }
 
index 171c8a654887a65dcb91663e1173d48242923653..ac4d089430fd1476e88a6636ea9e763255896b25 100644 (file)
@@ -510,17 +510,6 @@ static int au1x00_drv_pcmcia_probe(struct platform_device *dev)
        return ret;
 }
 
-static int au1x00_drv_pcmcia_suspend(struct platform_device *dev,
-                                    pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&dev->dev);
-}
-
-static int au1x00_drv_pcmcia_resume(struct platform_device *dev)
-{
-       return pcmcia_socket_dev_resume(&dev->dev);
-}
-
 static struct platform_driver au1x00_pcmcia_driver = {
        .driver = {
                .name           = "au1x00-pcmcia",
@@ -528,8 +517,6 @@ static struct platform_driver au1x00_pcmcia_driver = {
        },
        .probe          = au1x00_drv_pcmcia_probe,
        .remove         = au1x00_drv_pcmcia_remove,
-       .suspend        = au1x00_drv_pcmcia_suspend,
-       .resume         = au1x00_drv_pcmcia_resume,
 };
 
 
index 2482ce7ac6dcb3f9845eeebe664ab30defeb76b8..93f9ddeb0c36d1519762a4e55289f98d84bbca78 100644 (file)
@@ -300,16 +300,6 @@ static int __devexit bfin_cf_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int bfin_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-       return pcmcia_socket_dev_suspend(&pdev->dev);
-}
-
-static int bfin_cf_resume(struct platform_device *pdev)
-{
-       return pcmcia_socket_dev_resume(&pdev->dev);
-}
-
 static struct platform_driver bfin_cf_driver = {
        .driver = {
                   .name = (char *)driver_name,
@@ -317,8 +307,6 @@ static struct platform_driver bfin_cf_driver = {
                   },
        .probe = bfin_cf_probe,
        .remove = __devexit_p(bfin_cf_remove),
-       .suspend = bfin_cf_suspend,
-       .resume = bfin_cf_resume,
 };
 
 static int __init bfin_cf_init(void)
index e679e708db630e3c8a93a7f6d87ded908a2c397e..75ed866e6953944c871dd46bfc94f4a54da997bd 100644 (file)
@@ -76,65 +76,6 @@ DECLARE_RWSEM(pcmcia_socket_list_rwsem);
 EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
 
 
-/*
- * Low-level PCMCIA socket drivers need to register with the PCCard
- * core using pcmcia_register_socket.
- *
- * socket drivers are expected to use the following callbacks in their
- * .drv struct:
- *  - pcmcia_socket_dev_suspend
- *  - pcmcia_socket_dev_resume
- * These functions check for the appropriate struct pcmcia_soket arrays,
- * and pass them to the low-level functions pcmcia_{suspend,resume}_socket
- */
-static int socket_early_resume(struct pcmcia_socket *skt);
-static int socket_late_resume(struct pcmcia_socket *skt);
-static int socket_resume(struct pcmcia_socket *skt);
-static int socket_suspend(struct pcmcia_socket *skt);
-
-static void pcmcia_socket_dev_run(struct device *dev,
-                                 int (*cb)(struct pcmcia_socket *))
-{
-       struct pcmcia_socket *socket;
-
-       down_read(&pcmcia_socket_list_rwsem);
-       list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
-               if (socket->dev.parent != dev)
-                       continue;
-               mutex_lock(&socket->skt_mutex);
-               cb(socket);
-               mutex_unlock(&socket->skt_mutex);
-       }
-       up_read(&pcmcia_socket_list_rwsem);
-}
-
-int pcmcia_socket_dev_suspend(struct device *dev)
-{
-       pcmcia_socket_dev_run(dev, socket_suspend);
-       return 0;
-}
-EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
-
-void pcmcia_socket_dev_early_resume(struct device *dev)
-{
-       pcmcia_socket_dev_run(dev, socket_early_resume);
-}
-EXPORT_SYMBOL(pcmcia_socket_dev_early_resume);
-
-void pcmcia_socket_dev_late_resume(struct device *dev)
-{
-       pcmcia_socket_dev_run(dev, socket_late_resume);
-}
-EXPORT_SYMBOL(pcmcia_socket_dev_late_resume);
-
-int pcmcia_socket_dev_resume(struct device *dev)
-{
-       pcmcia_socket_dev_run(dev, socket_resume);
-       return 0;
-}
-EXPORT_SYMBOL(pcmcia_socket_dev_resume);
-
-
 struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt)
 {
        struct device *dev = get_device(&skt->dev);
@@ -578,12 +519,18 @@ static int socket_early_resume(struct pcmcia_socket *skt)
 
 static int socket_late_resume(struct pcmcia_socket *skt)
 {
+       int ret;
+
        mutex_lock(&skt->ops_mutex);
        skt->state &= ~SOCKET_SUSPEND;
        mutex_unlock(&skt->ops_mutex);
 
-       if (!(skt->state & SOCKET_PRESENT))
-               return socket_insert(skt);
+       if (!(skt->state & SOCKET_PRESENT)) {
+               ret = socket_insert(skt);
+               if (ret == -ENODEV)
+                       ret = 0;
+               return ret;
+       }
 
        if (skt->resume_status) {
                socket_shutdown(skt);
@@ -919,11 +866,66 @@ static void pcmcia_release_socket_class(struct class *data)
 }
 
 
+#ifdef CONFIG_PM
+
+static int __pcmcia_pm_op(struct device *dev,
+                         int (*callback) (struct pcmcia_socket *skt))
+{
+       struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
+       int ret;
+
+       mutex_lock(&s->skt_mutex);
+       ret = callback(s);
+       mutex_unlock(&s->skt_mutex);
+
+       return ret;
+}
+
+static int pcmcia_socket_dev_suspend_noirq(struct device *dev)
+{
+       return __pcmcia_pm_op(dev, socket_suspend);
+}
+
+static int pcmcia_socket_dev_resume_noirq(struct device *dev)
+{
+       return __pcmcia_pm_op(dev, socket_early_resume);
+}
+
+static int pcmcia_socket_dev_resume(struct device *dev)
+{
+       return __pcmcia_pm_op(dev, socket_late_resume);
+}
+
+static const struct dev_pm_ops pcmcia_socket_pm_ops = {
+       /* dev_resume may be called with IRQs enabled */
+       SET_SYSTEM_SLEEP_PM_OPS(NULL,
+                               pcmcia_socket_dev_resume)
+
+       /* late suspend must be called with IRQs disabled */
+       .suspend_noirq = pcmcia_socket_dev_suspend_noirq,
+       .freeze_noirq = pcmcia_socket_dev_suspend_noirq,
+       .poweroff_noirq = pcmcia_socket_dev_suspend_noirq,
+
+       /* early resume must be called with IRQs disabled */
+       .resume_noirq = pcmcia_socket_dev_resume_noirq,
+       .thaw_noirq = pcmcia_socket_dev_resume_noirq,
+       .restore_noirq = pcmcia_socket_dev_resume_noirq,
+};
+
+#define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops)
+
+#else /* CONFIG_PM */
+
+#define PCMCIA_SOCKET_CLASS_PM_OPS NULL
+
+#endif /* CONFIG_PM */
+
 struct class pcmcia_socket_class = {
        .name = "pcmcia_socket",
        .dev_uevent = pcmcia_socket_uevent,
        .dev_release = pcmcia_release_socket,
        .class_release = pcmcia_release_socket_class,
+       .pm = PCMCIA_SOCKET_CLASS_PM_OPS,
 };
 EXPORT_SYMBOL(pcmcia_socket_class);
 
index 9254ab0b29b1b1262fdc1fdb9b1c705041128ae7..a520193b645393ef60f4cf01861533bd987a2522 100644 (file)
@@ -558,37 +558,10 @@ static int __devexit db1x_pcmcia_socket_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int db1x_pcmcia_suspend(struct device *dev)
-{
-       return pcmcia_socket_dev_suspend(dev);
-}
-
-static int db1x_pcmcia_resume(struct device *dev)
-{
-       return pcmcia_socket_dev_resume(dev);
-}
-
-static struct dev_pm_ops db1x_pcmcia_pmops = {
-       .resume         = db1x_pcmcia_resume,
-       .suspend        = db1x_pcmcia_suspend,
-       .thaw           = db1x_pcmcia_resume,
-       .freeze         = db1x_pcmcia_suspend,
-};
-
-#define DB1XXX_SS_PMOPS &db1x_pcmcia_pmops
-
-#else
-
-#define DB1XXX_SS_PMOPS NULL
-
-#endif
-
 static struct platform_driver db1x_pcmcia_socket_driver = {
        .driver = {
                .name   = "db1xxx_pcmcia",
                .owner  = THIS_MODULE,
-               .pm     = DB1XXX_SS_PMOPS
        },
        .probe          = db1x_pcmcia_socket_probe,
        .remove         = __devexit_p(db1x_pcmcia_socket_remove),
index ad93ebd7b2a2f8d3e5cdd65b07bff388d49e3db2..52d33b2a5bc559afbd7b59338b09ac8e36bd1b3b 100644 (file)
@@ -509,8 +509,12 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu
        p_dev->device_no = (s->device_count++);
        mutex_unlock(&s->ops_mutex);
 
-       /* max of 2 devices per card */
-       if (p_dev->device_no >= 2)
+       /* max of 2 PFC devices */
+       if ((p_dev->device_no >= 2) && (function == 0))
+               goto err_free;
+
+       /* max of 4 devices overall */
+       if (p_dev->device_no >= 4)
                goto err_free;
 
        p_dev->socket = s;
index f5da6265331331a5209f9a938d32b1d3989f430f..3003bb3dfcc0d08912897b2192e732ea26cccbf3 100644 (file)
@@ -39,27 +39,11 @@ static struct pci_device_id i82092aa_pci_ids[] = {
 };
 MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids);
 
-#ifdef CONFIG_PM
-static int i82092aa_socket_suspend (struct pci_dev *dev, pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&dev->dev);
-}
-
-static int i82092aa_socket_resume (struct pci_dev *dev)
-{
-       return pcmcia_socket_dev_resume(&dev->dev);
-}
-#endif
-
 static struct pci_driver i82092aa_pci_driver = {
        .name           = "i82092aa",
        .id_table       = i82092aa_pci_ids,
        .probe          = i82092aa_pci_probe,
        .remove         = __devexit_p(i82092aa_pci_remove),
-#ifdef CONFIG_PM
-       .suspend        = i82092aa_socket_suspend,
-       .resume         = i82092aa_socket_resume,
-#endif
 };
 
 
index c13fd9360511b89fe3b52f37477bb86a6dab5f1a..d53d9b5659c71ba960345b5453975753de154210 100644 (file)
@@ -1223,16 +1223,7 @@ static int pcic_init(struct pcmcia_socket *s)
        return 0;
 }
 
-static int i82365_drv_pcmcia_suspend(struct platform_device *dev,
-                                    pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&dev->dev);
-}
 
-static int i82365_drv_pcmcia_resume(struct platform_device *dev)
-{
-       return pcmcia_socket_dev_resume(&dev->dev);
-}
 static struct pccard_operations pcic_operations = {
        .init                   = pcic_init,
        .get_status             = pcic_get_status,
@@ -1248,8 +1239,6 @@ static struct platform_driver i82365_driver = {
                .name = "i82365",
                .owner          = THIS_MODULE,
        },
-       .suspend        = i82365_drv_pcmcia_suspend,
-       .resume         = i82365_drv_pcmcia_resume,
 };
 
 static struct platform_device *i82365_device;
index 0ece2cd4a85ea9640bd408fe0dc55ebe65a5692e..ab21264468d6e5f6764c06dada7f9f3face9d3da 100644 (file)
@@ -685,16 +685,7 @@ static struct pccard_operations pcc_operations = {
        .set_mem_map            = pcc_set_mem_map,
 };
 
-static int cfc_drv_pcmcia_suspend(struct platform_device *dev,
-                                    pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&dev->dev);
-}
 
-static int cfc_drv_pcmcia_resume(struct platform_device *dev)
-{
-       return pcmcia_socket_dev_resume(&dev->dev);
-}
 /*====================================================================*/
 
 static struct platform_driver pcc_driver = {
@@ -702,8 +693,6 @@ static struct platform_driver pcc_driver = {
                .name           = "cfc",
                .owner          = THIS_MODULE,
        },
-       .suspend        = cfc_drv_pcmcia_suspend,
-       .resume         = cfc_drv_pcmcia_resume,
 };
 
 static struct platform_device pcc_device = {
index 72844c5a6d05fb53999ded835e5bf56f22ba6a21..0caf3db7c70012ff2edc0fe3d41586474fe09546 100644 (file)
@@ -663,16 +663,6 @@ static struct pccard_operations pcc_operations = {
        .set_mem_map            = pcc_set_mem_map,
 };
 
-static int pcc_drv_pcmcia_suspend(struct platform_device *dev,
-                                    pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&dev->dev);
-}
-
-static int pcc_drv_pcmcia_resume(struct platform_device *dev)
-{
-       return pcmcia_socket_dev_resume(&dev->dev);
-}
 /*====================================================================*/
 
 static struct platform_driver pcc_driver = {
@@ -680,8 +670,6 @@ static struct platform_driver pcc_driver = {
                .name           = "pcc",
                .owner          = THIS_MODULE,
        },
-       .suspend        = pcc_drv_pcmcia_suspend,
-       .resume         = pcc_drv_pcmcia_resume,
 };
 
 static struct platform_device pcc_device = {
index 61c2159181288e5442381696b1eb60e2eaed8994..01ef7de15322bf9668edb16aea84006b0ea7b43e 100644 (file)
@@ -1288,21 +1288,6 @@ static int m8xx_remove(struct of_device *ofdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int m8xx_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&pdev->dev);
-}
-
-static int m8xx_resume(struct platform_device *pdev)
-{
-       return pcmcia_socket_dev_resume(&pdev->dev);
-}
-#else
-#define m8xx_suspend NULL
-#define m8xx_resume NULL
-#endif
-
 static const struct of_device_id m8xx_pcmcia_match[] = {
        {
         .type = "pcmcia",
@@ -1318,8 +1303,6 @@ static struct of_platform_driver m8xx_pcmcia_driver = {
        .match_table = m8xx_pcmcia_match,
        .probe = m8xx_probe,
        .remove = m8xx_remove,
-       .suspend = m8xx_suspend,
-       .resume = m8xx_resume,
 };
 
 static int __init m8xx_init(void)
index 3ef991552398095ddc9de8b7f2505be88108437f..9edc396577b9ecaf25b403bda90f7a603a242a05 100644 (file)
@@ -330,24 +330,12 @@ static int __exit omap_cf_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int omap_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-       return pcmcia_socket_dev_suspend(&pdev->dev);
-}
-
-static int omap_cf_resume(struct platform_device *pdev)
-{
-       return pcmcia_socket_dev_resume(&pdev->dev);
-}
-
 static struct platform_driver omap_cf_driver = {
        .driver = {
                .name   = (char *) driver_name,
                .owner  = THIS_MODULE,
        },
        .remove         = __exit_p(omap_cf_remove),
-       .suspend        = omap_cf_suspend,
-       .resume         = omap_cf_resume,
 };
 
 static int __init omap_cf_init(void)
index 7ba57a565cd72500d01a6666fde4d64ec4610fd7..4a34268cc512a306cae7bae0159634673a494c5a 100644 (file)
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/io.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
 
 #include <asm/system.h>
-#include <asm/io.h>
 
 #include "pd6729.h"
 #include "i82365.h"
@@ -222,9 +222,9 @@ static irqreturn_t pd6729_interrupt(int irq, void *dev)
                                                ? SS_READY : 0;
                        }
 
-                       if (events) {
+                       if (events)
                                pcmcia_parse_events(&socket[i].socket, events);
-                       }
+
                        active |= events;
                }
 
@@ -256,9 +256,8 @@ static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value)
        status = indirect_read(socket, I365_STATUS);
        *value = 0;
 
-       if ((status & I365_CS_DETECT) == I365_CS_DETECT) {
+       if ((status & I365_CS_DETECT) == I365_CS_DETECT)
                *value |= SS_DETECT;
-       }
 
        /*
         * IO cards have a different meaning of bits 0,1
@@ -308,7 +307,7 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
        socket->card_irq = state->io_irq;
 
        reg = 0;
-       /* The reset bit has "inverse" logic */
+       /* The reset bit has "inverse" logic */
        if (!(state->flags & SS_RESET))
                reg |= I365_PC_RESET;
        if (state->flags & SS_IOCARD)
@@ -380,7 +379,7 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
                indirect_write(socket, I365_POWER, reg);
 
        if (irq_mode == 1) {
-                /* all interrupts are to be done as PCI interrupts */
+               /* all interrupts are to be done as PCI interrupts */
                data = PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ;
        } else
                data = 0;
@@ -391,9 +390,9 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
        /* Enable specific interrupt events */
 
        reg = 0x00;
-       if (state->csc_mask & SS_DETECT) {
+       if (state->csc_mask & SS_DETECT)
                reg |= I365_CSC_DETECT;
-       }
+
        if (state->flags & SS_IOCARD) {
                if (state->csc_mask & SS_STSCHG)
                        reg |= I365_CSC_STSCHG;
@@ -450,9 +449,12 @@ static int pd6729_set_io_map(struct pcmcia_socket *sock,
 
        ioctl = indirect_read(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map);
 
-       if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
-       if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
-       if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
+       if (io->flags & MAP_0WS)
+               ioctl |= I365_IOCTL_0WS(map);
+       if (io->flags & MAP_16BIT)
+               ioctl |= I365_IOCTL_16BIT(map);
+       if (io->flags & MAP_AUTOSZ)
+               ioctl |= I365_IOCTL_IOCS16(map);
 
        indirect_write(socket, I365_IOCTL, ioctl);
 
@@ -497,7 +499,7 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock,
 
        /* write the stop address */
 
-       i= (mem->res->end >> 12) & 0x0fff;
+       i = (mem->res->end >> 12) & 0x0fff;
        switch (to_cycles(mem->speed)) {
        case 0:
                break;
@@ -563,7 +565,7 @@ static int pd6729_init(struct pcmcia_socket *sock)
 
 /* the pccard structure and its functions */
 static struct pccard_operations pd6729_operations = {
-       .init                   = pd6729_init,
+       .init                   = pd6729_init,
        .get_status             = pd6729_get_status,
        .set_socket             = pd6729_set_socket,
        .set_io_map             = pd6729_set_io_map,
@@ -578,8 +580,13 @@ static irqreturn_t pd6729_test(int irq, void *dev)
 
 static int pd6729_check_irq(int irq)
 {
-       if (request_irq(irq, pd6729_test, IRQF_PROBE_SHARED, "x", pd6729_test)
-               != 0) return -1;
+       int ret;
+
+       ret = request_irq(irq, pd6729_test, IRQF_PROBE_SHARED, "x",
+                         pd6729_test);
+       if (ret)
+               return -1;
+
        free_irq(irq, pd6729_test);
        return 0;
 }
@@ -591,7 +598,7 @@ static u_int __devinit pd6729_isa_scan(void)
 
        if (irq_mode == 1) {
                printk(KERN_INFO "pd6729: PCI card interrupts, "
-                                               "PCI status changes\n");
+                      "PCI status changes\n");
                return 0;
        }
 
@@ -607,9 +614,10 @@ static u_int __devinit pd6729_isa_scan(void)
                if (mask & (1<<i))
                        printk("%s%d", ((mask & ((1<<i)-1)) ? "," : ""), i);
 
-       if (mask == 0) printk("none!");
-
-       printk("  polling status changes.\n");
+       if (mask == 0)
+               printk("none!");
+       else
+               printk("  polling status changes.\n");
 
        return mask;
 }
@@ -624,11 +632,16 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
 
        socket = kzalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS,
                         GFP_KERNEL);
-       if (!socket)
+       if (!socket) {
+               dev_warn(&dev->dev, "failed to kzalloc socket.\n");
                return -ENOMEM;
+       }
 
-       if ((ret = pci_enable_device(dev)))
+       ret = pci_enable_device(dev);
+       if (ret) {
+               dev_warn(&dev->dev, "failed to enable pci_device.\n");
                goto err_out_free_mem;
+       }
 
        if (!pci_resource_start(dev, 0)) {
                dev_warn(&dev->dev, "refusing to load the driver as the "
@@ -639,7 +652,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
        dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx "
                "on irq %d\n",
                (unsigned long long)pci_resource_start(dev, 0), dev->irq);
-       /*
+       /*
         * Since we have no memory BARs some firmware may not
         * have had PCI_COMMAND_MEMORY enabled, yet the device needs it.
         */
@@ -685,8 +698,9 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
        pci_set_drvdata(dev, socket);
        if (irq_mode == 1) {
                /* Register the interrupt handler */
-               if ((ret = request_irq(dev->irq, pd6729_interrupt, IRQF_SHARED,
-                                                       "pd6729", socket))) {
+               ret = request_irq(dev->irq, pd6729_interrupt, IRQF_SHARED,
+                                 "pd6729", socket);
+               if (ret) {
                        dev_err(&dev->dev, "Failed to register irq %d\n",
                                dev->irq);
                        goto err_out_free_res;
@@ -750,18 +764,6 @@ static void __devexit pd6729_pci_remove(struct pci_dev *dev)
        kfree(socket);
 }
 
-#ifdef CONFIG_PM
-static int pd6729_socket_suspend(struct pci_dev *dev, pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&dev->dev);
-}
-
-static int pd6729_socket_resume(struct pci_dev *dev)
-{
-       return pcmcia_socket_dev_resume(&dev->dev);
-}
-#endif
-
 static struct pci_device_id pd6729_pci_ids[] = {
        {
                .vendor         = PCI_VENDOR_ID_CIRRUS,
@@ -778,10 +780,6 @@ static struct pci_driver pd6729_pci_driver = {
        .id_table       = pd6729_pci_ids,
        .probe          = pd6729_pci_probe,
        .remove         = __devexit_p(pd6729_pci_remove),
-#ifdef CONFIG_PM
-       .suspend        = pd6729_socket_suspend,
-       .resume         = pd6729_socket_resume,
-#endif
 };
 
 static int pd6729_module_init(void)
index 76e640bccde848c258799b2d4b245e73a17e37bb..0a876fabfe44f1596b7109310fea5934d3567c90 100644 (file)
@@ -325,19 +325,13 @@ static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
        return 0;
 }
 
-static int pxa2xx_drv_pcmcia_suspend(struct device *dev)
-{
-       return pcmcia_socket_dev_suspend(dev);
-}
-
 static int pxa2xx_drv_pcmcia_resume(struct device *dev)
 {
        pxa2xx_configure_sockets(dev);
-       return pcmcia_socket_dev_resume(dev);
+       return 0;
 }
 
 static const struct dev_pm_ops pxa2xx_drv_pcmcia_pm_ops = {
-       .suspend        = pxa2xx_drv_pcmcia_suspend,
        .resume         = pxa2xx_drv_pcmcia_resume,
 };
 
index 4663b3fa9f9616a66db5214fc6f5ef16c1b37dc0..2e47991eccf6267c6ed1ec0c0ad3ec995ed713a6 100644 (file)
@@ -810,6 +810,13 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
        unsigned long size = end - start + 1;
        int ret = 0;
 
+#if defined(CONFIG_X86)
+       /* on x86, avoid anything < 0x100 for it is often used for
+        * legacy platform devices */
+       if (start < 0x100)
+               start = 0x100;
+#endif
+
        if (end < start)
                return -EINVAL;
 
@@ -867,10 +874,8 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
                        if (res == &ioport_resource)
                                continue;
                        dev_printk(KERN_INFO, &s->cb_dev->dev,
-                                  "pcmcia: parent PCI bridge I/O "
-                                  "window: 0x%llx - 0x%llx\n",
-                                  (unsigned long long)res->start,
-                                  (unsigned long long)res->end);
+                                  "pcmcia: parent PCI bridge window: %pR\n",
+                                  res);
                        if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
                                done |= IORESOURCE_IO;
 
@@ -880,10 +885,8 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
                        if (res == &iomem_resource)
                                continue;
                        dev_printk(KERN_INFO, &s->cb_dev->dev,
-                                  "pcmcia: parent PCI bridge Memory "
-                                  "window: 0x%llx - 0x%llx\n",
-                                  (unsigned long long)res->start,
-                                  (unsigned long long)res->end);
+                                  "pcmcia: parent PCI bridge window: %pR\n",
+                                  res);
                        if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
                                done |= IORESOURCE_MEM;
                }
index 8db86b90c200e089a59dc5ea0fd17e721e490411..518896241429336b878db5a54099780ab84239ea 100644 (file)
@@ -95,17 +95,6 @@ static int sa11x0_drv_pcmcia_remove(struct platform_device *dev)
        return 0;
 }
 
-static int sa11x0_drv_pcmcia_suspend(struct platform_device *dev,
-                                    pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&dev->dev);
-}
-
-static int sa11x0_drv_pcmcia_resume(struct platform_device *dev)
-{
-       return pcmcia_socket_dev_resume(&dev->dev);
-}
-
 static struct platform_driver sa11x0_pcmcia_driver = {
        .driver = {
                .name           = "sa11x0-pcmcia",
@@ -113,8 +102,6 @@ static struct platform_driver sa11x0_pcmcia_driver = {
        },
        .probe          = sa11x0_drv_pcmcia_probe,
        .remove         = sa11x0_drv_pcmcia_remove,
-       .suspend        = sa11x0_drv_pcmcia_suspend,
-       .resume         = sa11x0_drv_pcmcia_resume,
 };
 
 /* sa11x0_pcmcia_init()
index db79ca61cf964ec7ba51b71b2d41f7d97dd8e62b..799e9793e49ecb335695877b16668867d7194d18 100644 (file)
@@ -213,16 +213,6 @@ static int __devexit pcmcia_remove(struct sa1111_dev *dev)
        return 0;
 }
 
-static int pcmcia_suspend(struct sa1111_dev *dev, pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&dev->dev);
-}
-
-static int pcmcia_resume(struct sa1111_dev *dev)
-{
-       return pcmcia_socket_dev_resume(&dev->dev);
-}
-
 static struct sa1111_driver pcmcia_driver = {
        .drv = {
                .name   = "sa1111-pcmcia",
@@ -230,8 +220,6 @@ static struct sa1111_driver pcmcia_driver = {
        .devid          = SA1111_DEVID_PCMCIA,
        .probe          = pcmcia_probe,
        .remove         = __devexit_p(pcmcia_remove),
-       .suspend        = pcmcia_suspend,
-       .resume         = pcmcia_resume,
 };
 
 static int __init sa1111_drv_pcmcia_init(void)
index 12c49ee135e1edb36ce47a17d06f3be9ee2fe822..bac85f3236bb428c17f72bcd32ac9cbf7fe894f8 100644 (file)
@@ -348,16 +348,6 @@ static int __init get_tcic_id(void)
     return id;
 }
 
-static int tcic_drv_pcmcia_suspend(struct platform_device *dev,
-                                    pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&dev->dev);
-}
-
-static int tcic_drv_pcmcia_resume(struct platform_device *dev)
-{
-       return pcmcia_socket_dev_resume(&dev->dev);
-}
 /*====================================================================*/
 
 static struct platform_driver tcic_driver = {
@@ -365,8 +355,6 @@ static struct platform_driver tcic_driver = {
                .name = "tcic-pcmcia",
                .owner          = THIS_MODULE,
        },
-       .suspend        = tcic_drv_pcmcia_suspend,
-       .resume         = tcic_drv_pcmcia_resume,
 };
 
 static struct platform_device tcic_device = {
index aaccdb9f4ba170672a1de284769a03e4f361212d..86e4a1a3c6426d4524a79effd9310fa48c7bc2e3 100644 (file)
@@ -705,24 +705,11 @@ static int __devinit vrc4171_card_setup(char *options)
 
 __setup("vrc4171_card=", vrc4171_card_setup);
 
-static int vrc4171_card_suspend(struct platform_device *dev,
-                                    pm_message_t state)
-{
-       return pcmcia_socket_dev_suspend(&dev->dev);
-}
-
-static int vrc4171_card_resume(struct platform_device *dev)
-{
-       return pcmcia_socket_dev_resume(&dev->dev);
-}
-
 static struct platform_driver vrc4171_card_driver = {
        .driver = {
                .name           = vrc4171_card_name,
                .owner          = THIS_MODULE,
        },
-       .suspend        = vrc4171_card_suspend,
-       .resume         = vrc4171_card_resume,
 };
 
 static int __devinit vrc4171_card_init(void)
index 418988ab6edf336892675a39241aec7b9111910f..f19ad02374d97abe0f589c25e9c24e8f88e35a71 100644 (file)
@@ -1290,12 +1290,9 @@ static int yenta_dev_suspend_noirq(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct yenta_socket *socket = pci_get_drvdata(pdev);
-       int ret;
-
-       ret = pcmcia_socket_dev_suspend(dev);
 
        if (!socket)
-               return ret;
+               return 0;
 
        if (socket->type && socket->type->save_state)
                socket->type->save_state(socket);
@@ -1312,7 +1309,7 @@ static int yenta_dev_suspend_noirq(struct device *dev)
         */
        /* pci_set_power_state(dev, 3); */
 
-       return ret;
+       return 0;
 }
 
 static int yenta_dev_resume_noirq(struct device *dev)
@@ -1336,26 +1333,16 @@ static int yenta_dev_resume_noirq(struct device *dev)
        if (socket->type && socket->type->restore_state)
                socket->type->restore_state(socket);
 
-       pcmcia_socket_dev_early_resume(dev);
-       return 0;
-}
-
-static int yenta_dev_resume(struct device *dev)
-{
-       pcmcia_socket_dev_late_resume(dev);
        return 0;
 }
 
 static const struct dev_pm_ops yenta_pm_ops = {
        .suspend_noirq = yenta_dev_suspend_noirq,
        .resume_noirq = yenta_dev_resume_noirq,
-       .resume = yenta_dev_resume,
        .freeze_noirq = yenta_dev_suspend_noirq,
        .thaw_noirq = yenta_dev_resume_noirq,
-       .thaw = yenta_dev_resume,
        .poweroff_noirq = yenta_dev_suspend_noirq,
        .restore_noirq = yenta_dev_resume_noirq,
-       .restore = yenta_dev_resume,
 };
 
 #define YENTA_PM_OPS   (&yenta_pm_ops)
index e631dbeafd798ff87d9d7a0eee27953c6d5aa446..7bec4588c268c3d420a0c12a421b443152644200 100644 (file)
@@ -385,6 +385,16 @@ config EEEPC_LAPTOP
 
          If you have an Eee PC laptop, say Y or M here.
 
+config EEEPC_WMI
+       tristate "Eee PC WMI Hotkey Driver (EXPERIMENTAL)"
+       depends on ACPI_WMI
+       depends on INPUT
+       depends on EXPERIMENTAL
+       ---help---
+         Say Y here if you want to support WMI-based hotkeys on Eee PC laptops.
+
+         To compile this driver as a module, choose M here: the module will
+         be called eeepc-wmi.
 
 config ACPI_WMI
        tristate "WMI"
index 9cd9fa0a27e640389cd22a0872cbbdf48933adf5..a906490e3530a91f44b41b571af0b9737d85feae 100644 (file)
@@ -4,6 +4,7 @@
 #
 obj-$(CONFIG_ASUS_LAPTOP)      += asus-laptop.o
 obj-$(CONFIG_EEEPC_LAPTOP)     += eeepc-laptop.o
+obj-$(CONFIG_EEEPC_WMI)                += eeepc-wmi.o
 obj-$(CONFIG_MSI_LAPTOP)       += msi-laptop.o
 obj-$(CONFIG_ACPI_CMPC)                += classmate-laptop.o
 obj-$(CONFIG_COMPAL_LAPTOP)    += compal-laptop.o
index db5f7db2ba33e4821b41dae2226fe656c32b2518..475ab50732abfa1f455b1e18b2cfd893e7c36d20 100644 (file)
@@ -139,7 +139,7 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
 
 /* Backlight */
 static acpi_handle lcd_switch_handle;
-static const char *lcd_switch_paths[] = {
+static char *lcd_switch_paths[] = {
   "\\_SB.PCI0.SBRG.EC0._Q10",  /* All new models */
   "\\_SB.PCI0.ISA.EC0._Q10",   /* A1x */
   "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */
@@ -153,7 +153,7 @@ static const char *lcd_switch_paths[] = {
 #define METHOD_SWITCH_DISPLAY  "SDSP"
 
 static acpi_handle display_get_handle;
-static const char *display_get_paths[] = {
+static char *display_get_paths[] = {
   /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
   "\\_SB.PCI0.P0P1.VGA.GETD",
   /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
new file mode 100644 (file)
index 0000000..2466b7b
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Eee PC WMI hotkey driver
+ *
+ * Copyright(C) 2010 Intel Corporation.
+ *
+ * Portions based on wistron_btns.c:
+ * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
+ * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
+ * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
+MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
+MODULE_LICENSE("GPL");
+
+#define EEEPC_WMI_EVENT_GUID   "ABBC0F72-8EA1-11D1-00A0-C90629100000"
+
+MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID);
+
+#define NOTIFY_BRNUP_MIN       0x11
+#define NOTIFY_BRNUP_MAX       0x1f
+#define NOTIFY_BRNDOWN_MIN     0x20
+#define NOTIFY_BRNDOWN_MAX     0x2e
+
+static const struct key_entry eeepc_wmi_keymap[] = {
+       /* Sleep already handled via generic ACPI code */
+       { KE_KEY, 0x5d, { KEY_WLAN } },
+       { KE_KEY, 0x32, { KEY_MUTE } },
+       { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
+       { KE_KEY, 0x30, { KEY_VOLUMEUP } },
+       { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
+       { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
+       { KE_END, 0},
+};
+
+static struct input_dev *eeepc_wmi_input_dev;
+
+static void eeepc_wmi_notify(u32 value, void *context)
+{
+       struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       acpi_status status;
+       int code;
+
+       status = wmi_get_event_data(value, &response);
+       if (status != AE_OK) {
+               pr_err("EEEPC WMI: bad event status 0x%x\n", status);
+               return;
+       }
+
+       obj = (union acpi_object *)response.pointer;
+
+       if (obj && obj->type == ACPI_TYPE_INTEGER) {
+               code = obj->integer.value;
+
+               if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
+                       code = NOTIFY_BRNUP_MIN;
+               else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
+                       code = NOTIFY_BRNDOWN_MIN;
+
+               if (!sparse_keymap_report_event(eeepc_wmi_input_dev,
+                                               code, 1, true))
+                       pr_info("EEEPC WMI: Unknown key %x pressed\n", code);
+       }
+
+       kfree(obj);
+}
+
+static int eeepc_wmi_input_setup(void)
+{
+       int err;
+
+       eeepc_wmi_input_dev = input_allocate_device();
+       if (!eeepc_wmi_input_dev)
+               return -ENOMEM;
+
+       eeepc_wmi_input_dev->name = "Eee PC WMI hotkeys";
+       eeepc_wmi_input_dev->phys = "wmi/input0";
+       eeepc_wmi_input_dev->id.bustype = BUS_HOST;
+
+       err = sparse_keymap_setup(eeepc_wmi_input_dev, eeepc_wmi_keymap, NULL);
+       if (err)
+               goto err_free_dev;
+
+       err = input_register_device(eeepc_wmi_input_dev);
+       if (err)
+               goto err_free_keymap;
+
+       return 0;
+
+err_free_keymap:
+       sparse_keymap_free(eeepc_wmi_input_dev);
+err_free_dev:
+       input_free_device(eeepc_wmi_input_dev);
+       return err;
+}
+
+static int __init eeepc_wmi_init(void)
+{
+       int err;
+       acpi_status status;
+
+       if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID)) {
+               pr_warning("EEEPC WMI: No known WMI GUID found\n");
+               return -ENODEV;
+       }
+
+       err = eeepc_wmi_input_setup();
+       if (err)
+               return err;
+
+       status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID,
+                                       eeepc_wmi_notify, NULL);
+       if (ACPI_FAILURE(status)) {
+               sparse_keymap_free(eeepc_wmi_input_dev);
+               input_unregister_device(eeepc_wmi_input_dev);
+               pr_err("EEEPC WMI: Unable to register notify handler - %d\n",
+                       status);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void __exit eeepc_wmi_exit(void)
+{
+       wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
+       sparse_keymap_free(eeepc_wmi_input_dev);
+       input_unregister_device(eeepc_wmi_input_dev);
+}
+
+module_init(eeepc_wmi_init);
+module_exit(eeepc_wmi_exit);
index c7bbe30010f70b3dc69542eb99fe14488cd31f45..5af16c2bb54043d090b93185c3f019a40257fcf2 100644 (file)
@@ -1038,6 +1038,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
                        goto overflow_err;
 
                regulator->dev = dev;
+               sysfs_attr_init(&regulator->dev_attr.attr);
                regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL);
                if (regulator->dev_attr.attr.name == NULL)
                        goto attr_name_err;
index f5532ed79272c08976723687684f461f49b5b281..b20b3e1d821a4bf679c82394199ce11e78ad8cd3 100644 (file)
@@ -45,7 +45,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val);
        LP3971_BUCK2 -> 4
        LP3971_BUCK3 -> 6
 */
-#define BUCK_VOL_CHANGE_SHIFT(x) (((1 << x) & ~0x01) << 1)
+#define BUCK_VOL_CHANGE_SHIFT(x) (((!!x) << 2) | (x & ~0x01))
 #define BUCK_VOL_CHANGE_FLAG_GO 0x01
 #define BUCK_VOL_CHANGE_FLAG_TARGET 0x02
 #define BUCK_VOL_CHANGE_FLAG_MASK 0x03
@@ -187,7 +187,8 @@ static int lp3971_ldo_set_voltage(struct regulator_dev *dev,
                return -EINVAL;
 
        return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo),
-               LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo), val);
+                       LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo),
+                       val << LDO_VOL_CONTR_SHIFT(ldo));
 }
 
 static struct regulator_ops lp3971_ldo_ops = {
@@ -439,6 +440,10 @@ static int __devinit setup_regulators(struct lp3971 *lp3971,
        lp3971->num_regulators = pdata->num_regulators;
        lp3971->rdev = kcalloc(pdata->num_regulators,
                                sizeof(struct regulator_dev *), GFP_KERNEL);
+       if (!lp3971->rdev) {
+               err = -ENOMEM;
+               goto err_nomem;
+       }
 
        /* Instantiate the regulators */
        for (i = 0; i < pdata->num_regulators; i++) {
@@ -461,6 +466,7 @@ error:
                regulator_unregister(lp3971->rdev[i]);
        kfree(lp3971->rdev);
        lp3971->rdev = NULL;
+err_nomem:
        return err;
 }
 
index a49fc952c9a98bd7495b59957b60a139e91b0f45..c0b09e15edb675ddc98728a77aadfc9c9f334c00 100644 (file)
@@ -243,8 +243,8 @@ static int __devexit max1586_pmic_remove(struct i2c_client *client)
        for (i = 0; i <= MAX1586_V6; i++)
                if (rdev[i])
                        regulator_unregister(rdev[i]);
-       kfree(rdev);
        i2c_set_clientdata(client, NULL);
+       kfree(rdev);
 
        return 0;
 }
index 3ebdf698c648f6cb588a0637cbcd15ab6782f3e3..833aaedc7e64c28076e4622eaf0093e5f7dec702 100644 (file)
@@ -356,6 +356,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
        dev_info(info->dev, "Max8649 regulator device is detected.\n");
        return 0;
 out:
+       i2c_set_clientdata(client, NULL);
        kfree(info);
        return ret;
 }
@@ -367,9 +368,9 @@ static int __devexit max8649_regulator_remove(struct i2c_client *client)
        if (info) {
                if (info->regulator)
                        regulator_unregister(info->regulator);
+               i2c_set_clientdata(client, NULL);
                kfree(info);
        }
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index f12f1bb62138f95851ae7da9289a1b89d159924c..47f90b2fc290208eb302e8b9ef44ed6fe7f53a1d 100644 (file)
@@ -470,8 +470,8 @@ static int __devexit max8660_remove(struct i2c_client *client)
        for (i = 0; i < MAX8660_V_END; i++)
                if (rdev[i])
                        regulator_unregister(rdev[i]);
-       kfree(rdev);
        i2c_set_clientdata(client, NULL);
+       kfree(rdev);
 
        return 0;
 }
index 67873f08ed40cccd89b52a764058affb0cb4e2b2..b6218f11c957ada5b98d5f3bd50d5c2093260ddd 100644 (file)
@@ -230,7 +230,7 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
        MAX8925_LDO(20, 750, 3900, 50),
 };
 
-static inline struct max8925_regulator_info *find_regulator_info(int id)
+static struct max8925_regulator_info * __devinit find_regulator_info(int id)
 {
        struct max8925_regulator_info *ri;
        int i;
@@ -247,7 +247,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
 {
        struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct max8925_platform_data *pdata = chip->dev->platform_data;
-       struct max8925_regulator_info *ri = NULL;
+       struct max8925_regulator_info *ri;
        struct regulator_dev *rdev;
 
        ri = find_regulator_info(pdev->id);
@@ -274,7 +274,9 @@ static int __devexit max8925_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
+       platform_set_drvdata(pdev, NULL);
        regulator_unregister(rdev);
+
        return 0;
 }
 
index d60c81b7b693c9c26afa236cf85abafd1b6e2ec2..1379c7faa44803be830bd37a6b39b554dd8e0c03 100644 (file)
@@ -319,35 +319,38 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
 {
        int ret;
        struct mc13783_rtc *priv;
+       struct mc13783 *mc13783;
        int rtcrst_pending;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
-       priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+       mc13783 = dev_get_drvdata(pdev->dev.parent);
+       priv->mc13783 = mc13783;
+
        platform_set_drvdata(pdev, priv);
 
-       mc13783_lock(priv->mc13783);
+       mc13783_lock(mc13783);
 
-       ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST,
+       ret = mc13783_irq_request(mc13783, MC13783_IRQ_RTCRST,
                        mc13783_rtc_reset_handler, DRIVER_NAME, priv);
        if (ret)
                goto err_reset_irq_request;
 
-       ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_RTCRST,
+       ret = mc13783_irq_status(mc13783, MC13783_IRQ_RTCRST,
                        NULL, &rtcrst_pending);
        if (ret)
                goto err_reset_irq_status;
 
        priv->valid = !rtcrst_pending;
 
-       ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ,
+       ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_1HZ,
                        mc13783_rtc_update_handler, DRIVER_NAME, priv);
        if (ret)
                goto err_update_irq_request;
 
-       ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_TODA,
+       ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_TODA,
                        mc13783_rtc_alarm_handler, DRIVER_NAME, priv);
        if (ret)
                goto err_alarm_irq_request;
@@ -357,22 +360,22 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
        if (IS_ERR(priv->rtc)) {
                ret = PTR_ERR(priv->rtc);
 
-               mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv);
+               mc13783_irq_free(mc13783, MC13783_IRQ_TODA, priv);
 err_alarm_irq_request:
 
-               mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
+               mc13783_irq_free(mc13783, MC13783_IRQ_1HZ, priv);
 err_update_irq_request:
 
 err_reset_irq_status:
 
-               mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
+               mc13783_irq_free(mc13783, MC13783_IRQ_RTCRST, priv);
 err_reset_irq_request:
 
                platform_set_drvdata(pdev, NULL);
                kfree(priv);
        }
 
-       mc13783_unlock(priv->mc13783);
+       mc13783_unlock(mc13783);
 
        return ret;
 }
index 51224f76b980eaf15908897b7a30fb19cca0ecfe..b3736b8aad39a743feeb8419fa3a2251d4d992c6 100644 (file)
@@ -2287,7 +2287,8 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
 
        if (cqr->cpmode == 1) {
                cplength = 0;
-               datasize = sizeof(struct tcw) + sizeof(struct tsb);
+               /* TCW needs to be 64 byte aligned, so leave enough room */
+               datasize = 64 + sizeof(struct tcw) + sizeof(struct tsb);
        } else {
                cplength = 2;
                datasize = 0;
@@ -2316,8 +2317,8 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
        if (cqr->cpmode == 1) {
                /* make a shallow copy of the original tcw but set new tsb */
                erp->cpmode = 1;
-               erp->cpaddr = erp->data;
-               tcw = erp->data;
+               erp->cpaddr = PTR_ALIGN(erp->data, 64);
+               tcw = erp->cpaddr;
                tsb = (struct tsb *) &tcw[1];
                *tcw = *((struct tcw *)cqr->cpaddr);
                tcw->tsb = (long)tsb;
index 01f4e7a34aa8b2aa8570bd16c4078b53c9f415cf..0cb2331168551ef4f290adb65683d8ee1902b30a 100644 (file)
@@ -3155,11 +3155,11 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
 
        tsb = NULL;
        sense = NULL;
-       if (irb->scsw.tm.tcw)
+       if (irb->scsw.tm.tcw && (irb->scsw.tm.fcxs == 0x01))
                tsb = tcw_get_tsb(
                        (struct tcw *)(unsigned long)irb->scsw.tm.tcw);
 
-       if (tsb && (irb->scsw.tm.fcxs == 0x01)) {
+       if (tsb) {
                len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                               " tsb->length %d\n", tsb->length);
                len += sprintf(page + len, KERN_ERR PRINTK_HEADER
index 740fe405c3959f199ca9d393d9d912443653101b..f449c696e5032a3415030ee41cc2c7f462fd0d2a 100644 (file)
@@ -84,6 +84,7 @@ static int proc_handler_callhome(struct ctl_table *ctl, int write,
                rc = copy_from_user(buf, buffer, sizeof(buf));
                if (rc != 0)
                        return -EFAULT;
+               buf[len - 1] = '\0';
                if (strict_strtoul(buf, 0, &val) != 0)
                        return -EINVAL;
                if (val != 0 && val != 1)
index fc7ae05ce48ae262374b0becc3373a1b42d00690..4b60ede07f0e0f9738d22c70d53c3393eff1b37e 100644 (file)
@@ -308,6 +308,13 @@ struct assign_storage_sccb {
        u16 rn;
 } __packed;
 
+int arch_get_memory_phys_device(unsigned long start_pfn)
+{
+       if (!rzm)
+               return 0;
+       return PFN_PHYS(start_pfn) >> ilog2(rzm);
+}
+
 static unsigned long long rn2addr(u16 rn)
 {
        return (unsigned long long) (rn - 1) * rzm;
@@ -704,13 +711,6 @@ int sclp_chp_deconfigure(struct chp_id chpid)
        return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8);
 }
 
-int arch_get_memory_phys_device(unsigned long start_pfn)
-{
-       if (!rzm)
-               return 0;
-       return PFN_PHYS(start_pfn) / rzm;
-}
-
 struct chp_info_sccb {
        struct sccb_header header;
        u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
index 3438658b66b76fb7f7aaf261310fe3512fa1cc70..3166d85914f289aa41e34c7b31fcb067e284dd5b 100644 (file)
@@ -141,33 +141,6 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
        return memcpy_hsa(dest, src, count, TO_KERNEL);
 }
 
-static int memcpy_real(void *dest, unsigned long src, size_t count)
-{
-       unsigned long flags;
-       int rc = -EFAULT;
-       register unsigned long _dest asm("2") = (unsigned long) dest;
-       register unsigned long _len1 asm("3") = (unsigned long) count;
-       register unsigned long _src  asm("4") = src;
-       register unsigned long _len2 asm("5") = (unsigned long) count;
-
-       if (count == 0)
-               return 0;
-       flags = __raw_local_irq_stnsm(0xf8UL); /* switch to real mode */
-       asm volatile (
-               "0:     mvcle   %1,%2,0x0\n"
-               "1:     jo      0b\n"
-               "       lhi     %0,0x0\n"
-               "2:\n"
-               EX_TABLE(1b,2b)
-               : "+d" (rc), "+d" (_dest), "+d" (_src), "+d" (_len1),
-                 "+d" (_len2), "=m" (*((long*)dest))
-               : "m" (*((long*)src))
-               : "cc", "memory");
-       __raw_local_irq_ssm(flags);
-
-       return rc;
-}
-
 static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
 {
        static char buf[4096];
@@ -175,7 +148,7 @@ static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
 
        while (offs < count) {
                size = min(sizeof(buf), count - offs);
-               if (memcpy_real(buf, src + offs, size))
+               if (memcpy_real(buf, (void *) src + offs, size))
                        return -EFAULT;
                if (copy_to_user(dest + offs, buf, size))
                        return -EFAULT;
@@ -663,7 +636,7 @@ static int __init zcore_reipl_init(void)
        if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE)
                rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE);
        else
-               rc = memcpy_real(ipl_block, ipib_info.ipib, PAGE_SIZE);
+               rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE);
        if (rc) {
                free_page((unsigned long) ipl_block);
                return rc;
index e91db4b380120fb1eae857179c1d42006b545bb1..175d202ab37ee20c1915b871b27dfe8a122ec293 100644 (file)
@@ -745,6 +745,7 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
        PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
        PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
        PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
        PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
        PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
index f7b9aff88f4a28836ef502b59ff37e77c32faf08..309de6be8204bcc9fc880c6c9ae39884f460c8b3 100644 (file)
@@ -779,10 +779,6 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
        if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
                ret = sci_br_interrupt(irq, ptr);
 
-       WARN_ONCE(ret == IRQ_NONE,
-                 "%s: %d IRQ %d, status %x, control %x\n", __func__,
-                 irq, port->line, ssr_status, scr_status);
-
        return ret;
 }
 
index fad67d33b0bdddf5a04cfb103842c83ac0a72d35..f70c49f915fa11c7878747f58973bebc899f5542 100644 (file)
@@ -31,7 +31,9 @@
 # define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0
 #elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \
       defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-      defined(CONFIG_ARCH_SHMOBILE)
+      defined(CONFIG_ARCH_SH7367) || \
+      defined(CONFIG_ARCH_SH7377) || \
+      defined(CONFIG_ARCH_SH7372)
 # define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define PORT_PTCR        0xA405011EUL
 # define PORT_PVCR        0xA4050122UL
@@ -94,7 +96,9 @@
 # define SCSCR_INIT(port)       0x0038  /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7724)
 # define SCIF_ORER              0x0001  /* overrun error bit */
-# define SCSCR_INIT(port)       0x0038  /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCSCR_INIT(port) ((port)->type == PORT_SCIFA ? \
+       0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \
+       0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ )
 #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
 # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
     defined(CONFIG_CPU_SUBTYPE_SH7786)  || \
     defined(CONFIG_CPU_SUBTYPE_SHX3)
 #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define SCI_CTRL_FLAGS_REIE ((port)->type == PORT_SCIFA ? 0 : 8)
 #else
 #define SCI_CTRL_FLAGS_REIE 0
 #endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_ARCH_SHMOBILE)
+    defined(CONFIG_ARCH_SH7367) || \
+    defined(CONFIG_ARCH_SH7377) || \
+    defined(CONFIG_ARCH_SH7372)
 # define SCIF_ORER    0x0200
 # define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER)
 # define SCIF_RFDC_MASK 0x007f
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_ARCH_SHMOBILE)
+    defined(CONFIG_ARCH_SH7367) || \
+    defined(CONFIG_ARCH_SH7377) || \
+    defined(CONFIG_ARCH_SH7372)
 # define SCxSR_RDxF_CLEAR(port)         (sci_in(port, SCxSR) & 0xfffc)
 # define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73)
 # define SCxSR_TDxE_CLEAR(port)         (sci_in(port, SCxSR) & 0xffdf)
     SCI_OUT(sci_size, sci_offset, value);                              \
   }
 
-#if defined(CONFIG_CPU_SH3) || defined(CONFIG_ARCH_SHMOBILE)
+#if defined(CONFIG_CPU_SH3) || \
+    defined(CONFIG_ARCH_SH7367) || \
+    defined(CONFIG_ARCH_SH7377) || \
+    defined(CONFIG_ARCH_SH7372)
 #if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
 #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
                                sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
       defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-      defined(CONFIG_ARCH_SHMOBILE)
+      defined(CONFIG_ARCH_SH7367) || \
+      defined(CONFIG_ARCH_SH7377) || \
+      defined(CONFIG_ARCH_SH7372)
 #define SCIF_FNS(name, scif_offset, scif_size) \
   CPU_SCIF_FNS(name, scif_offset, scif_size)
 #else
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_ARCH_SHMOBILE)
+    defined(CONFIG_ARCH_SH7367) || \
+    defined(CONFIG_ARCH_SH7377) || \
+    defined(CONFIG_ARCH_SH7372)
 
 SCIF_FNS(SCSMR,  0x00, 16)
 SCIF_FNS(SCBRR,  0x04,  8)
@@ -589,7 +606,9 @@ static inline int sci_rxd_in(struct uart_port *port)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
       defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-      defined(CONFIG_ARCH_SHMOBILE)
+      defined(CONFIG_ARCH_SH7367) || \
+      defined(CONFIG_ARCH_SH7377) || \
+      defined(CONFIG_ARCH_SH7372)
 #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
       defined(CONFIG_CPU_SUBTYPE_SH7724)
index a292b1edc41435886ceecc013db7754d67fe6f01..737a9f5401d1be0ade322d3e198bb6ef2b0f1a38 100644 (file)
@@ -226,7 +226,7 @@ void ConfigMACRegs2(struct et131x_adapter *etdev)
        }
 
        /* Enable TXMAC */
-       ctl |= 0x05;    /* TX mac enable, FC disable */
+       ctl |= 0x09;    /* TX mac enable, FC disable */
        writel(ctl, &etdev->regs->txmac.ctl);
 
        /* Ready to start the RXDMA/TXDMA engine */
index 5e13d23b5f0c887294ce45a9d3521049aaa126b4..8b45145b913618ea302bf062e905a67ed87baaf2 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
index ad37da2b6cb5bba78ac91664d93088f7ec2fb59c..a6a88dfd5029e87d13c141d6482f0efc8e085489 100644 (file)
@@ -125,7 +125,7 @@ static void handle_tx(struct vhost_net *net)
        mutex_lock(&vq->mutex);
        vhost_disable_notify(vq);
 
-       if (wmem < sock->sk->sk_sndbuf * 2)
+       if (wmem < sock->sk->sk_sndbuf / 2)
                tx_poll_stop(net);
        hdr_size = vq->hdr_size;
 
@@ -508,12 +508,12 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
        /* Verify that ring has been setup correctly. */
        if (!vhost_vq_access_ok(vq)) {
                r = -EFAULT;
-               goto err;
+               goto err_vq;
        }
        sock = get_socket(fd);
        if (IS_ERR(sock)) {
                r = PTR_ERR(sock);
-               goto err;
+               goto err_vq;
        }
 
        /* start polling new socket */
@@ -524,12 +524,14 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
        vhost_net_disable_vq(n, vq);
        rcu_assign_pointer(vq->private_data, sock);
        vhost_net_enable_vq(n, vq);
-       mutex_unlock(&vq->mutex);
 done:
        if (oldsock) {
                vhost_net_flush_vq(n, index);
                fput(oldsock->file);
        }
+
+err_vq:
+       mutex_unlock(&vq->mutex);
 err:
        mutex_unlock(&n->dev.mutex);
        return r;
index 7cd55e07879455abe95e04fa06656623b415c9a9..7bd7a1e4409d4e6f384c513734b743a1b56a55ca 100644 (file)
@@ -476,8 +476,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
                if (r < 0)
                        break;
                eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
-               if (IS_ERR(eventfp))
-                       return PTR_ERR(eventfp);
+               if (IS_ERR(eventfp)) {
+                       r = PTR_ERR(eventfp);
+                       break;
+               }
                if (eventfp != vq->kick) {
                        pollstop = filep = vq->kick;
                        pollstart = vq->kick = eventfp;
@@ -489,8 +491,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
                if (r < 0)
                        break;
                eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
-               if (IS_ERR(eventfp))
-                       return PTR_ERR(eventfp);
+               if (IS_ERR(eventfp)) {
+                       r = PTR_ERR(eventfp);
+                       break;
+               }
                if (eventfp != vq->call) {
                        filep = vq->call;
                        ctx = vq->call_ctx;
@@ -505,8 +509,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
                if (r < 0)
                        break;
                eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
-               if (IS_ERR(eventfp))
-                       return PTR_ERR(eventfp);
+               if (IS_ERR(eventfp)) {
+                       r = PTR_ERR(eventfp);
+                       break;
+               }
                if (eventfp != vq->error) {
                        filep = vq->error;
                        vq->error = eventfp;
index cc781c00f75d04a11a9b371db177dca3ea64b06d..e4c4d89b786034c33aaf687b9616feddd3c76bbd 100644 (file)
@@ -365,6 +365,8 @@ enum fp_registers {
        FP_CRC, /* 0x458 */
 };
 
+#define FP_PT2_HSP                     (1 << 22)
+#define FP_PT2_VSP                     (1 << 23)
 #define FP_PT2_SCRC                    (1 << 27)       /* shfclk free */
 
 #define FP_PM_P                                (1 << 24)       /* panel power ctl */
index 0e5d8c7c3ebae2ad81a62bd693c857e10771f01a..bc35a95e59d417ef85df900e26824f5de67eaa35 100644 (file)
@@ -274,7 +274,15 @@ static void lx_graphics_enable(struct fb_info *info)
                u32 msrlo, msrhi;
 
                write_fp(par, FP_PT1, 0);
-               write_fp(par, FP_PT2, FP_PT2_SCRC);
+               temp = FP_PT2_SCRC;
+
+               if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+                       temp |= FP_PT2_HSP;
+
+               if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+                       temp |= FP_PT2_VSP;
+
+               write_fp(par, FP_PT2, temp);
                write_fp(par, FP_DFC, FP_DFC_BC);
 
                msrlo = MSR_LX_MSR_PADSEL_TFT_SEL_LOW;
index c59e4baed8b2b7d780a67c24bd45ce50c25b4de7..300eff5de1b4830490e6a5f36d48adf8b63a5b1e 100644 (file)
@@ -116,6 +116,24 @@ static int generic_panel_resume(struct omap_dss_device *dssdev)
        return 0;
 }
 
+static void generic_panel_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       dpi_set_timings(dssdev, timings);
+}
+
+static void generic_panel_get_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       *timings = dssdev->panel.timings;
+}
+
+static int generic_panel_check_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       return dpi_check_timings(dssdev, timings);
+}
+
 static struct omap_dss_driver generic_driver = {
        .probe          = generic_panel_probe,
        .remove         = generic_panel_remove,
@@ -125,6 +143,10 @@ static struct omap_dss_driver generic_driver = {
        .suspend        = generic_panel_suspend,
        .resume         = generic_panel_resume,
 
+       .set_timings    = generic_panel_set_timings,
+       .get_timings    = generic_panel_get_timings,
+       .check_timings  = generic_panel_check_timings,
+
        .driver         = {
                .name   = "generic_panel",
                .owner  = THIS_MODULE,
index 8254a4232a536d3c844214e165bd67507d94c943..54344184dd733ceae5df78e9cff33ffa51c7629f 100644 (file)
@@ -590,6 +590,9 @@ int dss_init(bool skip_init)
                }
        }
 
+       dss.dsi_clk_source = DSS_SRC_DSS1_ALWON_FCLK;
+       dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK;
+
        dss_save_context();
 
        rev = dss_read_reg(DSS_REVISION);
index 55a4de5e5d10df6cc45c7dd6c9ef68c97636cd40..b266ffae0bdea5f23d4d8ca4fa007ed9166f605e 100644 (file)
@@ -511,13 +511,14 @@ static u32 omap_vram_sdram_size __initdata;
 static u32 omap_vram_def_sdram_size __initdata;
 static u32 omap_vram_def_sdram_start __initdata;
 
-static void __init omap_vram_early_vram(char **p)
+static int __init omap_vram_early_vram(char *p)
 {
-       omap_vram_def_sdram_size = memparse(*p, p);
-       if (**p == ',')
-               omap_vram_def_sdram_start = simple_strtoul((*p) + 1, p, 16);
+       omap_vram_def_sdram_size = memparse(p, &p);
+       if (*p == ',')
+               omap_vram_def_sdram_start = simple_strtoul(p + 1, &p, 16);
+       return 0;
 }
-__early_param("vram=", omap_vram_early_vram);
+early_param("vram", omap_vram_early_vram);
 
 /*
  * Called from map_io. We need to call to this early enough so that we
index 75285d3f393cba74c77eb35017e98b229d639769..c91a7f70f7b086f56882ba07f97ba38e314adfd6 100644 (file)
@@ -668,7 +668,7 @@ static int __init pxa168fb_probe(struct platform_device *pdev)
        /*
         * Map LCD controller registers.
         */
-       fbi->reg_base = ioremap_nocache(res->start, res->end - res->start);
+       fbi->reg_base = ioremap_nocache(res->start, resource_size(res));
        if (fbi->reg_base == NULL) {
                ret = -ENOMEM;
                goto failed;
index 3ef504370034c2311fdd50f631856ac95ab76903..bb4ed144d0e446c627fb8b4e391664058d094b87 100644 (file)
@@ -189,8 +189,9 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key, long acl_order)
        if (!permits)
                goto out_unlock;
 
-       memcpy(permits->permits, xpermits->permits,
-              count * sizeof(struct afs_permit));
+       if (xpermits)
+               memcpy(permits->permits, xpermits->permits,
+                       count * sizeof(struct afs_permit));
 
        _debug("key %x access %x",
               key_serial(key), vnode->status.caller_access);
index 15d80bb35d6f7c9e10adcb7ac62d587813449870..9b6aef0f75e5869ba007fda12f73dcb1f177cccf 100644 (file)
@@ -75,14 +75,16 @@ static int aout_core_dump(struct coredump_params *cprm)
        struct file *file = cprm->file;
        mm_segment_t fs;
        int has_dumped = 0;
-       unsigned long dump_start, dump_size;
+       void __user *dump_start;
+       int dump_size;
        struct user dump;
 #ifdef __alpha__
-#       define START_DATA(u)   (u.start_data)
+#       define START_DATA(u)   ((void __user *)u.start_data)
 #else
-#      define START_DATA(u)    ((u.u_tsize << PAGE_SHIFT) + u.start_code)
+#      define START_DATA(u)    ((void __user *)((u.u_tsize << PAGE_SHIFT) + \
+                                u.start_code))
 #endif
-#       define START_STACK(u)   (u.start_stack)
+#       define START_STACK(u)   ((void __user *)u.start_stack)
 
        fs = get_fs();
        set_fs(KERNEL_DS);
@@ -104,9 +106,9 @@ static int aout_core_dump(struct coredump_params *cprm)
 
 /* make sure we actually have a data and stack area to dump */
        set_fs(USER_DS);
-       if (!access_ok(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
+       if (!access_ok(VERIFY_READ, START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
                dump.u_dsize = 0;
-       if (!access_ok(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
+       if (!access_ok(VERIFY_READ, START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
                dump.u_ssize = 0;
 
        set_fs(KERNEL_DS);
index 2c32d00a66904883339fe2b25ebe991cdeb6a489..7ab23e006e4cbb20c31c7d4fca47d283c96e3121 100644 (file)
@@ -1590,7 +1590,7 @@ static size_t elf_core_vma_data_size(unsigned long mm_flags)
        struct vm_area_struct *vma;
        size_t size = 0;
 
-       for (vma = current->mm->mmap; vma; vma->vm_next)
+       for (vma = current->mm->mmap; vma; vma = vma->vm_next)
                if (maydump(vma, mm_flags))
                        size += vma->vm_end - vma->vm_start;
        return size;
index 23bb0ceabe31904521019fafd36bd1cf9ba8f8c1..ce8ef6107727a7ea2b383c4dd7767a14d75db496 100644 (file)
@@ -919,6 +919,10 @@ static int context_is_writeable_or_written(struct inode *inode,
 /*
  * We are only allowed to write into/dirty the page if the page is
  * clean, or already dirty within the same snap context.
+ *
+ * called with page locked.
+ * return success with page locked,
+ * or any failure (incl -EAGAIN) with page unlocked.
  */
 static int ceph_update_writeable_page(struct file *file,
                            loff_t pos, unsigned len,
@@ -961,9 +965,11 @@ retry_locked:
                        snapc = ceph_get_snap_context((void *)page->private);
                        unlock_page(page);
                        ceph_queue_writeback(inode);
-                       wait_event_interruptible(ci->i_cap_wq,
+                       r = wait_event_interruptible(ci->i_cap_wq,
                               context_is_writeable_or_written(inode, snapc));
                        ceph_put_snap_context(snapc);
+                       if (r == -ERESTARTSYS)
+                               return r;
                        return -EAGAIN;
                }
 
@@ -1035,7 +1041,7 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
        int r;
 
        do {
-               /* get a page*/
+               /* get a page */
                page = grab_cache_page_write_begin(mapping, index, 0);
                if (!page)
                        return -ENOMEM;
index f0318427b6dabd0a3d009288f1e29ba892c6ca84..8d8a8496476328c500e7e959e6a9fcbb90ac5d1d 100644 (file)
@@ -28,6 +28,12 @@ static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
        return (ac->want_keys & xi->have_keys) == ac->want_keys;
 }
 
+static int ceph_x_encrypt_buflen(int ilen)
+{
+       return sizeof(struct ceph_x_encrypt_header) + ilen + 16 +
+               sizeof(u32);
+}
+
 static int ceph_x_encrypt(struct ceph_crypto_key *secret,
                          void *ibuf, int ilen, void *obuf, size_t olen)
 {
@@ -150,6 +156,11 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
                struct timespec validity;
                struct ceph_crypto_key old_key;
                void *tp, *tpend;
+               struct ceph_timespec new_validity;
+               struct ceph_crypto_key new_session_key;
+               struct ceph_buffer *new_ticket_blob;
+               unsigned long new_expires, new_renew_after;
+               u64 new_secret_id;
 
                ceph_decode_need(&p, end, sizeof(u32) + 1, bad);
 
@@ -182,16 +193,16 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
                        goto bad;
 
                memcpy(&old_key, &th->session_key, sizeof(old_key));
-               ret = ceph_crypto_key_decode(&th->session_key, &dp, dend);
+               ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
                if (ret)
                        goto out;
 
-               ceph_decode_copy(&dp, &th->validity, sizeof(th->validity));
-               ceph_decode_timespec(&validity, &th->validity);
-               th->expires = get_seconds() + validity.tv_sec;
-               th->renew_after = th->expires - (validity.tv_sec / 4);
-               dout(" expires=%lu renew_after=%lu\n", th->expires,
-                    th->renew_after);
+               ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
+               ceph_decode_timespec(&validity, &new_validity);
+               new_expires = get_seconds() + validity.tv_sec;
+               new_renew_after = new_expires - (validity.tv_sec / 4);
+               dout(" expires=%lu renew_after=%lu\n", new_expires,
+                    new_renew_after);
 
                /* ticket blob for service */
                ceph_decode_8_safe(&p, end, is_enc, bad);
@@ -216,10 +227,21 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
                dout(" ticket blob is %d bytes\n", dlen);
                ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
                struct_v = ceph_decode_8(&tp);
-               th->secret_id = ceph_decode_64(&tp);
-               ret = ceph_decode_buffer(&th->ticket_blob, &tp, tpend);
+               new_secret_id = ceph_decode_64(&tp);
+               ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
                if (ret)
                        goto out;
+
+               /* all is well, update our ticket */
+               ceph_crypto_key_destroy(&th->session_key);
+               if (th->ticket_blob)
+                       ceph_buffer_put(th->ticket_blob);
+               th->session_key = new_session_key;
+               th->ticket_blob = new_ticket_blob;
+               th->validity = new_validity;
+               th->secret_id = new_secret_id;
+               th->expires = new_expires;
+               th->renew_after = new_renew_after;
                dout(" got ticket service %d (%s) secret_id %lld len %d\n",
                     type, ceph_entity_type_name(type), th->secret_id,
                     (int)th->ticket_blob->vec.iov_len);
@@ -242,7 +264,7 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
                                   struct ceph_x_ticket_handler *th,
                                   struct ceph_x_authorizer *au)
 {
-       int len;
+       int maxlen;
        struct ceph_x_authorize_a *msg_a;
        struct ceph_x_authorize_b msg_b;
        void *p, *end;
@@ -253,15 +275,15 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
        dout("build_authorizer for %s %p\n",
             ceph_entity_type_name(th->service), au);
 
-       len = sizeof(*msg_a) + sizeof(msg_b) + sizeof(u32) +
-               ticket_blob_len + 16;
-       dout("  need len %d\n", len);
-       if (au->buf && au->buf->alloc_len < len) {
+       maxlen = sizeof(*msg_a) + sizeof(msg_b) +
+               ceph_x_encrypt_buflen(ticket_blob_len);
+       dout("  need len %d\n", maxlen);
+       if (au->buf && au->buf->alloc_len < maxlen) {
                ceph_buffer_put(au->buf);
                au->buf = NULL;
        }
        if (!au->buf) {
-               au->buf = ceph_buffer_new(len, GFP_NOFS);
+               au->buf = ceph_buffer_new(maxlen, GFP_NOFS);
                if (!au->buf)
                        return -ENOMEM;
        }
@@ -296,6 +318,7 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
        au->buf->vec.iov_len = p - au->buf->vec.iov_base;
        dout(" built authorizer nonce %llx len %d\n", au->nonce,
             (int)au->buf->vec.iov_len);
+       BUG_ON(au->buf->vec.iov_len > maxlen);
        return 0;
 
 out_buf:
index db122bb357b89f413c485d532c5cba8a83944b39..7d0a0d0adc18f882e88e31f91650dab7b168014c 100644 (file)
@@ -1407,6 +1407,7 @@ static int try_nonblocking_invalidate(struct inode *inode)
  */
 void ceph_check_caps(struct ceph_inode_info *ci, int flags,
                     struct ceph_mds_session *session)
+       __releases(session->s_mutex)
 {
        struct ceph_client *client = ceph_inode_to_client(&ci->vfs_inode);
        struct ceph_mds_client *mdsc = &client->mdsc;
@@ -1414,7 +1415,6 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
        struct ceph_cap *cap;
        int file_wanted, used;
        int took_snap_rwsem = 0;             /* true if mdsc->snap_rwsem held */
-       int drop_session_lock = session ? 0 : 1;
        int issued, implemented, want, retain, revoking, flushing = 0;
        int mds = -1;   /* keep track of how far we've gone through i_caps list
                           to avoid an infinite loop on retry */
@@ -1639,7 +1639,7 @@ ack:
        if (queue_invalidate)
                ceph_queue_invalidate(inode);
 
-       if (session && drop_session_lock)
+       if (session)
                mutex_unlock(&session->s_mutex);
        if (took_snap_rwsem)
                up_read(&mdsc->snap_rwsem);
@@ -2195,18 +2195,19 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
  * Handle a cap GRANT message from the MDS.  (Note that a GRANT may
  * actually be a revocation if it specifies a smaller cap set.)
  *
- * caller holds s_mutex.
+ * caller holds s_mutex and i_lock, we drop both.
+ *
  * return value:
  *  0 - ok
  *  1 - check_caps on auth cap only (writeback)
  *  2 - check_caps (ack revoke)
  */
-static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
-                           struct ceph_mds_session *session,
-                           struct ceph_cap *cap,
-                           struct ceph_buffer *xattr_buf)
+static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
+                            struct ceph_mds_session *session,
+                            struct ceph_cap *cap,
+                            struct ceph_buffer *xattr_buf)
        __releases(inode->i_lock)
-
+       __releases(session->s_mutex)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
        int mds = session->s_mds;
@@ -2216,7 +2217,7 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
        u64 size = le64_to_cpu(grant->size);
        u64 max_size = le64_to_cpu(grant->max_size);
        struct timespec mtime, atime, ctime;
-       int reply = 0;
+       int check_caps = 0;
        int wake = 0;
        int writeback = 0;
        int revoked_rdcache = 0;
@@ -2329,11 +2330,12 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
                if ((used & ~newcaps) & CEPH_CAP_FILE_BUFFER)
                        writeback = 1; /* will delay ack */
                else if (dirty & ~newcaps)
-                       reply = 1;     /* initiate writeback in check_caps */
+                       check_caps = 1;  /* initiate writeback in check_caps */
                else if (((used & ~newcaps) & CEPH_CAP_FILE_CACHE) == 0 ||
                           revoked_rdcache)
-                       reply = 2;     /* send revoke ack in check_caps */
+                       check_caps = 2;     /* send revoke ack in check_caps */
                cap->issued = newcaps;
+               cap->implemented |= newcaps;
        } else if (cap->issued == newcaps) {
                dout("caps unchanged: %s -> %s\n",
                     ceph_cap_string(cap->issued), ceph_cap_string(newcaps));
@@ -2346,6 +2348,7 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
                                              * pending revocation */
                wake = 1;
        }
+       BUG_ON(cap->issued & ~cap->implemented);
 
        spin_unlock(&inode->i_lock);
        if (writeback)
@@ -2359,7 +2362,14 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
                ceph_queue_invalidate(inode);
        if (wake)
                wake_up(&ci->i_cap_wq);
-       return reply;
+
+       if (check_caps == 1)
+               ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_AUTHONLY,
+                               session);
+       else if (check_caps == 2)
+               ceph_check_caps(ci, CHECK_CAPS_NODELAY, session);
+       else
+               mutex_unlock(&session->s_mutex);
 }
 
 /*
@@ -2548,9 +2558,8 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
                        ci->i_cap_exporting_issued = cap->issued;
                }
                __ceph_remove_cap(cap);
-       } else {
-               WARN_ON(!cap);
        }
+       /* else, we already released it */
 
        spin_unlock(&inode->i_lock);
 }
@@ -2621,9 +2630,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        u64 cap_id;
        u64 size, max_size;
        u64 tid;
-       int check_caps = 0;
        void *snaptrace;
-       int r;
 
        dout("handle_caps from mds%d\n", mds);
 
@@ -2668,8 +2675,9 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        case CEPH_CAP_OP_IMPORT:
                handle_cap_import(mdsc, inode, h, session,
                                  snaptrace, le32_to_cpu(h->snap_trace_len));
-               check_caps = 1; /* we may have sent a RELEASE to the old auth */
-               goto done;
+               ceph_check_caps(ceph_inode(inode), CHECK_CAPS_NODELAY,
+                               session);
+               goto done_unlocked;
        }
 
        /* the rest require a cap */
@@ -2686,16 +2694,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        switch (op) {
        case CEPH_CAP_OP_REVOKE:
        case CEPH_CAP_OP_GRANT:
-               r = handle_cap_grant(inode, h, session, cap, msg->middle);
-               if (r == 1)
-                       ceph_check_caps(ceph_inode(inode),
-                                       CHECK_CAPS_NODELAY|CHECK_CAPS_AUTHONLY,
-                                       session);
-               else if (r == 2)
-                       ceph_check_caps(ceph_inode(inode),
-                                       CHECK_CAPS_NODELAY,
-                                       session);
-               break;
+               handle_cap_grant(inode, h, session, cap, msg->middle);
+               goto done_unlocked;
 
        case CEPH_CAP_OP_FLUSH_ACK:
                handle_cap_flush_ack(inode, tid, h, session, cap);
@@ -2713,9 +2713,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
 
 done:
        mutex_unlock(&session->s_mutex);
-
-       if (check_caps)
-               ceph_check_caps(ceph_inode(inode), CHECK_CAPS_NODELAY, NULL);
+done_unlocked:
        if (inode)
                iput(inode);
        return;
@@ -2838,11 +2836,18 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
        struct ceph_cap *cap;
        struct ceph_mds_request_release *rel = *p;
        int ret = 0;
-
-       dout("encode_inode_release %p mds%d drop %s unless %s\n", inode,
-            mds, ceph_cap_string(drop), ceph_cap_string(unless));
+       int used = 0;
 
        spin_lock(&inode->i_lock);
+       used = __ceph_caps_used(ci);
+
+       dout("encode_inode_release %p mds%d used %s drop %s unless %s\n", inode,
+            mds, ceph_cap_string(used), ceph_cap_string(drop),
+            ceph_cap_string(unless));
+
+       /* only drop unused caps */
+       drop &= ~used;
+
        cap = __get_cap_for_mds(ci, mds);
        if (cap && __cap_is_valid(cap)) {
                if (force ||
index 5107384ee02927351889ace8f32c5535f718dda8..8a9116e15b701a809d6b6d78636c97d56bc81c97 100644 (file)
@@ -288,8 +288,10 @@ more:
                        CEPH_MDS_OP_LSSNAP : CEPH_MDS_OP_READDIR;
 
                /* discard old result, if any */
-               if (fi->last_readdir)
+               if (fi->last_readdir) {
                        ceph_mdsc_put_request(fi->last_readdir);
+                       fi->last_readdir = NULL;
+               }
 
                /* requery frag tree, as the frag topology may have changed */
                frag = ceph_choose_frag(ceph_inode(inode), frag, NULL, NULL);
index 7abe1aed819b080de138a17ec16f8d7d9c7d9523..aca82d55cc53882a5fc3af08955e56a9f317e8cd 100644 (file)
@@ -378,6 +378,22 @@ void ceph_destroy_inode(struct inode *inode)
 
        ceph_queue_caps_release(inode);
 
+       /*
+        * we may still have a snap_realm reference if there are stray
+        * caps in i_cap_exporting_issued or i_snap_caps.
+        */
+       if (ci->i_snap_realm) {
+               struct ceph_mds_client *mdsc =
+                       &ceph_client(ci->vfs_inode.i_sb)->mdsc;
+               struct ceph_snap_realm *realm = ci->i_snap_realm;
+
+               dout(" dropping residual ref to snap realm %p\n", realm);
+               spin_lock(&realm->inodes_with_caps_lock);
+               list_del_init(&ci->i_snap_realm_item);
+               spin_unlock(&realm->inodes_with_caps_lock);
+               ceph_put_snap_realm(mdsc, realm);
+       }
+
        kfree(ci->i_symlink);
        while ((n = rb_first(&ci->i_fragtree)) != NULL) {
                frag = rb_entry(n, struct ceph_inode_frag, node);
index a2600101ec220d0bd17b657d8a69889c6f0055a2..5c7920be6420ee27a6f939754704fc0ed32f8c97 100644 (file)
@@ -328,6 +328,8 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
        struct ceph_mds_session *s;
 
        s = kzalloc(sizeof(*s), GFP_NOFS);
+       if (!s)
+               return ERR_PTR(-ENOMEM);
        s->s_mdsc = mdsc;
        s->s_mds = mds;
        s->s_state = CEPH_MDS_SESSION_NEW;
@@ -529,7 +531,7 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
 {
        dout("__unregister_request %p tid %lld\n", req, req->r_tid);
        rb_erase(&req->r_node, &mdsc->request_tree);
-       ceph_mdsc_put_request(req);
+       RB_CLEAR_NODE(&req->r_node);
 
        if (req->r_unsafe_dir) {
                struct ceph_inode_info *ci = ceph_inode(req->r_unsafe_dir);
@@ -538,6 +540,8 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
                list_del_init(&req->r_unsafe_dir_item);
                spin_unlock(&ci->i_unsafe_lock);
        }
+
+       ceph_mdsc_put_request(req);
 }
 
 /*
@@ -862,6 +866,7 @@ static int send_renew_caps(struct ceph_mds_client *mdsc,
        if (time_after_eq(jiffies, session->s_cap_ttl) &&
            time_after_eq(session->s_cap_ttl, session->s_renew_requested))
                pr_info("mds%d caps stale\n", session->s_mds);
+       session->s_renew_requested = jiffies;
 
        /* do not try to renew caps until a recovering mds has reconnected
         * with its clients. */
@@ -874,7 +879,6 @@ static int send_renew_caps(struct ceph_mds_client *mdsc,
 
        dout("send_renew_caps to mds%d (%s)\n", session->s_mds,
                ceph_mds_state_name(state));
-       session->s_renew_requested = jiffies;
        msg = create_session_msg(CEPH_SESSION_REQUEST_RENEWCAPS,
                                 ++session->s_renew_seq);
        if (IS_ERR(msg))
@@ -1566,8 +1570,13 @@ static int __do_request(struct ceph_mds_client *mdsc,
 
        /* get, open session */
        session = __ceph_lookup_mds_session(mdsc, mds);
-       if (!session)
+       if (!session) {
                session = register_session(mdsc, mds);
+               if (IS_ERR(session)) {
+                       err = PTR_ERR(session);
+                       goto finish;
+               }
+       }
        dout("do_request mds%d session %p state %s\n", mds, session,
             session_state_name(session->s_state));
        if (session->s_state != CEPH_MDS_SESSION_OPEN &&
@@ -1770,7 +1779,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        dout("handle_reply %p\n", req);
 
        /* correct session? */
-       if (!req->r_session && req->r_session != session) {
+       if (req->r_session != session) {
                pr_err("mdsc_handle_reply got %llu on session mds%d"
                       " not mds%d\n", tid, session->s_mds,
                       req->r_session ? req->r_session->s_mds : -1);
@@ -2682,29 +2691,41 @@ void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc)
  */
 static void wait_unsafe_requests(struct ceph_mds_client *mdsc, u64 want_tid)
 {
-       struct ceph_mds_request *req = NULL;
+       struct ceph_mds_request *req = NULL, *nextreq;
        struct rb_node *n;
 
        mutex_lock(&mdsc->mutex);
        dout("wait_unsafe_requests want %lld\n", want_tid);
+restart:
        req = __get_oldest_req(mdsc);
        while (req && req->r_tid <= want_tid) {
+               /* find next request */
+               n = rb_next(&req->r_node);
+               if (n)
+                       nextreq = rb_entry(n, struct ceph_mds_request, r_node);
+               else
+                       nextreq = NULL;
                if ((req->r_op & CEPH_MDS_OP_WRITE)) {
                        /* write op */
                        ceph_mdsc_get_request(req);
+                       if (nextreq)
+                               ceph_mdsc_get_request(nextreq);
                        mutex_unlock(&mdsc->mutex);
                        dout("wait_unsafe_requests  wait on %llu (want %llu)\n",
                             req->r_tid, want_tid);
                        wait_for_completion(&req->r_safe_completion);
                        mutex_lock(&mdsc->mutex);
-                       n = rb_next(&req->r_node);
                        ceph_mdsc_put_request(req);
-               } else {
-                       n = rb_next(&req->r_node);
+                       if (!nextreq)
+                               break;  /* next dne before, so we're done! */
+                       if (RB_EMPTY_NODE(&nextreq->r_node)) {
+                               /* next request was removed from tree */
+                               ceph_mdsc_put_request(nextreq);
+                               goto restart;
+                       }
+                       ceph_mdsc_put_request(nextreq);  /* won't go away */
                }
-               if (!n)
-                       break;
-               req = rb_entry(n, struct ceph_mds_request, r_node);
+               req = nextreq;
        }
        mutex_unlock(&mdsc->mutex);
        dout("wait_unsafe_requests done\n");
index 781656a49bf87d101444139cb0483c055df802fb..a32f0f896d9f3c8d29b6d5758df000ae556b8683 100644 (file)
@@ -365,6 +365,14 @@ void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr)
        queue_con(con);
 }
 
+/*
+ * return true if this connection ever successfully opened
+ */
+bool ceph_con_opened(struct ceph_connection *con)
+{
+       return con->connect_seq > 0;
+}
+
 /*
  * generic get/put
  */
@@ -830,13 +838,6 @@ static void prepare_read_connect(struct ceph_connection *con)
        con->in_base_pos = 0;
 }
 
-static void prepare_read_connect_retry(struct ceph_connection *con)
-{
-       dout("prepare_read_connect_retry %p\n", con);
-       con->in_base_pos = strlen(CEPH_BANNER) + sizeof(con->actual_peer_addr)
-               + sizeof(con->peer_addr_for_me);
-}
-
 static void prepare_read_ack(struct ceph_connection *con)
 {
        dout("prepare_read_ack %p\n", con);
@@ -1146,7 +1147,7 @@ static int process_connect(struct ceph_connection *con)
                }
                con->auth_retry = 1;
                prepare_write_connect(con->msgr, con, 0);
-               prepare_read_connect_retry(con);
+               prepare_read_connect(con);
                break;
 
        case CEPH_MSGR_TAG_RESETSESSION:
@@ -1843,8 +1844,6 @@ static void ceph_fault(struct ceph_connection *con)
                goto out;
        }
 
-       clear_bit(BUSY, &con->state);  /* to avoid an improbable race */
-
        mutex_lock(&con->mutex);
        if (test_bit(CLOSED, &con->state))
                goto out_unlock;
index 4caaa5911110372510946678dc62b1ac181fcc38..a343dae73cdcf4f6f458480e4b910e5b9889093e 100644 (file)
@@ -223,6 +223,7 @@ extern void ceph_con_init(struct ceph_messenger *msgr,
                          struct ceph_connection *con);
 extern void ceph_con_open(struct ceph_connection *con,
                          struct ceph_entity_addr *addr);
+extern bool ceph_con_opened(struct ceph_connection *con);
 extern void ceph_con_close(struct ceph_connection *con);
 extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg);
 extern void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg);
index dbe63db9762fc11048bbe5f3bcb37e0aad7f3e2c..c7b4dedaace674d60112326531d0d467dd69d122 100644 (file)
@@ -413,11 +413,22 @@ static void remove_old_osds(struct ceph_osd_client *osdc, int remove_all)
  */
 static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
 {
+       struct ceph_osd_request *req;
        int ret = 0;
 
        dout("__reset_osd %p osd%d\n", osd, osd->o_osd);
        if (list_empty(&osd->o_requests)) {
                __remove_osd(osdc, osd);
+       } else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd],
+                         &osd->o_con.peer_addr,
+                         sizeof(osd->o_con.peer_addr)) == 0 &&
+                  !ceph_con_opened(&osd->o_con)) {
+               dout(" osd addr hasn't changed and connection never opened,"
+                    " letting msgr retry");
+               /* touch each r_stamp for handle_timeout()'s benfit */
+               list_for_each_entry(req, &osd->o_requests, r_osd_item)
+                       req->r_stamp = jiffies;
+               ret = -EAGAIN;
        } else {
                ceph_con_close(&osd->o_con);
                ceph_con_open(&osd->o_con, &osdc->osdmap->osd_addr[osd->o_osd]);
@@ -633,7 +644,7 @@ static int __send_request(struct ceph_osd_client *osdc,
        reqhead->flags |= cpu_to_le32(req->r_flags);  /* e.g., RETRY */
        reqhead->reassert_version = req->r_reassert_version;
 
-       req->r_sent_stamp = jiffies;
+       req->r_stamp = jiffies;
        list_move_tail(&osdc->req_lru, &req->r_req_lru_item);
 
        ceph_msg_get(req->r_request); /* send consumes a ref */
@@ -660,7 +671,7 @@ static void handle_timeout(struct work_struct *work)
        unsigned long timeout = osdc->client->mount_args->osd_timeout * HZ;
        unsigned long keepalive =
                osdc->client->mount_args->osd_keepalive_timeout * HZ;
-       unsigned long last_sent = 0;
+       unsigned long last_stamp = 0;
        struct rb_node *p;
        struct list_head slow_osds;
 
@@ -697,12 +708,12 @@ static void handle_timeout(struct work_struct *work)
                req = list_entry(osdc->req_lru.next, struct ceph_osd_request,
                                 r_req_lru_item);
 
-               if (time_before(jiffies, req->r_sent_stamp + timeout))
+               if (time_before(jiffies, req->r_stamp + timeout))
                        break;
 
-               BUG_ON(req == last_req && req->r_sent_stamp == last_sent);
+               BUG_ON(req == last_req && req->r_stamp == last_stamp);
                last_req = req;
-               last_sent = req->r_sent_stamp;
+               last_stamp = req->r_stamp;
 
                osd = req->r_osd;
                BUG_ON(!osd);
@@ -718,7 +729,7 @@ static void handle_timeout(struct work_struct *work)
         */
        INIT_LIST_HEAD(&slow_osds);
        list_for_each_entry(req, &osdc->req_lru, r_req_lru_item) {
-               if (time_before(jiffies, req->r_sent_stamp + keepalive))
+               if (time_before(jiffies, req->r_stamp + keepalive))
                        break;
 
                osd = req->r_osd;
@@ -862,7 +873,9 @@ static int __kick_requests(struct ceph_osd_client *osdc,
 
        dout("kick_requests osd%d\n", kickosd ? kickosd->o_osd : -1);
        if (kickosd) {
-               __reset_osd(osdc, kickosd);
+               err = __reset_osd(osdc, kickosd);
+               if (err == -EAGAIN)
+                       return 1;
        } else {
                for (p = rb_first(&osdc->osds); p; p = n) {
                        struct ceph_osd *osd =
@@ -913,7 +926,7 @@ static int __kick_requests(struct ceph_osd_client *osdc,
 
 kick:
                dout("kicking %p tid %llu osd%d\n", req, req->r_tid,
-                    req->r_osd->o_osd);
+                    req->r_osd ? req->r_osd->o_osd : -1);
                req->r_flags |= CEPH_OSD_FLAG_RETRY;
                err = __send_request(osdc, req);
                if (err) {
index 1b1a3ca43afc3ab0a4fab62bbba065603358e62f..b0759911e7c3899b17d3836182b7f4fdbd6a0cdd 100644 (file)
@@ -70,7 +70,7 @@ struct ceph_osd_request {
 
        char              r_oid[40];          /* object name */
        int               r_oid_len;
-       unsigned long     r_sent_stamp;
+       unsigned long     r_stamp;            /* send OR check time */
        bool              r_resend;           /* msg send failed, needs retry */
 
        struct ceph_file_layout r_file_layout;
index b83f2692b835f74164061f6200b8507692884d13..d82fe87c2a6e62f2a825ebb859158306e73a1448 100644 (file)
@@ -480,6 +480,14 @@ static struct ceph_pg_pool_info *__lookup_pg_pool(struct rb_root *root, int id)
        return NULL;
 }
 
+void __decode_pool(void **p, struct ceph_pg_pool_info *pi)
+{
+       ceph_decode_copy(p, &pi->v, sizeof(pi->v));
+       calc_pg_masks(pi);
+       *p += le32_to_cpu(pi->v.num_snaps) * sizeof(u64);
+       *p += le32_to_cpu(pi->v.num_removed_snap_intervals) * sizeof(u64) * 2;
+}
+
 /*
  * decode a full map.
  */
@@ -526,12 +534,8 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
                                   ev, CEPH_PG_POOL_VERSION);
                        goto bad;
                }
-               ceph_decode_copy(p, &pi->v, sizeof(pi->v));
+               __decode_pool(p, pi);
                __insert_pg_pool(&map->pg_pools, pi);
-               calc_pg_masks(pi);
-               *p += le32_to_cpu(pi->v.num_snaps) * sizeof(u64);
-               *p += le32_to_cpu(pi->v.num_removed_snap_intervals)
-                       * sizeof(u64) * 2;
        }
        ceph_decode_32_safe(p, end, map->pool_max, bad);
 
@@ -714,8 +718,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
                        pi->id = pool;
                        __insert_pg_pool(&map->pg_pools, pi);
                }
-               ceph_decode_copy(p, &pi->v, sizeof(pi->v));
-               calc_pg_masks(pi);
+               __decode_pool(p, pi);
        }
 
        /* old_pool */
index bf2a5f3846a4df0e0170362c17f3a0c9ee08fa3d..df04e210a055bf6aa4c041667ca351dbbfc90e2e 100644 (file)
@@ -314,9 +314,9 @@ static int build_snap_context(struct ceph_snap_realm *realm)
           because we rebuild_snap_realms() works _downward_ in
           hierarchy after each update.) */
        if (realm->cached_context &&
-           realm->cached_context->seq <= realm->seq &&
+           realm->cached_context->seq == realm->seq &&
            (!parent ||
-            realm->cached_context->seq <= parent->cached_context->seq)) {
+            realm->cached_context->seq >= parent->cached_context->seq)) {
                dout("build_snap_context %llx %p: %p seq %lld (%d snaps)"
                     " (unchanged)\n",
                     realm->ino, realm, realm->cached_context,
@@ -818,7 +818,9 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                         * queued (again) by ceph_update_snap_trace()
                         * below.  Queue it _now_, under the old context.
                         */
+                       spin_lock(&realm->inodes_with_caps_lock);
                        list_del_init(&ci->i_snap_realm_item);
+                       spin_unlock(&realm->inodes_with_caps_lock);
                        spin_unlock(&inode->i_lock);
 
                        ceph_queue_cap_snap(ci,
index ef9008b885b57b81c757f0e79ddf55d0e520a857..0d0e97ed3ff6029659837f1394a4827506eb1704 100644 (file)
@@ -582,7 +582,9 @@ got:
        inode->i_generation = sbi->s_next_generation++;
        spin_unlock(&sbi->s_next_gen_lock);
 
-       ei->i_state = EXT3_STATE_NEW;
+       ei->i_state_flags = 0;
+       ext3_set_inode_state(inode, EXT3_STATE_NEW);
+
        ei->i_extra_isize =
                (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
                sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
index 7f920b7263a4056612d05fea439c5b7c93c7cfe8..ea33bdf0a3004b927c10be9289b21125dcf53c38 100644 (file)
@@ -2811,7 +2811,7 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino)
        inode->i_mtime.tv_sec = (signed)le32_to_cpu(raw_inode->i_mtime);
        inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0;
 
-       ei->i_state = 0;
+       ei->i_state_flags = 0;
        ei->i_dir_start_lookup = 0;
        ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
        /* We now have enough fields to check if the inode was active or not.
index 361c0b9962a8142b38823e8e9202d0d070c0130b..57f6eef6ccd6c03afbd4c35d0fa364f4e350bbf8 100644 (file)
@@ -263,7 +263,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
                                        ext4_group_t f;
 
                                        f = ext4_flex_group(sbi, block_group);
-                                       atomic_dec(&sbi->s_flex_groups[f].free_inodes);
+                                       atomic_dec(&sbi->s_flex_groups[f].used_dirs);
                                }
 
                        }
@@ -773,7 +773,7 @@ static int ext4_claim_inode(struct super_block *sb,
                if (sbi->s_log_groups_per_flex) {
                        ext4_group_t f = ext4_flex_group(sbi, group);
 
-                       atomic_inc(&sbi->s_flex_groups[f].free_inodes);
+                       atomic_inc(&sbi->s_flex_groups[f].used_dirs);
                }
        }
        gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
index 986120f30066c68b68f7b40906a489cc2870810b..11119e07233b75b481a16d8936f4342d271c4973 100644 (file)
@@ -1035,7 +1035,7 @@ static int ext4_indirect_calc_metadata_amount(struct inode *inode,
                                              sector_t lblock)
 {
        struct ext4_inode_info *ei = EXT4_I(inode);
-       int dind_mask = EXT4_ADDR_PER_BLOCK(inode->i_sb) - 1;
+       sector_t dind_mask = ~((sector_t)EXT4_ADDR_PER_BLOCK(inode->i_sb) - 1);
        int blk_bits;
 
        if (lblock < EXT4_NDIR_BLOCKS)
@@ -1050,7 +1050,7 @@ static int ext4_indirect_calc_metadata_amount(struct inode *inode,
        }
        ei->i_da_metadata_calc_last_lblock = lblock & dind_mask;
        ei->i_da_metadata_calc_len = 1;
-       blk_bits = roundup_pow_of_two(lblock + 1);
+       blk_bits = order_base_2(lblock);
        return (blk_bits / EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb)) + 1;
 }
 
index ba191dae87304e9106940dfe25e8af41573181ca..e14d22c170d542f3d65b7b50065f0256e0c940b3 100644 (file)
@@ -68,7 +68,21 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf);
 static int ext4_unfreeze(struct super_block *sb);
 static void ext4_write_super(struct super_block *sb);
 static int ext4_freeze(struct super_block *sb);
+static int ext4_get_sb(struct file_system_type *fs_type, int flags,
+                      const char *dev_name, void *data, struct vfsmount *mnt);
 
+#if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+static struct file_system_type ext3_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "ext3",
+       .get_sb         = ext4_get_sb,
+       .kill_sb        = kill_block_super,
+       .fs_flags       = FS_REQUIRES_DEV,
+};
+#define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type)
+#else
+#define IS_EXT3_SB(sb) (0)
+#endif
 
 ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
                               struct ext4_group_desc *bg)
@@ -2539,7 +2553,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
         * enable delayed allocation by default
         * Use -o nodelalloc to turn it off
         */
-       set_opt(sbi->s_mount_opt, DELALLOC);
+       if (!IS_EXT3_SB(sb))
+               set_opt(sbi->s_mount_opt, DELALLOC);
 
        if (!parse_options((char *) data, sb, &journal_devnum,
                           &journal_ioprio, NULL, 0))
@@ -4068,7 +4083,7 @@ static int ext4_get_sb(struct file_system_type *fs_type, int flags,
        return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super,mnt);
 }
 
-#if !defined(CONTIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
 static struct file_system_type ext2_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "ext2",
@@ -4095,15 +4110,7 @@ static inline void register_as_ext2(void) { }
 static inline void unregister_as_ext2(void) { }
 #endif
 
-#if !defined(CONTIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
-static struct file_system_type ext3_fs_type = {
-       .owner          = THIS_MODULE,
-       .name           = "ext3",
-       .get_sb         = ext4_get_sb,
-       .kill_sb        = kill_block_super,
-       .fs_flags       = FS_REQUIRES_DEV,
-};
-
+#if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
 static inline void register_as_ext3(void)
 {
        int err = register_filesystem(&ext3_fs_type);
index c1ef50154868efd0ce58c3ddca97c04e1a7f1371..6fcc7e71fbaaf0c8f1d21b3cf50fab86d67f50ee 100644 (file)
@@ -309,7 +309,7 @@ static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
 {
        struct fat_mount_options *opts = &MSDOS_SB(dir->i_sb)->options;
        wchar_t *ip, *ext_start, *end, *name_start;
-       unsigned char base[9], ext[4], buf[8], *p;
+       unsigned char base[9], ext[4], buf[5], *p;
        unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
        int chl, chi;
        int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen;
@@ -467,7 +467,7 @@ static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
                        return 0;
        }
 
-       i = jiffies & 0xffff;
+       i = jiffies;
        sz = (jiffies >> 16) & 0x7;
        if (baselen > 2) {
                baselen = numtail2_baselen;
@@ -476,7 +476,7 @@ static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
        name_res[baselen + 4] = '~';
        name_res[baselen + 5] = '1' + sz;
        while (1) {
-               sprintf(buf, "%04X", i);
+               snprintf(buf, sizeof(buf), "%04X", i & 0xffff);
                memcpy(&name_res[baselen], buf, 4);
                if (vfat_find_form(dir, name_res) < 0)
                        break;
index e513ac599c8e9b587c8646e33485be20d2ce1c4e..0b589a9b4ffcf623b9b1544cff596ee24b52cbb0 100644 (file)
@@ -53,7 +53,7 @@ const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5] = {
 static void fscache_object_slow_work_put_ref(struct slow_work *);
 static int  fscache_object_slow_work_get_ref(struct slow_work *);
 static void fscache_object_slow_work_execute(struct slow_work *);
-#ifdef CONFIG_SLOW_WORK_PROC
+#ifdef CONFIG_SLOW_WORK_DEBUG
 static void fscache_object_slow_work_desc(struct slow_work *, struct seq_file *);
 #endif
 static void fscache_initialise_object(struct fscache_object *);
@@ -69,7 +69,7 @@ const struct slow_work_ops fscache_object_slow_work_ops = {
        .get_ref        = fscache_object_slow_work_get_ref,
        .put_ref        = fscache_object_slow_work_put_ref,
        .execute        = fscache_object_slow_work_execute,
-#ifdef CONFIG_SLOW_WORK_PROC
+#ifdef CONFIG_SLOW_WORK_DEBUG
        .desc           = fscache_object_slow_work_desc,
 #endif
 };
@@ -364,7 +364,7 @@ static void fscache_object_slow_work_execute(struct slow_work *work)
 /*
  * describe an object for slow-work debugging
  */
-#ifdef CONFIG_SLOW_WORK_PROC
+#ifdef CONFIG_SLOW_WORK_DEBUG
 static void fscache_object_slow_work_desc(struct slow_work *work,
                                          struct seq_file *m)
 {
index 313e79a14266e69e2a47aafdffefc89b29f510df..9f6c928d45861d6bc807aff4aa81541a3a2b316f 100644 (file)
@@ -500,7 +500,7 @@ static void fscache_op_execute(struct slow_work *work)
 /*
  * describe an operation for slow-work debugging
  */
-#ifdef CONFIG_SLOW_WORK_PROC
+#ifdef CONFIG_SLOW_WORK_DEBUG
 static void fscache_op_desc(struct slow_work *work, struct seq_file *m)
 {
        struct fscache_operation *op =
@@ -517,7 +517,7 @@ const struct slow_work_ops fscache_op_slow_work_ops = {
        .get_ref        = fscache_op_get_ref,
        .put_ref        = fscache_op_put_ref,
        .execute        = fscache_op_execute,
-#ifdef CONFIG_SLOW_WORK_PROC
+#ifdef CONFIG_SLOW_WORK_DEBUG
        .desc           = fscache_op_desc,
 #endif
 };
index c598ea4c4e7d580d9046e1cb8ccb42e1d14db6c6..69809024d71d951d9fbac1ee951dfefc83a299b2 100644 (file)
@@ -881,6 +881,7 @@ submit_failed:
        goto nobufs;
 
 nobufs_unlock_obj:
+       spin_unlock(&cookie->stores_lock);
        spin_unlock(&object->lock);
 nobufs:
        spin_unlock(&cookie->lock);
index 9718c22f186d04ff309614dbeee6337a8d5ec185..a5d0c56d3ebc925b44d8d6a3a1bf0e8765d603ad 100644 (file)
@@ -80,6 +80,7 @@ static void writeseg_end_io(struct bio *bio, int err)
                        prefetchw(&bvec->bv_page->flags);
 
                end_page_writeback(page);
+               page_cache_release(page);
        } while (bvec >= bio->bi_io_vec);
        bio_put(bio);
        if (atomic_dec_and_test(&super->s_pending_writes))
@@ -97,8 +98,10 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
        unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
        int i;
 
+       if (max_pages > BIO_MAX_PAGES)
+               max_pages = BIO_MAX_PAGES;
        bio = bio_alloc(GFP_NOFS, max_pages);
-       BUG_ON(!bio); /* FIXME: handle this */
+       BUG_ON(!bio);
 
        for (i = 0; i < nr_pages; i++) {
                if (i >= max_pages) {
@@ -191,8 +194,10 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
        unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
        int i;
 
+       if (max_pages > BIO_MAX_PAGES)
+               max_pages = BIO_MAX_PAGES;
        bio = bio_alloc(GFP_NOFS, max_pages);
-       BUG_ON(!bio); /* FIXME: handle this */
+       BUG_ON(!bio);
 
        for (i = 0; i < nr_pages; i++) {
                if (i >= max_pages) {
index 56a8bfbb012041be7279216ff334831ea911edbe..c76b4b5c7ff6fa79aca003b3975568ad82b44dd8 100644 (file)
@@ -303,12 +303,12 @@ static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir)
                                (filler_t *)logfs_readpage, NULL);
                if (IS_ERR(page))
                        return PTR_ERR(page);
-               dd = kmap_atomic(page, KM_USER0);
+               dd = kmap(page);
                BUG_ON(dd->namelen == 0);
 
                full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen),
                                pos, be64_to_cpu(dd->ino), dd->type);
-               kunmap_atomic(dd, KM_USER0);
+               kunmap(page);
                page_cache_release(page);
                if (full)
                        break;
index 6ad30a4c9052179b4fe56da98a81f381b7a531a7..d57c7b07b60bd101849bafa36bbb387bfd30d877 100644 (file)
@@ -800,6 +800,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
 {
        struct logfs_super *super = logfs_super(sb);
        struct logfs_area *area = super->s_journal_area;
+       struct btree_head32 *head = &super->s_reserved_segments;
        u32 segno, ec;
        int i, err;
 
@@ -807,6 +808,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
        /* Drop old segments */
        journal_for_each(i)
                if (super->s_journal_seg[i]) {
+                       btree_remove32(head, super->s_journal_seg[i]);
                        logfs_set_segment_unreserved(sb,
                                        super->s_journal_seg[i],
                                        super->s_journal_ec[i]);
@@ -819,8 +821,13 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
                super->s_journal_seg[i] = segno;
                super->s_journal_ec[i] = ec;
                logfs_set_segment_reserved(sb, segno);
+               err = btree_insert32(head, segno, (void *)1, GFP_KERNEL);
+               BUG_ON(err); /* mempool should prevent this */
+               err = logfs_erase_segment(sb, segno, 1);
+               BUG_ON(err); /* FIXME: remount-ro would be nicer */
        }
        /* Manually move journal_area */
+       freeseg(sb, area->a_segno);
        area->a_segno = super->s_journal_seg[0];
        area->a_is_open = 0;
        area->a_used_bytes = 0;
index 129779431373adfbf5f674b48e26913f80986f19..b84b0eec6024d87b17079229e249668f07418400 100644 (file)
@@ -587,6 +587,7 @@ void move_page_to_btree(struct page *page);
 int logfs_init_mapping(struct super_block *sb);
 void logfs_sync_area(struct logfs_area *area);
 void logfs_sync_segments(struct super_block *sb);
+void freeseg(struct super_block *sb, u32 segno);
 
 /* area handling */
 int logfs_init_areas(struct super_block *sb);
index 7a23b3e7c0a798c3b750d96f08cf1351950cefde..c3a3a6814b8412600e7e4fdd54611edc71c84de9 100644 (file)
@@ -1594,7 +1594,6 @@ int logfs_delete(struct inode *inode, pgoff_t index,
        return ret;
 }
 
-/* Rewrite cannot mark the inode dirty but has to write it immediatly. */
 int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
                gc_level_t gc_level, long flags)
 {
@@ -1611,6 +1610,18 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
                if (level != 0)
                        alloc_indirect_block(inode, page, 0);
                err = logfs_write_buf(inode, page, flags);
+               if (!err && shrink_level(gc_level) == 0) {
+                       /* Rewrite cannot mark the inode dirty but has to
+                        * write it immediatly.
+                        * Q: Can't we just create an alias for the inode
+                        * instead?  And if not, why not?
+                        */
+                       if (inode->i_ino == LOGFS_INO_MASTER)
+                               logfs_write_anchor(inode->i_sb);
+                       else {
+                               err = __logfs_write_inode(inode, flags);
+                       }
+               }
        }
        logfs_put_write_page(page);
        return err;
index 1a14f9910d55ef94a46c64ba910caa1d92bbfdec..0ecd8f07c11e466b531d002fd8d2aa0900983098 100644 (file)
@@ -93,49 +93,57 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
        } while (len);
 }
 
-/*
- * bdev_writeseg will write full pages.  Memset the tail to prevent data leaks.
- */
-static void pad_wbuf(struct logfs_area *area, int final)
+static void pad_partial_page(struct logfs_area *area)
 {
        struct super_block *sb = area->a_sb;
-       struct logfs_super *super = logfs_super(sb);
        struct page *page;
        u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes);
        pgoff_t index = ofs >> PAGE_SHIFT;
        long offset = ofs & (PAGE_SIZE-1);
        u32 len = PAGE_SIZE - offset;
 
-       if (len == PAGE_SIZE) {
-               /* The math in this function can surely use some love */
-               len = 0;
-       }
-       if (len) {
-               BUG_ON(area->a_used_bytes >= super->s_segsize);
-
-               page = get_mapping_page(area->a_sb, index, 0);
+       if (len % PAGE_SIZE) {
+               page = get_mapping_page(sb, index, 0);
                BUG_ON(!page); /* FIXME: reserve a pool */
                memset(page_address(page) + offset, 0xff, len);
                SetPagePrivate(page);
                page_cache_release(page);
        }
+}
 
-       if (!final)
-               return;
+static void pad_full_pages(struct logfs_area *area)
+{
+       struct super_block *sb = area->a_sb;
+       struct logfs_super *super = logfs_super(sb);
+       u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes);
+       u32 len = super->s_segsize - area->a_used_bytes;
+       pgoff_t index = PAGE_CACHE_ALIGN(ofs) >> PAGE_CACHE_SHIFT;
+       pgoff_t no_indizes = len >> PAGE_CACHE_SHIFT;
+       struct page *page;
 
-       area->a_used_bytes += len;
-       for ( ; area->a_used_bytes < super->s_segsize;
-                       area->a_used_bytes += PAGE_SIZE) {
-               /* Memset another page */
-               index++;
-               page = get_mapping_page(area->a_sb, index, 0);
+       while (no_indizes) {
+               page = get_mapping_page(sb, index, 0);
                BUG_ON(!page); /* FIXME: reserve a pool */
-               memset(page_address(page), 0xff, PAGE_SIZE);
+               SetPageUptodate(page);
+               memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
                SetPagePrivate(page);
                page_cache_release(page);
+               index++;
+               no_indizes--;
        }
 }
 
+/*
+ * bdev_writeseg will write full pages.  Memset the tail to prevent data leaks.
+ * Also make sure we allocate (and memset) all pages for final writeout.
+ */
+static void pad_wbuf(struct logfs_area *area, int final)
+{
+       pad_partial_page(area);
+       if (final)
+               pad_full_pages(area);
+}
+
 /*
  * We have to be careful with the alias tree.  Since lookup is done by bix,
  * it needs to be normalized, so 14, 15, 16, etc. all match when dealing with
@@ -683,7 +691,7 @@ int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow)
        return 0;
 }
 
-static void freeseg(struct super_block *sb, u32 segno)
+void freeseg(struct super_block *sb, u32 segno)
 {
        struct logfs_super *super = logfs_super(sb);
        struct address_space *mapping = super->s_mapping_inode->i_mapping;
index c66beab78deedb5efd8fa5d7dfb27a7f4d78b95b..9d856c49afc5b7ba93618039fe5fa2ec9a3492ff 100644 (file)
@@ -277,7 +277,7 @@ static int logfs_recover_sb(struct super_block *sb)
        }
        if (valid0 && valid1 && ds_cmp(ds0, ds1)) {
                printk(KERN_INFO"Superblocks don't match - fixing.\n");
-               return write_one_sb(sb, super->s_devops->find_last_sb);
+               return logfs_write_sb(sb);
        }
        /* If neither is valid now, something's wrong.  Didn't we properly
         * check them before?!? */
@@ -289,6 +289,10 @@ static int logfs_make_writeable(struct super_block *sb)
 {
        int err;
 
+       err = logfs_open_segfile(sb);
+       if (err)
+               return err;
+
        /* Repair any broken superblock copies */
        err = logfs_recover_sb(sb);
        if (err)
@@ -299,10 +303,6 @@ static int logfs_make_writeable(struct super_block *sb)
        if (err)
                return err;
 
-       err = logfs_open_segfile(sb);
-       if (err)
-               return err;
-
        /* Do one GC pass before any data gets dirtied */
        logfs_gc_pass(sb);
 
@@ -328,7 +328,7 @@ static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt)
 
        sb->s_root = d_alloc_root(rootdir);
        if (!sb->s_root)
-               goto fail;
+               goto fail2;
 
        super->s_erase_page = alloc_pages(GFP_KERNEL, 0);
        if (!super->s_erase_page)
@@ -572,8 +572,7 @@ int logfs_get_sb_device(struct file_system_type *type, int flags,
        return 0;
 
 err1:
-       up_write(&sb->s_umount);
-       deactivate_super(sb);
+       deactivate_locked_super(sb);
        return err;
 err0:
        kfree(super);
index 1c0fca6e899eef7aa768ed704e2216c3d024c7df..a7dce91a7e4244c3dab9bbb10644fd31ec371bee 100644 (file)
@@ -1610,8 +1610,7 @@ exit:
 
 static struct file *do_last(struct nameidata *nd, struct path *path,
                            int open_flag, int acc_mode,
-                           int mode, const char *pathname,
-                           int *want_dir)
+                           int mode, const char *pathname)
 {
        struct dentry *dir = nd->path.dentry;
        struct file *filp;
@@ -1642,7 +1641,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
        if (nd->last.name[nd->last.len]) {
                if (open_flag & O_CREAT)
                        goto exit;
-               *want_dir = 1;
+               nd->flags |= LOOKUP_DIRECTORY;
        }
 
        /* just plain open? */
@@ -1656,8 +1655,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
                if (path->dentry->d_inode->i_op->follow_link)
                        return NULL;
                error = -ENOTDIR;
-               if (*want_dir && !path->dentry->d_inode->i_op->lookup)
-                       goto exit_dput;
+               if (nd->flags & LOOKUP_DIRECTORY) {
+                       if (!path->dentry->d_inode->i_op->lookup)
+                               goto exit_dput;
+               }
                path_to_nameidata(path, nd);
                audit_inode(pathname, nd->path.dentry);
                goto ok;
@@ -1766,7 +1767,6 @@ struct file *do_filp_open(int dfd, const char *pathname,
        int count = 0;
        int flag = open_to_namei_flags(open_flag);
        int force_reval = 0;
-       int want_dir = open_flag & O_DIRECTORY;
 
        if (!(open_flag & O_CREAT))
                mode = 0;
@@ -1828,7 +1828,9 @@ reval:
                if (open_flag & O_EXCL)
                        nd.flags |= LOOKUP_EXCL;
        }
-       filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname, &want_dir);
+       if (open_flag & O_DIRECTORY)
+               nd.flags |= LOOKUP_DIRECTORY;
+       filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
        while (unlikely(!filp)) { /* trailing symlink */
                struct path holder;
                struct inode *inode = path.dentry->d_inode;
@@ -1866,7 +1868,7 @@ reval:
                }
                holder = path;
                nd.flags &= ~LOOKUP_PARENT;
-               filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname, &want_dir);
+               filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
                if (inode->i_op->put_link)
                        inode->i_op->put_link(holder.dentry, &nd, cookie);
                path_put(&holder);
index ae8d02294e462283eb2c421048dc381c8d87bf36..ae0d92736531c4da6ffaa0e8ac33a85287f2b36f 100644 (file)
@@ -491,7 +491,8 @@ static int nfs_release_page(struct page *page, gfp_t gfp)
 {
        dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
 
-       if (gfp & __GFP_WAIT)
+       /* Only do I/O if gfp is a superset of GFP_KERNEL */
+       if ((gfp & GFP_KERNEL) == GFP_KERNEL)
                nfs_wb_page(page->mapping->host, page);
        /* If PagePrivate() is set, then the page is not freeable */
        if (PagePrivate(page))
index 4d338be492cb28f6e91ae9eecfe30af64555154d..dd17713413a5019d6a61d712447d91b02e7db81d 100644 (file)
@@ -5552,6 +5552,8 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nf
        if (status != 0)
                goto out;
        status = decode_delegreturn(&xdr);
+       if (status != 0)
+               goto out;
        decode_getfattr(&xdr, res->fattr, res->server,
                        !RPC_IS_ASYNC(rqstp->rq_task));
 out:
index 636eaafd6ea257c7bfaf53dc7b7ce8399f81a103..6129a431aa3401b3f637fd6354925373c7c45a01 100644 (file)
@@ -323,14 +323,14 @@ int nilfs_write_logs(struct list_head *logs, struct the_nilfs *nilfs)
 int nilfs_wait_on_logs(struct list_head *logs)
 {
        struct nilfs_segment_buffer *segbuf;
-       int err;
+       int err, ret = 0;
 
        list_for_each_entry(segbuf, logs, sb_list) {
                err = nilfs_segbuf_wait(segbuf);
-               if (err)
-                       return err;
+               if (err && !ret)
+                       ret = err;
        }
-       return 0;
+       return ret;
 }
 
 /*
index 69576a95e13f918b340c51b1ffdc701d1053fc2f..c161d89061b5fb506a13529b79abd2d184944d24 100644 (file)
@@ -1510,6 +1510,12 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
                if (mode != SC_LSEG_SR || sci->sc_stage.scnt < NILFS_ST_CPFILE)
                        break;
 
+               nilfs_clear_logs(&sci->sc_segbufs);
+
+               err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
+               if (unlikely(err))
+                       return err;
+
                if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
                        err = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
                                                        sci->sc_freesegs,
@@ -1517,12 +1523,6 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
                                                        NULL);
                        WARN_ON(err); /* do not happen */
                }
-               nilfs_clear_logs(&sci->sc_segbufs);
-
-               err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
-               if (unlikely(err))
-                       return err;
-
                nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA);
                sci->sc_stage = prev_stage;
        }
@@ -1897,8 +1897,7 @@ static void nilfs_segctor_abort_construction(struct nilfs_sc_info *sci,
 
        list_splice_tail_init(&sci->sc_write_logs, &logs);
        ret = nilfs_wait_on_logs(&logs);
-       if (ret)
-               nilfs_abort_logs(&logs, NULL, sci->sc_super_root, ret);
+       nilfs_abort_logs(&logs, NULL, sci->sc_super_root, ret ? : err);
 
        list_splice_tail_init(&sci->sc_segbufs, &logs);
        nilfs_cancel_segusage(&logs, nilfs->ns_sufile);
index 0501974bedd0d3b96764b48b5725054fbe7ca412..8ccf0f8c9cc8d6c0f16809cdc45a47a2f95832d7 100644 (file)
@@ -30,6 +30,8 @@
 #include "alloc.h"
 #include "dlmglue.h"
 #include "file.h"
+#include "inode.h"
+#include "journal.h"
 #include "ocfs2_fs.h"
 
 #include "xattr.h"
@@ -165,6 +167,60 @@ static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type)
        return acl;
 }
 
+/*
+ * Helper function to set i_mode in memory and disk. Some call paths
+ * will not have di_bh or a journal handle to pass, in which case it
+ * will create it's own.
+ */
+static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh,
+                             handle_t *handle, umode_t new_mode)
+{
+       int ret, commit_handle = 0;
+       struct ocfs2_dinode *di;
+
+       if (di_bh == NULL) {
+               ret = ocfs2_read_inode_block(inode, &di_bh);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       } else
+               get_bh(di_bh);
+
+       if (handle == NULL) {
+               handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb),
+                                          OCFS2_INODE_UPDATE_CREDITS);
+               if (IS_ERR(handle)) {
+                       ret = PTR_ERR(handle);
+                       mlog_errno(ret);
+                       goto out_brelse;
+               }
+
+               commit_handle = 1;
+       }
+
+       di = (struct ocfs2_dinode *)di_bh->b_data;
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       inode->i_mode = new_mode;
+       di->i_mode = cpu_to_le16(inode->i_mode);
+
+       ocfs2_journal_dirty(handle, di_bh);
+
+out_commit:
+       if (commit_handle)
+               ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+out_brelse:
+       brelse(di_bh);
+out:
+       return ret;
+}
+
 /*
  * Set the access or default ACL of an inode.
  */
@@ -193,9 +249,14 @@ static int ocfs2_set_acl(handle_t *handle,
                        if (ret < 0)
                                return ret;
                        else {
-                               inode->i_mode = mode;
                                if (ret == 0)
                                        acl = NULL;
+
+                               ret = ocfs2_acl_set_mode(inode, di_bh,
+                                                        handle, mode);
+                               if (ret)
+                                       return ret;
+
                        }
                }
                break;
@@ -283,6 +344,7 @@ int ocfs2_init_acl(handle_t *handle,
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct posix_acl *acl = NULL;
        int ret = 0;
+       mode_t mode;
 
        if (!S_ISLNK(inode->i_mode)) {
                if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
@@ -291,12 +353,17 @@ int ocfs2_init_acl(handle_t *handle,
                        if (IS_ERR(acl))
                                return PTR_ERR(acl);
                }
-               if (!acl)
-                       inode->i_mode &= ~current_umask();
+               if (!acl) {
+                       mode = inode->i_mode & ~current_umask();
+                       ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
+                       if (ret) {
+                               mlog_errno(ret);
+                               goto cleanup;
+                       }
+               }
        }
        if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
                struct posix_acl *clone;
-               mode_t mode;
 
                if (S_ISDIR(inode->i_mode)) {
                        ret = ocfs2_set_acl(handle, inode, di_bh,
@@ -313,7 +380,7 @@ int ocfs2_init_acl(handle_t *handle,
                mode = inode->i_mode;
                ret = posix_acl_create_masq(clone, &mode);
                if (ret >= 0) {
-                       inode->i_mode = mode;
+                       ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
                        if (ret > 0) {
                                ret = ocfs2_set_acl(handle, inode,
                                                    di_bh, ACL_TYPE_ACCESS,
index a659606dcb9592f1d0c719ed7167b1fe158296f2..9289b4357d27dcf0559a5b6f438e0ca4205e359b 100644 (file)
@@ -1875,7 +1875,6 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
 ok:
                spin_unlock(&res->spinlock);
        }
-       spin_unlock(&dlm->spinlock);
 
        // mlog(0, "woo!  got an assert_master from node %u!\n",
        //           assert->node_idx);
@@ -1926,7 +1925,6 @@ ok:
                /* master is known, detach if not already detached.
                 * ensures that only one assert_master call will happen
                 * on this mle. */
-               spin_lock(&dlm->spinlock);
                spin_lock(&dlm->master_lock);
 
                rr = atomic_read(&mle->mle_refs.refcount);
@@ -1959,7 +1957,6 @@ ok:
                        __dlm_put_mle(mle);
                }
                spin_unlock(&dlm->master_lock);
-               spin_unlock(&dlm->spinlock);
        } else if (res) {
                if (res->owner != assert->node_idx) {
                        mlog(0, "assert_master from %u, but current "
@@ -1967,6 +1964,7 @@ ok:
                             res->owner, namelen, name);
                }
        }
+       spin_unlock(&dlm->spinlock);
 
 done:
        ret = 0;
index 278a223aae14b8a2d347890735c729567e3840cc..ab207901d32a28e2423019007e10da4ed5eb2a0f 100644 (file)
@@ -891,6 +891,21 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
        /* Do some basic inode verification... */
        di = (struct ocfs2_dinode *) di_bh->b_data;
        if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL))) {
+               /*
+                * Inodes in the orphan dir must have ORPHANED_FL.  The only
+                * inodes that come back out of the orphan dir are reflink
+                * targets. A reflink target may be moved out of the orphan
+                * dir between the time we scan the directory and the time we
+                * process it. This would lead to HAS_REFCOUNT_FL being set but
+                * ORPHANED_FL not.
+                */
+               if (di->i_dyn_features & cpu_to_le16(OCFS2_HAS_REFCOUNT_FL)) {
+                       mlog(0, "Reflinked inode %llu is no longer orphaned.  "
+                            "it shouldn't be deleted\n",
+                            (unsigned long long)oi->ip_blkno);
+                       goto bail;
+               }
+
                /* for lack of a better error? */
                status = -EEXIST;
                mlog(ML_ERROR,
index ca992d91f5110e9a376ca4a0f71a5101f4294e29..c983715d8d8c3d7d734ade4ae339f39439d82aa0 100644 (file)
@@ -872,8 +872,10 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
                             (unsigned long long)la_start_blk,
                             (unsigned long long)blkno);
 
-                       status = ocfs2_free_clusters(handle, main_bm_inode,
-                                                    main_bm_bh, blkno, count);
+                       status = ocfs2_release_clusters(handle,
+                                                       main_bm_inode,
+                                                       main_bm_bh, blkno,
+                                                       count);
                        if (status < 0) {
                                mlog_errno(status);
                                goto bail;
@@ -984,8 +986,7 @@ static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
        }
 
 retry_enospc:
-       (*ac)->ac_bits_wanted = osb->local_alloc_bits;
-
+       (*ac)->ac_bits_wanted = osb->local_alloc_default_bits;
        status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);
        if (status == -ENOSPC) {
                if (ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_ENOSPC) ==
@@ -1061,6 +1062,7 @@ retry_enospc:
                    OCFS2_LA_DISABLED)
                        goto bail;
 
+               ac->ac_bits_wanted = osb->local_alloc_default_bits;
                status = ocfs2_claim_clusters(osb, handle, ac,
                                              osb->local_alloc_bits,
                                              &cluster_off,
index 544ac6245175f26c23249cf916c5001ae8f5d067..b5cb3ede9408944d99abc7c7c3b28c01b1ddadeb 100644 (file)
@@ -133,7 +133,7 @@ int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl)
 
        if (!(fl->fl_flags & FL_POSIX))
                return -ENOLCK;
-       if (__mandatory_lock(inode))
+       if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
                return -ENOLCK;
 
        return ocfs2_plock(osb->cconn, OCFS2_I(inode)->ip_blkno, file, cmd, fl);
index d9cd4e373a5309e24602b5dab9899f208a756523..b1eb50ae40979a6451cbc5db003313a013868d54 100644 (file)
@@ -84,7 +84,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
 static int ocfs2_orphan_add(struct ocfs2_super *osb,
                            handle_t *handle,
                            struct inode *inode,
-                           struct ocfs2_dinode *fe,
+                           struct buffer_head *fe_bh,
                            char *name,
                            struct ocfs2_dir_lookup_result *lookup,
                            struct inode *orphan_dir_inode);
@@ -879,7 +879,7 @@ static int ocfs2_unlink(struct inode *dir,
        fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
        if (inode_is_unlinkable(inode)) {
-               status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name,
+               status = ocfs2_orphan_add(osb, handle, inode, fe_bh, orphan_name,
                                          &orphan_insert, orphan_dir);
                if (status < 0) {
                        mlog_errno(status);
@@ -1300,7 +1300,7 @@ static int ocfs2_rename(struct inode *old_dir,
                if (S_ISDIR(new_inode->i_mode) ||
                    (ocfs2_read_links_count(newfe) == 1)) {
                        status = ocfs2_orphan_add(osb, handle, new_inode,
-                                                 newfe, orphan_name,
+                                                 newfe_bh, orphan_name,
                                                  &orphan_insert, orphan_dir);
                        if (status < 0) {
                                mlog_errno(status);
@@ -1911,7 +1911,7 @@ leave:
 static int ocfs2_orphan_add(struct ocfs2_super *osb,
                            handle_t *handle,
                            struct inode *inode,
-                           struct ocfs2_dinode *fe,
+                           struct buffer_head *fe_bh,
                            char *name,
                            struct ocfs2_dir_lookup_result *lookup,
                            struct inode *orphan_dir_inode)
@@ -1919,6 +1919,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
        struct buffer_head *orphan_dir_bh = NULL;
        int status = 0;
        struct ocfs2_dinode *orphan_fe;
+       struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
        mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
 
@@ -1959,6 +1960,21 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
                goto leave;
        }
 
+       /*
+        * We're going to journal the change of i_flags and i_orphaned_slot.
+        * It's safe anyway, though some callers may duplicate the journaling.
+        * Journaling within the func just make the logic look more
+        * straightforward.
+        */
+       status = ocfs2_journal_access_di(handle,
+                                        INODE_CACHE(inode),
+                                        fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
        le32_add_cpu(&fe->i_flags, OCFS2_ORPHANED_FL);
 
        /* Record which orphan dir our inode now resides
@@ -1966,6 +1982,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
         * dir to lock. */
        fe->i_orphaned_slot = cpu_to_le16(osb->slot_num);
 
+       ocfs2_journal_dirty(handle, fe_bh);
+
        mlog(0, "Inode %llu orphaned in slot %d\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num);
 
@@ -2123,7 +2141,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
        }
 
        di = (struct ocfs2_dinode *)new_di_bh->b_data;
-       status = ocfs2_orphan_add(osb, handle, inode, di, orphan_name,
+       status = ocfs2_orphan_add(osb, handle, inode, new_di_bh, orphan_name,
                                  &orphan_insert, orphan_dir);
        if (status < 0) {
                mlog_errno(status);
index 1238b491db90d5635059f07a44178b8a7e9a1571..adf5e2ebc2c436b60992dfc39ae506327aaf9054 100644 (file)
@@ -763,8 +763,18 @@ static inline unsigned int ocfs2_megabytes_to_clusters(struct super_block *sb,
        return megs << (20 - OCFS2_SB(sb)->s_clustersize_bits);
 }
 
-#define ocfs2_set_bit ext2_set_bit
-#define ocfs2_clear_bit ext2_clear_bit
+static inline void _ocfs2_set_bit(unsigned int bit, unsigned long *bitmap)
+{
+       ext2_set_bit(bit, bitmap);
+}
+#define ocfs2_set_bit(bit, addr) _ocfs2_set_bit((bit), (unsigned long *)(addr))
+
+static inline void _ocfs2_clear_bit(unsigned int bit, unsigned long *bitmap)
+{
+       ext2_clear_bit(bit, bitmap);
+}
+#define ocfs2_clear_bit(bit, addr) _ocfs2_clear_bit((bit), (unsigned long *)(addr))
+
 #define ocfs2_test_bit ext2_test_bit
 #define ocfs2_find_next_zero_bit ext2_find_next_zero_bit
 #define ocfs2_find_next_bit ext2_find_next_bit
index 9e96921dffda4f9f9b32970c142bacc59984802a..29405f2ff616e6c32ba3488ade4296deec1d5b94 100644 (file)
@@ -4075,6 +4075,7 @@ static int ocfs2_complete_reflink(struct inode *s_inode,
        OCFS2_I(t_inode)->ip_dyn_features = OCFS2_I(s_inode)->ip_dyn_features;
        spin_unlock(&OCFS2_I(t_inode)->ip_lock);
        i_size_write(t_inode, size);
+       t_inode->i_blocks = s_inode->i_blocks;
 
        di->i_xattr_inline_size = s_di->i_xattr_inline_size;
        di->i_clusters = s_di->i_clusters;
index c3c60bc3e0729a5fb55f99254dc5babd150ae6ff..19ba00f28547bcf0d31fc8bc69ed34c340660c85 100644 (file)
@@ -95,13 +95,6 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
                                             struct buffer_head *group_bh,
                                             unsigned int bit_off,
                                             unsigned int num_bits);
-static inline int ocfs2_block_group_clear_bits(handle_t *handle,
-                                              struct inode *alloc_inode,
-                                              struct ocfs2_group_desc *bg,
-                                              struct buffer_head *group_bh,
-                                              unsigned int bit_off,
-                                              unsigned int num_bits);
-
 static int ocfs2_relink_block_group(handle_t *handle,
                                    struct inode *alloc_inode,
                                    struct buffer_head *fe_bh,
@@ -152,7 +145,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
 
 #define do_error(fmt, ...)                                             \
        do{                                                             \
-               if (clean_error)                                        \
+               if (resize)                                     \
                        mlog(ML_ERROR, fmt "\n", ##__VA_ARGS__);        \
                else                                                    \
                        ocfs2_error(sb, fmt, ##__VA_ARGS__);            \
@@ -160,7 +153,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
 
 static int ocfs2_validate_gd_self(struct super_block *sb,
                                  struct buffer_head *bh,
-                                 int clean_error)
+                                 int resize)
 {
        struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
 
@@ -211,7 +204,7 @@ static int ocfs2_validate_gd_self(struct super_block *sb,
 static int ocfs2_validate_gd_parent(struct super_block *sb,
                                    struct ocfs2_dinode *di,
                                    struct buffer_head *bh,
-                                   int clean_error)
+                                   int resize)
 {
        unsigned int max_bits;
        struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
@@ -233,8 +226,11 @@ static int ocfs2_validate_gd_parent(struct super_block *sb,
                return -EINVAL;
        }
 
-       if (le16_to_cpu(gd->bg_chain) >=
-           le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) {
+       /* In resize, we may meet the case bg_chain == cl_next_free_rec. */
+       if ((le16_to_cpu(gd->bg_chain) >
+            le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) ||
+           ((le16_to_cpu(gd->bg_chain) ==
+            le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) && !resize)) {
                do_error("Group descriptor #%llu has bad chain %u",
                         (unsigned long long)bh->b_blocknr,
                         le16_to_cpu(gd->bg_chain));
@@ -1975,18 +1971,18 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
                                      bits_wanted, cluster_start, num_clusters);
 }
 
-static inline int ocfs2_block_group_clear_bits(handle_t *handle,
-                                              struct inode *alloc_inode,
-                                              struct ocfs2_group_desc *bg,
-                                              struct buffer_head *group_bh,
-                                              unsigned int bit_off,
-                                              unsigned int num_bits)
+static int ocfs2_block_group_clear_bits(handle_t *handle,
+                                       struct inode *alloc_inode,
+                                       struct ocfs2_group_desc *bg,
+                                       struct buffer_head *group_bh,
+                                       unsigned int bit_off,
+                                       unsigned int num_bits,
+                                       void (*undo_fn)(unsigned int bit,
+                                                       unsigned long *bmap))
 {
        int status;
        unsigned int tmp;
-       int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;
        struct ocfs2_group_desc *undo_bg = NULL;
-       int cluster_bitmap = 0;
 
        mlog_entry_void();
 
@@ -1996,20 +1992,18 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle,
 
        mlog(0, "off = %u, num = %u\n", bit_off, num_bits);
 
-       if (ocfs2_is_cluster_bitmap(alloc_inode))
-               journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
-
+       BUG_ON(undo_fn && !ocfs2_is_cluster_bitmap(alloc_inode));
        status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode),
-                                        group_bh, journal_type);
+                                        group_bh,
+                                        undo_fn ?
+                                        OCFS2_JOURNAL_ACCESS_UNDO :
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
 
-       if (ocfs2_is_cluster_bitmap(alloc_inode))
-               cluster_bitmap = 1;
-
-       if (cluster_bitmap) {
+       if (undo_fn) {
                jbd_lock_bh_state(group_bh);
                undo_bg = (struct ocfs2_group_desc *)
                                        bh2jh(group_bh)->b_committed_data;
@@ -2020,13 +2014,13 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle,
        while(tmp--) {
                ocfs2_clear_bit((bit_off + tmp),
                                (unsigned long *) bg->bg_bitmap);
-               if (cluster_bitmap)
-                       ocfs2_set_bit(bit_off + tmp,
-                                     (unsigned long *) undo_bg->bg_bitmap);
+               if (undo_fn)
+                       undo_fn(bit_off + tmp,
+                               (unsigned long *) undo_bg->bg_bitmap);
        }
        le16_add_cpu(&bg->bg_free_bits_count, num_bits);
 
-       if (cluster_bitmap)
+       if (undo_fn)
                jbd_unlock_bh_state(group_bh);
 
        status = ocfs2_journal_dirty(handle, group_bh);
@@ -2039,12 +2033,14 @@ bail:
 /*
  * expects the suballoc inode to already be locked.
  */
-int ocfs2_free_suballoc_bits(handle_t *handle,
-                            struct inode *alloc_inode,
-                            struct buffer_head *alloc_bh,
-                            unsigned int start_bit,
-                            u64 bg_blkno,
-                            unsigned int count)
+static int _ocfs2_free_suballoc_bits(handle_t *handle,
+                                    struct inode *alloc_inode,
+                                    struct buffer_head *alloc_bh,
+                                    unsigned int start_bit,
+                                    u64 bg_blkno,
+                                    unsigned int count,
+                                    void (*undo_fn)(unsigned int bit,
+                                                    unsigned long *bitmap))
 {
        int status = 0;
        u32 tmp_used;
@@ -2079,7 +2075,7 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
 
        status = ocfs2_block_group_clear_bits(handle, alloc_inode,
                                              group, group_bh,
-                                             start_bit, count);
+                                             start_bit, count, undo_fn);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -2110,6 +2106,17 @@ bail:
        return status;
 }
 
+int ocfs2_free_suballoc_bits(handle_t *handle,
+                            struct inode *alloc_inode,
+                            struct buffer_head *alloc_bh,
+                            unsigned int start_bit,
+                            u64 bg_blkno,
+                            unsigned int count)
+{
+       return _ocfs2_free_suballoc_bits(handle, alloc_inode, alloc_bh,
+                                        start_bit, bg_blkno, count, NULL);
+}
+
 int ocfs2_free_dinode(handle_t *handle,
                      struct inode *inode_alloc_inode,
                      struct buffer_head *inode_alloc_bh,
@@ -2123,11 +2130,13 @@ int ocfs2_free_dinode(handle_t *handle,
                                        inode_alloc_bh, bit, bg_blkno, 1);
 }
 
-int ocfs2_free_clusters(handle_t *handle,
-                      struct inode *bitmap_inode,
-                      struct buffer_head *bitmap_bh,
-                      u64 start_blk,
-                      unsigned int num_clusters)
+static int _ocfs2_free_clusters(handle_t *handle,
+                               struct inode *bitmap_inode,
+                               struct buffer_head *bitmap_bh,
+                               u64 start_blk,
+                               unsigned int num_clusters,
+                               void (*undo_fn)(unsigned int bit,
+                                               unsigned long *bitmap))
 {
        int status;
        u16 bg_start_bit;
@@ -2154,9 +2163,9 @@ int ocfs2_free_clusters(handle_t *handle,
        mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n",
             (unsigned long long)bg_blkno, bg_start_bit);
 
-       status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
-                                         bg_start_bit, bg_blkno,
-                                         num_clusters);
+       status = _ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
+                                          bg_start_bit, bg_blkno,
+                                          num_clusters, undo_fn);
        if (status < 0) {
                mlog_errno(status);
                goto out;
@@ -2170,6 +2179,32 @@ out:
        return status;
 }
 
+int ocfs2_free_clusters(handle_t *handle,
+                       struct inode *bitmap_inode,
+                       struct buffer_head *bitmap_bh,
+                       u64 start_blk,
+                       unsigned int num_clusters)
+{
+       return _ocfs2_free_clusters(handle, bitmap_inode, bitmap_bh,
+                                   start_blk, num_clusters,
+                                   _ocfs2_set_bit);
+}
+
+/*
+ * Give never-used clusters back to the global bitmap.  We don't need
+ * to protect these bits in the undo buffer.
+ */
+int ocfs2_release_clusters(handle_t *handle,
+                          struct inode *bitmap_inode,
+                          struct buffer_head *bitmap_bh,
+                          u64 start_blk,
+                          unsigned int num_clusters)
+{
+       return _ocfs2_free_clusters(handle, bitmap_inode, bitmap_bh,
+                                   start_blk, num_clusters,
+                                   _ocfs2_clear_bit);
+}
+
 static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg)
 {
        printk("Block Group:\n");
index fa60723c43e82b0a6d766e8ea439af393a7ce7bd..e0f46df357e664cc7b8c883b1d509fe884fcb950 100644 (file)
@@ -127,6 +127,11 @@ int ocfs2_free_clusters(handle_t *handle,
                        struct buffer_head *bitmap_bh,
                        u64 start_blk,
                        unsigned int num_clusters);
+int ocfs2_release_clusters(handle_t *handle,
+                          struct inode *bitmap_inode,
+                          struct buffer_head *bitmap_bh,
+                          u64 start_blk,
+                          unsigned int num_clusters);
 
 static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
 {
index d1b0d386f6d1c43c58b8e0016530f7830ea6eddf..3e7773089b968d7f29a0986fd65731646d0a382d 100644 (file)
@@ -1622,7 +1622,7 @@ static void ocfs2_xa_block_wipe_namevalue(struct ocfs2_xa_loc *loc)
        /* Now tell xh->xh_entries about it */
        for (i = 0; i < count; i++) {
                offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset);
-               if (offset < namevalue_offset)
+               if (offset <= namevalue_offset)
                        le16_add_cpu(&xh->xh_entries[i].xe_name_offset,
                                     namevalue_size);
        }
@@ -6528,13 +6528,11 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode,
                                          int indexed)
 {
        int ret;
-       struct ocfs2_alloc_context *meta_ac;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       struct ocfs2_xattr_set_ctxt ctxt = {
-               .meta_ac = meta_ac,
-       };
+       struct ocfs2_xattr_set_ctxt ctxt;
 
-       ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
+       memset(&ctxt, 0, sizeof(ctxt));
+       ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &ctxt.meta_ac);
        if (ret < 0) {
                mlog_errno(ret);
                return ret;
@@ -6556,7 +6554,7 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode,
 
        ocfs2_commit_trans(osb, ctxt.handle);
 out:
-       ocfs2_free_alloc_context(meta_ac);
+       ocfs2_free_alloc_context(ctxt.meta_ac);
        return ret;
 }
 
index 0028d2ef0662b0f01fd21b7685754d9939ebbd51..90be97f1f5a8c8ce5cf737c3e52020e0e516a291 100644 (file)
  */
 #include <asm/unaligned.h>
 
-#define SYS_IND(p)     (get_unaligned(&p->sys_ind))
-#define NR_SECTS(p)    ({ __le32 __a = get_unaligned(&p->nr_sects);    \
-                               le32_to_cpu(__a); \
-                       })
+#define SYS_IND(p)     get_unaligned(&p->sys_ind)
 
-#define START_SECT(p)  ({ __le32 __a = get_unaligned(&p->start_sect);  \
-                               le32_to_cpu(__a); \
-                       })
+static inline sector_t nr_sects(struct partition *p)
+{
+       return (sector_t)get_unaligned_le32(&p->nr_sects);
+}
+
+static inline sector_t start_sect(struct partition *p)
+{
+       return (sector_t)get_unaligned_le32(&p->start_sect);
+}
 
 static inline int is_extended_partition(struct partition *p)
 {
@@ -104,13 +107,13 @@ static int aix_magic_present(unsigned char *p, struct block_device *bdev)
 
 static void
 parse_extended(struct parsed_partitions *state, struct block_device *bdev,
-                       u32 first_sector, u32 first_size)
+                       sector_t first_sector, sector_t first_size)
 {
        struct partition *p;
        Sector sect;
        unsigned char *data;
-       u32 this_sector, this_size;
-       int sector_size = bdev_logical_block_size(bdev) / 512;
+       sector_t this_sector, this_size;
+       sector_t sector_size = bdev_logical_block_size(bdev) / 512;
        int loopct = 0;         /* number of links followed
                                   without finding a data partition */
        int i;
@@ -145,14 +148,14 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,
                 * First process the data partition(s)
                 */
                for (i=0; i<4; i++, p++) {
-                       u32 offs, size, next;
-                       if (!NR_SECTS(p) || is_extended_partition(p))
+                       sector_t offs, size, next;
+                       if (!nr_sects(p) || is_extended_partition(p))
                                continue;
 
                        /* Check the 3rd and 4th entries -
                           these sometimes contain random garbage */
-                       offs = START_SECT(p)*sector_size;
-                       size = NR_SECTS(p)*sector_size;
+                       offs = start_sect(p)*sector_size;
+                       size = nr_sects(p)*sector_size;
                        next = this_sector + offs;
                        if (i >= 2) {
                                if (offs + size > this_size)
@@ -179,13 +182,13 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,
                 */
                p -= 4;
                for (i=0; i<4; i++, p++)
-                       if (NR_SECTS(p) && is_extended_partition(p))
+                       if (nr_sects(p) && is_extended_partition(p))
                                break;
                if (i == 4)
                        goto done;       /* nothing left to do */
 
-               this_sector = first_sector + START_SECT(p) * sector_size;
-               this_size = NR_SECTS(p) * sector_size;
+               this_sector = first_sector + start_sect(p) * sector_size;
+               this_size = nr_sects(p) * sector_size;
                put_dev_sector(sect);
        }
 done:
@@ -197,7 +200,7 @@ done:
 
 static void
 parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
-                       u32 offset, u32 size, int origin)
+                       sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_SOLARIS_X86_PARTITION
        Sector sect;
@@ -244,7 +247,7 @@ parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
  */
 static void
 parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
-               u32 offset, u32 size, int origin, char *flavour,
+               sector_t offset, sector_t size, int origin, char *flavour,
                int max_partitions)
 {
        Sector sect;
@@ -263,7 +266,7 @@ parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
        if (le16_to_cpu(l->d_npartitions) < max_partitions)
                max_partitions = le16_to_cpu(l->d_npartitions);
        for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
-               u32 bsd_start, bsd_size;
+               sector_t bsd_start, bsd_size;
 
                if (state->next == state->limit)
                        break;
@@ -290,7 +293,7 @@ parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
 
 static void
 parse_freebsd(struct parsed_partitions *state, struct block_device *bdev,
-               u32 offset, u32 size, int origin)
+               sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_BSD_DISKLABEL
        parse_bsd(state, bdev, offset, size, origin,
@@ -300,7 +303,7 @@ parse_freebsd(struct parsed_partitions *state, struct block_device *bdev,
 
 static void
 parse_netbsd(struct parsed_partitions *state, struct block_device *bdev,
-               u32 offset, u32 size, int origin)
+               sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_BSD_DISKLABEL
        parse_bsd(state, bdev, offset, size, origin,
@@ -310,7 +313,7 @@ parse_netbsd(struct parsed_partitions *state, struct block_device *bdev,
 
 static void
 parse_openbsd(struct parsed_partitions *state, struct block_device *bdev,
-               u32 offset, u32 size, int origin)
+               sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_BSD_DISKLABEL
        parse_bsd(state, bdev, offset, size, origin,
@@ -324,7 +327,7 @@ parse_openbsd(struct parsed_partitions *state, struct block_device *bdev,
  */
 static void
 parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
-               u32 offset, u32 size, int origin)
+               sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_UNIXWARE_DISKLABEL
        Sector sect;
@@ -348,7 +351,8 @@ parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
 
                if (p->s_label != UNIXWARE_FS_UNUSED)
                        put_partition(state, state->next++,
-                                               START_SECT(p), NR_SECTS(p));
+                                     le32_to_cpu(p->start_sect),
+                                     le32_to_cpu(p->nr_sects));
                p++;
        }
        put_dev_sector(sect);
@@ -363,7 +367,7 @@ parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
  */
 static void
 parse_minix(struct parsed_partitions *state, struct block_device *bdev,
-               u32 offset, u32 size, int origin)
+               sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_MINIX_SUBPARTITION
        Sector sect;
@@ -390,7 +394,7 @@ parse_minix(struct parsed_partitions *state, struct block_device *bdev,
                        /* add each partition in use */
                        if (SYS_IND(p) == MINIX_PARTITION)
                                put_partition(state, state->next++,
-                                             START_SECT(p), NR_SECTS(p));
+                                             start_sect(p), nr_sects(p));
                }
                printk(" >\n");
        }
@@ -401,7 +405,7 @@ parse_minix(struct parsed_partitions *state, struct block_device *bdev,
 static struct {
        unsigned char id;
        void (*parse)(struct parsed_partitions *, struct block_device *,
-                       u32, u32, int);
+                       sector_t, sector_t, int);
 } subtypes[] = {
        {FREEBSD_PARTITION, parse_freebsd},
        {NETBSD_PARTITION, parse_netbsd},
@@ -415,7 +419,7 @@ static struct {
  
 int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-       int sector_size = bdev_logical_block_size(bdev) / 512;
+       sector_t sector_size = bdev_logical_block_size(bdev) / 512;
        Sector sect;
        unsigned char *data;
        struct partition *p;
@@ -483,14 +487,21 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 
        state->next = 5;
        for (slot = 1 ; slot <= 4 ; slot++, p++) {
-               u32 start = START_SECT(p)*sector_size;
-               u32 size = NR_SECTS(p)*sector_size;
+               sector_t start = start_sect(p)*sector_size;
+               sector_t size = nr_sects(p)*sector_size;
                if (!size)
                        continue;
                if (is_extended_partition(p)) {
-                       /* prevent someone doing mkfs or mkswap on an
-                          extended partition, but leave room for LILO */
-                       put_partition(state, slot, start, size == 1 ? 1 : 2);
+                       /*
+                        * prevent someone doing mkfs or mkswap on an
+                        * extended partition, but leave room for LILO
+                        * FIXME: this uses one logical sector for > 512b
+                        * sector, although it may not be enough/proper.
+                        */
+                       sector_t n = 2;
+                       n = min(size, max(sector_size, n));
+                       put_partition(state, slot, start, n);
+
                        printk(" <");
                        parse_extended(state, bdev, start, size);
                        printk(" >");
@@ -513,7 +524,7 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
                unsigned char id = SYS_IND(p);
                int n;
 
-               if (!NR_SECTS(p))
+               if (!nr_sects(p))
                        continue;
 
                for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
@@ -521,8 +532,8 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 
                if (!subtypes[n].parse)
                        continue;
-               subtypes[n].parse(state, bdev, START_SECT(p)*sector_size,
-                                               NR_SECTS(p)*sector_size, slot);
+               subtypes[n].parse(state, bdev, start_sect(p)*sector_size,
+                                               nr_sects(p)*sector_size, slot);
        }
        put_dev_sector(sect);
        return 1;
index a7310841c83149e406c1089d30a8c27b2c1e67fb..b1f6e62773d3bbcebb8e314a446e9097e1656dc0 100644 (file)
@@ -442,12 +442,13 @@ static const struct file_operations proc_lstats_operations = {
 unsigned long badness(struct task_struct *p, unsigned long uptime);
 static int proc_oom_score(struct task_struct *task, char *buffer)
 {
-       unsigned long points;
+       unsigned long points = 0;
        struct timespec uptime;
 
        do_posix_clock_monotonic_gettime(&uptime);
        read_lock(&tasklist_lock);
-       points = badness(task->group_leader, uptime.tv_sec);
+       if (pid_alive(task))
+               points = badness(task, uptime.tv_sec);
        read_unlock(&tasklist_lock);
        return sprintf(buffer, "%lu\n", points);
 }
index a44a7897fd4d20988aa933a89fab2d9c1600d53a..b442dac8f5f99f5366c55eef420b6fb51120c5f0 100644 (file)
@@ -490,7 +490,7 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
                }
                read_unlock(&kclist_lock);
 
-               if (m == NULL) {
+               if (&m->list == &kclist_head) {
                        if (clear_user(buffer, tsz))
                                return -EFAULT;
                } else if (is_vmalloc_or_module_addr((void *)start)) {
index b7f4a1f94d48eff7711d8d2761b019385142d7f7..113386d6fd2de0bdd12721e65b85a0fcbe8ab7b1 100644 (file)
@@ -258,6 +258,7 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
        kiocb.ki_left = len;
+       kiocb.ki_nbytes = len;
 
        for (;;) {
                ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
@@ -313,6 +314,7 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
        kiocb.ki_left = len;
+       kiocb.ki_nbytes = len;
 
        for (;;) {
                ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
index ba98546fabbd1921beedc54074f7399115f14f54..f3de5e8a2ae810124bec85a9e95b026c25c58cb0 100644 (file)
@@ -2217,6 +2217,15 @@ static int journal_read_transaction(struct super_block *sb,
                brelse(d_bh);
                return 1;
        }
+
+       if (bdev_read_only(sb->s_bdev)) {
+               reiserfs_warning(sb, "clm-2076",
+                                "device is readonly, unable to replay log");
+               brelse(c_bh);
+               brelse(d_bh);
+               return -EROFS;
+       }
+
        trans_id = get_desc_trans_id(desc);
        /* now we know we've got a good transaction, and it was inside the valid time ranges */
        log_blocks = kmalloc(get_desc_trans_len(desc) *
@@ -2459,12 +2468,6 @@ static int journal_read(struct super_block *sb)
                goto start_log_replay;
        }
 
-       if (continue_replay && bdev_read_only(sb->s_bdev)) {
-               reiserfs_warning(sb, "clm-2076",
-                                "device is readonly, unable to replay log");
-               return -1;
-       }
-
        /* ok, there are transactions that need to be replayed.  start with the first log block, find
         ** all the valid transactions, and pick out the oldest.
         */
index 04bf5d791bdad8b9fea4c6eecc6d7772035d7144..ab190511bc182236c0e34bf70977516957a16816 100644 (file)
@@ -1618,10 +1618,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        save_mount_options(s, data);
 
        sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL);
-       if (!sbi) {
-               errval = -ENOMEM;
-               goto error_alloc;
-       }
+       if (!sbi)
+               return -ENOMEM;
        s->s_fs_info = sbi;
        /* Set default values for options: non-aggressive tails, RO on errors */
        REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_SMALLTAIL);
@@ -1878,12 +1876,12 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        return (0);
 
 error:
-       reiserfs_write_unlock(s);
-error_alloc:
        if (jinit_done) {       /* kill the commit thread, free journal ram */
                journal_release_error(NULL, s);
        }
 
+       reiserfs_write_unlock(s);
+
        reiserfs_free_bitmap_cache(s);
        if (SB_BUFFER_WITH_SB(s))
                brelse(SB_BUFFER_WITH_SB(s));
index d8b5bfcbdd30b027aae6c9eae937b566b7b2043d..de1fcffd906bc70ef94586ac951169ad376179ec 100644 (file)
@@ -76,7 +76,7 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
                return error;
        }
 
-       if (sec->length) {
+       if (sec->length && reiserfs_xattrs_initialized(inode->i_sb)) {
                blocks = reiserfs_xattr_jcreate_nblocks(inode) +
                         reiserfs_xattr_nblocks(inode, sec->length);
                /* We don't want to count the directories twice if we have
index 3a4767c01c5fd6ecee67d409fdf4a906bbe5da5f..4f7b44866b762351ca4bfacdbcb65cacec13d010 100644 (file)
@@ -65,6 +65,8 @@
 #define ACPI_VIDEO_HID                 "LNXVIDEO"
 #define ACPI_BAY_HID                   "LNXIOBAY"
 #define ACPI_DOCK_HID                  "LNXDOCK"
+/* Quirk for broken IBM BIOSes */
+#define ACPI_SMBUS_IBM_HID             "SMBUSIBM"
 
 /*
  * For fixed hardware buttons, we fabricate acpi_devices with HID
index 4a3c4e441027be39da3d37b8a817ff9f918661dd..de2f82efb15f9cfe384658f97571e25b6ad16d34 100644 (file)
@@ -1545,39 +1545,7 @@ static __inline__ void drm_core_dropmap(struct drm_local_map *map)
 {
 }
 
-
-static __inline__ void *drm_calloc_large(size_t nmemb, size_t size)
-{
-       if (size != 0 && nmemb > ULONG_MAX / size)
-               return NULL;
-
-       if (size * nmemb <= PAGE_SIZE)
-           return kcalloc(nmemb, size, GFP_KERNEL);
-
-       return __vmalloc(size * nmemb,
-                        GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
-}
-
-/* Modeled after cairo's malloc_ab, it's like calloc but without the zeroing. */
-static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size)
-{
-       if (size != 0 && nmemb > ULONG_MAX / size)
-               return NULL;
-
-       if (size * nmemb <= PAGE_SIZE)
-           return kmalloc(nmemb * size, GFP_KERNEL);
-
-       return __vmalloc(size * nmemb,
-                        GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
-}
-
-static __inline void drm_free_large(void *ptr)
-{
-       if (!is_vmalloc_addr(ptr))
-               return kfree(ptr);
-
-       vfree(ptr);
-}
+#include "drm_mem_util.h"
 /*@}*/
 
 #endif                         /* __KERNEL__ */
diff --git a/include/drm/drm_mem_util.h b/include/drm/drm_mem_util.h
new file mode 100644 (file)
index 0000000..6bd325f
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright Â© 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *     Jesse Barnes <jbarnes@virtuousgeek.org>
+ *
+ */
+#ifndef _DRM_MEM_UTIL_H_
+#define _DRM_MEM_UTIL_H_
+
+#include <linux/vmalloc.h>
+
+static __inline__ void *drm_calloc_large(size_t nmemb, size_t size)
+{
+       if (size != 0 && nmemb > ULONG_MAX / size)
+               return NULL;
+
+       if (size * nmemb <= PAGE_SIZE)
+           return kcalloc(nmemb, size, GFP_KERNEL);
+
+       return __vmalloc(size * nmemb,
+                        GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+}
+
+/* Modeled after cairo's malloc_ab, it's like calloc but without the zeroing. */
+static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size)
+{
+       if (size != 0 && nmemb > ULONG_MAX / size)
+               return NULL;
+
+       if (size * nmemb <= PAGE_SIZE)
+           return kmalloc(nmemb * size, GFP_KERNEL);
+
+       return __vmalloc(size * nmemb,
+                        GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
+}
+
+static __inline void drm_free_large(void *ptr)
+{
+       if (!is_vmalloc_addr(ptr))
+               return kfree(ptr);
+
+       vfree(ptr);
+}
+
+#endif
index 676104b7818c0d35cc69f6b60105891f29df63ee..04a6ebc27b966879c3592d510b8e231b5b276ad0 100644 (file)
        {0x1002, 0x9712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9713, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9715, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0, 0, 0}
 
 #define r128_PCI_IDS \
index e3f1b4a4b601aa5cb909030d733dad50f5c074cc..e929c27ede2229b2e3f656619464e4cb7cc0d47e 100644 (file)
@@ -115,7 +115,6 @@ struct ttm_backend {
        struct ttm_backend_func *func;
 };
 
-#define TTM_PAGE_FLAG_VMALLOC         (1 << 0)
 #define TTM_PAGE_FLAG_USER            (1 << 1)
 #define TTM_PAGE_FLAG_USER_DIRTY      (1 << 2)
 #define TTM_PAGE_FLAG_WRITE           (1 << 3)
index a2ed0591fb19c57f5544f74f6233afe7cda60d35..90f2471dc6f2382d9f522d0c80287a09069c9ed8 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ * See Documentation/circular-buffers.txt for more information.
+ */
+
 #ifndef _LINUX_CIRC_BUF_H
 #define _LINUX_CIRC_BUF_H 1
 
index 0cf725bdd2a1a76d2f9da0d6855268cf7a97955d..fc53492b6ad7fb67e904e88d2f02d184771a326e 100644 (file)
@@ -73,6 +73,7 @@ enum clock_event_nofitiers {
  * @list:              list head for the management code
  * @mode:              operating mode assigned by the management code
  * @next_event:                local storage for the next event in oneshot mode
+ * @retries:           number of forced programming retries
  */
 struct clock_event_device {
        const char              *name;
@@ -93,6 +94,7 @@ struct clock_event_device {
        struct list_head        list;
        enum clock_event_mode   mode;
        ktime_t                 next_event;
+       unsigned long           retries;
 };
 
 /*
index cac84b006667a42ee3296a3301e37f37978ec23f..5f494b4650977fcb9aac65aa7153320fb1c6f487 100644 (file)
@@ -565,17 +565,17 @@ enum {
 
 static inline int ext3_test_inode_state(struct inode *inode, int bit)
 {
-       return test_bit(bit, &EXT3_I(inode)->i_state);
+       return test_bit(bit, &EXT3_I(inode)->i_state_flags);
 }
 
 static inline void ext3_set_inode_state(struct inode *inode, int bit)
 {
-       set_bit(bit, &EXT3_I(inode)->i_state);
+       set_bit(bit, &EXT3_I(inode)->i_state_flags);
 }
 
 static inline void ext3_clear_inode_state(struct inode *inode, int bit)
 {
-       clear_bit(bit, &EXT3_I(inode)->i_state);
+       clear_bit(bit, &EXT3_I(inode)->i_state_flags);
 }
 #else
 /* Assume that user mode programs are passing in an ext3fs superblock, not
index 7679acdb519a14ae540f421a9d664b65914a5cfb..f42c098aed8d8a38c13849d5ef0940f6394b9594 100644 (file)
@@ -87,7 +87,7 @@ struct ext3_inode_info {
         * near to their parent directory's inode.
         */
        __u32   i_block_group;
-       unsigned long   i_state;        /* Dynamic state flags for ext3 */
+       unsigned long   i_state_flags;  /* Dynamic state flags for ext3 */
 
        /* block reservation info */
        struct ext3_block_alloc_info *i_block_alloc_info;
index 5a361f85cfec483e0a595dcb2f4c2ee632ac56d9..da7e52b099f3221cf723f008aa2ac627d276e11b 100644 (file)
@@ -64,9 +64,12 @@ extern bool freeze_task(struct task_struct *p, bool sig_only);
 extern void cancel_freezing(struct task_struct *p);
 
 #ifdef CONFIG_CGROUP_FREEZER
-extern int cgroup_frozen(struct task_struct *task);
+extern int cgroup_freezing_or_frozen(struct task_struct *task);
 #else /* !CONFIG_CGROUP_FREEZER */
-static inline int cgroup_frozen(struct task_struct *task) { return 0; }
+static inline int cgroup_freezing_or_frozen(struct task_struct *task)
+{
+       return 0;
+}
 #endif /* !CONFIG_CGROUP_FREEZER */
 
 /*
index 7be0c6fbe8808be086d884939c7c621e3f5d78cf..c57db27ac86140ba13798e1736b31d9254162a82 100644 (file)
@@ -105,7 +105,7 @@ struct fscache_operation {
        /* operation releaser */
        fscache_operation_release_t release;
 
-#ifdef CONFIG_SLOW_WORK_PROC
+#ifdef CONFIG_SLOW_WORK_DEBUG
        const char *name;               /* operation name */
        const char *state;              /* operation state */
 #define fscache_set_op_name(OP, N)     do { (OP)->name  = (N); } while(0)
index 1822d635be6b461124e659cfaa0861474a25e0bf..16b92d008bed842e141f77664e94446cbe652dcf 100644 (file)
@@ -2,6 +2,7 @@
 #define _IF_TUNNEL_H_
 
 #include <linux/types.h>
+#include <asm/byteorder.h>
 
 #ifdef __KERNEL__
 #include <linux/ip.h>
index 71ab79da7e7f6b3a12019849978e2da58a00b61c..26fad187d6610f3179dc3bf6b4b1b43820e1783a 100644 (file)
@@ -112,12 +112,14 @@ struct resource_list {
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
 
+extern struct resource *request_resource_conflict(struct resource *root, struct resource *new);
 extern int request_resource(struct resource *root, struct resource *new);
 extern int release_resource(struct resource *new);
 void release_child_resources(struct resource *new);
 extern void reserve_region_with_split(struct resource *root,
                             resource_size_t start, resource_size_t end,
                             const char *name);
+extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new);
 extern int insert_resource(struct resource *parent, struct resource *new);
 extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new);
 extern int allocate_resource(struct resource *root, struct resource *new,
index bc0fc795bd3536c90feb50b0ce4226c6461447e5..ece0b1c33816d414e79b7d6046d17230fe71bf28 100644 (file)
@@ -102,8 +102,6 @@ union { \
        unsigned char name##kfifo_buffer[size]; \
        struct kfifo name = __kfifo_initializer(size, name##kfifo_buffer)
 
-#undef __kfifo_initializer
-
 extern void kfifo_init(struct kfifo *fifo, void *buffer,
                        unsigned int size);
 extern __must_check int kfifo_alloc(struct kfifo *fifo, unsigned int size,
index c02c8db737011c848499c43580b64632980ff404..8a49cbf0376de0f42409ca1a5a1a71dd00104201 100644 (file)
@@ -268,6 +268,7 @@ struct _mmc_csd {
 
 #define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_MASK 0x3     /* Mask out reserved and DDR bits */
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
index c79a88be7c33813c494bc3694229b943f2fc4d9e..fa8b47637997cd4eef3f0e791ce8bf5b48b34a85 100644 (file)
@@ -2059,12 +2059,12 @@ static inline void skb_bond_set_mac_by_master(struct sk_buff *skb,
  * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
  * ARP on active-backup slaves with arp_validate enabled.
  */
-static inline int skb_bond_should_drop(struct sk_buff *skb)
+static inline int skb_bond_should_drop(struct sk_buff *skb,
+                                      struct net_device *master)
 {
-       struct net_device *dev = skb->dev;
-       struct net_device *master = dev->master;
-
        if (master) {
+               struct net_device *dev = skb->dev;
+
                if (master->priv_flags & IFF_MASTER_ARPMON)
                        dev->last_rx = jiffies;
 
index 53923868c9bddf8ab63a21019056b6858af5dbd9..361d6b5630ee8105e407477308bed1ab6f03ccf0 100644 (file)
@@ -76,7 +76,7 @@ extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n);
 extern int nfnetlink_has_listeners(struct net *net, unsigned int group);
 extern int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group,
                          int echo, gfp_t flags);
-extern void nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error);
+extern int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error);
 extern int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags);
 
 extern void nfnl_lock(void);
index d654873aa25afdaae0fe2ac921b2cd58db16bf04..1f7e300094cd4777ffe98600cc5319bcf5bb406f 100644 (file)
@@ -59,6 +59,7 @@
 enum nf_ip6_hook_priorities {
        NF_IP6_PRI_FIRST = INT_MIN,
        NF_IP6_PRI_CONNTRACK_DEFRAG = -400,
+       NF_IP6_PRI_RAW = -300,
        NF_IP6_PRI_SELINUX_FIRST = -225,
        NF_IP6_PRI_CONNTRACK = -200,
        NF_IP6_PRI_MANGLE = -150,
index fde27c0173266852787c4d15613f7116b10f3d21..6eaca5e1e8ca595fbfa388815c1b69675baaf314 100644 (file)
@@ -188,7 +188,7 @@ extern int netlink_has_listeners(struct sock *sk, unsigned int group);
 extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
 extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
                             __u32 group, gfp_t allocation);
-extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
+extern int netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
 extern int netlink_register_notifier(struct notifier_block *nb);
 extern int netlink_unregister_notifier(struct notifier_block *nb);
 
index 3024050c82a12610222a1b5e7d1c40d44e339b5a..872a98e13d6ab7ce2b833cf073925048c43807f9 100644 (file)
@@ -123,22 +123,11 @@ static inline int rcu_read_lock_held(void)
        return lock_is_held(&rcu_lock_map);
 }
 
-/**
- * rcu_read_lock_bh_held - might we be in RCU-bh read-side critical section?
- *
- * If CONFIG_PROVE_LOCKING is selected and enabled, returns nonzero iff in
- * an RCU-bh read-side critical section.  In absence of CONFIG_PROVE_LOCKING,
- * this assumes we are in an RCU-bh read-side critical section unless it can
- * prove otherwise.
- *
- * Check rcu_scheduler_active to prevent false positives during boot.
+/*
+ * rcu_read_lock_bh_held() is defined out of line to avoid #include-file
+ * hell.
  */
-static inline int rcu_read_lock_bh_held(void)
-{
-       if (!debug_lockdep_rcu_enabled())
-               return 1;
-       return lock_is_held(&rcu_bh_lock_map);
-}
+extern int rcu_read_lock_bh_held(void);
 
 /**
  * rcu_read_lock_sched_held - might we be in RCU-sched read-side critical section?
@@ -160,7 +149,7 @@ static inline int rcu_read_lock_sched_held(void)
                return 1;
        if (debug_locks)
                lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
-       return lockdep_opinion || preempt_count() != 0;
+       return lockdep_opinion || preempt_count() != 0 || irqs_disabled();
 }
 #else /* #ifdef CONFIG_PREEMPT */
 static inline int rcu_read_lock_sched_held(void)
@@ -191,7 +180,7 @@ static inline int rcu_read_lock_bh_held(void)
 #ifdef CONFIG_PREEMPT
 static inline int rcu_read_lock_sched_held(void)
 {
-       return !rcu_scheduler_active || preempt_count() != 0;
+       return !rcu_scheduler_active || preempt_count() != 0 || irqs_disabled();
 }
 #else /* #ifdef CONFIG_PREEMPT */
 static inline int rcu_read_lock_sched_held(void)
index 99928dce37ea927bde2f515df93ad9a2bab2a239..7fa02b4af838513b9a609122db0772654cdc2f91 100644 (file)
@@ -70,6 +70,11 @@ int reiserfs_security_write(struct reiserfs_transaction_handle *th,
 void reiserfs_security_free(struct reiserfs_security_handle *sec);
 #endif
 
+static inline int reiserfs_xattrs_initialized(struct super_block *sb)
+{
+       return REISERFS_SB(sb)->priv_root != NULL;
+}
+
 #define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header))
 static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size)
 {
index 03f816a9b65950ba998b00aaf5f3352f25be0c7f..124f90cd5a38bd39ab88af0563aa0d0ff9aa06d2 100644 (file)
@@ -190,9 +190,6 @@ struct skb_shared_info {
        atomic_t        dataref;
        unsigned short  nr_frags;
        unsigned short  gso_size;
-#ifdef CONFIG_HAS_DMA
-       dma_addr_t      dma_head;
-#endif
        /* Warning: this field is not always filled in (UFO)! */
        unsigned short  gso_segs;
        unsigned short  gso_type;
@@ -201,9 +198,6 @@ struct skb_shared_info {
        struct sk_buff  *frag_list;
        struct skb_shared_hwtstamps hwtstamps;
        skb_frag_t      frags[MAX_SKB_FRAGS];
-#ifdef CONFIG_HAS_DMA
-       dma_addr_t      dma_maps[MAX_SKB_FRAGS];
-#endif
        /* Intermediate layers must ensure that destructor_arg
         * remains valid until skb destructor */
        void *          destructor_arg;
index 7b3aae2052a6e37340ed04548487333141d925cd..354cc5617f8b87304b97eebeec2c4b3e8a52428a 100644 (file)
@@ -255,6 +255,7 @@ struct ucred {
 #define MSG_ERRQUEUE   0x2000  /* Fetch message from error queue */
 #define MSG_NOSIGNAL   0x4000  /* Do not generate SIGPIPE */
 #define MSG_MORE       0x8000  /* Sender will send more */
+#define MSG_WAITFORONE 0x10000 /* recvmmsg(): block until 1+ packets avail */
 
 #define MSG_EOF         MSG_FIN
 
index d7152b451e21d7fb2bb84fcd3ffc33afa8ace8e9..7c91260c44a93ef8870f6c0cd2620cb0619e113f 100644 (file)
@@ -36,7 +36,6 @@ struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt);
 void xprt_free_bc_request(struct rpc_rqst *req);
 int xprt_setup_backchannel(struct rpc_xprt *, unsigned int min_reqs);
 void xprt_destroy_backchannel(struct rpc_xprt *, int max_reqs);
-void bc_release_request(struct rpc_task *);
 int bc_send(struct rpc_rqst *req);
 
 /*
@@ -59,6 +58,10 @@ static inline int svc_is_backchannel(const struct svc_rqst *rqstp)
 {
        return 0;
 }
+
+static inline void xprt_free_bc_request(struct rpc_rqst *req)
+{
+}
 #endif /* CONFIG_NFS_V4_1 */
 #endif /* _LINUX_SUNRPC_BC_XPRT_H */
 
index f994ae58a002a59bc45db3a5cd36fae0df75e17e..057929b0a6514963b66098e9f3ff58129937ffa5 100644 (file)
@@ -688,7 +688,7 @@ asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg);
 asmlinkage long sys_shmget(key_t key, size_t size, int flag);
 asmlinkage long sys_shmdt(char __user *shmaddr);
 asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
-asmlinkage long sys_ipc(unsigned int call, int first, int second,
+asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
                unsigned long third, void __user *ptr, long fifth);
 
 asmlinkage long sys_mq_open(const char __user *name, int oflag, mode_t mode, struct mq_attr __user *attr);
index f59604ed0ec606c75449d6b2cd8416abf6f7f38f..78b4bd3be496c22f96fb6bc6400d2e831b6ce210 100644 (file)
@@ -49,7 +49,7 @@ struct tracepoint {
                void **it_func;                                         \
                                                                        \
                rcu_read_lock_sched_notrace();                          \
-               it_func = rcu_dereference((tp)->funcs);                 \
+               it_func = rcu_dereference_sched((tp)->funcs);           \
                if (it_func) {                                          \
                        do {                                            \
                                ((void(*)(proto))(*it_func))(args);     \
index 04a6908e38d2883a136a60c92ddb1405e1d1ff60..ff77e8f882f13fdc8545662b3543685e661de0f4 100644 (file)
@@ -176,6 +176,6 @@ extern void hci_sock_cleanup(void);
 extern int bt_sysfs_init(void);
 extern void bt_sysfs_cleanup(void);
 
-extern struct class *bt_class;
+extern struct dentry *bt_debugfs;
 
 #endif /* __BLUETOOTH_H */
index f82e463c875a51600ad0055c86c164d12e3e16ed..4fc05b58503eb4beab8fc20b3ab0b762f9f3d293 100644 (file)
@@ -945,7 +945,11 @@ static inline u64 nla_get_u64(const struct nlattr *nla)
  */
 static inline __be64 nla_get_be64(const struct nlattr *nla)
 {
-       return *(__be64 *) nla_data(nla);
+       __be64 tmp;
+
+       nla_memcpy(&tmp, nla, sizeof(tmp));
+
+       return tmp;
 }
 
 /**
index 32896a77391054babaeb60482ad121a4864329af..2e488b60bc7603668de714acc570e3c463db28d4 100644 (file)
@@ -277,12 +277,6 @@ extern struct pccard_resource_ops pccard_nonstatic_ops;
 #endif
 
 
-/* socket drivers are expected to use these callbacks in their .drv struct */
-extern int pcmcia_socket_dev_suspend(struct device *dev);
-extern void pcmcia_socket_dev_early_resume(struct device *dev);
-extern void pcmcia_socket_dev_late_resume(struct device *dev);
-extern int pcmcia_socket_dev_resume(struct device *dev);
-
 /* socket drivers use this callback in their IRQ handler */
 extern void pcmcia_parse_events(struct pcmcia_socket *socket,
                                unsigned int events);
index a1ab78ceb4b62abf17551bc990a3298d1c95a320..cbead27caefcc2bc8e62de6181e2832ac621843f 100644 (file)
@@ -858,7 +858,7 @@ static int __init kernel_init(void * unused)
        /*
         * init can allocate pages on any node
         */
-       set_mems_allowed(node_possible_map);
+       set_mems_allowed(node_states[N_HIGH_MEMORY]);
        /*
         * init can run on any cpu.
         */
index 355a3da9ec73dd8bba5f596c1e1d026e53d881ea..1d6f53f6b562441bcf5ef99c85067275eecf6c5a 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
-SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second,
+SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
                unsigned long, third, void __user *, ptr, long, fifth)
 {
        int version, ret;
index ef909a32975006eafd43ce7693314eef5c5ffa4d..e2769e13980c49b2546d0bb2c6cef1e0065f6ca7 100644 (file)
@@ -27,7 +27,6 @@
  */
 
 #include <linux/cgroup.h>
-#include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
index 59e9ef6aab4002e1d99170f50156e733e8f46343..eb3f34d574196a8adb00c8327500f40c9ac03c5c 100644 (file)
@@ -47,17 +47,20 @@ static inline struct freezer *task_freezer(struct task_struct *task)
                            struct freezer, css);
 }
 
-int cgroup_frozen(struct task_struct *task)
+int cgroup_freezing_or_frozen(struct task_struct *task)
 {
        struct freezer *freezer;
        enum freezer_state state;
 
        task_lock(task);
        freezer = task_freezer(task);
-       state = freezer->state;
+       if (!freezer->css.cgroup->parent)
+               state = CGROUP_THAWED; /* root cgroup can't be frozen */
+       else
+               state = freezer->state;
        task_unlock(task);
 
-       return state == CGROUP_FROZEN;
+       return (state == CGROUP_FREEZING) || (state == CGROUP_FROZEN);
 }
 
 /*
index ba401fab459f94a42010f6175b2b69c490920645..d10946748ec2a3c9a070301f4af78c5f4dd18845 100644 (file)
@@ -920,9 +920,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
  *    call to guarantee_online_mems(), as we know no one is changing
  *    our task's cpuset.
  *
- *    Hold callback_mutex around the two modifications of our tasks
- *    mems_allowed to synchronize with cpuset_mems_allowed().
- *
  *    While the mm_struct we are migrating is typically from some
  *    other task, the task_struct mems_allowed that we are hacking
  *    is for our current task, which must allocate new pages for that
@@ -973,15 +970,20 @@ static void cpuset_change_nodemask(struct task_struct *p,
        struct cpuset *cs;
        int migrate;
        const nodemask_t *oldmem = scan->data;
-       nodemask_t newmems;
+       NODEMASK_ALLOC(nodemask_t, newmems, GFP_KERNEL);
+
+       if (!newmems)
+               return;
 
        cs = cgroup_cs(scan->cg);
-       guarantee_online_mems(cs, &newmems);
+       guarantee_online_mems(cs, newmems);
 
        task_lock(p);
-       cpuset_change_task_nodemask(p, &newmems);
+       cpuset_change_task_nodemask(p, newmems);
        task_unlock(p);
 
+       NODEMASK_FREE(newmems);
+
        mm = get_task_mm(p);
        if (!mm)
                return;
@@ -1051,16 +1053,21 @@ static void update_tasks_nodemask(struct cpuset *cs, const nodemask_t *oldmem,
 static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
                           const char *buf)
 {
-       nodemask_t oldmem;
+       NODEMASK_ALLOC(nodemask_t, oldmem, GFP_KERNEL);
        int retval;
        struct ptr_heap heap;
 
+       if (!oldmem)
+               return -ENOMEM;
+
        /*
         * top_cpuset.mems_allowed tracks node_stats[N_HIGH_MEMORY];
         * it's read-only
         */
-       if (cs == &top_cpuset)
-               return -EACCES;
+       if (cs == &top_cpuset) {
+               retval = -EACCES;
+               goto done;
+       }
 
        /*
         * An empty mems_allowed is ok iff there are no tasks in the cpuset.
@@ -1076,11 +1083,13 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
                        goto done;
 
                if (!nodes_subset(trialcs->mems_allowed,
-                               node_states[N_HIGH_MEMORY]))
-                       return -EINVAL;
+                               node_states[N_HIGH_MEMORY])) {
+                       retval =  -EINVAL;
+                       goto done;
+               }
        }
-       oldmem = cs->mems_allowed;
-       if (nodes_equal(oldmem, trialcs->mems_allowed)) {
+       *oldmem = cs->mems_allowed;
+       if (nodes_equal(*oldmem, trialcs->mems_allowed)) {
                retval = 0;             /* Too easy - nothing to do */
                goto done;
        }
@@ -1096,10 +1105,11 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
        cs->mems_allowed = trialcs->mems_allowed;
        mutex_unlock(&callback_mutex);
 
-       update_tasks_nodemask(cs, &oldmem, &heap);
+       update_tasks_nodemask(cs, oldmem, &heap);
 
        heap_free(&heap);
 done:
+       NODEMASK_FREE(oldmem);
        return retval;
 }
 
@@ -1384,40 +1394,47 @@ static void cpuset_attach(struct cgroup_subsys *ss, struct cgroup *cont,
                          struct cgroup *oldcont, struct task_struct *tsk,
                          bool threadgroup)
 {
-       nodemask_t from, to;
        struct mm_struct *mm;
        struct cpuset *cs = cgroup_cs(cont);
        struct cpuset *oldcs = cgroup_cs(oldcont);
+       NODEMASK_ALLOC(nodemask_t, from, GFP_KERNEL);
+       NODEMASK_ALLOC(nodemask_t, to, GFP_KERNEL);
+
+       if (from == NULL || to == NULL)
+               goto alloc_fail;
 
        if (cs == &top_cpuset) {
                cpumask_copy(cpus_attach, cpu_possible_mask);
-               to = node_possible_map;
        } else {
                guarantee_online_cpus(cs, cpus_attach);
-               guarantee_online_mems(cs, &to);
        }
+       guarantee_online_mems(cs, to);
 
        /* do per-task migration stuff possibly for each in the threadgroup */
-       cpuset_attach_task(tsk, &to, cs);
+       cpuset_attach_task(tsk, to, cs);
        if (threadgroup) {
                struct task_struct *c;
                rcu_read_lock();
                list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) {
-                       cpuset_attach_task(c, &to, cs);
+                       cpuset_attach_task(c, to, cs);
                }
                rcu_read_unlock();
        }
 
        /* change mm; only needs to be done once even if threadgroup */
-       from = oldcs->mems_allowed;
-       to = cs->mems_allowed;
+       *from = oldcs->mems_allowed;
+       *to = cs->mems_allowed;
        mm = get_task_mm(tsk);
        if (mm) {
-               mpol_rebind_mm(mm, &to);
+               mpol_rebind_mm(mm, to);
                if (is_memory_migrate(cs))
-                       cpuset_migrate_mm(mm, &from, &to);
+                       cpuset_migrate_mm(mm, from, to);
                mmput(mm);
        }
+
+alloc_fail:
+       NODEMASK_FREE(from);
+       NODEMASK_FREE(to);
 }
 
 /* The various types of files and directories in a cpuset file system */
@@ -1562,13 +1579,21 @@ static int cpuset_sprintf_cpulist(char *page, struct cpuset *cs)
 
 static int cpuset_sprintf_memlist(char *page, struct cpuset *cs)
 {
-       nodemask_t mask;
+       NODEMASK_ALLOC(nodemask_t, mask, GFP_KERNEL);
+       int retval;
+
+       if (mask == NULL)
+               return -ENOMEM;
 
        mutex_lock(&callback_mutex);
-       mask = cs->mems_allowed;
+       *mask = cs->mems_allowed;
        mutex_unlock(&callback_mutex);
 
-       return nodelist_scnprintf(page, PAGE_SIZE, mask);
+       retval = nodelist_scnprintf(page, PAGE_SIZE, *mask);
+
+       NODEMASK_FREE(mask);
+
+       return retval;
 }
 
 static ssize_t cpuset_common_file_read(struct cgroup *cont,
@@ -1997,7 +2022,10 @@ static void scan_for_empty_cpusets(struct cpuset *root)
        struct cpuset *cp;      /* scans cpusets being updated */
        struct cpuset *child;   /* scans child cpusets of cp */
        struct cgroup *cont;
-       nodemask_t oldmems;
+       NODEMASK_ALLOC(nodemask_t, oldmems, GFP_KERNEL);
+
+       if (oldmems == NULL)
+               return;
 
        list_add_tail((struct list_head *)&root->stack_list, &queue);
 
@@ -2014,7 +2042,7 @@ static void scan_for_empty_cpusets(struct cpuset *root)
                    nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY]))
                        continue;
 
-               oldmems = cp->mems_allowed;
+               *oldmems = cp->mems_allowed;
 
                /* Remove offline cpus and mems from this cpuset. */
                mutex_lock(&callback_mutex);
@@ -2030,9 +2058,10 @@ static void scan_for_empty_cpusets(struct cpuset *root)
                        remove_tasks_in_empty_cpuset(cp);
                else {
                        update_tasks_cpumask(cp, NULL);
-                       update_tasks_nodemask(cp, &oldmems, NULL);
+                       update_tasks_nodemask(cp, oldmems, NULL);
                }
        }
+       NODEMASK_FREE(oldmems);
 }
 
 /*
@@ -2090,20 +2119,33 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb,
 static int cpuset_track_online_nodes(struct notifier_block *self,
                                unsigned long action, void *arg)
 {
+       NODEMASK_ALLOC(nodemask_t, oldmems, GFP_KERNEL);
+
+       if (oldmems == NULL)
+               return NOTIFY_DONE;
+
        cgroup_lock();
        switch (action) {
        case MEM_ONLINE:
-       case MEM_OFFLINE:
+               *oldmems = top_cpuset.mems_allowed;
                mutex_lock(&callback_mutex);
                top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
                mutex_unlock(&callback_mutex);
-               if (action == MEM_OFFLINE)
-                       scan_for_empty_cpusets(&top_cpuset);
+               update_tasks_nodemask(&top_cpuset, oldmems, NULL);
+               break;
+       case MEM_OFFLINE:
+               /*
+                * needn't update top_cpuset.mems_allowed explicitly because
+                * scan_for_empty_cpusets() will update it.
+                */
+               scan_for_empty_cpusets(&top_cpuset);
                break;
        default:
                break;
        }
        cgroup_unlock();
+
+       NODEMASK_FREE(oldmems);
        return NOTIFY_OK;
 }
 #endif
index 1ed8ca18790c1e937208af47bed6695f4218858b..1b1129d0cce87077055704c78d4ae364d8fb4cc8 100644 (file)
@@ -364,7 +364,7 @@ struct cred *prepare_usermodehelper_creds(void)
 
        new = kmem_cache_alloc(cred_jar, GFP_ATOMIC);
        if (!new)
-               return NULL;
+               goto free_tgcred;
 
        kdebug("prepare_usermodehelper_creds() alloc %p", new);
 
@@ -397,6 +397,10 @@ struct cred *prepare_usermodehelper_creds(void)
 
 error:
        put_cred(new);
+free_tgcred:
+#ifdef CONFIG_KEYS
+       kfree(tgcred);
+#endif
        return NULL;
 }
 
index 3cb2c661bb781ab5468a54e58a106cdb14269a7b..31aa9332ef3f8d4f5447f72a3989cbfd0dc7c6df 100644 (file)
@@ -333,6 +333,12 @@ void __init free_early_partial(u64 start, u64 end)
        struct early_res *r;
        int i;
 
+       if (start == end)
+               return;
+
+       if (WARN_ONCE(start > end, "  wrong range [%#llx, %#llx]\n", start, end))
+               return;
+
 try_next:
        i = find_overlapped_early(start, end);
        if (i >= max_early_res)
index 42ec11b2af8af5205c09523a9b18b3bf6fdd98ef..b7091d5ca2f829ae61f0140ae6b1901213bfab62 100644 (file)
@@ -359,6 +359,23 @@ static inline void mask_ack_irq(struct irq_desc *desc, int irq)
                if (desc->chip->ack)
                        desc->chip->ack(irq);
        }
+       desc->status |= IRQ_MASKED;
+}
+
+static inline void mask_irq(struct irq_desc *desc, int irq)
+{
+       if (desc->chip->mask) {
+               desc->chip->mask(irq);
+               desc->status |= IRQ_MASKED;
+       }
+}
+
+static inline void unmask_irq(struct irq_desc *desc, int irq)
+{
+       if (desc->chip->unmask) {
+               desc->chip->unmask(irq);
+               desc->status &= ~IRQ_MASKED;
+       }
 }
 
 /*
@@ -484,10 +501,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
        raw_spin_lock(&desc->lock);
        desc->status &= ~IRQ_INPROGRESS;
 
-       if (unlikely(desc->status & IRQ_ONESHOT))
-               desc->status |= IRQ_MASKED;
-       else if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
-               desc->chip->unmask(irq);
+       if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT)))
+               unmask_irq(desc, irq);
 out_unlock:
        raw_spin_unlock(&desc->lock);
 }
@@ -524,8 +539,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
        action = desc->action;
        if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
                desc->status |= IRQ_PENDING;
-               if (desc->chip->mask)
-                       desc->chip->mask(irq);
+               mask_irq(desc, irq);
                goto out;
        }
 
@@ -593,7 +607,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
                irqreturn_t action_ret;
 
                if (unlikely(!action)) {
-                       desc->chip->mask(irq);
+                       mask_irq(desc, irq);
                        goto out_unlock;
                }
 
@@ -605,8 +619,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
                if (unlikely((desc->status &
                               (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
                              (IRQ_PENDING | IRQ_MASKED))) {
-                       desc->chip->unmask(irq);
-                       desc->status &= ~IRQ_MASKED;
+                       unmask_irq(desc, irq);
                }
 
                desc->status &= ~IRQ_PENDING;
@@ -716,7 +729,7 @@ set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
        __set_irq_handler(irq, handle, 0, name);
 }
 
-void __init set_irq_noprobe(unsigned int irq)
+void set_irq_noprobe(unsigned int irq)
 {
        struct irq_desc *desc = irq_to_desc(irq);
        unsigned long flags;
@@ -731,7 +744,7 @@ void __init set_irq_noprobe(unsigned int irq)
        raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
 
-void __init set_irq_probe(unsigned int irq)
+void set_irq_probe(unsigned int irq)
 {
        struct irq_desc *desc = irq_to_desc(irq);
        unsigned long flags;
index eb6078ca60c7f548a052aa42c247dbb8b24d9620..398fda155f6e26dd72dd1fa00805b1383c156a5d 100644 (file)
@@ -382,6 +382,7 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
 {
        struct irq_desc *desc = irq_to_desc(irq);
        struct irqaction *action;
+       unsigned long flags;
 
        if (!desc)
                return 0;
@@ -389,11 +390,14 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
        if (desc->status & IRQ_NOREQUEST)
                return 0;
 
+       raw_spin_lock_irqsave(&desc->lock, flags);
        action = desc->action;
        if (action)
                if (irqflags & action->flags & IRQF_SHARED)
                        action = NULL;
 
+       raw_spin_unlock_irqrestore(&desc->lock, flags);
+
        return !action;
 }
 
@@ -483,8 +487,26 @@ static int irq_wait_for_interrupt(struct irqaction *action)
  */
 static void irq_finalize_oneshot(unsigned int irq, struct irq_desc *desc)
 {
+again:
        chip_bus_lock(irq, desc);
        raw_spin_lock_irq(&desc->lock);
+
+       /*
+        * Implausible though it may be we need to protect us against
+        * the following scenario:
+        *
+        * The thread is faster done than the hard interrupt handler
+        * on the other CPU. If we unmask the irq line then the
+        * interrupt can come in again and masks the line, leaves due
+        * to IRQ_INPROGRESS and the irq line is masked forever.
+        */
+       if (unlikely(desc->status & IRQ_INPROGRESS)) {
+               raw_spin_unlock_irq(&desc->lock);
+               chip_bus_sync_unlock(irq, desc);
+               cpu_relax();
+               goto again;
+       }
+
        if (!(desc->status & IRQ_DISABLED) && (desc->status & IRQ_MASKED)) {
                desc->status &= ~IRQ_MASKED;
                desc->chip->unmask(irq);
index 761fdd2b3034ae87272578fe1314680af5c0d71f..11f3515ca83f6af2b4614d11ac429c2fdf56bb4f 100644 (file)
@@ -69,9 +69,16 @@ struct kgdb_state {
        struct pt_regs          *linux_regs;
 };
 
+/* Exception state values */
+#define DCPU_WANT_MASTER 0x1 /* Waiting to become a master kgdb cpu */
+#define DCPU_NEXT_MASTER 0x2 /* Transition from one master cpu to another */
+#define DCPU_IS_SLAVE    0x4 /* Slave cpu enter exception */
+#define DCPU_SSTEP       0x8 /* CPU is single stepping */
+
 static struct debuggerinfo_struct {
        void                    *debuggerinfo;
        struct task_struct      *task;
+       int                     exception_state;
 } kgdb_info[NR_CPUS];
 
 /**
@@ -391,27 +398,22 @@ int kgdb_mem2hex(char *mem, char *buf, int count)
 
 /*
  * Copy the binary array pointed to by buf into mem.  Fix $, #, and
- * 0x7d escaped with 0x7d.  Return a pointer to the character after
- * the last byte written.
+ * 0x7d escaped with 0x7d. Return -EFAULT on failure or 0 on success.
+ * The input buf is overwitten with the result to write to mem.
  */
 static int kgdb_ebin2mem(char *buf, char *mem, int count)
 {
-       int err = 0;
-       char c;
+       int size = 0;
+       char *c = buf;
 
        while (count-- > 0) {
-               c = *buf++;
-               if (c == 0x7d)
-                       c = *buf++ ^ 0x20;
-
-               err = probe_kernel_write(mem, &c, 1);
-               if (err)
-                       break;
-
-               mem++;
+               c[size] = *buf++;
+               if (c[size] == 0x7d)
+                       c[size] = *buf++ ^ 0x20;
+               size++;
        }
 
-       return err;
+       return probe_kernel_write(mem, c, size);
 }
 
 /*
@@ -562,49 +564,6 @@ static struct task_struct *getthread(struct pt_regs *regs, int tid)
        return find_task_by_pid_ns(tid, &init_pid_ns);
 }
 
-/*
- * CPU debug state control:
- */
-
-#ifdef CONFIG_SMP
-static void kgdb_wait(struct pt_regs *regs)
-{
-       unsigned long flags;
-       int cpu;
-
-       local_irq_save(flags);
-       cpu = raw_smp_processor_id();
-       kgdb_info[cpu].debuggerinfo = regs;
-       kgdb_info[cpu].task = current;
-       /*
-        * Make sure the above info reaches the primary CPU before
-        * our cpu_in_kgdb[] flag setting does:
-        */
-       smp_wmb();
-       atomic_set(&cpu_in_kgdb[cpu], 1);
-
-       /* Disable any cpu specific hw breakpoints */
-       kgdb_disable_hw_debug(regs);
-
-       /* Wait till primary CPU is done with debugging */
-       while (atomic_read(&passive_cpu_wait[cpu]))
-               cpu_relax();
-
-       kgdb_info[cpu].debuggerinfo = NULL;
-       kgdb_info[cpu].task = NULL;
-
-       /* fix up hardware debug registers on local cpu */
-       if (arch_kgdb_ops.correct_hw_break)
-               arch_kgdb_ops.correct_hw_break();
-
-       /* Signal the primary CPU that we are done: */
-       atomic_set(&cpu_in_kgdb[cpu], 0);
-       touch_softlockup_watchdog_sync();
-       clocksource_touch_watchdog();
-       local_irq_restore(flags);
-}
-#endif
-
 /*
  * Some architectures need cache flushes when we set/clear a
  * breakpoint:
@@ -1400,34 +1359,13 @@ static int kgdb_reenter_check(struct kgdb_state *ks)
        return 1;
 }
 
-/*
- * kgdb_handle_exception() - main entry point from a kernel exception
- *
- * Locking hierarchy:
- *     interface locks, if any (begin_session)
- *     kgdb lock (kgdb_active)
- */
-int
-kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
+static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs)
 {
-       struct kgdb_state kgdb_var;
-       struct kgdb_state *ks = &kgdb_var;
        unsigned long flags;
        int sstep_tries = 100;
        int error = 0;
        int i, cpu;
-
-       ks->cpu                 = raw_smp_processor_id();
-       ks->ex_vector           = evector;
-       ks->signo               = signo;
-       ks->ex_vector           = evector;
-       ks->err_code            = ecode;
-       ks->kgdb_usethreadid    = 0;
-       ks->linux_regs          = regs;
-
-       if (kgdb_reenter_check(ks))
-               return 0; /* Ouch, double exception ! */
-
+       int trace_on = 0;
 acquirelock:
        /*
         * Interrupts will be restored by the 'trap return' code, except when
@@ -1435,13 +1373,43 @@ acquirelock:
         */
        local_irq_save(flags);
 
-       cpu = raw_smp_processor_id();
+       cpu = ks->cpu;
+       kgdb_info[cpu].debuggerinfo = regs;
+       kgdb_info[cpu].task = current;
+       /*
+        * Make sure the above info reaches the primary CPU before
+        * our cpu_in_kgdb[] flag setting does:
+        */
+       atomic_inc(&cpu_in_kgdb[cpu]);
 
        /*
-        * Acquire the kgdb_active lock:
+        * CPU will loop if it is a slave or request to become a kgdb
+        * master cpu and acquire the kgdb_active lock:
         */
-       while (atomic_cmpxchg(&kgdb_active, -1, cpu) != -1)
+       while (1) {
+               if (kgdb_info[cpu].exception_state & DCPU_WANT_MASTER) {
+                       if (atomic_cmpxchg(&kgdb_active, -1, cpu) == cpu)
+                               break;
+               } else if (kgdb_info[cpu].exception_state & DCPU_IS_SLAVE) {
+                       if (!atomic_read(&passive_cpu_wait[cpu]))
+                               goto return_normal;
+               } else {
+return_normal:
+                       /* Return to normal operation by executing any
+                        * hw breakpoint fixup.
+                        */
+                       if (arch_kgdb_ops.correct_hw_break)
+                               arch_kgdb_ops.correct_hw_break();
+                       if (trace_on)
+                               tracing_on();
+                       atomic_dec(&cpu_in_kgdb[cpu]);
+                       touch_softlockup_watchdog_sync();
+                       clocksource_touch_watchdog();
+                       local_irq_restore(flags);
+                       return 0;
+               }
                cpu_relax();
+       }
 
        /*
         * For single stepping, try to only enter on the processor
@@ -1475,9 +1443,6 @@ acquirelock:
        if (kgdb_io_ops->pre_exception)
                kgdb_io_ops->pre_exception();
 
-       kgdb_info[ks->cpu].debuggerinfo = ks->linux_regs;
-       kgdb_info[ks->cpu].task = current;
-
        kgdb_disable_hw_debug(ks->linux_regs);
 
        /*
@@ -1486,15 +1451,9 @@ acquirelock:
         */
        if (!kgdb_single_step) {
                for (i = 0; i < NR_CPUS; i++)
-                       atomic_set(&passive_cpu_wait[i], 1);
+                       atomic_inc(&passive_cpu_wait[i]);
        }
 
-       /*
-        * spin_lock code is good enough as a barrier so we don't
-        * need one here:
-        */
-       atomic_set(&cpu_in_kgdb[ks->cpu], 1);
-
 #ifdef CONFIG_SMP
        /* Signal the other CPUs to enter kgdb_wait() */
        if ((!kgdb_single_step) && kgdb_do_roundup)
@@ -1518,6 +1477,9 @@ acquirelock:
        kgdb_single_step = 0;
        kgdb_contthread = current;
        exception_level = 0;
+       trace_on = tracing_is_on();
+       if (trace_on)
+               tracing_off();
 
        /* Talk to debugger with gdbserial protocol */
        error = gdb_serial_stub(ks);
@@ -1526,13 +1488,11 @@ acquirelock:
        if (kgdb_io_ops->post_exception)
                kgdb_io_ops->post_exception();
 
-       kgdb_info[ks->cpu].debuggerinfo = NULL;
-       kgdb_info[ks->cpu].task = NULL;
-       atomic_set(&cpu_in_kgdb[ks->cpu], 0);
+       atomic_dec(&cpu_in_kgdb[ks->cpu]);
 
        if (!kgdb_single_step) {
                for (i = NR_CPUS-1; i >= 0; i--)
-                       atomic_set(&passive_cpu_wait[i], 0);
+                       atomic_dec(&passive_cpu_wait[i]);
                /*
                 * Wait till all the CPUs have quit
                 * from the debugger.
@@ -1551,6 +1511,8 @@ kgdb_restore:
                else
                        kgdb_sstep_pid = 0;
        }
+       if (trace_on)
+               tracing_on();
        /* Free kgdb_active */
        atomic_set(&kgdb_active, -1);
        touch_softlockup_watchdog_sync();
@@ -1560,13 +1522,52 @@ kgdb_restore:
        return error;
 }
 
+/*
+ * kgdb_handle_exception() - main entry point from a kernel exception
+ *
+ * Locking hierarchy:
+ *     interface locks, if any (begin_session)
+ *     kgdb lock (kgdb_active)
+ */
+int
+kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
+{
+       struct kgdb_state kgdb_var;
+       struct kgdb_state *ks = &kgdb_var;
+       int ret;
+
+       ks->cpu                 = raw_smp_processor_id();
+       ks->ex_vector           = evector;
+       ks->signo               = signo;
+       ks->ex_vector           = evector;
+       ks->err_code            = ecode;
+       ks->kgdb_usethreadid    = 0;
+       ks->linux_regs          = regs;
+
+       if (kgdb_reenter_check(ks))
+               return 0; /* Ouch, double exception ! */
+       kgdb_info[ks->cpu].exception_state |= DCPU_WANT_MASTER;
+       ret = kgdb_cpu_enter(ks, regs);
+       kgdb_info[ks->cpu].exception_state &= ~DCPU_WANT_MASTER;
+       return ret;
+}
+
 int kgdb_nmicallback(int cpu, void *regs)
 {
 #ifdef CONFIG_SMP
+       struct kgdb_state kgdb_var;
+       struct kgdb_state *ks = &kgdb_var;
+
+       memset(ks, 0, sizeof(struct kgdb_state));
+       ks->cpu                 = cpu;
+       ks->linux_regs          = regs;
+
        if (!atomic_read(&cpu_in_kgdb[cpu]) &&
-                       atomic_read(&kgdb_active) != cpu &&
-                       atomic_read(&cpu_in_kgdb[atomic_read(&kgdb_active)])) {
-               kgdb_wait((struct pt_regs *)regs);
+           atomic_read(&kgdb_active) != -1 &&
+           atomic_read(&kgdb_active) != cpu) {
+               kgdb_info[cpu].exception_state |= DCPU_IS_SLAVE;
+               kgdb_cpu_enter(ks, regs);
+               kgdb_info[cpu].exception_state &= ~DCPU_IS_SLAVE;
                return 0;
        }
 #endif
@@ -1742,11 +1743,11 @@ EXPORT_SYMBOL_GPL(kgdb_unregister_io_module);
  */
 void kgdb_breakpoint(void)
 {
-       atomic_set(&kgdb_setting_breakpoint, 1);
+       atomic_inc(&kgdb_setting_breakpoint);
        wmb(); /* Sync point before breakpoint */
        arch_kgdb_breakpoint();
        wmb(); /* Sync point after breakpoint */
-       atomic_set(&kgdb_setting_breakpoint, 0);
+       atomic_dec(&kgdb_setting_breakpoint);
 }
 EXPORT_SYMBOL_GPL(kgdb_breakpoint);
 
index 82ed0ea15194caf27c72dd3a40d459731eb718df..83911c7801751dd847348145db20f4e3e40e33b6 100644 (file)
@@ -219,7 +219,7 @@ int kthreadd(void *unused)
        set_task_comm(tsk, "kthreadd");
        ignore_signals(tsk);
        set_cpus_allowed_ptr(tsk, cpu_all_mask);
-       set_mems_allowed(node_possible_map);
+       set_mems_allowed(node_states[N_HIGH_MEMORY]);
 
        current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG;
 
index 1a22dfd42df9b4089e9630f2635a425a26d4959b..bc7704b3a4431434e15bacb3127cfb9a5e1517a9 100644 (file)
@@ -1061,9 +1061,9 @@ static void check_thread_timers(struct task_struct *tsk,
        }
 }
 
-static void stop_process_timers(struct task_struct *tsk)
+static void stop_process_timers(struct signal_struct *sig)
 {
-       struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
+       struct thread_group_cputimer *cputimer = &sig->cputimer;
        unsigned long flags;
 
        if (!cputimer->running)
@@ -1072,6 +1072,10 @@ static void stop_process_timers(struct task_struct *tsk)
        spin_lock_irqsave(&cputimer->lock, flags);
        cputimer->running = 0;
        spin_unlock_irqrestore(&cputimer->lock, flags);
+
+       sig->cputime_expires.prof_exp = cputime_zero;
+       sig->cputime_expires.virt_exp = cputime_zero;
+       sig->cputime_expires.sched_exp = 0;
 }
 
 static u32 onecputick;
@@ -1133,7 +1137,7 @@ static void check_process_timers(struct task_struct *tsk,
            list_empty(&timers[CPUCLOCK_VIRT]) &&
            cputime_eq(sig->it[CPUCLOCK_VIRT].expires, cputime_zero) &&
            list_empty(&timers[CPUCLOCK_SCHED])) {
-               stop_process_timers(tsk);
+               stop_process_timers(sig);
                return;
        }
 
index 5ade1bdcf366a9e93789097ea99ba8aba9dceccc..71ae29052ab6c2275c6f48239b56cdd4be4cba33 100644 (file)
@@ -88,12 +88,11 @@ static int try_to_freeze_tasks(bool sig_only)
                printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
                                "(%d tasks refusing to freeze):\n",
                                elapsed_csecs / 100, elapsed_csecs % 100, todo);
-               show_state();
                read_lock(&tasklist_lock);
                do_each_thread(g, p) {
                        task_lock(p);
                        if (freezing(p) && !freezer_should_skip(p))
-                               printk(KERN_ERR " %s\n", p->comm);
+                               sched_show_task(p);
                        cancel_freezing(p);
                        task_unlock(p);
                } while_each_thread(g, p);
@@ -145,7 +144,7 @@ static void thaw_tasks(bool nosig_only)
                if (nosig_only && should_send_signal(p))
                        continue;
 
-               if (cgroup_frozen(p))
+               if (cgroup_freezing_or_frozen(p))
                        continue;
 
                thaw_process(p);
index f1125c1a6321950030c42e8e5e2df2689d068a94..63fe25433980a943096634841d0ce5ff0ed33f7f 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
+#include <linux/hardirq.h>
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 static struct lock_class_key rcu_lock_key;
@@ -66,6 +67,28 @@ EXPORT_SYMBOL_GPL(rcu_sched_lock_map);
 int rcu_scheduler_active __read_mostly;
 EXPORT_SYMBOL_GPL(rcu_scheduler_active);
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+
+/**
+ * rcu_read_lock_bh_held - might we be in RCU-bh read-side critical section?
+ *
+ * Check for bottom half being disabled, which covers both the
+ * CONFIG_PROVE_RCU and not cases.  Note that if someone uses
+ * rcu_read_lock_bh(), but then later enables BH, lockdep (if enabled)
+ * will show the situation.
+ *
+ * Check debug_lockdep_rcu_enabled() to prevent false positives during boot.
+ */
+int rcu_read_lock_bh_held(void)
+{
+       if (!debug_lockdep_rcu_enabled())
+               return 1;
+       return in_softirq();
+}
+EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held);
+
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
 /*
  * This function is invoked towards the end of the scheduler's initialization
  * process.  Before this is called, the idle task might contain
index 2d5be5d9bf5f2937fecaf881236cd48f13078fab..9c358e26353427b5a553e900014359c80c4eced2 100644 (file)
@@ -219,19 +219,34 @@ void release_child_resources(struct resource *r)
 }
 
 /**
- * request_resource - request and reserve an I/O or memory resource
+ * request_resource_conflict - request and reserve an I/O or memory resource
  * @root: root resource descriptor
  * @new: resource descriptor desired by caller
  *
- * Returns 0 for success, negative error code on error.
+ * Returns 0 for success, conflict resource on error.
  */
-int request_resource(struct resource *root, struct resource *new)
+struct resource *request_resource_conflict(struct resource *root, struct resource *new)
 {
        struct resource *conflict;
 
        write_lock(&resource_lock);
        conflict = __request_resource(root, new);
        write_unlock(&resource_lock);
+       return conflict;
+}
+
+/**
+ * request_resource - request and reserve an I/O or memory resource
+ * @root: root resource descriptor
+ * @new: resource descriptor desired by caller
+ *
+ * Returns 0 for success, negative error code on error.
+ */
+int request_resource(struct resource *root, struct resource *new)
+{
+       struct resource *conflict;
+
+       conflict = request_resource_conflict(root, new);
        return conflict ? -EBUSY : 0;
 }
 
@@ -474,25 +489,40 @@ static struct resource * __insert_resource(struct resource *parent, struct resou
 }
 
 /**
- * insert_resource - Inserts a resource in the resource tree
+ * insert_resource_conflict - Inserts resource in the resource tree
  * @parent: parent of the new resource
  * @new: new resource to insert
  *
- * Returns 0 on success, -EBUSY if the resource can't be inserted.
+ * Returns 0 on success, conflict resource if the resource can't be inserted.
  *
- * This function is equivalent to request_resource when no conflict
+ * This function is equivalent to request_resource_conflict when no conflict
  * happens. If a conflict happens, and the conflicting resources
  * entirely fit within the range of the new resource, then the new
  * resource is inserted and the conflicting resources become children of
  * the new resource.
  */
-int insert_resource(struct resource *parent, struct resource *new)
+struct resource *insert_resource_conflict(struct resource *parent, struct resource *new)
 {
        struct resource *conflict;
 
        write_lock(&resource_lock);
        conflict = __insert_resource(parent, new);
        write_unlock(&resource_lock);
+       return conflict;
+}
+
+/**
+ * insert_resource - Inserts a resource in the resource tree
+ * @parent: parent of the new resource
+ * @new: new resource to insert
+ *
+ * Returns 0 on success, -EBUSY if the resource can't be inserted.
+ */
+int insert_resource(struct resource *parent, struct resource *new)
+{
+       struct resource *conflict;
+
+       conflict = insert_resource_conflict(parent, new);
        return conflict ? -EBUSY : 0;
 }
 
index 9ab3cd7858d38001cc4ed0586bf187438e685cd7..49d2fa7b687a6cd9956e5d7179ab26822bcff6f1 100644 (file)
@@ -2650,7 +2650,7 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
 {
        unsigned long flags;
        struct rq *rq;
-       int cpu = get_cpu();
+       int cpu __maybe_unused = get_cpu();
 
 #ifdef CONFIG_SMP
        /*
@@ -4902,7 +4902,9 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
        int ret;
        cpumask_var_t mask;
 
-       if (len < cpumask_size())
+       if (len < nr_cpu_ids)
+               return -EINVAL;
+       if (len & (sizeof(unsigned long)-1))
                return -EINVAL;
 
        if (!alloc_cpumask_var(&mask, GFP_KERNEL))
@@ -4910,10 +4912,12 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
 
        ret = sched_getaffinity(pid, mask);
        if (ret == 0) {
-               if (copy_to_user(user_mask_ptr, mask, cpumask_size()))
+               size_t retlen = min_t(size_t, len, cpumask_size());
+
+               if (copy_to_user(user_mask_ptr, mask, retlen))
                        ret = -EFAULT;
                else
-                       ret = cpumask_size();
+                       ret = retlen;
        }
        free_cpumask_var(mask);
 
index 7494bbf5a27035fcd80cb7b9bf4814452e37e9a8..7d3f4fa9ef4f3b15eeee03b4ed3f3684819c8cf8 100644 (file)
@@ -637,7 +637,7 @@ int delayed_slow_work_enqueue(struct delayed_slow_work *dwork,
                        goto cancelled;
 
                /* the timer holds a reference whilst it is pending */
-               ret = work->ops->get_ref(work);
+               ret = slow_work_get_ref(work);
                if (ret < 0)
                        goto cant_get_ref;
 
index 321f3c59d7324f4100629b55111bb02b05c70161..a29ebd1ef41df7a4295e3173848e5239c05caa60 100644 (file)
@@ -43,28 +43,28 @@ extern void slow_work_new_thread_desc(struct slow_work *, struct seq_file *);
  */
 static inline void slow_work_set_thread_pid(int id, pid_t pid)
 {
-#ifdef CONFIG_SLOW_WORK_PROC
+#ifdef CONFIG_SLOW_WORK_DEBUG
        slow_work_pids[id] = pid;
 #endif
 }
 
 static inline void slow_work_mark_time(struct slow_work *work)
 {
-#ifdef CONFIG_SLOW_WORK_PROC
+#ifdef CONFIG_SLOW_WORK_DEBUG
        work->mark = CURRENT_TIME;
 #endif
 }
 
 static inline void slow_work_begin_exec(int id, struct slow_work *work)
 {
-#ifdef CONFIG_SLOW_WORK_PROC
+#ifdef CONFIG_SLOW_WORK_DEBUG
        slow_work_execs[id] = work;
 #endif
 }
 
 static inline void slow_work_end_exec(int id, struct slow_work *work)
 {
-#ifdef CONFIG_SLOW_WORK_PROC
+#ifdef CONFIG_SLOW_WORK_DEBUG
        write_lock(&slow_work_execs_lock);
        slow_work_execs[id] = NULL;
        write_unlock(&slow_work_execs_lock);
index 0d4c7898ab805dd868880e7deca2d0d69d88fc67..4b493f67dcb562c183258115619539f3a68cd62a 100644 (file)
@@ -155,11 +155,11 @@ void softlockup_tick(void)
         * Wake up the high-prio watchdog task twice per
         * threshold timespan.
         */
-       if (now > touch_ts + softlockup_thresh/2)
+       if (time_after(now - softlockup_thresh/2, touch_ts))
                wake_up_process(per_cpu(softlockup_watchdog, this_cpu));
 
        /* Warn about unreasonable delays: */
-       if (now <= (touch_ts + softlockup_thresh))
+       if (time_before_eq(now - softlockup_thresh, touch_ts))
                return;
 
        per_cpu(softlockup_print_ts, this_cpu) = touch_ts;
index 0a8a213016f005bfc51632b22b668f037a75c3f2..aada0e52680ace6cc7d5e09a111a3879c1c6bda3 100644 (file)
 
 #include "tick-internal.h"
 
+/* Limit min_delta to a jiffie */
+#define MIN_DELTA_LIMIT                (NSEC_PER_SEC / HZ)
+
+static int tick_increase_min_delta(struct clock_event_device *dev)
+{
+       /* Nothing to do if we already reached the limit */
+       if (dev->min_delta_ns >= MIN_DELTA_LIMIT)
+               return -ETIME;
+
+       if (dev->min_delta_ns < 5000)
+               dev->min_delta_ns = 5000;
+       else
+               dev->min_delta_ns += dev->min_delta_ns >> 1;
+
+       if (dev->min_delta_ns > MIN_DELTA_LIMIT)
+               dev->min_delta_ns = MIN_DELTA_LIMIT;
+
+       printk(KERN_WARNING "CE: %s increased min_delta_ns to %llu nsec\n",
+              dev->name ? dev->name : "?",
+              (unsigned long long) dev->min_delta_ns);
+       return 0;
+}
+
 /**
  * tick_program_event internal worker function
  */
@@ -37,23 +60,28 @@ int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires,
                if (!ret || !force)
                        return ret;
 
+               dev->retries++;
                /*
-                * We tried 2 times to program the device with the given
-                * min_delta_ns. If that's not working then we double it
+                * We tried 3 times to program the device with the given
+                * min_delta_ns. If that's not working then we increase it
                 * and emit a warning.
                 */
                if (++i > 2) {
                        /* Increase the min. delta and try again */
-                       if (!dev->min_delta_ns)
-                               dev->min_delta_ns = 5000;
-                       else
-                               dev->min_delta_ns += dev->min_delta_ns >> 1;
-
-                       printk(KERN_WARNING
-                              "CE: %s increasing min_delta_ns to %llu nsec\n",
-                              dev->name ? dev->name : "?",
-                              (unsigned long long) dev->min_delta_ns << 1);
-
+                       if (tick_increase_min_delta(dev)) {
+                               /*
+                                * Get out of the loop if min_delta_ns
+                                * hit the limit already. That's
+                                * better than staying here forever.
+                                *
+                                * We clear next_event so we have a
+                                * chance that the box survives.
+                                */
+                               printk(KERN_WARNING
+                                      "CE: Reprogramming failure. Giving up\n");
+                               dev->next_event.tv64 = KTIME_MAX;
+                               return -ETIME;
+                       }
                        i = 0;
                }
 
index 16736379a9caaba6320f32f3df6e94cb5a9abbda..39f6177fafac110d342d2cedcd093b7a736bfdc8 100644 (file)
@@ -818,7 +818,8 @@ void update_wall_time(void)
        shift = min(shift, maxshift);
        while (offset >= timekeeper.cycle_interval) {
                offset = logarithmic_accumulation(offset, shift);
-               shift--;
+               if(offset < timekeeper.cycle_interval<<shift)
+                       shift--;
        }
 
        /* correct the clock when NTP error is too big */
index bdfb8dd1050cfb64f4cca35f22b749b06a294dd1..1a4a7dd787779345eafb02bc5781973cf68a1d6a 100644 (file)
@@ -228,6 +228,7 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu)
        SEQ_printf(m, " event_handler:  ");
        print_name_offset(m, dev->event_handler);
        SEQ_printf(m, "\n");
+       SEQ_printf(m, " retries:        %lu\n", dev->retries);
 }
 
 static void timer_list_show_tickdevices(struct seq_file *m)
@@ -257,7 +258,7 @@ static int timer_list_show(struct seq_file *m, void *v)
        u64 now = ktime_to_ns(ktime_get());
        int cpu;
 
-       SEQ_printf(m, "Timer List Version: v0.5\n");
+       SEQ_printf(m, "Timer List Version: v0.6\n");
        SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES);
        SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now);
 
index c61a7949387f93e69b1a4979eff1a03c7e7131b4..fc965eae0e87bf43a238d5c018f12726feb2dc4d 100644 (file)
@@ -880,6 +880,7 @@ int try_to_del_timer_sync(struct timer_list *timer)
        if (base->running_timer == timer)
                goto out;
 
+       timer_stats_timer_clear_start_info(timer);
        ret = 0;
        if (timer_pending(timer)) {
                detach_timer(timer, 1);
index 05a9f83b8819c39dcc03c76f737eaaf5ae7bbfe7..d1187ef20caf914048fb897dc5c63f1b302edbf6 100644 (file)
@@ -207,6 +207,14 @@ EXPORT_SYMBOL_GPL(tracing_is_on);
 #define RB_MAX_SMALL_DATA      (RB_ALIGNMENT * RINGBUF_TYPE_DATA_TYPE_LEN_MAX)
 #define RB_EVNT_MIN_SIZE       8U      /* two 32bit words */
 
+#if !defined(CONFIG_64BIT) || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+# define RB_FORCE_8BYTE_ALIGNMENT      0
+# define RB_ARCH_ALIGNMENT             RB_ALIGNMENT
+#else
+# define RB_FORCE_8BYTE_ALIGNMENT      1
+# define RB_ARCH_ALIGNMENT             8U
+#endif
+
 /* define RINGBUF_TYPE_DATA for 'case RINGBUF_TYPE_DATA:' */
 #define RINGBUF_TYPE_DATA 0 ... RINGBUF_TYPE_DATA_TYPE_LEN_MAX
 
@@ -1547,7 +1555,7 @@ rb_update_event(struct ring_buffer_event *event,
 
        case 0:
                length -= RB_EVNT_HDR_SIZE;
-               if (length > RB_MAX_SMALL_DATA)
+               if (length > RB_MAX_SMALL_DATA || RB_FORCE_8BYTE_ALIGNMENT)
                        event->array[0] = length;
                else
                        event->type_len = DIV_ROUND_UP(length, RB_ALIGNMENT);
@@ -1722,11 +1730,11 @@ static unsigned rb_calculate_event_length(unsigned length)
        if (!length)
                length = 1;
 
-       if (length > RB_MAX_SMALL_DATA)
+       if (length > RB_MAX_SMALL_DATA || RB_FORCE_8BYTE_ALIGNMENT)
                length += sizeof(event.array[0]);
 
        length += RB_EVNT_HDR_SIZE;
-       length = ALIGN(length, RB_ALIGNMENT);
+       length = ALIGN(length, RB_ARCH_ALIGNMENT);
 
        return length;
 }
index 8e5ec5e1ab91f11505ac1a7589bb196ff10e1147..1fafb4b99c9bb30c37e151a2db441e3cc9c5fb5f 100644 (file)
@@ -103,7 +103,8 @@ config HEADERS_CHECK
 
 config DEBUG_SECTION_MISMATCH
        bool "Enable full Section mismatch analysis"
-       depends on UNDEFINED
+       depends on UNDEFINED || (BLACKFIN)
+       default y
        # This option is on purpose disabled for now.
        # It will be enabled when we are down to a reasonable number
        # of section mismatch warnings (< 10 for an allyesconfig build)
index d7c791ef00367e27ac65f4a51da946abbd45d271..9b134460b0160aad89ca87b3f42080090c52de24 100644 (file)
@@ -180,19 +180,12 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end)
        end_aligned = end & ~(BITS_PER_LONG - 1);
 
        if (end_aligned <= start_aligned) {
-#if 1
-               printk(KERN_DEBUG " %lx - %lx\n", start, end);
-#endif
                for (i = start; i < end; i++)
                        __free_pages_bootmem(pfn_to_page(i), 0);
 
                return;
        }
 
-#if 1
-       printk(KERN_DEBUG " %lx %lx - %lx %lx\n",
-                start, start_aligned, end_aligned, end);
-#endif
        for (i = start; i < start_aligned; i++)
                __free_pages_bootmem(pfn_to_page(i), 0);
 
@@ -428,9 +421,6 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 {
 #ifdef CONFIG_NO_BOOTMEM
        free_early(physaddr, physaddr + size);
-#if 0
-       printk(KERN_DEBUG "free %lx %lx\n", physaddr, size);
-#endif
 #else
        unsigned long start, end;
 
@@ -456,9 +446,6 @@ void __init free_bootmem(unsigned long addr, unsigned long size)
 {
 #ifdef CONFIG_NO_BOOTMEM
        free_early(addr, addr + size);
-#if 0
-       printk(KERN_DEBUG "free %lx %lx\n", addr, size);
-#endif
 #else
        unsigned long start, end;
 
index a93f1b7f508cde17cb0b41f7183641dcfdb7a26f..8cdfc2a1e8bffbdfed7e7d92842552e3ee41aa6f 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -751,7 +751,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
                 * page
                 */
                if (page_mapcount(page) + 1 + swapped != page_count(page)) {
-                       set_pte_at_notify(mm, addr, ptep, entry);
+                       set_pte_at(mm, addr, ptep, entry);
                        goto out_unlock;
                }
                entry = pte_wrprotect(entry);
index 7973b5221fb8e86b816c8e9667aff5f6c5fa7e21..9ed760dc74481a7436e3ab7b084ff8abd233ee01 100644 (file)
@@ -3691,8 +3691,10 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
        else
                mem = vmalloc(size);
 
-       if (mem)
-               memset(mem, 0, size);
+       if (!mem)
+               return NULL;
+
+       memset(mem, 0, size);
        mem->stat = alloc_percpu(struct mem_cgroup_stat_cpu);
        if (!mem->stat) {
                if (size < PAGE_SIZE)
@@ -3946,28 +3948,6 @@ one_by_one:
        }
        return ret;
 }
-#else  /* !CONFIG_MMU */
-static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
-                               struct cgroup *cgroup,
-                               struct task_struct *p,
-                               bool threadgroup)
-{
-       return 0;
-}
-static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss,
-                               struct cgroup *cgroup,
-                               struct task_struct *p,
-                               bool threadgroup)
-{
-}
-static void mem_cgroup_move_task(struct cgroup_subsys *ss,
-                               struct cgroup *cont,
-                               struct cgroup *old_cont,
-                               struct task_struct *p,
-                               bool threadgroup)
-{
-}
-#endif
 
 /**
  * is_target_pte_for_mc - check a pte whether it is valid for move charge
@@ -4330,6 +4310,28 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
        }
        mem_cgroup_clear_mc();
 }
+#else  /* !CONFIG_MMU */
+static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
+                               struct cgroup *cgroup,
+                               struct task_struct *p,
+                               bool threadgroup)
+{
+       return 0;
+}
+static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss,
+                               struct cgroup *cgroup,
+                               struct task_struct *p,
+                               bool threadgroup)
+{
+}
+static void mem_cgroup_move_task(struct cgroup_subsys *ss,
+                               struct cgroup *cont,
+                               struct cgroup *old_cont,
+                               struct task_struct *p,
+                               bool threadgroup)
+{
+}
+#endif
 
 struct cgroup_subsys mem_cgroup_subsys = {
        .name = "memory",
index 5b7f2002e54b17e8d9b67e75cff0aaa06c9296b4..bc9ba5a1f5b965516fdf5edccc4d10e0998dc3c1 100644 (file)
@@ -130,6 +130,7 @@ void __sync_task_rss_stat(struct task_struct *task, struct mm_struct *mm)
 
        for (i = 0; i < NR_MM_COUNTERS; i++) {
                if (task->rss_stat.count[i]) {
+                       BUG_ON(!mm);
                        add_mm_counter(mm, i, task->rss_stat.count[i]);
                        task->rss_stat.count[i] = 0;
                }
index 643f66e101878015cbea8b3dc9ac1eb948d2d702..8034abd3a1351700414ad7024c16da56774522fd 100644 (file)
@@ -806,9 +806,13 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
 
        err = 0;
        if (nmask) {
-               task_lock(current);
-               get_policy_nodemask(pol, nmask);
-               task_unlock(current);
+               if (mpol_store_user_nodemask(pol)) {
+                       *nmask = pol->w.user_nodemask;
+               } else {
+                       task_lock(current);
+                       get_policy_nodemask(pol, nmask);
+                       task_unlock(current);
+               }
        }
 
  out:
@@ -2195,8 +2199,8 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
                        char *rest = nodelist;
                        while (isdigit(*rest))
                                rest++;
-                       if (!*rest)
-                               err = 0;
+                       if (*rest)
+                               goto out;
                }
                break;
        case MPOL_INTERLEAVE:
@@ -2205,7 +2209,6 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
                 */
                if (!nodelist)
                        nodes = node_states[N_HIGH_MEMORY];
-               err = 0;
                break;
        case MPOL_LOCAL:
                /*
@@ -2215,11 +2218,19 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
                        goto out;
                mode = MPOL_PREFERRED;
                break;
-
-       /*
-        * case MPOL_BIND:    mpol_new() enforces non-empty nodemask.
-        * case MPOL_DEFAULT: mpol_new() enforces empty nodemask, ignores flags.
-        */
+       case MPOL_DEFAULT:
+               /*
+                * Insist on a empty nodelist
+                */
+               if (!nodelist)
+                       err = 0;
+               goto out;
+       case MPOL_BIND:
+               /*
+                * Insist on a nodelist
+                */
+               if (!nodelist)
+                       goto out;
        }
 
        mode_flags = 0;
@@ -2233,13 +2244,14 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
                else if (!strcmp(flags, "relative"))
                        mode_flags |= MPOL_F_RELATIVE_NODES;
                else
-                       err = 1;
+                       goto out;
        }
 
        new = mpol_new(mode, mode_flags, &nodes);
        if (IS_ERR(new))
-               err = 1;
-       else {
+               goto out;
+
+       {
                int ret;
                NODEMASK_SCRATCH(scratch);
                if (scratch) {
@@ -2250,13 +2262,15 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
                        ret = -ENOMEM;
                NODEMASK_SCRATCH_FREE(scratch);
                if (ret) {
-                       err = 1;
                        mpol_put(new);
-               } else if (no_context) {
-                       /* save for contextualization */
-                       new->w.user_nodemask = nodes;
+                       goto out;
                }
        }
+       err = 0;
+       if (no_context) {
+               /* save for contextualization */
+               new->w.user_nodemask = nodes;
+       }
 
 out:
        /* Restore string for error message */
index 0777654147c9d0e3fd0b676771dc5052bcab9455..9e82e937000e19f8210b10886457a3d82ee0870b 100644 (file)
@@ -53,6 +53,7 @@ void unuse_mm(struct mm_struct *mm)
        struct task_struct *tsk = current;
 
        task_lock(tsk);
+       sync_mm_rss(tsk, mm);
        tsk->mm = NULL;
        /* active_mm is still 'mm' */
        enter_lazy_tlb(mm, tsk);
index 605ace8982a8dcbc14ac061ab824166a16220180..63fa17d121f027ca5c75f09eab994db346316d2b 100644 (file)
@@ -146,7 +146,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                        (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
 
        for (i = 0; i < nr_pages; i++) {
-               vma = find_extend_vma(mm, start);
+               vma = find_vma(mm, start);
                if (!vma)
                        goto finish_or_fault;
 
@@ -162,7 +162,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                }
                if (vmas)
                        vmas[i] = vma;
-               start += PAGE_SIZE;
+               start = (start + PAGE_SIZE) & PAGE_MASK;
        }
 
        return i;
@@ -764,7 +764,7 @@ EXPORT_SYMBOL(find_vma);
  */
 struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
 {
-       return find_vma(mm, addr & PAGE_MASK);
+       return find_vma(mm, addr);
 }
 
 /*
@@ -1040,10 +1040,9 @@ static int do_mmap_shared_file(struct vm_area_struct *vma)
        if (ret != -ENOSYS)
                return ret;
 
-       /* getting an ENOSYS error indicates that direct mmap isn't
-        * possible (as opposed to tried but failed) so we'll fall
-        * through to making a private copy of the data and mapping
-        * that if we can */
+       /* getting -ENOSYS indicates that direct mmap isn't possible (as
+        * opposed to tried but failed) so we can only give a suitable error as
+        * it's not possible to make a private copy if MAP_SHARED was given */
        return -ENODEV;
 }
 
index 453512266ea1dd783dbc68f5e6b511dd64ec5ac5..db783d7af5a3cd41ab2695c0c7f326e5a266e3f2 100644 (file)
@@ -378,6 +378,8 @@ static void vlan_transfer_features(struct net_device *dev,
 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
        vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
 #endif
+       vlandev->real_num_tx_queues = dev->real_num_tx_queues;
+       BUG_ON(vlandev->real_num_tx_queues > vlandev->num_tx_queues);
 
        if (old_features != vlandev->features)
                netdev_features_change(vlandev);
index c0316e0ca6e854724ccb6dc07e1441dd697e7277..c584a0af77d3efaf436a1cc07413fcfa31f442e1 100644 (file)
@@ -11,7 +11,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
        if (netpoll_rx(skb))
                return NET_RX_DROP;
 
-       if (skb_bond_should_drop(skb))
+       if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
                goto drop;
 
        skb->skb_iif = skb->dev->ifindex;
@@ -83,7 +83,7 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
 {
        struct sk_buff *p;
 
-       if (skb_bond_should_drop(skb))
+       if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
                goto drop;
 
        skb->skb_iif = skb->dev->ifindex;
index 9e83272fc5b022e6a4b765888f06647ce0d92f67..2fd057c81bbf151b080ebf31681386a0ae0363dd 100644 (file)
@@ -361,6 +361,14 @@ static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb,
        return ret;
 }
 
+static u16 vlan_dev_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+       struct net_device *rdev = vlan_dev_info(dev)->real_dev;
+       const struct net_device_ops *ops = rdev->netdev_ops;
+
+       return ops->ndo_select_queue(rdev, skb);
+}
+
 static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu)
 {
        /* TODO: gotta make sure the underlying layer can handle it,
@@ -688,7 +696,8 @@ static const struct header_ops vlan_header_ops = {
        .parse   = eth_header_parse,
 };
 
-static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops;
+static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops,
+                   vlan_netdev_ops_sq, vlan_netdev_accel_ops_sq;
 
 static int vlan_dev_init(struct net_device *dev)
 {
@@ -722,11 +731,17 @@ static int vlan_dev_init(struct net_device *dev)
        if (real_dev->features & NETIF_F_HW_VLAN_TX) {
                dev->header_ops      = real_dev->header_ops;
                dev->hard_header_len = real_dev->hard_header_len;
-               dev->netdev_ops         = &vlan_netdev_accel_ops;
+               if (real_dev->netdev_ops->ndo_select_queue)
+                       dev->netdev_ops = &vlan_netdev_accel_ops_sq;
+               else
+                       dev->netdev_ops = &vlan_netdev_accel_ops;
        } else {
                dev->header_ops      = &vlan_header_ops;
                dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
-               dev->netdev_ops         = &vlan_netdev_ops;
+               if (real_dev->netdev_ops->ndo_select_queue)
+                       dev->netdev_ops = &vlan_netdev_ops_sq;
+               else
+                       dev->netdev_ops = &vlan_netdev_ops;
        }
 
        if (is_vlan_dev(real_dev))
@@ -865,6 +880,56 @@ static const struct net_device_ops vlan_netdev_accel_ops = {
 #endif
 };
 
+static const struct net_device_ops vlan_netdev_ops_sq = {
+       .ndo_select_queue       = vlan_dev_select_queue,
+       .ndo_change_mtu         = vlan_dev_change_mtu,
+       .ndo_init               = vlan_dev_init,
+       .ndo_uninit             = vlan_dev_uninit,
+       .ndo_open               = vlan_dev_open,
+       .ndo_stop               = vlan_dev_stop,
+       .ndo_start_xmit =  vlan_dev_hard_start_xmit,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = vlan_dev_set_mac_address,
+       .ndo_set_rx_mode        = vlan_dev_set_rx_mode,
+       .ndo_set_multicast_list = vlan_dev_set_rx_mode,
+       .ndo_change_rx_flags    = vlan_dev_change_rx_flags,
+       .ndo_do_ioctl           = vlan_dev_ioctl,
+       .ndo_neigh_setup        = vlan_dev_neigh_setup,
+       .ndo_get_stats          = vlan_dev_get_stats,
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+       .ndo_fcoe_ddp_setup     = vlan_dev_fcoe_ddp_setup,
+       .ndo_fcoe_ddp_done      = vlan_dev_fcoe_ddp_done,
+       .ndo_fcoe_enable        = vlan_dev_fcoe_enable,
+       .ndo_fcoe_disable       = vlan_dev_fcoe_disable,
+       .ndo_fcoe_get_wwn       = vlan_dev_fcoe_get_wwn,
+#endif
+};
+
+static const struct net_device_ops vlan_netdev_accel_ops_sq = {
+       .ndo_select_queue       = vlan_dev_select_queue,
+       .ndo_change_mtu         = vlan_dev_change_mtu,
+       .ndo_init               = vlan_dev_init,
+       .ndo_uninit             = vlan_dev_uninit,
+       .ndo_open               = vlan_dev_open,
+       .ndo_stop               = vlan_dev_stop,
+       .ndo_start_xmit =  vlan_dev_hwaccel_hard_start_xmit,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = vlan_dev_set_mac_address,
+       .ndo_set_rx_mode        = vlan_dev_set_rx_mode,
+       .ndo_set_multicast_list = vlan_dev_set_rx_mode,
+       .ndo_change_rx_flags    = vlan_dev_change_rx_flags,
+       .ndo_do_ioctl           = vlan_dev_ioctl,
+       .ndo_neigh_setup        = vlan_dev_neigh_setup,
+       .ndo_get_stats          = vlan_dev_get_stats,
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+       .ndo_fcoe_ddp_setup     = vlan_dev_fcoe_ddp_setup,
+       .ndo_fcoe_ddp_done      = vlan_dev_fcoe_ddp_done,
+       .ndo_fcoe_enable        = vlan_dev_fcoe_enable,
+       .ndo_fcoe_disable       = vlan_dev_fcoe_disable,
+       .ndo_fcoe_get_wwn       = vlan_dev_fcoe_get_wwn,
+#endif
+};
+
 void vlan_setup(struct net_device *dev)
 {
        ether_setup(dev);
index cafb55b0cea5ca290f0a2ac4fc5e73eac200ba5e..05fd125f74fe8c5a7981208e6c3389bffb75f118 100644 (file)
@@ -8,8 +8,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-struct class *bt_class = NULL;
-EXPORT_SYMBOL_GPL(bt_class);
+static struct class *bt_class;
 
 struct dentry *bt_debugfs = NULL;
 EXPORT_SYMBOL_GPL(bt_debugfs);
index 4db7ae2fe07dea0fcc12d142f072b8ebef5c6a58..7794a2e2adcea93128fc5fcf4ccf8a8e306af434 100644 (file)
@@ -40,6 +40,8 @@
 #include <linux/skbuff.h>
 #include <linux/list.h>
 #include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/crc16.h>
 #include <net/sock.h>
@@ -2830,6 +2832,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                        int len = cmd->len - sizeof(*rsp);
                        char req[64];
 
+                       if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
+                               l2cap_send_disconn_req(conn, sk);
+                               goto done;
+                       }
+
                        /* throw out any old stored conf requests */
                        result = L2CAP_CONF_SUCCESS;
                        len = l2cap_parse_conf_rsp(sk, rsp->data,
@@ -3937,31 +3944,42 @@ drop:
        return 0;
 }
 
-static ssize_t l2cap_sysfs_show(struct class *dev,
-                               struct class_attribute *attr,
-                               char *buf)
+static int l2cap_debugfs_show(struct seq_file *f, void *p)
 {
        struct sock *sk;
        struct hlist_node *node;
-       char *str = buf;
 
        read_lock_bh(&l2cap_sk_list.lock);
 
        sk_for_each(sk, node, &l2cap_sk_list.head) {
                struct l2cap_pinfo *pi = l2cap_pi(sk);
 
-               str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
-                               batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
-                               sk->sk_state, __le16_to_cpu(pi->psm), pi->scid,
-                               pi->dcid, pi->imtu, pi->omtu, pi->sec_level);
+               seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
+                                       batostr(&bt_sk(sk)->src),
+                                       batostr(&bt_sk(sk)->dst),
+                                       sk->sk_state, __le16_to_cpu(pi->psm),
+                                       pi->scid, pi->dcid,
+                                       pi->imtu, pi->omtu, pi->sec_level);
        }
 
        read_unlock_bh(&l2cap_sk_list.lock);
 
-       return str - buf;
+       return 0;
 }
 
-static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL);
+static int l2cap_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, l2cap_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations l2cap_debugfs_fops = {
+       .open           = l2cap_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct dentry *l2cap_debugfs;
 
 static const struct proto_ops l2cap_sock_ops = {
        .family         = PF_BLUETOOTH,
@@ -4021,8 +4039,12 @@ static int __init l2cap_init(void)
                goto error;
        }
 
-       if (class_create_file(bt_class, &class_attr_l2cap) < 0)
-               BT_ERR("Failed to create L2CAP info file");
+       if (bt_debugfs) {
+               l2cap_debugfs = debugfs_create_file("l2cap", 0444,
+                                       bt_debugfs, NULL, &l2cap_debugfs_fops);
+               if (!l2cap_debugfs)
+                       BT_ERR("Failed to create L2CAP debug file");
+       }
 
        BT_INFO("L2CAP ver %s", VERSION);
        BT_INFO("L2CAP socket layer initialized");
@@ -4036,7 +4058,7 @@ error:
 
 static void __exit l2cap_exit(void)
 {
-       class_remove_file(bt_class, &class_attr_l2cap);
+       debugfs_remove(l2cap_debugfs);
 
        if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
                BT_ERR("L2CAP socket unregistration failed");
index db8a68e1a5ba835c11eff1f4d1f0525642e9ab41..13f114e8b0f9c1a584f05f47fd336a140a710e31 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/net.h>
 #include <linux/mutex.h>
 #include <linux/kthread.h>
@@ -2098,13 +2100,10 @@ static struct hci_cb rfcomm_cb = {
        .security_cfm   = rfcomm_security_cfm
 };
 
-static ssize_t rfcomm_dlc_sysfs_show(struct class *dev,
-                                    struct class_attribute *attr,
-                                    char *buf)
+static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x)
 {
        struct rfcomm_session *s;
        struct list_head *pp, *p;
-       char *str = buf;
 
        rfcomm_lock();
 
@@ -2114,18 +2113,32 @@ static ssize_t rfcomm_dlc_sysfs_show(struct class *dev,
                        struct sock *sk = s->sock->sk;
                        struct rfcomm_dlc *d = list_entry(pp, struct rfcomm_dlc, list);
 
-                       str += sprintf(str, "%s %s %ld %d %d %d %d\n",
-                                       batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
-                                       d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits);
+                       seq_printf(f, "%s %s %ld %d %d %d %d\n",
+                                               batostr(&bt_sk(sk)->src),
+                                               batostr(&bt_sk(sk)->dst),
+                                               d->state, d->dlci, d->mtu,
+                                               d->rx_credits, d->tx_credits);
                }
        }
 
        rfcomm_unlock();
 
-       return (str - buf);
+       return 0;
 }
 
-static CLASS_ATTR(rfcomm_dlc, S_IRUGO, rfcomm_dlc_sysfs_show, NULL);
+static int rfcomm_dlc_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, rfcomm_dlc_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations rfcomm_dlc_debugfs_fops = {
+       .open           = rfcomm_dlc_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct dentry *rfcomm_dlc_debugfs;
 
 /* ---- Initialization ---- */
 static int __init rfcomm_init(void)
@@ -2142,8 +2155,12 @@ static int __init rfcomm_init(void)
                goto unregister;
        }
 
-       if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0)
-               BT_ERR("Failed to create RFCOMM info file");
+       if (bt_debugfs) {
+               rfcomm_dlc_debugfs = debugfs_create_file("rfcomm_dlc", 0444,
+                               bt_debugfs, NULL, &rfcomm_dlc_debugfs_fops);
+               if (!rfcomm_dlc_debugfs)
+                       BT_ERR("Failed to create RFCOMM debug file");
+       }
 
        err = rfcomm_init_ttys();
        if (err < 0)
@@ -2171,7 +2188,7 @@ unregister:
 
 static void __exit rfcomm_exit(void)
 {
-       class_remove_file(bt_class, &class_attr_rfcomm_dlc);
+       debugfs_remove(rfcomm_dlc_debugfs);
 
        hci_unregister_cb(&rfcomm_cb);
 
index ca87d6ac6a2036dd7030c334c133e4326edcda62..7f439765403dced3bbbad74cb1a38dcec1a52327 100644 (file)
@@ -40,6 +40,8 @@
 #include <linux/skbuff.h>
 #include <linux/list.h>
 #include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
@@ -1061,28 +1063,38 @@ done:
        return result;
 }
 
-static ssize_t rfcomm_sock_sysfs_show(struct class *dev,
-                                     struct class_attribute *attr,
-                                     char *buf)
+static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p)
 {
        struct sock *sk;
        struct hlist_node *node;
-       char *str = buf;
 
        read_lock_bh(&rfcomm_sk_list.lock);
 
        sk_for_each(sk, node, &rfcomm_sk_list.head) {
-               str += sprintf(str, "%s %s %d %d\n",
-                               batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
+               seq_printf(f, "%s %s %d %d\n",
+                               batostr(&bt_sk(sk)->src),
+                               batostr(&bt_sk(sk)->dst),
                                sk->sk_state, rfcomm_pi(sk)->channel);
        }
 
        read_unlock_bh(&rfcomm_sk_list.lock);
 
-       return (str - buf);
+       return 0;
 }
 
-static CLASS_ATTR(rfcomm, S_IRUGO, rfcomm_sock_sysfs_show, NULL);
+static int rfcomm_sock_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, rfcomm_sock_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations rfcomm_sock_debugfs_fops = {
+       .open           = rfcomm_sock_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct dentry *rfcomm_sock_debugfs;
 
 static const struct proto_ops rfcomm_sock_ops = {
        .family         = PF_BLUETOOTH,
@@ -1122,8 +1134,12 @@ int __init rfcomm_init_sockets(void)
        if (err < 0)
                goto error;
 
-       if (class_create_file(bt_class, &class_attr_rfcomm) < 0)
-               BT_ERR("Failed to create RFCOMM info file");
+       if (bt_debugfs) {
+               rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444,
+                               bt_debugfs, NULL, &rfcomm_sock_debugfs_fops);
+               if (!rfcomm_sock_debugfs)
+                       BT_ERR("Failed to create RFCOMM debug file");
+       }
 
        BT_INFO("RFCOMM socket layer initialized");
 
@@ -1137,7 +1153,7 @@ error:
 
 void rfcomm_cleanup_sockets(void)
 {
-       class_remove_file(bt_class, &class_attr_rfcomm);
+       debugfs_remove(rfcomm_sock_debugfs);
 
        if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)
                BT_ERR("RFCOMM socket layer unregistration failed");
index f93b939539bc121da4448ce68e0e785b55b08416..e5b16b76b22e5619825a09c5b0870be74297bd73 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/socket.h>
 #include <linux/skbuff.h>
 #include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/list.h>
 #include <net/sock.h>
 
@@ -953,28 +955,36 @@ drop:
        return 0;
 }
 
-static ssize_t sco_sysfs_show(struct class *dev,
-                               struct class_attribute *attr,
-                               char *buf)
+static int sco_debugfs_show(struct seq_file *f, void *p)
 {
        struct sock *sk;
        struct hlist_node *node;
-       char *str = buf;
 
        read_lock_bh(&sco_sk_list.lock);
 
        sk_for_each(sk, node, &sco_sk_list.head) {
-               str += sprintf(str, "%s %s %d\n",
-                               batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
-                               sk->sk_state);
+               seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src),
+                               batostr(&bt_sk(sk)->dst), sk->sk_state);
        }
 
        read_unlock_bh(&sco_sk_list.lock);
 
-       return (str - buf);
+       return 0;
 }
 
-static CLASS_ATTR(sco, S_IRUGO, sco_sysfs_show, NULL);
+static int sco_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, sco_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations sco_debugfs_fops = {
+       .open           = sco_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct dentry *sco_debugfs;
 
 static const struct proto_ops sco_sock_ops = {
        .family         = PF_BLUETOOTH,
@@ -1032,8 +1042,12 @@ static int __init sco_init(void)
                goto error;
        }
 
-       if (class_create_file(bt_class, &class_attr_sco) < 0)
-               BT_ERR("Failed to create SCO info file");
+       if (bt_debugfs) {
+               sco_debugfs = debugfs_create_file("sco", 0444,
+                                       bt_debugfs, NULL, &sco_debugfs_fops);
+               if (!sco_debugfs)
+                       BT_ERR("Failed to create SCO debug file");
+       }
 
        BT_INFO("SCO (Voice Link) ver %s", VERSION);
        BT_INFO("SCO socket layer initialized");
@@ -1047,7 +1061,7 @@ error:
 
 static void __exit sco_exit(void)
 {
-       class_remove_file(bt_class, &class_attr_sco);
+       debugfs_remove(sco_debugfs);
 
        if (bt_sock_unregister(BTPROTO_SCO) < 0)
                BT_ERR("SCO socket unregistration failed");
index bcc490cc9452f3e87273836ef406c54608c49084..59d4394d2ce8ba24271e50ea0016033e6b42ab24 100644 (file)
@@ -2483,6 +2483,7 @@ int netif_receive_skb(struct sk_buff *skb)
 {
        struct packet_type *ptype, *pt_prev;
        struct net_device *orig_dev;
+       struct net_device *master;
        struct net_device *null_or_orig;
        struct net_device *null_or_bond;
        int ret = NET_RX_DROP;
@@ -2503,11 +2504,12 @@ int netif_receive_skb(struct sk_buff *skb)
 
        null_or_orig = NULL;
        orig_dev = skb->dev;
-       if (orig_dev->master) {
-               if (skb_bond_should_drop(skb))
+       master = ACCESS_ONCE(orig_dev->master);
+       if (master) {
+               if (skb_bond_should_drop(skb, master))
                        null_or_orig = orig_dev; /* deliver only exact match */
                else
-                       skb->dev = orig_dev->master;
+                       skb->dev = master;
        }
 
        __get_cpu_var(netdev_rx_stat).total++;
index d4ec38fa64e6df2742c9c79e7551d6f996f9a600..6f9206b36dc2d517909d37e332c2f13d520cd497 100644 (file)
@@ -614,7 +614,7 @@ void netpoll_print_options(struct netpoll *np)
                         np->name, np->local_port);
        printk(KERN_INFO "%s: local IP %pI4\n",
                         np->name, &np->local_ip);
-       printk(KERN_INFO "%s: interface %s\n",
+       printk(KERN_INFO "%s: interface '%s'\n",
                         np->name, np->dev_name);
        printk(KERN_INFO "%s: remote port %d\n",
                         np->name, np->remote_port);
@@ -661,6 +661,9 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
                if ((delim = strchr(cur, '@')) == NULL)
                        goto parse_failed;
                *delim = 0;
+               if (*cur == ' ' || *cur == '\t')
+                       printk(KERN_INFO "%s: warning: whitespace"
+                                       "is not allowed\n", np->name);
                np->remote_port = simple_strtol(cur, NULL, 10);
                cur = delim;
        }
@@ -708,7 +711,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
        return 0;
 
  parse_failed:
-       printk(KERN_INFO "%s: couldn't parse config at %s!\n",
+       printk(KERN_INFO "%s: couldn't parse config at '%s'!\n",
               np->name, cur);
        return -1;
 }
index 51ca946e339268b58181870695906e1f29257d85..3feb2b39030838ca08fb02e0b0063711b34e76b2 100644 (file)
@@ -1194,7 +1194,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
                hlist_for_each_entry_rcu(dev, node, head, index_hlist) {
                        if (idx < s_idx)
                                goto cont;
-                       if (idx > s_idx)
+                       if (h > s_h || idx > s_idx)
                                s_ip_idx = 0;
                        in_dev = __in_dev_get_rcu(dev);
                        if (!in_dev)
index af5d897928606df52c3f97483f860c934d2bf6fd..01ef8ba9025cd70c576787d1ec32eb22504f5042 100644 (file)
@@ -961,7 +961,9 @@ fib_find_node(struct trie *t, u32 key)
        struct node *n;
 
        pos = 0;
-       n = rcu_dereference(t->trie);
+       n = rcu_dereference_check(t->trie,
+                                 rcu_read_lock_held() ||
+                                 lockdep_rtnl_is_held());
 
        while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
                tn = (struct tnode *) n;
index f47c9f76754b2f03d900bf2cabe9907f93907bd3..f78402d097b3d57e357d57bf8829b5da4b9762be 100644 (file)
@@ -810,11 +810,13 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                        tunnel->err_count = 0;
        }
 
-       max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen;
+       max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + rt->u.dst.header_len;
 
        if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
            (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
                struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
+               if (max_headroom > dev->needed_headroom)
+                       dev->needed_headroom = max_headroom;
                if (!new_skb) {
                        ip_rt_put(rt);
                        txq->tx_dropped++;
index 8582e12e4a62a8b11ec53d129aabbf16842fcc8e..d0a6092a67be7be38902a15f160d9cf407bf98c7 100644 (file)
@@ -802,6 +802,9 @@ static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock)
        int line;
        struct mfc_cache *uc, *c, **cp;
 
+       if (mfc->mfcc_parent >= MAXVIFS)
+               return -ENFILE;
+
        line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);
 
        for (cp = &net->ipv4.mfc_cache_array[line];
@@ -1613,17 +1616,20 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm)
        int ct;
        struct rtnexthop *nhp;
        struct net *net = mfc_net(c);
-       struct net_device *dev = net->ipv4.vif_table[c->mfc_parent].dev;
        u8 *b = skb_tail_pointer(skb);
        struct rtattr *mp_head;
 
-       if (dev)
-               RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex);
+       /* If cache is unresolved, don't try to parse IIF and OIF */
+       if (c->mfc_parent > MAXVIFS)
+               return -ENOENT;
+
+       if (VIF_EXISTS(net, c->mfc_parent))
+               RTA_PUT(skb, RTA_IIF, 4, &net->ipv4.vif_table[c->mfc_parent].dev->ifindex);
 
        mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
 
        for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
-               if (c->mfc_un.res.ttls[ct] < 255) {
+               if (VIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) {
                        if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
                                goto rtattr_failure;
                        nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
index a770df2493d23652fa5640517b59d9e2f47e7893..d413b57be9b35a38bfab24d16effbf9223a1a991 100644 (file)
@@ -1097,7 +1097,7 @@ static int slow_chain_length(const struct rtable *head)
 }
 
 static int rt_intern_hash(unsigned hash, struct rtable *rt,
-                         struct rtable **rp, struct sk_buff *skb)
+                         struct rtable **rp, struct sk_buff *skb, int ifindex)
 {
        struct rtable   *rth, **rthp;
        unsigned long   now;
@@ -1212,11 +1212,16 @@ restart:
                    slow_chain_length(rt_hash_table[hash].chain) > rt_chain_length_max) {
                        struct net *net = dev_net(rt->u.dst.dev);
                        int num = ++net->ipv4.current_rt_cache_rebuild_count;
-                       if (!rt_caching(dev_net(rt->u.dst.dev))) {
+                       if (!rt_caching(net)) {
                                printk(KERN_WARNING "%s: %d rebuilds is over limit, route caching disabled\n",
                                        rt->u.dst.dev->name, num);
                        }
-                       rt_emergency_hash_rebuild(dev_net(rt->u.dst.dev));
+                       rt_emergency_hash_rebuild(net);
+                       spin_unlock_bh(rt_hash_lock_addr(hash));
+
+                       hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
+                                       ifindex, rt_genid(net));
+                       goto restart;
                }
        }
 
@@ -1441,7 +1446,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                                        dev_hold(rt->u.dst.dev);
                                if (rt->idev)
                                        in_dev_hold(rt->idev);
-                               rt->u.dst.obsolete      = 0;
+                               rt->u.dst.obsolete      = -1;
                                rt->u.dst.lastuse       = jiffies;
                                rt->u.dst.path          = &rt->u.dst;
                                rt->u.dst.neighbour     = NULL;
@@ -1477,7 +1482,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                                                        &netevent);
 
                                rt_del(hash, rth);
-                               if (!rt_intern_hash(hash, rt, &rt, NULL))
+                               if (!rt_intern_hash(hash, rt, &rt, NULL, rt->fl.oif))
                                        ip_rt_put(rt);
                                goto do_next;
                        }
@@ -1506,11 +1511,12 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
        struct dst_entry *ret = dst;
 
        if (rt) {
-               if (dst->obsolete) {
+               if (dst->obsolete > 0) {
                        ip_rt_put(rt);
                        ret = NULL;
                } else if ((rt->rt_flags & RTCF_REDIRECTED) ||
-                          rt->u.dst.expires) {
+                          (rt->u.dst.expires &&
+                           time_after_eq(jiffies, rt->u.dst.expires))) {
                        unsigned hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
                                                rt->fl.oif,
                                                rt_genid(dev_net(dst->dev)));
@@ -1726,7 +1732,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
 
 static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
 {
-       return NULL;
+       if (rt_is_expired((struct rtable *)dst))
+               return NULL;
+       return dst;
 }
 
 static void ipv4_dst_destroy(struct dst_entry *dst)
@@ -1888,7 +1896,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        if (!rth)
                goto e_nobufs;
 
-       rth->u.dst.output= ip_rt_bug;
+       rth->u.dst.output = ip_rt_bug;
+       rth->u.dst.obsolete = -1;
 
        atomic_set(&rth->u.dst.__refcnt, 1);
        rth->u.dst.flags= DST_HOST;
@@ -1927,7 +1936,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
        in_dev_put(in_dev);
        hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
-       return rt_intern_hash(hash, rth, NULL, skb);
+       return rt_intern_hash(hash, rth, NULL, skb, dev->ifindex);
 
 e_nobufs:
        in_dev_put(in_dev);
@@ -2054,6 +2063,7 @@ static int __mkroute_input(struct sk_buff *skb,
        rth->fl.oif     = 0;
        rth->rt_spec_dst= spec_dst;
 
+       rth->u.dst.obsolete = -1;
        rth->u.dst.input = ip_forward;
        rth->u.dst.output = ip_output;
        rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev));
@@ -2093,7 +2103,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
        /* put it into the cache */
        hash = rt_hash(daddr, saddr, fl->iif,
                       rt_genid(dev_net(rth->u.dst.dev)));
-       return rt_intern_hash(hash, rth, NULL, skb);
+       return rt_intern_hash(hash, rth, NULL, skb, fl->iif);
 }
 
 /*
@@ -2218,6 +2228,7 @@ local_input:
                goto e_nobufs;
 
        rth->u.dst.output= ip_rt_bug;
+       rth->u.dst.obsolete = -1;
        rth->rt_genid = rt_genid(net);
 
        atomic_set(&rth->u.dst.__refcnt, 1);
@@ -2249,7 +2260,7 @@ local_input:
        }
        rth->rt_type    = res.type;
        hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));
-       err = rt_intern_hash(hash, rth, NULL, skb);
+       err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);
        goto done;
 
 no_route:
@@ -2444,6 +2455,7 @@ static int __mkroute_output(struct rtable **result,
        rth->rt_spec_dst= fl->fl4_src;
 
        rth->u.dst.output=ip_output;
+       rth->u.dst.obsolete = -1;
        rth->rt_genid = rt_genid(dev_net(dev_out));
 
        RT_CACHE_STAT_INC(out_slow_tot);
@@ -2495,7 +2507,7 @@ static int ip_mkroute_output(struct rtable **rp,
        if (err == 0) {
                hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif,
                               rt_genid(dev_net(dev_out)));
-               err = rt_intern_hash(hash, rth, rp, NULL);
+               err = rt_intern_hash(hash, rth, rp, NULL, oldflp->oif);
        }
 
        return err;
index 5901010fad55bc969fe509ae8d3fde0aef443b2d..6afb6d8662b2cebb984bec82657ab4221e95e464 100644 (file)
@@ -429,7 +429,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
                if (tp->urg_seq == tp->copied_seq &&
                    !sock_flag(sk, SOCK_URGINLINE) &&
                    tp->urg_data)
-                       target--;
+                       target++;
 
                /* Potential race condition. If read of tp below will
                 * escape above sk->sk_state, we can be illegally awaken
@@ -1254,6 +1254,39 @@ static void tcp_prequeue_process(struct sock *sk)
        tp->ucopy.memory = 0;
 }
 
+#ifdef CONFIG_NET_DMA
+static void tcp_service_net_dma(struct sock *sk, bool wait)
+{
+       dma_cookie_t done, used;
+       dma_cookie_t last_issued;
+       struct tcp_sock *tp = tcp_sk(sk);
+
+       if (!tp->ucopy.dma_chan)
+               return;
+
+       last_issued = tp->ucopy.dma_cookie;
+       dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+
+       do {
+               if (dma_async_memcpy_complete(tp->ucopy.dma_chan,
+                                             last_issued, &done,
+                                             &used) == DMA_SUCCESS) {
+                       /* Safe to free early-copied skbs now */
+                       __skb_queue_purge(&sk->sk_async_wait_queue);
+                       break;
+               } else {
+                       struct sk_buff *skb;
+                       while ((skb = skb_peek(&sk->sk_async_wait_queue)) &&
+                              (dma_async_is_complete(skb->dma_cookie, done,
+                                                     used) == DMA_SUCCESS)) {
+                               __skb_dequeue(&sk->sk_async_wait_queue);
+                               kfree_skb(skb);
+                       }
+               }
+       } while (wait);
+}
+#endif
+
 static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
 {
        struct sk_buff *skb;
@@ -1546,6 +1579,10 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        /* __ Set realtime policy in scheduler __ */
                }
 
+#ifdef CONFIG_NET_DMA
+               if (tp->ucopy.dma_chan)
+                       dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+#endif
                if (copied >= target) {
                        /* Do not sleep, just process backlog. */
                        release_sock(sk);
@@ -1554,6 +1591,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        sk_wait_data(sk, &timeo);
 
 #ifdef CONFIG_NET_DMA
+               tcp_service_net_dma(sk, false);  /* Don't block */
                tp->ucopy.wakeup = 0;
 #endif
 
@@ -1633,6 +1671,9 @@ do_prequeue:
                                                copied = -EFAULT;
                                        break;
                                }
+
+                               dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+
                                if ((offset + used) == skb->len)
                                        copied_early = 1;
 
@@ -1702,27 +1743,9 @@ skip_copy:
        }
 
 #ifdef CONFIG_NET_DMA
-       if (tp->ucopy.dma_chan) {
-               dma_cookie_t done, used;
-
-               dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
-
-               while (dma_async_memcpy_complete(tp->ucopy.dma_chan,
-                                                tp->ucopy.dma_cookie, &done,
-                                                &used) == DMA_IN_PROGRESS) {
-                       /* do partial cleanup of sk_async_wait_queue */
-                       while ((skb = skb_peek(&sk->sk_async_wait_queue)) &&
-                              (dma_async_is_complete(skb->dma_cookie, done,
-                                                     used) == DMA_SUCCESS)) {
-                               __skb_dequeue(&sk->sk_async_wait_queue);
-                               kfree_skb(skb);
-                       }
-               }
+       tcp_service_net_dma(sk, true);  /* Wait for queue to drain */
+       tp->ucopy.dma_chan = NULL;
 
-               /* Safe to free early-copied skbs now */
-               __skb_queue_purge(&sk->sk_async_wait_queue);
-               tp->ucopy.dma_chan = NULL;
-       }
        if (tp->ucopy.pinned_list) {
                dma_unpin_iovec_pages(tp->ucopy.pinned_list);
                tp->ucopy.pinned_list = NULL;
index 788851ca8c5d10578afceb8be921638f1ed8254d..c096a4218b8f5e44a4e495152bb385bd8e80cc38 100644 (file)
@@ -2511,6 +2511,9 @@ static void tcp_mark_head_lost(struct sock *sk, int packets)
        int err;
        unsigned int mss;
 
+       if (packets == 0)
+               return;
+
        WARN_ON(packets > tp->packets_out);
        if (tp->lost_skb_hint) {
                skb = tp->lost_skb_hint;
index 70df40980a87a201e79f036aebabcfcc9dbb68c4..f4df5f931f364797ee99c07f2877a92d19a56276 100644 (file)
@@ -370,6 +370,11 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
        if (sk->sk_state == TCP_CLOSE)
                goto out;
 
+       if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) {
+               NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
+               goto out;
+       }
+
        icsk = inet_csk(sk);
        tp = tcp_sk(sk);
        seq = ntohl(th->seq);
index 3381b4317c270230a7c44ee7d57daf6ac4345897..7e567ae5eaab052d482a296db7ff4457114eef78 100644 (file)
@@ -3610,7 +3610,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
                hlist_for_each_entry_rcu(dev, node, head, index_hlist) {
                        if (idx < s_idx)
                                goto cont;
-                       if (idx > s_idx)
+                       if (h > s_h || idx > s_idx)
                                s_ip_idx = 0;
                        ip_idx = 0;
                        if ((idev = __in6_dev_get(dev)) == NULL)
index 52e0f74fdfe0cdfa2c8b8dc515244a64f0dc1010..27acfb58650acf1527f5efbe22bc6765fae39ad4 100644 (file)
@@ -1113,6 +1113,9 @@ static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock)
        unsigned char ttls[MAXMIFS];
        int i;
 
+       if (mfc->mf6cc_parent >= MAXMIFS)
+               return -ENFILE;
+
        memset(ttls, 255, MAXMIFS);
        for (i = 0; i < MAXMIFS; i++) {
                if (IF_ISSET(i, &mfc->mf6cc_ifset))
@@ -1692,17 +1695,20 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
        int ct;
        struct rtnexthop *nhp;
        struct net *net = mfc6_net(c);
-       struct net_device *dev = net->ipv6.vif6_table[c->mf6c_parent].dev;
        u8 *b = skb_tail_pointer(skb);
        struct rtattr *mp_head;
 
-       if (dev)
-               RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex);
+       /* If cache is unresolved, don't try to parse IIF and OIF */
+       if (c->mf6c_parent > MAXMIFS)
+               return -ENOENT;
+
+       if (MIF_EXISTS(net, c->mf6c_parent))
+               RTA_PUT(skb, RTA_IIF, 4, &net->ipv6.vif6_table[c->mf6c_parent].dev->ifindex);
 
        mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
 
        for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
-               if (c->mfc_un.res.ttls[ct] < 255) {
+               if (MIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) {
                        if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
                                goto rtattr_failure;
                        nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
index aef31a29de9ed37f3cf48ab12b738ddf9856882b..b9cf7cd6192316a265a9b670e558c3740514e0d8 100644 (file)
@@ -13,7 +13,7 @@ static const struct xt_table packet_raw = {
        .valid_hooks = RAW_VALID_HOOKS,
        .me = THIS_MODULE,
        .af = NFPROTO_IPV6,
-       .priority = NF_IP6_PRI_FIRST,
+       .priority = NF_IP6_PRI_RAW,
 };
 
 /* The work comes in here from netfilter.c. */
index 52cd3eff31dcccf7f79abed6d2860ceb73b09780..0d7713c5c206ae1965b252edb3ccbb02d6328a63 100644 (file)
@@ -879,7 +879,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
 
        rt = (struct rt6_info *) dst;
 
-       if (rt && rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))
+       if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))
                return dst;
 
        return NULL;
@@ -890,12 +890,17 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
        struct rt6_info *rt = (struct rt6_info *) dst;
 
        if (rt) {
-               if (rt->rt6i_flags & RTF_CACHE)
-                       ip6_del_rt(rt);
-               else
+               if (rt->rt6i_flags & RTF_CACHE) {
+                       if (rt6_check_expired(rt)) {
+                               ip6_del_rt(rt);
+                               dst = NULL;
+                       }
+               } else {
                        dst_release(dst);
+                       dst = NULL;
+               }
        }
-       return NULL;
+       return dst;
 }
 
 static void ip6_link_failure(struct sk_buff *skb)
index 368707882647bb83293a5be6536b00d6ccca2982..344145f23c34adff8562afa8f4b88f17c1a40677 100644 (file)
@@ -2129,10 +2129,9 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c
        int err;
 
        out_skb = pfkey_xfrm_policy2msg_prep(xp);
-       if (IS_ERR(out_skb)) {
-               err = PTR_ERR(out_skb);
-               goto out;
-       }
+       if (IS_ERR(out_skb))
+               return PTR_ERR(out_skb);
+
        err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
        if (err < 0)
                return err;
@@ -2148,7 +2147,6 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c
        out_hdr->sadb_msg_seq = c->seq;
        out_hdr->sadb_msg_pid = c->pid;
        pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp));
-out:
        return 0;
 
 }
index 2b2af631d2b870d3c9f4f81146833fd4a93f2cf9..569410a85953d7ab057ed61bc17445b3a1667407 100644 (file)
@@ -582,7 +582,9 @@ nla_put_failure:
 nlmsg_failure:
        kfree_skb(skb);
 errout:
-       nfnetlink_set_err(net, 0, group, -ENOBUFS);
+       if (nfnetlink_set_err(net, 0, group, -ENOBUFS) > 0)
+               return -ENOBUFS;
+
        return 0;
 }
 #endif /* CONFIG_NF_CONNTRACK_EVENTS */
index 8eb0cc23ada3760a79a0eaefa76ada8745acd4f2..6afa3d52ea5f1d7af8d2be47db8ece008429eeb6 100644 (file)
@@ -113,9 +113,9 @@ int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid,
 }
 EXPORT_SYMBOL_GPL(nfnetlink_send);
 
-void nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error)
+int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error)
 {
-       netlink_set_err(net->nfnl, pid, group, error);
+       return netlink_set_err(net->nfnl, pid, group, error);
 }
 EXPORT_SYMBOL_GPL(nfnetlink_set_err);
 
index 9e9c48963942ad39b722be5790c8a4b01750b1d4..215a64835de82748af7db9682ba69aa3104fde39 100644 (file)
@@ -493,6 +493,7 @@ static void hashlimit_ipv6_mask(__be32 *i, unsigned int p)
        case 64 ... 95:
                i[2] = maskl(i[2], p - 64);
                i[3] = 0;
+               break;
        case 96 ... 127:
                i[3] = maskl(i[3], p - 96);
                break;
@@ -879,7 +880,8 @@ static void dl_seq_stop(struct seq_file *s, void *v)
        struct xt_hashlimit_htable *htable = s->private;
        unsigned int *bucket = (unsigned int *)v;
 
-       kfree(bucket);
+       if (!IS_ERR(bucket))
+               kfree(bucket);
        spin_unlock_bh(&htable->lock);
 }
 
index 7073dbb8100c83fb163498453d814beed8fd2dbe..971d172afecee06b6000261526f334ca23cfa095 100644 (file)
@@ -267,7 +267,7 @@ recent_mt(const struct sk_buff *skb, const struct xt_match_param *par)
                for (i = 0; i < e->nstamps; i++) {
                        if (info->seconds && time_after(time, e->stamps[i]))
                                continue;
-                       if (info->hit_count && ++hits >= info->hit_count) {
+                       if (!info->hit_count || ++hits >= info->hit_count) {
                                ret = !ret;
                                break;
                        }
index 320d0423a24062fd58aaf6340b021f7be587f581..acbbae1e89b580cddd91f8d425052ca200540b43 100644 (file)
@@ -1093,6 +1093,7 @@ static inline int do_one_set_err(struct sock *sk,
                                 struct netlink_set_err_data *p)
 {
        struct netlink_sock *nlk = nlk_sk(sk);
+       int ret = 0;
 
        if (sk == p->exclude_sk)
                goto out;
@@ -1104,10 +1105,15 @@ static inline int do_one_set_err(struct sock *sk,
            !test_bit(p->group - 1, nlk->groups))
                goto out;
 
+       if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) {
+               ret = 1;
+               goto out;
+       }
+
        sk->sk_err = p->code;
        sk->sk_error_report(sk);
 out:
-       return 0;
+       return ret;
 }
 
 /**
@@ -1116,12 +1122,16 @@ out:
  * @pid: the PID of a process that we want to skip (if any)
  * @groups: the broadcast group that will notice the error
  * @code: error code, must be negative (as usual in kernelspace)
+ *
+ * This function returns the number of broadcast listeners that have set the
+ * NETLINK_RECV_NO_ENOBUFS socket option.
  */
-void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
+int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
 {
        struct netlink_set_err_data info;
        struct hlist_node *node;
        struct sock *sk;
+       int ret = 0;
 
        info.exclude_sk = ssk;
        info.pid = pid;
@@ -1132,9 +1142,10 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
        read_lock(&nl_table_lock);
 
        sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list)
-               do_one_set_err(sk, &info);
+               ret += do_one_set_err(sk, &info);
 
        read_unlock(&nl_table_lock);
+       return ret;
 }
 EXPORT_SYMBOL(netlink_set_err);
 
index 77228f28fa363240fce7da4e32d0b81bd8ea3951..2d744f22a9a1e0433363137c2aef908bf19f3508 100644 (file)
@@ -88,6 +88,11 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local,
 
        /* get a notification message to send to the server app */
        notification = alloc_skb(0, GFP_NOFS);
+       if (!notification) {
+               _debug("no memory");
+               ret = -ENOMEM;
+               goto error_nofree;
+       }
        rxrpc_new_skb(notification);
        notification->mark = RXRPC_SKB_MARK_NEW_CALL;
 
@@ -189,6 +194,7 @@ invalid_service:
        ret = -ECONNREFUSED;
 error:
        rxrpc_free_skb(notification);
+error_nofree:
        _leave(" = %d", ret);
        return ret;
 }
index 21f9c7678aa3ea903a9741305c22b6157e8637c3..2f691fb180d127751877003af00e624334da474c 100644 (file)
@@ -328,13 +328,16 @@ config NET_CLS_FLOW
          module will be called cls_flow.
 
 config NET_CLS_CGROUP
-       bool "Control Group Classifier"
+       tristate "Control Group Classifier"
        select NET_CLS
        depends on CGROUPS
        ---help---
          Say Y here if you want to classify packets based on the control
          cgroup of their process.
 
+         To compile this code as a module, choose M here: the
+         module will be called cls_cgroup.
+
 config NET_EMATCH
        bool "Extended Matches"
        select NET_CLS
index e4877ca6727c4b098ef1b6f08163fd7702d3eea2..7f27d2c15e08324d0d5e3b20d913676b1bbbcdd2 100644 (file)
@@ -24,6 +24,25 @@ struct cgroup_cls_state
        u32 classid;
 };
 
+static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss,
+                                              struct cgroup *cgrp);
+static void cgrp_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp);
+static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp);
+
+struct cgroup_subsys net_cls_subsys = {
+       .name           = "net_cls",
+       .create         = cgrp_create,
+       .destroy        = cgrp_destroy,
+       .populate       = cgrp_populate,
+#ifdef CONFIG_NET_CLS_CGROUP
+       .subsys_id      = net_cls_subsys_id,
+#else
+#define net_cls_subsys_id net_cls_subsys.subsys_id
+#endif
+       .module         = THIS_MODULE,
+};
+
+
 static inline struct cgroup_cls_state *cgrp_cls_state(struct cgroup *cgrp)
 {
        return container_of(cgroup_subsys_state(cgrp, net_cls_subsys_id),
@@ -79,14 +98,6 @@ static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
        return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files));
 }
 
-struct cgroup_subsys net_cls_subsys = {
-       .name           = "net_cls",
-       .create         = cgrp_create,
-       .destroy        = cgrp_destroy,
-       .populate       = cgrp_populate,
-       .subsys_id      = net_cls_subsys_id,
-};
-
 struct cls_cgroup_head
 {
        u32                     handle;
@@ -277,12 +288,19 @@ static struct tcf_proto_ops cls_cgroup_ops __read_mostly = {
 
 static int __init init_cgroup_cls(void)
 {
-       return register_tcf_proto_ops(&cls_cgroup_ops);
+       int ret = register_tcf_proto_ops(&cls_cgroup_ops);
+       if (ret)
+               return ret;
+       ret = cgroup_load_subsys(&net_cls_subsys);
+       if (ret)
+               unregister_tcf_proto_ops(&cls_cgroup_ops);
+       return ret;
 }
 
 static void __exit exit_cgroup_cls(void)
 {
        unregister_tcf_proto_ops(&cls_cgroup_ops);
+       cgroup_unload_subsys(&net_cls_subsys);
 }
 
 module_init(init_cgroup_cls);
index 769c386bd4288758635acde6ca77c401a49c61a8..f55ffe9f8c87f27d670ddea0da7aff762355cf2f 100644 (file)
@@ -2135,6 +2135,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
                        break;
                ++datagrams;
 
+               /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
+               if (flags & MSG_WAITFORONE)
+                       flags |= MSG_DONTWAIT;
+
                if (timeout) {
                        ktime_get_ts(timeout);
                        *timeout = timespec_sub(end_time, *timeout);
index 0cfccc2a02979c4844c63dffbbdd47312a0139e6..c389ccf6437d5870868ec49f489b3f07f131ed46 100644 (file)
@@ -1280,9 +1280,8 @@ alloc_enc_pages(struct rpc_rqst *rqstp)
        rqstp->rq_release_snd_buf = priv_release_snd_buf;
        return 0;
 out_free:
-       for (i--; i >= 0; i--) {
-               __free_page(rqstp->rq_enc_pages[i]);
-       }
+       rqstp->rq_enc_pages_num = i;
+       priv_release_snd_buf(rqstp);
 out:
        return -EAGAIN;
 }
index 13f214f531208603a0e8f2b7cfe8ff0cfbc79bea..f0c05d3311c1a1ac3dca0d19ab701cd5e00a9559 100644 (file)
@@ -37,21 +37,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #define RPCDBG_FACILITY        RPCDBG_SVCDSP
 
-void bc_release_request(struct rpc_task *task)
-{
-       struct rpc_rqst *req = task->tk_rqstp;
-
-       dprintk("RPC:       bc_release_request: task= %p\n", task);
-
-       /*
-        * Release this request only if it's a backchannel
-        * preallocated request
-        */
-       if (!bc_prealloc(req))
-               return;
-       xprt_free_bc_request(req);
-}
-
 /* Empty callback ops */
 static const struct rpc_call_ops nfs41_callback_ops = {
 };
index 154034b675bd90de493d1438ff46a2b230178742..19c9983d53607483cce29654b8e589dca6da539d 100644 (file)
@@ -659,6 +659,7 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
        task = rpc_new_task(&task_setup_data);
        if (!task) {
                xprt_free_bc_request(req);
+               task = ERR_PTR(-ENOMEM);
                goto out;
        }
        task->tk_rqstp = req;
index 8d63f8fd29b7e3ff0e940d7457d45203f99c56b1..20e30c6f8355dc0bc612bffb44abefee7c3536df 100644 (file)
@@ -587,6 +587,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
        struct dentry *dentry;
 
        dentry = __rpc_lookup_create(parent, name);
+       if (IS_ERR(dentry))
+               return dentry;
        if (dentry->d_inode == NULL)
                return dentry;
        dput(dentry);
index 469de292c23c34b8ba9a0f9ea24e07d4b77d5e09..42f09ade00445289c22a51f88550af7b7dadb85a 100644 (file)
@@ -46,6 +46,7 @@
 
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/metrics.h>
+#include <linux/sunrpc/bc_xprt.h>
 
 #include "sunrpc.h"
 
@@ -1032,21 +1033,16 @@ void xprt_release(struct rpc_task *task)
        if (req->rq_release_snd_buf)
                req->rq_release_snd_buf(req);
 
-       /*
-        * Early exit if this is a backchannel preallocated request.
-        * There is no need to have it added to the RPC slot list.
-        */
-       if (is_bc_request)
-               return;
-
-       memset(req, 0, sizeof(*req));   /* mark unused */
-
        dprintk("RPC: %5u release request %p\n", task->tk_pid, req);
+       if (likely(!is_bc_request)) {
+               memset(req, 0, sizeof(*req));   /* mark unused */
 
-       spin_lock(&xprt->reserve_lock);
-       list_add(&req->rq_list, &xprt->free);
-       rpc_wake_up_next(&xprt->backlog);
-       spin_unlock(&xprt->reserve_lock);
+               spin_lock(&xprt->reserve_lock);
+               list_add(&req->rq_list, &xprt->free);
+               rpc_wake_up_next(&xprt->backlog);
+               spin_unlock(&xprt->reserve_lock);
+       } else
+               xprt_free_bc_request(req);
 }
 
 /**
index e4839c07c913a38253959a942d7111611a507fa2..9847c30b5001ce5d4e3cd9e1b5828e80cdd7ef24 100644 (file)
@@ -2251,9 +2251,6 @@ static struct rpc_xprt_ops xs_tcp_ops = {
        .buf_free               = rpc_free,
        .send_request           = xs_tcp_send_request,
        .set_retrans_timeout    = xprt_set_retrans_timeout_def,
-#if defined(CONFIG_NFS_V4_1)
-       .release_request        = bc_release_request,
-#endif /* CONFIG_NFS_V4_1 */
        .close                  = xs_tcp_close,
        .destroy                = xs_destroy,
        .print_stats            = xs_tcp_print_stats,
index f76f3d13276dd114c880e13ec45cad7452f992b9..6f97a13bcee4131aedbbf97a4f9db49c50e519e5 100755 (executable)
@@ -284,7 +284,7 @@ foreach my $file (@ARGV) {
        my $file_cnt = @files;
        my $lastfile;
 
-       open(my $patch, '<', $file)
+       open(my $patch, "< $file")
            or die "$P: Can't open $file: $!\n";
        while (<$patch>) {
            my $patch_line = $_;
index c7865c362d28fdbe160c94bfdd54e40bf34f8dd5..fcdfb245a5755d3bc534ac25d35728c214e8d03d 100755 (executable)
@@ -1424,6 +1424,8 @@ sub dump_struct($$) {
        $nested =~ s/\/\*.*?\*\///gos;
        # strip kmemcheck_bitfield_{begin,end}.*;
        $members =~ s/kmemcheck_bitfield_.*?;//gos;
+       # strip attributes
+       $members =~ s/__aligned\s*\(\d+\)//gos;
 
        create_parameterlist($members, ';', $file);
        check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
@@ -1728,6 +1730,7 @@ sub dump_function($$) {
     $prototype =~ s/^noinline +//;
     $prototype =~ s/__devinit +//;
     $prototype =~ s/__init +//;
+    $prototype =~ s/__init_or_module +//;
     $prototype =~ s/^#\s*define\s+//; #ak added
     $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
 
index 743ac6a2906598fdbd70a04f6a3c6910fd86fdfe..fd51fa8b06a12cea27815c2ec9b121841cbc3076 100644 (file)
@@ -205,6 +205,7 @@ int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
        if (!rtd->dma_desc_array)
                goto err1;
 
+       rtd->dma_ch = -1;
        runtime->private_data = rtd;
        return 0;
 
index b546ac2660f9f64b8436e3efe836cfa0f298afee..a2ff86189d2a583ad208c8e61beed816d3f23a67 100644 (file)
@@ -148,6 +148,9 @@ static void pcm_debug_name(struct snd_pcm_substream *substream,
 
 #define xrun_debug(substream, mask) \
                        ((substream)->pstr->xrun_debug & (mask))
+#else
+#define xrun_debug(substream, mask)    0
+#endif
 
 #define dump_stack_on_xrun(substream) do {                     \
                if (xrun_debug(substream, XRUN_DEBUG_STACK))    \
@@ -169,6 +172,7 @@ static void xrun(struct snd_pcm_substream *substream)
        }
 }
 
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
 #define hw_ptr_error(substream, fmt, args...)                          \
        do {                                                            \
                if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {          \
@@ -255,8 +259,6 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
 
 #else /* ! CONFIG_SND_PCM_XRUN_DEBUG */
 
-#define xrun_debug(substream, mask)    0
-#define xrun(substream)                        do { } while (0)
 #define hw_ptr_error(substream, fmt, args...) do { } while (0)
 #define xrun_log(substream, pos)       do { } while (0)
 #define xrun_log_show(substream)       do { } while (0)
index 725fef0f59a379d5dd8e2a71e1993dcf151046fb..a4127bab9231fcb05ce72ac1c52b470e441b57a1 100644 (file)
@@ -363,13 +363,13 @@ static void vidc_audio_trigger(int dev, int enable_bits)
        struct audio_operations *adev = audio_devs[dev];
 
        if (enable_bits & PCM_ENABLE_OUTPUT) {
-               if (!(adev->flags & DMA_ACTIVE)) {
+               if (!(adev->dmap_out->flags & DMA_ACTIVE)) {
                        unsigned long flags;
 
                        local_irq_save(flags);
 
                        /* prevent recusion */
-                       adev->flags |= DMA_ACTIVE;
+                       adev->dmap_out->flags |= DMA_ACTIVE;
 
                        dma_interrupt = vidc_audio_dma_interrupt;
                        vidc_sound_dma_irq(0, NULL);
index 1caf5e3c1f6ad481064ea70cced23293333de96a..e68c98ef4041508c2f9a2361172ab592be3ec90c 100644 (file)
@@ -1852,12 +1852,14 @@ static unsigned int ad1981_jacks_blacklist[] = {
        0x10140523, /* Thinkpad R40 */
        0x10140534, /* Thinkpad X31 */
        0x10140537, /* Thinkpad T41p */
+       0x1014053e, /* Thinkpad R40e */
        0x10140554, /* Thinkpad T42p/R50p */
        0x10140567, /* Thinkpad T43p 2668-G7U */
        0x10140581, /* Thinkpad X41-2527 */
        0x10280160, /* Dell Dimension 2400 */
        0x104380b0, /* Asus A7V8X-MX */
        0x11790241, /* Toshiba Satellite A-15 S127 */
+       0x1179ff10, /* Toshiba P500 */
        0x144dc01a, /* Samsung NP-X20C004/SEG */
        0 /* end */
 };
index 1ded64e056433e22f8e96d8b0fbeb6dbf2c557d4..329968edca9b840fc622602535b0088cdb73bd6c 100644 (file)
@@ -941,13 +941,21 @@ static snd_pcm_uframes_t snd_cmipci_pcm_pointer(struct cmipci *cm, struct cmipci
                                                struct snd_pcm_substream *substream)
 {
        size_t ptr;
-       unsigned int reg;
+       unsigned int reg, rem, tries;
+
        if (!rec->running)
                return 0;
 #if 1 // this seems better..
        reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2;
-       ptr = rec->dma_size - (snd_cmipci_read_w(cm, reg) + 1);
-       ptr >>= rec->shift;
+       for (tries = 0; tries < 3; tries++) {
+               rem = snd_cmipci_read_w(cm, reg);
+               if (rem < rec->dma_size)
+                       goto ok;
+       } 
+       printk(KERN_ERR "cmipci: invalid PCM pointer: %#x\n", rem);
+       return SNDRV_PCM_POS_XRUN;
+ok:
+       ptr = (rec->dma_size - (rem + 1)) >> rec->shift;
 #else
        reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1;
        ptr = snd_cmipci_read(cm, reg) - rec->offset;
index 8b2915631cc38bcde8e6490cc9947de4c6110684..4bb90675f70fced63e22fe1f9b70283b2094e673 100644 (file)
@@ -2269,6 +2269,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x8086, 0xd601, "eMachines T5212", POS_FIX_LPIB),
index 194a28c5499219b99d3b10ed2ae357cde7707679..61682e1d09da9388048b3a1d95fce96a44001175 100644 (file)
@@ -1591,6 +1591,21 @@ static int patch_cxt5047(struct hda_codec *codec)
 #endif 
        }
        spec->vmaster_nid = 0x13;
+
+       switch (codec->subsystem_id >> 16) {
+       case 0x103c:
+               /* HP laptops have really bad sound over 0 dB on NID 0x10.
+                * Fix max PCM level to 0 dB (originally it has 0x1e steps
+                * with 0 dB offset 0x17)
+                */
+               snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT,
+                                         (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
+                                         (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+                                         (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+                                         (1 << AC_AMPCAP_MUTE_SHIFT));
+               break;
+       }
+
        return 0;
 }
 
index 70669a246902570de791822919fecba4fc0d5f19..3c10c0b149f4c682d683a6ae21ae837b3fe18f4d 100644 (file)
@@ -538,8 +538,6 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
  * patch entries
  */
 static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
-       { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
-       { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
        { .id = 0x10de0002, .name = "MCP77/78 HDMI",
          .patch = patch_nvhdmi_8ch_7x },
        { .id = 0x10de0003, .name = "MCP77/78 HDMI",
@@ -550,12 +548,16 @@ static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
          .patch = patch_nvhdmi_8ch_7x },
        { .id = 0x10de0007, .name = "MCP79/7A HDMI",
          .patch = patch_nvhdmi_8ch_7x },
-       { .id = 0x10de000c, .name = "MCP89 HDMI",
+       { .id = 0x10de000a, .name = "GT220 HDMI",
          .patch = patch_nvhdmi_8ch_89 },
        { .id = 0x10de000b, .name = "GT21x HDMI",
          .patch = patch_nvhdmi_8ch_89 },
+       { .id = 0x10de000c, .name = "MCP89 HDMI",
+         .patch = patch_nvhdmi_8ch_89 },
        { .id = 0x10de000d, .name = "GT240 HDMI",
          .patch = patch_nvhdmi_8ch_89 },
+       { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
+       { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
        {} /* terminator */
 };
 
@@ -564,11 +566,12 @@ MODULE_ALIAS("snd-hda-codec-id:10de0003");
 MODULE_ALIAS("snd-hda-codec-id:10de0005");
 MODULE_ALIAS("snd-hda-codec-id:10de0006");
 MODULE_ALIAS("snd-hda-codec-id:10de0007");
-MODULE_ALIAS("snd-hda-codec-id:10de0067");
-MODULE_ALIAS("snd-hda-codec-id:10de8001");
-MODULE_ALIAS("snd-hda-codec-id:10de000c");
+MODULE_ALIAS("snd-hda-codec-id:10de000a");
 MODULE_ALIAS("snd-hda-codec-id:10de000b");
+MODULE_ALIAS("snd-hda-codec-id:10de000c");
 MODULE_ALIAS("snd-hda-codec-id:10de000d");
+MODULE_ALIAS("snd-hda-codec-id:10de0067");
+MODULE_ALIAS("snd-hda-codec-id:10de8001");
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
index 4ec57633af88efb14ce5a632d2dbf1c67d91b7cf..9a23444e9e7ac2ee609678c6fb8a8f9a91ee1e1d 100644 (file)
@@ -2532,8 +2532,6 @@ static int alc_build_controls(struct hda_codec *codec)
                        return err;
        }
 
-       alc_free_kctls(codec); /* no longer needed */
-
        /* assign Capture Source enums to NID */
        kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
        if (!kctl)
@@ -2602,6 +2600,9 @@ static int alc_build_controls(struct hda_codec *codec)
                        }
                }
        }
+
+       alc_free_kctls(codec); /* no longer needed */
+
        return 0;
 }
 
@@ -10042,8 +10043,11 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
        alc_set_pin_output(codec, nid, pin_type);
        if (spec->multiout.dac_nids[dac_idx] == 0x25)
                idx = 4;
-       else
+       else {
+               if (spec->multiout.num_dacs >= dac_idx)
+                       return;
                idx = spec->multiout.dac_nids[dac_idx] - 2;
+       }
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
 
 }
index 8c416bb18a57cef781249611bdbae060212b924d..c4be3fab94e58c44e50d9218279c632b490378e4 100644 (file)
@@ -1730,6 +1730,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
                      "HP HDX", STAC_HP_HDX),  /* HDX16 */
        SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620,
                      "HP dv6", STAC_HP_DV5),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061,
+                     "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */
        SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010,
                      "HP", STAC_HP_DV5),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
index f9f367d29a9095e8bc5a44be2da0da9b45f4ba7e..d50f1699ccb2e6d63e07984cc0fcd80b0a22dc5c 100644 (file)
@@ -778,7 +778,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
        if (dac33->fifo_mode) {
                /* Generic for all FIFO modes */
                /* 50-51 : ASRC Control registers */
-               dac33_write(codec, DAC33_ASRC_CTRL_A, (1 << 4)); /* div=2 */
+               dac33_write(codec, DAC33_ASRC_CTRL_A, DAC33_SRCLKDIV(1));
                dac33_write(codec, DAC33_ASRC_CTRL_B, 1); /* ??? */
 
                /* Write registers 0x34 and 0x35 (MSB, LSB) */
@@ -1038,11 +1038,7 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
        case SND_SOC_DAIFMT_DSP_A:
                aictrl_a |= DAC33_AFMT_DSP;
                aictrl_b &= ~DAC33_DATA_DELAY_MASK;
-               aictrl_b |= DAC33_DATA_DELAY(1); /* 1 bit delay */
-               break;
-       case SND_SOC_DAIFMT_DSP_B:
-               aictrl_a |= DAC33_AFMT_DSP;
-               aictrl_b &= ~DAC33_DATA_DELAY_MASK; /* No delay */
+               aictrl_b |= DAC33_DATA_DELAY(0);
                break;
        case SND_SOC_DAIFMT_RIGHT_J:
                aictrl_a |= DAC33_AFMT_RIGHT_J;
@@ -1066,7 +1062,7 @@ static void dac33_init_chip(struct snd_soc_codec *codec)
 {
        /* 44-46: DAC Control Registers */
        /* A : DAC sample rate Fsref/1.5 */
-       dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(1));
+       dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0));
        /* B : DAC src=normal, not muted */
        dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT |
                                             DAC33_DACSRCL_LEFT);
index 0ad9f5d536c67bf89afe1172ef863cff2fdfd6d0..486bdd21a98ab9115f6ee6e37133491079d0ca4d 100644 (file)
@@ -74,7 +74,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec)
                msleep(1);
                reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0);
                dev_dbg(codec->dev, "DC servo: %x\n", reg);
-       } while (reg & WM8993_DCS_DATAPATH_BUSY);
+       } while (reg & WM8993_DCS_DATAPATH_BUSY && count < 400);
 
        if (reg & WM8993_DCS_DATAPATH_BUSY)
                dev_err(codec->dev, "Timed out waiting for DC Servo\n");
index c7d0fd9b7de884522ee02f1ef838dccd8ed53269..7174b4c710de4451f974214558af0dc27516457d 100644 (file)
@@ -1,6 +1,6 @@
 config SND_IMX_SOC
        tristate "SoC Audio for Freescale i.MX CPUs"
-       depends on ARCH_MXC && BROKEN
+       depends on ARCH_MXC
        select SND_PCM
        select FIQ
        select SND_SOC_AC97_BUS
index 106674979b535a54110ba0b1a0e47048178bb9e9..f07f6d8b93e14cf8f038416154361bc7b8038aee 100644 (file)
@@ -32,6 +32,7 @@ config SND_SOC_SH4_SIU
        select DMA_ENGINE
        select DMADEVICES
        select SH_DMAE
+       select FW_LOADER
 
 ##
 ## Boards
index c30a33592340e4977c4d82cfb7dabd618370be2c..152d6c9b1fa4a07619c7cd3d11a7f45b7777a1ff 100644 (file)
@@ -47,7 +47,6 @@
 #include "util/probe-event.h"
 
 #define MAX_PATH_LEN 256
-#define MAX_PROBES 128
 
 /* Session management structure */
 static struct {
index 0b719e3dde050611c282b0c21dccbd91f507ad70..1f529321607eb2c2c852bb481982f1287fc86ef9 100644 (file)
@@ -455,7 +455,7 @@ static void print_sym_table(void)
        struct sym_entry *syme, *n;
        struct rb_root tmp = RB_ROOT;
        struct rb_node *nd;
-       int sym_width = 0, dso_width = 0, max_dso_width;
+       int sym_width = 0, dso_width = 0, dso_short_width = 0;
        const int win_width = winsize.ws_col - 1;
 
        samples = userspace_samples = 0;
@@ -545,15 +545,20 @@ static void print_sym_table(void)
                if (syme->map->dso->long_name_len > dso_width)
                        dso_width = syme->map->dso->long_name_len;
 
+               if (syme->map->dso->short_name_len > dso_short_width)
+                       dso_short_width = syme->map->dso->short_name_len;
+
                if (syme->name_len > sym_width)
                        sym_width = syme->name_len;
        }
 
        printed = 0;
 
-       max_dso_width = winsize.ws_col - sym_width - 29;
-       if (dso_width > max_dso_width)
-               dso_width = max_dso_width;
+       if (sym_width + dso_width > winsize.ws_col - 29) {
+               dso_width = dso_short_width;
+               if (sym_width + dso_width > winsize.ws_col - 29)
+                       sym_width = winsize.ws_col - dso_width - 29;
+       }
        putchar('\n');
        if (nr_counters == 1)
                printf("             samples  pcnt");
index 53181dbfe4a8dae101a279a40f10654865c90796..7c004b6ef24ffe725730564cb9418adfcc808be4 100644 (file)
@@ -242,7 +242,7 @@ void parse_perf_probe_event(const char *str, struct probe_point *pp,
 
        /* Parse probe point */
        parse_perf_probe_probepoint(argv[0], pp);
-       if (pp->file || pp->line)
+       if (pp->file || pp->line || pp->lazy_line)
                *need_dwarf = true;
 
        /* Copy arguments and ensure return probe has no C argument */
index 1e6c65ebbd80f6f1954ffec13715a21ab9f53ed2..c171a243d05b721b7cfdc9b743a73cbbf75099a3 100644 (file)
@@ -333,8 +333,8 @@ static void show_location(Dwarf_Op *op, struct probe_finder *pf)
                die("%u exceeds max register number.", regn);
 
        if (deref)
-               ret = snprintf(pf->buf, pf->len, " %s=+%ju(%s)",
-                              pf->var, (uintmax_t)offs, regs);
+               ret = snprintf(pf->buf, pf->len, " %s=%+jd(%s)",
+                              pf->var, (intmax_t)offs, regs);
        else
                ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs);
        DIE_IF(ret < 0);
@@ -352,8 +352,7 @@ static void show_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
        if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
                goto error;
        /* TODO: handle more than 1 exprs */
-       ret = dwarf_getlocation_addr(&attr, (pf->addr - pf->cu_base),
-                                    &expr, &nexpr, 1);
+       ret = dwarf_getlocation_addr(&attr, pf->addr, &expr, &nexpr, 1);
        if (ret <= 0 || nexpr == 0)
                goto error;
 
@@ -437,8 +436,7 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
 
        /* Get the frame base attribute/ops */
        dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
-       ret = dwarf_getlocation_addr(&fb_attr, (pf->addr - pf->cu_base),
-                                    &pf->fb_ops, &nops, 1);
+       ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
        if (ret <= 0 || nops == 0)
                pf->fb_ops = NULL;
 
@@ -455,6 +453,9 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
        /* *pf->fb_ops will be cached in libdw. Don't free it. */
        pf->fb_ops = NULL;
 
+       if (pp->found == MAX_PROBES)
+               die("Too many( > %d) probe point found.\n", MAX_PROBES);
+
        pp->probes[pp->found] = strdup(tmp);
        pp->found++;
 }
@@ -641,7 +642,6 @@ static void find_probe_point_by_func(struct probe_finder *pf)
 int find_probe_point(int fd, struct probe_point *pp)
 {
        struct probe_finder pf = {.pp = pp};
-       int ret;
        Dwarf_Off off, noff;
        size_t cuhl;
        Dwarf_Die *diep;
@@ -668,10 +668,6 @@ int find_probe_point(int fd, struct probe_point *pp)
                        pf.fname = NULL;
 
                if (!pp->file || pf.fname) {
-                       /* Save CU base address (for frame_base) */
-                       ret = dwarf_lowpc(&pf.cu_die, &pf.cu_base);
-                       if (ret != 0)
-                               pf.cu_base = 0;
                        if (pp->function)
                                find_probe_point_by_func(&pf);
                        else if (pp->lazy_line)
index d1a651793ba6661bf88684e62978f697d5cbd9f6..21f7354397b459414bcc438813411fa901fe19ff 100644 (file)
@@ -71,7 +71,6 @@ struct probe_finder {
 
        /* For variable searching */
        Dwarf_Op                *fb_ops;        /* Frame base attribute */
-       Dwarf_Addr              cu_base;        /* Current CU base address */
        const char              *var;           /* Current variable name */
        char                    *buf;           /* Current output buffer */
        int                     len;            /* Length of output buffer */
index 323c0aea0a91172cced9261cdfd966cd2c0aa57d..c458c4a371d11ea11715f3937111843234739462 100644 (file)
@@ -163,9 +163,17 @@ void dso__set_long_name(struct dso *self, char *name)
        self->long_name_len = strlen(name);
 }
 
+static void dso__set_short_name(struct dso *self, const char *name)
+{
+       if (name == NULL)
+               return;
+       self->short_name = name;
+       self->short_name_len = strlen(name);
+}
+
 static void dso__set_basename(struct dso *self)
 {
-       self->short_name = basename(self->long_name);
+       dso__set_short_name(self, basename(self->long_name));
 }
 
 struct dso *dso__new(const char *name)
@@ -176,7 +184,7 @@ struct dso *dso__new(const char *name)
                int i;
                strcpy(self->name, name);
                dso__set_long_name(self, self->name);
-               self->short_name = self->name;
+               dso__set_short_name(self, self->name);
                for (i = 0; i < MAP__NR_TYPES; ++i)
                        self->symbols[i] = self->symbol_names[i] = RB_ROOT;
                self->slen_calculated = 0;
@@ -897,7 +905,6 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
        struct kmap *kmap = self->kernel ? map__kmap(map) : NULL;
        struct map *curr_map = map;
        struct dso *curr_dso = self;
-       size_t dso_name_len = strlen(self->short_name);
        Elf_Data *symstrs, *secstrs;
        uint32_t nr_syms;
        int err = -1;
@@ -987,7 +994,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
                        char dso_name[PATH_MAX];
 
                        if (strcmp(section_name,
-                                  curr_dso->short_name + dso_name_len) == 0)
+                                  (curr_dso->short_name +
+                                   self->short_name_len)) == 0)
                                goto new_symbol;
 
                        if (strcmp(section_name, ".text") == 0) {
@@ -1782,7 +1790,7 @@ struct dso *dso__new_kernel(const char *name)
        struct dso *self = dso__new(name ?: "[kernel.kallsyms]");
 
        if (self != NULL) {
-               self->short_name = "[kernel]";
+               dso__set_short_name(self, "[kernel]");
                self->kernel     = 1;
        }
 
index 280dadd32a08972f59bde677d4f7bc6c14a0da36..f30a37428919b6d959eba0811cf0489ed4d8e5b2 100644 (file)
@@ -110,9 +110,10 @@ struct dso {
        u8               sorted_by_name;
        u8               loaded;
        u8               build_id[BUILD_ID_SIZE];
-       u16              long_name_len;
        const char       *short_name;
        char             *long_name;
+       u16              long_name_len;
+       u16              short_name_len;
        char             name[0];
 };