]> nv-tegra.nvidia Code Review - linux-3.10.git/commitdiff
Automatic merge of /spare/repo/netdev-2.6 branch forcedeth
author <jgarzik@pretzel.yyz.us> <>
Thu, 26 May 2005 02:10:25 +0000 (22:10 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Thu, 26 May 2005 02:10:25 +0000 (22:10 -0400)
362 files changed:
CREDITS
Documentation/cpusets.txt
Documentation/dvb/README.flexcop [new file with mode: 0644]
Documentation/dvb/bt8xx.txt
Documentation/dvb/ci.txt [new file with mode: 0644]
Documentation/dvb/get_dvb_firmware
Documentation/feature-removal-schedule.txt
Documentation/filesystems/sysfs-pci.txt
Documentation/power/devices.txt
Documentation/powerpc/hvcs.txt
Documentation/x86_64/boot-options.txt
Makefile
arch/alpha/kernel/osf_sys.c
arch/arm/mach-s3c2410/clock.c
arch/arm/mach-s3c2410/s3c2440.c
arch/arm/mm/Kconfig
arch/arm/mm/copypage-v4mc.S [deleted file]
arch/arm/mm/copypage-v4mc.c [new file with mode: 0644]
arch/arm/mm/copypage-v6.c
arch/arm/mm/flush.c
arch/arm/mm/mm-armv.c
arch/i386/kernel/cpu/amd.c
arch/i386/kernel/cpu/common.c
arch/i386/kernel/smpboot.c
arch/i386/mach-voyager/voyager_smp.c
arch/i386/mm/ioremap.c
arch/i386/pci/fixup.c
arch/ia64/ia32/ia32_ioctl.c
arch/mips/vr41xx/common/pmu.c
arch/ppc/kernel/head_44x.S
arch/ppc/kernel/setup.c
arch/ppc/lib/string.S
arch/ppc/mm/init.c
arch/ppc/syslib/ipic.c
arch/ppc/syslib/mpc83xx_devices.c
arch/ppc/syslib/mpc85xx_devices.c
arch/ppc/syslib/open_pic.c
arch/ppc64/kernel/mf.c
arch/ppc64/kernel/pmac_smp.c
arch/ppc64/kernel/prom_init.c
arch/ppc64/kernel/rtc.c
arch/ppc64/kernel/time.c
arch/sparc64/kernel/pci_iommu.c
arch/sparc64/kernel/sbus.c
arch/um/Kconfig_x86_64
arch/um/drivers/chan_kern.c
arch/um/drivers/mcast_kern.c
arch/um/drivers/mcast_user.c
arch/um/drivers/ubd_kern.c
arch/um/include/sysdep-i386/ptrace.h
arch/um/include/sysdep-x86_64/checksum.h
arch/um/include/sysdep-x86_64/ptrace.h
arch/um/kernel/Makefile
arch/um/kernel/checksum.c [deleted file]
arch/um/kernel/initrd.c [new file with mode: 0644]
arch/um/kernel/irq_user.c
arch/um/kernel/ksyms.c
arch/um/kernel/mem.c
arch/um/kernel/ptrace.c
arch/um/kernel/trap_kern.c
arch/um/kernel/tt/ksyms.c
arch/um/kernel/uml.lds.S
arch/um/sys-i386/Makefile
arch/um/sys-i386/delay.c
arch/um/sys-x86_64/Makefile
arch/um/sys-x86_64/delay.c
arch/um/sys-x86_64/ksyms.c
arch/um/sys-x86_64/ptrace.c
arch/um/sys-x86_64/syscalls.c
arch/um/sys-x86_64/user-offsets.c
arch/x86_64/Kconfig
arch/x86_64/defconfig
arch/x86_64/kernel/Makefile
arch/x86_64/kernel/apic.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/mpparse.c
arch/x86_64/kernel/nmi.c
arch/x86_64/kernel/pmtimer.c [new file with mode: 0644]
arch/x86_64/kernel/ptrace.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/signal.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/traps.c
arch/x86_64/kernel/vsyscall.c
arch/x86_64/kernel/x8664_ksyms.c
arch/x86_64/mm/fault.c
arch/x86_64/mm/ioremap.c
crypto/crypto_null.c
crypto/internal.h
drivers/base/Makefile
drivers/base/bus.c
drivers/base/core.c
drivers/base/interface.c [deleted file]
drivers/base/power/power.h
drivers/base/power/resume.c
drivers/base/power/shutdown.c
drivers/base/power/suspend.c
drivers/block/ioctl.c
drivers/block/pktcdvd.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/raw.c
drivers/char/watchdog/i8xx_tco.c
drivers/i2c/busses/i2c-keywest.c
drivers/ide/ide-cd.c
drivers/ide/ide-proc.c
drivers/ieee1394/Kconfig
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_transactions.c
drivers/ieee1394/ieee1394_transactions.h
drivers/ieee1394/nodemgr.c
drivers/ieee1394/ohci1394.c
drivers/ieee1394/ohci1394.h
drivers/ieee1394/pcilynx.c
drivers/ieee1394/pcilynx.h
drivers/ieee1394/video1394.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/include/ib_sa.h
drivers/input/keyboard/atkbd.c
drivers/input/mouse/alps.c
drivers/input/serio/serio.c
drivers/input/serio/serport.c
drivers/macintosh/therm_adt746x.c
drivers/md/linear.c
drivers/md/multipath.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid6main.c
drivers/media/common/saa7146_core.c
drivers/media/dvb/Kconfig
drivers/media/dvb/b2c2/Kconfig
drivers/media/dvb/b2c2/Makefile
drivers/media/dvb/b2c2/b2c2-common.c [deleted file]
drivers/media/dvb/b2c2/b2c2-usb-core.c [deleted file]
drivers/media/dvb/b2c2/flexcop-common.h [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-dma.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-eeprom.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-fe-tuner.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-hw-filter.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-i2c.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-misc.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-pci.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-reg.h [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-sram.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-usb.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-usb.h [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop.h [new file with mode: 0644]
drivers/media/dvb/b2c2/skystar2.c
drivers/media/dvb/bt8xx/Kconfig
drivers/media/dvb/bt8xx/Makefile
drivers/media/dvb/bt8xx/bt878.c
drivers/media/dvb/bt8xx/bt878.h
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/bt8xx/dst.h [deleted file]
drivers/media/dvb/bt8xx/dst_ca.c [new file with mode: 0644]
drivers/media/dvb/bt8xx/dst_ca.h [new file with mode: 0644]
drivers/media/dvb/bt8xx/dst_common.h [new file with mode: 0644]
drivers/media/dvb/bt8xx/dst_priv.h
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/bt8xx/dvb-bt8xx.h
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
drivers/media/dvb/dibusb/dvb-dibusb.h
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dvb_ca_en50221.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/dvb/dvb-core/dvbdev.h
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/at76c651.c
drivers/media/dvb/frontends/cx22700.c
drivers/media/dvb/frontends/cx22702.c
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/dib3000mb.c
drivers/media/dvb/frontends/dib3000mc.c
drivers/media/dvb/frontends/dvb-pll.h
drivers/media/dvb/frontends/dvb_dummy_fe.c
drivers/media/dvb/frontends/l64781.c
drivers/media/dvb/frontends/mt312.c
drivers/media/dvb/frontends/mt352.c
drivers/media/dvb/frontends/mt352.h
drivers/media/dvb/frontends/nxt2002.c
drivers/media/dvb/frontends/nxt6000.c
drivers/media/dvb/frontends/nxt6000_priv.h
drivers/media/dvb/frontends/or51132.c
drivers/media/dvb/frontends/sp8870.c
drivers/media/dvb/frontends/sp887x.c
drivers/media/dvb/frontends/stv0297.c
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/tda10021.c
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/tda1004x.h
drivers/media/dvb/frontends/tda8083.c
drivers/media/dvb/frontends/tda80xx.c
drivers/media/dvb/frontends/ves1820.c
drivers/media/dvb/frontends/ves1x93.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110.h
drivers/media/dvb/ttpci/av7110_av.c
drivers/media/dvb/ttpci/av7110_ca.c
drivers/media/dvb/ttpci/av7110_hw.c
drivers/media/dvb/ttpci/av7110_hw.h
drivers/media/dvb/ttpci/av7110_ir.c
drivers/media/dvb/ttpci/av7110_v4l.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget-core.c
drivers/media/dvb/ttpci/budget-patch.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttpci/budget.h
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/video/Kconfig
drivers/media/video/bttv-cards.c
drivers/media/video/bttv-i2c.c
drivers/media/video/saa7134/saa6752hs.c
drivers/media/video/video-buf-dvb.c
drivers/mmc/Kconfig
drivers/mmc/mmc_block.c
drivers/mmc/wbsd.c
drivers/mmc/wbsd.h
drivers/net/Makefile
drivers/net/amd8111e.c
drivers/net/e100.c
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_hw.c
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_main.c
drivers/net/e1000/e1000_osdep.h
drivers/net/e1000/e1000_param.c
drivers/net/ibm_emac/ibm_emac_core.c
drivers/net/ixgb/ixgb.h
drivers/net/ixgb/ixgb_ee.c
drivers/net/ixgb/ixgb_ethtool.c
drivers/net/ixgb/ixgb_main.c
drivers/net/ixgb/ixgb_osdep.h
drivers/net/pcnet32.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tulip/media.c
drivers/net/tulip/tulip_core.c
drivers/net/wireless/Kconfig
drivers/net/wireless/airo.c
drivers/net/wireless/atmel_cs.c
drivers/pci/hotplug.c
drivers/pci/hotplug/cpci_hotplug.h
drivers/pci/hotplug/cpci_hotplug_core.c
drivers/pci/hotplug/cpci_hotplug_pci.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.h
drivers/pci/pcie/portdrv_bus.c
drivers/pcmcia/ds.c
drivers/s390/block/dasd.c
drivers/sbus/char/aurora.c
drivers/scsi/aic7xxx/aic7770_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
drivers/scsi/aic7xxx/aic7xxx_proc.c
drivers/scsi/aic7xxx/aiclib.c
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
drivers/scsi/sata_svw.c
drivers/scsi/scsi_transport_spi.c
drivers/serial/21285.c
drivers/serial/8250.c
drivers/serial/amba-pl010.c
drivers/serial/amba-pl011.c
drivers/serial/clps711x.c
drivers/serial/pxa.c
drivers/serial/s3c2410.c
drivers/serial/sa1100.c
drivers/serial/serial_cs.c
drivers/serial/serial_lh7a40x.c
drivers/serial/serial_txx9.c
drivers/serial/sunsab.c
drivers/serial/sunsab.h
drivers/serial/vr41xx_siu.c
drivers/usb/atm/speedtch.c
drivers/usb/core/sysfs.c
drivers/usb/host/ehci-hub.c
drivers/usb/net/Kconfig
drivers/usb/net/usbnet.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/cypress_m8.h
fs/binfmt_elf.c
fs/buffer.c
fs/ext3/super.c
fs/namei.c
fs/proc/mmu.c
fs/reiserfs/stree.c
fs/reiserfs/super.c
include/asm-arm/arch-imx/imx-regs.h
include/asm-arm/arch-s3c2410/regs-nand.h
include/asm-arm/page.h
include/asm-ia64/ioctl32.h [deleted file]
include/asm-ppc64/iSeries/mf.h
include/asm-um/arch-signal-i386.h [deleted file]
include/asm-um/elf-i386.h
include/asm-um/elf-x86_64.h
include/asm-um/elf.h [deleted file]
include/asm-x86_64/apicdef.h
include/asm-x86_64/bug.h
include/asm-x86_64/io_apic.h
include/asm-x86_64/ioctl32.h [deleted file]
include/asm-x86_64/nmi.h
include/asm-x86_64/processor.h
include/asm-x86_64/proto.h
include/asm-x86_64/vsyscall.h
include/linux/device.h
include/linux/err.h
include/linux/if_tr.h
include/linux/libata.h
include/linux/mmc/protocol.h
include/linux/net.h
include/linux/netdevice.h
include/linux/pci_ids.h
include/linux/serial_core.h
include/linux/spinlock.h
include/linux/vmalloc.h
include/linux/wait.h
include/media/video-buf-dvb.h
include/net/act_generic.h
include/scsi/scsi_transport_spi.h
kernel/irq/handle.c
kernel/power/main.c
kernel/printk.c
kernel/profile.c
kernel/sched.c
kernel/signal.c
kernel/spinlock.c
mm/filemap.c
mm/memory.c
mm/mmap.c
mm/mremap.c
mm/nommu.c
mm/rmap.c
mm/swapfile.c
mm/vmalloc.c
net/ipv4/ip_output.c
net/ipv4/ipvs/ip_vs_xmit.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/tcp_input.c
net/ipv6/ip6_output.c
net/ipv6/xfrm6_output.c
net/netlink/af_netlink.c
net/unix/af_unix.c
net/xfrm/xfrm_algo.c
net/xfrm/xfrm_user.c
security/selinux/ss/services.c

diff --git a/CREDITS b/CREDITS
index 3b9e160d6f7efe52898700a41b923df2c5581413..9bd099d960f38b8d6ba4a61cec7f8dccf53f2c00 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -882,13 +882,12 @@ S: Blacksburg, Virginia 24061
 S: USA
 
 N: Randy Dunlap
-E: rddunlap@osdl.org
+E: rdunlap@xenotime.net
 W: http://www.xenotime.net/linux/linux.html
 W: http://www.linux-usb.org
 D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers
 D: x86 SMP, ACPI, bootflag hacking
-S: 12725 SW Millikan Way, Suite 400
-S: Beaverton, Oregon 97005
+S: (ask for current address)
 S: USA
 
 N: Bob Dunlop
index 1ad26d2c20ae61e0fabafefdee24ef5bb35b50e0..2f8f24eaefd9ac746f8a1e98b6e2c99abcc23b58 100644 (file)
@@ -252,8 +252,7 @@ in a tasks processor placement.
 There is an exception to the above.  If hotplug funtionality is used
 to remove all the CPUs that are currently assigned to a cpuset,
 then the kernel will automatically update the cpus_allowed of all
-tasks attached to CPUs in that cpuset with the online CPUs of the
-nearest parent cpuset that still has some CPUs online.  When memory
+tasks attached to CPUs in that cpuset to allow all CPUs.  When memory
 hotplug functionality for removing Memory Nodes is available, a
 similar exception is expected to apply there as well.  In general,
 the kernel prefers to violate cpuset placement, over starving a task
diff --git a/Documentation/dvb/README.flexcop b/Documentation/dvb/README.flexcop
new file mode 100644 (file)
index 0000000..a50c70f
--- /dev/null
@@ -0,0 +1,205 @@
+This README escorted the skystar2-driver rewriting procedure. It describes the
+state of the new flexcop-driver set and some internals are written down here
+too.
+
+This document hopefully describes things about the flexcop and its
+device-offsprings. Goal was to write an easy-to-write and easy-to-read set of
+drivers based on the skystar2.c and other information.
+
+Remark: flexcop-pci.c was a copy of skystar2.c, but every line has been
+touched and rewritten.
+
+History & News
+==============
+  2005-04-01 - correct USB ISOC transfers (thanks to Vadim Catana)
+
+
+
+
+General coding processing
+=========================
+
+We should proceed as follows (as long as no one complains):
+
+0) Think before start writing code!
+
+1) rewriting the skystar2.c with the help of the flexcop register descriptions
+and splitting up the files to a pci-bus-part and a flexcop-part.
+The new driver will be called b2c2-flexcop-pci.ko/b2c2-flexcop-usb.ko for the
+device-specific part and b2c2-flexcop.ko for the common flexcop-functions.
+
+2) Search for errors in the leftover of flexcop-pci.c (compare with pluto2.c
+and other pci drivers)
+
+3) make some beautification (see 'Improvements when rewriting (refactoring) is
+done')
+
+4) Testing the new driver and maybe substitute the skystar2.c with it, to reach
+a wider tester audience.
+
+5) creating an usb-bus-part using the already written flexcop code for the pci
+card.
+
+Idea: create a kernel-object for the flexcop and export all important
+functions. This option saves kernel-memory, but maybe a lot of functions have
+to be exported to kernel namespace.
+
+
+Current situation
+=================
+
+0) Done :)
+1) Done (some minor issues left)
+2) Done
+3) Not ready yet, more information is necessary
+4) next to be done (see the table below)
+5) USB driver is working (yes, there are some minor issues)
+
+What seems to be ready?
+-----------------------
+
+1) Rewriting
+1a) i2c is cut off from the flexcop-pci.c and seems to work
+1b) moved tuner and demod stuff from flexcop-pci.c to flexcop-tuner-fe.c
+1c) moved lnb and diseqc stuff from flexcop-pci.c to flexcop-tuner-fe.c
+1e) eeprom (reading MAC address)
+1d) sram (no dynamic sll size detection (commented out) (using default as JJ told me))
+1f) misc. register accesses for reading parameters (e.g. resetting, revision)
+1g) pid/mac filter (flexcop-hw-filter.c)
+1i) dvb-stuff initialization in flexcop.c (done)
+1h) dma stuff (now just using the size-irq, instead of all-together, to be done)
+1j) remove flexcop initialization from flexcop-pci.c completely (done)
+1l) use a well working dma IRQ method (done, see 'Known bugs and problems and TODO')
+1k) cleanup flexcop-files (remove unused EXPORT_SYMBOLs, make static from
+non-static where possible, moved code to proper places)
+
+2) Search for errors in the leftover of flexcop-pci.c (partially done)
+5a) add MAC address reading
+5c) feeding of ISOC data to the software demux (format of the isochronous data
+and speed optimization, no real error) (thanks to Vadim Catana)
+
+What to do in the near future?
+--------------------------------------
+(no special order here)
+
+5) USB driver
+5b) optimize isoc-transfer (submitting/killing isoc URBs when transfer is starting)
+
+Testing changes
+---------------
+
+O             = item is working
+P             = item is partially working
+X             = item is not working
+N             = item does not apply here
+<empty field> = item need to be examined
+
+       | PCI                               | USB
+item   | mt352 | nxt2002 | stv0299 | mt312 | mt352 | nxt2002 | stv0299 | mt312
+-------+-------+---------+---------+-------+-------+---------+---------+-------
+1a)    | O     |         |         |       | N     | N       | N       | N
+1b)    | O     |         |         |       |       |         | O       |
+1c)    | N     | N       |         |       | N     | N       | O       |
+1d)    |                 O                 |                 O
+1e)    |                 O                 |                 O
+1f)    |                                   P
+1g)    |                                   O
+1h)    |                 P                 |
+1i)    |                 O                 |                 N
+1j)    |                 O                 |                 N
+1l)    |                 O                 |                 N
+2)     |                 O                 |                 N
+5a)    |                 N                 |                 O
+5b)*   |                 N                 |
+5c)    |                 N                 |                 O
+
+* - not done yet
+
+Known bugs and problems and TODO
+--------------------------------
+
+1g/h/l) when pid filtering is enabled on the pci card
+
+DMA usage currently:
+  The DMA is splitted in 2 equal-sized subbuffers. The Flexcop writes to first
+  address and triggers an IRQ when it's full and starts writing to the second
+  address. When the second address is full, the IRQ is triggered again, and
+  the flexcop writes to first address again, and so on.
+  The buffersize of each address is currently 640*188 bytes.
+
+  Problem is, when using hw-pid-filtering and doing some low-bandwidth
+  operation (like scanning) the buffers won't be filled enough to trigger
+  the IRQ. That's why:
+
+  When PID filtering is activated, the timer IRQ is used. Every 1.97 ms the IRQ
+  is triggered.  Is the current write address of DMA1 different to the one
+  during the last IRQ, then the data is passed to the demuxer.
+
+  There is an additional DMA-IRQ-method: packet count IRQ. This isn't
+  implemented correctly yet.
+
+  The solution is to disable HW PID filtering, but I don't know how the DVB
+  API software demux behaves on slow systems with 45MBit/s TS.
+
+Solved bugs :)
+--------------
+1g) pid-filtering (somehow pid index 4 and 5 (EMM_PID and ECM_PID) aren't
+working)
+SOLUTION: also index 0 was affected, because net_translation is done for
+these indexes by default
+
+5b) isochronous transfer does only work in the first attempt (for the Sky2PC
+USB, Air2PC is working) SOLUTION: the flexcop was going asleep and never really
+woke up again (don't know if this need fixes, see
+flexcop-fe-tuner.c:flexcop_sleep)
+
+NEWS: when the driver is loaded and unloaded and loaded again (w/o doing
+anything in the while the driver is loaded the first time), no transfers take
+place anymore.
+
+Improvements when rewriting (refactoring) is done
+=================================================
+
+- split sleeping of the flexcop (misc_204.ACPI3_sig = 1;) from lnb_control
+  (enable sleeping for other demods than dvb-s)
+- add support for CableStar (stv0297 Microtune 203x/ALPS) (almost done, incompatibilities with the Nexus-CA)
+
+Debugging
+---------
+- add verbose debugging to skystar2.c (dump the reg_dw_data) and compare it
+  with this flexcop, this is important, because i2c is now using the
+  flexcop_ibi_value union from flexcop-reg.h (do you have a better idea for
+  that, please tell us so).
+
+Everything which is identical in the following table, can be put into a common
+flexcop-module.
+
+                  PCI                  USB
+-------------------------------------------------------------------------------
+Different:
+Register access:  accessing IO memory  USB control message
+I2C bus:          I2C bus of the FC    USB control message
+Data transfer:    DMA                  isochronous transfer
+EEPROM transfer:  through i2c bus      not clear yet
+
+Identical:
+Streaming:                 accessing registers
+PID Filtering:             accessing registers
+Sram destinations:         accessing registers
+Tuner/Demod:                     I2C bus
+DVB-stuff:            can be written for common use
+
+Acknowledgements (just for the rewriting part)
+================
+
+Bjarne Steinsbo thought a lot in the first place of the pci part for this code
+sharing idea.
+
+Andreas Oberritter for providing a recent PCI initialization template
+(pluto2.c).
+
+Boleslaw Ciesielski for pointing out a problem with firmware loader.
+
+Vadim Catana for correcting the USB transfer.
+
+comments, critics and ideas to linux-dvb@linuxtv.org.
index e3cacf4f2345e48258317bc23925e66a757a4a53..d64430bf4bb6ec5d681c2f7c30cc71905a72bd67 100644 (file)
@@ -17,74 +17,53 @@ Because of this, you need to enable
 "Device drivers" => "Multimedia devices"
   => "Video For Linux" => "BT848 Video For Linux"
 
+Furthermore you need to enable
+"Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices"
+  => "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI Cards"
+
 2) Loading Modules
 ==================
 
 In general you need to load the bttv driver, which will handle the gpio and
