Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
Linus Torvalds [Tue, 15 Jul 2008 22:01:29 +0000 (15:01 -0700)]
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (54 commits)
  [MIPS] Remove mips_machtype for LASAT machines
  [MIPS] Remove mips_machtype from EMMA2RH machines
  [MIPS] Remove mips_machtype from ARC based machines
  [MIPS] MTX-1 flash partition setup move to platform devices registration
  [MIPS] TXx9: cleanup and fix some sparse warnings
  [MIPS] TXx9: rename asm-mips/mach-jmr3927 to asm-mips/mach-tx39xx
  [MIPS] remove machtype for group Toshiba
  [MIPS] separate rbtx4927_time_init() and rbtx4937_time_init()
  [MIPS] separate rbtx4927_arch_init() and rbtx4937_arch_init()
  [MIPS] txx9_cpu_clock setup move to rbtx4927_time_init()
  [MIPS] txx9_board_vec set directly without mips_machtype
  [MIPS] IP22: Add platform device for Indy volume buttons
  [MIPS] cmbvr4133: Remove support
  [MIPS] remove wrppmc_machine_power_off()
  [MIPS] replace inline assembler to cpu_wait()
  [MIPS] IP22/28: Add platform devices for HAL2
  [MIPS] TXx9: Update and merge defconfigs
  [MIPS] TXx9: Make single kernel can support multiple boards
  [MIPS] TXx9: Update defconfigs
  [MIPS] TXx9: Reorganize PCI code
  ...

542 files changed:
Documentation/IRQ-affinity.txt
Documentation/RCU/NMI-RCU.txt
Documentation/RCU/RTFP.txt
Documentation/RCU/checklist.txt
Documentation/RCU/torture.txt
Documentation/RCU/whatisRCU.txt
Documentation/cputopology.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/ext4.txt
Documentation/filesystems/gfs2-glocks.txt [new file with mode: 0644]
Documentation/filesystems/proc.txt
Documentation/i2c/busses/i2c-i810 [deleted file]
Documentation/i2c/busses/i2c-prosavage [deleted file]
Documentation/i2c/busses/i2c-savage4 [deleted file]
Documentation/i2c/fault-codes [new file with mode: 0644]
Documentation/i2c/smbus-protocol
Documentation/i2c/writing-clients
Documentation/kernel-parameters.txt
MAINTAINERS
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/kernel/core_marvel.c
arch/alpha/kernel/irq.c
arch/alpha/kernel/process.c
arch/alpha/kernel/smp.c
arch/alpha/oprofile/common.c
arch/arm/Kconfig
arch/arm/kernel/smp.c
arch/arm/kernel/stacktrace.c
arch/arm/oprofile/op_model_mpcore.c
arch/arm/vfp/vfpmodule.c
arch/avr32/kernel/stacktrace.c
arch/cris/arch-v32/kernel/smp.c
arch/ia64/Kconfig
arch/ia64/kernel/mca.c
arch/ia64/kernel/palinfo.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/process.c
arch/ia64/kernel/smp.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/uncached.c
arch/ia64/sn/kernel/irq.c
arch/ia64/sn/kernel/sn2/sn_hwperf.c
arch/m32r/Kconfig
arch/m32r/kernel/m32r_ksyms.c
arch/m32r/kernel/smp.c
arch/m32r/kernel/traps.c
arch/mips/Kconfig
arch/mips/kernel/irq-rm9000.c
arch/mips/kernel/smp.c
arch/mips/kernel/smtc.c
arch/mips/kernel/stacktrace.c
arch/mips/mm/c-r4k.c
arch/mips/oprofile/common.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/pmc-sierra/yosemite/prom.c
arch/mips/sibyte/cfe/setup.c
arch/mips/sibyte/sb1250/prom.c
arch/mips/sibyte/swarm/Makefile
arch/mips/sibyte/swarm/swarm-i2c.c [new file with mode: 0644]
arch/parisc/Kconfig
arch/parisc/kernel/cache.c
arch/parisc/kernel/smp.c
arch/parisc/mm/init.c
arch/powerpc/Kconfig
arch/powerpc/kernel/machine_kexec_64.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/stacktrace.c
arch/powerpc/kernel/tau_6xx.c
arch/powerpc/kernel/time.c
arch/powerpc/mm/slice.c
arch/powerpc/mm/tlb_64.c
arch/powerpc/oprofile/common.c
arch/powerpc/platforms/cell/interrupt.c
arch/powerpc/platforms/ps3/smp.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/sysdev/mpic.c
arch/ppc/kernel/smp.c
arch/s390/appldata/appldata_base.c
arch/s390/kernel/smp.c
arch/s390/kernel/stacktrace.c
arch/s390/kernel/time.c
arch/sh/Kconfig
arch/sh/kernel/smp.c
arch/sh/kernel/stacktrace.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/stacktrace.c
arch/sparc64/mm/hugetlbpage.c
arch/um/kernel/smp.c
arch/x86/Kconfig
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/apic_32.c
arch/x86/kernel/cpu/mcheck/mce_64.c
arch/x86/kernel/cpu/mcheck/non-fatal.c
arch/x86/kernel/cpu/mtrr/main.c
arch/x86/kernel/cpu/perfctr-watchdog.c
arch/x86/kernel/cpuid.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/io_apic_32.c
arch/x86/kernel/io_apic_64.c
arch/x86/kernel/irqinit_64.c
arch/x86/kernel/ldt.c
arch/x86/kernel/nmi.c
arch/x86/kernel/process.c
arch/x86/kernel/quirks.c
arch/x86/kernel/smp.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/smpcommon.c
arch/x86/kernel/stacktrace.c
arch/x86/kernel/tlb_32.c
arch/x86/kernel/tlb_64.c
arch/x86/kernel/vsyscall_64.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/msr-on-cpu.c
arch/x86/mach-voyager/voyager_smp.c
arch/x86/mm/pageattr.c
arch/x86/oprofile/nmi_int.c
arch/x86/pci/amd_bus.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/smp.c
arch/x86/xen/xen-ops.h
block/blk-core.c
block/blk-exec.c
crypto/async_tx/async_tx.c
drivers/acpi/processor_idle.c
drivers/ata/ahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-pmp.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/libata.h
drivers/ata/pata_bf54x.c
drivers/ata/pata_legacy.c
drivers/ata/pata_qdi.c
drivers/ata/pata_scc.c
drivers/ata/pata_winbond.c
drivers/ata/sata_svw.c
drivers/base/topology.c
drivers/block/paride/pd.c
drivers/char/agp/generic.c
drivers/char/sysrq.c
drivers/clocksource/acpi_pm.c
drivers/cpuidle/cpuidle.c
drivers/firewire/fw-card.c
drivers/firewire/fw-device.c
drivers/firewire/fw-device.h
drivers/firewire/fw-ohci.c
drivers/firewire/fw-sbp2.c
drivers/firewire/fw-transaction.c
drivers/firewire/fw-transaction.h
drivers/gpu/drm/drm_memory.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-ali1535.c
drivers/i2c/busses/i2c-ali1563.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-amd756-s4882.c
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-cpm.c [new file with mode: 0644]
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-hydra.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-i810.c [deleted file]
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-isch.c [new file with mode: 0644]
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-nforce2-s4985.c [new file with mode: 0644]
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-pasemi.c
drivers/i2c/busses/i2c-pca-platform.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-pmcmsp.c
drivers/i2c/busses/i2c-prosavage.c [deleted file]
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-savage4.c [deleted file]
drivers/i2c/busses/i2c-sibyte.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-sis630.c
drivers/i2c/busses/i2c-sis96x.c
drivers/i2c/busses/i2c-stub.c
drivers/i2c/busses/i2c-taos-evm.c
drivers/i2c/busses/i2c-via.c
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/i2c-voodoo3.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/chips/Kconfig
drivers/i2c/chips/Makefile
drivers/i2c/chips/at24.c [new file with mode: 0644]
drivers/i2c/chips/eeprom.c
drivers/i2c/chips/max6875.c
drivers/i2c/chips/pca9539.c
drivers/i2c/chips/pcf8574.c
drivers/i2c/chips/pcf8591.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ide/Kconfig
drivers/ide/Makefile
drivers/ide/arm/palm_bk3710.c
drivers/ide/h8300/ide-h8300.c
drivers/ide/ide-acpi.c
drivers/ide/ide-atapi.c [new file with mode: 0644]
drivers/ide/ide-cd.c
drivers/ide/ide-cd.h
drivers/ide/ide-cd_ioctl.c
drivers/ide/ide-disk.c
drivers/ide/ide-dma.c
drivers/ide/ide-floppy.c
drivers/ide/ide-io.c
drivers/ide/ide-iops.c
drivers/ide/ide-probe.c
drivers/ide/ide-tape.c
drivers/ide/ide-taskfile.c
drivers/ide/ide-timing.h
drivers/ide/ide.c
drivers/ide/legacy/ali14xx.c
drivers/ide/legacy/gayle.c
drivers/ide/legacy/ht6560b.c
drivers/ide/legacy/qd65xx.c
drivers/ide/pci/aec62xx.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/amd74xx.c
drivers/ide/pci/cmd640.c
drivers/ide/pci/cmd64x.c
drivers/ide/pci/cy82c693.c
drivers/ide/pci/hpt366.c
drivers/ide/pci/ns87415.c
drivers/ide/pci/scc_pata.c
drivers/ide/pci/sgiioc4.c
drivers/ide/pci/siimage.c
drivers/ide/pci/via82cxxx.c
drivers/ide/ppc/pmac.c
drivers/ide/setup-pci.c
drivers/ieee1394/csr1212.c
drivers/ieee1394/dma.c
drivers/ieee1394/highlevel.c
drivers/ieee1394/highlevel.h
drivers/ieee1394/raw1394.c
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.h
drivers/ieee1394/video1394.c
drivers/infiniband/core/addr.c
drivers/infiniband/core/agent.h
drivers/infiniband/core/cache.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/device.c
drivers/infiniband/core/fmr_pool.c
drivers/infiniband/core/mad_priv.h
drivers/infiniband/core/mad_rmpp.c
drivers/infiniband/core/mad_rmpp.h
drivers/infiniband/core/packer.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/sysfs.c
drivers/infiniband/core/ucm.c
drivers/infiniband/core/ud_header.c
drivers/infiniband/core/umem.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/amso1100/c2_rnic.c
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_hal.h
drivers/infiniband/hw/cxgb3/cxio_wr.h
drivers/infiniband/hw/cxgb3/iwch.c
drivers/infiniband/hw/cxgb3/iwch.h
drivers/infiniband/hw/cxgb3/iwch_cq.c
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/infiniband/hw/cxgb3/iwch_provider.h
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/ehca/ehca_reqs.c
drivers/infiniband/hw/ehca/hcp_if.c
drivers/infiniband/hw/ehca/hcp_if.h
drivers/infiniband/hw/ipath/ipath_cq.c
drivers/infiniband/hw/ipath/ipath_iba7220.c
drivers/infiniband/hw/ipath/ipath_mad.c
drivers/infiniband/hw/ipath/ipath_rc.c
drivers/infiniband/hw/ipath/ipath_ruc.c
drivers/infiniband/hw/ipath/ipath_uc.c
drivers/infiniband/hw/ipath/ipath_ud.c
drivers/infiniband/hw/ipath/ipath_verbs.c
drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
drivers/infiniband/hw/mlx4/cq.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mthca/mthca_allocator.c
drivers/infiniband/hw/mthca/mthca_av.c
drivers/infiniband/hw/mthca/mthca_catas.c
drivers/infiniband/hw/mthca/mthca_cmd.c
drivers/infiniband/hw/mthca/mthca_cmd.h
drivers/infiniband/hw/mthca/mthca_config_reg.h
drivers/infiniband/hw/mthca/mthca_cq.c
drivers/infiniband/hw/mthca/mthca_dev.h
drivers/infiniband/hw/mthca/mthca_doorbell.h
drivers/infiniband/hw/mthca/mthca_eq.c
drivers/infiniband/hw/mthca/mthca_mad.c
drivers/infiniband/hw/mthca/mthca_main.c
drivers/infiniband/hw/mthca/mthca_mcg.c
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/mthca/mthca_memfree.h
drivers/infiniband/hw/mthca/mthca_mr.c
drivers/infiniband/hw/mthca/mthca_pd.c
drivers/infiniband/hw/mthca/mthca_profile.c
drivers/infiniband/hw/mthca/mthca_profile.h
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/mthca/mthca_provider.h
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/hw/mthca/mthca_reset.c
drivers/infiniband/hw/mthca/mthca_srq.c
drivers/infiniband/hw/mthca/mthca_uar.c
drivers/infiniband/hw/mthca/mthca_user.h
drivers/infiniband/hw/mthca/mthca_wqe.h
drivers/infiniband/hw/nes/nes.c
drivers/infiniband/hw/nes/nes.h
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_hw.c
drivers/infiniband/hw/nes/nes_hw.h
drivers/infiniband/hw/nes/nes_utils.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/ulp/ipoib/Kconfig
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
drivers/infiniband/ulp/ipoib/ipoib_fs.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/ipoib/ipoib_verbs.c
drivers/infiniband/ulp/ipoib/ipoib_vlan.c
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/infiniband/ulp/iser/iser_memory.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h
drivers/lguest/x86/core.c
drivers/net/cxgb3/cxgb3_ctl_defs.h
drivers/net/cxgb3/cxgb3_offload.c
drivers/net/cxgb3/version.h
drivers/net/macvlan.c
drivers/net/mlx4/fw.c
drivers/net/mlx4/fw.h
drivers/net/mlx4/main.c
drivers/net/mlx4/mcg.c
drivers/scsi/a100u2w.c
drivers/scsi/ide-scsi.c
drivers/scsi/sd.c
drivers/video/fb_ddc.c
drivers/video/intelfb/intelfb_i2c.c
drivers/video/matrox/i2c-matroxfb.c
drivers/watchdog/booke_wdt.c
fs/buffer.c
fs/ext4/balloc.c
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/ext4_extents.h
fs/ext4/ext4_i.h
fs/ext4/ext4_jbd2.h
fs/ext4/ext4_sb.h
fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/fsync.c
fs/ext4/group.h
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/ext4/xattr_trusted.c
fs/ext4/xattr_user.c
fs/gfs2/Kconfig
fs/gfs2/Makefile
fs/gfs2/gfs2.h
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/locking.c
fs/gfs2/locking/dlm/lock.c
fs/gfs2/locking/dlm/lock_dlm.h
fs/gfs2/locking/dlm/mount.c
fs/gfs2/locking/dlm/sysfs.c
fs/gfs2/locking/dlm/thread.c
fs/gfs2/locking/nolock/Makefile [deleted file]
fs/gfs2/locking/nolock/main.c [deleted file]
fs/gfs2/log.c
fs/gfs2/log.h
fs/gfs2/main.c
fs/gfs2/meta_io.c
fs/gfs2/meta_io.h
fs/gfs2/ops_address.c
fs/gfs2/ops_file.c
fs/gfs2/ops_fstype.c
fs/gfs2/ops_inode.c
fs/gfs2/ops_super.c
fs/gfs2/quota.c
fs/gfs2/recovery.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/gfs2/sys.c
fs/jbd2/checkpoint.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/jbd2/transaction.c
fs/jfs/jfs_debug.c
fs/jfs/jfs_debug.h
fs/jfs/jfs_dtree.h
fs/jfs/jfs_imap.c
fs/jfs/jfs_logmgr.c
fs/jfs/jfs_metapage.c
fs/jfs/jfs_txnmgr.c
fs/jfs/jfs_xtree.c
fs/jfs/namei.c
fs/jfs/super.c
fs/mpage.c
include/asm-alpha/smp.h
include/asm-arm/smp.h
include/asm-generic/pgtable.h
include/asm-ia64/smp.h
include/asm-m32r/smp.h
include/asm-mips/smp.h
include/asm-parisc/smp.h
include/asm-powerpc/smp.h
include/asm-sh/smp.h
include/asm-sparc/smp.h
include/asm-x86/dwarf2.h
include/asm-x86/hw_irq.h
include/asm-x86/irq_vectors.h
include/asm-x86/mach-default/entry_arch.h
include/asm-x86/mach-visws/entry_arch.h
include/asm-x86/mach-voyager/entry_arch.h
include/asm-x86/smp.h
include/asm-x86/xen/events.h
include/drm/drmP.h
include/linux/blkdev.h
include/linux/dcache.h
include/linux/fs.h
include/linux/i2c-algo-pcf.h
include/linux/i2c-id.h
include/linux/i2c.h
include/linux/i2c/at24.h [new file with mode: 0644]
include/linux/ide.h
include/linux/interrupt.h
include/linux/irq.h
include/linux/jbd2.h
include/linux/libata.h
include/linux/list.h
include/linux/lm_interface.h
include/linux/mlx4/device.h
include/linux/mpage.h
include/linux/percpu_counter.h
include/linux/rcuclassic.h
include/linux/rculist.h
include/linux/rcupdate.h
include/linux/rcupreempt.h
include/linux/smp.h
include/linux/topology.h
include/linux/writeback.h
include/rdma/ib_addr.h
include/rdma/ib_cache.h
include/rdma/ib_cm.h
include/rdma/ib_fmr_pool.h
include/rdma/ib_mad.h
include/rdma/ib_pack.h
include/rdma/ib_sa.h
include/rdma/ib_smi.h
include/rdma/ib_user_cm.h
include/rdma/ib_user_mad.h
include/rdma/ib_user_verbs.h
include/rdma/ib_verbs.h
include/rdma/iw_cm.h
include/rdma/rdma_cm.h
include/rdma/rdma_cm_ib.h
include/scsi/scsi_device.h
init/main.c
kernel/Makefile
kernel/backtracetest.c
kernel/hrtimer.c
kernel/irq/manage.c
kernel/irq/proc.c
kernel/pid.c
kernel/posix-cpu-timers.c
kernel/profile.c
kernel/rcuclassic.c
kernel/rcupdate.c
kernel/rcupreempt.c
kernel/rcupreempt_trace.c
kernel/rcutorture.c
kernel/smp.c [new file with mode: 0644]
kernel/softirq.c
kernel/stacktrace.c
kernel/sysctl.c
kernel/time/tick-broadcast.c
kernel/time/tick-sched.c
lib/Kconfig.debug
lib/percpu_counter.c
lib/textsearch.c
mm/filemap.c
mm/page-writeback.c
mm/page_alloc.c
mm/slab.c
mm/slub.c
net/802/psnap.c
net/8021q/vlan.c
net/bridge/br_fdb.c
net/bridge/br_stp.c
net/core/flow.c
net/iucv/iucv.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_netlink.c
net/netlabel/netlabel_domainhash.c
security/selinux/hooks.c
security/selinux/include/security.h
security/selinux/ss/services.c
virt/kvm/kvm_main.c

index 938d7dd..b4a615b 100644 (file)
@@ -1,17 +1,26 @@
+ChangeLog:
+       Started by Ingo Molnar <mingo@redhat.com>
+       Update by Max Krasnyansky <maxk@qualcomm.com>
 
-SMP IRQ affinity, started by Ingo Molnar <mingo@redhat.com>
-
+SMP IRQ affinity
 
 /proc/irq/IRQ#/smp_affinity specifies which target CPUs are permitted
 for a given IRQ source. It's a bitmask of allowed CPUs. It's not allowed
 to turn off all CPUs, and if an IRQ controller does not support IRQ
 affinity then the value will not change from the default 0xffffffff.
 
+/proc/irq/default_smp_affinity specifies default affinity mask that applies
+to all non-active IRQs. Once IRQ is allocated/activated its affinity bitmask
+will be set to the default mask. It can then be changed as described above.
+Default mask is 0xffffffff.
+
 Here is an example of restricting IRQ44 (eth1) to CPU0-3 then restricting
-the IRQ to CPU4-7 (this is an 8-CPU SMP box):
+it to CPU4-7 (this is an 8-CPU SMP box):
 
+[root@moon 44]# cd /proc/irq/44
 [root@moon 44]# cat smp_affinity
 ffffffff
+
 [root@moon 44]# echo 0f > smp_affinity
 [root@moon 44]# cat smp_affinity
 0000000f
@@ -21,17 +30,27 @@ PING hell (195.4.7.3): 56 data bytes
 --- hell ping statistics ---
 6029 packets transmitted, 6027 packets received, 0% packet loss
 round-trip min/avg/max = 0.1/0.1/0.4 ms
-[root@moon 44]# cat /proc/interrupts | grep 44:
- 44:          0       1785       1785       1783       1783          1
-1          0   IO-APIC-level  eth1
+[root@moon 44]# cat /proc/interrupts | grep 'CPU\|44:'
+           CPU0       CPU1       CPU2       CPU3      CPU4       CPU5        CPU6       CPU7
+ 44:       1068       1785       1785       1783         0          0           0         0    IO-APIC-level  eth1
+
+As can be seen from the line above IRQ44 was delivered only to the first four
+processors (0-3).
+Now lets restrict that IRQ to CPU(4-7).
+
 [root@moon 44]# echo f0 > smp_affinity
+[root@moon 44]# cat smp_affinity
+000000f0
 [root@moon 44]# ping -f h
 PING hell (195.4.7.3): 56 data bytes
 ..
 --- hell ping statistics ---
 2779 packets transmitted, 2777 packets received, 0% packet loss
 round-trip min/avg/max = 0.1/0.5/585.4 ms
-[root@moon 44]# cat /proc/interrupts | grep 44:
- 44:       1068       1785       1785       1784       1784       1069       1070       1069   IO-APIC-level  eth1
-[root@moon 44]#
+[root@moon 44]# cat /proc/interrupts |  'CPU\|44:'
+           CPU0       CPU1       CPU2       CPU3      CPU4       CPU5        CPU6       CPU7
+ 44:       1068       1785       1785       1783      1784       1069        1070       1069   IO-APIC-level  eth1
+
+This time around IRQ44 was delivered only to the last four processors.
+i.e counters for the CPU0-3 did not change.
 
index c64158e..a6d32e6 100644 (file)
@@ -93,6 +93,9 @@ Since NMI handlers disable preemption, synchronize_sched() is guaranteed
 not to return until all ongoing NMI handlers exit.  It is therefore safe
 to free up the handler's data as soon as synchronize_sched() returns.
 