-i2c communication for us. Next you need the common dvb-bt8xx device driver
-and one frontend driver.
-
-The bttv driver will HANG YOUR SYSTEM IF YOU DO NOT SPECIFY THE CORRECT 
-CARD ID!
-
-(If you don't get your card running and you suspect that the card id you're
-using is wrong, have a look at "bttv-cards.c" for a list of possible card
-ids.)
-
-Pay attention to failures when you load the frontend drivers
-(e.g. dmesg, /var/log/messages).
+i2c communication for us, plus the common dvb-bt8xx device driver.
+The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110) and
+TwinHan (dst) are loaded automatically by the dvb-bt8xx device driver.
 
 3a) Nebula / Pinnacle PCTV
 --------------------------
 
-   $ modprobe bttv i2c_hw=1 card=0x68
-   $ modprobe dvb-bt8xx
-   
-For Nebula cards use the "nxt6000" frontend driver:
-   $ modprobe nxt6000
+   $ modprobe bttv (normally bttv is being loaded automatically by kmod)
+   $ modprobe dvb-bt8xx (or just place dvb-bt8xx in /etc/modules for automatic loading)
 
-For Pinnacle PCTV cards use the "cx24110" frontend driver:
-   $ modprobe cx24110
 
-3b) TwinHan
------------
+3b) TwinHan and Clones
+--------------------------
 
    $ modprobe bttv i2c_hw=1 card=0x71
    $ modprobe dvb-bt8xx
    $ modprobe dst
 
-The value 0x71 will override the PCI type detection for dvb-bt8xx, which 
-is necessary for TwinHan cards.#
+The value 0x71 will override the PCI type detection for dvb-bt8xx,
+which  is necessary for TwinHan cards.
 
-If you're having an older card (blue color circuit) and card=0x71 locks your
-machine, try using 0x68, too. If that does not work, ask on the DVB mailing list.
+If you're having an older card (blue color circuit) and card=0x71 locks
+your machine, try using 0x68, too. If that does not work, ask on the
+mailing list.
 
-The DST module takes a couple of useful parameters, in case the
-dst drivers fails to detect your type of card correctly.
+The DST module takes a couple of useful parameters.
 
-dst_type takes values 0 (satellite), 1 (terrestial TV), 2 (cable).
+verbose takes values 0 to 5. These values control the verbosity level.
 
-dst_type_flags takes bit combined values:
-1 = new tuner type packets. You can use this if your card is detected
-    and you have debug and you continually see the tuner packets not
-    working (make sure not a basic problem like dish alignment etc.)
+debug takes values 0 and 1. You can either disable or enable debugging.
 
-2 = TS 204. If your card tunes OK, but the picture is terrible, seemingly
-    breaking up in one half continually, and crc fails a lot, then
-    this is worth a try (or trying to turn off)
+dst_addons takes values 0 and 0x20. A value of 0 means it is a FTA card.
+0x20 means it has a Conditional Access slot.
 
-4 = has symdiv. Some cards, mostly without new tuner packets, require
-    a symbol division algorithm. Doesn't apply to terrestial TV.
-
-You can also specify a value to have the autodetected values turned off
-(e.g. 0). The autodected values are determined bythe cards 'response
+The autodected values are determined bythe cards 'response
 string' which you can see in your logs e.g.
 
-dst_check_ci: recognize DST-MOT
-
-or 
+dst_get_device_id: Recognise [DSTMCI]
 
-dst_check_ci: unable to recognize DSTXCI or STXCI
 
 --
-Authors: Richard Walker, Jamie Honan, Michael Hunold
+Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham
diff --git a/Documentation/dvb/ci.txt b/Documentation/dvb/ci.txt
new file mode 100644 (file)
index 0000000..62e0701
--- /dev/null
@@ -0,0 +1,219 @@
+* For the user
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+NOTE: This document describes the usage of the high level CI API as
+in accordance to the Linux DVB API. This is a not a documentation for the,
+existing low level CI API.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To utilize the High Level CI capabilities,
+
+(1*) This point is valid only for the Twinhan/clones
+  For the Twinhan/Twinhan clones, the dst_ca module handles the CI
+  hardware handling.This module is loaded automatically if a CI
+  (Common Interface, that holds the CAM (Conditional Access Module)
+  is detected.
+
+(2) one requires a userspace application, ca_zap. This small userland
+  application is in charge of sending the descrambling related information
+  to the CAM.
+
+This application requires the following to function properly as of now.
+
+       (a) Tune to a valid channel, with szap.
+         eg: $ szap -c channels.conf -r "TMC" -x
+
+       (b) a channels.conf containing a valid PMT PID
+
+         eg: TMC:11996:h:0:27500:278:512:650:321
+
+         here 278 is a valid PMT PID. the rest of the values are the
+         same ones that szap uses.
+
+       (c) after running a szap, you have to run ca_zap, for the
+         descrambler to function,
+
+         eg: $ ca_zap patched_channels.conf "TMC"
+
+         The patched means a patch to apply to scan, such that scan can
+         generate a channels.conf_with pmt, which has this PMT PID info
+         (NOTE: szap cannot use this channels.conf with the PMT_PID)
+
+
+       (d) Hopeflly Enjoy your favourite subscribed channel as you do with
+         a FTA card.
+
+(3) Currently ca_zap, and dst_test, both are meant for demonstration
+  purposes only, they can become full fledged applications if necessary.
+
+
+* Cards that fall in this category
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+At present the cards that fall in this category are the Twinhan and it's
+clones, these cards are available as VVMER, Tomato, Hercules, Orange and
+so on.
+
+* CI modules that are supported
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The CI module support is largely dependant upon the firmware on the cards
+Some cards do support almost all of the available CI modules. There is
+nothing much that can be done in order to make additional CI modules
+working with these cards.
+
+Modules that have been tested by this driver at present are
+
+(1) Irdeto 1 and 2 from SCM
+(2) Viaccess from SCM
+(3) Dragoncam
+
+* The High level CI API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* For the programmer
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+With the High Level CI approach any new card with almost any random
+architecture can be implemented with this style, the definitions
+insidethe switch statement can be easily adapted for any card, thereby
+eliminating the need for any additional ioctls.
+
+The disadvantage is that the driver/hardware has to manage the rest. For
+the application programmer it would be as simple as sending/receiving an
+array to/from the CI ioctls as defined in the Linux DVB API. No changes
+have been made in the API to accomodate this feature.
+
+
+* Why the need for another CI interface ?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This is one of the most commonly asked question. Well a nice question.
+Strictly speaking this is not a new interface.
+
+The CI interface is defined in the DVB API in ca.h as
+
+typedef struct ca_slot_info {
+       int num;               /* slot number */
+
+       int type;              /* CA interface this slot supports */
+#define CA_CI            1     /* CI high level interface */
+#define CA_CI_LINK       2     /* CI link layer level interface */
+#define CA_CI_PHYS       4     /* CI physical layer level interface */
+#define CA_DESCR         8     /* built-in descrambler */
+#define CA_SC          128     /* simple smart card interface */
+
+       unsigned int flags;
+#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */
+#define CA_CI_MODULE_READY   2
+} ca_slot_info_t;
+
+
+
+This CI interface follows the CI high level interface, which is not
+implemented by most applications. Hence this area is revisited.
+
+This CI interface is quite different in the case that it tries to
+accomodate all other CI based devices, that fall into the other categories
+
+This means that this CI interface handles the EN50221 style tags in the
+Application layer only and no session management is taken care of by the
+application. The driver/hardware will take care of all that.
+
+This interface is purely an EN50221 interface exchanging APDU's. This
+means that no session management, link layer or a transport layer do
+exist in this case in the application to driver communication. It is
+as simple as that. The driver/hardware has to take care of that.
+
+
+With this High Level CI interface, the interface can be defined with the
+regular ioctls.
+
+All these ioctls are also valid for the High level CI interface
+
+#define CA_RESET          _IO('o', 128)
+#define CA_GET_CAP        _IOR('o', 129, ca_caps_t)
+#define CA_GET_SLOT_INFO  _IOR('o', 130, ca_slot_info_t)
+#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t)
+#define CA_GET_MSG        _IOR('o', 132, ca_msg_t)
+#define CA_SEND_MSG       _IOW('o', 133, ca_msg_t)
+#define CA_SET_DESCR      _IOW('o', 134, ca_descr_t)
+#define CA_SET_PID        _IOW('o', 135, ca_pid_t)
+
+
+On querying the device, the device yields information thus
+
+CA_GET_SLOT_INFO
+----------------------------
+Command = [info]
+APP: Number=[1]
+APP: Type=[1]
+APP: flags=[1]
+APP: CI High level interface
+APP: CA/CI Module Present
+
+CA_GET_CAP
+----------------------------
+Command = [caps]
+APP: Slots=[1]
+APP: Type=[1]
+APP: Descrambler keys=[16]
+APP: Type=[1]
+
+CA_SEND_MSG
+----------------------------
+Descriptors(Program Level)=[ 09 06 06 04 05 50 ff f1]
+Found CA descriptor @ program level
+
+(20) ES type=[2] ES pid=[201]  ES length =[0 (0x0)]
+(25) ES type=[4] ES pid=[301]  ES length =[0 (0x0)]
+ca_message length is 25 (0x19) bytes
+EN50221 CA MSG=[ 9f 80 32 19 03 01 2d d1 f0 08 01 09 06 06 04 05 50 ff f1 02 e0 c9 00 00 04 e1 2d 00 00]
+
+
+Not all ioctl's are implemented in the driver from the API, the other
+features of the hardware that cannot be implemented by the API are achieved
+using the CA_GET_MSG and CA_SEND_MSG ioctls. An EN50221 style wrapper is
+used to exchange the data to maintain compatibility with other hardware.
+
+
+/* a message to/from a CI-CAM */
+typedef struct ca_msg {
+       unsigned int index;
+       unsigned int type;
+       unsigned int length;
+       unsigned char msg[256];
+} ca_msg_t;
+
+
+The flow of data can be described thus,
+
+
+
+
+
+       App (User)
+       -----
+       parse
+         |
+         |
+         v
+       en50221 APDU (package)
+   --------------------------------------
+   |     |                             | High Level CI driver
+   |     |                             |
+   |     v                             |
+   |   en50221 APDU (unpackage)        |
+   |     |                             |
+   |     |                             |
+   |     v                             |
+   |   sanity checks                   |
+   |     |                             |
+   |     |                             |
+   |     v                             |
+   |   do (H/W dep)                    |
+   --------------------------------------
+         |    Hardware
+         |
+         v
+
+
+
+
+The High Level CI interface uses the EN50221 DVB standard, following a
+standard ensures futureproofness.
index 3ffdcb394299f43b65f50c7df3898281504fd32c..a750f0101d9de7d15f47a13e0cc7240b3299ba1f 100644 (file)
@@ -107,7 +107,7 @@ sub tda10045 {
 sub tda10046 {
     my $sourcefile = "tt_budget_217g.zip";
     my $url = "http://www.technotrend.de/new/217g/$sourcefile";
-    my $hash = "a25b579e37109af60f4a36c37893957c";
+    my $hash = "6a7e1e2f2644b162ff0502367553c72d";
     my $outfile = "dvb-fe-tda10046.fw";
     my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
 
@@ -115,7 +115,7 @@ sub tda10046 {
 
     wgetfile($sourcefile, $url);
     unzip($sourcefile, $tmpdir);
-    extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24479, "$tmpdir/fwtmp");
+    extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24478, "$tmpdir/fwtmp");
     verify("$tmpdir/fwtmp", $hash);
     copy("$tmpdir/fwtmp", $outfile);
 
index d3c52dd24a2ae6f5a39d35d788c8831aa52f4b9c..b9eb209318ab7d737ba7e6be2a0587ce9e8a9d25 100644 (file)
@@ -63,3 +63,23 @@ Why: Outside of Linux, the only implementations of anything even
        people, who might be using implementations that I am not aware
        of, to adjust to this upcoming change.
 Who:   Paul E. McKenney <paulmck@us.ibm.com>
+
+---------------------------
+
+What:  IEEE1394 Audio and Music Data Transmission Protocol driver,
+       Connection Management Procedures driver
+When:  November 2005
+Files: drivers/ieee1394/{amdtp,cmp}*
+Why:   These are incomplete, have never worked, and are better implemented
+       in userland via raw1394 (see http://freebob.sourceforge.net/ for
+       example.)
+Who:   Jody McIntyre <scjody@steamballoon.com>
+
+---------------------------
+
+What:  raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
+When:  November 2005
+Why:   Deprecated in favour of the new ioctl-based rawiso interface, which is
+       more efficient.  You should really be using libraw1394 for raw1394
+       access anyway.
+Who:   Jody McIntyre <scjody@steamballoon.com>
index e97d024eae77e5fa9f1ac338074a24baf42680e5..988a62fae11f883b8b2ba14ba95d83490a3fc5a1 100644 (file)
@@ -7,7 +7,6 @@ that support it.  For example, a given bus might look like this:
      |-- 0000:17:00.0
      |   |-- class
      |   |-- config
-     |   |-- detach_state
      |   |-- device
      |   |-- irq
      |   |-- local_cpus
@@ -19,7 +18,7 @@ that support it.  For example, a given bus might look like this:
      |   |-- subsystem_device
      |   |-- subsystem_vendor
      |   `-- vendor
-     `-- detach_state
+     `-- ...
 
 The topmost element describes the PCI domain and bus number.  In this case,
 the domain number is 0000 and the bus number is 17 (both values are in hex).
@@ -31,7 +30,6 @@ files, each with their own function.
        ----               --------
        class              PCI class (ascii, ro)
        config             PCI config space (binary, rw)
-       detach_state       connection status (bool, rw)
        device             PCI device (ascii, ro)
        irq                IRQ number (ascii, ro)
        local_cpus         nearby CPU mask (cpumask, ro)
@@ -85,4 +83,4 @@ useful return codes should be provided.
 
 Legacy resources are protected by the HAVE_PCI_LEGACY define.  Platforms
 wishing to support legacy functionality should define it and provide
-pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
\ No newline at end of file
+pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
index 5d4ae9a39f1d5df7ffa644d39d0235a71b22c125..f987afe43e28e1327ee76ab4f3fdb617abfe0829 100644 (file)
@@ -207,27 +207,6 @@ SYSTEM_SHUTDOWN, I do not understand this one too much. probably event
 #READY_AFTER_RESUME
 #
 
-Driver Detach Power Management
-
-The kernel now supports the ability to place a device in a low-power
-state when it is detached from its driver, which happens when its
-module is removed. 
-
-Each device contains a 'detach_state' file in its sysfs directory
-which can be used to control this state. Reading from this file
-displays what the current detach state is set to. This is 0 (On) by
-default. A user may write a positive integer value to this file in the
-range of 1-4 inclusive. 
-
-A value of 1-3 will indicate the device should be placed in that
-low-power state, which will cause ->suspend() to be called for that
-device. A value of 4 indicates that the device should be shutdown, so
-->shutdown() will be called for that device. 
-
-The driver is responsible for reinitializing the device when the
-module is re-inserted during it's ->probe() (or equivalent) method. 
-The driver core will not call any extra functions when binding the
-device to the driver. 
 
 pm_message_t meaning
 
index c0a62e116e6e969e2e6e6cbe7b354a1e16a42fdc..dca75cbda6f8abc144afb9efcdea77b7b5f21eac 100644 (file)
@@ -347,8 +347,8 @@ address that is created by firmware.  An example vty-server sysfs entry
 looks like the following:
 
        Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
-       .   current_vty   devspec  name          partner_vtys
-       ..  detach_state  index    partner_clcs  vterm_state
+       .   current_vty   devspec       name          partner_vtys
+       ..  index         partner_clcs  vterm_state
 
 Each entry is provided, by default with a "name" attribute.  Reading the
 "name" attribute will reveal the device type as shown in the following
index 44b6eea60ecec18a090a426a3c5cbef7920b5e82..b9e6be00cadfbc1f2e767076c467ccb6f6ad28e6 100644 (file)
@@ -25,6 +25,9 @@ APICs
 
    noapictimer  Don't set up the APIC timer
 
+   no_timer_check Don't check the IO-APIC timer. This can work around
+                problems with incorrect timer initialization on some boards.
+
 Early Console
 
    syntax: earlyprintk=vga
index bddcb861b49bbb90bc5646a7da5c55833f4689b5..c11a317ea910df5c8456de992ae8f932a102b12b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 12
-EXTRAVERSION =-rc4
+EXTRAVERSION =-rc5
 NAME=Woozy Numbat
 
 # *DOCUMENTATION*
@@ -530,7 +530,7 @@ endif
 include $(srctree)/arch/$(ARCH)/Makefile
 
 # arch Makefile may override CC so keep this after arch Makefile is included
-NOSTDINC_FLAGS := -nostdinc -isystem $(shell $(CC) -print-file-name=include)
+NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 CHECKFLAGS     += $(NOSTDINC_FLAGS)
 
 # warn about C99 declaration after statement
index 64e450dddb49d55c3ddea43bb35371958f52369a..167fd89f8707aeb1b0ad59190e9fa352718d5900 100644 (file)
@@ -1150,16 +1150,13 @@ osf_usleep_thread(struct timeval32 __user *sleep, struct timeval32 __user *remai
        if (get_tv32(&tmp, sleep))
                goto fault;
 
-       ticks = tmp.tv_usec;
-       ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
-       ticks += tmp.tv_sec * HZ;
+       ticks = timeval_to_jiffies(&tmp);
 
        current->state = TASK_INTERRUPTIBLE;
        ticks = schedule_timeout(ticks);
 
        if (remain) {
-               tmp.tv_sec = ticks / HZ;
-               tmp.tv_usec = ticks % HZ;
+               jiffies_to_timeval(ticks, &tmp);
                if (put_tv32(remain, &tmp))
                        goto fault;
        }
index e23f534d4e1d1696ff7343ad29f1ecad893f9cc1..8d986b8401c2474f3948bb3a4301c26a9784b7f1 100644 (file)
@@ -478,7 +478,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
 {
        unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
 
-       s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate) * 2;
+       s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate);
 
        printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
               print_mhz(s3c2440_clk_upll.rate));
index 9a8cc5ae225566e5d6d17de94df3fe79dbfe9a2c..d4c8281b55f64a5c3a7a4f2d4fef2c6433215d25 100644 (file)
@@ -192,9 +192,11 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
 
        iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc));
        iotable_init(mach_desc, size);
+
        /* rename any peripherals used differing from the s3c2410 */
 
-       s3c_device_i2c.name = "s3c2440-i2c";
+       s3c_device_i2c.name  = "s3c2440-i2c";
+       s3c_device_nand.name = "s3c2440-nand";
 
        /* change irq for watchdog */
 
@@ -225,7 +227,7 @@ void __init s3c2440_init_clocks(int xtal)
                break;
 
        case S3C2440_CLKDIVN_HDIVN_2:
-               hdiv = 1;
+               hdiv = 2;
                break;
 
        case S3C2440_CLKDIVN_HDIVN_4_8:
index c4fc6be629deeee971c6635b5130d7e329970a63..48bac7da8c70589dba5f06be40b325457398c640 100644 (file)
@@ -412,21 +412,20 @@ config CPU_BPREDICT_DISABLE
 
 config TLS_REG_EMUL
        bool
-       default y if (SMP || CPU_32v6) && (CPU_32v5 || CPU_32v4 || CPU_32v3)
+       default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
        help
-         We might be running on an ARMv6+ processor which should have the TLS
-         register but for some reason we can't use it, or maybe an SMP system
-         using a pre-ARMv6 processor (there are apparently a few prototypes
-         like that in existence) and therefore access to that register must
-         be emulated.
+         An SMP system using a pre-ARMv6 processor (there are apparently
+         a few prototypes like that in existence) and therefore access to
+         that required register must be emulated.
 
 config HAS_TLS_REG
        bool
-       depends on CPU_32v6
-       default y if !TLS_REG_EMUL
+       depends on !TLS_REG_EMUL
+       default y if SMP || CPU_32v7
        help
          This selects support for the CP15 thread register.
-         It is defined to be available on ARMv6 or later.  If a particular
-         ARMv6 or later CPU doesn't support it then it must omc;ide "select
-         TLS_REG_EMUL" along with its other caracteristics.
+         It is defined to be available on some ARMv6 processors (including
+         all SMP capable ARMv6's) or later processors.  User space may
+         assume directly accessing that register and always obtain the
+         expected value only on ARMv7 and above.
 
diff --git a/arch/arm/mm/copypage-v4mc.S b/arch/arm/mm/copypage-v4mc.S
deleted file mode 100644 (file)
index 305af3d..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *  linux/arch/arm/lib/copy_page-armv4mc.S
- *
- *  Copyright (C) 1995-2001 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  ASM optimised string functions
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/constants.h>
-
-       .text
-       .align  5
-/*
- * ARMv4 mini-dcache optimised copy_user_page
- *
- * We flush the destination cache lines just before we write the data into the
- * corresponding address.  Since the Dcache is read-allocate, this removes the
- * Dcache aliasing issue.  The writes will be forwarded to the write buffer,
- * and merged as appropriate.
- *
- * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
- * instruction.  If your processor does not supply this, you have to write your
- * own copy_user_page that does the right thing.
- */
-ENTRY(v4_mc_copy_user_page)
-       stmfd   sp!, {r4, lr}                   @ 2
-       mov     r4, r0
-       mov     r0, r1
-       bl      map_page_minicache
-       mov     r1, #PAGE_SZ/64                 @ 1
-       ldmia   r0!, {r2, r3, ip, lr}           @ 4
-1:     mcr     p15, 0, r4, c7, c6, 1           @ 1   invalidate D line
-       stmia   r4!, {r2, r3, ip, lr}           @ 4
-       ldmia   r0!, {r2, r3, ip, lr}           @ 4+1
-       stmia   r4!, {r2, r3, ip, lr}           @ 4
-       ldmia   r0!, {r2, r3, ip, lr}           @ 4
-       mcr     p15, 0, r4, c7, c6, 1           @ 1   invalidate D line
-       stmia   r4!, {r2, r3, ip, lr}           @ 4
-       ldmia   r0!, {r2, r3, ip, lr}           @ 4
-       subs    r1, r1, #1                      @ 1
-       stmia   r4!, {r2, r3, ip, lr}           @ 4
-       ldmneia r0!, {r2, r3, ip, lr}           @ 4
-       bne     1b                              @ 1
-       ldmfd   sp!, {r4, pc}                   @ 3
-
-       .align  5
-/*
- * ARMv4 optimised clear_user_page
- *
- * Same story as above.
- */
-ENTRY(v4_mc_clear_user_page)
-       str     lr, [sp, #-4]!
-       mov     r1, #PAGE_SZ/64                 @ 1
-       mov     r2, #0                          @ 1
-       mov     r3, #0                          @ 1
-       mov     ip, #0                          @ 1
-       mov     lr, #0                          @ 1
-1:     mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
-       stmia   r0!, {r2, r3, ip, lr}           @ 4
-       stmia   r0!, {r2, r3, ip, lr}           @ 4
-       mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
-       stmia   r0!, {r2, r3, ip, lr}           @ 4
-       stmia   r0!, {r2, r3, ip, lr}           @ 4
-       subs    r1, r1, #1                      @ 1
-       bne     1b                              @ 1
-       ldr     pc, [sp], #4
-
-       __INITDATA
-
-       .type   v4_mc_user_fns, #object
-ENTRY(v4_mc_user_fns)
-       .long   v4_mc_clear_user_page
-       .long   v4_mc_copy_user_page
-       .size   v4_mc_user_fns, . - v4_mc_user_fns
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
new file mode 100644 (file)
index 0000000..fc69dcc
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *  linux/arch/arm/lib/copypage-armv4mc.S
+ *
+ *  Copyright (C) 1995-2005 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This handles the mini data cache, as found on SA11x0 and XScale
+ * processors.  When we copy a user page page, we map it in such a way
+ * that accesses to this page will not touch the main data cache, but
+ * will be cached in the mini data cache.  This prevents us thrashing
+ * the main data cache on page faults.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+/*
+ * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
+ * specific hacks for copying pages efficiently.
+ */
+#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
+                                 L_PTE_CACHEABLE)
+
+#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
+
+static DEFINE_SPINLOCK(minicache_lock);
+
+/*
+ * ARMv4 mini-dcache optimised copy_user_page
+ *
+ * We flush the destination cache lines just before we write the data into the
+ * corresponding address.  Since the Dcache is read-allocate, this removes the
+ * Dcache aliasing issue.  The writes will be forwarded to the write buffer,
+ * and merged as appropriate.
+ *
+ * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
+ * instruction.  If your processor does not supply this, you have to write your
+ * own copy_user_page that does the right thing.
+ */
+static void __attribute__((naked))
+mc_copy_user_page(void *from, void *to)
+{
+       asm volatile(
+       "stmfd  sp!, {r4, lr}                   @ 2\n\
+       mov     r4, %2                          @ 1\n\
+       ldmia   %0!, {r2, r3, ip, lr}           @ 4\n\
+1:     mcr     p15, 0, %1, c7, c6, 1           @ 1   invalidate D line\n\
+       stmia   %1!, {r2, r3, ip, lr}           @ 4\n\
+       ldmia   %0!, {r2, r3, ip, lr}           @ 4+1\n\
+       stmia   %1!, {r2, r3, ip, lr}           @ 4\n\
+       ldmia   %0!, {r2, r3, ip, lr}           @ 4\n\
+       mcr     p15, 0, %1, c7, c6, 1           @ 1   invalidate D line\n\
+       stmia   %1!, {r2, r3, ip, lr}           @ 4\n\
+       ldmia   %0!, {r2, r3, ip, lr}           @ 4\n\
+       subs    r4, r4, #1                      @ 1\n\
+       stmia   %1!, {r2, r3, ip, lr}           @ 4\n\
+       ldmneia %0!, {r2, r3, ip, lr}           @ 4\n\
+       bne     1b                              @ 1\n\
+       ldmfd   sp!, {r4, pc}                   @ 3"
+       :
+       : "r" (from), "r" (to), "I" (PAGE_SIZE / 64));
+}
+
+void v4_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
+{
+       spin_lock(&minicache_lock);
+
+       set_pte(TOP_PTE(0xffff8000), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot));
+       flush_tlb_kernel_page(0xffff8000);
+
+       mc_copy_user_page((void *)0xffff8000, kto);
+
+       spin_unlock(&minicache_lock);
+}
+
+/*
+ * ARMv4 optimised clear_user_page
+ */
+void __attribute__((naked))
+v4_mc_clear_user_page(void *kaddr, unsigned long vaddr)
+{
+       asm volatile(
+       "str    lr, [sp, #-4]!\n\
+       mov     r1, %0                          @ 1\n\
+       mov     r2, #0                          @ 1\n\
+       mov     r3, #0                          @ 1\n\
+       mov     ip, #0                          @ 1\n\
+       mov     lr, #0                          @ 1\n\
+1:     mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line\n\
+       stmia   r0!, {r2, r3, ip, lr}           @ 4\n\
+       stmia   r0!, {r2, r3, ip, lr}           @ 4\n\
+       mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line\n\
+       stmia   r0!, {r2, r3, ip, lr}           @ 4\n\
+       stmia   r0!, {r2, r3, ip, lr}           @ 4\n\
+       subs    r1, r1, #1                      @ 1\n\
+       bne     1b                              @ 1\n\
+       ldr     pc, [sp], #4"
+       :
+       : "I" (PAGE_SIZE / 64));
+}
+
+struct cpu_user_fns v4_mc_user_fns __initdata = {
+       .cpu_clear_user_page    = v4_mc_clear_user_page, 
+       .cpu_copy_user_page     = v4_mc_copy_user_page,
+};
index 694ac8208858a9c54475f8f3173b71cca7787d4e..a8c00236bd3d54283da26f1fe36d3a0cc3d6c636 100644 (file)
@@ -26,8 +26,8 @@
 #define to_address     (0xffffc000)
 #define to_pgprot      PAGE_KERNEL
 
-static pte_t *from_pte;
-static pte_t *to_pte;
+#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
+
 static DEFINE_SPINLOCK(v6_lock);
 
 #define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
@@ -74,8 +74,8 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd
         */
        spin_lock(&v6_lock);
 
-       set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
-       set_pte(to_pte + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot));
+       set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
+       set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot));
 
        from = from_address + (offset << PAGE_SHIFT);
        to   = to_address + (offset << PAGE_SHIFT);
@@ -114,7 +114,7 @@ void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
         */
        spin_lock(&v6_lock);
 
-       set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
+       set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
        flush_tlb_kernel_page(to);
        clear_page((void *)to);
 
@@ -129,21 +129,6 @@ struct cpu_user_fns v6_user_fns __initdata = {
 static int __init v6_userpage_init(void)
 {
        if (cache_is_vipt_aliasing()) {
-               pgd_t *pgd;
-               pmd_t *pmd;
-
-               pgd = pgd_offset_k(from_address);
-               pmd = pmd_alloc(&init_mm, pgd, from_address);
-               if (!pmd)
-                       BUG();
-               from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
-               if (!from_pte)
-                       BUG();
-
-               to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
-               if (!to_pte)
-                       BUG();
-
                cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing;
                cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing;
        }
@@ -151,5 +136,4 @@ static int __init v6_userpage_init(void)
        return 0;
 }
 
-__initcall(v6_userpage_init);
-
+core_initcall(v6_userpage_init);
index c6de48d895032de8d615ee0f1ae8d8b31e13a716..4085ed983e46e07c3ac62ba31f8b0e605ee2594c 100644 (file)
 
 #include <asm/cacheflush.h>
 #include <asm/system.h>
+#include <asm/tlbflush.h>
+
+#ifdef CONFIG_CPU_CACHE_VIPT
+#define ALIAS_FLUSH_START      0xffff4000
+
+#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
+
+static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
+{
+       unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
+
+       set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL));
+       flush_tlb_kernel_page(to);
+
+       asm(    "mcrr   p15, 0, %1, %0, c14\n"
+       "       mcrr    p15, 0, %1, %0, c5\n"
+           :
+           : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES)
+           : "cc");
+}
+#else
+#define flush_pfn_alias(pfn,vaddr)     do { } while (0)
+#endif
 
 static void __flush_dcache_page(struct address_space *mapping, struct page *page)
 {
@@ -36,6 +59,18 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
        if (!mapping)
                return;
 
+       /*
+        * This is a page cache page.  If we have a VIPT cache, we
+        * only need to do one flush - which would be at the relevant
+        * userspace colour, which is congruent with page->index.
+        */
+       if (cache_is_vipt()) {
+               if (cache_is_vipt_aliasing())
+                       flush_pfn_alias(page_to_pfn(page),
+                                       page->index << PAGE_CACHE_SHIFT);
+               return;
+       }
+
        /*
         * There are possible user space mappings of this page:
         * - VIVT cache: we need to also write back and invalidate all user
@@ -57,8 +92,6 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
                        continue;
                offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
                flush_cache_page(mpnt, mpnt->vm_start + offset, page_to_pfn(page));
-               if (cache_is_vipt())
-                       break;
        }
        flush_dcache_mmap_unlock(mapping);
 }
index 585dfb8e20b96a7526b519d85afe8dc67226c562..2c2b93d77d433248dba64b6a1dd525eae51277fc 100644 (file)
@@ -37,6 +37,8 @@ pgprot_t pgprot_kernel;
 
 EXPORT_SYMBOL(pgprot_kernel);
 
+pmd_t *top_pmd;
+
 struct cachepolicy {
        const char      policy[16];
        unsigned int    cr_mask;
@@ -142,6 +144,16 @@ __setup("noalign", noalign_setup);
 
 #define FIRST_KERNEL_PGD_NR    (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
 
+static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
+{
+       return pmd_offset(pgd, virt);
+}
+
+static inline pmd_t *pmd_off_k(unsigned long virt)
+{
+       return pmd_off(pgd_offset_k(virt), virt);
+}
+
 /*
  * need to get a 16k page for level 1
  */
@@ -220,7 +232,7 @@ void free_pgd_slow(pgd_t *pgd)
                return;
 
        /* pgd is always present and good */
-       pmd = (pmd_t *)pgd;
+       pmd = pmd_off(pgd, 0);
        if (pmd_none(*pmd))
                goto free;
        if (pmd_bad(*pmd)) {
@@ -246,9 +258,8 @@ free:
 static inline void
 alloc_init_section(unsigned long virt, unsigned long phys, int prot)
 {
-       pmd_t *pmdp;
+       pmd_t *pmdp = pmd_off_k(virt);
 
-       pmdp = pmd_offset(pgd_offset_k(virt), virt);
        if (virt & (1 << 20))
                pmdp++;
 
@@ -283,11 +294,9 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
 static inline void
 alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
 {
-       pmd_t *pmdp;
+       pmd_t *pmdp = pmd_off_k(virt);
        pte_t *ptep;
 
-       pmdp = pmd_offset(pgd_offset_k(virt), virt);
-
        if (pmd_none(*pmdp)) {
                unsigned long pmdval;
                ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
@@ -310,7 +319,7 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
  */
 static inline void clear_mapping(unsigned long virt)
 {
-       pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
+       pmd_clear(pmd_off_k(virt));
 }
 
 struct mem_types {
@@ -578,7 +587,7 @@ void setup_mm_for_reboot(char mode)
                         PMD_TYPE_SECT;
                if (cpu_arch <= CPU_ARCH_ARMv5)
                        pmdval |= PMD_BIT4;
-               pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
+               pmd = pmd_off(pgd, i << PGDIR_SHIFT);
                pmd[0] = __pmd(pmdval);
                pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
                flush_pmd_entry(pmd);
@@ -675,6 +684,8 @@ void __init memtable_init(struct meminfo *mi)
 
        flush_cache_all();
        flush_tlb_all();
+
+       top_pmd = pmd_off_k(0xffff0000);
 }
 
 /*
index 16dbc4151be43b8e671869b2a52220f47ec0b6ac..73aeaf5a9d4e493f7e2be65ac67a285d966e062c 100644 (file)
@@ -24,9 +24,6 @@ __asm__(".align 4\nvide: ret");
 
 static void __init init_amd(struct cpuinfo_x86 *c)
 {
-#ifdef CONFIG_X86_SMP
-       int cpu = c == &boot_cpu_data ? 0 : c - cpu_data;
-#endif
        u32 l, h;
        int mbytes = num_physpages >> (20-PAGE_SHIFT);
        int r;
@@ -198,14 +195,19 @@ static void __init init_amd(struct cpuinfo_x86 *c)
                        c->x86_num_cores = 1;
        }
 
-#ifdef CONFIG_X86_SMP
+#ifdef CONFIG_X86_HT
        /*
         * On a AMD dual core setup the lower bits of the APIC id
         * distingush the cores.  Assumes number of cores is a power
         * of two.
         */
        if (c->x86_num_cores > 1) {
-               cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
+               int cpu = smp_processor_id();
+               unsigned bits = 0;
+               while ((1 << bits) < c->x86_num_cores)
+                       bits++;
+               cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
+               phys_proc_id[cpu] >>= bits;
                printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
                       cpu, c->x86_num_cores, cpu_core_id[cpu]);
        }
index 6be0310e3cd3a15fc70bcf4782228cf73d7e161a..d199e525680aeabb7e6d5fc88ce895a217d92a1e 100644 (file)
@@ -243,6 +243,10 @@ static void __init early_cpu_detect(void)
        }
 
        early_intel_workaround(c);
+
+#ifdef CONFIG_X86_HT
+       phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+#endif
 }
 
 void __init generic_identify(struct cpuinfo_x86 * c)
index cbea7ac582e57a09fe919e4cc444c53a6a525ba4..35bfe138cb1a408a165c08de7c456a546118cf94 100644 (file)
@@ -888,6 +888,7 @@ void *xquad_portio;
 
 cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
 cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_core_map);
 
 static void __init smp_boot_cpus(unsigned int max_cpus)
 {
index 903d739ca74ae1543c0e6ddb79c4a3518b86ec91..a6e0ddd65bd0df08dbe59cd23c7f2592d1307dc2 100644 (file)
@@ -97,7 +97,6 @@ static void ack_vic_irq(unsigned int irq);
 static void vic_enable_cpi(void);
 static void do_boot_cpu(__u8 cpuid);
 static void do_quad_bootstrap(void);
-static inline void wrapper_smp_local_timer_interrupt(struct pt_regs *);
 
 int hard_smp_processor_id(void);
 
@@ -125,6 +124,14 @@ send_QIC_CPI(__u32 cpuset, __u8 cpi)
        }
 }
 
+static inline void
+wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
+{
+       irq_enter();
+       smp_local_timer_interrupt(regs);
+       irq_exit();
+}
+
 static inline void
 send_one_CPI(__u8 cpu, __u8 cpi)
 {
@@ -1249,14 +1256,6 @@ smp_vic_timer_interrupt(struct pt_regs *regs)
        smp_local_timer_interrupt(regs);
 }
 
-static inline void
-wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
-{
-       irq_enter();
-       smp_local_timer_interrupt(regs);
-       irq_exit();
-}
-
 /* local (per CPU) timer interrupt.  It does both profiling and
  * process statistics/rescheduling.
  *
index db06f7399913f7da8a3b42d110f0dc24b41272cb..ab542792b27bbab0aa9be9fdf29d865b00e319e5 100644 (file)
@@ -238,19 +238,21 @@ void iounmap(volatile void __iomem *addr)
                        addr < phys_to_virt(ISA_END_ADDRESS))
                return;
 
-       p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
+       write_lock(&vmlist_lock);
+       p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
        if (!p) { 
-               printk("__iounmap: bad address %p\n", addr);
-               return;
+               printk("iounmap: bad address %p\n", addr);
+               goto out_unlock;
        }
 
        if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
-               /* p->size includes the guard page, but cpa doesn't like that */
                change_page_attr(virt_to_page(__va(p->phys_addr)),
                                 p->size >> PAGE_SHIFT,
                                 PAGE_KERNEL);
                global_flush_tlb();
        } 
+out_unlock:
+       write_unlock(&vmlist_lock);
        kfree(p); 
 }
 
index be52c5ac4e054692478d845505b654adf5d869b6..8e8e895e1b5a62749a1a1bf233fdf25dfaf782da 100644 (file)
@@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci
 #define MAX_PCIEROOT   6
 static int quirk_aspm_offset[MAX_PCIEROOT << 3];
 
-#define GET_INDEX(a, b) (((a - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + b)
+#define GET_INDEX(a, b) ((((a) - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + ((b) & 7))
 
 static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
 {
index 9845dabe2613ae91bf456607b59d48400fe5689d..164b211f417474db5e566c4bab14024b10a3077c 100644 (file)
@@ -13,7 +13,6 @@
   
 #define        INCLUDES
 #include "compat_ioctl.c"
-#include <asm/ioctl32.h>
 
 #define IOCTL_NR(a)    ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
 
index c5f1043de9384c2f495705d0ff9c43fd670b8066..53166f3598b25fdd82cde85c1963fefa0e22c742 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  pmu.c, Power Management Unit routines for NEC VR4100 series.
  *
- *  Copyright (C) 2003-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  *  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
@@ -17,7 +17,9 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/types.h>
 #include <asm/reboot.h>
 #include <asm/system.h>
 
-#define PMUCNT2REG     KSEG1ADDR(0x0f0000c6)
+#define PMU_TYPE1_BASE 0x0b0000a0UL
+#define PMU_TYPE1_SIZE 0x0eUL
+
+#define PMU_TYPE2_BASE 0x0f0000c0UL
+#define PMU_TYPE2_SIZE 0x10UL
+
+#define PMUCNT2REG     0x06
  #define SOFTRST       0x0010
 
+static void __iomem *pmu_base;
+
+#define pmu_read(offset)               readw(pmu_base + (offset))
+#define pmu_write(offset, value)       writew((value), pmu_base + (offset))
+
 static inline void software_reset(void)
 {
-       uint16_t val;
+       uint16_t pmucnt2;
 
        switch (current_cpu_data.cputype) {
        case CPU_VR4122:
        case CPU_VR4131:
        case CPU_VR4133:
-               val = readw(PMUCNT2REG);
-               val |= SOFTRST;
-               writew(val, PMUCNT2REG);
+               pmucnt2 = pmu_read(PMUCNT2REG);
+               pmucnt2 |= SOFTRST;
+               pmu_write(PMUCNT2REG, pmucnt2);
                break;
        default:
                break;
@@ -71,6 +84,34 @@ static void vr41xx_power_off(void)
 
 static int __init vr41xx_pmu_init(void)
 {
+       unsigned long start, size;
+
+       switch (current_cpu_data.cputype) {
+       case CPU_VR4111:
+       case CPU_VR4121:
+               start = PMU_TYPE1_BASE;
+               size = PMU_TYPE1_SIZE;
+               break;
+       case CPU_VR4122:
+       case CPU_VR4131:
+       case CPU_VR4133:
+               start = PMU_TYPE2_BASE;
+               size = PMU_TYPE2_SIZE;
+               break;
+       default:
+               printk("Unexpected CPU of NEC VR4100 series\n");
+               return -ENODEV;
+       }
+
+       if (request_mem_region(start, size, "PMU") == NULL)
+               return -EBUSY;
+
+       pmu_base = ioremap(start, size);
+       if (pmu_base == NULL) {
+               release_mem_region(start, size);
+               return -EBUSY;
+       }
+
        _machine_restart = vr41xx_restart;
        _machine_halt = vr41xx_halt;
        _machine_power_off = vr41xx_power_off;
@@ -78,4 +119,4 @@ static int __init vr41xx_pmu_init(void)
        return 0;
 }
 
-early_initcall(vr41xx_pmu_init);
+core_initcall(vr41xx_pmu_init);
index 9b6a8e5136570537adca7dc8ddf244a8fac19cfd..6c7ae6052464f3d28f7cc754487e8aaa6fba1361 100644 (file)
@@ -330,8 +330,9 @@ interrupt_base:
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-       andis.  r11, r10, 0x8000
-       beq     3f
+       lis     r11, TASK_SIZE@h
+       cmplw   r10, r11
+       blt+    3f
        lis     r11, swapper_pg_dir@h
        ori     r11, r11, swapper_pg_dir@l
 
@@ -464,8 +465,9 @@ interrupt_base:
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-       andis.  r11, r10, 0x8000
-       beq     3f
+       lis     r11, TASK_SIZE@h
+       cmplw   r10, r11
+       blt+    3f
        lis     r11, swapper_pg_dir@h
        ori     r11, r11, swapper_pg_dir@l
 
@@ -533,8 +535,9 @@ interrupt_base:
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-       andis.  r11, r10, 0x8000
-       beq     3f
+       lis     r11, TASK_SIZE@h
+       cmplw   r10, r11
+       blt+    3f
        lis     r11, swapper_pg_dir@h
        ori     r11, r11, swapper_pg_dir@l
 
index 5dfb42f1a1529d561bf73b5b5c1411a3e51f6402..5c20266e3b1fd80c45f88af83d0a3b3b475d5bd4 100644 (file)
@@ -499,7 +499,7 @@ static int __init set_preferred_console(void)
 {
        struct device_node *prom_stdout;
        char *name;
-       int offset;
+       int offset = 0;
 
        if (of_stdout_device == NULL)
                return -ENODEV;
@@ -753,6 +753,8 @@ void __init setup_arch(char **cmdline_p)
        strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
        *cmdline_p = cmd_line;
 
+       parse_early_param();
+
        /* set up the bootmem stuff with available memory */
        do_init_bootmem();
        if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
index 8d08a2eb225e8608310c205033a34db857eb5ebf..36c9b97fd92abf9c6728f425e73d9d88fa0d8a84 100644 (file)
@@ -446,6 +446,7 @@ _GLOBAL(__copy_tofrom_user)
 #ifdef CONFIG_8xx
        /* Don't use prefetch on 8xx */
        mtctr   r0
+       li      r0,0
 53:    COPY_16_BYTES_WITHEX(0)
        bdnz    53b
 
@@ -564,7 +565,9 @@ _GLOBAL(__copy_tofrom_user)
 /* or write fault in cacheline loop */
 105:   li      r9,1
 92:    li      r3,LG_CACHELINE_BYTES
-       b       99f
+       mfctr   r8
+       add     r0,r0,r8
+       b       106f
 /* read fault in final word loop */
 108:   li      r9,0
        b       93f
@@ -585,7 +588,7 @@ _GLOBAL(__copy_tofrom_user)
  * r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
  */
 99:    mfctr   r0
-       slw     r3,r0,r3
+106:   slw     r3,r0,r3
        add.    r3,r3,r5
        beq     120f                    /* shouldn't happen */
        cmpwi   0,r9,0
index be02a7fec2b73ceb42675c54e747eafea7ac55c2..363c157e3617e8f375b0bbae6f31fd499f59cbff 100644 (file)
@@ -179,6 +179,7 @@ void free_initmem(void)
        if (!have_of)
                FREESEC(openfirmware);
        printk("\n");
+       ppc_md.progress = NULL;
 #undef FREESEC
 }
 
index acb2cde3171f8d141b7f38f95e9def9a62210851..580ed658e87253b51873b624ed5b8f0d228f1ba5 100644 (file)
@@ -479,7 +479,7 @@ void __init ipic_init(phys_addr_t phys_addr,
        temp = 0;
        for (i = 0 ; i < senses_count ; i++) {
                if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
-                       temp |= 1 << (16 - i);
+                       temp |= 1 << (15 - i);
                        if (i != 0)
                                irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
                        else
index 5c1a919eaabfb367a57e0ec714ceebf129aaa0ff..75c8e9834ae70ad142f2aa8e65e025065a4816de 100644 (file)
@@ -61,6 +61,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
                .iotype         = UPIO_MEM,
                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
        },
+       { },
 };
 
 struct platform_device ppc_sys_platform_devices[] = {
index a231795ee26f0a37cc228d51a76a27c314240481..1e658ef57e75d7853ae59b557a5f054ca5a58467 100644 (file)
@@ -61,6 +61,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
                .iotype         = UPIO_MEM,
                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ,
        },
+       { },
 };
 
 struct platform_device ppc_sys_platform_devices[] = {
index 7619e16fccaef18ddd666a5058487283f884af5c..9d4ed68b580419c5c7e1e0e02509a58e9e29ca60 100644 (file)
@@ -557,12 +557,10 @@ static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec)
  */
 void openpic_cause_IPI(u_int ipi, cpumask_t cpumask)
 {
-       cpumask_t phys;
        DECL_THIS_CPU;
 
        CHECK_THIS_CPU;
        check_arg_ipi(ipi);
-       phys = physmask(cpumask);
        openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
                      cpus_addr(physmask(cpumask))[0]);
 }
index 1bd52ece497c6016a80ff535a68d52babbb139c6..5aca7e8005a80f9b5a188d04269347ac90c411b1 100644 (file)
@@ -1,7 +1,7 @@
 /*
   * mf.c
   * Copyright (C) 2001 Troy D. Armstrong  IBM Corporation
-  * Copyright (C) 2004 Stephen Rothwell  IBM Corporation
+  * Copyright (C) 2004-2005 Stephen Rothwell  IBM Corporation
   *
   * This modules exists as an interface between a Linux secondary partition
   * running on an iSeries and the primary partition's Virtual Service
 
 #include <asm/time.h>
 #include <asm/uaccess.h>
+#include <asm/paca.h>
 #include <asm/iSeries/vio.h>
 #include <asm/iSeries/mf.h>
 #include <asm/iSeries/HvLpConfig.h>
 #include <asm/iSeries/ItSpCommArea.h>
+#include <asm/iSeries/ItLpQueue.h>
 
 /*
  * This is the structure layout for the Machine Facilites LPAR event
@@ -696,36 +698,23 @@ static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
        complete(&rtc->com);
 }
 
-int mf_get_rtc(struct rtc_time *tm)
+static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
 {
-       struct ce_msg_comp_data ce_complete;
-       struct rtc_time_data rtc_data;
-       int rc;
-
-       memset(&ce_complete, 0, sizeof(ce_complete));
-       memset(&rtc_data, 0, sizeof(rtc_data));
-       init_completion(&rtc_data.com);
-       ce_complete.handler = &get_rtc_time_complete;
-       ce_complete.token = &rtc_data;
-       rc = signal_ce_msg_simple(0x40, &ce_complete);
-       if (rc)
-               return rc;
-       wait_for_completion(&rtc_data.com);
        tm->tm_wday = 0;
        tm->tm_yday = 0;
        tm->tm_isdst = 0;
-       if (rtc_data.rc) {
+       if (rc) {
                tm->tm_sec = 0;
                tm->tm_min = 0;
                tm->tm_hour = 0;
                tm->tm_mday = 15;
                tm->tm_mon = 5;
                tm->tm_year = 52;
-               return rtc_data.rc;
+               return rc;
        }
 
-       if ((rtc_data.ce_msg.ce_msg[2] == 0xa9) ||
-           (rtc_data.ce_msg.ce_msg[2] == 0xaf)) {
+       if ((ce_msg[2] == 0xa9) ||
+           (ce_msg[2] == 0xaf)) {
                /* TOD clock is not set */
                tm->tm_sec = 1;
                tm->tm_min = 1;
@@ -736,7 +725,6 @@ int mf_get_rtc(struct rtc_time *tm)
                mf_set_rtc(tm);
        }
        {
-               u8 *ce_msg = rtc_data.ce_msg.ce_msg;
                u8 year = ce_msg[5];
                u8 sec = ce_msg[6];
                u8 min = ce_msg[7];
@@ -765,6 +753,63 @@ int mf_get_rtc(struct rtc_time *tm)
        return 0;
 }
 
+int mf_get_rtc(struct rtc_time *tm)
+{
+       struct ce_msg_comp_data ce_complete;
+       struct rtc_time_data rtc_data;
+       int rc;
+
+       memset(&ce_complete, 0, sizeof(ce_complete));
+       memset(&rtc_data, 0, sizeof(rtc_data));
+       init_completion(&rtc_data.com);
+       ce_complete.handler = &get_rtc_time_complete;
+       ce_complete.token = &rtc_data;
+       rc = signal_ce_msg_simple(0x40, &ce_complete);
+       if (rc)
+               return rc;
+       wait_for_completion(&rtc_data.com);
+       return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
+}
+
+struct boot_rtc_time_data {
+       int busy;
+       struct ce_msg_data ce_msg;
+       int rc;
+};
+
+static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
+{
+       struct boot_rtc_time_data *rtc = token;
+
+       memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
+       rtc->rc = 0;
+       rtc->busy = 0;
+}
+
+int mf_get_boot_rtc(struct rtc_time *tm)
+{
+       struct ce_msg_comp_data ce_complete;
+       struct boot_rtc_time_data rtc_data;
+       int rc;
+
+       memset(&ce_complete, 0, sizeof(ce_complete));
+       memset(&rtc_data, 0, sizeof(rtc_data));
+       rtc_data.busy = 1;
+       ce_complete.handler = &get_boot_rtc_time_complete;
+       ce_complete.token = &rtc_data;
+       rc = signal_ce_msg_simple(0x40, &ce_complete);
+       if (rc)
+               return rc;
+       /* We need to poll here as we are not yet taking interrupts */
+       while (rtc_data.busy) {
+               extern unsigned long lpevent_count;
+               struct ItLpQueue *lpq = get_paca()->lpqueue_ptr;
+               if (lpq && ItLpQueue_isLpIntPending(lpq))
+                       lpevent_count += ItLpQueue_process(lpq, NULL);
+       }
+       return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
+}
+
 int mf_set_rtc(struct rtc_time *tm)
 {
        char ce_time[12];
index c27588ede2fea38f3990f2104f1af4d37246de23..a23de37227bfcc9b81edc2839a6f817f58e61171 100644 (file)
@@ -68,6 +68,7 @@ extern struct smp_ops_t *smp_ops;
 
 static void (*pmac_tb_freeze)(int freeze);
 static struct device_node *pmac_tb_clock_chip_host;
+static u8 pmac_tb_pulsar_addr;
 static DEFINE_SPINLOCK(timebase_lock);
 static unsigned long timebase;
 
@@ -106,12 +107,9 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
        u8 data;
        int rc;
 
-       /* Strangely, the device-tree says address is 0xd2, but darwin
-        * accesses 0xd0 ...
-        */
        pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
        rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
-                              0xd4 | pmac_low_i2c_read,
+                              pmac_tb_pulsar_addr | pmac_low_i2c_read,
                               0x2e, &data, 1);
        if (rc != 0)
                goto bail;
@@ -120,7 +118,7 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
 
        pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
        rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
-                              0xd4 | pmac_low_i2c_write,
+                              pmac_tb_pulsar_addr | pmac_low_i2c_write,
                               0x2e, &data, 1);
  bail:
        if (rc != 0) {
@@ -185,6 +183,12 @@ static int __init smp_core99_probe(void)
        if (ncpus <= 1)
                return 1;
 
+       /* HW sync only on these platforms */
+       if (!machine_is_compatible("PowerMac7,2") &&
+           !machine_is_compatible("PowerMac7,3") &&
+           !machine_is_compatible("RackMac3,1"))
+               goto nohwsync;
+
        /* Look for the clock chip */
        for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) {
                struct device_node *p = of_get_parent(cc);
@@ -198,11 +202,18 @@ static int __init smp_core99_probe(void)
                        goto next;
                switch (*reg) {
                case 0xd2:
-                       pmac_tb_freeze = smp_core99_cypress_tb_freeze;
-                       printk(KERN_INFO "Timebase clock is Cypress chip\n");
+                       if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
+                               pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
+                               pmac_tb_pulsar_addr = 0xd2;
+                               printk(KERN_INFO "Timebase clock is Pulsar chip\n");
+                       } else if (device_is_compatible(cc, "cy28508")) {
+                               pmac_tb_freeze = smp_core99_cypress_tb_freeze;
+                               printk(KERN_INFO "Timebase clock is Cypress chip\n");
+                       }
                        break;
                case 0xd4:
                        pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
+                       pmac_tb_pulsar_addr = 0xd4;
                        printk(KERN_INFO "Timebase clock is Pulsar chip\n");
                        break;
                }
@@ -210,12 +221,15 @@ static int __init smp_core99_probe(void)
                        pmac_tb_clock_chip_host = p;
                        smp_ops->give_timebase = smp_core99_give_timebase;
                        smp_ops->take_timebase = smp_core99_take_timebase;
+                       of_node_put(cc);
+                       of_node_put(p);
                        break;
                }
        next:
                of_node_put(p);
        }
 
+ nohwsync:
        mpic_request_ipis();
 
        return ncpus;
index 35ec42de962e2f42d331e72f3a09cac678e6486a..6f79b7b9b445e8669411e34b48c1ea8ce5135965 100644 (file)
@@ -1750,7 +1750,44 @@ static void __init flatten_device_tree(void)
        prom_printf("Device tree struct  0x%x -> 0x%x\n",
                    RELOC(dt_struct_start), RELOC(dt_struct_end));
 
- }
+}
+
+
+static void __init fixup_device_tree(void)
+{
+       unsigned long offset = reloc_offset();
+       phandle u3, i2c, mpic;
+       u32 u3_rev;
+       u32 interrupts[2];
+       u32 parent;
+
+       /* Some G5s have a missing interrupt definition, fix it up here */
+       u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
+       if ((long)u3 <= 0)
+               return;
+       i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
+       if ((long)i2c <= 0)
+               return;
+       mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
+       if ((long)mpic <= 0)
+               return;
+
+       /* check if proper rev of u3 */
+       if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0)
+               return;
+       if (u3_rev != 0x35)
+               return;
+       /* does it need fixup ? */
+       if (prom_getproplen(i2c, "interrupts") > 0)
+               return;
+       /* interrupt on this revision of u3 is number 0 and level */
+       interrupts[0] = 0;
+       interrupts[1] = 1;
+       prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
+       parent = (u32)mpic;
+       prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
+}
+
 
 static void __init prom_find_boot_cpu(void)
 {
@@ -1919,6 +1956,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
                        PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end)));
        }
 
+       /*
+        * Fixup any known bugs in the device-tree
+        */
+       fixup_device_tree();
+
        /*
         * Now finally create the flattened device-tree
         */
index 3e70b91375fcb808464c190b5e39e1dc72ed9d15..67989055a9fee0b50d9f1b1928183bb66a02be4e 100644 (file)
@@ -292,47 +292,10 @@ int iSeries_set_rtc_time(struct rtc_time *tm)
 
 void iSeries_get_boot_time(struct rtc_time *tm)
 {
-       unsigned long time;
-       static unsigned long lastsec = 1;
-
-       u32 dataWord1 = *((u32 *)(&xSpCommArea.xBcdTimeAtIplStart));
-       u32 dataWord2 = *(((u32 *)&(xSpCommArea.xBcdTimeAtIplStart)) + 1);
-       int year = 1970;
-       int year1 = ( dataWord1 >> 24 ) & 0x000000FF;
-       int year2 = ( dataWord1 >> 16 ) & 0x000000FF;
-       int sec = ( dataWord1 >> 8 ) & 0x000000FF;
-       int min = dataWord1 & 0x000000FF;
-       int hour = ( dataWord2 >> 24 ) & 0x000000FF;
-       int day = ( dataWord2 >> 8 ) & 0x000000FF;
-       int mon = dataWord2 & 0x000000FF;
-
        if ( piranha_simulator )
                return;
 
-       BCD_TO_BIN(sec);
-       BCD_TO_BIN(min);
-       BCD_TO_BIN(hour);
-       BCD_TO_BIN(day);
-       BCD_TO_BIN(mon);
-       BCD_TO_BIN(year1);
-       BCD_TO_BIN(year2);
-       year = year1 * 100 + year2;
-
-       time = mktime(year, mon, day, hour, min, sec);
-       time += ( jiffies / HZ );
-
-       /* Now THIS is a nasty hack!
-       * It ensures that the first two calls get different answers.  
-       * That way the loop in init_time (time.c) will not think
-       * the clock is stuck.
-       */
-       if ( lastsec ) {
-               time -= lastsec;
-               --lastsec;
-       }
-
-       to_tm(time, tm); 
-       tm->tm_year -= 1900;
+       mf_get_boot_rtc(tm);
        tm->tm_mon  -= 1;
 }
 #endif
index 772a465b49f9c2d65636e71d27b7f4ca70f6c17f..3d54745108c788a12099ddeaef929d9985060948 100644 (file)
@@ -515,6 +515,7 @@ void __init time_init(void)
        do_gtod.varp = &do_gtod.vars[0];
        do_gtod.var_idx = 0;
        do_gtod.varp->tb_orig_stamp = tb_last_stamp;
+       get_paca()->next_jiffy_update_tb = tb_last_stamp + tb_ticks_per_jiffy;
        do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
        do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
        do_gtod.varp->tb_to_xs = tb_to_xs;
index 292983413ae2af3616f57b13f47e485212753251..33ca56c90da2637a6e233535239d74131c1b5455 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/delay.h>
 
 #include <asm/pbm.h>
 
@@ -379,6 +380,56 @@ bad:
        return PCI_DMA_ERROR_CODE;
 }
 
+static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages)
+{
+       int limit;
+
+       PCI_STC_FLUSHFLAG_INIT(strbuf);
+       if (strbuf->strbuf_ctxflush &&
+           iommu->iommu_ctxflush) {
+               unsigned long matchreg, flushreg;
+
+               flushreg = strbuf->strbuf_ctxflush;
+               matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+
+               limit = 100000;
+               pci_iommu_write(flushreg, ctx);
+               for(;;) {
+                       if (((long)pci_iommu_read(matchreg)) >= 0L)
+                               break;
+                       limit--;
+                       if (!limit)
+                               break;
+                       udelay(1);
+               }
+               if (!limit)
+                       printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
+                              "timeout vaddr[%08x] ctx[%lx]\n",
+                              vaddr, ctx);
+       } else {
+               unsigned long i;
+
+               for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
+                       pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+       }
+
+       pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+       (void) pci_iommu_read(iommu->write_complete_reg);
+
+       limit = 100000;
+       while (!PCI_STC_FLUSHFLAG_SET(strbuf)) {
+               limit--;
+               if (!limit)
+                       break;
+               udelay(1);
+               membar("#LoadLoad");
+       }
+       if (!limit)
+               printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
+                      "vaddr[%08x] ctx[%lx] npages[%ld]\n",
+                      vaddr, ctx, npages);
+}
+
 /* Unmap a single streaming mode DMA translation. */
 void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
 {
@@ -386,7 +437,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
        struct pci_iommu *iommu;
        struct pci_strbuf *strbuf;
        iopte_t *base;
-       unsigned long flags, npages, i, ctx;
+       unsigned long flags, npages, ctx;
 
        if (direction == PCI_DMA_NONE)
                BUG();
@@ -414,29 +465,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
                ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
 
        /* Step 1: Kick data out of streaming buffers if necessary. */
-       if (strbuf->strbuf_enabled) {
-               u32 vaddr = bus_addr;
-
-               PCI_STC_FLUSHFLAG_INIT(strbuf);
-               if (strbuf->strbuf_ctxflush &&
-                   iommu->iommu_ctxflush) {
-                       unsigned long matchreg, flushreg;
-
-                       flushreg = strbuf->strbuf_ctxflush;
-                       matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
-                       do {
-                               pci_iommu_write(flushreg, ctx);
-                       } while(((long)pci_iommu_read(matchreg)) < 0L);
-               } else {
-                       for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
-                               pci_iommu_write(strbuf->strbuf_pflush, vaddr);
-               }
-
-               pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
-               (void) pci_iommu_read(iommu->write_complete_reg);
-               while (!PCI_STC_FLUSHFLAG_SET(strbuf))
-                       membar("#LoadLoad");
-       }
+       if (strbuf->strbuf_enabled)
+               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
 
        /* Step 2: Clear out first TSB entry. */
        iopte_make_dummy(iommu, base);
@@ -647,29 +677,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
                ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
 
        /* Step 1: Kick data out of streaming buffers if necessary. */
-       if (strbuf->strbuf_enabled) {
-               u32 vaddr = (u32) bus_addr;
-
-               PCI_STC_FLUSHFLAG_INIT(strbuf);
-               if (strbuf->strbuf_ctxflush &&
-                   iommu->iommu_ctxflush) {
-                       unsigned long matchreg, flushreg;
-
-                       flushreg = strbuf->strbuf_ctxflush;
-                       matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
-                       do {
-                               pci_iommu_write(flushreg, ctx);
-                       } while(((long)pci_iommu_read(matchreg)) < 0L);
-               } else {
-                       for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
-                               pci_iommu_write(strbuf->strbuf_pflush, vaddr);
-               }
-
-               pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
-               (void) pci_iommu_read(iommu->write_complete_reg);
-               while (!PCI_STC_FLUSHFLAG_SET(strbuf))
-                       membar("#LoadLoad");
-       }
+       if (strbuf->strbuf_enabled)
+               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
 
        /* Step 2: Clear out first TSB entry. */
        iopte_make_dummy(iommu, base);
@@ -715,28 +724,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size
        }
 
        /* Step 2: Kick data out of streaming buffers. */
-       PCI_STC_FLUSHFLAG_INIT(strbuf);
-       if (iommu->iommu_ctxflush &&
-           strbuf->strbuf_ctxflush) {
-               unsigned long matchreg, flushreg;
-
-               flushreg = strbuf->strbuf_ctxflush;
-               matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
-               do {
-                       pci_iommu_write(flushreg, ctx);
-               } while(((long)pci_iommu_read(matchreg)) < 0L);
-       } else {
-               unsigned long i;
-
-               for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
-                       pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
-       }
-
-       /* Step 3: Perform flush synchronization sequence. */
-       pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
-       (void) pci_iommu_read(iommu->write_complete_reg);
-       while (!PCI_STC_FLUSHFLAG_SET(strbuf))
-               membar("#LoadLoad");
+       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
@@ -749,7 +737,8 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
        struct pcidev_cookie *pcp;
        struct pci_iommu *iommu;
        struct pci_strbuf *strbuf;
-       unsigned long flags, ctx;
+       unsigned long flags, ctx, npages, i;
+       u32 bus_addr;
 
        pcp = pdev->sysdata;
        iommu = pcp->pbm->iommu;
@@ -772,36 +761,14 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
        }
 
        /* Step 2: Kick data out of streaming buffers. */
-       PCI_STC_FLUSHFLAG_INIT(strbuf);
-       if (iommu->iommu_ctxflush &&
-           strbuf->strbuf_ctxflush) {
-               unsigned long matchreg, flushreg;
-
-               flushreg = strbuf->strbuf_ctxflush;
-               matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
-               do {
-                       pci_iommu_write(flushreg, ctx);
-               } while (((long)pci_iommu_read(matchreg)) < 0L);
-       } else {
-               unsigned long i, npages;
-               u32 bus_addr;
-
-               bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
-
-               for(i = 1; i < nelems; i++)
-                       if (!sglist[i].dma_length)
-                               break;
-               i--;
-               npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT;
-               for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
-                       pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
-       }
-
-       /* Step 3: Perform flush synchronization sequence. */
-       pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
-       (void) pci_iommu_read(iommu->write_complete_reg);
-       while (!PCI_STC_FLUSHFLAG_SET(strbuf))
-               membar("#LoadLoad");
+       bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
+       for(i = 1; i < nelems; i++)
+               if (!sglist[i].dma_length)
+                       break;
+       i--;
+       npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
+                 - bus_addr) >> IO_PAGE_SHIFT;
+       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
index 14d9c3a21b9aab04d79a0fb60703a4661cf2c80d..76ea6455433f1a7aa89005190b4fe60d56d3aea3 100644 (file)
@@ -117,19 +117,34 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages
 
 #define STRBUF_TAG_VALID       0x02UL
 
-static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
 {
+       unsigned long n;
+       int limit;
+
        iommu->strbuf_flushflag = 0UL;
-       while (npages--)
-               upa_writeq(base + (npages << IO_PAGE_SHIFT),
+       n = npages;
+       while (n--)
+               upa_writeq(base + (n << IO_PAGE_SHIFT),
                           iommu->strbuf_regs + STRBUF_PFLUSH);
 
        /* Whoopee cushion! */
        upa_writeq(__pa(&iommu->strbuf_flushflag),
                   iommu->strbuf_regs + STRBUF_FSYNC);
        upa_readq(iommu->sbus_control_reg);
-       while (iommu->strbuf_flushflag == 0UL)
+
+       limit = 100000;
+       while (iommu->strbuf_flushflag == 0UL) {
+               limit--;
+               if (!limit)
+                       break;
+               udelay(1);
                membar("#LoadLoad");
+       }
+       if (!limit)
+               printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
+                      "vaddr[%08x] npages[%ld]\n",
+                      base, npages);
 }
 
 static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages)
@@ -406,7 +421,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size,
 
        spin_lock_irqsave(&iommu->lock, flags);
        free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT);
-       strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -569,7 +584,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int
        iommu = sdev->bus->iommu;
        spin_lock_irqsave(&iommu->lock, flags);
        free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT);
-       strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -581,7 +596,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t
        size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK));
 
        spin_lock_irqsave(&iommu->lock, flags);
-       strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -605,7 +620,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int
        size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
index fd8d7e8982b19b6c066e80b8d46db30eafa3bd77..f162f50f0b179539c5a6f8c0dfa439dc47ebfff5 100644 (file)
@@ -6,6 +6,10 @@ config 64BIT
        bool
        default y
 
+config TOP_ADDR
+       hex
+       default 0x80000000
+
 config 3_LEVEL_PGTABLES
        bool
        default y
index 0150038af795f054e66b8331f9ffcf4d2e8d612a..14a12d6b3df6e89c695860170ce10145d1556f0d 100644 (file)
 #include "os.h"
 
 #ifdef CONFIG_NOCONFIG_CHAN
+
+/* The printk's here are wrong because we are complaining that there is no
+ * output device, but printk is printing to that output device.  The user will
+ * never see the error.  printf would be better, except it can't run on a
+ * kernel stack because it will overflow it.
+ * Use printk for now since that will avoid crashing.
+ */
+
 static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(NULL);
 }
@@ -30,27 +38,27 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 static int not_configged_open(int input, int output, int primary, void *data,
                              char **dev_out)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-ENODEV);
 }
 
 static void not_configged_close(int fd, void *data)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
 }
 
 static int not_configged_read(int fd, char *c_out, void *data)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
 
 static int not_configged_write(int fd, const char *buf, int len, void *data)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
@@ -58,7 +66,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data)
 static int not_configged_console_write(int fd, const char *buf, int len,
                                       void *data)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
@@ -66,7 +74,7 @@ static int not_configged_console_write(int fd, const char *buf, int len,
 static int not_configged_window_size(int fd, void *data, unsigned short *rows,
                                     unsigned short *cols)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-ENODEV);
 }
index faf714e87b5b1a8bd78663b18c37c3799b29fb07..217438cdef336fff7e609fbb63378a541c3e93f4 100644 (file)
@@ -73,7 +73,6 @@ int mcast_setup(char *str, char **mac_out, void *data)
        struct mcast_init *init = data;
        char *port_str = NULL, *ttl_str = NULL, *remain;
        char *last;
-       int n;
 
        *init = ((struct mcast_init)
                { .addr         = "239.192.168.1",
@@ -89,13 +88,12 @@ int mcast_setup(char *str, char **mac_out, void *data)
        }
        
        if(port_str != NULL){
-               n = simple_strtoul(port_str, &last, 10);
+               init->port = simple_strtoul(port_str, &last, 10);
                if((*last != '\0') || (last == port_str)){
                        printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", 
                               port_str);
                        return(0);
                }
-               init->port = htons(n);
        }
 
        if(ttl_str != NULL){
index 0fe1d9fa9139a8b326ed831527c48e49f378eb2f..7a0d115b29d09e8b9361668e424c208c0f1a6e5b 100644 (file)
@@ -38,7 +38,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
        }
        sin->sin_family = AF_INET;
        sin->sin_addr.s_addr = in_aton(addr);
-       sin->sin_port = port;
+       sin->sin_port = htons(port);
        return(sin);
 }
 
@@ -55,28 +55,25 @@ static int mcast_open(void *data)
        struct mcast_data *pri = data;
        struct sockaddr_in *sin = pri->mcast_addr;
        struct ip_mreq mreq;
-       int fd, yes = 1;
+       int fd = -EINVAL, yes = 1, err = -EINVAL;;
 
 
-       if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) {
-               fd = -EINVAL;
+       if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
                goto out;
-       }
 
        fd = socket(AF_INET, SOCK_DGRAM, 0);
+
        if (fd < 0){
                printk("mcast_open : data socket failed, errno = %d\n", 
                       errno);
-               fd = -ENOMEM;
+               fd = -errno;
                goto out;
        }
 
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
                printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
                        errno);
-               os_close_file(fd);
-               fd = -EINVAL;
-               goto out;
+               goto out_close;
        }
 
        /* set ttl according to config */
@@ -84,26 +81,20 @@ static int mcast_open(void *data)
                       sizeof(pri->ttl)) < 0) {
                printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
                        errno);
-               os_close_file(fd);
-               fd = -EINVAL;
-               goto out;
+               goto out_close;
        }
 
        /* set LOOP, so data does get fed back to local sockets */
        if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
                printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
                        errno);
-               os_close_file(fd);
-               fd = -EINVAL;
-               goto out;
+               goto out_close;
        }
 
        /* bind socket to mcast address */
        if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
                printk("mcast_open : data bind failed, errno = %d\n", errno);
-               os_close_file(fd);
-               fd = -EINVAL;
-               goto out;
+               goto out_close;
        }               
        
        /* subscribe to the multicast group */
@@ -117,12 +108,15 @@ static int mcast_open(void *data)
                       "interface on the host.\n");
                printk("eth0 should be configured in order to use the "
                       "multicast transport.\n");
-               os_close_file(fd);
-               fd = -EINVAL;
+                goto out_close;
        }
 
  out:
-       return(fd);
+       return fd;
+
+ out_close:
+        os_close_file(fd);
+        return err;
 }
 
 static void mcast_close(int fd, void *data)
@@ -164,14 +158,3 @@ struct net_user_info mcast_user_info = {
        .delete_address = NULL,
        .max_packet     = MAX_PACKET - ETH_HEADER_OTHER
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 9a56ff94308dff7a06a5b0fd5cff8ed3b14249ad..88f956c34fedb0cf9b58e618ccb4b8c0e427a8c3 100644 (file)
@@ -55,7 +55,7 @@
 #include "mem_kern.h"
 #include "cow.h"
 
-enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP };
+enum ubd_req { UBD_READ, UBD_WRITE };
 
 struct io_thread_req {
        enum ubd_req op;
@@ -68,8 +68,6 @@ struct io_thread_req {
        unsigned long sector_mask;
        unsigned long long cow_offset;
        unsigned long bitmap_words[2];
-       int map_fd;
-       unsigned long long map_offset;
        int error;
 };
 
@@ -122,10 +120,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
 
 #define MAX_DEV (8)
 
-/* Changed in early boot */
-static int ubd_do_mmap = 0;
-#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
-
 static struct block_device_operations ubd_blops = {
         .owner         = THIS_MODULE,
         .open          = ubd_open,
@@ -175,12 +169,6 @@ struct ubd {
        int no_cow;
        struct cow cow;
        struct platform_device pdev;
-
-       int map_writes;
-       int map_reads;
-       int nomap_writes;
-       int nomap_reads;
-       int write_maps;
 };
 
 #define DEFAULT_COW { \
@@ -200,11 +188,6 @@ struct ubd {
        .openflags =            OPEN_FLAGS, \
         .no_cow =               0, \
         .cow =                 DEFAULT_COW, \
-       .map_writes             = 0, \
-       .map_reads              = 0, \
-       .nomap_writes           = 0, \
-       .nomap_reads            = 0, \
-       .write_maps             = 0, \
 }
 
 struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
@@ -314,13 +297,6 @@ static int ubd_setup_common(char *str, int *index_out)
                int major;
 
                str++;
-               if(!strcmp(str, "mmap")){
-                       CHOOSE_MODE(printk("mmap not supported by the ubd "
-                                          "driver in tt mode\n"),
-                                   ubd_do_mmap = 1);
-                       return(0);
-               }
-
                if(!strcmp(str, "sync")){
                        global_openflags = of_sync(global_openflags);
                        return(0);
@@ -524,7 +500,7 @@ static void ubd_handler(void)
 {
        struct io_thread_req req;
        struct request *rq = elv_next_request(ubd_queue);
-       int n, err;
+       int n;
 
        do_ubd = NULL;
        intr_count++;
@@ -538,19 +514,6 @@ static void ubd_handler(void)
                return;
        }
         
-       if((req.op != UBD_MMAP) &&
-          ((req.offset != ((__u64) (rq->sector)) << 9) ||
-           (req.length != (rq->current_nr_sectors) << 9)))
-               panic("I/O op mismatch");
-       
-       if(req.map_fd != -1){
-               err = physmem_subst_mapping(req.buffer, req.map_fd,
-                                           req.map_offset, 1);
-               if(err)
-                       printk("ubd_handler - physmem_subst_mapping failed, "
-                              "err = %d\n", -err);
-       }
-
        ubd_finish(rq, req.error);
        reactivate_fd(thread_fd, UBD_IRQ);      
        do_ubd_request(ubd_queue);
@@ -583,14 +546,10 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
 
 static void ubd_close(struct ubd *dev)
 {
-       if(ubd_do_mmap)
-               physmem_forget_descriptor(dev->fd);
        os_close_file(dev->fd);
        if(dev->cow.file == NULL)
                return;
 
-       if(ubd_do_mmap)
-               physmem_forget_descriptor(dev->cow.fd);
        os_close_file(dev->cow.fd);
        vfree(dev->cow.bitmap);
        dev->cow.bitmap = NULL;
@@ -1010,94 +969,13 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
                           req->bitmap_words, bitmap_len);
 }
 
-static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
-{
-       __u64 sector;
-       unsigned char *bitmap;
-       int bit, i;
-
-       /* mmap must have been requested on the command line */
-       if(!ubd_do_mmap)
-               return(-1);
-
-       /* The buffer must be page aligned */
-       if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
-               return(-1);
-
-       /* The request must be a page long */
-       if((req->current_nr_sectors << 9) != PAGE_SIZE)
-               return(-1);
-
-       if(dev->cow.file == NULL)
-               return(dev->fd);
-
-       sector = offset >> 9;
-       bitmap = (unsigned char *) dev->cow.bitmap;
-       bit = ubd_test_bit(sector, bitmap);
-
-       for(i = 1; i < req->current_nr_sectors; i++){
-               if(ubd_test_bit(sector + i, bitmap) != bit)
-                       return(-1);
-       }
-
-       if(bit || (rq_data_dir(req) == WRITE))
-               offset += dev->cow.data_offset;
-
-       /* The data on disk must be page aligned */
-       if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
-               return(-1);
-
-       return(bit ? dev->fd : dev->cow.fd);
-}
-
-static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
-                               struct request *req,
-                               struct io_thread_req *io_req)
-{
-       int err;
-
-       if(rq_data_dir(req) == WRITE){
-               /* Writes are almost no-ops since the new data is already in the
-                * host page cache
-                */
-               dev->map_writes++;
-               if(dev->cow.file != NULL)
-                       cowify_bitmap(io_req->offset, io_req->length,
-                                     &io_req->sector_mask, &io_req->cow_offset,
-                                     dev->cow.bitmap, dev->cow.bitmap_offset,
-                                     io_req->bitmap_words,
-                                     dev->cow.bitmap_len);
-       }
-       else {
-               int w;
-
-               if((dev->cow.file != NULL) && (fd == dev->cow.fd))
-                       w = 0;
-               else w = dev->openflags.w;
-
-               if((dev->cow.file != NULL) && (fd == dev->fd))
-                       offset += dev->cow.data_offset;
-
-               err = physmem_subst_mapping(req->buffer, fd, offset, w);
-               if(err){
-                       printk("physmem_subst_mapping failed, err = %d\n",
-                              -err);
-                       return(1);
-               }
-               dev->map_reads++;
-       }
-       io_req->op = UBD_MMAP;
-       io_req->buffer = req->buffer;
-       return(0);
-}
-
 /* Called with ubd_io_lock held */
 static int prepare_request(struct request *req, struct io_thread_req *io_req)
 {
        struct gendisk *disk = req->rq_disk;
        struct ubd *dev = disk->private_data;
        __u64 offset;
-       int len, fd;
+       int len;
 
        if(req->rq_status == RQ_INACTIVE) return(1);
 
@@ -1114,34 +992,12 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
 
        io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
        io_req->fds[1] = dev->fd;
-       io_req->map_fd = -1;
        io_req->cow_offset = -1;
        io_req->offset = offset;
        io_req->length = len;
        io_req->error = 0;
        io_req->sector_mask = 0;
 
-       fd = mmap_fd(req, dev, io_req->offset);
-       if(fd > 0){
-               /* If mmapping is otherwise OK, but the first access to the
-                * page is a write, then it's not mapped in yet.  So we have
-                * to write the data to disk first, then we can map the disk
-                * page in and continue normally from there.
-                */
-               if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
-                       io_req->map_fd = dev->fd;
-                       io_req->map_offset = io_req->offset +
-                               dev->cow.data_offset;
-                       dev->write_maps++;
-               }
-               else return(prepare_mmap_request(dev, fd, io_req->offset, req,
-                                                io_req));
-       }
-
-       if(rq_data_dir(req) == READ)
-               dev->nomap_reads++;
-       else dev->nomap_writes++;
-
        io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
        io_req->offsets[0] = 0;
        io_req->offsets[1] = dev->cow.data_offset;
@@ -1229,143 +1085,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
        return(-EINVAL);
 }
 
-static int ubd_check_remapped(int fd, unsigned long address, int is_write,
-                             __u64 offset)
-{
-       __u64 bitmap_offset;
-       unsigned long new_bitmap[2];
-       int i, err, n;
-
-       /* If it's not a write access, we can't do anything about it */
-       if(!is_write)
-               return(0);
-
-       /* We have a write */
-       for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
-               struct ubd *dev = &ubd_dev[i];
-
-               if((dev->fd != fd) && (dev->cow.fd != fd))
-                       continue;
-
-               /* It's a write to a ubd device */
-
-               /* This should be impossible now */
-               if(!dev->openflags.w){
-                       /* It's a write access on a read-only device - probably
-                        * shouldn't happen.  If the kernel is trying to change
-                        * something with no intention of writing it back out,
-                        * then this message will clue us in that this needs
-                        * fixing
-                        */
-                       printk("Write access to mapped page from readonly ubd "
-                              "device %d\n", i);
-                       return(0);
-               }
-
-               /* It's a write to a writeable ubd device - it must be COWed
-                * because, otherwise, the page would have been mapped in
-                * writeable
-                */
-
-               if(!dev->cow.file)
-                       panic("Write fault on writeable non-COW ubd device %d",
-                             i);
-
-               /* It should also be an access to the backing file since the
-                * COW pages should be mapped in read-write
-                */
-
-               if(fd == dev->fd)
-                       panic("Write fault on a backing page of ubd "
-                             "device %d\n", i);
-
-               /* So, we do the write, copying the backing data to the COW
-                * file...
-                */
-
-               err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
-               if(err < 0)
-                       panic("Couldn't seek to %lld in COW file of ubd "
-                             "device %d, err = %d",
-                             offset + dev->cow.data_offset, i, -err);
-
-               n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
-               if(n != PAGE_SIZE)
-                       panic("Couldn't copy data to COW file of ubd "
-                             "device %d, err = %d", i, -n);
-
-               /* ... updating the COW bitmap... */
-
-               cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
-                             dev->cow.bitmap, dev->cow.bitmap_offset,
-                             new_bitmap, dev->cow.bitmap_len);
-
-               err = os_seek_file(dev->fd, bitmap_offset);
-               if(err < 0)
-                       panic("Couldn't seek to %lld in COW file of ubd "
-                             "device %d, err = %d", bitmap_offset, i, -err);
-
-               n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
-               if(n != sizeof(new_bitmap))
-                       panic("Couldn't update bitmap  of ubd device %d, "
-                             "err = %d", i, -n);
-
-               /* Maybe we can map the COW page in, and maybe we can't.  If
-                * it is a pre-V3 COW file, we can't, since the alignment will
-                * be wrong.  If it is a V3 or later COW file which has been
-                * moved to a system with a larger page size, then maybe we
-                * can't, depending on the exact location of the page.
-                */
-
-               offset += dev->cow.data_offset;
-
-               /* Remove the remapping, putting the original anonymous page
-                * back.  If the COW file can be mapped in, that is done.
-                * Otherwise, the COW page is read in.
-                */
-
-               if(!physmem_remove_mapping((void *) address))
-                       panic("Address 0x%lx not remapped by ubd device %d",
-                             address, i);
-               if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
-                       physmem_subst_mapping((void *) address, dev->fd,
-                                             offset, 1);
-               else {
-                       err = os_seek_file(dev->fd, offset);
-                       if(err < 0)
-                               panic("Couldn't seek to %lld in COW file of "
-                                     "ubd device %d, err = %d", offset, i,
-                                     -err);
-
-                       n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
-                       if(n != PAGE_SIZE)
-                               panic("Failed to read page from offset %llx of "
-                                     "COW file of ubd device %d, err = %d",
-                                     offset, i, -n);
-               }
-
-               return(1);
-       }
-
-       /* It's not a write on a ubd device */
-       return(0);
-}
-
-static struct remapper ubd_remapper = {
-       .list   = LIST_HEAD_INIT(ubd_remapper.list),
-       .proc   = ubd_check_remapped,
-};
-
-static int ubd_remapper_setup(void)
-{
-       if(ubd_do_mmap)
-               register_remapper(&ubd_remapper);
-
-       return(0);
-}
-
-__initcall(ubd_remapper_setup);
-
 static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
 {
        struct uml_stat buf1, buf2;
@@ -1568,15 +1287,6 @@ void do_io(struct io_thread_req *req)
        int err;
        __u64 off;
 
-       if(req->op == UBD_MMAP){
-               /* Touch the page to force the host to do any necessary IO to
-                * get it into memory
-                */
-               n = *((volatile int *) req->buffer);
-               req->error = update_bitmap(req);
-               return;
-       }
-
        nsectors = req->length / req->sectorsize;
        start = 0;
        do {
index 84ec7ff5cf8c11754cdb6b72df60f5ddb0fc1784..6eaeb9919983ebd71dc6d6120207103fc2a481cf 100644 (file)
@@ -31,7 +31,6 @@ extern int sysemu_supported;
 #ifdef UML_CONFIG_MODE_SKAS
 
 #include "skas_ptregs.h"
-#include "sysdep/faultinfo.h"
 
 #define REGS_IP(r) ((r)[HOST_IP])
 #define REGS_SP(r) ((r)[HOST_SP])
@@ -59,6 +58,7 @@ extern int sysemu_supported;
 #define PTRACE_SYSEMU_SINGLESTEP 32
 #endif
 
+#include "sysdep/faultinfo.h"
 #include "choose-mode.h"
 
 union uml_pt_regs {
index 572c6c19be33b3ea0e496ea803011040db5cfb4f..ea97005af69443883110f3573035b6cf5f5ab753 100644 (file)
@@ -9,8 +9,6 @@
 #include "linux/in6.h"
 #include "asm/uaccess.h"
 
-extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst, int len,
-                                          int sum, int *err_ptr);
 extern unsigned csum_partial(const unsigned char *buff, unsigned len,
                              unsigned sum);
 
@@ -31,10 +29,15 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
 }
 
 static __inline__
-unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
-                                        int len, int sum, int *err_ptr)
+unsigned int csum_partial_copy_from_user(const unsigned char *src,
+                                         unsigned char *dst, int len, int sum,
+                                         int *err_ptr)
 {
-       return csum_partial_copy_from(src, dst, len, sum, err_ptr);
+        if(copy_from_user(dst, src, len)){
+                *err_ptr = -EFAULT;
+                return(-1);
+        }
+        return csum_partial(dst, len, sum);
 }
 
 /**
@@ -137,15 +140,6 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b)
         return a;
 }
 
-#endif
+extern unsigned short ip_compute_csum(unsigned char * buff, int len);
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+#endif
index 348e8fcd513fe6b4759a943603327bcb927fbad2..be8acd5efd974ac9a3b36a2b3a7703d332900996 100644 (file)
@@ -135,6 +135,7 @@ extern int mode_tt;
        __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
 #define UPT_SC(r) ((r)->tt.sc)
 #define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
+#define UPT_SYSCALL_RET(r) UPT_RAX(r)
 
 extern int user_context(unsigned long sp);
 
@@ -196,32 +197,32 @@ struct syscall_args {
 
 
 #define UPT_SET(regs, reg, val) \
-        ({      unsigned long val; \
+        ({      unsigned long __upt_val = val; \
                 switch(reg){ \
-               case R8: UPT_R8(regs) = val; break; \
-               case R9: UPT_R9(regs) = val; break; \
-               case R10: UPT_R10(regs) = val; break; \
-               case R11: UPT_R11(regs) = val; break; \
-               case R12: UPT_R12(regs) = val; break; \
-               case R13: UPT_R13(regs) = val; break; \
-               case R14: UPT_R14(regs) = val; break; \
-               case R15: UPT_R15(regs) = val; break; \
-                case RIP: UPT_IP(regs) = val; break; \
-                case RSP: UPT_SP(regs) = val; break; \
-                case RAX: UPT_RAX(regs) = val; break; \
-                case RBX: UPT_RBX(regs) = val; break; \
-                case RCX: UPT_RCX(regs) = val; break; \
-                case RDX: UPT_RDX(regs) = val; break; \
-                case RSI: UPT_RSI(regs) = val; break; \
-                case RDI: UPT_RDI(regs) = val; break; \
-                case RBP: UPT_RBP(regs) = val; break; \
-                case ORIG_RAX: UPT_ORIG_RAX(regs) = val; break; \
-                case CS: UPT_CS(regs) = val; break; \
-                case DS: UPT_DS(regs) = val; break; \
-                case ES: UPT_ES(regs) = val; break; \
-                case FS: UPT_FS(regs) = val; break; \
-                case GS: UPT_GS(regs) = val; break; \
-                case EFLAGS: UPT_EFLAGS(regs) = val; break; \
+                case R8: UPT_R8(regs) = __upt_val; break; \
+                case R9: UPT_R9(regs) = __upt_val; break; \
+                case R10: UPT_R10(regs) = __upt_val; break; \
+                case R11: UPT_R11(regs) = __upt_val; break; \
+                case R12: UPT_R12(regs) = __upt_val; break; \
+                case R13: UPT_R13(regs) = __upt_val; break; \
+                case R14: UPT_R14(regs) = __upt_val; break; \
+                case R15: UPT_R15(regs) = __upt_val; break; \
+                case RIP: UPT_IP(regs) = __upt_val; break; \
+                case RSP: UPT_SP(regs) = __upt_val; break; \
+                case RAX: UPT_RAX(regs) = __upt_val; break; \
+                case RBX: UPT_RBX(regs) = __upt_val; break; \
+                case RCX: UPT_RCX(regs) = __upt_val; break; \
+                case RDX: UPT_RDX(regs) = __upt_val; break; \
+                case RSI: UPT_RSI(regs) = __upt_val; break; \
+                case RDI: UPT_RDI(regs) = __upt_val; break; \
+                case RBP: UPT_RBP(regs) = __upt_val; break; \
+                case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
+                case CS: UPT_CS(regs) = __upt_val; break; \
+                case DS: UPT_DS(regs) = __upt_val; break; \
+                case ES: UPT_ES(regs) = __upt_val; break; \
+                case FS: UPT_FS(regs) = __upt_val; break; \
+                case GS: UPT_GS(regs) = __upt_val; break; \
+                case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
                 default :  \
                         panic("Bad register in UPT_SET : %d\n", reg);  \
                        break; \
@@ -245,14 +246,3 @@ struct syscall_args {
         CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 9736ca27c5f0782edfc34f18d830c03977fb9d65..a8918e80df9623542a7b2cce781c2476b4fb9827 100644 (file)
@@ -14,7 +14,7 @@ obj-y = config.o exec_kern.o exitcode.o \
        tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
        user_util.o
 
-obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
+obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)    += gprof_syms.o
 obj-$(CONFIG_GCOV)     += gmon_syms.o
 obj-$(CONFIG_TTY_LOG)  += tty_log.o
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
new file mode 100644 (file)
index 0000000..82ecf90
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/init.h"
+#include "linux/bootmem.h"
+#include "linux/initrd.h"
+#include "asm/types.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "initrd.h"
+#include "init.h"
+#include "os.h"
+
+/* Changed by uml_initrd_setup, which is a setup */
+static char *initrd __initdata = NULL;
+
+static int __init read_initrd(void)
+{
+       void *area;
+       long long size;
+       int err;
+
+       if(initrd == NULL) return 0;
+       err = os_file_size(initrd, &size);
+       if(err) return 0;
+       area = alloc_bootmem(size);
+       if(area == NULL) return 0;
+       if(load_initrd(initrd, area, size) == -1) return 0;
+       initrd_start = (unsigned long) area;
+       initrd_end = initrd_start + size;
+       return 0;
+}
+
+__uml_postsetup(read_initrd);
+
+static int __init uml_initrd_setup(char *line, int *add)
+{
+       initrd = line;
+       return 0;
+}
+
+__uml_setup("initrd=", uml_initrd_setup,
+"initrd=<initrd image>\n"
+"    This is used to boot UML from an initrd image.  The argument is the\n"
+"    name of the file containing the image.\n\n"
+);
+
+int load_initrd(char *filename, void *buf, int size)
+{
+       int fd, n;
+
+       fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+       if(fd < 0){
+               printk("Opening '%s' failed - err = %d\n", filename, -fd);
+               return(-1);
+       }
+       n = os_read_file(fd, buf, size);
+       if(n != size){
+               printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+                      filename, -n);
+               return(-1);
+       }
+
+       os_close_file(fd);
+       return(0);
+}
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
index 6d6f9484b884d357240beaf65266c0d376644e55..b3074cbaa479ac3de6c42242006d8e5c1f33cb42 100644 (file)
@@ -236,9 +236,15 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
                                       (*prev)->fd, pollfds[i].fd);
                                goto out;
                        }
-                       memcpy(&pollfds[i], &pollfds[i + 1],
-                              (pollfds_num - i - 1) * sizeof(pollfds[0]));
+
                        pollfds_num--;
+
+                       /* This moves the *whole* array after pollfds[i] (though
+                        * it doesn't spot as such)! */
+
+                       memmove(&pollfds[i], &pollfds[i + 1],
+                              (pollfds_num - i) * sizeof(pollfds[0]));
+
                        if(last_irq_ptr == &old_fd->next) 
                                last_irq_ptr = prev;
                        *prev = (*prev)->next;
index 78d69dc74b26d3b4653932f39227159259dc2dd2..99439fa15ef42514b8e563623f6eaa8238c829cc 100644 (file)
@@ -57,6 +57,7 @@ EXPORT_SYMBOL(copy_to_user_tt);
 EXPORT_SYMBOL(strncpy_from_user_skas);
 EXPORT_SYMBOL(copy_to_user_skas);
 EXPORT_SYMBOL(copy_from_user_skas);
+EXPORT_SYMBOL(clear_user_skas);
 #endif
 EXPORT_SYMBOL(uml_strdup);
 
index f156661781cb19a2000900d195503616090de77d..c22825f13e40fda8ab8a2b21d8cc5df6fc04f6d4 100644 (file)
@@ -100,12 +100,37 @@ void mem_init(void)
 #endif
 }
 
+/*
+ * Create a page table and place a pointer to it in a middle page
+ * directory entry.
+ */
+static void __init one_page_table_init(pmd_t *pmd)
+{
+       if (pmd_none(*pmd)) {
+               pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+               set_pmd(pmd, __pmd(_KERNPG_TABLE +
+                                          (unsigned long) __pa(pte)));
+               if (pte != pte_offset_kernel(pmd, 0))
+                       BUG();
+       }
+}
+
+static void __init one_md_table_init(pud_t *pud)
+{
+#ifdef CONFIG_3_LEVEL_PGTABLES
+       pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+       set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
+       if (pmd_table != pmd_offset(pud, 0))
+               BUG();
+#endif
+}
+
 static void __init fixrange_init(unsigned long start, unsigned long end, 
                                 pgd_t *pgd_base)
 {
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
-       pte_t *pte;
        int i, j;
        unsigned long vaddr;
 
@@ -115,15 +140,12 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
        pgd = pgd_base + i;
 
        for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
-               pmd = (pmd_t *)pgd;
+               pud = pud_offset(pgd, vaddr);
+               if (pud_none(*pud))
+                       one_md_table_init(pud);
+               pmd = pmd_offset(pud, vaddr);
                for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
-                       if (pmd_none(*pmd)) {
-                               pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-                               set_pmd(pmd, __pmd(_KERNPG_TABLE + 
-                                                  (unsigned long) __pa(pte)));
-                               if (pte != pte_offset_kernel(pmd, 0))
-                                       BUG();
-                       }
+                       one_page_table_init(pmd);
                        vaddr += PMD_SIZE;
                }
                j = 0;
index 2b75d8d9ba738f493289aa86c045ea3cd07fdc71..2925e15324de370b29689b9587cc6311d95f935a 100644 (file)
@@ -28,9 +28,9 @@ static inline void set_singlestepping(struct task_struct *child, int on)
         child->thread.singlestep_syscall = 0;
 
 #ifdef SUBARCH_SET_SINGLESTEPPING
-        SUBARCH_SET_SINGLESTEPPING(child, on)
+        SUBARCH_SET_SINGLESTEPPING(child, on);
 #endif
-                }
+}
 
 /*
  * Called by kernel/ptrace.c when detaching..
@@ -83,7 +83,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
        }
 
 #ifdef SUBACH_PTRACE_SPECIAL
-        SUBARCH_PTRACE_SPECIAL(child,request,addr,data)
+        SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
 #endif
 
        ret = ptrace_check_attach(child, request == PTRACE_KILL);
index 5fca2c61eb980a631fe70d500b18b9422e17e0cf..1de22d8a313a0d7ad158952ca2077fd15e5a305f 100644 (file)
@@ -57,10 +57,11 @@ int handle_page_fault(unsigned long address, unsigned long ip,
        *code_out = SEGV_ACCERR;
        if(is_write && !(vma->vm_flags & VM_WRITE)) 
                goto out;
+
+        if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+                goto out;
+
        page = address & PAGE_MASK;
-       pgd = pgd_offset(mm, page);
-       pud = pud_offset(pgd, page);
-       pmd = pmd_offset(pud, page);
        do {
  survive:
                switch (handle_mm_fault(mm, vma, address, is_write)){
@@ -106,33 +107,6 @@ out_of_memory:
        goto out;
 }
 
-LIST_HEAD(physmem_remappers);
-
-void register_remapper(struct remapper *info)
-{
-       list_add(&info->list, &physmem_remappers);
-}
-
-static int check_remapped_addr(unsigned long address, int is_write)
-{
-       struct remapper *remapper;
-       struct list_head *ele;
-       __u64 offset;
-       int fd;
-
-       fd = phys_mapping(__pa(address), &offset);
-       if(fd == -1)
-               return(0);
-
-       list_for_each(ele, &physmem_remappers){
-               remapper = list_entry(ele, struct remapper, list);
-               if((*remapper->proc)(fd, address, is_write, offset))
-                       return(1);
-       }
-
-       return(0);
-}
-
 /*
  * We give a *copy* of the faultinfo in the regs to segv.
  * This must be done, since nesting SEGVs could overwrite
@@ -151,8 +125,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
                 flush_tlb_kernel_vm();
                 return(0);
         }
-       else if(check_remapped_addr(address & PAGE_MASK, is_write))
-               return(0);
        else if(current->mm == NULL)
                panic("Segfault with no mm");
        err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
index 92ec85d67c7c601706f2e35fafe25862aa00372c..84a9385a8fefbcc1048cedbc2a71edecaf9999e4 100644 (file)
@@ -12,6 +12,7 @@ EXPORT_SYMBOL(__do_copy_to_user);
 EXPORT_SYMBOL(__do_strncpy_from_user);
 EXPORT_SYMBOL(__do_strnlen_user); 
 EXPORT_SYMBOL(__do_clear_user);
+EXPORT_SYMBOL(clear_user_tt);
 
 EXPORT_SYMBOL(tracing_pid);
 EXPORT_SYMBOL(honeypot);
index 76eadb3091894d8058b571d235d02ac2ad0c01ad..dd5355500bdccdc66423761a0dd69ce88baca6bd 100644 (file)
@@ -73,6 +73,8 @@ SECTIONS
 
   .got           : { *(.got.plt) *(.got) }
   .dynamic       : { *(.dynamic) }
+  .tdata         : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss                  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
   /* We want the small data sections together, so single-instruction offsets
      can access them all, and initialized data all before uninitialized, so
      we can shorten the on-disk segment size.  */
index fcd67c3414e40d47cfb384b502efdcbc6af29cc1..4351e5605506edc13a059fadcf48c6abd1f9a3c8 100644 (file)
@@ -9,11 +9,11 @@ USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
 
 SYMLINKS = bitops.c semaphore.c highmem.c module.c
 
+include arch/um/scripts/Makefile.rules
+
 bitops.c-dir = lib
 semaphore.c-dir = kernel
 highmem.c-dir = mm
 module.c-dir = kernel
 
 subdir- := util
-
-include arch/um/scripts/Makefile.rules
index e9892eef51cee5dd85038ba98c22432bb81d42af..2c11b9770e8b351c3756864237ff27b9be721e41 100644 (file)
@@ -1,5 +1,7 @@
-#include "linux/delay.h"
-#include "asm/param.h"
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/param.h>
 
 void __delay(unsigned long time)
 {
@@ -20,13 +22,19 @@ void __udelay(unsigned long usecs)
        int i, n;
 
        n = (loops_per_jiffy * HZ * usecs) / MILLION;
-       for(i=0;i<n;i++) ;
+        for(i=0;i<n;i++)
+                cpu_relax();
 }
 
+EXPORT_SYMBOL(__udelay);
+
 void __const_udelay(unsigned long usecs)
 {
        int i, n;
 
        n = (loops_per_jiffy * HZ * usecs) / MILLION;
-       for(i=0;i<n;i++) ;
+        for(i=0;i<n;i++)
+                cpu_relax();
 }
+
+EXPORT_SYMBOL(__const_udelay);
index 3d7da911cc8c90cf0cf0d78382a7b6b8f36d0416..608466ad6b22309c802f2df4af9ffca71dc21d98 100644 (file)
@@ -14,11 +14,11 @@ obj-$(CONFIG_MODULES) += module.o um_module.o
 
 USER_OBJS := ptrace_user.o sigcontext.o
 
-include arch/um/scripts/Makefile.rules
-
 SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
        semaphore.c thunk.S module.c
 
+include arch/um/scripts/Makefile.rules
+
 bitops.c-dir = lib
 csum-copy.S-dir = lib
 csum-partial.c-dir = lib
@@ -28,6 +28,4 @@ semaphore.c-dir = kernel
 thunk.S-dir = lib
 module.c-dir = kernel
 
-CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial
-
 subdir- := util
index 651332aeec22db781a0af12181210515b788a990..137f4446b4390cfe49b7036de853b1fff05d350a 100644 (file)
@@ -5,40 +5,37 @@
  * Licensed under the GPL
  */
 
-#include "linux/delay.h"
-#include "asm/processor.h"
-#include "asm/param.h"
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <asm/processor.h>
+#include <asm/param.h>
 
 void __delay(unsigned long loops)
 {
        unsigned long i;
 
-       for(i = 0; i < loops; i++) ;
+        for(i = 0; i < loops; i++)
+                cpu_relax();
 }
 
 void __udelay(unsigned long usecs)
 {
-       int i, n;
+       unsigned long i, n;
 
        n = (loops_per_jiffy * HZ * usecs) / MILLION;
-       for(i=0;i<n;i++) ;
+        for(i=0;i<n;i++)
+                cpu_relax();
 }
 
+EXPORT_SYMBOL(__udelay);
+
 void __const_udelay(unsigned long usecs)
 {
-       int i, n;
+       unsigned long i, n;
 
        n = (loops_per_jiffy * HZ * usecs) / MILLION;
-       for(i=0;i<n;i++) ;
+        for(i=0;i<n;i++)
+                cpu_relax();
 }
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+EXPORT_SYMBOL(__const_udelay);
index a27f0ee6a4f657e3cacdb77366276862abdc5bfe..8592738082038b0b8d500408fcc0e616793e457e 100644 (file)
@@ -16,5 +16,4 @@ EXPORT_SYMBOL(__up_wakeup);
 EXPORT_SYMBOL(__memcpy);
 
 /* Networking helper routines. */
-/*EXPORT_SYMBOL(csum_partial_copy_from);
-EXPORT_SYMBOL(csum_partial_copy_to);*/
+EXPORT_SYMBOL(ip_compute_csum);
index b593bb256f2cf96d0b65ee3a76de1a1594b4af18..74eee5c7c6dd7aa3b6b79d244bb54d2cda33439a 100644 (file)
@@ -5,10 +5,11 @@
  */
 
 #define __FRAME_OFFSETS
-#include "asm/ptrace.h"
-#include "linux/sched.h"
-#include "linux/errno.h"
-#include "asm/elf.h"
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/elf.h>
 
 /* XXX x86_64 */
 unsigned long not_ss;
index dd9914642b8e905e5744d81cf712d9af9a141a84..d4a59657fb99c4601a40ff61b455e81d9e5afc2d 100644 (file)
@@ -15,6 +15,7 @@
 #include "asm/unistd.h"
 #include "asm/prctl.h" /* XXX This should get the constants from libc */
 #include "choose-mode.h"
+#include "kern.h"
 
 asmlinkage long sys_uname64(struct new_utsname __user * name)
 {
index 5e14792e48384458e075d0cf4bccf9e3bb4260c6..513d17ceafd4de4cad8a5f722837347eb038af53 100644 (file)
@@ -3,6 +3,14 @@
 #include <signal.h>
 #define __FRAME_OFFSETS
 #include <asm/ptrace.h>
+#include <asm/types.h>
+/* For some reason, x86_64 defines u64 and u32 only in <pci/types.h>, which I
+ * refuse to include here, even though they're used throughout the headers.
+ * These are used in asm/user.h, and that include can't be avoided because of
+ * the sizeof(struct user_regs_struct) below.
+ */
+typedef __u64 u64;
+typedef __u32 u32;
 #include <asm/user.h>
 
 #define DEFINE(sym, val) \
index 44ee7f6acf7b521ac9e291eb949e0257ecb5d7fd..82cb2a3f127ad84e5c7fea33abceb69a78f0e532 100644 (file)
@@ -303,6 +303,20 @@ config HPET_TIMER
          as it is off-chip.  You can find the HPET spec at
          <http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>.
 
+config X86_PM_TIMER
+       bool "PM timer"
+       default y
+       help
+         Support the ACPI PM timer for time keeping. This is slow,
+         but is useful on some chipsets without HPET on systems with more
+         than one CPU. On a single processor or single socket multi core
+         system it is normally not required.
+         When the PM timer is active 64bit vsyscalls are disabled
+         and should not be enabled (/proc/sys/kernel/vsyscall64 should
+         not be changed).
+         The kernel selects the PM timer only as a last resort, so it is
+         useful to enable just in case.
+
 config HPET_EMULATE_RTC
        bool "Provide RTC interrupt"
        depends on HPET_TIMER && RTC=y
index 9ce51dee30b301972d6d5a8b160b8bef74d17049..569595b74c7ccfc5412053959f5cd68891122848 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-bk7
-# Sat Mar 12 23:43:44 2005
+# Linux kernel version: 2.6.12-rc4
+# Fri May 13 06:39:11 2005
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -11,8 +11,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_X86_CMPXCHG=y
 CONFIG_EARLY_PRINTK=y
-CONFIG_HPET_TIMER=y
-CONFIG_HPET_EMULATE_RTC=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
 
@@ -22,6 +20,7 @@ CONFIG_GENERIC_IOMAP=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -33,7 +32,6 @@ CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=18
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
@@ -43,10 +41,11 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
@@ -93,6 +92,9 @@ CONFIG_DISCONTIGMEM=y
 CONFIG_NUMA=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_NR_CPUS=8
+CONFIG_HPET_TIMER=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
 CONFIG_GART_IOMMU=y
 CONFIG_SWIOTLB=y
 CONFIG_X86_MCE=y
@@ -100,6 +102,7 @@ CONFIG_X86_MCE_INTEL=y
 CONFIG_SECCOMP=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
 
 #
 # Power management options
@@ -129,7 +132,7 @@ CONFIG_ACPI_NUMA=y
 # CONFIG_ACPI_IBM is not set
 CONFIG_ACPI_TOSHIBA=y
 CONFIG_ACPI_BLACKLIST_YEAR=2001
-CONFIG_ACPI_DEBUG=y
+# CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_BUS=y
 CONFIG_ACPI_EC=y
 CONFIG_ACPI_POWER=y
@@ -141,6 +144,7 @@ CONFIG_ACPI_SYSTEM=y
 # CPU Frequency scaling
 #
 CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
 # CONFIG_CPU_FREQ_DEBUG is not set
 CONFIG_CPU_FREQ_STAT=y
 # CONFIG_CPU_FREQ_STAT_DETAILS is not set
@@ -150,7 +154,6 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_TABLE=y
 
 #
 # CPUFreq processor drivers
@@ -164,6 +167,7 @@ CONFIG_X86_ACPI_CPUFREQ=y
 # shared options
 #
 CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
+# CONFIG_X86_SPEEDSTEP_LIB is not set
 
 #
 # Bus options (PCI etc.)
@@ -172,19 +176,17 @@ CONFIG_PCI=y
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 CONFIG_UNORDERED_IO=y
+# CONFIG_PCIEPORTBUS is not set
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
 
-#
-# PC-card bridges
-#
-
 #
 # PCI Hotplug Support
 #
@@ -254,7 +256,7 @@ CONFIG_LBD=y
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_AS is not set
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
@@ -308,7 +310,8 @@ CONFIG_BLK_DEV_AMD74XX=y
 CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+# CONFIG_PDC202XX_FORCE is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
@@ -353,7 +356,7 @@ CONFIG_BLK_DEV_SD=y
 #
 # SCSI low-level drivers
 #
-CONFIG_BLK_DEV_3W_XXXX_RAID=y
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
@@ -384,7 +387,6 @@ CONFIG_SCSI_SATA_VIA=y
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
@@ -392,7 +394,6 @@ CONFIG_SCSI_SATA_VIA=y
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -401,6 +402,7 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -437,7 +439,6 @@ CONFIG_NET=y
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -502,7 +503,7 @@ CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=y
 
 #
 # ARCnet devices
@@ -525,8 +526,7 @@ CONFIG_MII=y
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
-CONFIG_AMD8111_ETH=y
-# CONFIG_AMD8111E_NAPI is not set
+# CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
 CONFIG_FORCEDETH=y
@@ -536,7 +536,7 @@ CONFIG_FORCEDETH=y
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
-CONFIG_8139CP=m
+CONFIG_8139CP=y
 CONFIG_8139TOO=y
 # CONFIG_8139TOO_PIO is not set
 # CONFIG_8139TOO_TUNE_TWISTER is not set
@@ -671,6 +671,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -696,6 +697,7 @@ CONFIG_RTC=y
 #
 CONFIG_AGP=y
 CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
 # CONFIG_DRM is not set
 # CONFIG_MWAVE is not set
 CONFIG_RAW_DRIVER=y
@@ -703,7 +705,7 @@ CONFIG_HPET=y
 # CONFIG_HPET_RTC_IRQ is not set
 CONFIG_HPET_MMAP=y
 CONFIG_MAX_RAW_DEVS=256
-CONFIG_HANGCHECK_TIMER=y
+# CONFIG_HANGCHECK_TIMER is not set
 
 #
 # TPM devices
@@ -786,6 +788,8 @@ CONFIG_SOUND_ICH=y
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -797,8 +801,6 @@ CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -826,7 +828,6 @@ CONFIG_USB_PRINTER=y
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -965,7 +966,7 @@ CONFIG_AUTOFS_FS=y
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
+CONFIG_JOLIET=y
 # CONFIG_ZISOFS is not set
 # CONFIG_UDF_FS is not set
 
@@ -1092,9 +1093,10 @@ CONFIG_OPROFILE=y
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_PRINTK_TIME is not set
+CONFIG_LOG_BUF_SHIFT=18
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
index 0a3318e08ab6f123e5a015f4c9cd2198c932b821..5ca4a4598fdad807b5aa0e8143c2aa55525fced2 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_GART_IOMMU)      += pci-gart.o aperture.o
 obj-$(CONFIG_DUMMY_IOMMU)      += pci-nommu.o pci-dma.o
 obj-$(CONFIG_SWIOTLB)          += swiotlb.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
+obj-$(CONFIG_X86_PM_TIMER)     += pmtimer.o
 
 obj-$(CONFIG_MODULES)          += module.o
 
index 7e13545748e0ef3378c87a23c401ba25f34d6c65..f8e6cc4fecd4887acc244fee292f401a96aac59b 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/mpspec.h>
 #include <asm/pgalloc.h>
 #include <asm/mach_apic.h>
+#include <asm/nmi.h>
 
 int apic_verbosity;
 
@@ -925,7 +926,7 @@ __init int oem_force_hpet_timer(void)
        unsigned id;
        DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
 
-       bitmap_empty(clustermap, NUM_APIC_CLUSTERS);
+       bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
 
        for (i = 0; i < NR_CPUS; i++) {
                id = bios_cpu_apicid[i];
@@ -1056,7 +1057,7 @@ int __init APIC_init_uniprocessor (void)
                nr_ioapics = 0;
 #endif
        setup_boot_APIC_clock();
-
+       check_nmi_watchdog();
        return 0;
 }
 
index 1086b5fcac21c51ad8acb01a02c6c8a6a971a8c7..28817490fdc69510a527c9974be8bb550aa2a5b6 100644 (file)
@@ -220,13 +220,18 @@ sysret_careful:
        jmp sysret_check
 
        /* Handle a signal */ 
-       /* edx: work flags (arg3) */
 sysret_signal:
        sti
+       testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
+       jz    1f
+
+       /* Really a signal */
+       /* edx: work flags (arg3) */
        leaq do_notify_resume(%rip),%rax
        leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
        xorl %esi,%esi # oldset -> arg2
        call ptregscall_common
+1:     movl $_TIF_NEED_RESCHED,%edi
        jmp sysret_check
        
        /* Do syscall tracing */
@@ -484,6 +489,8 @@ retint_careful:
        jmp retint_check
        
 retint_signal:
+       testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
+       jz    retint_swapgs
        sti
        SAVE_REST
        movq $-1,ORIG_RAX(%rsp)                         
@@ -492,8 +499,8 @@ retint_signal:
        call do_notify_resume
        RESTORE_REST
        cli
+       movl $_TIF_NEED_RESCHED,%edi
        GET_THREAD_INFO(%rcx)
-       movl $_TIF_WORK_MASK,%edi
        jmp retint_check
 
 #ifdef CONFIG_PREEMPT
index 60be58617eb977e1620beda8e363ba9cfd9fc17c..80e9b498c44343b4683e3cc0d79e4f2b42e8f727 100644 (file)
@@ -42,6 +42,8 @@
 
 int sis_apic_bug; /* not actually supported, dummy for compile */
 
+static int no_timer_check;
+
 static DEFINE_SPINLOCK(ioapic_lock);
 
 /*
@@ -1601,7 +1603,7 @@ static inline void check_timer(void)
                 * Ok, does IRQ0 through the IOAPIC work?
                 */
                unmask_IO_APIC_irq(0);
-               if (timer_irq_works()) {
+               if (!no_timer_check && timer_irq_works()) {
                        nmi_watchdog_default();
                        if (nmi_watchdog == NMI_IO_APIC) {
                                disable_8259A_irq(0);
@@ -1671,6 +1673,13 @@ static inline void check_timer(void)
        panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
 }
 
+static int __init notimercheck(char *s)
+{
+       no_timer_check = 1;
+       return 1;
+}
+__setup("no_timer_check", notimercheck);
+
 /*
  *
  * IRQ's that are handled by the PIC in the MPS IOAPIC case.
@@ -1804,76 +1813,6 @@ device_initcall(ioapic_init_sysfs);
 
 #define IO_APIC_MAX_ID         0xFE
 
-int __init io_apic_get_unique_id (int ioapic, int apic_id)
-{
-       union IO_APIC_reg_00 reg_00;
-       static physid_mask_t apic_id_map;
-       unsigned long flags;
-       int i = 0;
-
-       /*
-        * The P4 platform supports up to 256 APIC IDs on two separate APIC 
-        * buses (one for LAPICs, one for IOAPICs), where predecessors only 
-        * supports up to 16 on one shared APIC bus.
-        * 
-        * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
-        *      advantage of new APIC bus architecture.
-        */
-
-       if (physids_empty(apic_id_map))
-               apic_id_map = phys_cpu_present_map;
-
-       spin_lock_irqsave(&ioapic_lock, flags);
-       reg_00.raw = io_apic_read(ioapic, 0);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
-
-       if (apic_id >= IO_APIC_MAX_ID) {
-               apic_printk(APIC_QUIET, KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
-                       "%d\n", ioapic, apic_id, reg_00.bits.ID);
-               apic_id = reg_00.bits.ID;
-       }
-
-       /*
-        * Every APIC in a system must have a unique ID or we get lots of nice 
-        * 'stuck on smp_invalidate_needed IPI wait' messages.
-        */
-       if (physid_isset(apic_id, apic_id_map)) {
-
-               for (i = 0; i < IO_APIC_MAX_ID; i++) {
-                       if (!physid_isset(i, apic_id_map))
-                               break;
-               }
-
-               if (i == IO_APIC_MAX_ID)
-                       panic("Max apic_id exceeded!\n");
-
-               apic_printk(APIC_VERBOSE, KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
-                       "trying %d\n", ioapic, apic_id, i);
-
-               apic_id = i;
-       } 
-
-       physid_set(apic_id, apic_id_map);
-
-       if (reg_00.bits.ID != apic_id) {
-               reg_00.bits.ID = apic_id;
-
-               spin_lock_irqsave(&ioapic_lock, flags);
-               io_apic_write(ioapic, 0, reg_00.raw);
-               reg_00.raw = io_apic_read(ioapic, 0);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
-
-               /* Sanity check */
-               if (reg_00.bits.ID != apic_id)
-                       panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
-       }
-
-       apic_printk(APIC_VERBOSE,KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
-
-       return apic_id;
-}
-
-
 int __init io_apic_get_version (int ioapic)
 {
        union IO_APIC_reg_01    reg_01;
index 7ec031c6ca10fe566e444fcafcb3b1b4995887b9..f86d9db94bfcc437b378fc32024d603c449cfdf1 100644 (file)
@@ -107,6 +107,7 @@ static int __init mpf_checksum(unsigned char *mp, int len)
 static void __init MP_processor_info (struct mpc_config_processor *m)
 {
        int ver;
+       static int found_bsp=0;
 
        if (!(m->mpc_cpuflag & CPU_ENABLED))
                return;
@@ -126,11 +127,6 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
                        " Processor ignored.\n", NR_CPUS);
                return;
        }
-       if (num_processors >= maxcpus) {
-               printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
-                       " Processor ignored.\n", maxcpus);
-               return;
-       }
 
        num_processors++;
 
@@ -150,7 +146,19 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
                ver = 0x10;
        }
        apic_version[m->mpc_apicid] = ver;
-       bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
+       if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+               /*
+                * bios_cpu_apicid is required to have processors listed
+                * in same order as logical cpu numbers. Hence the first
+                * entry is BSP, and so on.
+                */
+               bios_cpu_apicid[0] = m->mpc_apicid;
+               x86_cpu_to_apicid[0] = m->mpc_apicid;
+               found_bsp = 1;
+       } else {
+               bios_cpu_apicid[num_processors - found_bsp] = m->mpc_apicid;
+               x86_cpu_to_apicid[num_processors - found_bsp] = m->mpc_apicid;
+       }
 }
 
 static void __init MP_bus_info (struct mpc_config_bus *m)
@@ -759,7 +767,7 @@ void __init mp_register_ioapic (
        mp_ioapics[idx].mpc_apicaddr = address;
 
        set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
-       mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
+       mp_ioapics[idx].mpc_apicid = id;
        mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
        
        /* 
index 61de0b34a01e850fedb824115b2e0560ed98ff59..31c0f2e6ac916c8f1cd93f025cf3182b92f1fa3e 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/msr.h>
 #include <asm/proto.h>
 #include <asm/kdebug.h>
+#include <asm/local.h>
 
 /*
  * lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
@@ -59,7 +60,8 @@ int panic_on_timeout;
 
 unsigned int nmi_watchdog = NMI_DEFAULT;
 static unsigned int nmi_hz = HZ;
-unsigned int nmi_perfctr_msr;  /* the MSR to reset in NMI handler */
+static unsigned int nmi_perfctr_msr;   /* the MSR to reset in NMI handler */
+static unsigned int nmi_p4_cccr_val;
 
 /* Note that these events don't tick when the CPU idles. This means
    the frequency varies with CPU load. */
@@ -71,61 +73,87 @@ unsigned int nmi_perfctr_msr;       /* the MSR to reset in NMI handler */
 #define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING   0x76
 #define K7_NMI_EVENT           K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
 
-#define P6_EVNTSEL0_ENABLE     (1 << 22)
-#define P6_EVNTSEL_INT         (1 << 20)
-#define P6_EVNTSEL_OS          (1 << 17)
-#define P6_EVNTSEL_USR         (1 << 16)
-#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
-#define P6_NMI_EVENT           P6_EVENT_CPU_CLOCKS_NOT_HALTED
+#define MSR_P4_MISC_ENABLE     0x1A0
+#define MSR_P4_MISC_ENABLE_PERF_AVAIL  (1<<7)
+#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL        (1<<12)
+#define MSR_P4_PERFCTR0                0x300
+#define MSR_P4_CCCR0           0x360
+#define P4_ESCR_EVENT_SELECT(N)        ((N)<<25)
+#define P4_ESCR_OS             (1<<3)
+#define P4_ESCR_USR            (1<<2)
+#define P4_CCCR_OVF_PMI0       (1<<26)
+#define P4_CCCR_OVF_PMI1       (1<<27)
+#define P4_CCCR_THRESHOLD(N)   ((N)<<20)
+#define P4_CCCR_COMPLEMENT     (1<<19)
+#define P4_CCCR_COMPARE                (1<<18)
+#define P4_CCCR_REQUIRED       (3<<16)
+#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
+#define P4_CCCR_ENABLE         (1<<12)
+/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+   CRU_ESCR0 (with any non-null event selector) through a complemented
+   max threshold. [IA32-Vol3, Section 14.9.9] */
+#define MSR_P4_IQ_COUNTER0     0x30C
+#define P4_NMI_CRU_ESCR0       (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
+#define P4_NMI_IQ_CCCR0        \
+       (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|     \
+        P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
+
+static __init inline int nmi_known_cpu(void)
+{
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_AMD:
+               return boot_cpu_data.x86 == 15;
+       case X86_VENDOR_INTEL:
+               return boot_cpu_data.x86 == 15;
+       }
+       return 0;
+}
 
 /* Run after command line and cpu_init init, but before all other checks */
 void __init nmi_watchdog_default(void)
 {
        if (nmi_watchdog != NMI_DEFAULT)
                return;
-
-       /* For some reason the IO APIC watchdog doesn't work on the AMD
-          8111 chipset. For now switch to local APIC mode using
-          perfctr0 there.  On Intel CPUs we don't have code to handle
-          the perfctr and the IO-APIC seems to work, so use that.  */
-
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
-               nmi_watchdog = NMI_LOCAL_APIC; 
-               printk(KERN_INFO 
-              "Using local APIC NMI watchdog using perfctr0\n");
-       } else {
-               printk(KERN_INFO "Using IO APIC NMI watchdog\n");
+       if (nmi_known_cpu())
+               nmi_watchdog = NMI_LOCAL_APIC;
+       else
                nmi_watchdog = NMI_IO_APIC;
-       }
 }
 
-/* Why is there no CPUID flag for this? */
-static __init int cpu_has_lapic(void)
+#ifdef CONFIG_SMP
+/* The performance counters used by NMI_LOCAL_APIC don't trigger when
+ * the CPU is idle. To make sure the NMI watchdog really ticks on all
+ * CPUs during the test make them busy.
+ */
+static __init void nmi_cpu_busy(void *data)
 {
-       switch (boot_cpu_data.x86_vendor) { 
-       case X86_VENDOR_INTEL:
-       case X86_VENDOR_AMD: 
-               return boot_cpu_data.x86 >= 6; 
-       /* .... add more cpus here or find a different way to figure this out. */       
-       default:
-               return 0;
-       }       
+       volatile int *endflag = data;
+       local_irq_enable();
+       /* Intentionally don't use cpu_relax here. This is
+          to make sure that the performance counter really ticks,
+          even if there is a simulator or similar that catches the
+          pause instruction. On a real HT machine this is fine because
+          all other CPUs are busy with "useless" delay loops and don't
+          care if they get somewhat less cycles. */
+       while (*endflag == 0)
+               barrier();
 }
+#endif
 
-static int __init check_nmi_watchdog (void)
+int __init check_nmi_watchdog (void)
 {
-       int counts[NR_CPUS];
+       volatile int endflag = 0;
+       int *counts;
        int cpu;
 
-       if (nmi_watchdog == NMI_NONE)
-               return 0;
+       counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
+       if (!counts)
+               return -1;
 
-       if (nmi_watchdog == NMI_LOCAL_APIC && !cpu_has_lapic())  {
-               nmi_watchdog = NMI_NONE;
-               return -1; 
-       }       
+       printk(KERN_INFO "testing NMI watchdog ... ");
 
-       printk(KERN_INFO "Testing NMI watchdog ... ");
+       if (nmi_watchdog == NMI_LOCAL_APIC)
+               smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0);
 
        for (cpu = 0; cpu < NR_CPUS; cpu++)
                counts[cpu] = cpu_pda[cpu].__nmi_count; 
@@ -133,15 +161,22 @@ static int __init check_nmi_watchdog (void)
        mdelay((10*1000)/nmi_hz); // wait 10 ticks
 
        for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               if (!cpu_online(cpu))
+                       continue;
                if (cpu_pda[cpu].__nmi_count - counts[cpu] <= 5) {
-                       printk("CPU#%d: NMI appears to be stuck (%d)!\n", 
+                       endflag = 1;
+                       printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
                               cpu,
+                              counts[cpu],
                               cpu_pda[cpu].__nmi_count);
                        nmi_active = 0;
                        lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
+                       nmi_perfctr_msr = 0;
+                       kfree(counts);
                        return -1;
                }
        }
+       endflag = 1;
        printk("OK.\n");
 
        /* now that we know it works we can reduce NMI frequency to
@@ -149,10 +184,9 @@ static int __init check_nmi_watchdog (void)
        if (nmi_watchdog == NMI_LOCAL_APIC)
                nmi_hz = 1;
 
+       kfree(counts);
        return 0;
 }
-/* Have this called later during boot so counters are updating */
-late_initcall(check_nmi_watchdog);
 
 int __init setup_nmi_watchdog(char *str)
 {
@@ -170,7 +204,7 @@ int __init setup_nmi_watchdog(char *str)
 
        if (nmi >= NMI_INVALID)
                return 0;
-               nmi_watchdog = nmi;
+       nmi_watchdog = nmi;
        return 1;
 }
 
@@ -185,7 +219,10 @@ static void disable_lapic_nmi_watchdog(void)
                wrmsr(MSR_K7_EVNTSEL0, 0, 0);
                break;
        case X86_VENDOR_INTEL:
-               wrmsr(MSR_IA32_EVNTSEL0, 0, 0);
+               if (boot_cpu_data.x86 == 15) {
+                       wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
+                       wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
+               }
                break;
        }
        nmi_active = -1;
@@ -253,7 +290,7 @@ void enable_timer_nmi_watchdog(void)
 
 static int nmi_pm_active; /* nmi_active before suspend */
 
-static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
+static int lapic_nmi_suspend(struct sys_device *dev, u32 state)
 {
        nmi_pm_active = nmi_active;
        disable_lapic_nmi_watchdog();
@@ -300,22 +337,27 @@ late_initcall(init_lapic_nmi_sysfs);
  * Original code written by Keith Owens.
  */
 
+static void clear_msr_range(unsigned int base, unsigned int n)
+{
+       unsigned int i;
+
+       for(i = 0; i < n; ++i)
+               wrmsr(base+i, 0, 0);
+}
+
 static void setup_k7_watchdog(void)
 {
        int i;
        unsigned int evntsel;
 
-       /* No check, so can start with slow frequency */
-       nmi_hz = 1; 
-
-       /* XXX should check these in EFER */
-
        nmi_perfctr_msr = MSR_K7_PERFCTR0;
 
        for(i = 0; i < 4; ++i) {
                /* Simulator may not support it */
-               if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL))
+               if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL)) {
+                       nmi_perfctr_msr = 0;
                        return;
+               }
                wrmsrl(MSR_K7_PERFCTR0+i, 0UL);
        }
 
@@ -325,12 +367,54 @@ static void setup_k7_watchdog(void)
                | K7_NMI_EVENT;
 
        wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
-       wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz*1000) / nmi_hz);
+       wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
        apic_write(APIC_LVTPC, APIC_DM_NMI);
        evntsel |= K7_EVNTSEL_ENABLE;
        wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
 }
 
+
+static int setup_p4_watchdog(void)
+{
+       unsigned int misc_enable, dummy;
+
+       rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
+       if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
+               return 0;
+
+       nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
+       nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
+#ifdef CONFIG_SMP
+       if (smp_num_siblings == 2)
+               nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
+#endif
+
+       if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
+               clear_msr_range(0x3F1, 2);
+       /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
+          docs doesn't fully define it, so leave it alone for now. */
+       if (boot_cpu_data.x86_model >= 0x3) {
+               /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
+               clear_msr_range(0x3A0, 26);
+               clear_msr_range(0x3BC, 3);
+       } else {
+               clear_msr_range(0x3A0, 31);
+       }
+       clear_msr_range(0x3C0, 6);
+       clear_msr_range(0x3C8, 6);
+       clear_msr_range(0x3E0, 2);
+       clear_msr_range(MSR_P4_CCCR0, 18);
+       clear_msr_range(MSR_P4_PERFCTR0, 18);
+
+       wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
+       wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
+       Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
+       wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+       wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
+       return 1;
+}
+
 void setup_apic_nmi_watchdog(void)
 {
        switch (boot_cpu_data.x86_vendor) {
@@ -341,6 +425,13 @@ void setup_apic_nmi_watchdog(void)
                        return;
                setup_k7_watchdog();
                break;
+       case X86_VENDOR_INTEL:
+               if (boot_cpu_data.x86 != 15)
+                       return;
+               if (!setup_p4_watchdog())
+                       return;
+               break;
+
        default:
                return;
        }
@@ -355,56 +446,67 @@ void setup_apic_nmi_watchdog(void)
  *
  * as these watchdog NMI IRQs are generated on every CPU, we only
  * have to check the current processor.
- *
- * since NMIs don't listen to _any_ locks, we have to be extremely
- * careful not to rely on unsafe variables. The printk might lock
- * up though, so we have to break up any console locks first ...
- * [when there will be more tty-related locks, break them up
- *  here too!]
  */
 
-static unsigned int
-       last_irq_sums [NR_CPUS],
-       alert_counter [NR_CPUS];
+static DEFINE_PER_CPU(unsigned, last_irq_sum);
+static DEFINE_PER_CPU(local_t, alert_counter);
+static DEFINE_PER_CPU(int, nmi_touch);
 
 void touch_nmi_watchdog (void)
 {
        int i;
 
        /*
-        * Just reset the alert counters, (other CPUs might be
-        * spinning on locks we hold):
+        * Tell other CPUs to reset their alert counters. We cannot
+        * do it ourselves because the alert count increase is not
+        * atomic.
         */
        for (i = 0; i < NR_CPUS; i++)
-               alert_counter[i] = 0;
+               per_cpu(nmi_touch, i) = 1;
 }
 
 void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
 {
-       int sum, cpu;
+       int sum;
+       int touched = 0;
 
-       cpu = safe_smp_processor_id();
        sum = read_pda(apic_timer_irqs);
-       if (last_irq_sums[cpu] == sum) {
+       if (__get_cpu_var(nmi_touch)) {
+               __get_cpu_var(nmi_touch) = 0;
+               touched = 1;
+       }
+       if (!touched && __get_cpu_var(last_irq_sum) == sum) {
                /*
                 * Ayiee, looks like this CPU is stuck ...
                 * wait a few IRQs (5 seconds) before doing the oops ...
                 */
-               alert_counter[cpu]++;
-               if (alert_counter[cpu] == 5*nmi_hz) {
+               local_inc(&__get_cpu_var(alert_counter));
+               if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz) {
                        if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
                                                        == NOTIFY_STOP) {
-                               alert_counter[cpu] = 0; 
+                               local_set(&__get_cpu_var(alert_counter), 0);
                                return;
                        } 
                        die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs);
                }
        } else {
-               last_irq_sums[cpu] = sum;
-               alert_counter[cpu] = 0;
+               __get_cpu_var(last_irq_sum) = sum;
+               local_set(&__get_cpu_var(alert_counter), 0);
        }
-       if (nmi_perfctr_msr)
+       if (nmi_perfctr_msr) {
+               if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
+                       /*
+                        * P4 quirks:
+                        * - An overflown perfctr will assert its interrupt
+                        *   until the OVF flag in its CCCR is cleared.
+                        * - LVTPC is masked on interrupt and must be
+                        *   unmasked by the LVTPC handler.
+                        */
+                       wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
+                       apic_write(APIC_LVTPC, APIC_DM_NMI);
+               }
                wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+       }
 }
 
 static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c
new file mode 100644 (file)
index 0000000..feb5f10
--- /dev/null
@@ -0,0 +1,101 @@
+/* Ported over from i386 by AK, original copyright was:
+ *
+ * (C) Dominik Brodowski <linux@brodo.de> 2003
+ *
+ * Driver to use the Power Management Timer (PMTMR) available in some
+ * southbridges as primary timing source for the Linux kernel.
+ *
+ * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
+ * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
+ *
+ * This file is licensed under the GPL v2.
+ *
+ * Dropped all the hardware bug workarounds for now. Hopefully they
+ * are not needed on 64bit chipsets.
+ */
+
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/cpumask.h>
+#include <asm/io.h>
+#include <asm/proto.h>
+#include <asm/msr.h>
+#include <asm/vsyscall.h>
+
+/* The I/O port the PMTMR resides at.
+ * The location is detected during setup_arch(),
+ * in arch/i386/kernel/acpi/boot.c */
+u32 pmtmr_ioport;
+
+/* value of the Power timer at last timer interrupt */
+static u32 offset_delay;
+static u32 last_pmtmr_tick;
+
+#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
+
+static inline u32 cyc2us(u32 cycles)
+{
+       /* The Power Management Timer ticks at 3.579545 ticks per microsecond.
+        * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
+        *
+        * Even with HZ = 100, delta is at maximum 35796 ticks, so it can
+        * easily be multiplied with 286 (=0x11E) without having to fear
+        * u32 overflows.
+        */
+       cycles *= 286;
+       return (cycles >> 10);
+}
+
+int pmtimer_mark_offset(void)
+{
+       static int first_run = 1;
+       unsigned long tsc;
+       u32 lost;
+
+       u32 tick = inl(pmtmr_ioport);
+       u32 delta;
+
+       delta = cyc2us((tick - last_pmtmr_tick) & ACPI_PM_MASK);
+
+       last_pmtmr_tick = tick;
+       monotonic_base += delta * NSEC_PER_USEC;
+
+       delta += offset_delay;
+
+       lost = delta / (USEC_PER_SEC / HZ);
+       offset_delay = delta % (USEC_PER_SEC / HZ);
+
+       rdtscll(tsc);
+       vxtime.last_tsc = tsc - offset_delay * cpu_khz;
+
+       /* don't calculate delay for first run,
+          or if we've got less then a tick */
+       if (first_run || (lost < 1)) {
+               first_run = 0;
+               offset_delay = 0;
+       }
+
+       return lost - 1;
+}
+
+unsigned int do_gettimeoffset_pm(void)
+{
+       u32 now, offset, delta = 0;
+
+       offset = last_pmtmr_tick;
+       now = inl(pmtmr_ioport);
+       delta = (now - offset) & ACPI_PM_MASK;
+
+       return offset_delay + cyc2us(delta);
+}
+
+
+static int __init nopmtimer_setup(char *s)
+{
+       pmtmr_ioport = 0;
+       return 0;
+}
+
+__setup("nopmtimer", nopmtimer_setup);
index e26e86bb56fe53381e2016e4f478dbdc37ec0294..525f6a128a279c0f559392af0b962de4101e46e8 100644 (file)
@@ -257,13 +257,13 @@ static int putreg(struct task_struct *child,
                        value &= 0xffff;
                        return 0;
                case offsetof(struct user_regs_struct,fs_base):
-                       if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
-                               return -EIO; 
+                       if (value >= TASK_SIZE)
+                               return -EIO;
                        child->thread.fs = value;
                        return 0;
                case offsetof(struct user_regs_struct,gs_base):
-                       if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
-                               return -EIO; 
+                       if (value >= TASK_SIZE)
+                               return -EIO;
                        child->thread.gs = value;
                        return 0;
                case offsetof(struct user_regs_struct, eflags):
@@ -277,6 +277,11 @@ static int putreg(struct task_struct *child,
                                return -EIO;
                        value &= 0xffff;
                        break;
+               case offsetof(struct user_regs_struct, rip):
+                       /* Check if the new RIP address is canonical */
+                       if (value >= TASK_SIZE)
+                               return -EIO;
+                       break;
        }
        put_stack_long(child, regno - sizeof(struct pt_regs), value);
        return 0;
@@ -375,7 +380,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
                        break;
 
                switch (addr) { 
-               case 0 ... sizeof(struct user_regs_struct):
+               case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
                        tmp = getreg(child, addr);
                        break;
                case offsetof(struct user, u_debugreg[0]):
@@ -420,7 +425,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
                        break;
 
                switch (addr) { 
-               case 0 ... sizeof(struct user_regs_struct)
+               case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
                        ret = putreg(child, addr, data);
                        break;
                /* Disallows to set a breakpoint into the vsyscall */
index 2129cf9ba6b2fc066194474c058f821eefe22f4c..99f038ede23c323d98eca770b17344f4bc97838d 100644 (file)
@@ -719,7 +719,6 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
        }
 }
 
-#ifdef CONFIG_SMP
 /*
  * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
  * Assumes number of cores is a power of two.
@@ -727,17 +726,26 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
 static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
-       int cpu = c->x86_apicid;
+       int cpu = smp_processor_id();
        int node = 0;
+       unsigned bits;
        if (c->x86_num_cores == 1)
                return;
-       cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
+
+       bits = 0;
+       while ((1 << bits) < c->x86_num_cores)
+               bits++;
+
+       /* Low order bits define the core id (index of core in socket) */
+       cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
+       /* Convert the APIC ID into the socket ID */
+       phys_proc_id[cpu] >>= bits;
 
 #ifdef CONFIG_NUMA
        /* When an ACPI SRAT table is available use the mappings from SRAT
           instead. */
        if (acpi_numa <= 0) {
-               node = cpu_core_id[cpu];
+               node = phys_proc_id[cpu];
                if (!node_online(node))
                        node = first_node(node_online_map);
                cpu_to_node[cpu] = node;
@@ -745,15 +753,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
                node = cpu_to_node[cpu];
        }
 #endif
+
        printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
                        cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
 #endif
 }
-#else
-static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
-{
-}
-#endif
 
 static int __init init_amd(struct cpuinfo_x86 *c)
 {
@@ -925,7 +929,6 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
        c->x86_clflush_size = 64;
        c->x86_cache_alignment = c->x86_clflush_size;
        c->x86_num_cores = 1;
-       c->x86_apicid = c == &boot_cpu_data ? 0 : c - cpu_data;
        c->extended_cpuid_level = 0;
        memset(&c->x86_capability, 0, sizeof c->x86_capability);
 
@@ -954,11 +957,14 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
                } 
                if (c->x86_capability[0] & (1<<19)) 
                        c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
-               c->x86_apicid = misc >> 24;
        } else {
                /* Have CPUID level 0 only - unheard of */
                c->x86 = 4;
        }
+
+#ifdef CONFIG_SMP
+       phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+#endif
 }
 
 /*
@@ -1088,7 +1094,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* Other (Linux-defined) */
-               "cxmmx", NULL, "cyrix_arr", "centaur_mcr", "k8c+",
+               "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
                "constant_tsc", NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
index d439ced150c603c33cbc2220bec5532654822b86..3fdcdba0fec5f8ebf758170f4a62b1d3f41135e8 100644 (file)
@@ -452,7 +452,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                        regs->rip -= 2;
                }
                if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) {
-                       regs->rax = __NR_restart_syscall;
+                       regs->rax = test_thread_flag(TIF_IA32) ?
+                                       __NR_ia32_restart_syscall :
+                                       __NR_restart_syscall;
                        regs->rip -= 2;
                }
        }
index 73f7e8b9543aa55051e6a912e231db6ad6c8aa3b..f1ec0f34594124f73feb76dcf0f270dc420dfca5 100644 (file)
@@ -56,6 +56,7 @@
 #include <asm/kdebug.h>
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
+#include <asm/nmi.h>
 
 /* Change for real CPU hotplug. Note other files need to be fixed
    first too. */
@@ -93,6 +94,7 @@ int smp_threads_ready;
 
 cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
 cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_core_map);
 
 /*
  * Trampoline 80x86 program as an array.
@@ -125,96 +127,210 @@ static void __cpuinit smp_store_cpu_info(int id)
 
        *c = boot_cpu_data;
        identify_cpu(c);
+       print_cpu_info(c);
 }
 
 /*
- * Synchronize TSCs of CPUs
+ * New Funky TSC sync algorithm borrowed from IA64.
+ * Main advantage is that it doesn't reset the TSCs fully and
+ * in general looks more robust and it works better than my earlier
+ * attempts. I believe it was written by David Mosberger. Some minor
+ * adjustments for x86-64 by me -AK
  *
- * This new algorithm is less accurate than the old "zero TSCs"
- * one, but we cannot zero TSCs anymore in the new hotplug CPU
- * model.
+ * Original comment reproduced below.
+ *
+ * Synchronize TSC of the current (slave) CPU with the TSC of the
+ * MASTER CPU (normally the time-keeper CPU).  We use a closed loop to
+ * eliminate the possibility of unaccounted-for errors (such as
+ * getting a machine check in the middle of a calibration step).  The
+ * basic idea is for the slave to ask the master what itc value it has
+ * and to read its own itc before and after the master responds.  Each
+ * iteration gives us three timestamps:
+ *
+ *     slave           master
+ *
+ *     t0 ---\
+ *             ---\
+ *                --->
+ *                     tm
+ *                /---
+ *            /---
+ *     t1 <---
+ *
+ *
+ * The goal is to adjust the slave's TSC such that tm falls exactly
+ * half-way between t0 and t1.  If we achieve this, the clocks are
+ * synchronized provided the interconnect between the slave and the
+ * master is symmetric.  Even if the interconnect were asymmetric, we
+ * would still know that the synchronization error is smaller than the
+ * roundtrip latency (t0 - t1).
+ *
+ * When the interconnect is quiet and symmetric, this lets us
+ * synchronize the TSC to within one or two cycles.  However, we can
+ * only *guarantee* that the synchronization is accurate to within a
+ * round-trip time, which is typically in the range of several hundred
+ * cycles (e.g., ~500 cycles).  In practice, this means that the TSCs
+ * are usually almost perfectly synchronized, but we shouldn't assume
+ * that the accuracy is much better than half a micro second or so.
+ *
+ * [there are other errors like the latency of RDTSC and of the
+ * WRMSR. These can also account to hundreds of cycles. So it's
+ * probably worse. It claims 153 cycles error on a dual Opteron,
+ * but I suspect the numbers are actually somewhat worse -AK]
  */
 
-static atomic_t __cpuinitdata tsc_flag;
+#define MASTER 0
+#define SLAVE  (SMP_CACHE_BYTES/8)
+
+/* Intentionally don't use cpu_relax() while TSC synchronization
+   because we don't want to go into funky power save modi or cause
+   hypervisors to schedule us away.  Going to sleep would likely affect
+   latency and low latency is the primary objective here. -AK */
+#define no_cpu_relax() barrier()
+
 static __cpuinitdata DEFINE_SPINLOCK(tsc_sync_lock);
-static unsigned long long __cpuinitdata bp_tsc, ap_tsc;
+static volatile __cpuinitdata unsigned long go[SLAVE + 1];
+static int notscsync __cpuinitdata;
+
+#undef DEBUG_TSC_SYNC
 
-#define NR_LOOPS 5
+#define NUM_ROUNDS     64      /* magic value */
+#define NUM_ITERS      5       /* likewise */
 
-static void __cpuinit sync_tsc_bp_init(int init)
+/* Callback on boot CPU */
+static __cpuinit void sync_master(void *arg)
 {
-       if (init)
-               _raw_spin_lock(&tsc_sync_lock);
-       else
-               _raw_spin_unlock(&tsc_sync_lock);
-       atomic_set(&tsc_flag, 0);
+       unsigned long flags, i;
+
+       if (smp_processor_id() != boot_cpu_id)
+               return;
+
+       go[MASTER] = 0;
+
+       local_irq_save(flags);
+       {
+               for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
+                       while (!go[MASTER])
+                               no_cpu_relax();
+                       go[MASTER] = 0;
+                       rdtscll(go[SLAVE]);
+               }
+       }
+       local_irq_restore(flags);
 }
 
 /*
- * Synchronize TSC on AP with BP.
+ * Return the number of cycles by which our tsc differs from the tsc
+ * on the master (time-keeper) CPU.  A positive number indicates our
+ * tsc is ahead of the master, negative that it is behind.
  */
-static void __cpuinit __sync_tsc_ap(void)
+static inline long
+get_delta(long *rt, long *master)
 {
-       if (!cpu_has_tsc)
-               return;
-       Dprintk("AP %d syncing TSC\n", smp_processor_id());
+       unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
+       unsigned long tcenter, t0, t1, tm;
+       int i;
 
-       while (atomic_read(&tsc_flag) != 0)
-               cpu_relax();
-       atomic_inc(&tsc_flag);
-       mb();
-       _raw_spin_lock(&tsc_sync_lock);
-       wrmsrl(MSR_IA32_TSC, bp_tsc);
-       _raw_spin_unlock(&tsc_sync_lock);
-       rdtscll(ap_tsc);
-       mb();
-       atomic_inc(&tsc_flag);
-       mb();
+       for (i = 0; i < NUM_ITERS; ++i) {
+               rdtscll(t0);
+               go[MASTER] = 1;
+               while (!(tm = go[SLAVE]))
+                       no_cpu_relax();
+               go[SLAVE] = 0;
+               rdtscll(t1);
+
+               if (t1 - t0 < best_t1 - best_t0)
+                       best_t0 = t0, best_t1 = t1, best_tm = tm;
+       }
+
+       *rt = best_t1 - best_t0;
+       *master = best_tm - best_t0;
+
+       /* average best_t0 and best_t1 without overflow: */
+       tcenter = (best_t0/2 + best_t1/2);
+       if (best_t0 % 2 + best_t1 % 2 == 2)
+               ++tcenter;
+       return tcenter - best_tm;
 }
 
-static void __cpuinit sync_tsc_ap(void)
+static __cpuinit void sync_tsc(void)
 {
-       int i;
-       for (i = 0; i < NR_LOOPS; i++)
-               __sync_tsc_ap();
+       int i, done = 0;
+       long delta, adj, adjust_latency = 0;
+       unsigned long flags, rt, master_time_stamp, bound;
+#if DEBUG_TSC_SYNC
+       static struct syncdebug {
+               long rt;        /* roundtrip time */
+               long master;    /* master's timestamp */
+               long diff;      /* difference between midpoint and master's timestamp */
+               long lat;       /* estimate of tsc adjustment latency */
+       } t[NUM_ROUNDS] __cpuinitdata;
+#endif
+
+       go[MASTER] = 1;
+
+       smp_call_function(sync_master, NULL, 1, 0);
+
+       while (go[MASTER])      /* wait for master to be ready */
+               no_cpu_relax();
+
+       spin_lock_irqsave(&tsc_sync_lock, flags);
+       {
+               for (i = 0; i < NUM_ROUNDS; ++i) {
+                       delta = get_delta(&rt, &master_time_stamp);
+                       if (delta == 0) {
+                               done = 1;       /* let's lock on to this... */
+                               bound = rt;
+                       }
+
+                       if (!done) {
+                               unsigned long t;
+                               if (i > 0) {
+                                       adjust_latency += -delta;
+                                       adj = -delta + adjust_latency/4;
+                               } else
+                                       adj = -delta;
+
+                               rdtscll(t);
+                               wrmsrl(MSR_IA32_TSC, t + adj);
+                       }
+#if DEBUG_TSC_SYNC
+                       t[i].rt = rt;
+                       t[i].master = master_time_stamp;
+                       t[i].diff = delta;
+                       t[i].lat = adjust_latency/4;
+#endif
+               }
+       }
+       spin_unlock_irqrestore(&tsc_sync_lock, flags);
+
+#if DEBUG_TSC_SYNC
+       for (i = 0; i < NUM_ROUNDS; ++i)
+               printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
+                      t[i].rt, t[i].master, t[i].diff, t[i].lat);
+#endif
+
+       printk(KERN_INFO
+              "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, "
+              "maxerr %lu cycles)\n",
+              smp_processor_id(), boot_cpu_id, delta, rt);
 }
 
-/*
- * Synchronize TSC from BP to AP.
- */
-static void __cpuinit __sync_tsc_bp(int cpu)
+static void __cpuinit tsc_sync_wait(void)
 {
-       if (!cpu_has_tsc)
+       if (notscsync || !cpu_has_tsc)
                return;
-
-       /* Wait for AP */
-       while (atomic_read(&tsc_flag) == 0)
-               cpu_relax();
-       /* Save BPs TSC */
-       sync_core();
-       rdtscll(bp_tsc);
-       /* Don't do the sync core here to avoid too much latency. */
-       mb();
-       /* Start the AP */
-       _raw_spin_unlock(&tsc_sync_lock);
-       /* Wait for AP again */
-       while (atomic_read(&tsc_flag) < 2)
-               cpu_relax();
-       rdtscl(bp_tsc);
-       barrier();
+       printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n", smp_processor_id(),
+                       boot_cpu_id);
+       sync_tsc();
 }
 
-static void __cpuinit sync_tsc_bp(int cpu)
+static __init int notscsync_setup(char *s)
 {
-       int i;
-       for (i = 0; i < NR_LOOPS - 1; i++) {
-               __sync_tsc_bp(cpu);
-               sync_tsc_bp_init(1);
-       }
-       __sync_tsc_bp(cpu);
-       printk(KERN_INFO "Synced TSC of CPU %d difference %Ld\n",
-              cpu, ap_tsc - bp_tsc);
+       notscsync = 1;
+       return 0;
 }
+__setup("notscsync", notscsync_setup);
 
 static atomic_t init_deasserted __cpuinitdata;
 
@@ -315,11 +431,6 @@ void __cpuinit start_secondary(void)
        cpu_init();
        smp_callin();
 
-       /*
-        * Synchronize the TSC with the BP
-        */
-       sync_tsc_ap();
-
        /* otherwise gcc will move up the smp_processor_id before the cpu_init */
        barrier();
 
@@ -334,7 +445,6 @@ void __cpuinit start_secondary(void)
                enable_8259A_irq(0);
        }
 
-
        enable_APIC_timer();
 
        /*
@@ -343,6 +453,11 @@ void __cpuinit start_secondary(void)
        cpu_set(smp_processor_id(), cpu_online_map);
        mb();
 
+       /* Wait for TSC sync to not schedule things before.
+          We still process interrupts, which could see an inconsistent
+          time in that window unfortunately. */
+       tsc_sync_wait();
+
        cpu_idle();
 }
 
@@ -531,7 +646,6 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
                printk("failed fork for CPU %d\n", cpu);
                return PTR_ERR(idle);
        }
-       x86_cpu_to_apicid[cpu] = apicid;
 
        cpu_pda[cpu].pcurrent = idle;
 
@@ -600,8 +714,6 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
 
                if (cpu_isset(cpu, cpu_callin_map)) {
                        /* number CPUs logically, starting from 1 (BSP is 0) */
-                       Dprintk("OK.\n");
-                       print_cpu_info(&cpu_data[cpu]);
                        Dprintk("CPU has booted.\n");
                } else {
                        boot_error = 1;
@@ -842,7 +954,6 @@ void __cpuinit smp_prepare_cpus(unsigned int max_cpus)
                      GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
                /* Or can we switch back to PIC here? */
        }
-       x86_cpu_to_apicid[0] = boot_cpu_id;
 
        /*
         * Now start the IO-APICs
@@ -889,18 +1000,14 @@ int __cpuinit __cpu_up(unsigned int cpu)
                printk("__cpu_up: bad cpu %d\n", cpu);
                return -EINVAL;
        }
-       sync_tsc_bp_init(1);
 
        /* Boot it! */
        err = do_boot_cpu(cpu, apicid);
        if (err < 0) {
-               sync_tsc_bp_init(0);
                Dprintk("do_boot_cpu failed %d\n", err);
                return err;
        }
 
-       sync_tsc_bp(cpu);
-
        /* Unleash the CPU! */
        Dprintk("waiting for cpu %d\n", cpu);
 
@@ -923,4 +1030,6 @@ void __cpuinit smp_cpus_done(unsigned int max_cpus)
 
        detect_siblings();
        time_init_gtod();
+
+       check_nmi_watchdog();
 }
index 0e3b60e1ac5b54f60d4a2a7cff4492c8ddef9774..735b6767c8ed78eda64acda6cba265cbfc8df44e 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/sysdev.h>
 #include <linux/bcd.h>
 #include <linux/kallsyms.h>
+#include <linux/acpi.h>
+#include <acpi/achware.h>      /* for PM timer frequency */
 #include <asm/8253pit.h>
 #include <asm/pgtable.h>
 #include <asm/vsyscall.h>
@@ -396,6 +398,10 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick;
 
                vxtime.last = offset;
+#ifdef CONFIG_X86_PM_TIMER
+       } else if (vxtime.mode == VXTIME_PMTMR) {
+               lost = pmtimer_mark_offset();
+#endif
        } else {
                offset = (((tsc - vxtime.last_tsc) *
                           vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ);
@@ -898,6 +904,13 @@ void __init time_init(void)
                        hpet_period;
                cpu_khz = hpet_calibrate_tsc();
                timename = "HPET";
+#ifdef CONFIG_X86_PM_TIMER
+       } else if (pmtmr_ioport) {
+               vxtime_hz = PM_TIMER_FREQUENCY;
+               timename = "PM";
+               pit_init();
+               cpu_khz = pit_calibrate_tsc();
+#endif
        } else {
                pit_init();
                cpu_khz = pit_calibrate_tsc();
@@ -922,6 +935,27 @@ void __init time_init(void)
 #endif
 }
 
+/*
+ * Make an educated guess if the TSC is trustworthy and synchronized
+ * over all CPUs.
+ */
+static __init int unsynchronized_tsc(void)
+{
+#ifdef CONFIG_SMP
+       if (oem_force_hpet_timer())
+               return 1;
+       /* Intel systems are normally all synchronized. Exceptions
+          are handled in the OEM check above. */
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+               return 0;
+       /* All in a single socket - should be synchronized */
+       if (cpus_weight(cpu_core_map[0]) == num_online_cpus())
+               return 0;
+#endif
+       /* Assume multi socket systems are not synchronized */
+       return num_online_cpus() > 1;
+}
+
 /*
  * Decide after all CPUs are booted what mode gettimeofday should use.
  */
@@ -929,29 +963,23 @@ void __init time_init_gtod(void)
 {
        char *timetype;
 
-       /*
-        * AMD systems with more than one CPU don't have fully synchronized
-        * TSCs. Always use HPET gettimeofday for these, although it is slower.
-        * Intel SMP systems usually have synchronized TSCs, so use always
-        * the TSC.
-        *
-        * Exceptions:
-        * IBM Summit2 checked by oem_force_hpet_timer().
-        * AMD dual core may also not need HPET. Check me.
-        *
-        * Can be turned off with "notsc".
-        */
-       if (num_online_cpus() > 1 &&
-           boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-               notsc = 1;
-       /* Some systems will want to disable TSC and use HPET. */
-       if (oem_force_hpet_timer())
+       if (unsynchronized_tsc())
                notsc = 1;
        if (vxtime.hpet_address && notsc) {
                timetype = "HPET";
                vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
                vxtime.mode = VXTIME_HPET;
                do_gettimeoffset = do_gettimeoffset_hpet;
+#ifdef CONFIG_X86_PM_TIMER
+       /* Using PM for gettimeofday is quite slow, but we have no other
+          choice because the TSC is too unreliable on some systems. */
+       } else if (pmtmr_ioport && !vxtime.hpet_address && notsc) {
+               timetype = "PM";
+               do_gettimeoffset = do_gettimeoffset_pm;
+               vxtime.mode = VXTIME_PMTMR;
+               sysctl_vsyscall = 0;
+               printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n");
+#endif
        } else {
                timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC";
                vxtime.mode = VXTIME_TSC;
index 65a37f52c56ef2c0760f2e3db9dfec9312a74d88..3dfec8fdabcdd35799cf014d08fc89d6bf1a7701 100644 (file)
@@ -332,10 +332,12 @@ void handle_BUG(struct pt_regs *regs)
        printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line);
 } 
 
+#ifdef CONFIG_BUG
 void out_of_line_bug(void)
 { 
        BUG(); 
 } 
+#endif
 
 static DEFINE_SPINLOCK(die_lock);
 static int die_owner = -1;
index b4b8dc59663ad447f6228fff15209067928b642e..2e5734425949648ea92bd8d7fd9e65e6f99a8ed5 100644 (file)
@@ -65,7 +65,7 @@ static force_inline void do_vgettimeofday(struct timeval * tv)
                usec = (__xtime.tv_nsec / 1000) +
                        (__jiffies - __wall_jiffies) * (1000000 / HZ);
 
-               if (__vxtime.mode == VXTIME_TSC) {
+               if (__vxtime.mode != VXTIME_HPET) {
                        sync_core();
                        rdtscll(t);
                        if (t < __vxtime.last_tsc)
@@ -217,8 +217,9 @@ static int __init vsyscall_init(void)
        BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
        BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
        map_vsyscall();
-       sysctl_vsyscall = 1;
+#ifdef CONFIG_SYSCTL
        register_sysctl_table(kernel_root_table2, 0);
+#endif
        return 0;
 }
 
index a43dedb58fa2a7415bd281be832186ff3a34f900..68ec03070e5adbe82925dba26772a688cecd1b9b 100644 (file)
@@ -193,8 +193,9 @@ EXPORT_SYMBOL(smp_num_siblings);
 extern void do_softirq_thunk(void);
 EXPORT_SYMBOL(do_softirq_thunk);
 
-void out_of_line_bug(void);
+#ifdef CONFIG_BUG
 EXPORT_SYMBOL(out_of_line_bug);
+#endif
 
 EXPORT_SYMBOL(init_level4_pgt);
 
index e0330921676413d100b6a1f2cf2c6f579133e3d8..5d6b2114cc9a4e5d30b9736a339dad5bc03839fc 100644 (file)
@@ -234,6 +234,8 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
 
 /*
  * Handle a fault on the vmalloc or module mapping area
+ *
+ * This assumes no large pages in there.
  */
 static int vmalloc_fault(unsigned long address)
 {
@@ -272,7 +274,10 @@ static int vmalloc_fault(unsigned long address)
        if (!pte_present(*pte_ref))
                return -1;
        pte = pte_offset_kernel(pmd, address);
-       if (!pte_present(*pte) || pte_page(*pte) != pte_page(*pte_ref))
+       /* Don't use pte_page here, because the mappings can point
+          outside mem_map, and the NUMA hash lookup cannot handle
+          that. */
+       if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
                BUG();
        __flush_tlb_all();
        return 0;
@@ -346,7 +351,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
         * protection