+Important note: for this to work, the architecture in question must
+invoke irq_enter() and irq_exit() on NMI entry and exit, respectively.
+
 
 Answer to Quick Quiz
 
index 39ad8f5..9f711d2 100644 (file)
@@ -52,6 +52,10 @@ of each iteration.  Unfortunately, chaotic relaxation requires highly
 structured data, such as the matrices used in scientific programs, and
 is thus inapplicable to most data structures in operating-system kernels.
 
+In 1992, Henry (now Alexia) Massalin completed a dissertation advising
+parallel programmers to defer processing when feasible to simplify
+synchronization.  RCU makes extremely heavy use of this advice.
+
 In 1993, Jacobson [Jacobson93] verbally described what is perhaps the
 simplest deferred-free technique: simply waiting a fixed amount of time
 before freeing blocks awaiting deferred free.  Jacobson did not describe
@@ -138,6 +142,13 @@ blocking in read-side critical sections appeared [PaulEMcKenney2006c],
 Robert Olsson described an RCU-protected trie-hash combination
 [RobertOlsson2006a].
 
+2007 saw the journal version of the award-winning RCU paper from 2006
+[ThomasEHart2007a], as well as a paper demonstrating use of Promela
+and Spin to mechanically verify an optimization to Oleg Nesterov's
+QRCU [PaulEMcKenney2007QRCUspin], a design document describing
+preemptible RCU [PaulEMcKenney2007PreemptibleRCU], and the three-part
+LWN "What is RCU?" series [PaulEMcKenney2007WhatIsRCUFundamentally,
+PaulEMcKenney2008WhatIsRCUUsage, and PaulEMcKenney2008WhatIsRCUAPI].
 
 Bibtex Entries
 
@@ -202,6 +213,20 @@ Bibtex Entries
 ,Year="1991"
 }
 
+@phdthesis{HMassalinPhD
+,author="H. Massalin"
+,title="Synthesis: An Efficient Implementation of Fundamental Operating
+System Services"
+,school="Columbia University"
+,address="New York, NY"
+,year="1992"
+,annotation="
+       Mondo optimizing compiler.
+       Wait-free stuff.
+       Good advice: defer work to avoid synchronization.
+"
+}
+
 @unpublished{Jacobson93
 ,author="Van Jacobson"
 ,title="Avoid Read-Side Locking Via Delayed Free"
@@ -635,3 +660,86 @@ Revised:
 "
 }
 
+@unpublished{PaulEMcKenney2007PreemptibleRCU
+,Author="Paul E. McKenney"
+,Title="The design of preemptible read-copy-update"
+,month="October"
+,day="8"
+,year="2007"
+,note="Available:
+\url{http://lwn.net/Articles/253651/}
+[Viewed October 25, 2007]"
+,annotation="
+       LWN article describing the design of preemptible RCU.
+"
+}
+
+########################################################################
+#
+#      "What is RCU?" LWN series.
+#
+
+@unpublished{PaulEMcKenney2007WhatIsRCUFundamentally
+,Author="Paul E. McKenney and Jonathan Walpole"
+,Title="What is {RCU}, Fundamentally?"
+,month="December"
+,day="17"
+,year="2007"
+,note="Available:
+\url{http://lwn.net/Articles/262464/}
+[Viewed December 27, 2007]"
+,annotation="
+       Lays out the three basic components of RCU: (1) publish-subscribe,
+       (2) wait for pre-existing readers to complete, and (2) maintain
+       multiple versions.
+"
+}
+
+@unpublished{PaulEMcKenney2008WhatIsRCUUsage
+,Author="Paul E. McKenney"
+,Title="What is {RCU}? Part 2: Usage"
+,month="January"
+,day="4"
+,year="2008"
+,note="Available:
+\url{http://lwn.net/Articles/263130/}
+[Viewed January 4, 2008]"
+,annotation="
+       Lays out six uses of RCU:
+       1. RCU is a Reader-Writer Lock Replacement
+       2. RCU is a Restricted Reference-Counting Mechanism
+       3. RCU is a Bulk Reference-Counting Mechanism
+       4. RCU is a Poor Man's Garbage Collector
+       5. RCU is a Way of Providing Existence Guarantees
+       6. RCU is a Way of Waiting for Things to Finish 
+"
+}
+
+@unpublished{PaulEMcKenney2008WhatIsRCUAPI
+,Author="Paul E. McKenney"
+,Title="{RCU} part 3: the {RCU} {API}"
+,month="January"
+,day="17"
+,year="2008"
+,note="Available:
+\url{http://lwn.net/Articles/264090/}
+[Viewed January 10, 2008]"
+,annotation="
+       Gives an overview of the Linux-kernel RCU API and a brief annotated RCU
+       bibliography.
+"
+}
+
+@article{DinakarGuniguntala2008IBMSysJ
+,author="D. Guniguntala and P. E. McKenney and J. Triplett and J. Walpole"
+,title="The read-copy-update mechanism for supporting real-time applications on shared-memory multiprocessor systems with {Linux}"
+,Year="2008"
+,Month="April"
+,journal="IBM Systems Journal"
+,volume="47"
+,number="2"
+,pages="@@-@@"
+,annotation="
+       RCU, realtime RCU, sleepable RCU, performance.
+"
+}
index 42b01bc..cf5562c 100644 (file)
@@ -13,10 +13,13 @@ over a rather long period of time, but improvements are always welcome!
        detailed performance measurements show that RCU is nonetheless
        the right tool for the job.
 
-       The other exception would be where performance is not an issue,
-       and RCU provides a simpler implementation.  An example of this
-       situation is the dynamic NMI code in the Linux 2.6 kernel,
-       at least on architectures where NMIs are rare.
+       Another exception is where performance is not an issue, and RCU
+       provides a simpler implementation.  An example of this situation
+       is the dynamic NMI code in the Linux 2.6 kernel, at least on
+       architectures where NMIs are rare.
+
+       Yet another exception is where the low real-time latency of RCU's
+       read-side primitives is critically important.
 
 1.     Does the update code have proper mutual exclusion?
 
@@ -39,9 +42,10 @@ over a rather long period of time, but improvements are always welcome!
 
 2.     Do the RCU read-side critical sections make proper use of
        rcu_read_lock() and friends?  These primitives are needed
-       to suppress preemption (or bottom halves, in the case of
-       rcu_read_lock_bh()) in the read-side critical sections,
-       and are also an excellent aid to readability.
+       to prevent grace periods from ending prematurely, which
+       could result in data being unceremoniously freed out from
+       under your read-side code, which can greatly increase the
+       actuarial risk of your kernel.
 
        As a rough rule of thumb, any dereference of an RCU-protected
        pointer must be covered by rcu_read_lock() or rcu_read_lock_bh()
@@ -54,15 +58,30 @@ over a rather long period of time, but improvements are always welcome!
        be running while updates are in progress.  There are a number
        of ways to handle this concurrency, depending on the situation:
 
-       a.      Make updates appear atomic to readers.  For example,
+       a.      Use the RCU variants of the list and hlist update
+               primitives to add, remove, and replace elements on an
+               RCU-protected list.  Alternatively, use the RCU-protected
+               trees that have been added to the Linux kernel.
+
+               This is almost always the best approach.
+
+       b.      Proceed as in (a) above, but also maintain per-element
+               locks (that are acquired by both readers and writers)
+               that guard per-element state.  Of course, fields that
+               the readers refrain from accessing can be guarded by the
+               update-side lock.
+
+               This works quite well, also.
+
+       c.      Make updates appear atomic to readers.  For example,
                pointer updates to properly aligned fields will appear
                atomic, as will individual atomic primitives.  Operations
                performed under a lock and sequences of multiple atomic
                primitives will -not- appear to be atomic.
 
-               This is almost always the best approach.
+               This can work, but is starting to get a bit tricky.
 
-       b.      Carefully order the updates and the reads so that
+       d.      Carefully order the updates and the reads so that
                readers see valid data at all phases of the update.
                This is often more difficult than it sounds, especially
                given modern CPUs' tendency to reorder memory references.
@@ -123,18 +142,22 @@ over a rather long period of time, but improvements are always welcome!
                when publicizing a pointer to a structure that can
                be traversed by an RCU read-side critical section.
 
-5.     If call_rcu(), or a related primitive such as call_rcu_bh(),
-       is used, the callback function must be written to be called
-       from softirq context.  In particular, it cannot block.
+5.     If call_rcu(), or a related primitive such as call_rcu_bh() or
+       call_rcu_sched(), is used, the callback function must be
+       written to be called from softirq context.  In particular,
+       it cannot block.
 
 6.     Since synchronize_rcu() can block, it cannot be called from
-       any sort of irq context.
+       any sort of irq context.  Ditto for synchronize_sched() and
+       synchronize_srcu().
 
 7.     If the updater uses call_rcu(), then the corresponding readers
        must use rcu_read_lock() and rcu_read_unlock().  If the updater
        uses call_rcu_bh(), then the corresponding readers must use
-       rcu_read_lock_bh() and rcu_read_unlock_bh().  Mixing things up
-       will result in confusion and broken kernels.
+       rcu_read_lock_bh() and rcu_read_unlock_bh().  If the updater
+       uses call_rcu_sched(), then the corresponding readers must
+       disable preemption.  Mixing things up will result in confusion
+       and broken kernels.
 
        One exception to this rule: rcu_read_lock() and rcu_read_unlock()
        may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
@@ -143,9 +166,9 @@ over a rather long period of time, but improvements are always welcome!
        such cases is a must, of course!  And the jury is still out on
        whether the increased speed is worth it.
 
-8.     Although synchronize_rcu() is a bit slower than is call_rcu(),
-       it usually results in simpler code.  So, unless update
-       performance is critically important or the updaters cannot block,
+8.     Although synchronize_rcu() is slower than is call_rcu(), it
+       usually results in simpler code.  So, unless update performance
+       is critically important or the updaters cannot block,
        synchronize_rcu() should be used in preference to call_rcu().
 
        An especially important property of the synchronize_rcu()
@@ -187,23 +210,23 @@ over a rather long period of time, but improvements are always welcome!
                number of updates per grace period.
 
 9.     All RCU list-traversal primitives, which include
-       list_for_each_rcu(), list_for_each_entry_rcu(),
+       rcu_dereference(), list_for_each_rcu(), list_for_each_entry_rcu(),
        list_for_each_continue_rcu(), and list_for_each_safe_rcu(),
-       must be within an RCU read-side critical section.  RCU
+       must be either within an RCU read-side critical section or
+       must be protected by appropriate update-side locks.  RCU
        read-side critical sections are delimited by rcu_read_lock()
        and rcu_read_unlock(), or by similar primitives such as
        rcu_read_lock_bh() and rcu_read_unlock_bh().
 
-       Use of the _rcu() list-traversal primitives outside of an
-       RCU read-side critical section causes no harm other than
-       a slight performance degradation on Alpha CPUs.  It can
-       also be quite helpful in reducing code bloat when common
-       code is shared between readers and updaters.
+       The reason that it is permissible to use RCU list-traversal
+       primitives when the update-side lock is held is that doing so
+       can be quite helpful in reducing code bloat when common code is
+       shared between readers and updaters.
 
 10.    Conversely, if you are in an RCU read-side critical section,
-       you -must- use the "_rcu()" variants of the list macros.
-       Failing to do so will break Alpha and confuse people reading
-       your code.
+       and you don't hold the appropriate update-side lock, you -must-
+       use the "_rcu()" variants of the list macros.  Failing to do so
+       will break Alpha and confuse people reading your code.
 
 11.    Note that synchronize_rcu() -only- guarantees to wait until
        all currently executing rcu_read_lock()-protected RCU read-side
@@ -230,6 +253,14 @@ over a rather long period of time, but improvements are always welcome!
        must use whatever locking or other synchronization is required
        to safely access and/or modify that data structure.
 
+       RCU callbacks are -usually- executed on the same CPU that executed
+       the corresponding call_rcu(), call_rcu_bh(), or call_rcu_sched(),
+       but are by -no- means guaranteed to be.  For example, if a given
+       CPU goes offline while having an RCU callback pending, then that
+       RCU callback will execute on some surviving CPU.  (If this was
+       not the case, a self-spawning RCU callback would prevent the
+       victim CPU from ever going offline.)
+
 14.    SRCU (srcu_read_lock(), srcu_read_unlock(), and synchronize_srcu())
        may only be invoked from process context.  Unlike other forms of
        RCU, it -is- permissible to block in an SRCU read-side critical
index 2967a65..a342b6e 100644 (file)
@@ -10,23 +10,30 @@ status messages via printk(), which can be examined via the dmesg
 command (perhaps grepping for "torture").  The test is started
 when the module is loaded, and stops when the module is unloaded.
 
-However, actually setting this config option to "y" results in the system
-running the test immediately upon boot, and ending only when the system
-is taken down.  Normally, one will instead want to build the system
-with CONFIG_RCU_TORTURE_TEST=m and to use modprobe and rmmod to control
-the test, perhaps using a script similar to the one shown at the end of
-this document.  Note that you will need CONFIG_MODULE_UNLOAD in order
-to be able to end the test.
+CONFIG_RCU_TORTURE_TEST_RUNNABLE
+
+It is also possible to specify CONFIG_RCU_TORTURE_TEST=y, which will
+result in the tests being loaded into the base kernel.  In this case,
+the CONFIG_RCU_TORTURE_TEST_RUNNABLE config option is used to specify
+whether the RCU torture tests are to be started immediately during
+boot or whether the /proc/sys/kernel/rcutorture_runnable file is used
+to enable them.  This /proc file can be used to repeatedly pause and
+restart the tests, regardless of the initial state specified by the
+CONFIG_RCU_TORTURE_TEST_RUNNABLE config option.
+
+You will normally -not- want to start the RCU torture tests during boot
+(and thus the default is CONFIG_RCU_TORTURE_TEST_RUNNABLE=n), but doing
+this can sometimes be useful in finding boot-time bugs.
 
 
 MODULE PARAMETERS
 
 This module has the following parameters:
 
-nreaders       This is the number of RCU reading threads supported.
-               The default is twice the number of CPUs.  Why twice?
-               To properly exercise RCU implementations with preemptible
-               read-side critical sections.
+irqreaders     Says to invoke RCU readers from irq level.  This is currently
+               done via timers.  Defaults to "1" for variants of RCU that
+               permit this.  (Or, more accurately, variants of RCU that do
+               -not- permit this know to ignore this variable.)
 
 nfakewriters   This is the number of RCU fake writer threads to run.  Fake
                writer threads repeatedly use the synchronous "wait for
@@ -37,6 +44,16 @@ nfakewriters This is the number of RCU fake writer threads to run.  Fake
                to trigger special cases caused by multiple writers, such as
                the synchronize_srcu() early return optimization.
 
+nreaders       This is the number of RCU reading threads supported.
+               The default is twice the number of CPUs.  Why twice?
+               To properly exercise RCU implementations with preemptible
+               read-side critical sections.
+
+shuffle_interval
+               The number of seconds to keep the test threads affinitied
+               to a particular subset of the CPUs, defaults to 3 seconds.
+               Used in conjunction with test_no_idle_hz.
+
 stat_interval  The number of seconds between output of torture
                statistics (via printk()).  Regardless of the interval,
                statistics are printed when the module is unloaded.
@@ -44,10 +61,11 @@ stat_interval       The number of seconds between output of torture
                be printed -only- when the module is unloaded, and this
                is the default.
 
-shuffle_interval
-               The number of seconds to keep the test threads affinitied
-               to a particular subset of the CPUs, defaults to 5 seconds.
-               Used in conjunction with test_no_idle_hz.
+stutter                The length of time to run the test before pausing for this
+               same period of time.  Defaults to "stutter=5", so as
+               to run and pause for (roughly) five-second intervals.
+               Specifying "stutter=0" causes the test to run continuously
+               without pausing, which is the old default behavior.
 
 test_no_idle_hz        Whether or not to test the ability of RCU to operate in
                a kernel that disables the scheduling-clock interrupt to
index e0d6d99..e04d643 100644 (file)
@@ -1,3 +1,11 @@
+Please note that the "What is RCU?" LWN series is an excellent place
+to start learning about RCU:
+
+1.     What is RCU, Fundamentally?  http://lwn.net/Articles/262464/
+2.     What is RCU? Part 2: Usage   http://lwn.net/Articles/263130/
+3.     RCU part 3: the RCU API      http://lwn.net/Articles/264090/
+
+
 What is RCU?
 
 RCU is a synchronization mechanism that was added to the Linux kernel
@@ -772,26 +780,18 @@ Linux-kernel source code, but it helps to have a full list of the
 APIs, since there does not appear to be a way to categorize them
 in docbook.  Here is the list, by category.
 
-Markers for RCU read-side critical sections:
-
-       rcu_read_lock
-       rcu_read_unlock
-       rcu_read_lock_bh
-       rcu_read_unlock_bh
-       srcu_read_lock
-       srcu_read_unlock
-
 RCU pointer/list traversal:
 
        rcu_dereference
+       list_for_each_entry_rcu
+       hlist_for_each_entry_rcu
+
        list_for_each_rcu               (to be deprecated in favor of
                                         list_for_each_entry_rcu)
-       list_for_each_entry_rcu
        list_for_each_continue_rcu      (to be deprecated in favor of new
                                         list_for_each_entry_continue_rcu)
-       hlist_for_each_entry_rcu
 
-RCU pointer update:
+RCU pointer/list update:
 
        rcu_assign_pointer
        list_add_rcu
@@ -799,16 +799,36 @@ RCU pointer update:
        list_del_rcu
        list_replace_rcu
        hlist_del_rcu
+       hlist_add_after_rcu
+       hlist_add_before_rcu
        hlist_add_head_rcu
+       hlist_replace_rcu
+       list_splice_init_rcu()
 
-RCU grace period:
+RCU:   Critical sections       Grace period            Barrier
+
+       rcu_read_lock           synchronize_net         rcu_barrier
+       rcu_read_unlock         synchronize_rcu
+                               call_rcu
+
+
+bh:    Critical sections       Grace period            Barrier
+
+       rcu_read_lock_bh        call_rcu_bh             rcu_barrier_bh
+       rcu_read_unlock_bh
+
+
+sched: Critical sections       Grace period            Barrier
+
+       [preempt_disable]       synchronize_sched       rcu_barrier_sched
+       [and friends]           call_rcu_sched
+
+
+SRCU:  Critical sections       Grace period            Barrier
+
+       srcu_read_lock          synchronize_srcu        N/A
+       srcu_read_unlock
 
-       synchronize_net
-       synchronize_sched
-       synchronize_rcu
-       synchronize_srcu
-       call_rcu
-       call_rcu_bh
 
 See the comment headers in the source code (or the docbook generated
 from them) for more information.
index b61cb95..bd699da 100644 (file)
@@ -14,9 +14,8 @@ represent the thread siblings to cpu X in the same physical package;
 To implement it in an architecture-neutral way, a new source file,
 drivers/base/topology.c, is to export the 4 attributes.
 
-If one architecture wants to support this feature, it just needs to
-implement 4 defines, typically in file include/asm-XXX/topology.h.
-The 4 defines are:
+For an architecture to support this feature, it must define some of
+these macros in include/asm-XXX/topology.h:
 #define topology_physical_package_id(cpu)
 #define topology_core_id(cpu)
 #define topology_thread_siblings(cpu)
@@ -25,17 +24,10 @@ The 4 defines are:
 The type of **_id is int.
 The type of siblings is cpumask_t.
 
-To be consistent on all architectures, the 4 attributes should have
-default values if their values are unavailable. Below is the rule.
-1) physical_package_id: If cpu has no physical package id, -1 is the
-default value.
-2) core_id: If cpu doesn't support multi-core, its core id is 0.
-3) thread_siblings: Just include itself, if the cpu doesn't support
-HT/multi-thread.
-4) core_siblings: Just include itself, if the cpu doesn't support
-multi-core and HT/Multi-thread.
-
-So be careful when declaring the 4 defines in include/asm-XXX/topology.h.
-
-If an attribute isn't defined on an architecture, it won't be exported.
-
+To be consistent on all architectures, include/linux/topology.h
+provides default definitions for any of the above macros that are
+not defined by include/asm-XXX/topology.h:
+1) physical_package_id: -1
+2) core_id: 0
+3) thread_siblings: just the given CPU
+4) core_siblings: just the given CPU
index 46ece3f..65a1482 100644 (file)
@@ -222,13 +222,6 @@ Who:       Thomas Gleixner <tglx@linutronix.de>
 
 ---------------------------
 
-What:  i2c-i810, i2c-prosavage and i2c-savage4
-When:  May 2008
-Why:   These drivers are superseded by i810fb, intelfb and savagefb.
-Who:   Jean Delvare <khali@linux-fr.org>
-
----------------------------
-
 What (Why):
        - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
          (superseded by xt_TOS/xt_tos target & match)
index 0c5086d..80e193d 100644 (file)
@@ -13,72 +13,93 @@ Mailing list: linux-ext4@vger.kernel.org
 1. Quick usage instructions:
 ===========================
 
-  - Grab updated e2fsprogs from
-    ftp://ftp.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs-interim/
-    This is a patchset on top of e2fsprogs-1.39, which can be found at
+  - Compile and install the latest version of e2fsprogs (as of this
+    writing version 1.41) from:
+
+    http://sourceforge.net/project/showfiles.php?group_id=2406
+       
+       or
+
     ftp://ftp.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/
 
-  - It's still mke2fs -j /dev/hda1
+       or grab the latest git repository from:
+
+    git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
+
+  - Create a new filesystem using the ext4dev filesystem type:
+
+       # mke2fs -t ext4dev /dev/hda1
+
+    Or configure an existing ext3 filesystem to support extents and set
+    the test_fs flag to indicate that it's ok for an in-development
+    filesystem to touch this filesystem:
 
-  - mount /dev/hda1 /wherever -t ext4dev
+       # tune2fs -O extents -E test_fs /dev/hda1
 
-  - To enable extents,
+    If the filesystem was created with 128 byte inodes, it can be
+    converted to use 256 byte for greater efficiency via:
 
-       mount /dev/hda1 /wherever -t ext4dev -o extents
+        # tune2fs -I 256 /dev/hda1
 
-  - The filesystem is compatible with the ext3 driver until you add a file
-    which has extents (ie: `mount -o extents', then create a file).
+    (Note: we currently do not have tools to convert an ext4dev
+    filesystem back to ext3; so please do not do try this on production
+    filesystems.)
 
-    NOTE: The "extents" mount flag is temporary.  It will soon go away and
-    extents will be enabled by the "-o extents" flag to mke2fs or tune2fs
+  - Mounting:
+
+       # mount -t ext4dev /dev/hda1 /wherever
 
   - When comparing performance with other filesystems, remember that
-    ext3/4 by default offers higher data integrity guarantees than most.  So
-    when comparing with a metadata-only journalling filesystem, use `mount -o
-    data=writeback'.  And you might as well use `mount -o nobh' too along
-    with it.  Making the journal larger than the mke2fs default often helps
-    performance with metadata-intensive workloads.
+    ext3/4 by default offers higher data integrity guarantees than most.
+    So when comparing with a metadata-only journalling filesystem, such
+    as ext3, use `mount -o data=writeback'.  And you might as well use
+    `mount -o nobh' too along with it.  Making the journal larger than
+    the mke2fs default often helps performance with metadata-intensive
+    workloads.
 
 2. Features
 ===========
 
 2.1 Currently available
 
-* ability to use filesystems > 16TB
+* ability to use filesystems > 16TB (e2fsprogs support not available yet)
 * extent format reduces metadata overhead (RAM, IO for access, transactions)
 * extent format more robust in face of on-disk corruption due to magics,
 * internal redunancy in tree
-
-2.1 Previously available, soon to be enabled by default by "mkefs.ext4":
-
-* dir_index and resize inode will be on by default
-* large inodes will be used by default for fast EAs, nsec timestamps, etc
+* improved file allocation (multi-block alloc)
+* fix 32000 subdirectory limit
+* nsec timestamps for mtime, atime, ctime, create time
+* inode version field on disk (NFSv4, Lustre)
+* reduced e2fsck time via uninit_bg feature
+* journal checksumming for robustness, performance
+* persistent file preallocation (e.g for streaming media, databases)
+* ability to pack bitmaps and inode tables into larger virtual groups via the
+  flex_bg feature
+* large file support
+* Inode allocation using large virtual block groups via flex_bg
+* delayed allocation
+* large block (up to pagesize) support
+* efficent new ordered mode in JBD2 and ext4(avoid using buffer head to force
+  the ordering)
 
 2.2 Candidate features for future inclusion
 
-There are several under discussion, whether they all make it in is
-partly a function of how much time everyone has to work on them:
+* Online defrag (patches available but not well tested)
+* reduced mke2fs time via lazy itable initialization in conjuction with
+  the uninit_bg feature (capability to do this is available in e2fsprogs
+  but a kernel thread to do lazy zeroing of unused inode table blocks
+  after filesystem is first mounted is required for safety)
 
-* improved file allocation (multi-block alloc, delayed alloc; basically done)
-* fix 32000 subdirectory limit (patch exists, needs some e2fsck work)
-* nsec timestamps for mtime, atime, ctime, create time (patch exists,
-  needs some e2fsck work)
-* inode version field on disk (NFSv4, Lustre; prototype exists)
-* reduced mke2fs/e2fsck time via uninitialized groups (prototype exists)
-* journal checksumming for robustness, performance (prototype exists)
-* persistent file preallocation (e.g for streaming media, databases)
+There are several others under discussion, whether they all make it in is
+partly a function of how much time everyone has to work on them. Features like
+metadata checksumming have been discussed and planned for a bit but no patches
+exist yet so I'm not sure they're in the near-term roadmap.
 
-Features like metadata checksumming have been discussed and planned for
-a bit but no patches exist yet so I'm not sure they're in the near-term
-roadmap.
+The big performance win will come with mballoc, delalloc and flex_bg
+grouping of bitmaps and inode tables.  Some test results available here:
 
-The big performance win will come with mballoc and delalloc.  CFS has
-been using mballoc for a few years already with Lustre, and IBM + Bull
-did a lot of benchmarking on it.  The reason it isn't in the first set of
-patches is partly a manageability issue, and partly because it doesn't
-directly affect the on-disk format (outside of much better allocation)
-so it isn't critical to get into the first round of changes.  I believe
-Alex is working on a new set of patches right now.
+ - http://www.bullopensource.org/ext4/20080530/ffsb-write-2.6.26-rc2.html
+ - http://www.bullopensource.org/ext4/20080530/ffsb-readwrite-2.6.26-rc2.html
 
 3. Options
 ==========
@@ -222,9 +243,11 @@ stripe=n           Number of filesystem blocks that mballoc will try
                        to use for allocation size and alignment. For RAID5/6
                        systems this should be the number of data
                        disks *  RAID chunk size in file system blocks.
-
+delalloc       (*)     Deferring block allocation until write-out time.
+nodelalloc             Disable delayed allocation. Blocks are allocation
+                       when data is copied from user to page cache.
 Data Mode
----------
+=========
 There are 3 different data modes:
 
 * writeback mode
@@ -236,10 +259,10 @@ typically provide the best ext4 performance.
 
 * ordered mode
 In data=ordered mode, ext4 only officially journals metadata, but it logically
-groups metadata and data blocks into a single unit called a transaction.  When
-it's time to write the new metadata out to disk, the associated data blocks
-are written first.  In general, this mode performs slightly slower than
-writeback but significantly faster than journal mode.
+groups metadata information related to data changes with the data blocks into a
+single unit called a transaction.  When it's time to write the new metadata
+out to disk, the associated data blocks are written first.  In general,
+this mode performs slightly slower than writeback but significantly faster than journal mode.
 
 * journal mode
 data=journal mode provides full data and metadata journaling.  All new data is
@@ -247,7 +270,8 @@ written to the journal first, and then to its final location.
 In the event of a crash, the journal can be replayed, bringing both data and
 metadata into a consistent state.  This mode is the slowest except when data
 needs to be read from and written to disk at the same time where it
-outperforms all others modes.
+outperforms all others modes.  Curently ext4 does not have delayed
+allocation support if this data journalling mode is selected.
 
 References
 ==========
@@ -256,7 +280,8 @@ kernel source:      <file:fs/ext4/>
                <file:fs/jbd2/>
 
 programs:      http://e2fsprogs.sourceforge.net/
-               http://ext2resize.sourceforge.net
 
 useful links:  http://fedoraproject.org/wiki/ext3-devel
                http://www.bullopensource.org/ext4/
+               http://ext4.wiki.kernel.org/index.php/Main_Page
+               http://fedoraproject.org/wiki/Features/Ext4
diff --git a/Documentation/filesystems/gfs2-glocks.txt b/Documentation/filesystems/gfs2-glocks.txt
new file mode 100644 (file)
index 0000000..4dae9a3
--- /dev/null
@@ -0,0 +1,114 @@
+                   Glock internal locking rules
+                  ------------------------------
+
+This documents the basic principles of the glock state machine
+internals. Each glock (struct gfs2_glock in fs/gfs2/incore.h)
+has two main (internal) locks:
+
+ 1. A spinlock (gl_spin) which protects the internal state such
+    as gl_state, gl_target and the list of holders (gl_holders)
+ 2. A non-blocking bit lock, GLF_LOCK, which is used to prevent other
+    threads from making calls to the DLM, etc. at the same time. If a
+    thread takes this lock, it must then call run_queue (usually via the
+    workqueue) when it releases it in order to ensure any pending tasks
+    are completed.
+
+The gl_holders list contains all the queued lock requests (not
+just the holders) associated with the glock. If there are any
+held locks, then they will be contiguous entries at the head
+of the list. Locks are granted in strictly the order that they
+are queued, except for those marked LM_FLAG_PRIORITY which are
+used only during recovery, and even then only for journal locks.
+
+There are three lock states that users of the glock layer can request,
+namely shared (SH), deferred (DF) and exclusive (EX). Those translate
+to the following DLM lock modes:
+
+Glock mode    | DLM lock mode
+------------------------------
+    UN        |    IV/NL  Unlocked (no DLM lock associated with glock) or NL
+    SH        |    PR     (Protected read)
+    DF        |    CW     (Concurrent write)
+    EX        |    EX     (Exclusive)
+
+Thus DF is basically a shared mode which is incompatible with the "normal"
+shared lock mode, SH. In GFS2 the DF mode is used exclusively for direct I/O
+operations. The glocks are basically a lock plus some routines which deal
+with cache management. The following rules apply for the cache:
+
+Glock mode   |  Cache data | Cache Metadata | Dirty Data | Dirty Metadata
+--------------------------------------------------------------------------
+    UN       |     No      |       No       |     No     |      No
+    SH       |     Yes     |       Yes      |     No     |      No
+    DF       |     No      |       Yes      |     No     |      No
+    EX       |     Yes     |       Yes      |     Yes    |      Yes
+
+These rules are implemented using the various glock operations which
+are defined for each type of glock. Not all types of glocks use
+all the modes. Only inode glocks use the DF mode for example.
+
+Table of glock operations and per type constants:
+
+Field            | Purpose
+----------------------------------------------------------------------------
+go_xmote_th      | Called before remote state change (e.g. to sync dirty data)
+go_xmote_bh      | Called after remote state change (e.g. to refill cache)
+go_inval         | Called if remote state change requires invalidating the cache
+go_demote_ok     | Returns boolean value of whether its ok to demote a glock
+                 | (e.g. checks timeout, and that there is no cached data)
+go_lock          | Called for the first local holder of a lock
+go_unlock        | Called on the final local unlock of a lock
+go_dump          | Called to print content of object for debugfs file, or on
+                 | error to dump glock to the log.
+go_type;         | The type of the glock, LM_TYPE_.....
+go_min_hold_time | The minimum hold time
+
+The minimum hold time for each lock is the time after a remote lock
+grant for which we ignore remote demote requests. This is in order to
+prevent a situation where locks are being bounced around the cluster
+from node to node with none of the nodes making any progress. This
+tends to show up most with shared mmaped files which are being written
+to by multiple nodes. By delaying the demotion in response to a
+remote callback, that gives the userspace program time to make
+some progress before the pages are unmapped.
+
+There is a plan to try and remove the go_lock and go_unlock callbacks
+if possible, in order to try and speed up the fast path though the locking.
+Also, eventually we hope to make the glock "EX" mode locally shared
+such that any local locking will be done with the i_mutex as required
+rather than via the glock.
+
+Locking rules for glock operations:
+
+Operation     |  GLF_LOCK bit lock held |  gl_spin spinlock held
+-----------------------------------------------------------------
+go_xmote_th   |       Yes               |       No
+go_xmote_bh   |       Yes               |       No
+go_inval      |       Yes               |       No
+go_demote_ok  |       Sometimes         |       Yes
+go_lock       |       Yes               |       No
+go_unlock     |       Yes               |       No
+go_dump       |       Sometimes         |       Yes
+
+N.B. Operations must not drop either the bit lock or the spinlock
+if its held on entry. go_dump and do_demote_ok must never block.
+Note that go_dump will only be called if the glock's state
+indicates that it is caching uptodate data.
+
+Glock locking order within GFS2:
+
+ 1. i_mutex (if required)
+ 2. Rename glock (for rename only)
+ 3. Inode glock(s)
+    (Parents before children, inodes at "same level" with same parent in
+     lock number order)
+ 4. Rgrp glock(s) (for (de)allocation operations)
+ 5. Transaction glock (via gfs2_trans_begin) for non-read operations
+ 6. Page lock  (always last, very important!)
+
+There are two glocks per inode. One deals with access to the inode
+itself (locking order as above), and the other, known as the iopen
+glock is used in conjunction with the i_nlink field in the inode to
+determine the lifetime of the inode in question. Locking of inodes
+is on a per-inode basis. Locking of rgrps is on a per rgrp basis.
+
index dbc3c6a..7f268f3 100644 (file)
@@ -380,28 +380,35 @@ i386 and x86_64 platforms support the new IRQ vector displays.
 Of some interest is the introduction of the /proc/irq directory to 2.4.
 It could be used to set IRQ to CPU affinity, this means that you can "hook" an
 IRQ to only one CPU, or to exclude a CPU of handling IRQs. The contents of the
-irq subdir is one subdir for each IRQ, and one file; prof_cpu_mask
+irq subdir is one subdir for each IRQ, and two files; default_smp_affinity and
+prof_cpu_mask.
 
 For example 
   > ls /proc/irq/
   0  10  12  14  16  18  2  4  6  8  prof_cpu_mask
-  1  11  13  15  17  19  3  5  7  9
+  1  11  13  15  17  19  3  5  7  9  default_smp_affinity
   > ls /proc/irq/0/
   smp_affinity
 
-The contents of the prof_cpu_mask file and each smp_affinity file for each IRQ
-is the same by default:
+smp_affinity is a bitmask, in which you can specify which CPUs can handle the
+IRQ, you can set it by doing:
 
-  > cat /proc/irq/0/smp_affinity 
-  ffffffff
+  > echo 1 > /proc/irq/10/smp_affinity
+
+This means that only the first CPU will handle the IRQ, but you can also echo
+5 which means that only the first and fourth CPU can handle the IRQ.
 
-It's a bitmask, in which you can specify which CPUs can handle the IRQ, you can
-set it by doing:
+The contents of each smp_affinity file is the same by default:
+
+  > cat /proc/irq/0/smp_affinity
+  ffffffff
 
-  > echo 1 > /proc/irq/prof_cpu_mask
+The default_smp_affinity mask applies to all non-active IRQs, which are the
+IRQs which have not yet been allocated/activated, and hence which lack a
+/proc/irq/[0-9]* directory.
 
-This means that only the first CPU will handle the IRQ, but you can also echo 5
-which means that only the first and fourth CPU can handle the IRQ.
+prof_cpu_mask specifies which CPUs are to be profiled by the system wide
+profiler. Default value is ffffffff (all cpus).
 
 The way IRQs are routed is handled by the IO-APIC, and it's Round Robin
 between all the CPUs which are allowed to handle it. As usual the kernel has
diff --git a/Documentation/i2c/busses/i2c-i810 b/Documentation/i2c/busses/i2c-i810
deleted file mode 100644 (file)
index 778210e..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-Kernel driver i2c-i810
-
-Supported adapters:
-  * Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH)
-  * Intel 82845G (GMCH)
-
-Authors: 
-       Frodo Looijaard <frodol@dds.nl>, 
-       Philip Edelbrock <phil@netroedge.com>,
-        Kyösti Mälkki <kmalkki@cc.hut.fi>,
-       Ralph Metzler <rjkm@thp.uni-koeln.de>,
-       Mark D. Studebaker <mdsxyz123@yahoo.com>
-
-Main contact: Mark Studebaker <mdsxyz123@yahoo.com>
-
-Description 
------------ 
-
-WARNING: If you have an '810' or '815' motherboard, your standard I2C
-temperature sensors are most likely on the 801's I2C bus. You want the
-i2c-i801 driver for those, not this driver.
-
-Now for the i2c-i810...
-
-The GMCH chip contains two I2C interfaces.
-
-The first interface is used for DDC (Data Display Channel) which is a
-serial channel through the VGA monitor connector to a DDC-compliant
-monitor. This interface is defined by the Video Electronics Standards
-Association (VESA). The standards are available for purchase at
-http://www.vesa.org .
-
-The second interface is a general-purpose I2C bus. It may be connected to a
-TV-out chip such as the BT869 or possibly to a digital flat-panel display.
-
-Features
--------- 
-
-Both busses use the i2c-algo-bit driver for 'bit banging'
-and support for specific transactions is provided by i2c-algo-bit.
-
-Issues
-------
-
-If you enable bus testing in i2c-algo-bit (insmod i2c-algo-bit bit_test=1),
-the test may fail; if so, the i2c-i810 driver won't be inserted. However,
-we think this has been fixed.
diff --git a/Documentation/i2c/busses/i2c-prosavage b/Documentation/i2c/busses/i2c-prosavage
deleted file mode 100644 (file)
index 7036879..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-Kernel driver i2c-prosavage
-
-Supported adapters:
-       
-       S3/VIA KM266/VT8375 aka ProSavage8 
-       S3/VIA KM133/VT8365 aka Savage4 
-
-Author: Henk Vergonet <henk@god.dyndns.org>
-
-Description
------------
-
-The Savage4 chips contain two I2C interfaces (aka a I2C 'master' or
-'host'). 
-
-The first interface is used for DDC (Data Display Channel) which is a
-serial channel through the VGA monitor connector to a DDC-compliant
-monitor. This interface is defined by the Video Electronics Standards
-Association (VESA). The standards are available for purchase at
-http://www.vesa.org . The second interface is a general-purpose I2C bus.
-
-Usefull for gaining access to the TV Encoder chips.
-
diff --git a/Documentation/i2c/busses/i2c-savage4 b/Documentation/i2c/busses/i2c-savage4
deleted file mode 100644 (file)
index 6ecceab..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-Kernel driver i2c-savage4
-
-Supported adapters:
-  * Savage4
-  * Savage2000
-
-Authors: 
-       Alexander Wold <awold@bigfoot.com>,
-       Mark D. Studebaker <mdsxyz123@yahoo.com> 
-
-Description
------------
-
-The Savage4 chips contain two I2C interfaces (aka a I2C 'master'
-or 'host'). 
-
-The first interface is used for DDC (Data Display Channel) which is a
-serial channel through the VGA monitor connector to a DDC-compliant
-monitor. This interface is defined by the Video Electronics Standards
-Association (VESA). The standards are available for purchase at
-http://www.vesa.org . The DDC bus is not yet supported because its register
-is not directly memory-mapped.
-
-The second interface is a general-purpose I2C bus. This is the only
-interface supported by the driver at the moment.
-
diff --git a/Documentation/i2c/fault-codes b/Documentation/i2c/fault-codes
new file mode 100644 (file)
index 0000000..045765c
--- /dev/null
@@ -0,0 +1,127 @@
+This is a summary of the most important conventions for use of fault
+codes in the I2C/SMBus stack.
+
+
+A "Fault" is not always an "Error"
+----------------------------------
+Not all fault reports imply errors; "page faults" should be a familiar
+example.  Software often retries idempotent operations after transient
+faults.  There may be fancier recovery schemes that are appropriate in
+some cases, such as re-initializing (and maybe resetting).  After such
+recovery, triggered by a fault report, there is no error.
+
+In a similar way, sometimes a "fault" code just reports one defined
+result for an operation ... it doesn't indicate that anything is wrong
+at all, just that the outcome wasn't on the "golden path".
+
+In short, your I2C driver code may need to know these codes in order
+to respond correctly.  Other code may need to rely on YOUR code reporting
+the right fault code, so that it can (in turn) behave correctly.
+
+
+I2C and SMBus fault codes
+-------------------------
+These are returned as negative numbers from most calls, with zero or
+some positive number indicating a non-fault return.  The specific
+numbers associated with these symbols differ between architectures,
+though most Linux systems use <asm-generic/errno*.h> numbering.
+
+Note that the descriptions here are not exhaustive.  There are other
+codes that may be returned, and other cases where these codes should
+be returned.  However, drivers should not return other codes for these
+cases (unless the hardware doesn't provide unique fault reports).
+
+Also, codes returned by adapter probe methods follow rules which are
+specific to their host bus (such as PCI, or the platform bus).
+
+
+EAGAIN
+       Returned by I2C adapters when they lose arbitration in master
+       transmit mode:  some other master was transmitting different
+       data at the same time.
+
+       Also returned when trying to invoke an I2C operation in an
+       atomic context, when some task is already using that I2C bus
+       to execute some other operation.
+
+EBADMSG
+       Returned by SMBus logic when an invalid Packet Error Code byte
+       is received.  This code is a CRC covering all bytes in the
+       transaction, and is sent before the terminating STOP.  This
+       fault is only reported on read transactions; the SMBus slave
+       may have a way to report PEC mismatches on writes from the
+       host.  Note that even if PECs are in use, you should not rely
+       on these as the only way to detect incorrect data transfers.
+
+EBUSY
+       Returned by SMBus adapters when the bus was busy for longer
+       than allowed.  This usually indicates some device (maybe the
+       SMBus adapter) needs some fault recovery (such as resetting),
+       or that the reset was attempted but failed.
+
+EINVAL
+       This rather vague error means an invalid parameter has been
+       detected before any I/O operation was started.  Use a more
+       specific fault code when you can.
+
+       One example would be a driver trying an SMBus Block Write
+       with block size outside the range of 1-32 bytes.
+
+EIO
+       This rather vague error means something went wrong when
+       performing an I/O operation.  Use a more specific fault
+       code when you can.
+
+ENODEV
+       Returned by driver probe() methods.  This is a bit more
+       specific than ENXIO, implying the problem isn't with the
+       address, but with the device found there.  Driver probes
+       may verify the device returns *correct* responses, and
+       return this as appropriate.  (The driver core will warn
+       about probe faults other than ENXIO and ENODEV.)
+
+ENOMEM
+       Returned by any component that can't allocate memory when
+       it needs to do so.
+
+ENXIO
+       Returned by I2C adapters to indicate that the address phase
+       of a transfer didn't get an ACK.  While it might just mean
+       an I2C device was temporarily not responding, usually it
+       means there's nothing listening at that address.
+
+       Returned by driver probe() methods to indicate that they
+       found no device to bind to.  (ENODEV may also be used.)
+
+EOPNOTSUPP
+       Returned by an adapter when asked to perform an operation
+       that it doesn't, or can't, support.
+
+       For example, this would be returned when an adapter that
+       doesn't support SMBus block transfers is asked to execute
+       one.  In that case, the driver making that request should
+       have verified that functionality was supported before it
+       made that block transfer request.
+
+       Similarly, if an I2C adapter can't execute all legal I2C
+       messages, it should return this when asked to perform a
+       transaction it can't.  (These limitations can't be seen in
+       the adapter's functionality mask, since the assumption is
+       that if an adapter supports I2C it supports all of I2C.)
+
+EPROTO
+       Returned when slave does not conform to the relevant I2C
+       or SMBus (or chip-specific) protocol specifications.  One
+       case is when the length of an SMBus block data response
+       (from the SMBus slave) is outside the range 1-32 bytes.
+
+ETIMEDOUT
+       This is returned by drivers when an operation took too much
+       time, and was aborted before it completed.
+
+       SMBus adapters may return it when an operation took more
+       time than allowed by the SMBus specification; for example,
+       when a slave stretches clocks too far.  I2C has no such
+       timeouts, but it's normal for I2C adapters to impose some
+       arbitrary limits (much longer than SMBus!) too.
+
index 03f08fb..24bfb65 100644 (file)
@@ -42,8 +42,8 @@ Count (8 bits): A data byte containing the length of a block operation.
 [..]: Data sent by I2C device, as opposed to data sent by the host adapter.
 
 
-SMBus Quick Command:  i2c_smbus_write_quick()
-=============================================
+SMBus Quick Command
+===================
 
 This sends a single bit to the device, at the place of the Rd/Wr bit.
 
index d4cd412..6b61b3a 100644 (file)
@@ -44,6 +44,10 @@ static struct i2c_driver foo_driver = {
        .id_table       = foo_ids,
        .probe          = foo_probe,
        .remove         = foo_remove,
+       /* if device autodetection is needed: */
+       .class          = I2C_CLASS_SOMETHING,
+       .detect         = foo_detect,
+       .address_data   = &addr_data,
 
        /* else, driver uses "legacy" binding model: */
        .attach_adapter = foo_attach_adapter,
@@ -217,6 +221,31 @@ in the I2C bus driver. You may want to save the returned i2c_client
 reference for later use.
 
 
+Device Detection (Standard driver model)
+----------------------------------------
+
+Sometimes you do not know in advance which I2C devices are connected to
+a given I2C bus.  This is for example the case of hardware monitoring
+devices on a PC's SMBus.  In that case, you may want to let your driver
+detect supported devices automatically.  This is how the legacy model
+was working, and is now available as an extension to the standard
+driver model (so that we can finally get rid of the legacy model.)
+
+You simply have to define a detect callback which will attempt to
+identify supported devices (returning 0 for supported ones and -ENODEV
+for unsupported ones), a list of addresses to probe, and a device type
+(or class) so that only I2C buses which may have that type of device
+connected (and not otherwise enumerated) will be probed.  The i2c
+core will then call you back as needed and will instantiate a device
+for you for every successful detection.
+
+Note that this mechanism is purely optional and not suitable for all
+devices.  You need some reliable way to identify the supported devices
+(typically using device-specific, dedicated identification registers),
+otherwise misdetections are likely to occur and things can get wrong
+quickly.
+
+
 Device Deletion (Standard driver model)
 ---------------------------------------
 
@@ -569,7 +598,6 @@ SMBus communication
   in terms of it. Never use this function directly!
 
 
-  extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
   extern s32 i2c_smbus_read_byte(struct i2c_client * client);
   extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value);
   extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
@@ -578,30 +606,31 @@ SMBus communication
   extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
   extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
                                        u8 command, u16 value);
+  extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
+                                       u8 command, u8 *values);
   extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
                                         u8 command, u8 length,
                                         u8 *values);
   extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
                                            u8 command, u8 length, u8 *values);
-
-These ones were removed in Linux 2.6.10 because they had no users, but could
-be added back later if needed:
-
-  extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
-                                       u8 command, u8 *values);
   extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
                                             u8 command, u8 length,
                                             u8 *values);
+
+These ones were removed from i2c-core because they had no users, but could
+be added back later if needed:
+
+  extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
   extern s32 i2c_smbus_process_call(struct i2c_client * client,
                                     u8 command, u16 value);
   extern s32 i2c_smbus_block_process_call(struct i2c_client *client,
                                           u8 command, u8 length,
                                           u8 *values)
 
-All these transactions return -1 on failure. The 'write' transactions 
-return 0 on success; the 'read' transactions return the read value, except 
-for read_block, which returns the number of values read. The block buffers 
-need not be longer than 32 bytes.
+All these transactions return a negative errno value on failure. The 'write'
+transactions return 0 on success; the 'read' transactions return the read
+value, except for block transactions, which return the number of values
+read. The block buffers need not be longer than 32 bytes.
 
 You can read the file `smbus-protocol' for more information about the
 actual SMBus protocol.
index b3a5aad..312fe77 100644 (file)
@@ -571,6 +571,8 @@ and is between 256 and 4096 characters. It is defined in the file
 
        debug_objects   [KNL] Enable object debugging
 
+       debugpat        [X86] Enable PAT debugging
+
        decnet.addr=    [HW,NET]
                        Format: <area>[,<node>]
                        See also Documentation/networking/decnet.txt.
@@ -756,9 +758,6 @@ and is between 256 and 4096 characters. It is defined in the file
        hd=             [EIDE] (E)IDE hard drive subsystem geometry
                        Format: <cyl>,<head>,<sect>
 
-       hd?=            [HW] (E)IDE subsystem
-       hd?lun=         See Documentation/ide/ide.txt.
-
        highmem=nn[KMG] [KNL,BOOT] forces the highmem zone to have an exact
                        size of <nn>. This works even on boxes that have no
                        highmem otherwise. This also works to reduce highmem
@@ -1610,6 +1609,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        Format: { parport<nr> | timid | 0 }
                        See also Documentation/parport.txt.
 
+       pmtmr=          [X86] Manual setup of pmtmr I/O Port. 
+                       Override pmtimer IOPort with a hex value.
+                       e.g. pmtmr=0x508
+
        pnpacpi=        [ACPI]
                        { off }
 
index 1528e58..fc6c005 100644 (file)
@@ -1686,6 +1686,13 @@ L:       linuxppc-embedded@ozlabs.org
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
+FREESCALE I2C CPM DRIVER
+P:     Jochen Friedrich
+M:     jochen@scram.de
+L:     linuxppc-dev@ozlabs.org
+L:     i2c@lm-sensors.org
+S:     Maintained
+
 FREESCALE SOC FS_ENET DRIVER
 P:     Pantelis Antoniou
 M:     pantelis.antoniou@gmail.com
@@ -1770,6 +1777,11 @@ M:       hch@infradead.org
 W:     ftp://ftp.openlinux.org/pub/people/hch/vxfs
 S:     Maintained
 
+FTRACE
+P:     Steven Rostedt
+M:     srostedt@redhat.com
+S:     Maintained
+
 FUJITSU FR-V (FRV) PORT
 P:     David Howells
 M:     dhowells@redhat.com
index 3ea332b..ad89a33 100644 (file)
@@ -39,3 +39,6 @@ config HAVE_KRETPROBES
 
 config HAVE_DMA_ATTRS
        def_bool n
+
+config USE_GENERIC_SMP_HELPERS
+       def_bool n
index 729cdbd..dbe8c28 100644 (file)
@@ -528,6 +528,7 @@ config ARCH_MAY_HAVE_PC_FDC
 config SMP
        bool "Symmetric multi-processing support"
        depends on ALPHA_SABLE || ALPHA_LYNX || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK || ALPHA_MARVEL
+       select USE_GENERIC_SMP_HELPERS
        ---help---
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
index b04f1fe..04dcc5e 100644 (file)
@@ -660,9 +660,9 @@ __marvel_rtc_io(u8 b, unsigned long addr, int write)
 
 #ifdef CONFIG_SMP
                if (smp_processor_id() != boot_cpuid)
-                       smp_call_function_on_cpu(__marvel_access_rtc,
-                                                &rtc_access, 1, 1,
-                                                cpumask_of_cpu(boot_cpuid));
+                       smp_call_function_single(boot_cpuid,
+                                                __marvel_access_rtc,
+                                                &rtc_access, 1);
                else
                        __marvel_access_rtc(&rtc_access);
 #else
index facf82a..c626a82 100644 (file)
@@ -42,8 +42,7 @@ void ack_bad_irq(unsigned int irq)
 #ifdef CONFIG_SMP 
 static char irq_user_affinity[NR_IRQS];
 
-int
-select_smp_affinity(unsigned int irq)
+int irq_select_affinity(unsigned int irq)
 {
        static int last_cpu;
        int cpu = last_cpu + 1;
@@ -51,7 +50,7 @@ select_smp_affinity(unsigned int irq)
        if (!irq_desc[irq].chip->set_affinity || irq_user_affinity[irq])
                return 1;
 
-       while (!cpu_possible(cpu))
+       while (!cpu_possible(cpu) || !cpu_isset(cpu, irq_default_affinity))
                cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
        last_cpu = cpu;
 
index 96ed82f..351407e 100644 (file)
@@ -160,7 +160,7 @@ common_shutdown(int mode, char *restart_cmd)
        struct halt_info args;
        args.mode = mode;
        args.restart_cmd = restart_cmd;
-       on_each_cpu(common_shutdown_1, &args, 1, 0);
+       on_each_cpu(common_shutdown_1, &args, 0);
 }
 
 void
index 2525692..83df541 100644 (file)
@@ -62,6 +62,7 @@ static struct {
 enum ipi_message_type {
        IPI_RESCHEDULE,
        IPI_CALL_FUNC,
+       IPI_CALL_FUNC_SINGLE,
        IPI_CPU_STOP,
 };
 
@@ -558,51 +559,6 @@ send_ipi_message(cpumask_t to_whom, enum ipi_message_type operation)
                wripir(i);
 }
 
-/* Structure and data for smp_call_function.  This is designed to 
-   minimize static memory requirements.  Plus it looks cleaner.  */
-
-struct smp_call_struct {
-       void (*func) (void *info);
-       void *info;
-       long wait;
-       atomic_t unstarted_count;
-       atomic_t unfinished_count;
-};
-
-static struct smp_call_struct *smp_call_function_data;
-
-/* Atomicly drop data into a shared pointer.  The pointer is free if
-   it is initially locked.  If retry, spin until free.  */
-
-static int
-pointer_lock (void *lock, void *data, int retry)
-{
-       void *old, *tmp;
-
-       mb();
- again:
-       /* Compare and swap with zero.  */
-       asm volatile (
-       "1:     ldq_l   %0,%1\n"
-       "       mov     %3,%2\n"
-       "       bne     %0,2f\n"
-       "       stq_c   %2,%1\n"
-       "       beq     %2,1b\n"
-       "2:"
-       : "=&r"(old), "=m"(*(void **)lock), "=&r"(tmp)
-       : "r"(data)
-       : "memory");
-
-       if (old == 0)
-               return 0;
-       if (! retry)
-               return -EBUSY;
-
-       while (*(void **)lock)
-               barrier();
-       goto again;
-}
-
 void
 handle_ipi(struct pt_regs *regs)
 {
@@ -632,31 +588,12 @@ handle_ipi(struct pt_regs *regs)
                        break;
 
                case IPI_CALL_FUNC:
-                   {
-                       struct smp_call_struct *data;
-                       void (*func)(void *info);
-                       void *info;
-                       int wait;
-
-                       data = smp_call_function_data;
-                       func = data->func;
-                       info = data->info;
-                       wait = data->wait;
-
-                       /* Notify the sending CPU that the data has been
-                          received, and execution is about to begin.  */
-                       mb();
-                       atomic_dec (&data->unstarted_count);
-
-                       /* At this point the structure may be gone unless
-                          wait is true.  */
-                       (*func)(info);
-
-                       /* Notify the sending CPU that the task is done.  */
-                       mb();
-                       if (wait) atomic_dec (&data->unfinished_count);
+                       generic_smp_call_function_interrupt();
+                       break;
+
+               case IPI_CALL_FUNC_SINGLE:
+                       generic_smp_call_function_single_interrupt();
                        break;
-                   }
 
                case IPI_CPU_STOP:
                        halt();
@@ -700,102 +637,15 @@ smp_send_stop(void)
        send_ipi_message(to_whom, IPI_CPU_STOP);
 }
 
-/*
- * Run a function on all other CPUs.
- *  <func>     The function to run. This must be fast and non-blocking.
- *  <info>     An arbitrary pointer to pass to the function.
- *  <retry>    If true, keep retrying until ready.
- *  <wait>     If true, wait until function has completed on other CPUs.
- *  [RETURNS]   0 on success, else a negative status code.
- *
- * Does not return until remote CPUs are nearly ready to execute <func>
- * or are or have executed.
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
- */
-
-int
-smp_call_function_on_cpu (void (*func) (void *info), void *info, int retry,
-                         int wait, cpumask_t to_whom)
+void arch_send_call_function_ipi(cpumask_t mask)
 {
-       struct smp_call_struct data;
-       unsigned long timeout;
-       int num_cpus_to_call;
-       
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
-       data.func = func;
-       data.info = info;
-       data.wait = wait;
-
-       cpu_clear(smp_processor_id(), to_whom);
-       num_cpus_to_call = cpus_weight(to_whom);
-
-       atomic_set(&data.unstarted_count, num_cpus_to_call);
-       atomic_set(&data.unfinished_count, num_cpus_to_call);
-
-       /* Acquire the smp_call_function_data mutex.  */
-       if (pointer_lock(&smp_call_function_data, &data, retry))
-               return -EBUSY;
-
-       /* Send a message to the requested CPUs.  */
-       send_ipi_message(to_whom, IPI_CALL_FUNC);
-
-       /* Wait for a minimal response.  */
-       timeout = jiffies + HZ;
-       while (atomic_read (&data.unstarted_count) > 0
-              && time_before (jiffies, timeout))
-               barrier();
-
-       /* If there's no response yet, log a message but allow a longer
-        * timeout period -- if we get a response this time, log
-        * a message saying when we got it.. 
-        */
-       if (atomic_read(&data.unstarted_count) > 0) {
-               long start_time = jiffies;
-               printk(KERN_ERR "%s: initial timeout -- trying long wait\n",
-                      __func__);
-               timeout = jiffies + 30 * HZ;
-               while (atomic_read(&data.unstarted_count) > 0
-                      && time_before(jiffies, timeout))
-                       barrier();
-               if (atomic_read(&data.unstarted_count) <= 0) {
-                       long delta = jiffies - start_time;
-                       printk(KERN_ERR 
-                              "%s: response %ld.%ld seconds into long wait\n",
-                              __func__, delta / HZ,
-                              (100 * (delta - ((delta / HZ) * HZ))) / HZ);
-               }
-       }
-
-       /* We either got one or timed out -- clear the lock. */
-       mb();
-       smp_call_function_data = NULL;
-
-       /* 
-        * If after both the initial and long timeout periods we still don't
-        * have a response, something is very wrong...
-        */
-       BUG_ON(atomic_read (&data.unstarted_count) > 0);
-
-       /* Wait for a complete response, if needed.  */
-       if (wait) {
-               while (atomic_read (&data.unfinished_count) > 0)
-                       barrier();
-       }
-
-       return 0;
+       send_ipi_message(mask, IPI_CALL_FUNC);
 }
-EXPORT_SYMBOL(smp_call_function_on_cpu);
 
-int
-smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
+void arch_send_call_function_single_ipi(int cpu)
 {
-       return smp_call_function_on_cpu (func, info, retry, wait,
-                                        cpu_online_map);
+       send_ipi_message(cpumask_of_cpu(cpu), IPI_CALL_FUNC_SINGLE);
 }
-EXPORT_SYMBOL(smp_call_function);
 
 static void
 ipi_imb(void *ignored)
@@ -807,7 +657,7 @@ void
 smp_imb(void)
 {
        /* Must wait other processors to flush their icache before continue. */
-       if (on_each_cpu(ipi_imb, NULL, 1, 1))
+       if (on_each_cpu(ipi_imb, NULL, 1))
                printk(KERN_CRIT "smp_imb: timed out\n");
 }
 EXPORT_SYMBOL(smp_imb);
@@ -823,7 +673,7 @@ flush_tlb_all(void)
 {
        /* Although we don't have any data to pass, we do want to
           synchronize with the other processors.  */
-       if (on_each_cpu(ipi_flush_tlb_all, NULL, 1, 1)) {
+       if (on_each_cpu(ipi_flush_tlb_all, NULL, 1)) {
                printk(KERN_CRIT "flush_tlb_all: timed out\n");
        }
 }
@@ -860,7 +710,7 @@ flush_tlb_mm(struct mm_struct *mm)
                }
        }
 
-       if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) {
+       if (smp_call_function(ipi_flush_tlb_mm, mm, 1)) {
                printk(KERN_CRIT "flush_tlb_mm: timed out\n");
        }
 
@@ -913,7 +763,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
        data.mm = mm;
        data.addr = addr;
 
-       if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) {
+       if (smp_call_function(ipi_flush_tlb_page, &data, 1)) {
                printk(KERN_CRIT "flush_tlb_page: timed out\n");
        }
 
@@ -965,7 +815,7 @@ flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
                }
        }
 
-       if (smp_call_function(ipi_flush_icache_page, mm, 1, 1)) {
+       if (smp_call_function(ipi_flush_icache_page, mm, 1)) {
                printk(KERN_CRIT "flush_icache_page: timed out\n");
        }
 
index 9fc0eeb..7c3d5ec 100644 (file)
@@ -65,7 +65,7 @@ op_axp_setup(void)
        model->reg_setup(&reg, ctr, &sys);
 
        /* Configure the registers on all cpus.  */
-       (void)smp_call_function(model->cpu_setup, &reg, 0, 1);
+       (void)smp_call_function(model->cpu_setup, &reg, 1);
        model->cpu_setup(&reg);
        return 0;
 }
@@ -86,7 +86,7 @@ op_axp_cpu_start(void *dummy)
 static int
 op_axp_start(void)
 {
-       (void)smp_call_function(op_axp_cpu_start, NULL, 0, 1);
+       (void)smp_call_function(op_axp_cpu_start, NULL, 1);
        op_axp_cpu_start(NULL);
        return 0;
 }
@@ -101,7 +101,7 @@ op_axp_cpu_stop(void *dummy)
 static void
 op_axp_stop(void)
 {
-       (void)smp_call_function(op_axp_cpu_stop, NULL, 0, 1);
+       (void)smp_call_function(op_axp_cpu_stop, NULL, 1);
        op_axp_cpu_stop(NULL);
 }
 
index 258f136..c7ad324 100644 (file)
@@ -701,6 +701,7 @@ source "kernel/time/Kconfig"
 config SMP
        bool "Symmetric Multi-Processing (EXPERIMENTAL)"
        depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP)
+       select USE_GENERIC_SMP_HELPERS
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
index eefae1d..5a7c095 100644 (file)
@@ -68,20 +68,10 @@ enum ipi_msg_type {
        IPI_TIMER,
        IPI_RESCHEDULE,
        IPI_CALL_FUNC,
+       IPI_CALL_FUNC_SINGLE,
        IPI_CPU_STOP,
 };
 
-struct smp_call_struct {
-       void (*func)(void *info);
-       void *info;
-       int wait;
-       cpumask_t pending;
-       cpumask_t unfinished;
-};
-
-static struct smp_call_struct * volatile smp_call_function_data;
-static DEFINE_SPINLOCK(smp_call_function_lock);
-
 int __cpuinit __cpu_up(unsigned int cpu)
 {
        struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
@@ -366,114 +356,15 @@ static void send_ipi_message(cpumask_t callmap, enum ipi_msg_type msg)
        local_irq_restore(flags);
 }
 
-/*
- * You must not call this function with disabled interrupts, from a
- * hardware interrupt handler, nor from a bottom half handler.
- */
-static int smp_call_function_on_cpu(void (*func)(void *info), void *info,
-                                   int retry, int wait, cpumask_t callmap)
-{
-       struct smp_call_struct data;
-       unsigned long timeout;
-       int ret = 0;
-
-       data.func = func;
-       data.info = info;
-       data.wait = wait;
-
-       cpu_clear(smp_processor_id(), callmap);
-       if (cpus_empty(callmap))
-               goto out;
-
-       data.pending = callmap;
-       if (wait)
-               data.unfinished = callmap;
-
-       /*
-        * try to get the mutex on smp_call_function_data
-        */
-       spin_lock(&smp_call_function_lock);
-       smp_call_function_data = &data;
-
-       send_ipi_message(callmap, IPI_CALL_FUNC);
-
-       timeout = jiffies + HZ;
-       while (!cpus_empty(data.pending) && time_before(jiffies, timeout))
-               barrier();
-
-       /*
-        * did we time out?
-        */
-       if (!cpus_empty(data.pending)) {
-               /*
-                * this may be causing our panic - report it
-                */
-               printk(KERN_CRIT
-                      "CPU%u: smp_call_function timeout for %p(%p)\n"
-                      "      callmap %lx pending %lx, %swait\n",
-                      smp_processor_id(), func, info, *cpus_addr(callmap),
-                      *cpus_addr(data.pending), wait ? "" : "no ");
-
-               /*
-                * TRACE
-                */
-               timeout = jiffies + (5 * HZ);
-               while (!cpus_empty(data.pending) && time_before(jiffies, timeout))
-                       barrier();
-
-               if (cpus_empty(data.pending))
-                       printk(KERN_CRIT "     RESOLVED\n");
-               else
-                       printk(KERN_CRIT "     STILL STUCK\n");
-       }
-
-       /*
-        * whatever happened, we're done with the data, so release it
-        */
-       smp_call_function_data = NULL;
-       spin_unlock(&smp_call_function_lock);
-
-       if (!cpus_empty(data.pending)) {
-               ret = -ETIMEDOUT;
-               goto out;
-       }
-
-       if (wait)
-               while (!cpus_empty(data.unfinished))
-                       barrier();
- out:
-
-       return 0;
-}
-
-int smp_call_function(void (*func)(void *info), void *info, int retry,
-                      int wait)
+void arch_send_call_function_ipi(cpumask_t mask)
 {
-       return smp_call_function_on_cpu(func, info, retry, wait,
-                                       cpu_online_map);
+       send_ipi_message(mask, IPI_CALL_FUNC);
 }
-EXPORT_SYMBOL_GPL(smp_call_function);
 
-int smp_call_function_single(int cpu, void (*func)(void *info), void *info,
-                            int retry, int wait)
+void arch_send_call_function_single_ipi(int cpu)
 {
-       /* prevent preemption and reschedule on another processor */
-       int current_cpu = get_cpu();
-       int ret = 0;
-
-       if (cpu == current_cpu) {
-               local_irq_disable();
-               func(info);
-               local_irq_enable();
-       } else
-               ret = smp_call_function_on_cpu(func, info, retry, wait,
-                                              cpumask_of_cpu(cpu));
-
-       put_cpu();
-
-       return ret;
+       send_ipi_message(cpumask_of_cpu(cpu), IPI_CALL_FUNC_SINGLE);
 }
-EXPORT_SYMBOL_GPL(smp_call_function_single);
 
 void show_ipi_list(struct seq_file *p)
 {
@@ -521,27 +412,6 @@ asmlinkage void __exception do_local_timer(struct pt_regs *regs)
 }
 #endif
 
-/*
- * ipi_call_function - handle IPI from smp_call_function()
- *
- * Note that we copy data out of the cross-call structure and then
- * let the caller know that we're here and have done with their data
- */
-static void ipi_call_function(unsigned int cpu)
-{
-       struct smp_call_struct *data = smp_call_function_data;
-       void (*func)(void *info) = data->func;
-       void *info = data->info;
-       int wait = data->wait;
-
-       cpu_clear(cpu, data->pending);
-
-       func(info);
-
-       if (wait)
-               cpu_clear(cpu, data->unfinished);
-}
-
 static DEFINE_SPINLOCK(stop_lock);
 
 /*
@@ -611,7 +481,11 @@ asmlinkage void __exception do_IPI(struct pt_regs *regs)
                                break;
 
                        case IPI_CALL_FUNC:
-                               ipi_call_function(cpu);
+                               generic_smp_call_function_interrupt();
+                               break;
+
+                       case IPI_CALL_FUNC_SINGLE:
+                               generic_smp_call_function_single_interrupt();
                                break;
 
                        case IPI_CPU_STOP:
@@ -662,14 +536,13 @@ int setup_profiling_timer(unsigned int multiplier)
 }
 
 static int
-on_each_cpu_mask(void (*func)(void *), void *info, int retry, int wait,
-                cpumask_t mask)
+on_each_cpu_mask(void (*func)(void *), void *info, int wait, cpumask_t mask)
 {
        int ret = 0;
 
        preempt_disable();
 
-       ret = smp_call_function_on_cpu(func, info, retry, wait, mask);
+       ret = smp_call_function_mask(mask, func, info, wait);
        if (cpu_isset(smp_processor_id(), mask))
                func(info);
 
@@ -731,14 +604,14 @@ static inline void ipi_flush_tlb_kernel_range(void *arg)
 
 void flush_tlb_all(void)
 {
-       on_each_cpu(ipi_flush_tlb_all, NULL, 1, 1);
+       on_each_cpu(ipi_flush_tlb_all, NULL, 1);
 }
 
 void flush_tlb_mm(struct mm_struct *mm)
 {
        cpumask_t mask = mm->cpu_vm_mask;
 
-       on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, 1, mask);
+       on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mask);
 }
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
@@ -749,7 +622,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
        ta.ta_vma = vma;
        ta.ta_start = uaddr;
 
-       on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, 1, mask);
+       on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mask);
 }
 
 void flush_tlb_kernel_page(unsigned long kaddr)
@@ -758,7 +631,7 @@ void flush_tlb_kernel_page(unsigned long kaddr)
 
        ta.ta_start = kaddr;
 
-       on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1, 1);
+       on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
 }
 
 void flush_tlb_range(struct vm_area_struct *vma,
@@ -771,7 +644,7 @@ void flush_tlb_range(struct vm_area_struct *vma,
        ta.ta_start = start;
        ta.ta_end = end;
 
-       on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, 1, mask);
+       on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mask);
 }
 
 void flush_tlb_kernel_range(unsigned long start, unsigned long end)
@@ -781,5 +654,5 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
        ta.ta_start = start;
        ta.ta_end = end;
 
-       on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1, 1);
+       on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
 }
index 90e0c35..fc650f6 100644 (file)
@@ -92,4 +92,5 @@ void save_stack_trace(struct stack_trace *trace)
 {
        save_stack_trace_tsk(current, trace);
 }
+EXPORT_SYMBOL_GPL(save_stack_trace);
 #endif
index 74fae60..4458705 100644 (file)
@@ -201,7 +201,7 @@ static int em_call_function(int (*fn)(void))
        data.ret = 0;
 
        preempt_disable();
-       smp_call_function(em_func, &data, 1, 1);
+       smp_call_function(em_func, &data, 1);
        em_func(&data);
        preempt_enable();
 
index 32455c6..c0d2c9b 100644 (file)
@@ -352,7 +352,7 @@ static int __init vfp_init(void)
        else if (vfpsid & FPSID_NODOUBLE) {
                printk("no double precision support\n");
        } else {
-               smp_call_function(vfp_enable, NULL, 1, 1);
+               smp_call_function(vfp_enable, NULL, 1);
 
                VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT;  /* Extract the architecture version */
                printk("implementor %02x architecture %d part %02x variant %x rev %x\n",
index 9a68190..f4bdb44 100644 (file)
@@ -51,3 +51,4 @@ void save_stack_trace(struct stack_trace *trace)
                fp = frame->fp;
        }
 }
+EXPORT_SYMBOL_GPL(save_stack_trace);
index a9c3334..952a24b 100644 (file)
@@ -194,7 +194,7 @@ void stop_this_cpu(void* dummy)
 /* Other calls */
 void smp_send_stop(void)
 {
-       smp_call_function(stop_this_cpu, NULL, 1, 0);
+       smp_call_function(stop_this_cpu, NULL, 0);
 }
 
 int setup_profiling_timer(unsigned int multiplier)
@@ -316,8 +316,7 @@ int send_ipi(int vector, int wait, cpumask_t cpu_mask)
  * You must not call this function with disabled interrupts or from a
  * hardware interrupt handler or from a bottom half handler.
  */
-int smp_call_function(void (*func)(void *info), void *info,
-                     int nonatomic, int wait)
+int smp_call_function(void (*func)(void *info), void *info, int wait)
 {
        cpumask_t cpu_mask = CPU_MASK_ALL;
        struct call_data_struct data;
index 16be414..18bcc10 100644 (file)
@@ -303,6 +303,7 @@ config VIRT_CPU_ACCOUNTING
 
 config SMP
        bool "Symmetric multi-processing support"
+       select USE_GENERIC_SMP_HELPERS
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, say N.  If you have a system with more
index 705176b..7dd96c1 100644 (file)
@@ -707,7 +707,7 @@ ia64_mca_cmc_vector_enable (void *dummy)
 static void
 ia64_mca_cmc_vector_disable_keventd(struct work_struct *unused)
 {
-       on_each_cpu(ia64_mca_cmc_vector_disable, NULL, 1, 0);
+       on_each_cpu(ia64_mca_cmc_vector_disable, NULL, 0);
 }
 
 /*
@@ -719,7 +719,7 @@ ia64_mca_cmc_vector_disable_keventd(struct work_struct *unused)
 static void
 ia64_mca_cmc_vector_enable_keventd(struct work_struct *unused)
 {
-       on_each_cpu(ia64_mca_cmc_vector_enable, NULL, 1, 0);
+       on_each_cpu(ia64_mca_cmc_vector_enable, NULL, 0);
 }
 
 /*
@@ -1881,7 +1881,7 @@ static int __cpuinit mca_cpu_callback(struct notifier_block *nfb,
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
                smp_call_function_single(hotcpu, ia64_mca_cmc_vector_adjust,
-                                        NULL, 1, 0);
+                                        NULL, 0);
                break;
        }
        return NOTIFY_OK;
index 9dc00f7..e5c57f4 100644 (file)
@@ -921,7 +921,7 @@ int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
 
 
        /* will send IPI to other CPU and wait for completion of remote call */
-       if ((ret=smp_call_function_single(f->req_cpu, palinfo_smp_call, &ptr, 0, 1))) {
+       if ((ret=smp_call_function_single(f->req_cpu, palinfo_smp_call, &ptr, 1))) {
                printk(KERN_ERR "palinfo: remote CPU call from %d to %d on function %d: "
                       "error %d\n", smp_processor_id(), f->req_cpu, f->func_id, ret);
                return 0;
index 7714a97..19d4493 100644 (file)
@@ -1820,7 +1820,7 @@ pfm_syswide_cleanup_other_cpu(pfm_context_t *ctx)
        int ret;
 
        DPRINT(("calling CPU%d for cleanup\n", ctx->ctx_cpu));
-       ret = smp_call_function_single(ctx->ctx_cpu, pfm_syswide_force_stop, ctx, 0, 1);
+       ret = smp_call_function_single(ctx->ctx_cpu, pfm_syswide_force_stop, ctx, 1);
        DPRINT(("called CPU%d for cleanup ret=%d\n", ctx->ctx_cpu, ret));
 }
 #endif /* CONFIG_SMP */
@@ -6508,7 +6508,7 @@ pfm_install_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl)
        }
 
        /* save the current system wide pmu states */
-       ret = on_each_cpu(pfm_alt_save_pmu_state, NULL, 0, 1);
+       ret = on_each_cpu(pfm_alt_save_pmu_state, NULL, 1);
        if (ret) {
                DPRINT(("on_each_cpu() failed: %d\n", ret));
                goto cleanup_reserve;
@@ -6553,7 +6553,7 @@ pfm_remove_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl)
 
        pfm_alt_intr_handler = NULL;
 
-       ret = on_each_cpu(pfm_alt_restore_pmu_state, NULL, 0, 1);
+       ret = on_each_cpu(pfm_alt_restore_pmu_state, NULL, 1);
        if (ret) {
                DPRINT(("on_each_cpu() failed: %d\n", ret));
        }
index a3a34b4..fabaf08 100644 (file)
@@ -286,7 +286,7 @@ void cpu_idle_wait(void)
 {
        smp_mb();
        /* kick all the CPUs so that they exit out of pm_idle */
-       smp_call_function(do_nothing, NULL, 0, 1);
+       smp_call_function(do_nothing, NULL, 1);
 }
 EXPORT_SYMBOL_GPL(cpu_idle_wait);
 
index 983296f..3676468 100644 (file)
@@ -60,25 +60,9 @@ static struct local_tlb_flush_counts {
 
 static DEFINE_PER_CPU(unsigned int, shadow_flush_counts[NR_CPUS]) ____cacheline_aligned;
 
-
-/*
- * Structure and data for smp_call_function(). This is designed to minimise static memory
- * requirements. It also looks cleaner.
- */
-static  __cacheline_aligned DEFINE_SPINLOCK(call_lock);
-
-struct call_data_struct {
-       void (*func) (void *info);
-       void *info;
-       long wait;
-       atomic_t started;
-       atomic_t finished;
-};
-
-static volatile struct call_data_struct *call_data;
-
 #define IPI_CALL_FUNC          0
 #define IPI_CPU_STOP           1
+#define IPI_CALL_FUNC_SINGLE   2
 #define IPI_KDUMP_CPU_STOP     3
 
 /* This needs to be cacheline aligned because it is written to by *other* CPUs.  */
@@ -86,43 +70,6 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(u64, ipi_operation);
 
 extern void cpu_halt (void);
 
-void
-lock_ipi_calllock(void)
-{
-       spin_lock_irq(&call_lock);
-}
-
-void
-unlock_ipi_calllock(void)
-{
-       spin_unlock_irq(&call_lock);
-}
-
-static inline void
-handle_call_data(void)
-{
-       struct call_data_struct *data;
-       void (*func)(void *info);
-       void *info;
-       int wait;
-
-       /* release the 'pointer lock' */
-       data = (struct call_data_struct *)call_data;
-       func = data->func;
-       info = data->info;
-       wait = data->wait;
-
-       mb();
-       atomic_inc(&data->started);
-       /* At this point the structure may be gone unless wait is true. */
-       (*func)(info);
-
-       /* Notify the sending CPU that the task is done. */
-       mb();
-       if (wait)
-               atomic_inc(&data->finished);
-}
-
 static void
 stop_this_cpu(void)
 {
@@ -163,13 +110,15 @@ handle_IPI (int irq, void *dev_id)
                        ops &= ~(1 << which);
 
                        switch (which) {
-                       case IPI_CALL_FUNC:
-                               handle_call_data();
-                               break;
-
                        case IPI_CPU_STOP:
                                stop_this_cpu();
                                break;
+                       case IPI_CALL_FUNC:
+                               generic_smp_call_function_interrupt();
+                               break;
+                       case IPI_CALL_FUNC_SINGLE:
+                               generic_smp_call_function_single_interrupt();
+                               break;
 #ifdef CONFIG_KEXEC
                        case IPI_KDUMP_CPU_STOP:
                                unw_init_running(kdump_cpu_freeze, NULL);
@@ -187,6 +136,8 @@ handle_IPI (int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+
+
 /*
  * Called with preemption disabled.
  */
@@ -334,7 +285,7 @@ smp_flush_tlb_cpumask(cpumask_t xcpumask)
 void
 smp_flush_tlb_all (void)
 {
-       on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1);
+       on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1);
 }
 
 void
@@ -357,193 +308,18 @@ smp_flush_tlb_mm (struct mm_struct *mm)
         * anyhow, and once a CPU is interrupted, the cost of local_flush_tlb_all() is
         * rather trivial.
         */
-       on_each_cpu((void (*)(void *))local_finish_flush_tlb_mm, mm, 1, 1);
+       on_each_cpu((void (*)(void *))local_finish_flush_tlb_mm, mm, 1);
 }
 
-/*
- * Run a function on a specific CPU
- *  <func>     The function to run. This must be fast and non-blocking.
- *  <info>     An arbitrary pointer to pass to the function.
- *  <nonatomic>        Currently unused.
- *  <wait>     If true, wait until function has completed on other CPUs.
- *  [RETURNS]   0 on success, else a negative status code.
- *
- * Does not return until the remote CPU is nearly ready to execute <func>
- * or is or has executed.
- */
-
-int
-smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int nonatomic,
-                         int wait)
-{
-       struct call_data_struct data;
-       int cpus = 1;
-       int me = get_cpu(); /* prevent preemption and reschedule on another processor */
-
-       if (cpuid == me) {
-               local_irq_disable();
-               func(info);
-               local_irq_enable();
-               put_cpu();
-               return 0;
-       }
-
-       data.func = func;
-       data.info = info;
-       atomic_set(&data.started, 0);
-       data.wait = wait;
-       if (wait)
-               atomic_set(&data.finished, 0);
-
-       spin_lock_bh(&call_lock);
-
-       call_data = &data;
-       mb();   /* ensure store to call_data precedes setting of IPI_CALL_FUNC */
-       send_IPI_single(cpuid, IPI_CALL_FUNC);
-
-       /* Wait for response */
-       while (atomic_read(&data.started) != cpus)
-               cpu_relax();
-
-       if (wait)
-               while (atomic_read(&data.finished) != cpus)
-                       cpu_relax();
-       call_data = NULL;
-
-       spin_unlock_bh(&call_lock);
-       put_cpu();
-       return 0;
-}
-EXPORT_SYMBOL(smp_call_function_single);
-
-/**
- * smp_call_function_mask(): Run a function on a set of other CPUs.
- * <mask>      The set of cpus to run on.  Must not include the current cpu.
- * <func>      The function to run. This must be fast and non-blocking.
- * <info>      An arbitrary pointer to pass to the function.
- * <wait>      If true, wait (atomically) until function
- *             has completed on other CPUs.
- *
- * Returns 0 on success, else a negative status code.
- *
- * If @wait is true, then returns once @func has returned; otherwise
- * it returns just before the target cpu calls @func.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
- */
-int smp_call_function_mask(cpumask_t mask,
-                          void (*func)(void *), void *info,
-                          int wait)
+void arch_send_call_function_single_ipi(int cpu)
 {
-       struct call_data_struct data;
-       cpumask_t allbutself;
-       int cpus;
-
-       spin_lock(&call_lock);
-       allbutself = cpu_online_map;
-       cpu_clear(smp_processor_id(), allbutself);
-
-       cpus_and(mask, mask, allbutself);
-       cpus = cpus_weight(mask);
-       if (!cpus) {
-               spin_unlock(&call_lock);
-               return 0;
-       }
-
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
-       data.func = func;
-       data.info = info;
-       atomic_set(&data.started, 0);
-       data.wait = wait;
-       if (wait)
-               atomic_set(&data.finished, 0);
-
-       call_data = &data;
-       mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC*/
-
-       /* Send a message to other CPUs */
-       if (cpus_equal(mask, allbutself))
-               send_IPI_allbutself(IPI_CALL_FUNC);
-       else
-               send_IPI_mask(mask, IPI_CALL_FUNC);
-
-       /* Wait for response */
-       while (atomic_read(&data.started) != cpus)
-               cpu_relax();
-
-       if (wait)
-               while (atomic_read(&data.finished) != cpus)
-                       cpu_relax();
-       call_data = NULL;
-
-       spin_unlock(&call_lock);
-       return 0;
-
+       send_IPI_single(cpu, IPI_CALL_FUNC_SINGLE);
 }
-EXPORT_SYMBOL(smp_call_function_mask);
 
-/*
- * this function sends a 'generic call function' IPI to all other CPUs
- * in the system.
- */
-
-/*
- *  [SUMMARY]  Run a function on all other CPUs.
- *  <func>     The function to run. This must be fast and non-blocking.
- *  <info>     An arbitrary pointer to pass to the function.
- *  <nonatomic>        currently unused.
- *  <wait>     If true, wait (atomically) until function has completed on other CPUs.
- *  [RETURNS]   0 on success, else a negative status code.
- *
- * Does not return until remote CPUs are nearly ready to execute <func> or are or have
- * executed.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
- */
-int
-smp_call_function (void (*func) (void *info), void *info, int nonatomic, int wait)
+void arch_send_call_function_ipi(cpumask_t mask)
 {
-       struct call_data_struct data;
-       int cpus;
-
-       spin_lock(&call_lock);
-       cpus = num_online_cpus() - 1;
-       if (!cpus) {
-               spin_unlock(&call_lock);
-               return 0;
-       }
-
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
-       data.func = func;
-       data.info = info;
-       atomic_set(&data.started, 0);
-       data.wait = wait;
-       if (wait)
-               atomic_set(&data.finished, 0);
-
-       call_data = &data;
-       mb();   /* ensure store to call_data precedes setting of IPI_CALL_FUNC */
-       send_IPI_allbutself(IPI_CALL_FUNC);
-
-       /* Wait for response */
-       while (atomic_read(&data.started) != cpus)
-               cpu_relax();
-
-       if (wait)
-               while (atomic_read(&data.finished) != cpus)
-                       cpu_relax();
-       call_data = NULL;
-
-       spin_unlock(&call_lock);
-       return 0;
+       send_IPI_mask(mask, IPI_CALL_FUNC);
 }
-EXPORT_SYMBOL(smp_call_function);
 
 /*
  * this function calls the 'stop' function on all other CPUs in the system.
index d7ad42b..9d1d429 100644 (file)
@@ -317,7 +317,7 @@ ia64_sync_itc (unsigned int master)
 
        go[MASTER] = 1;
 
-       if (smp_call_function_single(master, sync_master, NULL, 1, 0) < 0) {
+       if (smp_call_function_single(master, sync_master, NULL, 0) < 0) {
                printk(KERN_ERR "sync_itc: failed to get attention of CPU %u!\n", master);
                return;
        }
@@ -395,14 +395,14 @@ smp_callin (void)
 
        fix_b0_for_bsp();
 
-       lock_ipi_calllock();
+       ipi_call_lock_irq();
        spin_lock(&vector_lock);
        /* Setup the per cpu irq handling data structures */
        __setup_vector_irq(cpuid);
        cpu_set(cpuid, cpu_online_map);
        per_cpu(cpu_state, cpuid) = CPU_ONLINE;
        spin_unlock(&vector_lock);
-       unlock_ipi_calllock();
+       ipi_call_unlock_irq();
 
        smp_setup_percpu_timer();
 
index e77995a..8eff8c1 100644 (file)
@@ -123,8 +123,7 @@ static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid)
        status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
        if (status == PAL_VISIBILITY_OK_REMOTE_NEEDED) {
                atomic_set(&uc_pool->status, 0);
-               status = smp_call_function(uncached_ipi_visibility, uc_pool,
-                                          0, 1);
+               status = smp_call_function(uncached_ipi_visibility, uc_pool, 1);
                if (status || atomic_read(&uc_pool->status))
                        goto failed;
        } else if (status != PAL_VISIBILITY_OK)
@@ -146,7 +145,7 @@ static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid)
        if (status != PAL_STATUS_SUCCESS)
                goto failed;
        atomic_set(&uc_pool->status, 0);
-       status = smp_call_function(uncached_ipi_mc_drain, uc_pool, 0, 1);
+       status = smp_call_function(uncached_ipi_mc_drain, uc_pool, 1);
        if (status || atomic_read(&uc_pool->status))
                goto failed;
 
index 53351c3..96c31b4 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/irq.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
+#include <linux/rculist.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/intr.h>
index 8cc0c47..636588e 100644 (file)
@@ -629,7 +629,7 @@ static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info)
                if (use_ipi) {
                        /* use an interprocessor interrupt to call SAL */
                        smp_call_function_single(cpu, sn_hwperf_call_sal,
-                               op_info, 1, 1);
+                               op_info, 1);
                }
                else {
                        /* migrate the task before calling SAL */ 
index de153de..a5f864c 100644 (file)
@@ -296,6 +296,7 @@ config PREEMPT
 
 config SMP
        bool "Symmetric multi-processing support"
+       select USE_GENERIC_SMP_HELPERS
        ---help---
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
index e6709fe..16bcb18 100644 (file)
@@ -43,9 +43,6 @@ EXPORT_SYMBOL(dcache_dummy);
 #endif
 EXPORT_SYMBOL(cpu_data);
 
-/* Global SMP stuff */
-EXPORT_SYMBOL(smp_call_function);
-
 /* TLB flushing */
 EXPORT_SYMBOL(smp_flush_tlb_page);
 #endif
index c837bc1..7577f97 100644 (file)
 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
 
 /*
- * Structure and data for smp_call_function(). This is designed to minimise
- * static memory requirements. It also looks cleaner.
- */
-static DEFINE_SPINLOCK(call_lock);
-
-struct call_data_struct {
-       void (*func) (void *info);
-       void *info;
-       atomic_t started;
-       atomic_t finished;
-       int wait;
-} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
-
-static struct call_data_struct *call_data;
-
-/*
  * For flush_cache_all()
  */
 static DEFINE_SPINLOCK(flushcache_lock);
@@ -96,9 +80,6 @@ void smp_invalidate_interrupt(void);
 void smp_send_stop(void);
 static void stop_this_cpu(void *);
 
-int smp_call_function(void (*) (void *), void *, int, int);
-void smp_call_function_interrupt(void);
-
 void smp_send_timer(void);
 void smp_ipi_timer_interrupt(struct pt_regs *);
 void smp_local_timer_interrupt(void);
@@ -231,7 +212,7 @@ void smp_flush_tlb_all(void)
        local_irq_save(flags);
        __flush_tlb_all();
        local_irq_restore(flags);
-       smp_call_function(flush_tlb_all_ipi, NULL, 1, 1);
+       smp_call_function(flush_tlb_all_ipi, NULL, 1);
        preempt_enable();
 }
 
@@ -524,7 +505,7 @@ void smp_invalidate_interrupt(void)
  *==========================================================================*/
 void smp_send_stop(void)
 {
-       smp_call_function(stop_this_cpu, NULL, 1, 0);
+       smp_call_function(stop_this_cpu, NULL, 0);
 }
 
 /*==========================================================================*
@@ -565,86 +546,14 @@ static void stop_this_cpu(void *dummy)
        for ( ; ; );
 }
 
-/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-/* Call function Routines                                                    */
-/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-
-/*==========================================================================*
- * Name:         smp_call_function
- *
- * Description:  This routine sends a 'CALL_FUNCTION_IPI' to all other CPUs
- *               in the system.
- *
- * Born on Date: 2002.02.05
- *
- * Arguments:    *func - The function to run. This must be fast and
- *                       non-blocking.
- *               *info - An arbitrary pointer to pass to the function.
- *               nonatomic - currently unused.
- *               wait - If true, wait (atomically) until function has
- *                      completed on other CPUs.
- *
- * Returns:      0 on success, else a negative status code. Does not return
- *               until remote CPUs are nearly ready to execute <<func>> or
- *               are or have executed.
- *
- * Cautions:     You must not call this function with disabled interrupts or
- *               from a hardware interrupt handler, you may call it from a
- *               bottom half handler.
- *
- * Modification log:
- * Date       Who Description
- * ---------- --- --------------------------------------------------------
- *
- *==========================================================================*/
-int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
-       int wait)
+void arch_send_call_function_ipi(cpumask_t mask)
 {
-       struct call_data_struct data;
-       int cpus;
-
-#ifdef DEBUG_SMP
-       unsigned long flags;
-       __save_flags(flags);
-       if (!(flags & 0x0040))  /* Interrupt Disable NONONO */
-               BUG();
-#endif /* DEBUG_SMP */
-
-       /* Holding any lock stops cpus from going down. */
-       spin_lock(&call_lock);
-       cpus = num_online_cpus() - 1;
-
-       if (!cpus) {
-               spin_unlock(&call_lock);
-               return 0;
-       }
-
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
-       data.func = func;
-       data.info = info;
-       atomic_set(&data.started, 0);
-       data.wait = wait;
-       if (wait)
-               atomic_set(&data.finished, 0);
-
-       call_data = &data;
-       mb();
-
-       /* Send a message to all other CPUs and wait for them to respond */
-       send_IPI_allbutself(CALL_FUNCTION_IPI, 0);
-
-       /* Wait for response */
-       while (atomic_read(&data.started) != cpus)
-               barrier();
-
-       if (wait)
-               while (atomic_read(&data.finished) != cpus)
-                       barrier();
-       spin_unlock(&call_lock);
+       send_IPI_mask(mask, CALL_FUNCTION_IPI, 0);
+}
 
-       return 0;
+void arch_send_call_function_single_ipi(int cpu)
+{
+       send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNC_SINGLE_IPI, 0);
 }
 
 /*==========================================================================*
@@ -666,27 +575,16 @@ int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
  *==========================================================================*/
 void smp_call_function_interrupt(void)
 {
-       void (*func) (void *info) = call_data->func;
-       void *info = call_data->info;
-       int wait = call_data->wait;
-
-       /*
-        * Notify initiating CPU that I've grabbed the data and am
-        * about to execute the function
-        */
-       mb();
-       atomic_inc(&call_data->started);
-       /*
-        * At this point the info structure may be out of scope unless wait==1
-        */
        irq_enter();
-       (*func)(info);
+       generic_smp_call_function_interrupt();
        irq_exit();
+}
 
-       if (wait) {
-               mb();
-               atomic_inc(&call_data->finished);
-       }
+void smp_call_function_single_interrupt(void)
+{
+       irq_enter();
+       generic_smp_call_function_single_interrupt();
+       irq_exit();
 }
 
 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
index 89ba4a0..46159a4 100644 (file)
@@ -40,6 +40,7 @@ extern void smp_invalidate_interrupt(void);
 extern void smp_call_function_interrupt(void);
 extern void smp_ipi_timer_interrupt(void);
 extern void smp_flush_cache_all_interrupt(void);
+extern void smp_call_function_single_interrupt(void);
 
 /*
  * for Boot AP function
@@ -103,7 +104,7 @@ void        set_eit_vector_entries(void)
        eit_vector[186] = (unsigned long)smp_call_function_interrupt;
        eit_vector[187] = (unsigned long)smp_ipi_timer_interrupt;
        eit_vector[188] = (unsigned long)smp_flush_cache_all_interrupt;
-       eit_vector[189] = 0;
+       eit_vector[189] = (unsigned long)smp_call_function_single_interrupt;
        eit_vector[190] = 0;
        eit_vector[191] = 0;
 #endif
index d23204e..d21df5f 100644 (file)
@@ -1657,6 +1657,7 @@ config SMP
        bool "Multi-Processing support"
        depends on SYS_SUPPORTS_SMP
        select IRQ_PER_CPU
+       select USE_GENERIC_SMP_HELPERS
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
index ed9febe..b47e461 100644 (file)
@@ -49,7 +49,7 @@ static void local_rm9k_perfcounter_irq_startup(void *args)
 
 static unsigned int rm9k_perfcounter_irq_startup(unsigned int irq)
 {
-       on_each_cpu(local_rm9k_perfcounter_irq_startup, (void *) irq, 0, 1);
+       on_each_cpu(local_rm9k_perfcounter_irq_startup, (void *) irq, 1);
 
        return 0;
 }
@@ -66,7 +66,7 @@ static void local_rm9k_perfcounter_irq_shutdown(void *args)
 
 static void rm9k_perfcounter_irq_shutdown(unsigned int irq)
 {
-       on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1);
+       on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 1);
 }
 
 static struct irq_chip rm9k_irq_controller = {
index cdf87a9..4410f17 100644 (file)
@@ -131,148 +131,29 @@ asmlinkage __cpuinit void start_secondary(void)
        cpu_idle();
 }
 
-DEFINE_SPINLOCK(smp_call_lock);
-
-struct call_data_struct *call_data;
-
-/*
- * Run a function on all other CPUs.
- *
- *  <mask>     cpuset_t of all processors to run the function on.
- *  <func>      The function to run. This must be fast and non-blocking.
- *  <info>      An arbitrary pointer to pass to the function.
- *  <retry>     If true, keep retrying until ready.
- *  <wait>      If true, wait until function has completed on other CPUs.
- *  [RETURNS]   0 on success, else a negative status code.
- *
- * Does not return until remote CPUs are nearly ready to execute <func>
- * or are or have executed.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler:
- *
- * CPU A                               CPU B
- * Disable interrupts
- *                                     smp_call_function()
- *                                     Take call_lock
- *                                     Send IPIs
- *                                     Wait for all cpus to acknowledge IPI
- *                                     CPU A has not responded, spin waiting
- *                                     for cpu A to respond, holding call_lock
- * smp_call_function()
- * Spin waiting for call_lock
- * Deadlock                            Deadlock
- */
-int smp_call_function_mask(cpumask_t mask, void (*func) (void *info),
-       void *info, int retry, int wait)
+void arch_send_call_function_ipi(cpumask_t mask)
 {
-       struct call_data_struct data;
-       int cpu = smp_processor_id();
-       int cpus;
-
-       /*
-        * Can die spectacularly if this CPU isn't yet marked online
-        */
-       BUG_ON(!cpu_online(cpu));
-
-       cpu_clear(cpu, mask);
-       cpus = cpus_weight(mask);
-       if (!cpus)
-               return 0;
-
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
-       data.func = func;
-       data.info = info;
-       atomic_set(&data.started, 0);
-       data.wait = wait;
-       if (wait)
-               atomic_set(&data.finished, 0);
-
-       spin_lock(&smp_call_lock);
-       call_data = &data;
-       smp_mb();
-
-       /* Send a message to all other CPUs and wait for them to respond */
        mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
-
-       /* Wait for response */
-       /* FIXME: lock-up detection, backtrace on lock-up */
-       while (atomic_read(&data.started) != cpus)
-               barrier();
-
-       if (wait)
-               while (atomic_read(&data.finished) != cpus)
-                       barrier();
-       call_data = NULL;
-       spin_unlock(&smp_call_lock);
-
-       return 0;
 }
 
-int smp_call_function(void (*func) (void *info), void *info, int retry,
-       int wait)
+/*
+ * We reuse the same vector for the single IPI
+ */
+void arch_send_call_function_single_ipi(int cpu)
 {
-       return smp_call_function_mask(cpu_online_map, func, info, retry, wait);
+       mp_ops->send_ipi_mask(cpumask_of_cpu(cpu), SMP_CALL_FUNCTION);
 }
-EXPORT_SYMBOL(smp_call_function);
 
+/*
+ * Call into both interrupt handlers, as we share the IPI for them
+ */
 void smp_call_function_interrupt(void)
 {
-       void (*func) (void *info) = call_data->func;
-       void *info = call_data->info;
-       int wait = call_data->wait;
-
-       /*
-        * Notify initiating CPU that I've grabbed the data and am
-        * about to execute the function.
-        */
-       smp_mb();
-       atomic_inc(&call_data->started);
-
-       /*
-        * At this point the info structure may be out of scope unless wait==1.
-        */
        irq_enter();
-       (*func)(info);
+       generic_smp_call_function_single_interrupt();
+       generic_smp_call_function_interrupt();
        irq_exit();
-
-       if (wait) {
-               smp_mb();
-               atomic_inc(&call_data->finished);
-       }
-}
-
-int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
-                            int retry, int wait)
-{
-       int ret, me;
-
-       /*
-        * Can die spectacularly if this CPU isn't yet marked online
-        */
-       if (!cpu_online(cpu))
-               return 0;
-
-       me = get_cpu();
-       BUG_ON(!cpu_online(me));
-
-       if (cpu == me) {
-               local_irq_disable();
-               func(info);
-               local_irq_enable();
-               put_cpu();
-               return 0;
-       }
-
-       ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, retry,
-                                    wait);
-
-       put_cpu();
-       return 0;
 }
-EXPORT_SYMBOL(smp_call_function_single);
 
 static void stop_this_cpu(void *dummy)
 {
@@ -286,7 +167,7 @@ static void stop_this_cpu(void *dummy)
 
 void smp_send_stop(void)
 {
-       smp_call_function(stop_this_cpu, NULL, 1, 0);
+       smp_call_function(stop_this_cpu, NULL, 0);
 }
 
 void __init smp_cpus_done(unsigned int max_cpus)
@@ -365,7 +246,7 @@ static void flush_tlb_all_ipi(void *info)
 
 void flush_tlb_all(void)
 {
-       on_each_cpu(flush_tlb_all_ipi, NULL, 1, 1);
+       on_each_cpu(flush_tlb_all_ipi, NULL, 1);
 }
 
 static void flush_tlb_mm_ipi(void *mm)
@@ -385,7 +266,7 @@ static void flush_tlb_mm_ipi(void *mm)
 static inline void smp_on_other_tlbs(void (*func) (void *info), void *info)
 {
 #ifndef CONFIG_MIPS_MT_SMTC
-       smp_call_function(func, info, 1, 1);
+       smp_call_function(func, info, 1);
 #endif
 }
 
@@ -485,7 +366,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
                .addr2 = end,
        };
 
-       on_each_cpu(flush_tlb_kernel_range_ipi, &fd, 1, 1);
+       on_each_cpu(flush_tlb_kernel_range_ipi, &fd, 1);
 }
 
 static void flush_tlb_page_ipi(void *info)
index 3e86318..a516286 100644 (file)
@@ -877,7 +877,6 @@ static void ipi_resched_interrupt(void)
        /* Return from interrupt should be enough to cause scheduler check */
 }
 
-
 static void ipi_call_interrupt(void)
 {
        /* Invoke generic function invocation code in smp.c */
index ebd9db8..5eb4681 100644 (file)
@@ -73,3 +73,4 @@ void save_stack_trace(struct stack_trace *trace)
        prepare_frametrace(regs);
        save_context_stack(trace, regs);
 }
+EXPORT_SYMBOL_GPL(save_stack_trace);
index 2709675..71df339 100644 (file)
  *    primary cache.
  */
 static inline void r4k_on_each_cpu(void (*func) (void *info), void *info,
-                                   int retry, int wait)
+                                   int wait)
 {
        preempt_disable();
 
 #if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
-       smp_call_function(func, info, retry, wait);
+       smp_call_function(func, info, wait);
 #endif
        func(info);
        preempt_enable();
@@ -350,7 +350,7 @@ static inline void local_r4k___flush_cache_all(void * args)
 
 static void r4k___flush_cache_all(void)
 {
-       r4k_on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1);
+       r4k_on_each_cpu(local_r4k___flush_cache_all, NULL, 1);
 }
 
 static inline int has_valid_asid(const struct mm_struct *mm)
@@ -397,7 +397,7 @@ static void r4k_flush_cache_range(struct vm_area_struct *vma,
        int exec = vma->vm_flags & VM_EXEC;
 
        if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc))
-               r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
+               r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1);
 }
 
 static inline void local_r4k_flush_cache_mm(void * args)
@@ -429,7 +429,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm)
        if (!cpu_has_dc_aliases)
                return;
 
-       r4k_on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_cache_mm, mm, 1);
 }
 
 struct flush_cache_page_args {
@@ -521,7 +521,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
        args.addr = addr;
        args.pfn = pfn;
 
-       r4k_on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_cache_page, &args, 1);
 }
 
 static inline void local_r4k_flush_data_cache_page(void * addr)
@@ -535,7 +535,7 @@ static void r4k_flush_data_cache_page(unsigned long addr)
                local_r4k_flush_data_cache_page((void *)addr);
        else
                r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr,
-                               1, 1);
+                               1);
 }
 
 struct flush_icache_range_args {
@@ -571,7 +571,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
        args.start = start;
        args.end = end;
 
-       r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1);
        instruction_hazard();
 }
 
@@ -672,7 +672,7 @@ static void local_r4k_flush_cache_sigtramp(void * arg)
 
 static void r4k_flush_cache_sigtramp(unsigned long addr)
 {
-       r4k_on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr, 1);
 }
 
 static void r4k_flush_icache_all(void)
index b5f6f71..dd2fbd6 100644 (file)
@@ -27,7 +27,7 @@ static int op_mips_setup(void)
        model->reg_setup(ctr);
 
        /* Configure the registers on all cpus.  */
-       on_each_cpu(model->cpu_setup, NULL, 0, 1);
+       on_each_cpu(model->cpu_setup, NULL, 1);
 
         return 0;
 }
@@ -58,7 +58,7 @@ static int op_mips_create_files(struct super_block * sb, struct dentry * root)
 
 static int op_mips_start(void)
 {
-       on_each_cpu(model->cpu_start, NULL, 0, 1);
+       on_each_cpu(model->cpu_start, NULL, 1);
 
        return 0;
 }
@@ -66,7 +66,7 @@ static int op_mips_start(void)
 static void op_mips_stop(void)
 {
        /* Disable performance monitoring for all counters.  */
-       on_each_cpu(model->cpu_stop, NULL, 0, 1);
+       on_each_cpu(model->cpu_stop, NULL, 1);
 }
 
 int __init oprofile_arch_init(struct oprofile_operations *ops)
index b40df7d..54759f1 100644 (file)
@@ -313,7 +313,7 @@ static int __init mipsxx_init(void)
        if (!cpu_has_mipsmt_pertccounters)
                counters = counters_total_to_per_cpu(counters);
 #endif
-       on_each_cpu(reset_counters, (void *)(long)counters, 0, 1);
+       on_each_cpu(reset_counters, (void *)(long)counters, 1);
 
        op_model_mipsxx_ops.num_counters = counters;
        switch (current_cpu_type()) {
@@ -382,7 +382,7 @@ static void mipsxx_exit(void)
        int counters = op_model_mipsxx_ops.num_counters;
 
        counters = counters_per_cpu_to_total(counters);
-       on_each_cpu(reset_counters, (void *)(long)counters, 0, 1);
+       on_each_cpu(reset_counters, (void *)(long)counters, 1);
 
        perf_irq = save_perf_irq;
 }
index 35dc435..cf4c868 100644 (file)
@@ -64,7 +64,7 @@ static void prom_exit(void)
 #ifdef CONFIG_SMP
        if (smp_processor_id())
                /* CPU 1 */
-               smp_call_function(prom_cpu0_exit, NULL, 1, 1);
+               smp_call_function(prom_cpu0_exit, NULL, 1);
 #endif
        prom_cpu0_exit(NULL);
 }
index 33fce82..fd9604d 100644 (file)
@@ -74,7 +74,7 @@ static void __noreturn cfe_linux_exit(void *arg)
                if (!reboot_smp) {
                        /* Get CPU 0 to do the cfe_exit */
                        reboot_smp = 1;
-                       smp_call_function(cfe_linux_exit, arg, 1, 0);
+                       smp_call_function(cfe_linux_exit, arg, 0);
                }
        } else {
                printk("Passing control back to CFE...\n");
index cf8f6b3..65b1af6 100644 (file)
@@ -66,7 +66,7 @@ static void prom_linux_exit(void)
 {
 #ifdef CONFIG_SMP
        if (smp_processor_id()) {
-               smp_call_function(prom_cpu0_exit, NULL, 1, 1);
+               smp_call_function(prom_cpu0_exit, NULL, 1);
        }
 #endif
        while(1);
index 1775755..255d692 100644 (file)
@@ -1,3 +1,4 @@
 obj-y                          := setup.o rtc_xicor1241.o rtc_m41t81.o
 
+obj-$(CONFIG_I2C_BOARDINFO)    += swarm-i2c.o
 obj-$(CONFIG_KGDB)             += dbg_io.o
diff --git a/arch/mips/sibyte/swarm/swarm-i2c.c b/arch/mips/sibyte/swarm/swarm-i2c.c
new file mode 100644 (file)
index 0000000..4282ac9
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *     arch/mips/sibyte/swarm/swarm-i2c.c
+ *
+ *     Broadcom BCM91250A (SWARM), etc. I2C platform setup.
+ *
+ *     Copyright (c) 2008  Maciej W. Rozycki
+ *
+ *     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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+
+static struct i2c_board_info swarm_i2c_info1[] __initdata = {
+       {
+               I2C_BOARD_INFO("m41t81", 0x68),
+       },
+};
+
+static int __init swarm_i2c_init(void)
+{
+       int err;
+
+       err = i2c_register_board_info(1, swarm_i2c_info1,
+                                     ARRAY_SIZE(swarm_i2c_info1));
+       if (err < 0)
+               printk(KERN_ERR
+                      "swarm-i2c: cannot register board I2C devices\n");
+       return err;
+}
+
+arch_initcall(swarm_i2c_init);
index bc7a19d..a7d4fd3 100644 (file)
@@ -199,6 +199,7 @@ endchoice
 
 config SMP
        bool "Symmetric multi-processing support"
+       select USE_GENERIC_SMP_HELPERS
        ---help---
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
index e10d25d..5259d8c 100644 (file)
@@ -51,12 +51,12 @@ static struct pdc_btlb_info btlb_info __read_mostly;
 void
 flush_data_cache(void)
 {
-       on_each_cpu(flush_data_cache_local, NULL, 1, 1);
+       on_each_cpu(flush_data_cache_local, NULL, 1);
 }
 void 
 flush_instruction_cache(void)
 {
-       on_each_cpu(flush_instruction_cache_local, NULL, 1, 1);
+       on_each_cpu(flush_instruction_cache_local, NULL, 1);
 }
 #endif
 
@@ -515,7 +515,7 @@ static void cacheflush_h_tmp_function(void *dummy)
 
 void flush_cache_all(void)
 {
-       on_each_cpu(cacheflush_h_tmp_function, NULL, 1, 1);
+       on_each_cpu(cacheflush_h_tmp_function, NULL, 1);
 }
 
 void flush_cache_mm(struct mm_struct *mm)
index 85fc775..d47f397 100644 (file)
@@ -84,19 +84,11 @@ EXPORT_SYMBOL(cpu_possible_map);
 
 DEFINE_PER_CPU(spinlock_t, ipi_lock) = SPIN_LOCK_UNLOCKED;
 
-struct smp_call_struct {
-       void (*func) (void *info);
-       void *info;
-       long wait;
-       atomic_t unstarted_count;
-       atomic_t unfinished_count;
-};
-static volatile struct smp_call_struct *smp_call_function_data;
-
 enum ipi_message_type {
        IPI_NOP=0,
        IPI_RESCHEDULE=1,
        IPI_CALL_FUNC,
+       IPI_CALL_FUNC_SINGLE,
        IPI_CPU_START,
        IPI_CPU_STOP,
        IPI_CPU_TEST
@@ -187,33 +179,12 @@ ipi_interrupt(int irq, void *dev_id)
 
                        case IPI_CALL_FUNC:
                                smp_debug(100, KERN_DEBUG "CPU%d IPI_CALL_FUNC\n", this_cpu);
-                               {
-                                       volatile struct smp_call_struct *data;
-                                       void (*func)(void *info);
-                                       void *info;
-                                       int wait;
-
-                                       data = smp_call_function_data;
-                                       func = data->func;
-                                       info = data->info;
-                                       wait = data->wait;
-
-                                       mb();
-                                       atomic_dec ((atomic_t *)&data->unstarted_count);
-
-                                       /* At this point, *data can't
-                                        * be relied upon.
-                                        */
-
-                                       (*func)(info);
-
-                                       /* Notify the sending CPU that the
-                                        * task is done.
-                                        */
-                                       mb();
-                                       if (wait)
-                                               atomic_dec ((atomic_t *)&data->unfinished_count);
-                               }
+                               generic_smp_call_function_interrupt();
+                               break;
+
+                       case IPI_CALL_FUNC_SINGLE:
+                               smp_debug(100, KERN_DEBUG "CPU%d IPI_CALL_FUNC_SINGLE\n", this_cpu);
+                               generic_smp_call_function_single_interrupt();
                                break;
 
                        case IPI_CPU_START:
@@ -256,6 +227,14 @@ ipi_send(int cpu, enum ipi_message_type op)
        spin_unlock_irqrestore(lock, flags);
 }
 
+static void
+send_IPI_mask(cpumask_t mask, enum ipi_message_type op)
+{
+       int cpu;
+
+       for_each_cpu_mask(cpu, mask)
+               ipi_send(cpu, op);
+}
 
 static inline void
 send_IPI_single(int dest_cpu, enum ipi_message_type op)
@@ -295,86 +274,15 @@ smp_send_all_nop(void)
        send_IPI_allbutself(IPI_NOP);
 }
 
-
-/**
- * Run a function on all other CPUs.
- *  <func>     The function to run. This must be fast and non-blocking.
- *  <info>     An arbitrary pointer to pass to the function.
- *  <retry>    If true, keep retrying until ready.
- *  <wait>     If true, wait until function has completed on other CPUs.
- *  [RETURNS]   0 on success, else a negative status code.
- *
- * Does not return until remote CPUs are nearly ready to execute <func>
- * or have executed.
- */
-
-int
-smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
+void arch_send_call_function_ipi(cpumask_t mask)
 {
-       struct smp_call_struct data;
-       unsigned long timeout;
-       static DEFINE_SPINLOCK(lock);
-       int retries = 0;
-
-       if (num_online_cpus() < 2)
-               return 0;
-
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
-       /* can also deadlock if IPIs are disabled */
-       WARN_ON((get_eiem() & (1UL<<(CPU_IRQ_MAX - IPI_IRQ))) == 0);
-
-       
-       data.func = func;
-       data.info = info;
-       data.wait = wait;
-       atomic_set(&data.unstarted_count, num_online_cpus() - 1);
-       atomic_set(&data.unfinished_count, num_online_cpus() - 1);
-
-       if (retry) {
-               spin_lock (&lock);
-               while (smp_call_function_data != 0)
-                       barrier();
-       }
-       else {
-               spin_lock (&lock);
-               if (smp_call_function_data) {
-                       spin_unlock (&lock);
-                       return -EBUSY;
-               }
-       }
-
-       smp_call_function_data = &data;
-       spin_unlock (&lock);
-       
-       /*  Send a message to all other CPUs and wait for them to respond  */
-       send_IPI_allbutself(IPI_CALL_FUNC);
-
- retry:
-       /*  Wait for response  */
-       timeout = jiffies + HZ;
-       while ( (atomic_read (&data.unstarted_count) > 0) &&
-               time_before (jiffies, timeout) )
-               barrier ();
-
-       if (atomic_read (&data.unstarted_count) > 0) {
-               printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d), try %d\n",
-                     smp_processor_id(), ++retries);
-               goto retry;
-       }
-       /* We either got one or timed out. Release the lock */
-
-       mb();
-       smp_call_function_data = NULL;
-
-       while (wait && atomic_read (&data.unfinished_count) > 0)
-                       barrier ();
-
-       return 0;
+       send_IPI_mask(mask, IPI_CALL_FUNC);
 }
 
-EXPORT_SYMBOL(smp_call_function);
+void arch_send_call_function_single_ipi(int cpu)
+{
+       send_IPI_single(cpu, IPI_CALL_FUNC_SINGLE);
+}
 
 /*
  * Flush all other CPU's tlb and then mine.  Do this with on_each_cpu()
@@ -384,7 +292,7 @@ EXPORT_SYMBOL(smp_call_function);
 void
 smp_flush_tlb_all(void)
 {
-       on_each_cpu(flush_tlb_all_local, NULL, 1, 1);
+       on_each_cpu(flush_tlb_all_local, NULL, 1);
 }
 
 /*
index ce0da68..b4d6c87 100644 (file)
@@ -1053,7 +1053,7 @@ void flush_tlb_all(void)
            do_recycle++;
        }
        spin_unlock(&sid_lock);
-       on_each_cpu(flush_tlb_all_local, NULL, 1, 1);
+       on_each_cpu(flush_tlb_all_local, NULL, 1);
        if (do_recycle) {
            spin_lock(&sid_lock);
            recycle_sids(recycle_ndirty,recycle_dirty_array);
index a5e9912..20eacf2 100644 (file)
@@ -111,6 +111,7 @@ config PPC
        select HAVE_KPROBES
        select HAVE_KRETPROBES
        select HAVE_LMB
+       select USE_GENERIC_SMP_HELPERS if SMP
        select HAVE_OPROFILE
 
 config EARLY_PRINTK
index 704375b..b732b5f 100644 (file)
@@ -172,7 +172,7 @@ static void kexec_prepare_cpus(void)
 {
        int my_cpu, i, notified=-1;
 
-       smp_call_function(kexec_smp_down, NULL, 0, /* wait */0);
+       smp_call_function(kexec_smp_down, NULL, /* wait */0);
        my_cpu = get_cpu();
 
        /* check the others cpus are now down (via paca hw cpu id == -1) */
index 34843c3..647f3e8 100644 (file)
@@ -747,7 +747,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
        /* Call function on all CPUs.  One of us will make the
         * rtas call
         */
-       if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0))
+       if (on_each_cpu(rtas_percpu_suspend_me, &data, 0))
                data.error = -EINVAL;
 
        wait_for_completion(&done);
index 1457aa0..5191b46 100644 (file)
@@ -72,12 +72,8 @@ struct smp_ops_t *smp_ops;
 
 static volatile unsigned int cpu_callin_map[NR_CPUS];
 
-void smp_call_function_interrupt(void);
-
 int smt_enabled_at_boot = 1;
 
-static int ipi_fail_ok;
-
 static void (*crash_ipi_function_ptr)(struct pt_regs *) = NULL;
 
 #ifdef CONFIG_PPC64
@@ -99,12 +95,15 @@ void smp_message_recv(int msg)
 {
        switch(msg) {
        case PPC_MSG_CALL_FUNCTION:
-               smp_call_function_interrupt();
+               generic_smp_call_function_interrupt();
                break;
        case PPC_MSG_RESCHEDULE:
                /* XXX Do we have to do this? */
                set_need_resched();
                break;
+       case PPC_MSG_CALL_FUNC_SINGLE:
+               generic_smp_call_function_single_interrupt();
+               break;
        case PPC_MSG_DEBUGGER_BREAK:
                if (crash_ipi_function_ptr) {
                        crash_ipi_function_ptr(get_irq_regs());
@@ -128,6 +127,19 @@ void smp_send_reschedule(int cpu)
                smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
 }
 
+void arch_send_call_function_single_ipi(int cpu)
+{
+       smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNC_SINGLE);
+}
+
+void arch_send_call_function_ipi(cpumask_t mask)
+{
+       unsigned int cpu;
+
+       for_each_cpu_mask(cpu, mask)
+               smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNCTION);
+}
+
 #ifdef CONFIG_DEBUGGER
 void smp_send_debugger_break(int cpu)
 {
@@ -154,215 +166,9 @@ static void stop_this_cpu(void *dummy)
                ;
 }
 
-/*
- * Structure and data for smp_call_function(). This is designed to minimise
- * static memory requirements. It also looks cleaner.
- * Stolen from the i386 version.
- */
-static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
-
-static struct call_data_struct {
-       void (*func) (void *info);
-       void *info;
-       atomic_t started;
-       atomic_t finished;
-       int wait;
-} *call_data;
-
-/* delay of at least 8 seconds */
-#define SMP_CALL_TIMEOUT       8
-
-/*
- * These functions send a 'generic call function' IPI to other online
- * CPUS in the system.
- *
- * [SUMMARY] Run a function on other CPUs.
- * <func> The function to run. This must be fast and non-blocking.
- * <info> An arbitrary pointer to pass to the function.
- * <nonatomic> currently unused.
- * <wait> If true, wait (atomically) until function has completed on other CPUs.
- * [RETURNS] 0 on success, else a negative status code. Does not return until
- * remote CPUs are nearly ready to execute <<func>> or are or have executed.
- * <map> is a cpu map of the cpus to send IPI to.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
- */
-static int __smp_call_function_map(void (*func) (void *info), void *info,
-                                  int nonatomic, int wait, cpumask_t map)
-{
-       struct call_data_struct data;
-       int ret = -1, num_cpus;
-       int cpu;
-       u64 timeout;
-
-       if (unlikely(smp_ops == NULL))
-               return ret;
-
-       data.func = func;
-       data.info = info;
-       atomic_set(&data.started, 0);
-       data.wait = wait;
-       if (wait)
-               atomic_set(&data.finished, 0);
-
-       /* remove 'self' from the map */
-       if (cpu_isset(smp_processor_id(), map))
-               cpu_clear(smp_processor_id(), map);
-
-       /* sanity check the map, remove any non-online processors. */
-       cpus_and(map, map, cpu_online_map);
-
-       num_cpus = cpus_weight(map);
-       if (!num_cpus)
-               goto done;
-
-       call_data = &data;
-       smp_wmb();
-       /* Send a message to all CPUs in the map */
-       for_each_cpu_mask(cpu, map)
-               smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNCTION);
-
-       timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec;
-
-       /* Wait for indication that they have received the message */
-       while (atomic_read(&data.started) != num_cpus) {
-               HMT_low();
-               if (get_tb() >= timeout) {
-                       printk("smp_call_function on cpu %d: other cpus not "
-                               "responding (%d)\n", smp_processor_id(),
-                               atomic_read(&data.started));
-                       if (!ipi_fail_ok)
-                               debugger(NULL);
-                       goto out;
-               }
-       }
-
-       /* optionally wait for the CPUs to complete */
-       if (wait) {
-               while (atomic_read(&data.finished) != num_cpus) {
-                       HMT_low();
-                       if (get_tb() >= timeout) {
-                               printk("smp_call_function on cpu %d: other "
-                                       "cpus not finishing (%d/%d)\n",
-                                       smp_processor_id(),
-                                       atomic_read(&data.finished),
-                                       atomic_read(&data.started));
-                               debugger(NULL);
-                               goto out;
-                       }
-               }
-       }
-
- done:
-       ret = 0;
-
- out:
-       call_data = NULL;
-       HMT_medium();
-       return ret;
-}
-
-static int __smp_call_function(void (*func)(void *info), void *info,
-                              int nonatomic, int wait)
-{
-       int ret;
-       spin_lock(&call_lock);
-       ret =__smp_call_function_map(func, info, nonatomic, wait,
-                                      cpu_online_map);
-       spin_unlock(&call_lock);
-       return ret;
-}
-
-int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
-                       int wait)
-{
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
-       return __smp_call_function(func, info, nonatomic, wait);
-}
-EXPORT_SYMBOL(smp_call_function);
-
-int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
-                            int nonatomic, int wait)
-{
-       cpumask_t map = CPU_MASK_NONE;
-       int ret = 0;
-
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
-       if (!cpu_online(cpu))
-               return -EINVAL;
-
-       cpu_set(cpu, map);
-       if (cpu != get_cpu()) {
-               spin_lock(&call_lock);
-               ret = __smp_call_function_map(func, info, nonatomic, wait, map);
-               spin_unlock(&call_lock);
-       } else {
-               local_irq_disable();
-               func(info);
-               local_irq_enable();
-       }
-       put_cpu();
-       return ret;
-}
-EXPORT_SYMBOL(smp_call_function_single);
-
 void smp_send_stop(void)
 {
-       int nolock;
-
-       /* It's OK to fail sending the IPI, since the alternative is to
-        * be stuck forever waiting on the other CPU to take the interrupt.
-        *
-        * It's better to at least continue and go through reboot, since this
-        * function is usually called at panic or reboot time in the first
-        * place.
-        */
-       ipi_fail_ok = 1;
-
-       /* Don't deadlock in case we got called through panic */
-       nolock = !spin_trylock(&call_lock);
-       __smp_call_function_map(stop_this_cpu, NULL, 1, 0, cpu_online_map);
-       if (!nolock)
-               spin_unlock(&call_lock);
-}
-
-void smp_call_function_interrupt(void)
-{
-       void (*func) (void *info);
-       void *info;
-       int wait;
-
-       /* call_data will be NULL if the sender timed out while
-        * waiting on us to receive the call.
-        */
-       if (!call_data)
-               return;
-
-       func = call_data->func;
-       info = call_data->info;
-       wait = call_data->wait;
-
-       if (!wait)
-               smp_mb__before_atomic_inc();
-
-       /*
-        * Notify initiating CPU that I've grabbed the data and am
-        * about to execute the function
-        */
-       atomic_inc(&call_data->started);
-       /*
-        * At this point the info structure may be out of scope unless wait==1
-        */
-       (*func)(info);
-       if (wait) {
-               smp_mb__before_atomic_inc();
-               atomic_inc(&call_data->finished);
-       }
+       smp_call_function(stop_this_cpu, NULL, 0);
 }
 
 extern struct gettimeofday_struct do_gtod;
@@ -596,9 +402,9 @@ int __devinit start_secondary(void *unused)
 
        secondary_cpu_time_init();
 
-       spin_lock(&call_lock);
+       ipi_call_lock();
        cpu_set(cpu, cpu_online_map);
-       spin_unlock(&call_lock);
+       ipi_call_unlock();
 
        local_irq_enable();
 
index 9629440..3cf0d94 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
+#include <linux/module.h>
 #include <asm/ptrace.h>
 
 /*
@@ -44,3 +45,4 @@ void save_stack_trace(struct stack_trace *trace)
                sp = newsp;
        }
 }
+EXPORT_SYMBOL_GPL(save_stack_trace);
index 368a493..c3a56d6 100644 (file)
@@ -192,7 +192,7 @@ static void tau_timeout_smp(unsigned long unused)
 
        /* schedule ourselves to be run again */
        mod_timer(&tau_timer, jiffies + shrink_timer) ;
-       on_each_cpu(tau_timeout, NULL, 1, 0);
+       on_each_cpu(tau_timeout, NULL, 0);
 }
 
 /*
@@ -234,7 +234,7 @@ int __init TAU_init(void)
        tau_timer.expires = jiffies + shrink_timer;
        add_timer(&tau_timer);
 
-       on_each_cpu(TAU_init_smp, NULL, 1, 0);
+       on_each_cpu(TAU_init_smp, NULL, 0);
 
        printk("Thermal assist unit ");
 #ifdef CONFIG_TAU_INT
index 73401e8..f1a38a6 100644 (file)
@@ -322,7 +322,7 @@ void snapshot_timebases(void)
 {
        if (!cpu_has_feature(CPU_FTR_PURR))
                return;
-       on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
+       on_each_cpu(snapshot_tb_and_purr, NULL, 1);
 }
 
 /*
index ad928ed..2bd12d9 100644 (file)
@@ -218,7 +218,7 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
        mb();
 
        /* XXX this is sub-optimal but will do for now */
-       on_each_cpu(slice_flush_segments, mm, 0, 1);
+       on_each_cpu(slice_flush_segments, mm, 1);
 #ifdef CONFIG_SPU_BASE
        spu_flush_all_slbs(mm);
 #endif
index e2d867c..69ad829 100644 (file)
@@ -66,7 +66,7 @@ static void pgtable_free_now(pgtable_free_t pgf)
 {
        pte_freelist_forced_free++;
 
-       smp_call_function(pte_free_smp_sync, NULL, 0, 1);
+       smp_call_function(pte_free_smp_sync, NULL, 1);
 
        pgtable_free(pgf);
 }
index 4908dc9..17807ac 100644 (file)
@@ -65,7 +65,7 @@ static int op_powerpc_setup(void)
 
        /* Configure the registers on all cpus.  If an error occurs on one
         * of the cpus, op_per_cpu_rc will be set to the error */
-       on_each_cpu(op_powerpc_cpu_setup, NULL, 0, 1);
+       on_each_cpu(op_powerpc_cpu_setup, NULL, 1);
 
 out:   if (op_per_cpu_rc) {
                /* error on setup release the performance counter hardware */
@@ -100,7 +100,7 @@ static int op_powerpc_start(void)
        if (model->global_start)
                return model->global_start(ctr);
        if (model->start) {
-               on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1);
+               on_each_cpu(op_powerpc_cpu_start, NULL, 1);
                return op_per_cpu_rc;
        }
        return -EIO; /* No start function is defined for this
@@ -115,7 +115,7 @@ static inline void op_powerpc_cpu_stop(void *dummy)
 static void op_powerpc_stop(void)
 {
        if (model->stop)
-               on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1);
+               on_each_cpu(op_powerpc_cpu_stop, NULL, 1);
         if (model->global_stop)
                 model->global_stop();
 }
index 5bf7df1..2d5bb22 100644 (file)
@@ -218,6 +218,7 @@ void iic_request_IPIs(void)
 {
        iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call");
        iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched");
+       iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE, "IPI-call-single");
 #ifdef CONFIG_DEBUGGER
        iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
 #endif /* CONFIG_DEBUGGER */
index f0b12f2..a0927a3 100644 (file)
@@ -105,9 +105,10 @@ static void __init ps3_smp_setup_cpu(int cpu)
         * to index needs to be setup.
         */
 
-       BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION  != 0);
-       BUILD_BUG_ON(PPC_MSG_RESCHEDULE     != 1);
-       BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3);
+       BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION    != 0);
+       BUILD_BUG_ON(PPC_MSG_RESCHEDULE       != 1);
+       BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2);
+       BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK   != 3);
 
        for (i = 0; i < MSG_COUNT; i++) {
                result = ps3_event_receive_port_setup(cpu, &virqs[i]);
index ebebc28..0fc830f 100644 (file)
@@ -383,13 +383,11 @@ static irqreturn_t xics_ipi_dispatch(int cpu)
                        mb();
                        smp_message_recv(PPC_MSG_RESCHEDULE);
                }
-#if 0
-               if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK,
+               if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,
                                       &xics_ipi_message[cpu].value)) {
                        mb();
-                       smp_message_recv(PPC_MSG_MIGRATE_TASK);
+                       smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
                }
-#endif
 #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
                if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
                                       &xics_ipi_message[cpu].value)) {
index 7680001..6c90c95 100644 (file)
@@ -1494,7 +1494,7 @@ void mpic_request_ipis(void)
        static char *ipi_names[] = {
                "IPI0 (call function)",
                "IPI1 (reschedule)",
-               "IPI2 (unused)",
+               "IPI2 (call function single)",
                "IPI3 (debugger break)",
        };
        BUG_ON(mpic == NULL);
index 0559985..bcab0d2 100644 (file)
@@ -152,7 +152,7 @@ static void stop_this_cpu(void *dummy)
 
 void smp_send_stop(void)
 {
-       smp_call_function(stop_this_cpu, NULL, 1, 0);
+       smp_call_function(stop_this_cpu, NULL, 0);
 }
 
 /*
index 9cb3d92..a7f8979 100644 (file)
@@ -203,7 +203,7 @@ __appldata_vtimer_setup(int cmd)
                        per_cpu(appldata_timer, i).expires = per_cpu_interval;
                        smp_call_function_single(i, add_virt_timer_periodic,
                                                 &per_cpu(appldata_timer, i),
-                                                0, 1);
+                                                1);
                }
                appldata_timer_active = 1;
                break;
@@ -228,7 +228,7 @@ __appldata_vtimer_setup(int cmd)
                        args.timer = &per_cpu(appldata_timer, i);
                        args.expires = per_cpu_interval;
                        smp_call_function_single(i, __appldata_mod_vtimer_wrap,
-                                                &args, 0, 1);
+                                                &args, 1);
                }
        }
 }
index 5d4fa4b..b678103 100644 (file)
@@ -109,7 +109,7 @@ static void do_call_function(void)
 }
 
 static void __smp_call_function_map(void (*func) (void *info), void *info,
-                                   int nonatomic, int wait, cpumask_t map)
+                                   int wait, cpumask_t map)
 {
        struct call_data_struct data;
        int cpu, local = 0;
@@ -162,7 +162,6 @@ out:
  * smp_call_function:
  * @func: the function to run; this must be fast and non-blocking
  * @info: an arbitrary pointer to pass to the function
- * @nonatomic: unused
  * @wait: if true, wait (atomically) until function has completed on other CPUs
  *
  * Run a function on all other CPUs.
@@ -170,15 +169,14 @@ out:
  * You must not call this function with disabled interrupts, from a
  * hardware interrupt handler or from a bottom half.
  */
-int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
-                     int wait)
+int smp_call_function(void (*func) (void *info), void *info, int wait)
 {
        cpumask_t map;
 
        spin_lock(&call_lock);
        map = cpu_online_map;
        cpu_clear(smp_processor_id(), map);
-       __smp_call_function_map(func, info, nonatomic, wait, map);
+       __smp_call_function_map(func, info, wait, map);
        spin_unlock(&call_lock);
        return 0;
 }
@@ -189,7 +187,6 @@ EXPORT_SYMBOL(smp_call_function);
  * @cpu: the CPU where func should run
  * @func: the function to run; this must be fast and non-blocking
  * @info: an arbitrary pointer to pass to the function
- * @nonatomic: unused
  * @wait: if true, wait (atomically) until function has completed on other CPUs
  *
  * Run a function on one processor.
@@ -198,11 +195,10 @@ EXPORT_SYMBOL(smp_call_function);
  * hardware interrupt handler or from a bottom half.
  */
 int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
-                            int nonatomic, int wait)
+                            int wait)
 {
        spin_lock(&call_lock);
-       __smp_call_function_map(func, info, nonatomic, wait,
-                               cpumask_of_cpu(cpu));
+       __smp_call_function_map(func, info, wait, cpumask_of_cpu(cpu));
        spin_unlock(&call_lock);
        return 0;
 }
@@ -228,7 +224,7 @@ int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
 {
        spin_lock(&call_lock);
        cpu_clear(smp_processor_id(), mask);
-       __smp_call_function_map(func, info, 0, wait, mask);
+       __smp_call_function_map(func, info, wait, mask);
        spin_unlock(&call_lock);
        return 0;
 }
@@ -303,7 +299,7 @@ static void smp_ptlb_callback(void *info)
 
 void smp_ptlb_all(void)
 {
-       on_each_cpu(smp_ptlb_callback, NULL, 0, 1);
+       on_each_cpu(smp_ptlb_callback, NULL, 1);
 }
 EXPORT_SYMBOL(smp_ptlb_all);
 #endif /* ! CONFIG_64BIT */
@@ -351,7 +347,7 @@ void smp_ctl_set_bit(int cr, int bit)
        memset(&parms.orvals, 0, sizeof(parms.orvals));
        memset(&parms.andvals, 0xff, sizeof(parms.andvals));
        parms.orvals[cr] = 1 << bit;
-       on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
+       on_each_cpu(smp_ctl_bit_callback, &parms, 1);
 }
 EXPORT_SYMBOL(smp_ctl_set_bit);
 
@@ -365,7 +361,7 @@ void smp_ctl_clear_bit(int cr, int bit)
        memset(&parms.orvals, 0, sizeof(parms.orvals));
        memset(&parms.andvals, 0xff, sizeof(parms.andvals));
        parms.andvals[cr] = ~(1L << bit);
-       on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
+       on_each_cpu(smp_ctl_bit_callback, &parms, 1);
 }
 EXPORT_SYMBOL(smp_ctl_clear_bit);
 
index 85e46a5..57571f1 100644 (file)
@@ -81,6 +81,7 @@ void save_stack_trace(struct stack_trace *trace)
                           S390_lowcore.thread_info,
                           S390_lowcore.thread_info + THREAD_SIZE, 1);
 }
+EXPORT_SYMBOL_GPL(save_stack_trace);
 
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
@@ -93,3 +94,4 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
        if (trace->nr_entries < trace->max_entries)
                trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
+EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
index 7418beb..f2cede3 100644 (file)
@@ -707,7 +707,7 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
         */
        memset(&etr_sync, 0, sizeof(etr_sync));
        preempt_disable();
-       smp_call_function(clock_sync_cpu_start, &etr_sync, 0, 0);
+       smp_call_function(clock_sync_cpu_start, &etr_sync, 0);
        local_irq_disable();
        enable_sync_clock();
 
@@ -746,7 +746,7 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
                rc = -EAGAIN;
        }
        local_irq_enable();
-       smp_call_function(clock_sync_cpu_end, NULL, 0, 0);
+       smp_call_function(clock_sync_cpu_end, NULL, 0);
        preempt_enable();
        return rc;
 }
@@ -926,7 +926,7 @@ static void etr_work_fn(struct work_struct *work)
        if (!eacr.ea) {
                /* Both ports offline. Reset everything. */
                eacr.dp = eacr.es = eacr.sl = 0;
-               on_each_cpu(disable_sync_clock, NULL, 0, 1);
+               on_each_cpu(disable_sync_clock, NULL, 1);
                del_timer_sync(&etr_timer);
                etr_update_eacr(eacr);
                clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
@@ -1432,7 +1432,7 @@ static void stp_work_fn(struct work_struct *work)
         */
        memset(&stp_sync, 0, sizeof(stp_sync));
        preempt_disable();
-       smp_call_function(clock_sync_cpu_start, &stp_sync, 0, 0);
+       smp_call_function(clock_sync_cpu_start, &stp_sync, 0);
        local_irq_disable();
        enable_sync_clock();
 
@@ -1465,7 +1465,7 @@ static void stp_work_fn(struct work_struct *work)
                stp_sync.in_sync = 1;
 
        local_irq_enable();
-       smp_call_function(clock_sync_cpu_end, NULL, 0, 0);
+       smp_call_function(clock_sync_cpu_end, NULL, 0);
        preempt_enable();
 }
 
index 9a854c8..3e7384f 100644 (file)
@@ -688,6 +688,7 @@ config CRASH_DUMP
 config SMP
        bool "Symmetric multi-processing support"
        depends on SYS_SUPPORTS_SMP
+       select USE_GENERIC_SMP_HELPERS
        ---help---
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
index 5d039d1..60c5084 100644 (file)
@@ -36,13 +36,6 @@ EXPORT_SYMBOL(cpu_possible_map);
 cpumask_t cpu_online_map;
 EXPORT_SYMBOL(cpu_online_map);
 
-static atomic_t cpus_booted = ATOMIC_INIT(0);
-
-/*
- * Run specified function on a particular processor.
- */
-void __smp_call_function(unsigned int cpu);
-
 static inline void __init smp_store_cpu_info(unsigned int cpu)
 {
        struct sh_cpuinfo *c = cpu_data + cpu;
@@ -175,45 +168,20 @@ static void stop_this_cpu(void *unused)
 
 void smp_send_stop(void)
 {
-       smp_call_function(stop_this_cpu, 0, 1, 0);
+       smp_call_function(stop_this_cpu, 0, 0);
 }
 
-struct smp_fn_call_struct smp_fn_call = {
-       .lock           = __SPIN_LOCK_UNLOCKED(smp_fn_call.lock),
-       .finished       = ATOMIC_INIT(0),
-};
-
-/*
- * The caller of this wants the passed function to run on every cpu.  If wait
- * is set, wait until all cpus have finished the function before returning.
- * The lock is here to protect the call structure.
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
- */
-int smp_call_function(void (*func)(void *info), void *info, int retry, int wait)
+void arch_send_call_function_ipi(cpumask_t mask)
 {
-       unsigned int nr_cpus = atomic_read(&cpus_booted);
-       int i;
-
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
-       spin_lock(&smp_fn_call.lock);
-
-       atomic_set(&smp_fn_call.finished, 0);
-       smp_fn_call.fn = func;
-       smp_fn_call.data = info;
-
-       for (i = 0; i < nr_cpus; i++)
-               if (i != smp_processor_id())
-                       plat_send_ipi(i, SMP_MSG_FUNCTION);
-
-       if (wait)
-               while (atomic_read(&smp_fn_call.finished) != (nr_cpus - 1));
+       int cpu;
 
-       spin_unlock(&smp_fn_call.lock);
+       for_each_cpu_mask(cpu, mask)
+               plat_send_ipi(cpu, SMP_MSG_FUNCTION);
+}
 
-       return 0;
+void arch_send_call_function_single_ipi(int cpu)
+{
+       plat_send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE);
 }
 
 /* Not really SMP stuff ... */
@@ -229,7 +197,7 @@ static void flush_tlb_all_ipi(void *info)
 
 void flush_tlb_all(void)
 {
-       on_each_cpu(flush_tlb_all_ipi, 0, 1, 1);
+       on_each_cpu(flush_tlb_all_ipi, 0, 1);
 }
 
 static void flush_tlb_mm_ipi(void *mm)
@@ -255,7 +223,7 @@ void flush_tlb_mm(struct mm_struct *mm)
        preempt_disable();
 
        if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
-               smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1);
+               smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1);
        } else {
                int i;
                for (i = 0; i < num_online_cpus(); i++)
@@ -292,7 +260,7 @@ void flush_tlb_range(struct vm_area_struct *vma,
                fd.vma = vma;
                fd.addr1 = start;
                fd.addr2 = end;
-               smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1, 1);
+               smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1);
        } else {
                int i;
                for (i = 0; i < num_online_cpus(); i++)
@@ -316,7 +284,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
 
        fd.addr1 = start;
        fd.addr2 = end;
-       on_each_cpu(flush_tlb_kernel_range_ipi, (void *)&fd, 1, 1);
+       on_each_cpu(flush_tlb_kernel_range_ipi, (void *)&fd, 1);
 }
 
 static void flush_tlb_page_ipi(void *info)
@@ -335,7 +303,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 
                fd.vma = vma;
                fd.addr1 = page;
-               smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1, 1);
+               smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1);
        } else {
                int i;
                for (i = 0; i < num_online_cpus(); i++)
@@ -359,6 +327,6 @@ void flush_tlb_one(unsigned long asid, unsigned long vaddr)
        fd.addr1 = asid;
        fd.addr2 = vaddr;
 
-       smp_call_function(flush_tlb_one_ipi, (void *)&fd, 1, 1);
+       smp_call_function(flush_tlb_one_ipi, (void *)&fd, 1);
        local_flush_tlb_one(asid, vaddr);
 }
index d41e561..1b2ae35 100644 (file)
@@ -34,3 +34,4 @@ void save_stack_trace(struct stack_trace *trace)
                }
        }
 }
+EXPORT_SYMBOL_GPL(save_stack_trace);
index fa63c68..c099d96 100644 (file)
@@ -807,7 +807,6 @@ extern unsigned long xcall_call_function;
  * smp_call_function(): Run a function on all other CPUs.
  * @func: The function to run. This must be fast and non-blocking.
  * @info: An arbitrary pointer to pass to the function.
- * @nonatomic: currently unused.
  * @wait: If true, wait (atomically) until function has completed on other CPUs.
  *
  * Returns 0 on success, else a negative status code. Does not return until
@@ -816,8 +815,8 @@ extern unsigned long xcall_call_function;
  * You must not call this function with disabled interrupts or from a
  * hardware interrupt handler or from a bottom half handler.
  */
-static int smp_call_function_mask(void (*func)(void *info), void *info,
-                                 int nonatomic, int wait, cpumask_t mask)
+static int sparc64_smp_call_function_mask(void (*func)(void *info), void *info,
+                                         int wait, cpumask_t mask)
 {
        struct call_data_struct data;
        int cpus;
@@ -852,11 +851,9 @@ out_unlock:
        return 0;
 }
 
-int smp_call_function(void (*func)(void *info), void *info,
-                     int nonatomic, int wait)
+int smp_call_function(void (*func)(void *info), void *info, int wait)
 {
-       return smp_call_function_mask(func, info, nonatomic, wait,
-                                     cpu_online_map);
+       return sparc64_smp_call_function_mask(func, info, wait, cpu_online_map);
 }
 
 void smp_call_function_client(int irq, struct pt_regs *regs)
@@ -893,7 +890,7 @@ static void tsb_sync(void *info)
 
 void smp_tsb_sync(struct mm_struct *mm)
 {
-       smp_call_function_mask(tsb_sync, mm, 0, 1, mm->cpu_vm_mask);
+       sparc64_smp_call_function_mask(tsb_sync, mm, 1, mm->cpu_vm_mask);
 }
 
 extern unsigned long xcall_flush_tlb_mm;
index c73ce3f..b3e3737 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
 #include <linux/thread_info.h>
+#include <linux/module.h>
 #include <asm/ptrace.h>
 #include <asm/stacktrace.h>
 
@@ -47,3 +48,4 @@ void save_stack_trace(struct stack_trace *trace)
                        trace->entries[trace->nr_entries++] = pc;
        } while (trace->nr_entries < trace->max_entries);
 }
+EXPORT_SYMBOL_GPL(save_stack_trace);
index 6cfab2e..ebefd2a 100644 (file)
@@ -344,7 +344,7 @@ void hugetlb_prefault_arch_hook(struct mm_struct *mm)
                         * also executing in this address space.
                         */
                        mm->context.sparc64_ctx_val = ctx;
-                       on_each_cpu(context_reload, mm, 0, 0);
+                       on_each_cpu(context_reload, mm, 0);
                }
                spin_unlock(&ctx_alloc_lock);
        }
index e1062ec..be2d50c 100644 (file)
@@ -214,8 +214,7 @@ void smp_call_function_slave(int cpu)
        atomic_inc(&scf_finished);
 }
 
-int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
-                     int wait)
+int smp_call_function(void (*_func)(void *info), void *_info, int wait)
 {
        int cpus = num_online_cpus() - 1;
        int i;
index 6958d6b..96e0c2e 100644 (file)
@@ -170,6 +170,7 @@ config GENERIC_PENDING_IRQ
 config X86_SMP
        bool
        depends on SMP && ((X86_32 && !X86_VOYAGER) || X86_64)
+       select USE_GENERIC_SMP_HELPERS
        default y
 
 config X86_32_SMP
@@ -447,7 +448,6 @@ config PARAVIRT_DEBUG
 config MEMTEST
        bool "Memtest"
        depends on X86_64
-       default y
        help
          This option adds a kernel parameter 'memtest', which allows memtest
          to be set.
@@ -455,7 +455,7 @@ config MEMTEST
                memtest=1, mean do 1 test pattern;
                ...
                memtest=4, mean do 4 test patterns.
-         If you are unsure how to answer this question, answer Y.
+         If you are unsure how to answer this question, answer N.
 
 config X86_SUMMIT_NUMA
        def_bool y
@@ -1135,21 +1135,18 @@ config MTRR
          See <file:Documentation/mtrr.txt> for more information.
 
 config MTRR_SANITIZER
-       def_bool y
+       bool
        prompt "MTRR cleanup support"
        depends on MTRR
        help
-         Convert MTRR layout from continuous to discrete, so some X driver
-         could add WB entries.
+         Convert MTRR layout from continuous to discrete, so X drivers can
+         add writeback entries.
 
-         Say N here if you see bootup problems (boot crash, boot hang,
-         spontaneous reboots).
+         Can be disabled with disable_mtrr_cleanup on the kernel command line.
+         The largest mtrr entry size for a continous block can be set with
+         mtrr_chunk_size.
 
-         Could be disabled with disable_mtrr_cleanup. Also mtrr_chunk_size
-         could be used to send largest mtrr entry size for continuous block
-         to hold holes (aka. UC entries)
-
-         If unsure, say Y.
+         If unsure, say N.
 
 config MTRR_SANITIZER_ENABLE_DEFAULT
        int "MTRR cleanup enable value (0-1)"
@@ -1166,7 +1163,7 @@ config MTRR_SANITIZER_SPARE_REG_NR_DEFAULT
        depends on MTRR_SANITIZER
        help
          mtrr cleanup spare entries default, it can be changed via
-         mtrr_spare_reg_nr=
+         mtrr_spare_reg_nr=N on the kernel command line.
 
 config X86_PAT
        bool
index e6a4b56..793ad20 100644 (file)
@@ -23,6 +23,15 @@ static unsigned long acpi_realmode;
 static char temp_stack[10240];
 #endif
 
+/* XXX: this macro should move to asm-x86/segment.h and be shared with the
+   boot code... */
+#define GDT_ENTRY(flags, base, limit)          \
+       (((u64)(base & 0xff000000) << 32) |     \
+        ((u64)flags << 40) |                   \
+        ((u64)(limit & 0x00ff0000) << 32) |    \
+        ((u64)(base & 0x00ffffff) << 16) |     \
+        ((u64)(limit & 0x0000ffff)))
+
 /**
  * acpi_save_state_mem - save kernel state
  *
@@ -51,18 +60,27 @@ int acpi_save_state_mem(void)
        header->video_mode = saved_video_mode;
 
        header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
+
+       /*
+        * Set up the wakeup GDT.  We set these up as Big Real Mode,
+        * that is, with limits set to 4 GB.  At least the Lenovo
+        * Thinkpad X61 is known to need this for the video BIOS
+        * initialization quirk to work; this is likely to also
+        * be the case for other laptops or integrated video devices.
+        */
+
        /* GDT[0]: GDT self-pointer */
        header->wakeup_gdt[0] =
                (u64)(sizeof(header->wakeup_gdt) - 1) +
                ((u64)(acpi_wakeup_address +
                        ((char *)&header->wakeup_gdt - (char *)acpi_realmode))
                                << 16);
-       /* GDT[1]: real-mode-like code segment */
-       header->wakeup_gdt[1] = (0x009bULL << 40) +
-               ((u64)acpi_wakeup_address << 16) + 0xffff;
-       /* GDT[2]: real-mode-like data segment */
-       header->wakeup_gdt[2] = (0x0093ULL << 40) +
-               ((u64)acpi_wakeup_address << 16) + 0xffff;
+       /* GDT[1]: big real mode-like code segment */
+       header->wakeup_gdt[1] =
+               GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff);
+       /* GDT[2]: big real mode-like data segment */
+       header->wakeup_gdt[2] =
+               GDT_ENTRY(0x8093, acpi_wakeup_address, 0xfffff);
 
 #ifndef CONFIG_64BIT
        store_gdt((struct desc_ptr *)&header->pmode_gdt);
index 3e58b67..a437d02 100644 (file)
@@ -1340,6 +1340,10 @@ void __init smp_intr_init(void)
 
        /* IPI for generic function call */
        alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+
+       /* IPI for single call function */
+       set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
+                               call_function_single_interrupt);
 }
 #endif
 
index 9874107..c4a7ec3 100644 (file)
@@ -364,7 +364,7 @@ static void mcheck_check_cpu(void *info)
 
 static void mcheck_timer(struct work_struct *work)
 {
-       on_each_cpu(mcheck_check_cpu, NULL, 1, 1);
+       on_each_cpu(mcheck_check_cpu, NULL, 1);
 
        /*
         * Alert userspace if needed.  If we logged an MCE, reduce the
@@ -621,7 +621,7 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
         * Collect entries that were still getting written before the
         * synchronize.
         */
-       on_each_cpu(collect_tscs, cpu_tsc, 1, 1);
+       on_each_cpu(collect_tscs, cpu_tsc, 1);
        for (i = next; i < MCE_LOG_LEN; i++) {
                if (mcelog.entry[i].finished &&
                    mcelog.entry[i].tsc < cpu_tsc[mcelog.entry[i].cpu]) {
@@ -746,7 +746,7 @@ static void mce_restart(void)
        if (next_interval)
                cancel_delayed_work(&mcheck_work);
        /* Timer race is harmless here */
-       on_each_cpu(mce_init, NULL, 1, 1);
+       on_each_cpu(mce_init, NULL, 1);
        next_interval = check_interval * HZ;
        if (next_interval)
                schedule_delayed_work(&mcheck_work,
index 00ccb6c..cc1fccd 100644 (file)
@@ -59,7 +59,7 @@ static DECLARE_DELAYED_WORK(mce_work, mce_work_fn);
 
 static void mce_work_fn(struct work_struct *work)
 {
-       on_each_cpu(mce_checkregs, NULL, 1, 1);
+       on_each_cpu(mce_checkregs, NULL, 1);
        schedule_delayed_work(&mce_work, round_jiffies_relative(MCE_RATE));
 }
 
index 105afe1..6f23969 100644 (file)
@@ -223,7 +223,7 @@ static void set_mtrr(unsigned int reg, unsigned long base,
        atomic_set(&data.gate,0);
 
        /*  Start the ball rolling on other CPUs  */
-       if (smp_call_function(ipi_handler, &data, 1, 0) != 0)
+       if (smp_call_function(ipi_handler, &data, 0) != 0)
                panic("mtrr: timed out waiting for other CPUs\n");
 
        local_irq_save(flags);
@@ -1682,7 +1682,7 @@ void mtrr_ap_init(void)
  */
 void mtrr_save_state(void)
 {
-       smp_call_function_single(0, mtrr_save_fixed_ranges, NULL, 1, 1);
+       smp_call_function_single(0, mtrr_save_fixed_ranges, NULL, 1);
 }
 
 static int __init mtrr_init_finialize(void)
index 2e9bef6..6d4bdc0 100644 (file)
@@ -189,7 +189,7 @@ void disable_lapic_nmi_watchdog(void)
        if (atomic_read(&nmi_active) <= 0)
                return;
 
-       on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
+       on_each_cpu(stop_apic_nmi_watchdog, NULL, 1);
 
        if (wd_ops)
                wd_ops->unreserve();
@@ -213,7 +213,7 @@ void enable_lapic_nmi_watchdog(void)
                return;
        }
 
-       on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
+       on_each_cpu(setup_apic_nmi_watchdog, NULL, 1);
        touch_nmi_watchdog();
 }
 
index 71f1c26..2de5fa2 100644 (file)
@@ -96,7 +96,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
        for (; count; count -= 16) {
                cmd.eax = pos;
                cmd.ecx = pos >> 32;
-               smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1, 1);
+               smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1);
                if (copy_to_user(tmp, &cmd, 16))
                        return -EFAULT;
                tmp += 16;
index ba41bf4..ae63e58 100644 (file)
@@ -816,6 +816,9 @@ END(invalidate_interrupt\num)
 ENTRY(call_function_interrupt)
        apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
 END(call_function_interrupt)
+ENTRY(call_function_single_interrupt)
+       apicinterrupt CALL_FUNCTION_SINGLE_VECTOR,smp_call_function_single_interrupt
+END(call_function_single_interrupt)
 ENTRY(irq_move_cleanup_interrupt)
        apicinterrupt IRQ_MOVE_CLEANUP_VECTOR,smp_irq_move_cleanup_interrupt
 END(irq_move_cleanup_interrupt)
index 603261a..558abf4 100644 (file)
@@ -1569,7 +1569,7 @@ void /*__init*/ print_local_APIC(void *dummy)
 
 void print_all_local_APICs(void)
 {
-       on_each_cpu(print_local_APIC, NULL, 1, 1);
+       on_each_cpu(print_local_APIC, NULL, 1);
 }
 
 void /*__init*/ print_PIC(void)
index b16ef02..6510cde 100644 (file)
@@ -1160,7 +1160,7 @@ void __apicdebuginit print_local_APIC(void * dummy)
 
 void print_all_local_APICs (void)
 {
-       on_each_cpu(print_local_APIC, NULL, 1, 1);
+       on_each_cpu(print_local_APIC, NULL, 1);
 }
 
 void __apicdebuginit print_PIC(void)
index 31f49e8..0373e88 100644 (file)
@@ -199,6 +199,10 @@ void __init native_init_IRQ(void)
        /* IPI for generic function call */
        alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
 
+       /* IPI for generic single function call */
+       alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
+                       call_function_single_interrupt);
+
        /* Low priority IPI to cleanup after moving an irq */
        set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
 #endif
index 21f2bae..a844957 100644 (file)
@@ -68,7 +68,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
                load_LDT(pc);
                mask = cpumask_of_cpu(smp_processor_id());
                if (!cpus_equal(current->mm->cpu_vm_mask, mask))
-                       smp_call_function(flush_ldt, current->mm, 1, 1);
+                       smp_call_function(flush_ldt, current->mm, 1);
                preempt_enable();
 #else
                load_LDT(pc);