diff -Nru a/Documentation/mmio_barrier.txt b/Documentation/mmio_barrier.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/mmio_barrier.txt Thu Oct 24 22:22:20 2002 @@ -0,0 +1,15 @@ +On some platforms, so-called memory-mapped I/O is weakly ordered. For +example, the following might occur: + +CPU A writes 0x1 to Device #1 +CPU B writes 0x2 to Device #1 +Device #1 sees 0x2 +Device #1 sees 0x1 + +On such platforms, driver writers are responsible for ensuring that I/O +writes to memory-mapped addresses on their device arrive in the order +intended. The mmiob() macro is provided for this purpose. A typical use +of this macro might be immediately prior to the exit of a critical +section of code proteced by spinlocks. This would ensure that subsequent +writes to I/O space arrived only after all prior writes (much like a +typical memory barrier op, mb(), only with respect to I/O). diff -Nru a/Makefile b/Makefile --- a/Makefile Thu Oct 24 22:22:20 2002 +++ b/Makefile Thu Oct 24 22:22:20 2002 @@ -155,7 +155,7 @@ NOSTDINC_FLAGS = -nostdinc -iwithprefix include CPPFLAGS := -D__KERNEL__ -Iinclude -CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ +CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -g -O2 \ -fomit-frame-pointer -fno-strict-aliasing -fno-common AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c Thu Oct 24 22:22:20 2002 +++ b/arch/i386/mm/fault.c Thu Oct 24 22:22:20 2002 @@ -28,8 +28,6 @@ extern void die(const char *,struct pt_regs *,long); -extern int console_loglevel; - /* * Ugly, ugly, but the goto's result in better assembly.. */ diff -Nru a/arch/ia64/Config.help b/arch/ia64/Config.help --- a/arch/ia64/Config.help Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/Config.help Thu Oct 24 22:22:20 2002 @@ -157,6 +157,11 @@ and ds.o. If you want to compile it as a module, say M here and read . +CONFIG_KALLSYMS + Say Y here to let the kernel print out symbolic crash information and + symbolic stack backtraces. This increases the size of the kernel + somewhat, as all symbols have to be loaded into the kernel image. + CONFIG_KCORE_ELF If you enabled support for /proc file system then the file /proc/kcore will contain the kernel core image. This can be used diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/Makefile Thu Oct 24 22:22:20 2002 @@ -33,44 +33,48 @@ CFLAGS += -mb-step endif -HEAD := arch/$(ARCH)/kernel/head.o arch/ia64/kernel/init_task.o +HEAD := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o -core-$(CONFIG_IA64_GENERIC) += arch/$(ARCH)/hp/ arch/$(ARCH)/dig/ -core-$(CONFIG_IA64_HP_SIM) += arch/$(ARCH)/hp/ -core-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/ arch/$(ARCH)/dig/ -core-$(CONFIG_IA64_SGI_SN) += arch/$(ARCH)/sn/kernel arch/$(ARCH)/sn/io +libs-y += arch/$(ARCH)/lib/ +core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ +core-$(CONFIG_IA32_SUPPORT) += arch/$(ARCH)/ia32/ core-$(CONFIG_IA64_DIG) += arch/$(ARCH)/dig/ +core-$(CONFIG_IA64_GENERIC) += arch/$(ARCH)/dig/ arch/$(ARCH)/hp/common/ arch/$(ARCH)/hp/zx1/ \ + arch/$(ARCH)/hp/sim/ +core-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/dig/ +core-$(CONFIG_IA64_SGI_SN) += arch/$(ARCH)/sn/kernel arch/$(ARCH)/sn/io \ + arch/$(ARCH)/sn/fakeprom +drivers-$(CONFIG_PCI) += arch/$(ARCH)/pci/ +drivers-$(CONFIG_IA64_HP_SIM) += arch/$(ARCH)/hp/sim/ +drivers-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/common/ arch/$(ARCH)/hp/zx1/ ifdef CONFIG_IA64_SGI_SN CFLAGS += -DBRINGUP SUBDIRS += arch/$(ARCH)/sn/fakeprom endif -core-$(CONFIG_IA32_SUPPORT) += arch/$(ARCH)/ia32/ +makeboot = $(call descend,arch/ia64/boot,$(1)) +maketool = $(call descend,arch/ia64/tools,$(1)) -libs-y += arch/$(ARCH)/lib/ -core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ -drivers-$(CONFIG_PCI) += arch/$(ARCH)/pci/ -drivers-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/common/ arch/$(ARCH)/hp/zx1/ +.PHONY: compressed archclean archmrproper $(TOPDIR)/include/asm-ia64/offsets.h + +all: compressed boot -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +boot: vmlinux + +@$(call makeboot,all) compressed: vmlinux $(OBJCOPY) $(OBJCOPYFLAGS) vmlinux vmlinux-tmp gzip vmlinux-tmp mv vmlinux-tmp.gz vmlinux.gz -rawboot: - @$(MAKEBOOT) rawboot - archclean: - @$(MAKEBOOT) clean + $(MAKE) -rR -f scripts/Makefile.clean obj=arch/$(ARCH)/boot archmrproper: - @$(MAKE) -C arch/$(ARCH)/tools mrproper prepare: $(TOPDIR)/include/asm-ia64/offsets.h $(TOPDIR)/include/asm-ia64/offsets.h: include/asm include/linux/version.h \ include/config/MARKER - @$(MAKE) -C arch/$(ARCH)/tools $@ + +@$(call maketool,$@) diff -Nru a/arch/ia64/boot/Makefile b/arch/ia64/boot/Makefile --- a/arch/ia64/boot/Makefile Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/boot/Makefile Thu Oct 24 22:22:20 2002 @@ -8,9 +8,11 @@ # Copyright (C) 1998 by David Mosberger-Tang # -LINKFLAGS = -static -T bootloader.lds +THIS = arch/$(ARCH)/boot -OBJECTS = bootloader.o +LINKFLAGS = -static -T $(THIS)/bootloader.lds + +OBJS = $(THIS)/bootloader.o targets-$(CONFIG_IA64_HP_SIM) += bootloader targets-$(CONFIG_IA64_GENERIC) += bootloader @@ -19,8 +21,8 @@ all: $(targets-y) -bootloader: $(OBJECTS) - $(LD) $(LINKFLAGS) $(OBJECTS) $(TOPDIR)/lib/lib.a $(TOPDIR)/arch/$(ARCH)/lib/lib.a \ +bootloader: $(OBJS) + $(LD) $(LINKFLAGS) $(OBJS) $(TOPDIR)/lib/lib.a $(TOPDIR)/arch/$(ARCH)/lib/lib.a \ -o bootloader clean: diff -Nru a/arch/ia64/config.in b/arch/ia64/config.in --- a/arch/ia64/config.in Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/config.in Thu Oct 24 22:22:20 2002 @@ -66,6 +66,10 @@ if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_DIG" = "y" -o "$CONFIG_IA64_HP_ZX1" = "y" ]; then + bool ' Enable NUMA support' CONFIG_NUMA + if [ "$CONFIG_NUMA" = "y" ]; then + define_bool CONFIG_DISCONTIGMEM y + fi bool ' Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA define_bool CONFIG_PM y define_bool CONFIG_IOSAPIC y @@ -267,6 +271,7 @@ bool 'Kernel debugging' CONFIG_DEBUG_KERNEL if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then + bool ' Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS bool ' Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS bool ' Disable VHPT' CONFIG_DISABLE_VHPT bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ diff -Nru a/arch/ia64/defconfig b/arch/ia64/defconfig --- a/arch/ia64/defconfig Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/defconfig Thu Oct 24 22:22:20 2002 @@ -43,7 +43,6 @@ # CONFIG_IA64_PAGE_SIZE_4KB is not set # CONFIG_IA64_PAGE_SIZE_8KB is not set CONFIG_IA64_PAGE_SIZE_16KB=y -# CONFIG_IA64_PAGE_SIZE_64KB is not set CONFIG_ACPI=y CONFIG_ACPI_EFI=y CONFIG_ACPI_INTERPRETER=y @@ -53,32 +52,35 @@ CONFIG_IA64_L1_CACHE_SHIFT=6 CONFIG_IA64_MCA=y CONFIG_PM=y +CONFIG_IOSAPIC=y CONFIG_KCORE_ELF=y +CONFIG_FORCE_MAX_ZONEORDER=18 +# CONFIG_HUGETLB_PAGE is not set CONFIG_SMP=y CONFIG_IA32_SUPPORT=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y CONFIG_EFI_VARS=y +CONFIG_NR_CPUS=16 CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_NR_CPUS=64 # # ACPI Support # +CONFIG_ACPI_BUTTON=y +CONFIG_ACPI_FAN=m +CONFIG_ACPI_PROCESSOR=m +CONFIG_ACPI_THERMAL=m +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_PCI=y CONFIG_ACPI=y CONFIG_ACPI_EFI=y CONFIG_ACPI_BOOT=y CONFIG_ACPI_BUS=y CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_PCI=y CONFIG_ACPI_POWER=y CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_FAN=m -CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_THERMAL=m -# CONFIG_ACPI_DEBUG is not set CONFIG_PCI=y CONFIG_PCI_NAMES=y # CONFIG_HOTPLUG is not set @@ -90,50 +92,6 @@ # CONFIG_PARPORT is not set # -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set @@ -142,6 +100,12 @@ # Plug and Play configuration # # CONFIG_PNP is not set +# CONFIG_PNP_NAMES is not set +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# # CONFIG_ISAPNP is not set # CONFIG_PNPBIOS is not set @@ -155,6 +119,7 @@ # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_CISS_SCSI_TAPE is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set @@ -188,12 +153,21 @@ # CONFIG_BLK_DEV_LVM is not set # -# ATA/IDE/MFM/RLL support +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_BOOT is not set +# CONFIG_FUSION_ISENSE is not set +# CONFIG_FUSION_CTL is not set +# CONFIG_FUSION_LAN is not set + +# +# ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y # -# ATA and ATAPI Block devices +# IDE, ATA and ATAPI Block devices # CONFIG_BLK_DEV_IDE=y @@ -207,29 +181,35 @@ # CONFIG_IDEDISK_STROKE is not set # CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=y CONFIG_BLK_DEV_IDESCSI=y +# CONFIG_IDE_TASK_IOCTL is not set # -# IDE chipset support +# IDE chipset support/bugfixes # # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_CMD640_ENHANCED is not set # CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_BLK_DEV_GENERIC is not set CONFIG_IDEPCI_SHARE_IRQ=y CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDE_TCQ is not set +# CONFIG_BLK_DEV_IDE_TCQ_DEFAULT is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set # CONFIG_IDEDMA_PCI_AUTO is not set # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set +CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set # CONFIG_BLK_DEV_CMD64X is not set # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -237,21 +217,25 @@ # CONFIG_HPT34X_AUTODMA is not set # CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NFORCE is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set # CONFIG_PDC202XX_BURST is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set # CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_RZ1000 is not set # CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set # CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_IVB is not set # CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_IDE_MODES=y # # SCSI support @@ -272,6 +256,7 @@ # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # # CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y @@ -281,9 +266,7 @@ # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_DPT_I2O is not set @@ -316,15 +299,60 @@ # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set CONFIG_SCSI_QLOGIC_1280=y -# CONFIG_SCSI_QLOGIC_QLA2100 is not set -# CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +CONFIG_FILTER=y +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# # Network device support # CONFIG_NETDEVICES=y @@ -352,6 +380,11 @@ # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set # CONFIG_NET_ISA is not set CONFIG_NET_PCI=y @@ -373,10 +406,11 @@ # CONFIG_8139TOO_PIO is not set # CONFIG_8139TOO_TUNE_TWISTER is not set # CONFIG_8139TOO_8129 is not set -# CONFIG_8139_NEW_RX_RESET is not set +# CONFIG_8139_OLD_RX_RESET is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set +# CONFIG_SUNDANCE_MMIO is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_VIA_RHINE_MMIO is not set @@ -388,6 +422,7 @@ # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set +# CONFIG_E1000_NAPI is not set # CONFIG_MYRI_SBUS is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set @@ -419,11 +454,6 @@ # CONFIG_WAN is not set # -# "Tulip" family network device support -# -# CONFIG_NET_TULIP is not set - -# # Amateur Radio support # # CONFIG_HAMRADIO is not set @@ -431,7 +461,7 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set # # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) @@ -442,22 +472,50 @@ # Input device support # CONFIG_INPUT=y -CONFIG_INPUT_KEYBDEV=y + +# +# Userland interfaces +# CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_GAMEPORT_NS558 is not set # CONFIG_GAMEPORT_L4 is not set -# CONFIG_INPUT_EMU10K1 is not set -# CONFIG_GAMEPORT_PCIGAME is not set +# CONFIG_GAMEPORT_EMU10K1 is not set +# CONFIG_GAMEPORT_VORTEX is not set # CONFIG_GAMEPORT_FM801 is not set # CONFIG_GAMEPORT_CS461x is not set CONFIG_SERIO=y +CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_JOYSTICK_ANALOG is not set # CONFIG_JOYSTICK_A3D is not set @@ -465,30 +523,56 @@ # CONFIG_JOYSTICK_COBRA is not set # CONFIG_JOYSTICK_GF2K is not set # CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set # CONFIG_JOYSTICK_INTERACT is not set # CONFIG_JOYSTICK_SIDEWINDER is not set # CONFIG_JOYSTICK_TMDC is not set -# CONFIG_JOYSTICK_IFORCE_USB is not set -# CONFIG_JOYSTICK_IFORCE_232 is not set +# CONFIG_JOYSTICK_IFORCE is not set # CONFIG_JOYSTICK_WARRIOR is not set # CONFIG_JOYSTICK_MAGELLAN is not set # CONFIG_JOYSTICK_SPACEORB is not set # CONFIG_JOYSTICK_SPACEBALL is not set # CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDDLER is not set # CONFIG_JOYSTICK_DB9 is not set # CONFIG_JOYSTICK_GAMECON is not set # CONFIG_JOYSTICK_TURBOGRAFX is not set +# CONFIG_INPUT_JOYDUMP is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_PCSPKR is not set +# CONFIG_INPUT_UINPUT is not set # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_ACPI=y -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_CS is not set +# CONFIG_SERIAL_8250_ACPI is not set +# CONFIG_SERIAL_8250_HCDP is not set +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -500,6 +584,8 @@ # CONFIG_I2C_PHILIPSPAR is not set # CONFIG_I2C_ELV is not set # CONFIG_I2C_VELLEMAN is not set +# CONFIG_SCx200_I2C is not set +# CONFIG_SCx200_ACB is not set # CONFIG_I2C_ALGOPCF is not set CONFIG_I2C_CHARDEV=y CONFIG_I2C_PROC=y @@ -508,10 +594,6 @@ # Mice # # CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set # CONFIG_QIC02_TAPE is not set # @@ -521,6 +603,7 @@ # CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set CONFIG_EFI_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -531,71 +614,37 @@ # # CONFIG_FTAPE is not set CONFIG_AGP=y -# CONFIG_AGP_INTEL is not set +CONFIG_AGP_INTEL=y +CONFIG_AGP_I810=y +CONFIG_AGP_VIA=y +CONFIG_AGP_AMD=y +CONFIG_AGP_SIS=y +CONFIG_AGP_ALI=y +CONFIG_AGP_SWORKS=y +# CONFIG_AGP_AMD_8151 is not set CONFIG_AGP_I460=y -# CONFIG_AGP_I810 is not set -# CONFIG_AGP_VIA is not set -# CONFIG_AGP_AMD is not set -# CONFIG_AGP_SIS is not set -# CONFIG_AGP_ALI is not set -# CONFIG_AGP_SWORKS is not set +CONFIG_AGP_HP_ZX1=y +CONFIG_DRM=y CONFIG_DRM_TDFX=y -# CONFIG_DRM_GAMMA is not set -# CONFIG_DRM_R128 is not set -# CONFIG_DRM_RADEON is not set -# CONFIG_DRM_I810 is not set -# CONFIG_DRM_MGA is not set +CONFIG_DRM_R128=y +CONFIG_DRM_RADEON=y +CONFIG_DRM_I810=y +CONFIG_DRM_I830=y +CONFIG_DRM_MGA=y +# CONFIG_SCx200_GPIO is not set +# CONFIG_RAW_DRIVER is not set # # Multimedia devices # -CONFIG_VIDEO_DEV=y - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set - -# -# Video Adapters -# -# CONFIG_VIDEO_BT848 is not set -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_CPIA is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MIROPCM20 is not set -# CONFIG_RADIO_MIROPCM20_RDS is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set +# CONFIG_VIDEO_DEV is not set # # File systems # # CONFIG_QUOTA is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set @@ -606,9 +655,9 @@ # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -CONFIG_JBD_DEBUG=y +CONFIG_EXT3_FS=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y # CONFIG_UMSDOS_FS is not set @@ -645,6 +694,9 @@ # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set # CONFIG_UFS_FS_WRITE is not set +# CONFIG_XFS_FS is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set # # Network File Systems @@ -653,13 +705,17 @@ # CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y +CONFIG_NFS_V4=y # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y +CONFIG_NFSD_V4=y # CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -670,6 +726,7 @@ # CONFIG_NCPFS_SMALLDOS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set +# CONFIG_AFS_FS is not set # CONFIG_ZISOFS_FS is not set # @@ -792,23 +849,23 @@ # Miscellaneous USB options # CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_LONG_TIMEOUT is not set +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set # # USB Host Controller Drivers # # CONFIG_USB_EHCI_HCD is not set # CONFIG_USB_OHCI_HCD is not set -CONFIG_USB_UHCI=m -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set +CONFIG_USB_UHCI_HCD_ALT=y # # USB Device Class drivers # # CONFIG_USB_AUDIO is not set # CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_MIDI is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set # CONFIG_USB_STORAGE is not set @@ -819,22 +876,26 @@ # CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_STORAGE_HP8200e is not set # CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set # CONFIG_USB_STORAGE_JUMPSHOT is not set # # USB Human Interface Devices (HID) # -CONFIG_USB_HID=m +CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y +# CONFIG_HID_FF is not set +# CONFIG_HID_PID is not set +# CONFIG_LOGITECH_FF is not set CONFIG_USB_HIDDEV=y -CONFIG_USB_KBD=m -CONFIG_USB_MOUSE=m +# CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_XPAD is not set # # USB Imaging devices # -# CONFIG_USB_DC2XX is not set # CONFIG_USB_MDC800 is not set # CONFIG_USB_SCANNER is not set # CONFIG_USB_MICROTEK is not set @@ -844,6 +905,10 @@ # USB Multimedia devices # # CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# # CONFIG_USB_VICAM is not set # CONFIG_USB_DSBR is not set # CONFIG_USB_IBMCAM is not set @@ -882,6 +947,7 @@ # CONFIG_USB_SERIAL_IPAQ is not set # CONFIG_USB_SERIAL_IR is not set # CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set # CONFIG_USB_SERIAL_KEYSPAN is not set # CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set @@ -891,6 +957,8 @@ # CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set # CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set # CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set # CONFIG_USB_SERIAL_KLSI is not set # CONFIG_USB_SERIAL_MCT_U232 is not set @@ -908,6 +976,10 @@ # CONFIG_USB_TIGL is not set # CONFIG_USB_AUERSWALD is not set # CONFIG_USB_RIO500 is not set +# CONFIG_USB_BRLVGER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_SPEEDTOUCH is not set +# CONFIG_USB_TEST is not set # # Library routines @@ -927,11 +999,19 @@ # CONFIG_IA64_GRANULE_16MB is not set CONFIG_IA64_GRANULE_64MB=y CONFIG_DEBUG_KERNEL=y +CONFIG_KALLSYMS=y CONFIG_IA64_PRINT_HAZARDS=y # CONFIG_DISABLE_VHPT is not set CONFIG_MAGIC_SYSRQ=y CONFIG_IA64_EARLY_PRINTK=y +# CONFIG_IA64_EARLY_PRINTK_UART is not set +CONFIG_IA64_EARLY_PRINTK_VGA=y # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_IA64_DEBUG_CMPXCHG is not set # CONFIG_IA64_DEBUG_IRQ is not set + +# +# Security options +# +CONFIG_SECURITY_CAPABILITIES=y diff -Nru a/arch/ia64/hp/Makefile b/arch/ia64/hp/Makefile --- a/arch/ia64/hp/Makefile Thu Oct 24 22:22:20 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,7 +0,0 @@ -# arch/ia64/hp/Makefile -# Copyright (c) 2002 Matthew Wilcox for Hewlett Packard - -obj-$(CONFIG_IA64_GENERIC) += sim/ zx1/ common/ -obj-$(CONFIG_IA64_HP_SIM) += sim/ - -include $(TOPDIR)/Rules.make diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c --- a/arch/ia64/hp/sim/simscsi.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/hp/sim/simscsi.c Thu Oct 24 22:22:20 2002 @@ -361,7 +361,9 @@ break; case MODE_SENSE: - printk("MODE_SENSE\n"); + /* sd.c uses this to determine whether disk does write-caching. */ + memset(sc->request_buffer, 0, 128); + sc->result = GOOD; break; case START_STOP: @@ -390,7 +392,5 @@ static Scsi_Host_Template driver_template = SIMSCSI; - -#define __initcall(fn) late_initcall(fn) #include "../drivers/scsi/scsi_module.c" diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c --- a/arch/ia64/hp/sim/simserial.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/hp/sim/simserial.c Thu Oct 24 22:22:20 2002 @@ -752,8 +752,7 @@ info->flags = sstate->flags; info->xmit_fifo_size = sstate->xmit_fifo_size; info->line = line; - info->tqueue.routine = do_softint; - info->tqueue.data = info; + INIT_WORK(&info->work, do_softint, info); info->state = sstate; if (sstate->info) { kfree(info); diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c --- a/arch/ia64/ia32/ia32_ioctl.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/ia32/ia32_ioctl.c Thu Oct 24 22:22:20 2002 @@ -26,6 +26,12 @@ #include #include #include +#include +/* Ugly hack. */ +#undef __KERNEL__ +#include +#define __KERNEL__ +#include #include @@ -60,6 +66,235 @@ || put_user(d->d_reclen, &d32->d_reclen) || copy_to_user(d32->d_name, d->d_name, namelen + 1)); } +/* + * The transform code for the SG_IO ioctl was brazenly lifted from + * the Sparc64 port in the file `arch/sparc64/kernel/ioctl32.c'. + * Thanks to Jakub Jelinek & Eddie C. Dost. + */ +typedef struct sg_io_hdr32 { + int interface_id; /* [i] 'S' for SCSI generic (required) */ + int dxfer_direction; /* [i] data transfer direction */ + char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + char mx_sb_len; /* [i] max length to write to sbp */ + short iovec_count; /* [i] 0 implies no scatter gather */ + int dxfer_len; /* [i] byte count of data transfer */ + int dxferp; /* [i], [*io] points to data transfer memory + or scatter gather list */ + int cmdp; /* [i], [*i] points to command to perform */ + int sbp; /* [i], [*o] points to sense_buffer memory */ + int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ + int flags; /* [i] 0 -> default, see SG_FLAG... */ + int pack_id; /* [i->o] unused internally (normally) */ + int usr_ptr; /* [i->o] unused internally */ + char status; /* [o] scsi status */ + char masked_status; /* [o] shifted, masked scsi status */ + char msg_status; /* [o] messaging level data (optional) */ + char sb_len_wr; /* [o] byte count actually written to sbp */ + short host_status; /* [o] errors from host adapter */ + short driver_status; /* [o] errors from software driver */ + int resid; /* [o] dxfer_len - actual_transferred */ + int duration; /* [o] time taken by cmd (unit: millisec) */ + int info; /* [o] auxiliary information */ +} sg_io_hdr32_t; /* 64 bytes long (on IA32) */ + +struct iovec32 { unsigned int iov_base; int iov_len; }; + +static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32) +{ + struct iovec32 *uiov = (struct iovec32 *) P(uptr32); + sg_iovec_t *kiov; + int i; + + sgp->dxferp = kmalloc(sgp->iovec_count * + sizeof(sg_iovec_t), GFP_KERNEL); + if (!sgp->dxferp) + return -ENOMEM; + memset(sgp->dxferp, 0, + sgp->iovec_count * sizeof(sg_iovec_t)); + + kiov = (sg_iovec_t *) sgp->dxferp; + for (i = 0; i < sgp->iovec_count; i++) { + int iov_base32; + if (__get_user(iov_base32, &uiov->iov_base) || + __get_user(kiov->iov_len, &uiov->iov_len)) + return -EFAULT; + + kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL); + if (!kiov->iov_base) + return -ENOMEM; + if (copy_from_user(kiov->iov_base, + (void *) P(iov_base32), + kiov->iov_len)) + return -EFAULT; + + uiov++; + kiov++; + } + + return 0; +} + +static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32) +{ + struct iovec32 *uiov = (struct iovec32 *) P(uptr32); + sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; + int i; + + for (i = 0; i < sgp->iovec_count; i++) { + int iov_base32; + + if (__get_user(iov_base32, &uiov->iov_base)) + return -EFAULT; + + if (copy_to_user((void *) P(iov_base32), + kiov->iov_base, + kiov->iov_len)) + return -EFAULT; + + uiov++; + kiov++; + } + + return 0; +} + +static void free_sg_iovec(sg_io_hdr_t *sgp) +{ + sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; + int i; + + for (i = 0; i < sgp->iovec_count; i++) { + if (kiov->iov_base) { + kfree(kiov->iov_base); + kiov->iov_base = NULL; + } + kiov++; + } + kfree(sgp->dxferp); + sgp->dxferp = NULL; +} + +static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + sg_io_hdr32_t *sg_io32; + sg_io_hdr_t sg_io64; + int dxferp32, cmdp32, sbp32; + mm_segment_t old_fs; + int err = 0; + + sg_io32 = (sg_io_hdr32_t *)arg; + err = __get_user(sg_io64.interface_id, &sg_io32->interface_id); + err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction); + err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len); + err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len); + err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count); + err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len); + err |= __get_user(sg_io64.timeout, &sg_io32->timeout); + err |= __get_user(sg_io64.flags, &sg_io32->flags); + err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id); + + sg_io64.dxferp = NULL; + sg_io64.cmdp = NULL; + sg_io64.sbp = NULL; + + err |= __get_user(cmdp32, &sg_io32->cmdp); + sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL); + if (!sg_io64.cmdp) { + err = -ENOMEM; + goto out; + } + if (copy_from_user(sg_io64.cmdp, + (void *) P(cmdp32), + sg_io64.cmd_len)) { + err = -EFAULT; + goto out; + } + + err |= __get_user(sbp32, &sg_io32->sbp); + sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL); + if (!sg_io64.sbp) { + err = -ENOMEM; + goto out; + } + if (copy_from_user(sg_io64.sbp, + (void *) P(sbp32), + sg_io64.mx_sb_len)) { + err = -EFAULT; + goto out; + } + + err |= __get_user(dxferp32, &sg_io32->dxferp); + if (sg_io64.iovec_count) { + int ret; + + if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) { + err = ret; + goto out; + } + } else { + sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL); + if (!sg_io64.dxferp) { + err = -ENOMEM; + goto out; + } + if (copy_from_user(sg_io64.dxferp, + (void *) P(dxferp32), + sg_io64.dxfer_len)) { + err = -EFAULT; + goto out; + } + } + + /* Unused internally, do not even bother to copy it over. */ + sg_io64.usr_ptr = NULL; + + if (err) + return -EFAULT; + + old_fs = get_fs(); + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64); + set_fs (old_fs); + + if (err < 0) + goto out; + + err = __put_user(sg_io64.pack_id, &sg_io32->pack_id); + err |= __put_user(sg_io64.status, &sg_io32->status); + err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status); + err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status); + err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr); + err |= __put_user(sg_io64.host_status, &sg_io32->host_status); + err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status); + err |= __put_user(sg_io64.resid, &sg_io32->resid); + err |= __put_user(sg_io64.duration, &sg_io32->duration); + err |= __put_user(sg_io64.info, &sg_io32->info); + err |= copy_to_user((void *)P(sbp32), sg_io64.sbp, sg_io64.mx_sb_len); + if (sg_io64.dxferp) { + if (sg_io64.iovec_count) + err |= copy_back_sg_iovec(&sg_io64, dxferp32); + else + err |= copy_to_user((void *)P(dxferp32), + sg_io64.dxferp, + sg_io64.dxfer_len); + } + if (err) + err = -EFAULT; + +out: + if (sg_io64.cmdp) + kfree(sg_io64.cmdp); + if (sg_io64.sbp) + kfree(sg_io64.sbp); + if (sg_io64.dxferp) { + if (sg_io64.iovec_count) { + free_sg_iovec(&sg_io64); + } else { + kfree(sg_io64.dxferp); + } + } + return err; +} asmlinkage long sys32_ioctl (unsigned int fd, unsigned int cmd, unsigned int arg) @@ -270,6 +505,9 @@ break; default: return sys_ioctl(fd, cmd, (unsigned long)arg); + + case IOCTL_NR(SG_IO): + return(sg_ioctl_trans(fd, cmd, arg)); } printk("%x:unimplemented IA32 ioctl system call\n", cmd); diff -Nru a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c --- a/arch/ia64/ia32/ia32_signal.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/ia32/ia32_signal.c Thu Oct 24 22:22:20 2002 @@ -39,6 +39,16 @@ #define __IA32_NR_sigreturn 119 #define __IA32_NR_rt_sigreturn 173 +register double f16 asm ("f16"); register double f17 asm ("f17"); +register double f18 asm ("f18"); register double f19 asm ("f19"); +register double f20 asm ("f20"); register double f21 asm ("f21"); +register double f22 asm ("f22"); register double f23 asm ("f23"); + +register double f24 asm ("f24"); register double f25 asm ("f25"); +register double f26 asm ("f26"); register double f27 asm ("f27"); +register double f28 asm ("f28"); register double f29 asm ("f29"); +register double f30 asm ("f30"); register double f31 asm ("f31"); + struct sigframe_ia32 { int pretcode; @@ -143,6 +153,282 @@ return err; } + +/* + * SAVE and RESTORE of ia32 fpstate info, from ia64 current state + * Used in exception handler to pass the fpstate to the user, and restore + * the fpstate while returning from the exception handler. + * + * fpstate info and their mapping to IA64 regs: + * fpstate REG(BITS) Attribute Comments + * cw ar.fcr(0:12) with bits 7 and 6 not used + * sw ar.fsr(0:15) + * tag ar.fsr(16:31) with odd numbered bits not used + * (read returns 0, writes ignored) + * ipoff ar.fir(0:31) RO + * cssel ar.fir(32:47) RO + * dataoff ar.fdr(0:31) RO + * datasel ar.fdr(32:47) RO + * + * _st[(0+TOS)%8] f8 + * _st[(1+TOS)%8] f9 (f8, f9 from ptregs) + * : : : (f10..f15 from live reg) + * : : : + * _st[(7+TOS)%8] f15 TOS=sw.top(bits11:13) + * + * status Same as sw RO + * magic 0 as X86_FXSR_MAGIC in ia32 + * mxcsr Bits(7:15)=ar.fcr(39:47) + * Bits(0:5) =ar.fsr(32:37) with bit 6 reserved + * _xmm[0..7] f16..f31 (live registers) + * with _xmm[0] + * Bit(64:127)=f17(0:63) + * Bit(0:63)=f16(0:63) + * All other fields unused... + */ + +#define __ldfe(regnum, x) \ +({ \ + register double __f__ asm ("f"#regnum); \ + __asm__ __volatile__ ("ldfe %0=[%1] ;;" :"=f"(__f__): "r"(x)); \ +}) + +#define __ldf8(regnum, x) \ +({ \ + register double __f__ asm ("f"#regnum); \ + __asm__ __volatile__ ("ldf8 %0=[%1] ;;" :"=f"(__f__): "r"(x)); \ +}) + +#define __stfe(x, regnum) \ +({ \ + register double __f__ asm ("f"#regnum); \ + __asm__ __volatile__ ("stfe [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \ +}) + +#define __stf8(x, regnum) \ +({ \ + register double __f__ asm ("f"#regnum); \ + __asm__ __volatile__ ("stf8 [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \ +}) + +static int +save_ia32_fpstate_live (struct _fpstate_ia32 *save) +{ + struct task_struct *tsk = current; + struct pt_regs *ptp; + struct _fpreg_ia32 *fpregp; + char buf[32]; + unsigned long fsr, fcr, fir, fdr; + unsigned long new_fsr; + unsigned long num128[2]; + unsigned long mxcsr=0; + int fp_tos, fr8_st_map; + + if (!access_ok(VERIFY_WRITE, save, sizeof(*save))) + return -EFAULT; + + /* Readin fsr, fcr, fir, fdr and copy onto fpstate */ + asm volatile ( "mov %0=ar.fsr;" : "=r"(fsr)); + asm volatile ( "mov %0=ar.fcr;" : "=r"(fcr)); + asm volatile ( "mov %0=ar.fir;" : "=r"(fir)); + asm volatile ( "mov %0=ar.fdr;" : "=r"(fdr)); + /* + * We need to clear the exception state before calling the signal handler. Clear + * the bits 15, bits 0-7 in fp status word. Similar to the functionality of fnclex + * instruction. + */ + new_fsr = fsr & ~0x80ff; + asm volatile ( "mov ar.fsr=%0;" :: "r"(new_fsr)); + + __put_user(fcr & 0xffff, &save->cw); + __put_user(fsr & 0xffff, &save->sw); + __put_user((fsr>>16) & 0xffff, &save->tag); + __put_user(fir, &save->ipoff); + __put_user((fir>>32) & 0xffff, &save->cssel); + __put_user(fdr, &save->dataoff); + __put_user((fdr>>32) & 0xffff, &save->datasel); + __put_user(fsr & 0xffff, &save->status); + + mxcsr = ((fcr>>32) & 0xff80) | ((fsr>>32) & 0x3f); + __put_user(mxcsr & 0xffff, &save->mxcsr); + __put_user( 0, &save->magic); //#define X86_FXSR_MAGIC 0x0000 + + /* + * save f8 and f9 from pt_regs + * save f10..f15 from live register set + */ + /* + * Find the location where f8 has to go in fp reg stack. This depends on + * TOP(11:13) field of sw. Other f reg continue sequentially from where f8 maps + * to. + */ + fp_tos = (fsr>>11)&0x7; + fr8_st_map = (8-fp_tos)&0x7; + ptp = ia64_task_regs(tsk); + fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); + ia64f2ia32f(fpregp, &ptp->f8); + copy_to_user(&save->_st[(0+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); + ia64f2ia32f(fpregp, &ptp->f9); + copy_to_user(&save->_st[(1+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); + + __stfe(fpregp, 10); + copy_to_user(&save->_st[(2+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); + __stfe(fpregp, 11); + copy_to_user(&save->_st[(3+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); + __stfe(fpregp, 12); + copy_to_user(&save->_st[(4+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); + __stfe(fpregp, 13); + copy_to_user(&save->_st[(5+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); + __stfe(fpregp, 14); + copy_to_user(&save->_st[(6+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); + __stfe(fpregp, 15); + copy_to_user(&save->_st[(7+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); + + __stf8(&num128[0], 16); + __stf8(&num128[1], 17); + copy_to_user(&save->_xmm[0], num128, sizeof(struct _xmmreg_ia32)); + + __stf8(&num128[0], 18); + __stf8(&num128[1], 19); + copy_to_user(&save->_xmm[1], num128, sizeof(struct _xmmreg_ia32)); + + __stf8(&num128[0], 20); + __stf8(&num128[1], 21); + copy_to_user(&save->_xmm[2], num128, sizeof(struct _xmmreg_ia32)); + + __stf8(&num128[0], 22); + __stf8(&num128[1], 23); + copy_to_user(&save->_xmm[3], num128, sizeof(struct _xmmreg_ia32)); + + __stf8(&num128[0], 24); + __stf8(&num128[1], 25); + copy_to_user(&save->_xmm[4], num128, sizeof(struct _xmmreg_ia32)); + + __stf8(&num128[0], 26); + __stf8(&num128[1], 27); + copy_to_user(&save->_xmm[5], num128, sizeof(struct _xmmreg_ia32)); + + __stf8(&num128[0], 28); + __stf8(&num128[1], 29); + copy_to_user(&save->_xmm[6], num128, sizeof(struct _xmmreg_ia32)); + + __stf8(&num128[0], 30); + __stf8(&num128[1], 31); + copy_to_user(&save->_xmm[7], num128, sizeof(struct _xmmreg_ia32)); + return 0; +} + +static int +restore_ia32_fpstate_live (struct _fpstate_ia32 *save) +{ + struct task_struct *tsk = current; + struct pt_regs *ptp; + unsigned int lo, hi; + unsigned long num128[2]; + unsigned long num64, mxcsr; + struct _fpreg_ia32 *fpregp; + char buf[32]; + unsigned long fsr, fcr; + int fp_tos, fr8_st_map; + + if (!access_ok(VERIFY_READ, save, sizeof(*save))) + return(-EFAULT); + + /* + * Updating fsr, fcr, fir, fdr. + * Just a bit more complicated than save. + * - Need to make sure that we dont write any value other than the + * specific fpstate info + * - Need to make sure that the untouched part of frs, fdr, fir, fcr + * should remain same while writing. + * So, we do a read, change specific fields and write. + */ + asm volatile ( "mov %0=ar.fsr;" : "=r"(fsr)); + asm volatile ( "mov %0=ar.fcr;" : "=r"(fcr)); + + __get_user(mxcsr, (unsigned int *)&save->mxcsr); + /* setting bits 0..5 8..12 with cw and 39..47 from mxcsr */ + __get_user(lo, (unsigned int *)&save->cw); + num64 = mxcsr & 0xff10; + num64 = (num64 << 32) | (lo & 0x1f3f); + fcr = (fcr & (~0xff1000001f3f)) | num64; + + /* setting bits 0..31 with sw and tag and 32..37 from mxcsr */ + __get_user(lo, (unsigned int *)&save->sw); + __get_user(hi, (unsigned int *)&save->tag); + num64 = mxcsr & 0x3f; + num64 = (num64 << 16) | (hi & 0xffff); + num64 = (num64 << 16) | (lo & 0xffff); + fsr = (fsr & (~0x3fffffffff)) | num64; + + asm volatile ( "mov ar.fsr=%0;" :: "r"(fsr)); + asm volatile ( "mov ar.fcr=%0;" :: "r"(fcr)); + /* + * restore f8, f9 onto pt_regs + * restore f10..f15 onto live registers + */ + /* + * Find the location where f8 has to go in fp reg stack. This depends on + * TOP(11:13) field of sw. Other f reg continue sequentially from where f8 maps + * to. + */ + fp_tos = (fsr>>11)&0x7; + fr8_st_map = (8-fp_tos)&0x7; + fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); + + ptp = ia64_task_regs(tsk); + copy_from_user(fpregp, &save->_st[(0+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); + ia32f2ia64f(&ptp->f8, fpregp); + copy_from_user(fpregp, &save->_st[(1+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); + ia32f2ia64f(&ptp->f9, fpregp); + + copy_from_user(fpregp, &save->_st[(2+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); + __ldfe(10, fpregp); + copy_from_user(fpregp, &save->_st[(3+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); + __ldfe(11, fpregp); + copy_from_user(fpregp, &save->_st[(4+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); + __ldfe(12, fpregp); + copy_from_user(fpregp, &save->_st[(5+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); + __ldfe(13, fpregp); + copy_from_user(fpregp, &save->_st[(6+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); + __ldfe(14, fpregp); + copy_from_user(fpregp, &save->_st[(7+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); + __ldfe(15, fpregp); + + copy_from_user(num128, &save->_xmm[0], sizeof(struct _xmmreg_ia32)); + __ldf8(16, &num128[0]); + __ldf8(17, &num128[1]); + + copy_from_user(num128, &save->_xmm[1], sizeof(struct _xmmreg_ia32)); + __ldf8(18, &num128[0]); + __ldf8(19, &num128[1]); + + copy_from_user(num128, &save->_xmm[2], sizeof(struct _xmmreg_ia32)); + __ldf8(20, &num128[0]); + __ldf8(21, &num128[1]); + + copy_from_user(num128, &save->_xmm[3], sizeof(struct _xmmreg_ia32)); + __ldf8(22, &num128[0]); + __ldf8(23, &num128[1]); + + copy_from_user(num128, &save->_xmm[4], sizeof(struct _xmmreg_ia32)); + __ldf8(24, &num128[0]); + __ldf8(25, &num128[1]); + + copy_from_user(num128, &save->_xmm[5], sizeof(struct _xmmreg_ia32)); + __ldf8(26, &num128[0]); + __ldf8(27, &num128[1]); + + copy_from_user(num128, &save->_xmm[6], sizeof(struct _xmmreg_ia32)); + __ldf8(28, &num128[0]); + __ldf8(29, &num128[1]); + + copy_from_user(num128, &save->_xmm[7], sizeof(struct _xmmreg_ia32)); + __ldf8(30, &num128[0]); + __ldf8(31, &num128[1]); + return 0; +} + static inline void sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int restorer) { @@ -170,13 +456,13 @@ sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sig->siglock); { oldset = current->blocked; current->blocked = set; recalc_sigpending(); } - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sig->siglock); /* * The return below usually returns to the signal handler. We need to pre-set the @@ -371,6 +657,9 @@ int err = 0; unsigned long flag; + if (!access_ok(VERIFY_WRITE, sc, sizeof(*sc))) + return -EFAULT; + err |= __put_user((regs->r16 >> 32) & 0xffff, (unsigned int *)&sc->fs); err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int *)&sc->gs); err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int *)&sc->es); @@ -397,6 +686,11 @@ err |= __put_user(regs->r12, &sc->esp_at_signal); err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int *)&sc->ss); + if ( save_ia32_fpstate_live(fpstate) < 0 ) + err = -EFAULT; + else + err |= __put_user((u32)(u64)fpstate, &sc->fpstate); + #if 0 tmp = save_i387(fpstate); if (tmp < 0) @@ -418,6 +712,9 @@ { unsigned int err = 0; + if (!access_ok(VERIFY_READ, sc, sizeof(*sc))) + return(-EFAULT); + #define COPY(ia64x, ia32x) err |= __get_user(regs->ia64x, &sc->ia32x) #define copyseg_gs(tmp) (regs->r16 |= (unsigned long) tmp << 48) @@ -477,6 +774,16 @@ regs->r1 = -1; /* disable syscall checks, r1 is orig_eax */ } + { + struct _fpstate_ia32 *buf = NULL; + u32 fpstate_ptr; + err |= get_user(fpstate_ptr, &(sc->fpstate)); + buf = (struct _fpstate_ia32 *)(u64)fpstate_ptr; + if (buf) { + err |= restore_ia32_fpstate_live(buf); + } + } + #if 0 { struct _fpstate * buf; @@ -686,10 +993,10 @@ goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sig->siglock); current->blocked = (sigset_t) set; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sig->siglock); if (restore_sigcontext_ia32(regs, &frame->sc, &eax)) goto badframe; @@ -717,10 +1024,10 @@ goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sig->siglock); current->blocked = set; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sig->siglock); if (restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext, &eax)) goto badframe; diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c --- a/arch/ia64/ia32/sys_ia32.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/ia32/sys_ia32.c Thu Oct 24 22:22:20 2002 @@ -2842,20 +2842,6 @@ } } -static inline void -ia32f2ia64f (void *dst, void *src) -{ - asm volatile ("ldfe f6=[%1];; stf.spill [%0]=f6" :: "r"(dst), "r"(src) : "memory"); - return; -} - -static inline void -ia64f2ia32f (void *dst, void *src) -{ - asm volatile ("ldf.fill f6=[%1];; stfe [%0]=f6" :: "r"(dst), "r"(src) : "memory"); - return; -} - static void put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos) diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/acpi.c Thu Oct 24 22:22:20 2002 @@ -8,6 +8,9 @@ * Copyright (C) 2000 Intel Corp. * Copyright (C) 2000,2001 J.I. Lee * Copyright (C) 2001 Paul Diefenbaugh + * Copyright (C) 2001 Jenna Hall + * Copyright (C) 2001 Takayoshi Kochi + * Copyright (C) 2002 Erich Focht * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -43,6 +46,7 @@ #include #include #include +#include #define PREFIX "ACPI: " @@ -447,6 +451,189 @@ } +#ifdef CONFIG_ACPI_NUMA + +#define SLIT_DEBUG + +#define PXM_FLAG_LEN ((MAX_PXM_DOMAINS + 1)/32) + +static int __initdata srat_num_cpus; /* number of cpus */ +static u32 __initdata pxm_flag[PXM_FLAG_LEN]; +#define pxm_bit_set(bit) (set_bit(bit,(void *)pxm_flag)) +#define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag)) +/* maps to convert between proximity domain and logical node ID */ +int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS]; +int __initdata nid_to_pxm_map[NR_NODES]; +static struct acpi_table_slit __initdata *slit_table; + +/* + * ACPI 2.0 SLIT (System Locality Information Table) + * http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf + */ +void __init +acpi_numa_slit_init (struct acpi_table_slit *slit) +{ + u32 len; + + len = sizeof(struct acpi_table_header) + 8 + + slit->localities * slit->localities; + if (slit->header.length != len) { + printk("ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n", + len, slit->header.length); + memset(numa_slit, 10, sizeof(numa_slit)); + return; + } + slit_table = slit; +} + +void __init +acpi_numa_processor_affinity_init (struct acpi_table_processor_affinity *pa) +{ + /* record this node in proximity bitmap */ + pxm_bit_set(pa->proximity_domain); + + node_cpuid[srat_num_cpus].phys_id = (pa->apic_id << 8) | (pa->lsapic_eid); + /* nid should be overridden as logical node id later */ + node_cpuid[srat_num_cpus].nid = pa->proximity_domain; + srat_num_cpus++; +} + +void __init +acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma) +{ + unsigned long paddr, size, hole_size, min_hole_size; + u8 pxm; + struct node_memblk_s *p, *q, *pend; + + pxm = ma->proximity_domain; + + /* fill node memory chunk structure */ + paddr = ma->base_addr_hi; + paddr = (paddr << 32) | ma->base_addr_lo; + size = ma->length_hi; + size = (size << 32) | ma->length_lo; + + if (num_memblks >= NR_MEMBLKS) { + printk("Too many mem chunks in SRAT. Ignoring %ld MBytes at %lx\n", + size/(1024*1024), paddr); + return; + } + + /* Ignore disabled entries */ + if (!ma->flags.enabled) + return; + + /* + * When the chunk is not the first one in the node, check distance + * from the other chunks. When the hole is too huge ignore the chunk. + * This restriction should be removed when multiple chunks per node + * is supported. + */ + pend = &node_memblk[num_memblks]; + min_hole_size = 0; + for (p = &node_memblk[0]; p < pend; p++) { + if (p->nid != pxm) + continue; + if (p->start_paddr < paddr) + hole_size = paddr - (p->start_paddr + p->size); + else + hole_size = p->start_paddr - (paddr + size); + + if (!min_hole_size || hole_size < min_hole_size) + min_hole_size = hole_size; + } + + if (min_hole_size) { + if (min_hole_size > size) { + printk("Too huge memory hole. Ignoring %ld MBytes at %lx\n", + size/(1024*1024), paddr); + return; + } + } + + /* record this node in proximity bitmap */ + pxm_bit_set(pxm); + + /* Insertion sort based on base address */ + pend = &node_memblk[num_memblks]; + for (p = &node_memblk[0]; p < pend; p++) { + if (paddr < p->start_paddr) + break; + } + if (p < pend) { + for (q = pend; q >= p; q--) + *(q + 1) = *q; + } + p->start_paddr = paddr; + p->size = size; + p->nid = pxm; + num_memblks++; +} + +void __init +acpi_numa_arch_fixup(void) +{ + int i, j, node_from, node_to; + + /* calculate total number of nodes in system from PXM bitmap */ + numnodes = 0; /* init total nodes in system */ + + memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map)); + memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map)); + for (i = 0; i < MAX_PXM_DOMAINS; i++) { + if (pxm_bit_test(i)) { + pxm_to_nid_map[i] = numnodes; + nid_to_pxm_map[numnodes++] = i; + } + } + + /* set logical node id in memory chunk structure */ + for (i = 0; i < num_memblks; i++) + node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid]; + + /* assign memory bank numbers for each chunk on each node */ + for (i = 0; i < numnodes; i++) { + int bank; + + bank = 0; + for (j = 0; j < num_memblks; j++) + if (node_memblk[j].nid == i) + node_memblk[j].bank = bank++; + } + + /* set logical node id in cpu structure */ + for (i = 0; i < srat_num_cpus; i++) + node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid]; + + printk("Number of logical nodes in system = %d\n", numnodes); + printk("Number of memory chunks in system = %d\n", num_memblks); + + if (!slit_table) return; + memset(numa_slit, -1, sizeof(numa_slit)); + for (i=0; ilocalities; i++) { + if (!pxm_bit_test(i)) + continue; + node_from = pxm_to_nid_map[i]; + for (j=0; jlocalities; j++) { + if (!pxm_bit_test(j)) + continue; + node_to = pxm_to_nid_map[j]; + node_distance(node_from, node_to) = + slit_table->entry[i*slit_table->localities + j]; + } + } + +#ifdef SLIT_DEBUG + printk("ACPI 2.0 SLIT locality table:\n"); + for (i = 0; i < numnodes; i++) { + for (j = 0; j < numnodes; j++) + printk("%03d ", node_distance(i,j)); + printk("\n"); + } +#endif +} +#endif /* CONFIG_ACPI_NUMA */ + static int __init acpi_parse_fadt (unsigned long phys_addr, unsigned long size) { @@ -556,12 +743,6 @@ int __init acpi_boot_init (char *cmdline) { - int result; - - /* Initialize the ACPI boot-time table parser */ - result = acpi_table_init(cmdline); - if (result) - return result; /* * MADT @@ -631,6 +812,9 @@ smp_boot_data.cpu_count = total_cpus; smp_build_cpu_map(); +#ifdef CONFIG_NUMA + build_cpu_to_node_map(); +#endif #endif /* Make boot-up look pretty */ printk("%d CPUs available, %d CPUs total\n", available_cpus, total_cpus); diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c --- a/arch/ia64/kernel/efi.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/efi.c Thu Oct 24 22:22:20 2002 @@ -60,66 +60,156 @@ static unsigned long mem_limit = ~0UL; -static efi_status_t -phys_get_time (efi_time_t *tm, efi_time_cap_t *tc) -{ - return efi_call_phys(__va(runtime->get_time), __pa(tm), __pa(tc)); -} - -static efi_status_t -phys_set_time (efi_time_t *tm) -{ - return efi_call_phys(__va(runtime->set_time), __pa(tm)); -} - -static efi_status_t -phys_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) -{ - return efi_call_phys(__va(runtime->get_wakeup_time), __pa(enabled), __pa(pending), - __pa(tm)); -} - -static efi_status_t -phys_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) -{ - return efi_call_phys(__va(runtime->set_wakeup_time), enabled, __pa(tm)); -} - -static efi_status_t -phys_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, - unsigned long *data_size, void *data) -{ - return efi_call_phys(__va(runtime->get_variable), __pa(name), __pa(vendor), __pa(attr), - __pa(data_size), __pa(data)); -} - -static efi_status_t -phys_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) -{ - return efi_call_phys(__va(runtime->get_next_variable), __pa(name_size), __pa(name), - __pa(vendor)); -} - -static efi_status_t -phys_set_variable (efi_char16_t *name, efi_guid_t *vendor, u32 attr, - unsigned long data_size, void *data) -{ - return efi_call_phys(__va(runtime->set_variable), __pa(name), __pa(vendor), attr, - data_size, __pa(data)); -} +#define efi_call_virt(f, args...) (*(f))(args) -static efi_status_t -phys_get_next_high_mono_count (u64 *count) -{ - return efi_call_phys(__va(runtime->get_next_high_mono_count), __pa(count)); -} - -static void -phys_reset_system (int reset_type, efi_status_t status, - unsigned long data_size, efi_char16_t *data) -{ - efi_call_phys(__va(runtime->reset_system), status, data_size, __pa(data)); -} +#define STUB_GET_TIME(prefix, adjust_arg) \ +static efi_status_t \ +prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \ +{ \ + struct ia64_fpreg fr[6]; \ + efi_status_t ret; \ + \ + ia64_save_scratch_fpregs(fr); \ + ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), \ + adjust_arg(tc)); \ + ia64_load_scratch_fpregs(fr); \ + return ret; \ +} + +#define STUB_SET_TIME(prefix, adjust_arg) \ +static efi_status_t \ +prefix##_set_time (efi_time_t *tm) \ +{ \ + struct ia64_fpreg fr[6]; \ + efi_status_t ret; \ + \ + ia64_save_scratch_fpregs(fr); \ + ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm)); \ + ia64_load_scratch_fpregs(fr); \ + return ret; \ +} + +#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \ +static efi_status_t \ +prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) \ +{ \ + struct ia64_fpreg fr[6]; \ + efi_status_t ret; \ + \ + ia64_save_scratch_fpregs(fr); \ + ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \ + adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \ + ia64_load_scratch_fpregs(fr); \ + return ret; \ +} + +#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \ +static efi_status_t \ +prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \ +{ \ + struct ia64_fpreg fr[6]; \ + efi_status_t ret; \ + \ + ia64_save_scratch_fpregs(fr); \ + ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \ + enabled, adjust_arg(tm)); \ + ia64_load_scratch_fpregs(fr); \ + return ret; \ +} + +#define STUB_GET_VARIABLE(prefix, adjust_arg) \ +static efi_status_t \ +prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \ + unsigned long *data_size, void *data) \ +{ \ + struct ia64_fpreg fr[6]; \ + efi_status_t ret; \ + \ + ia64_save_scratch_fpregs(fr); \ + ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \ + adjust_arg(name), adjust_arg(vendor), adjust_arg(attr), \ + adjust_arg(data_size), adjust_arg(data)); \ + ia64_load_scratch_fpregs(fr); \ + return ret; \ +} + +#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \ +static efi_status_t \ +prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) \ +{ \ + struct ia64_fpreg fr[6]; \ + efi_status_t ret; \ + \ + ia64_save_scratch_fpregs(fr); \ + ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable), \ + adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \ + ia64_load_scratch_fpregs(fr); \ + return ret; \ +} + +#define STUB_SET_VARIABLE(prefix, adjust_arg) \ +static efi_status_t \ +prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, u32 attr, \ + unsigned long data_size, void *data) \ +{ \ + struct ia64_fpreg fr[6]; \ + efi_status_t ret; \ + \ + ia64_save_scratch_fpregs(fr); \ + ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable), \ + adjust_arg(name), adjust_arg(vendor), attr, data_size, \ + adjust_arg(data)); \ + ia64_load_scratch_fpregs(fr); \ + return ret; \ +} + +#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \ +static efi_status_t \ +prefix##_get_next_high_mono_count (u64 *count) \ +{ \ + struct ia64_fpreg fr[6]; \ + efi_status_t ret; \ + \ + ia64_save_scratch_fpregs(fr); \ + ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \ + __va(runtime->get_next_high_mono_count), adjust_arg(count)); \ + ia64_load_scratch_fpregs(fr); \ + return ret; \ +} + +#define STUB_RESET_SYSTEM(prefix, adjust_arg) \ +static void \ +prefix##_reset_system (int reset_type, efi_status_t status, \ + unsigned long data_size, efi_char16_t *data) \ +{ \ + struct ia64_fpreg fr[6]; \ + \ + ia64_save_scratch_fpregs(fr); \ + efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \ + reset_type, status, data_size, adjust_arg(data)); \ + /* should not return, but just in case... */ \ + ia64_load_scratch_fpregs(fr); \ +} + +STUB_GET_TIME(phys, __pa) +STUB_SET_TIME(phys, __pa) +STUB_GET_WAKEUP_TIME(phys, __pa) +STUB_SET_WAKEUP_TIME(phys, __pa) +STUB_GET_VARIABLE(phys, __pa) +STUB_GET_NEXT_VARIABLE(phys, __pa) +STUB_SET_VARIABLE(phys, __pa) +STUB_GET_NEXT_HIGH_MONO_COUNT(phys, __pa) +STUB_RESET_SYSTEM(phys, __pa) + +STUB_GET_TIME(virt, ) +STUB_SET_TIME(virt, ) +STUB_GET_WAKEUP_TIME(virt, ) +STUB_SET_WAKEUP_TIME(virt, ) +STUB_GET_VARIABLE(virt, ) +STUB_GET_NEXT_VARIABLE(virt, ) +STUB_SET_VARIABLE(virt, ) +STUB_GET_NEXT_HIGH_MONO_COUNT(virt, ) +STUB_RESET_SYSTEM(virt, ) void efi_gettimeofday (struct timeval *tv) @@ -574,18 +664,17 @@ } /* - * Now that EFI is in virtual mode, we arrange for EFI functions to be - * called directly: + * Now that EFI is in virtual mode, we call the EFI functions more efficiently: */ - efi.get_time = __va(runtime->get_time); - efi.set_time = __va(runtime->set_time); - efi.get_wakeup_time = __va(runtime->get_wakeup_time); - efi.set_wakeup_time = __va(runtime->set_wakeup_time); - efi.get_variable = __va(runtime->get_variable); - efi.get_next_variable = __va(runtime->get_next_variable); - efi.set_variable = __va(runtime->set_variable); - efi.get_next_high_mono_count = __va(runtime->get_next_high_mono_count); - efi.reset_system = __va(runtime->reset_system); + efi.get_time = virt_get_time; + efi.set_time = virt_set_time; + efi.get_wakeup_time = virt_get_wakeup_time; + efi.set_wakeup_time = virt_set_wakeup_time; + efi.get_variable = virt_get_variable; + efi.get_next_variable = virt_get_next_variable; + efi.set_variable = virt_set_variable; + efi.get_next_high_mono_count = virt_get_next_high_mono_count; + efi.reset_system = virt_reset_system; } /* diff -Nru a/arch/ia64/kernel/fw-emu.c b/arch/ia64/kernel/fw-emu.c --- a/arch/ia64/kernel/fw-emu.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/fw-emu.c Thu Oct 24 22:22:20 2002 @@ -2,7 +2,7 @@ * PAL & SAL emulation. * * Copyright (C) 1998-2001 Hewlett-Packard Co - * Copyright (C) 1998-2001 David Mosberger-Tang + * David Mosberger-Tang * * For the HP simulator, this file gets include in boot/bootloader.c. * For SoftSDV, this file gets included in sys_softsdv.c. diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c --- a/arch/ia64/kernel/iosapic.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/iosapic.c Thu Oct 24 22:22:20 2002 @@ -133,12 +133,8 @@ return -1; } -/* - * Translate GSI number to the corresponding IA-64 interrupt vector. If no - * entry exists, return -1. - */ -int -gsi_to_vector (unsigned int gsi) +static inline int +_gsi_to_vector (unsigned int gsi) { struct iosapic_intr_info *info; @@ -148,6 +144,26 @@ return -1; } +/* + * Translate GSI number to the corresponding IA-64 interrupt vector. If no + * entry exists, return -1. + */ +inline int +gsi_to_vector (unsigned int gsi) +{ + return _gsi_to_vector(gsi); +} + +int +gsi_to_irq (unsigned int gsi) +{ + /* + * XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq + * numbers... + */ + return _gsi_to_vector(gsi); +} + static void set_rte (unsigned int vector, unsigned int dest) { @@ -157,7 +173,7 @@ int rte_index; char redir; - DBG(KERN_DEBUG"IOSAPIC: routing vector %d to %x\n", vector, dest); + DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest); rte_index = iosapic_intr_info[vector].rte_index; if (rte_index < 0) diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S --- a/arch/ia64/kernel/ivt.S Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/ivt.S Thu Oct 24 22:22:20 2002 @@ -116,8 +116,8 @@ ;; (p8) dep r25=r18,r25,2,6 (p8) shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT - ;; #endif + ;; cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of the faulting address ;; diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/mca.c Thu Oct 24 22:22:20 2002 @@ -1012,28 +1012,13 @@ void ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc) { - char str_buf[32]; - - sprintf(str_buf, "%2d.%02d", - (lh->revision.major >> 4) * 10 + (lh->revision.major & 0xf), - (lh->revision.minor >> 4) * 10 + (lh->revision.minor & 0xf)); - prfunc("+Err Record ID: %d SAL Rev: %s\n", lh->id, str_buf); - sprintf(str_buf, "%02d/%02d/%04d/ %02d:%02d:%02d", - (lh->timestamp.slh_month >> 4) * 10 + - (lh->timestamp.slh_month & 0xf), - (lh->timestamp.slh_day >> 4) * 10 + - (lh->timestamp.slh_day & 0xf), - (lh->timestamp.slh_century >> 4) * 1000 + - (lh->timestamp.slh_century & 0xf) * 100 + - (lh->timestamp.slh_year >> 4) * 10 + - (lh->timestamp.slh_year & 0xf), - (lh->timestamp.slh_hour >> 4) * 10 + - (lh->timestamp.slh_hour & 0xf), - (lh->timestamp.slh_minute >> 4) * 10 + - (lh->timestamp.slh_minute & 0xf), - (lh->timestamp.slh_second >> 4) * 10 + - (lh->timestamp.slh_second & 0xf)); - prfunc("+Time: %s Severity %d\n", str_buf, lh->severity); + prfunc("+Err Record ID: %d SAL Rev: %2x.%02x\n", lh->id, + lh->revision.major, lh->revision.minor); + prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x Severity %d\n", + lh->timestamp.slh_month, lh->timestamp.slh_day, + lh->timestamp.slh_century, lh->timestamp.slh_year, + lh->timestamp.slh_hour, lh->timestamp.slh_minute, + lh->timestamp.slh_second, lh->severity); } /* diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/perfmon.c Thu Oct 24 22:22:20 2002 @@ -63,6 +63,26 @@ * Misc macros and definitions */ #define PMU_FIRST_COUNTER 4 +#define PMU_MAX_PMCS 256 +#define PMU_MAX_PMDS 256 + +/* + * type of a PMU register (bitmask). + * bitmask structure: + * bit0 : register implemented + * bit1 : end marker + * bit2-3 : reserved + * bit4-7 : register type + * bit8-31: reserved + */ +#define PFM_REG_IMPL 0x1 /* register implemented */ +#define PFM_REG_END 0x2 /* end marker */ +#define PFM_REG_MONITOR (0x1<<4|PFM_REG_IMPL) /* a PMC with a pmc.pm field only */ +#define PFM_REG_COUNTING (0x2<<4|PFM_REG_IMPL) /* a PMC with a pmc.pm AND pmc.oi, a PMD used as a counter */ +#define PFM_REG_CONTROL (0x3<<4|PFM_REG_IMPL) /* PMU control register */ +#define PFM_REG_CONFIG (0x4<<4|PFM_REG_IMPL) /* refine configuration */ +#define PFM_REG_BUFFER (0x5<<4|PFM_REG_IMPL) /* PMD used as buffer */ + #define PFM_IS_DISABLED() pmu_conf.pfm_is_disabled @@ -70,13 +90,18 @@ #define PFM_FL_INHERIT_MASK (PFM_FL_INHERIT_NONE|PFM_FL_INHERIT_ONCE|PFM_FL_INHERIT_ALL) /* i assume unsigned */ -#define PMC_IS_IMPL(i) (i>6] & (1UL<< (i) %64)) -#define PMD_IS_IMPL(i) (i>6)] & (1UL<<(i) % 64)) +#define PMC_IS_IMPL(i) (i< PMU_MAX_PMCS && (pmu_conf.pmc_desc[i].type & PFM_REG_IMPL)) +#define PMD_IS_IMPL(i) (i< PMU_MAX_PMDS && (pmu_conf.pmd_desc[i].type & PFM_REG_IMPL)) /* XXX: these three assume that register i is implemented */ #define PMD_IS_COUNTING(i) (pmu_conf.pmd_desc[i].type == PFM_REG_COUNTING) #define PMC_IS_COUNTING(i) (pmu_conf.pmc_desc[i].type == PFM_REG_COUNTING) #define PMC_IS_MONITOR(i) (pmu_conf.pmc_desc[i].type == PFM_REG_MONITOR) +#define PMC_DFL_VAL(i) pmu_conf.pmc_desc[i].default_value +#define PMC_RSVD_MASK(i) pmu_conf.pmc_desc[i].reserved_mask +#define PMD_PMD_DEP(i) pmu_conf.pmd_desc[i].dep_pmd[0] +#define PMC_PMD_DEP(i) pmu_conf.pmc_desc[i].dep_pmd[0] + /* k assume unsigned */ #define IBR_IS_IMPL(k) (kpsb_lock) /* - * The possible type of a PMU register - */ -typedef enum { - PFM_REG_NOTIMPL, /* not implemented */ - PFM_REG_NONE, /* end marker */ - PFM_REG_MONITOR, /* a PMC with a pmc.pm field only */ - PFM_REG_COUNTING,/* a PMC with a pmc.pm AND pmc.oi, a PMD used as a counter */ - PFM_REG_CONTROL, /* PMU control register */ - PFM_REG_CONFIG, /* refine configuration */ - PFM_REG_BUFFER /* PMD used as buffer */ -} pfm_pmu_reg_type_t; - -/* * 64-bit software counter structure */ typedef struct { @@ -283,13 +295,16 @@ * dep_pmc[]: a bitmask of dependent PMC registers */ typedef struct { - pfm_pmu_reg_type_t type; + unsigned int type; int pm_pos; + unsigned long default_value; /* power-on default value */ + unsigned long reserved_mask; /* bitmask of reserved bits */ int (*read_check)(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs); int (*write_check)(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs); unsigned long dep_pmd[4]; unsigned long dep_pmc[4]; } pfm_reg_desc_t; + /* assume cnum is a valid monitor */ #define PMC_PM(cnum, val) (((val) >> (pmu_conf.pmc_desc[cnum].pm_pos)) & 0x1) #define PMC_WR_FUNC(cnum) (pmu_conf.pmc_desc[cnum].write_check) @@ -401,8 +416,6 @@ }; static struct ctl_table_header *pfm_sysctl_header; -static unsigned long reset_pmcs[IA64_NUM_PMC_REGS]; /* contains PAL reset values for PMCS */ - static void pfm_vm_close(struct vm_area_struct * area); static struct vm_operations_struct pfm_vm_ops={ @@ -422,7 +435,7 @@ /* * forward declarations */ -static void ia64_reset_pmu(struct task_struct *); +static void pfm_reset_pmu(struct task_struct *); #ifdef CONFIG_SMP static void pfm_fetch_regs(int cpu, struct task_struct *task, pfm_context_t *ctx); #endif @@ -2244,7 +2257,7 @@ pfm_lazy_save_regs(PMU_OWNER()); /* reset all registers to stable quiet state */ - ia64_reset_pmu(task); + pfm_reset_pmu(task); /* make sure nothing starts */ if (ctx->ctx_fl_system) { @@ -2307,7 +2320,7 @@ if (!PMC_IS_IMPL(cnum)) goto abort_mission; - tmp.reg_value = reset_pmcs[cnum]; + tmp.reg_value = PMC_DFL_VAL(cnum); PFM_REG_RETFLAG_SET(tmp.reg_flags, 0); @@ -2998,6 +3011,8 @@ p += sprintf(p, "CPU%-2d recorded samples : %lu\n", i, pfm_stats[i].pfm_recorded_samples_count); p += sprintf(p, "CPU%-2d smpl buffer full : %lu\n", i, pfm_stats[i].pfm_full_smpl_buffer_count); p += sprintf(p, "CPU%-2d owner : %d\n", i, pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1); + p += sprintf(p, "CPU%-2d syst_wide : %d\n", i, per_cpu(pfm_syst_wide, i)); + p += sprintf(p, "CPU%-2d dcr_pp : %d\n", i, per_cpu(pfm_dcr_pp, i)); } LOCK_PFS(); @@ -3398,11 +3413,10 @@ * XXX: make this routine able to work with non current context */ static void -ia64_reset_pmu(struct task_struct *task) +pfm_reset_pmu(struct task_struct *task) { struct thread_struct *t = &task->thread; pfm_context_t *ctx = t->pfm_context; - unsigned long mask; int i; if (task != current) { @@ -3415,30 +3429,27 @@ /* * install reset values for PMC. We skip PMC0 (done above) - * XX: good up to 64 PMCS */ - mask = pmu_conf.impl_regs[0] >> 1; - for(i=1; mask; mask>>=1, i++) { - if (mask & 0x1) { - ia64_set_pmc(i, reset_pmcs[i]); - /* - * When restoring context, we must restore ALL pmcs, even the ones - * that the task does not use to avoid leaks and possibly corruption - * of the sesion because of configuration conflicts. So here, we - * initialize the entire set used in the context switch restore routine. - */ - t->pmc[i] = reset_pmcs[i]; - DBprintk((" pmc[%d]=0x%lx\n", i, reset_pmcs[i])); - - } + for (i=1; (pmu_conf.pmc_desc[i].type & PFM_REG_END) == 0; i++) { + if ((pmu_conf.pmc_desc[i].type & PFM_REG_IMPL) == 0) continue; + ia64_set_pmc(i, PMC_DFL_VAL(i)); + /* + * When restoring context, we must restore ALL pmcs, even the ones + * that the task does not use to avoid leaks and possibly corruption + * of the sesion because of configuration conflicts. So here, we + * initialize the entire set used in the context switch restore routine. + */ + t->pmc[i] = PMC_DFL_VAL(i); + DBprintk(("pmc[%d]=0x%lx\n", i, t->pmc[i])); } + /* * clear reset values for PMD. * XXX: good up to 64 PMDS. Suppose that zero is a valid value. */ - mask = pmu_conf.impl_regs[4]; - for(i=0; mask; mask>>=1, i++) { - if (mask & 0x1) ia64_set_pmd(i, 0UL); + for (i=0; (pmu_conf.pmd_desc[i].type & PFM_REG_END) == 0; i++) { + if ((pmu_conf.pmd_desc[i].type & PFM_REG_IMPL) == 0) continue; + ia64_set_pmd(i, 0UL); t->pmd[i] = 0UL; } @@ -4119,23 +4130,6 @@ }; -static void -pfm_pmu_snapshot(void) -{ - int i; - - for (i=0; i < IA64_NUM_PMC_REGS; i++) { - if (i >= pmu_conf.num_pmcs) break; - if (PMC_IS_IMPL(i)) reset_pmcs[i] = ia64_get_pmc(i); - } -#ifdef CONFIG_MCKINLEY - /* - * set the 'stupid' enable bit to power the PMU! - */ - reset_pmcs[4] |= 1UL << 23; -#endif -} - /* * perfmon initialization routine, called from the initcall() table */ @@ -4160,6 +4154,9 @@ } pmu_conf.perf_ovfl_val = (1UL << pm_info.pal_perf_mon_info_s.width) - 1; + /* + * XXX: use the pfm_*_desc tables instead and simply verify with PAL + */ pmu_conf.max_counters = pm_info.pal_perf_mon_info_s.generic; pmu_conf.num_pmcs = find_num_pm_regs(pmu_conf.impl_regs); pmu_conf.num_pmds = find_num_pm_regs(&pmu_conf.impl_regs[4]); @@ -4184,23 +4181,10 @@ pmu_conf.num_dbrs <<=1; /* - * take a snapshot of all PMU registers. PAL is supposed - * to configure them with stable/safe values, i.e., not - * capturing anything. - * We take a snapshot now, before we make any modifications. This - * will become our master copy. Then we will reuse the snapshot - * to reset the PMU in pfm_enable(). Using this technique, perfmon - * does NOT have to know about the specific values to program for - * the PMC/PMD. The safe values may be different from one CPU model to - * the other. - */ - pfm_pmu_snapshot(); - - /* * setup the register configuration descriptions for the CPU */ - pmu_conf.pmc_desc = pmc_desc; - pmu_conf.pmd_desc = pmd_desc; + pmu_conf.pmc_desc = pfm_pmc_desc; + pmu_conf.pmd_desc = pfm_pmd_desc; /* we are all set */ pmu_conf.pfm_is_disabled = 0; @@ -4222,11 +4206,34 @@ void perfmon_init_percpu (void) { + int i; + if (smp_processor_id() == 0) register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction); ia64_set_pmv(IA64_PERFMON_VECTOR); ia64_srlz_d(); + + /* + * we first initialize the PMU to a stable state. + * the values may have been changed from their power-up + * values by software executed before the kernel took over. + * + * At this point, pmu_conf has not yet been initialized + * + * On McKinley, this code is ineffective until PMC4 is initialized. + */ + for (i=1; (pfm_pmc_desc[i].type & PFM_REG_END) == 0; i++) { + if ((pfm_pmc_desc[i].type & PFM_REG_IMPL) == 0) continue; + ia64_set_pmc(i, pfm_pmc_desc[i].default_value); + } + for (i=0; (pfm_pmd_desc[i].type & PFM_REG_END) == 0; i++) { + if ((pfm_pmd_desc[i].type & PFM_REG_IMPL) == 0) continue; + ia64_set_pmd(i, 0UL); + } + ia64_set_pmc(0,1UL); + ia64_srlz_d(); + } #else /* !CONFIG_PERFMON */ diff -Nru a/arch/ia64/kernel/perfmon_generic.h b/arch/ia64/kernel/perfmon_generic.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/kernel/perfmon_generic.h Thu Oct 24 22:22:20 2002 @@ -0,0 +1,29 @@ +#define RDEP(x) (1UL<<(x)) + +#if defined(CONFIG_ITANIUM) || defined(CONFIG_MCKINLEY) +#error "This file should only be used when CONFIG_ITANIUM and CONFIG_MCKINLEY are not defined" +#endif + +static pfm_reg_desc_t pmc_desc[PMU_MAX_PMCS]={ +/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc4 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc5 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc6 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc7 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, + { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +static pfm_reg_desc_t pmd_desc[PMU_MAX_PMDS]={ +/* pmd0 */ { PFM_REG_NOTIMPL , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, +/* pmd1 */ { PFM_REG_NOTIMPL , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, +/* pmd2 */ { PFM_REG_NOTIMPL , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, +/* pmd3 */ { PFM_REG_NOTIMPL , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, +/* pmd4 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}}, +/* pmd5 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}}, +/* pmd6 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}}, +/* pmd7 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}}, + { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; diff -Nru a/arch/ia64/kernel/perfmon_itanium.h b/arch/ia64/kernel/perfmon_itanium.h --- a/arch/ia64/kernel/perfmon_itanium.h Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/perfmon_itanium.h Thu Oct 24 22:22:20 2002 @@ -15,44 +15,44 @@ static int pfm_ita_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs); static int pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs); -static pfm_reg_desc_t pmc_desc[256]={ -/* pmc0 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc1 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc2 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc3 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc4 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc5 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc6 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc7 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc8 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc9 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc10 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc11 */ { PFM_REG_MONITOR, 6, NULL, pfm_ita_pmc_check, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc12 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc13 */ { PFM_REG_CONFIG, 0, NULL, pfm_ita_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, - { PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */ +static pfm_reg_desc_t pfm_pmc_desc[PMU_MAX_PMCS]={ +/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc4 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc8 */ { PFM_REG_CONFIG , 0, 0xf00000003ffffff8UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc9 */ { PFM_REG_CONFIG , 0, 0xf00000003ffffff8UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc10 */ { PFM_REG_MONITOR , 6, 0x0UL, -1UL, NULL, NULL, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc11 */ { PFM_REG_MONITOR , 6, 0x0000000010000000UL, -1UL, NULL, pfm_ita_pmc_check, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc13 */ { PFM_REG_CONFIG , 0, 0x0003ffff00000001UL, -1UL, NULL, pfm_ita_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, + { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ }; -static pfm_reg_desc_t pmd_desc[256]={ -/* pmd0 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, -/* pmd1 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, -/* pmd2 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, -/* pmd3 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, -/* pmd4 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}}, -/* pmd5 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}}, -/* pmd6 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}}, -/* pmd7 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}}, -/* pmd8 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd9 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd10 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd11 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd12 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd13 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd14 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd15 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd16 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd17 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, - { PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */ +static pfm_reg_desc_t pfm_pmd_desc[PMU_MAX_PMDS]={ +/* pmd0 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, +/* pmd1 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, +/* pmd2 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, +/* pmd3 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, +/* pmd4 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}}, +/* pmd5 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}}, +/* pmd6 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}}, +/* pmd7 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}}, +/* pmd8 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd9 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd10 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd11 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd12 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd13 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd14 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd15 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd16 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd17 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, + { PFM_REG_END , 0, 0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ }; static int diff -Nru a/arch/ia64/kernel/perfmon_mckinley.h b/arch/ia64/kernel/perfmon_mckinley.h --- a/arch/ia64/kernel/perfmon_mckinley.h Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/perfmon_mckinley.h Thu Oct 24 22:22:20 2002 @@ -12,51 +12,73 @@ #error "This file is only valid when CONFIG_MCKINLEY is defined" #endif +static int pfm_mck_reserved(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs); static int pfm_mck_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs); static int pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs); -static pfm_reg_desc_t pmc_desc[256]={ -/* pmc0 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc1 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc2 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc3 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc4 */ { PFM_REG_COUNTING, 6, NULL, pfm_mck_pmc_check, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc5 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc6 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc7 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc8 */ { PFM_REG_CONFIG, 0, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc9 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc10 */ { PFM_REG_MONITOR, 4, NULL, NULL, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc11 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc12 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc13 */ { PFM_REG_CONFIG, 0, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc14 */ { PFM_REG_CONFIG, 0, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc15 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, - { PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */ +static pfm_reg_desc_t pfm_pmc_desc[PMU_MAX_PMCS]={ +/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc4 */ { PFM_REG_COUNTING, 6, 0x0000000000800000UL, 0xfffff7fUL, NULL, pfm_mck_pmc_check, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc10 */ { PFM_REG_MONITOR , 4, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc11 */ { PFM_REG_MONITOR , 6, 0x0UL, 0x30f01cf, NULL, pfm_mck_reserved, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc13 */ { PFM_REG_CONFIG , 0, 0x00002078fefefefeUL, 0x1e00018181818UL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc14 */ { PFM_REG_CONFIG , 0, 0x0db60db60db60db6UL, 0x2492UL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc15 */ { PFM_REG_CONFIG , 0, 0x00000000fffffff0UL, 0xfUL, NULL, pfm_mck_reserved, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, + { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ }; -static pfm_reg_desc_t pmd_desc[256]={ -/* pmd0 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, -/* pmd1 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, -/* pmd2 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, -/* pmd3 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, -/* pmd4 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}}, -/* pmd5 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}}, -/* pmd6 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}}, -/* pmd7 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}}, -/* pmd8 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd9 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd10 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd11 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd12 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd13 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd14 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd15 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd16 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, -/* pmd17 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, - { PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */ +static pfm_reg_desc_t pfm_pmd_desc[PMU_MAX_PMDS]={ +/* pmd0 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, +/* pmd1 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, +/* pmd2 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, +/* pmd3 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, +/* pmd4 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}}, +/* pmd5 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}}, +/* pmd6 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}}, +/* pmd7 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}}, +/* pmd8 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd9 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd10 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd11 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd12 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd13 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd14 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd15 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd16 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd17 */ { PFM_REG_BUFFER , 0, 0x0UL, -1UL, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, + { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ }; +/* + * PMC reserved fields must have their power-up values preserved + */ +static int +pfm_mck_reserved(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs) +{ + unsigned long tmp1, tmp2, ival = *val; + + /* remove reserved areas from user value */ + tmp1 = ival & PMC_RSVD_MASK(cnum); + + /* get reserved fields values */ + tmp2 = PMC_DFL_VAL(cnum) & ~PMC_RSVD_MASK(cnum); + + *val = tmp1 | tmp2; + + DBprintk(("pmc[%d]=0x%lx, mask=0x%lx, reset=0x%lx, val=0x%lx\n", + cnum, ival, PMC_RSVD_MASK(cnum), PMC_DFL_VAL(cnum), *val)); + return 0; +} + static int pfm_mck_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs) { @@ -65,6 +87,9 @@ int ret = 0, check_case1 = 0; unsigned long val8 = 0, val14 = 0, val13 = 0; + /* first preserve the reserved fields */ + pfm_mck_reserved(task, cnum, val, regs); + /* * we must clear the debug registers if any pmc13.ena_dbrpX bit is enabled * before they are written (fl_using_dbreg==0) to avoid picking up stale information. @@ -105,7 +130,10 @@ case 8: val8 = *val; val13 = th->pmc[13]; val14 = th->pmc[14]; + *val |= 1UL << 2; /* bit 2 must always be 1 */ check_case1 = 1; + break; + case 9: *val |= 1UL << 2; /* bit 2 must always be 1 */ break; case 13: val8 = th->pmc[8]; val13 = *val; diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c --- a/arch/ia64/kernel/process.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/process.c Thu Oct 24 22:22:20 2002 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -45,8 +46,9 @@ do_show_stack (struct unw_frame_info *info, void *arg) { unsigned long ip, sp, bsp; + char buf[80]; /* don't make it so big that it overflows the stack! */ - printk("\nCall Trace: "); + printk("\nCall Trace:\n"); do { unw_get_ip(info, &ip); if (ip == 0) @@ -54,7 +56,9 @@ unw_get_sp(info, &sp); unw_get_bsp(info, &bsp); - printk("[<%016lx>] sp=0x%016lx bsp=0x%016lx\n", ip, sp, bsp); + snprintf(buf, sizeof(buf), " [<%016lx>] %%s sp=0x%016lx bsp=0x%016lx\n", + ip, sp, bsp); + print_symbol(buf, ip); } while (unw_unwind(info) >= 0); } @@ -94,6 +98,7 @@ printk("\nPid: %d, comm: %20s\n", current->pid, current->comm); printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s\n", regs->cr_ipsr, regs->cr_ifs, ip, print_tainted()); + print_symbol("ip is at %s\n", ip); printk("unat: %016lx pfs : %016lx rsc : %016lx\n", regs->ar_unat, regs->ar_pfs, regs->ar_rsc); printk("rnat: %016lx bsps: %016lx pr : %016lx\n", @@ -199,10 +204,8 @@ if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0) pfm_save_regs(task); -# ifdef CONFIG_SMP if (__get_cpu_var(pfm_syst_wide)) pfm_syst_wide_update_task(task, 0); -# endif #endif #ifdef CONFIG_IA32_SUPPORT @@ -221,9 +224,8 @@ if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0) pfm_load_regs(task); -# ifdef CONFIG_SMP - if (__get_cpu_var(pfm_syst_wide)) pfm_syst_wide_update_task(task, 1); -# endif + if (__get_cpu_var(pfm_syst_wide)) + pfm_syst_wide_update_task(task, 1); #endif #ifdef CONFIG_IA32_SUPPORT diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c --- a/arch/ia64/kernel/setup.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/setup.c Thu Oct 24 22:22:20 2002 @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -49,9 +50,6 @@ # error "struct cpuinfo_ia64 too big!" #endif -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) > (b) ? (a) : (b)) - extern char _end; #ifdef CONFIG_SMP @@ -95,6 +93,10 @@ static struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1]; static int num_rsvd_regions; +#define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */ + +#ifndef CONFIG_DISCONTIGMEM + static unsigned long bootmap_start; /* physical address where the bootmem map is located */ static int @@ -108,17 +110,63 @@ return 0; } -#define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */ +#else /* CONFIG_DISCONTIGMEM */ /* - * Free available memory based on the primitive map created from - * the boot parameters. This routine does not assume the incoming - * segments are sorted. + * efi_memmap_walk() knows nothing about layout of memory across nodes. Find + * out to which node a block of memory belongs. Ignore memory that we cannot + * identify, and split blocks that run across multiple nodes. + * + * Take this opportunity to round the start address up and the end address + * down to page boundaries. */ -static int -free_available_memory (unsigned long start, unsigned long end, void *arg) +void +call_pernode_memory (unsigned long start, unsigned long end, void *arg) +{ + unsigned long rs, re; + void (*func)(unsigned long, unsigned long, int, int); + int i; + + start = PAGE_ALIGN(start); + end &= PAGE_MASK; + if (start >= end) + return; + + func = arg; + + if (!num_memblks) { + /* + * This machine doesn't have SRAT, so call func with + * nid=0, bank=0. + */ + if (start < end) + (*func)(start, end - start, 0, 0); + return; + } + + for (i = 0; i < num_memblks; i++) { + rs = max(start, node_memblk[i].start_paddr); + re = min(end, node_memblk[i].start_paddr+node_memblk[i].size); + + if (rs < re) + (*func)(rs, re-rs, node_memblk[i].nid, + node_memblk[i].bank); + } +} + +#endif /* CONFIG_DISCONTIGMEM */ + +/* + * Filter incoming memory segments based on the primitive map created from the boot + * parameters. Segments contained in the map are removed from the memory ranges. A + * caller-specified function is called with the memory ranges that remain after filtering. + * This routine does not assume the incoming segments are sorted. + */ +int +filter_rsvd_memory (unsigned long start, unsigned long end, void *arg) { unsigned long range_start, range_end, prev_start; + void (*func)(unsigned long, unsigned long); int i; #if IGNORE_PFN0 @@ -132,13 +180,18 @@ * lowest possible address(walker uses virtual) */ prev_start = PAGE_OFFSET; + func = arg; for (i = 0; i < num_rsvd_regions; ++i) { - range_start = MAX(start, prev_start); - range_end = MIN(end, rsvd_region[i].start); + range_start = max(start, prev_start); + range_end = min(end, rsvd_region[i].start); if (range_start < range_end) - free_bootmem(__pa(range_start), range_end - range_start); +#ifdef CONFIG_DISCONTIGMEM + call_pernode_memory(__pa(range_start), __pa(range_end), func); +#else + (*func)(__pa(range_start), range_end - range_start); +#endif /* nothing more available in this segment */ if (range_end == end) return 0; @@ -150,6 +203,7 @@ } +#ifndef CONFIG_DISCONTIGMEM /* * Find a place to put the bootmap and return its starting address in bootmap_start. * This address must be page-aligned. @@ -171,8 +225,8 @@ free_start = PAGE_OFFSET; for (i = 0; i < num_rsvd_regions; i++) { - range_start = MAX(start, free_start); - range_end = MIN(end, rsvd_region[i].start & PAGE_MASK); + range_start = max(start, free_start); + range_end = min(end, rsvd_region[i].start & PAGE_MASK); if (range_end <= range_start) continue; /* skip over empty range */ @@ -188,6 +242,7 @@ } return 0; } +#endif /* !CONFIG_DISCONTIGMEM */ static void sort_regions (struct rsvd_region *rsvd_region, int max) @@ -252,6 +307,15 @@ sort_regions(rsvd_region, num_rsvd_regions); +#ifdef CONFIG_DISCONTIGMEM + { + extern void discontig_mem_init (void); + + bootmap_size = max_pfn = 0; /* stop gcc warnings */ + discontig_mem_init(); + } +#else /* !CONFIG_DISCONTIGMEM */ + /* first find highest page frame number */ max_pfn = 0; efi_memmap_walk(find_max_pfn, &max_pfn); @@ -268,8 +332,9 @@ bootmap_size = init_bootmem(bootmap_start >> PAGE_SHIFT, max_pfn); /* Free all available memory, then mark bootmem-map as being in use. */ - efi_memmap_walk(free_available_memory, 0); + efi_memmap_walk(filter_rsvd_memory, free_bootmem); reserve_bootmem(bootmap_start, bootmap_size); +#endif /* !CONFIG_DISCONTIGMEM */ #ifdef CONFIG_BLK_DEV_INITRD if (ia64_boot_param->initrd_start) { @@ -296,6 +361,16 @@ efi_init(); +#ifdef CONFIG_ACPI_BOOT + /* Initialize the ACPI boot-time table parser */ + acpi_table_init(*cmdline_p); + +#ifdef CONFIG_ACPI_NUMA + acpi_numa_init(); +#endif + +#endif /* CONFIG_APCI_BOOT */ + find_memory(); #if 0 @@ -530,6 +605,7 @@ /* start_kernel() requires this... */ } + /* * cpu_init() initializes state that is per-CPU. This function acts * as a 'CPU state barrier', nothing should get across. @@ -553,6 +629,26 @@ panic("Per-cpu data area too big! (%Zu > %Zu)", __per_cpu_end - __per_cpu_start, PAGE_SIZE); +# ifdef CONFIG_NUMA + { + static unsigned long boot_cpu_data; + + /* + * get_free_pages() cannot be used before cpu_init() done. BSP allocates + * "NR_CPUS" pages for all CPUs to avoid that AP calls get_zeroed_page(). + */ + if (cpu == 0) + boot_cpu_data = (unsigned long)alloc_bootmem_pages(PAGE_SIZE * NR_CPUS); + my_cpu_data = (void *)(boot_cpu_data + (cpu * PAGE_SIZE)); + + memcpy(my_cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); + __per_cpu_offset[cpu] = (char *) my_cpu_data - __per_cpu_start; + my_cpu_info = my_cpu_data + ((char *) &__get_cpu_var(cpu_info) - __per_cpu_start); + + my_cpu_info->node_data = get_node_data_ptr(); + my_cpu_info->nodeid = boot_get_local_nodeid(); + } +# else /* !CONFIG_NUMA */ /* * On the BSP, the page allocator isn't initialized by the time we get here. On * the APs, the bootmem allocator is no longer available... @@ -564,9 +660,10 @@ memcpy(my_cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); __per_cpu_offset[cpu] = (char *) my_cpu_data - __per_cpu_start; my_cpu_info = my_cpu_data + ((char *) &__get_cpu_var(cpu_info) - __per_cpu_start); -#else +# endif /* !CONFIG_NUMA */ +#else /* !CONFIG_SMP */ my_cpu_data = __phys_per_cpu_start; -#endif +#endif /* !CONFIG_SMP */ my_cpu_info = my_cpu_data + ((char *) &__get_cpu_var(cpu_info) - __per_cpu_start); /* @@ -579,7 +676,7 @@ #ifdef CONFIG_MCKINLEY { -#define FEATURE_SET 16 +# define FEATURE_SET 16 struct ia64_pal_retval iprv; if (my_cpu_info->family == 0x1f) { diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c --- a/arch/ia64/kernel/signal.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/signal.c Thu Oct 24 22:22:20 2002 @@ -41,6 +41,16 @@ # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) #endif +register double f16 asm ("f16"); register double f17 asm ("f17"); +register double f18 asm ("f18"); register double f19 asm ("f19"); +register double f20 asm ("f20"); register double f21 asm ("f21"); +register double f22 asm ("f22"); register double f23 asm ("f23"); + +register double f24 asm ("f24"); register double f25 asm ("f25"); +register double f26 asm ("f26"); register double f27 asm ("f27"); +register double f28 asm ("f28"); register double f29 asm ("f29"); +register double f30 asm ("f30"); register double f31 asm ("f31"); + long ia64_rt_sigsuspend (sigset_t *uset, size_t sigsetsize, struct sigscratch *scr) { @@ -58,13 +68,13 @@ sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sig->siglock); { oldset = current->blocked; current->blocked = set; recalc_sigpending(); } - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sig->siglock); /* * The return below usually returns to the signal handler. We need to @@ -264,12 +274,12 @@ sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sig->siglock); { current->blocked = set; recalc_sigpending(); } - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sig->siglock); if (restore_sigcontext(sc, scr)) goto give_sigsegv; @@ -458,13 +468,13 @@ ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NODEFER)) { - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sig->siglock); { sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); sigaddset(¤t->blocked, sig); recalc_sigpending(); } - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sig->siglock); } return 1; } diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c --- a/arch/ia64/kernel/smpboot.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/smpboot.c Thu Oct 24 22:22:20 2002 @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -426,6 +427,37 @@ cpu++; } } + +#ifdef CONFIG_NUMA + +char cpu_to_node_map[NR_CPUS] __cacheline_aligned; + +/* + * Build cpu to node mapping. + */ +void __init +build_cpu_to_node_map (void) +{ + int cpu, i; + + for(cpu = 0; cpu < NR_CPUS; ++cpu) { + /* + * All Itanium NUMA platforms I know use ACPI, so maybe we + * can drop this ifdef completely. [EF] + */ +#ifdef CONFIG_ACPI_NUMA + for (i = 0; i < NR_CPUS; ++i) + if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) { + cpu_to_node_map[cpu] = node_cpuid[i].nid; + break; + } +#else +# error Fixme: Dunno how to build CPU-to-node map. +#endif + } +} + +#endif /* CONFIG_NUMA */ /* * Cycle through the APs sending Wakeup IPIs to boot each. diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c --- a/arch/ia64/kernel/sys_ia64.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/sys_ia64.c Thu Oct 24 22:22:20 2002 @@ -282,18 +282,20 @@ extern int free_hugepages(struct vm_area_struct *); int retval; - vma = find_vma(mm, addr); - if (!vma || !is_vm_hugetlb_page(vma) || (vma->vm_start != addr)) - return -EINVAL; - down_write(&mm->mmap_sem); { + vma = find_vma(mm, addr); + if (!vma || !is_vm_hugetlb_page(vma) || (vma->vm_start != addr)) + retval = -EINVAL; + goto out; + spin_lock(&mm->page_table_lock); { retval = free_hugepages(vma); } spin_unlock(&mm->page_table_lock); } +out: up_write(&mm->mmap_sem); return retval; } diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c --- a/arch/ia64/kernel/time.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/time.c Thu Oct 24 22:22:20 2002 @@ -35,6 +35,7 @@ #endif +#if 0 static void do_profile (unsigned long ip) { @@ -58,6 +59,7 @@ atomic_inc((atomic_t *) &prof_buffer[ip]); } +#endif /* * Return the number of micro-seconds that elapsed since the last update to jiffy. The @@ -166,8 +168,11 @@ * four so that we can use a prof_shift of 2 to get instruction-level * instead of just bundle-level accuracy. */ +#if 0 + XXX fix me! if (!user_mode(regs)) do_profile(regs->cr_iip + 4*ia64_psr(regs)->ri); +#endif #ifdef CONFIG_SMP smp_do_timer(regs); diff -Nru a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c --- a/arch/ia64/kernel/traps.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/kernel/traps.c Thu Oct 24 22:22:20 2002 @@ -54,8 +54,8 @@ if (ia64_boot_param->fpswa) { /* FPSWA fixup: make the interface pointer a kernel virtual address: */ fpswa_interface = __va(ia64_boot_param->fpswa); - major = fpswa_interface->revision & 0xffff; - minor = fpswa_interface->revision >> 16; + major = fpswa_interface->revision >> 16; + minor = fpswa_interface->revision & 0xffff; } printk("fpswa interface at %lx (rev %d.%d)\n", ia64_boot_param->fpswa, major, minor); } @@ -69,7 +69,6 @@ { int loglevel_save = console_loglevel; - spin_lock_init(&timerlist_lock); if (yes) { oops_in_progress = 1; return; diff -Nru a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile --- a/arch/ia64/lib/Makefile Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/lib/Makefile Thu Oct 24 22:22:20 2002 @@ -2,6 +2,8 @@ # Makefile for ia64-specific library routines.. # +THIS = arch/$(ARCH)/lib + L_TARGET = lib.a export-objs := swiotlb.o @@ -32,26 +34,26 @@ AFLAGS___modsi3.o = -DMODULO AFLAGS___umodsi3.o = -DUNSIGNED -DMODULO -__divdi3.o: idiv64.S +$(THIS)/__divdi3.o: $(THIS)/idiv64.S $(cmd_as_o_S) -__udivdi3.o: idiv64.S +$(THIS)/__udivdi3.o: $(THIS)/idiv64.S $(cmd_as_o_S) -__moddi3.o: idiv64.S +$(THIS)/__moddi3.o: $(THIS)/idiv64.S $(cmd_as_o_S) -__umoddi3.o: idiv64.S +$(THIS)/__umoddi3.o: $(THIS)/idiv64.S $(cmd_as_o_S) -__divsi3.o: idiv32.S +$(THIS)/__divsi3.o: $(THIS)/idiv32.S $(cmd_as_o_S) -__udivsi3.o: idiv32.S +$(THIS)/__udivsi3.o: $(THIS)/idiv32.S $(cmd_as_o_S) -__modsi3.o: idiv32.S +$(THIS)/__modsi3.o: $(THIS)/idiv32.S $(cmd_as_o_S) -__umodsi3.o: idiv32.S +$(THIS)/__umodsi3.o: $(THIS)/idiv32.S $(cmd_as_o_S) diff -Nru a/arch/ia64/mm/Makefile b/arch/ia64/mm/Makefile --- a/arch/ia64/mm/Makefile Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/mm/Makefile Thu Oct 24 22:22:20 2002 @@ -9,5 +9,7 @@ obj-y := init.o fault.o tlb.o extable.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o +obj-$(CONFIG_NUMA) += numa.o +obj-$(CONFIG_DISCONTIGMEM) += discontig.o include $(TOPDIR)/Rules.make diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/mm/discontig.c Thu Oct 24 22:22:20 2002 @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2001 Intel Corp. + * Copyright (c) 2001 Tony Luck + * Copyright (c) 2002 NEC Corp. + * Copyright (c) 2002 Kimio Suganuma + */ + +/* + * Platform initialization for Discontig Memory + */ + +#include +#include +#include +#include +#include +#include + + +/* + * Round an address upward to the next multiple of GRANULE size. + */ +#define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1)) + +static struct ia64_node_data *node_data[NR_NODES]; +static long boot_pg_data[8*NR_NODES+sizeof(pg_data_t)] __initdata; +static pg_data_t *pg_data_ptr[NR_NODES] __initdata; +static bootmem_data_t bdata[NR_NODES][NR_BANKS_PER_NODE+1] __initdata; + +extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg); + +/* + * Return the compact node number of this cpu. Used prior to + * setting up the cpu_data area. + * Note - not fast, intended for boot use only!! + */ +int +boot_get_local_nodeid(void) +{ + int i; + + for (i = 0; i < NR_CPUS; i++) + if (node_cpuid[i].phys_id == hard_smp_processor_id()) + return node_cpuid[i].nid; + + /* node info missing, so nid should be 0.. */ + return 0; +} + +/* + * Return a pointer to the pg_data structure for a node. + * This function is used ONLY in early boot before the cpu_data + * structure is available. + */ +pg_data_t* __init +boot_get_pg_data_ptr(long node) +{ + return pg_data_ptr[node]; +} + + +/* + * Return a pointer to the node data for the current node. + * (boottime initialization only) + */ +struct ia64_node_data * +get_node_data_ptr(void) +{ + return node_data[boot_get_local_nodeid()]; +} + +/* + * We allocate one of the bootmem_data_t structs for each piece of memory + * that we wish to treat as a contiguous block. Each such block must start + * on a BANKSIZE boundary. Multiple banks per node is not supported. + */ +static int __init +build_maps(unsigned long pstart, unsigned long length, int node) +{ + bootmem_data_t *bdp; + unsigned long cstart, epfn; + + bdp = pg_data_ptr[node]->bdata; + epfn = GRANULEROUNDUP(pstart + length) >> PAGE_SHIFT; + cstart = pstart & ~(BANKSIZE - 1); + + if (!bdp->node_low_pfn) { + bdp->node_boot_start = cstart; + bdp->node_low_pfn = epfn; + } else { + bdp->node_boot_start = min(cstart, bdp->node_boot_start); + bdp->node_low_pfn = max(epfn, bdp->node_low_pfn); + } + + min_low_pfn = min(min_low_pfn, bdp->node_boot_start>>PAGE_SHIFT); + max_low_pfn = max(max_low_pfn, bdp->node_low_pfn); + + return 0; +} + +/* + * Find space on each node for the bootmem map. + * + * Called by efi_memmap_walk to find boot memory on each node. Note that + * only blocks that are free are passed to this routine (currently filtered by + * free_available_memory). + */ +static int __init +find_bootmap_space(unsigned long pstart, unsigned long length, int node) +{ + unsigned long mapsize, pages, epfn; + bootmem_data_t *bdp; + + epfn = (pstart + length) >> PAGE_SHIFT; + bdp = &pg_data_ptr[node]->bdata[0]; + + if (pstart < bdp->node_boot_start || epfn > bdp->node_low_pfn) + return 0; + + if (!bdp->node_bootmem_map) { + pages = bdp->node_low_pfn - (bdp->node_boot_start>>PAGE_SHIFT); + mapsize = bootmem_bootmap_pages(pages) << PAGE_SHIFT; + if (length > mapsize) { + init_bootmem_node( + BOOT_NODE_DATA(node), + pstart>>PAGE_SHIFT, + bdp->node_boot_start>>PAGE_SHIFT, + bdp->node_low_pfn); + } + + } + + return 0; +} + + +/* + * Free available memory to the bootmem allocator. + * + * Note that only blocks that are free are passed to this routine (currently + * filtered by free_available_memory). + * + */ +static int __init +discontig_free_bootmem_node(unsigned long pstart, unsigned long length, int node) +{ + free_bootmem_node(BOOT_NODE_DATA(node), pstart, length); + + return 0; +} + + +/* + * Reserve the space used by the bootmem maps. + */ +static void __init +discontig_reserve_bootmem(void) +{ + int node; + unsigned long mapbase, mapsize, pages; + bootmem_data_t *bdp; + + for (node = 0; node < numnodes; node++) { + bdp = BOOT_NODE_DATA(node)->bdata; + + pages = bdp->node_low_pfn - (bdp->node_boot_start>>PAGE_SHIFT); + mapsize = bootmem_bootmap_pages(pages) << PAGE_SHIFT; + mapbase = __pa(bdp->node_bootmem_map); + reserve_bootmem_node(BOOT_NODE_DATA(node), mapbase, mapsize); + } +} + +/* + * Allocate per node tables. + * - the pg_data structure is allocated on each node. This minimizes offnode + * memory references + * - the node data is allocated & initialized. Portions of this structure is read-only (after + * boot) and contains node-local pointers to usefuls data structures located on + * other nodes. + * + * We also switch to using the "real" pg_data structures at this point. Earlier in boot, we + * use a different structure. The only use for pg_data prior to the point in boot is to get + * the pointer to the bdata for the node. + */ +static void __init +allocate_pernode_structures(void) +{ + pg_data_t *pgdat=0, *new_pgdat_list=0; + int node, mynode; + + mynode = boot_get_local_nodeid(); + for (node = numnodes - 1; node >= 0 ; node--) { + node_data[node] = alloc_bootmem_node(BOOT_NODE_DATA(node), sizeof (struct ia64_node_data)); + pgdat = __alloc_bootmem_node(BOOT_NODE_DATA(node), sizeof(pg_data_t), SMP_CACHE_BYTES, 0); + pgdat->bdata = &(bdata[node][0]); + pg_data_ptr[node] = pgdat; + pgdat->pgdat_next = new_pgdat_list; + new_pgdat_list = pgdat; + } + + memcpy(node_data[mynode]->pg_data_ptrs, pg_data_ptr, sizeof(pg_data_ptr)); + memcpy(node_data[mynode]->node_data_ptrs, node_data, sizeof(node_data)); + + pgdat_list = new_pgdat_list; +} + +/* + * Called early in boot to setup the boot memory allocator, and to + * allocate the node-local pg_data & node-directory data structures.. + */ +void __init +discontig_mem_init(void) +{ + int node; + + if (numnodes == 0) { + printk("node info missing!\n"); + numnodes = 1; + } + + for (node = 0; node < numnodes; node++) { + pg_data_ptr[node] = (pg_data_t*) &boot_pg_data[node]; + pg_data_ptr[node]->bdata = &bdata[node][0]; + } + + min_low_pfn = -1; + max_low_pfn = 0; + + efi_memmap_walk(filter_rsvd_memory, build_maps); + efi_memmap_walk(filter_rsvd_memory, find_bootmap_space); + efi_memmap_walk(filter_rsvd_memory, discontig_free_bootmem_node); + discontig_reserve_bootmem(); + allocate_pernode_structures(); +} + +/* + * Initialize the paging system. + * - determine sizes of each node + * - initialize the paging system for the node + * - build the nodedir for the node. This contains pointers to + * the per-bank mem_map entries. + * - fix the page struct "virtual" pointers. These are bank specific + * values that the paging system doesnt understand. + * - replicate the nodedir structure to other nodes + */ + +void __init +discontig_paging_init(void) +{ + int node, mynode; + unsigned long max_dma, zones_size[MAX_NR_ZONES]; + unsigned long kaddr, ekaddr, bid; + struct page *page; + bootmem_data_t *bdp; + + max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT; + + mynode = boot_get_local_nodeid(); + for (node = 0; node < numnodes; node++) { + long pfn, startpfn; + + memset(zones_size, 0, sizeof(zones_size)); + + startpfn = -1; + bdp = BOOT_NODE_DATA(node)->bdata; + pfn = bdp->node_boot_start >> PAGE_SHIFT; + if (startpfn == -1) + startpfn = pfn; + if (pfn > max_dma) + zones_size[ZONE_NORMAL] += (bdp->node_low_pfn - pfn); + else if (bdp->node_low_pfn < max_dma) + zones_size[ZONE_DMA] += (bdp->node_low_pfn - pfn); + else { + zones_size[ZONE_DMA] += (max_dma - pfn); + zones_size[ZONE_NORMAL] += (bdp->node_low_pfn - max_dma); + } + + free_area_init_node(node, NODE_DATA(node), NULL, zones_size, startpfn, 0); + + page = NODE_DATA(node)->node_mem_map; + + bdp = BOOT_NODE_DATA(node)->bdata; + + kaddr = (unsigned long)__va(bdp->node_boot_start); + ekaddr = (unsigned long)__va(bdp->node_low_pfn << PAGE_SHIFT); + while (kaddr < ekaddr) { + bid = BANK_MEM_MAP_INDEX(kaddr); + node_data[mynode]->node_id_map[bid] = node; + node_data[mynode]->bank_mem_map_base[bid] = page; + kaddr += BANKSIZE; + page += BANKSIZE/PAGE_SIZE; + } + } + + /* + * Finish setting up the node data for this node, then copy it to the other nodes. + */ + for (node=0; node < numnodes; node++) + if (mynode != node) { + memcpy(node_data[node], node_data[mynode], sizeof(struct ia64_node_data)); + node_data[node]->node = node; + } +} + diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c --- a/arch/ia64/mm/init.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/mm/init.c Thu Oct 24 22:22:20 2002 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -78,7 +79,7 @@ vma->vm_mm = current->mm; vma->vm_start = IA64_RBS_BOT; vma->vm_end = vma->vm_start + PAGE_SIZE; - vma->vm_page_prot = protection_map[VM_READ | VM_WRITE]; + vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7]; vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP; vma->vm_ops = NULL; vma->vm_pgoff = 0; @@ -347,6 +348,15 @@ extern struct list_head htlbpage_freelist; #endif +#ifdef CONFIG_DISCONTIGMEM +void +paging_init (void) +{ + extern void discontig_paging_init(void); + + discontig_paging_init(); +} +#else /* !CONFIG_DISCONTIGMEM */ void paging_init (void) { @@ -365,6 +375,7 @@ } free_area_init(zones_size); } +#endif /* !CONFIG_DISCONTIGMEM */ static int count_pages (u64 start, u64 end, void *arg) @@ -380,10 +391,9 @@ { unsigned long num_reserved = 0; unsigned long *count = arg; - struct page *pg; - for (pg = virt_to_page(start); pg < virt_to_page(end); ++pg) - if (PageReserved(pg)) + for (; start < end; start += PAGE_SIZE) + if (PageReserved(virt_to_page(start))) ++num_reserved; *count += num_reserved; return 0; @@ -395,6 +405,7 @@ extern char __start_gate_section[]; long reserved_pages, codesize, datasize, initsize; unsigned long num_pgt_pages; + pg_data_t *pgdat; #ifdef CONFIG_PCI /* @@ -405,16 +416,19 @@ platform_pci_dma_init(); #endif +#ifndef CONFIG_DISCONTIGMEM if (!mem_map) BUG(); + max_mapnr = max_low_pfn; +#endif num_physpages = 0; efi_memmap_walk(count_pages, &num_physpages); - max_mapnr = max_low_pfn; high_memory = __va(max_low_pfn * PAGE_SIZE); - totalram_pages += free_all_bootmem(); + for_each_pgdat(pgdat) + totalram_pages += free_all_bootmem_node(pgdat); reserved_pages = 0; efi_memmap_walk(count_reserved_pages, &reserved_pages); @@ -425,7 +439,7 @@ printk("Memory: %luk/%luk available (%luk code, %luk reserved, %luk data, %luk init)\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT - 10), - max_mapnr << (PAGE_SHIFT - 10), codesize >> 10, reserved_pages << (PAGE_SHIFT - 10), + num_physpages << (PAGE_SHIFT - 10), codesize >> 10, reserved_pages << (PAGE_SHIFT - 10), datasize >> 10, initsize >> 10); /* @@ -440,6 +454,8 @@ num_pgt_pages = nr_free_pages() / 10; if (num_pgt_pages > pgt_cache_water[1]) pgt_cache_water[1] = num_pgt_pages; + + show_mem(); /* install the gate page in the global page table: */ put_gate_page(virt_to_page(__start_gate_section), GATE_ADDR); diff -Nru a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/mm/numa.c Thu Oct 24 22:22:20 2002 @@ -0,0 +1,46 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * This file contains NUMA specific variables and functions which can + * be split away from DISCONTIGMEM and are used on NUMA machines with + * contiguous memory. + * + * 2002/08/07 Erich Focht + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * The following structures are usually initialized by ACPI or + * similar mechanisms and describe the NUMA characteristics of the machine. + */ +int num_memblks = 0; +struct node_memblk_s node_memblk[NR_MEMBLKS]; +struct node_cpuid_s node_cpuid[NR_CPUS]; +/* + * This is a matrix with "distances" between nodes, they should be + * proportional to the memory access latency ratios. + */ +u8 numa_slit[NR_NODES * NR_NODES]; + +/* Identify which cnode a physical address resides on */ +int +paddr_to_nid(unsigned long paddr) +{ + int i; + + for (i = 0; i < num_memblks; i++) + if (paddr >= node_memblk[i].start_paddr && + paddr < node_memblk[i].start_paddr + node_memblk[i].size) + break; + + return (i < num_memblks) ? node_memblk[i].nid : -1; +} diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/pci/pci.c Thu Oct 24 22:22:20 2002 @@ -141,13 +141,13 @@ /* * Called after each bus is probed, but before its children are examined. */ -void __init +void __devinit pcibios_fixup_bus (struct pci_bus *b) { return; } -void __init +void __devinit pcibios_update_resource (struct pci_dev *dev, struct resource *root, struct resource *res, int resource) { @@ -163,7 +163,7 @@ /* ??? FIXME -- record old value for shutdown. */ } -void __init +void __devinit pcibios_update_irq (struct pci_dev *dev, int irq) { pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); @@ -171,7 +171,7 @@ /* ??? FIXME -- record old value for shutdown. */ } -void __init +void __devinit pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges) { } diff -Nru a/arch/ia64/tools/Makefile b/arch/ia64/tools/Makefile --- a/arch/ia64/tools/Makefile Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/tools/Makefile Thu Oct 24 22:22:20 2002 @@ -1,5 +1,6 @@ CFLAGS = -g -O2 -Wall $(CPPFLAGS) +THIS = arch/$(ARCH)/tools TARGET = $(TOPDIR)/include/asm-ia64/offsets.h all: @@ -9,13 +10,14 @@ mrproper: clean clean: - rm -f print_offsets.s print_offsets offsets.h + rm -f $(THIS)/print_offsets.s $(THIS)/print_offsets $(THIS)/offsets.h -$(TARGET): offsets.h - @if ! cmp -s offsets.h ${TARGET}; then \ +$(TARGET): $(THIS)/offsets.h + echo here we go + if ! cmp -s $(THIS)/offsets.h ${TARGET}; then \ echo -e "*** Updating ${TARGET}..."; \ - cp offsets.h ${TARGET}; \ - else \ + cp $(THIS)/offsets.h ${TARGET}; \ + else \ echo "*** ${TARGET} is up to date"; \ fi @@ -30,25 +32,24 @@ ifeq ($(CROSS_COMPILE),) -offsets.h: print_offsets - ./print_offsets > offsets.h +$(THIS)/offsets.h: $(THIS)/print_offsets + $(THIS)/print_offsets > $(THIS)/offsets.h comma := , -print_offsets: print_offsets.c FORCE +$(THIS)/print_offsets: $(THIS)/print_offsets.c FORCE $(CC) $(CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) \ - print_offsets.c -o $@ + $(THIS)/print_offsets.c -o $@ FORCE: else -offsets.h: print_offsets.s - $(AWK) -f print_offsets.awk $^ > $@ +$(THIS)/offsets.h: $(THIS)/print_offsets.s + $(AWK) -f $(THIS)/print_offsets.awk $^ > $@ -print_offsets.s: print_offsets.c - $(CC) $(CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -S \ - print_offsets.c -o $@ +$(THIS)/print_offsets.s: $(THIS)/print_offsets.c + $(CC) $(CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -S $^ -o $@ endif diff -Nru a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S --- a/arch/ia64/vmlinux.lds.S Thu Oct 24 22:22:20 2002 +++ b/arch/ia64/vmlinux.lds.S Thu Oct 24 22:22:20 2002 @@ -12,11 +12,11 @@ { /* Sections to be discarded */ /DISCARD/ : { - *(.text.exit) - *(.data.exit) + *(.exit.text) + *(.exit.data) *(.exitcall.exit) - *(.IA_64.unwind.text.exit) - *(.IA_64.unwind_info.text.exit) + *(.IA_64.unwind.exit.text) + *(.IA_64.unwind_info.exit.text) } v = PAGE_OFFSET; /* this symbol is here to make debugging easier... */ @@ -65,6 +65,13 @@ { *(__ksymtab) } __stop___ksymtab = .; + __kallsyms : AT(ADDR(__kallsyms) - PAGE_OFFSET) + { + __start___kallsyms = .; /* All kernel symbols */ + *(__kallsyms) + __stop___kallsyms = .; + } + /* Unwind info & table: */ . = ALIGN(8); .IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - PAGE_OFFSET) @@ -85,15 +92,15 @@ . = ALIGN(PAGE_SIZE); __init_begin = .; - .text.init : AT(ADDR(.text.init) - PAGE_OFFSET) - { *(.text.init) } + .init.text : AT(ADDR(.init.text) - PAGE_OFFSET) + { *(.init.text) } - .data.init : AT(ADDR(.data.init) - PAGE_OFFSET) - { *(.data.init) } + .init.data : AT(ADDR(.init.data) - PAGE_OFFSET) + { *(.init.data) } . = ALIGN(16); __setup_start = .; - .setup.init : AT(ADDR(.setup.init) - PAGE_OFFSET) - { *(.setup.init) } + .init.setup : AT(ADDR(.init.setup) - PAGE_OFFSET) + { *(.init.setup) } __setup_end = .; __initcall_start = .; .initcall.init : AT(ADDR(.initcall.init) - PAGE_OFFSET) diff -Nru a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c --- a/arch/parisc/kernel/traps.c Thu Oct 24 22:22:20 2002 +++ b/arch/parisc/kernel/traps.c Thu Oct 24 22:22:20 2002 @@ -43,7 +43,6 @@ static inline void console_verbose(void) { - extern int console_loglevel; console_loglevel = 15; } diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c Thu Oct 24 22:22:20 2002 +++ b/drivers/acpi/osl.c Thu Oct 24 22:22:20 2002 @@ -221,7 +221,14 @@ acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) { #ifdef CONFIG_IA64 - irq = gsi_to_vector(irq); + int vector; + + vector = acpi_irq_to_vector(irq); + if (vector < 0) { + printk(KERN_ERR PREFIX "SCI (IRQ%d) not registerd\n", irq); + return AE_OK; + } + irq = vector; #endif acpi_irq_irq = irq; acpi_irq_handler = handler; @@ -239,7 +246,7 @@ { if (acpi_irq_handler) { #ifdef CONFIG_IA64 - irq = gsi_to_vector(irq); + irq = acpi_irq_to_vector(irq); #endif free_irq(irq, acpi_irq); acpi_irq_handler = NULL; diff -Nru a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c --- a/drivers/acpi/pci_irq.c Thu Oct 24 22:22:20 2002 +++ b/drivers/acpi/pci_irq.c Thu Oct 24 22:22:20 2002 @@ -36,6 +36,9 @@ #ifdef CONFIG_X86_IO_APIC #include #endif +#ifdef CONFIG_IOSAPIC +# include +#endif #include "acpi_bus.h" #include "acpi_drivers.h" @@ -250,6 +253,8 @@ return_VALUE(0); } + entry->irq = entry->link.index; + if (!entry->irq && entry->link.handle) { entry->irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index); if (!entry->irq) { @@ -350,7 +355,7 @@ return_VALUE(dev->irq); } - dev->irq = irq; + dev->irq = gsi_to_irq(irq); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s using IRQ %d\n", dev->slot_name, dev->irq)); diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c --- a/drivers/block/rd.c Thu Oct 24 22:22:20 2002 +++ b/drivers/block/rd.c Thu Oct 24 22:22:20 2002 @@ -214,7 +214,7 @@ kunmap(vec->bv_page); if (rw == READ) { - flush_dcache_page(sbh->b_page); + flush_dcache_page(page); } else { SetPageDirty(page); } diff -Nru a/drivers/char/agp/agp.c b/drivers/char/agp/agp.c --- a/drivers/char/agp/agp.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/agp/agp.c Thu Oct 24 22:22:20 2002 @@ -25,6 +25,7 @@ * TODO: * - Allocate more than order 0 pages to avoid too much linear map splitting. */ + #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include "agp.h" MODULE_AUTHOR("Jeff Hartmann "); @@ -137,6 +139,9 @@ { int i; + pr_debug("agp_free_memory(curr=%p): type=%u, page_count=%Zu\n", + curr, curr->type, curr->page_count); + if ((agp_bridge.type == NOT_SUPPORTED) || (curr == NULL)) return; @@ -149,7 +154,6 @@ } if (curr->page_count != 0) { for (i = 0; i < curr->page_count; i++) { - curr->memory[i] &= ~(0x00000fff); agp_bridge.agp_destroy_page(phys_to_virt(curr->memory[i])); } } @@ -167,6 +171,8 @@ agp_memory *new; int i; + pr_debug("agp_allocate_memory(count=%Zu, type=%u)\n", page_count, type); + if (agp_bridge.type == NOT_SUPPORTED) return NULL; @@ -202,12 +208,13 @@ agp_free_memory(new); return NULL; } - new->memory[i] = agp_bridge.mask_memory(virt_to_phys(addr), type); + new->memory[i] = virt_to_phys(addr); new->page_count++; } flush_agp_mappings(); + pr_debug("agp_allocate_memory: new=%p\n", new); return new; } @@ -656,7 +663,7 @@ } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) - agp_bridge.gatt_table[j] = mem->memory[i]; + agp_bridge.gatt_table[j] = agp_bridge.mask_memory(mem->memory[i], mem->type); agp_bridge.tlb_flush(mem); return 0; @@ -992,6 +999,17 @@ }, #endif /* CONFIG_AGP_INTEL */ + +#ifdef CONFIG_AGP_I460 + { + .device_id = PCI_DEVICE_ID_INTEL_84460GX, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_460GX, + .vendor_name = "Intel", + .chipset_name = "460GX", + .chipset_setup = intel_i460_setup + }, +#endif #ifdef CONFIG_AGP_SIS { diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h --- a/drivers/char/agp/agp.h Thu Oct 24 22:22:20 2002 +++ b/drivers/char/agp/agp.h Thu Oct 24 22:22:20 2002 @@ -83,7 +83,7 @@ flush_agp_cache(); } #else -static void global_cache_flush(void) +static void __attribute__((unused)) global_cache_flush(void) { flush_agp_cache(); } diff -Nru a/drivers/char/agp/amd-agp.c b/drivers/char/agp/amd-agp.c --- a/drivers/char/agp/amd-agp.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/agp/amd-agp.c Thu Oct 24 22:22:20 2002 @@ -330,7 +330,7 @@ for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr; cur_gatt = GET_GATT(addr); - cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i]; + cur_gatt[GET_GATT_OFF(addr)] = agp_bridge.mask_memory(mem->memory[i], mem->type); } agp_bridge.tlb_flush(mem); return 0; diff -Nru a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c --- a/drivers/char/agp/hp-agp.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/agp/hp-agp.c Thu Oct 24 22:22:20 2002 @@ -43,8 +43,7 @@ #define HP_ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL #define HP_ZX1_PDIR_VALID_BIT 0x8000000000000000UL -#define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> \ - hp_private.io_tlb_shift) +#define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> hp_private.io_tlb_shift) static struct aper_size_info_fixed hp_zx1_sizes[] = { @@ -357,12 +356,7 @@ return HP_ZX1_PDIR_VALID_BIT | addr; } -static unsigned long hp_zx1_unmask_memory(unsigned long addr) -{ - return addr & ~(HP_ZX1_PDIR_VALID_BIT); -} - -int __init hp_zx1_setup (struct pci_dev *pdev) +int __init hp_zx1_setup (struct pci_dev *pdev __attribute__((unused))) { agp_bridge.masks = hp_zx1_masks; agp_bridge.num_of_masks = 1; @@ -374,7 +368,6 @@ agp_bridge.cleanup = hp_zx1_cleanup; agp_bridge.tlb_flush = hp_zx1_tlbflush; agp_bridge.mask_memory = hp_zx1_mask_memory; - agp_bridge.unmask_memory = hp_zx1_unmask_memory; agp_bridge.agp_enable = agp_generic_agp_enable; agp_bridge.cache_flush = global_cache_flush; agp_bridge.create_gatt_table = hp_zx1_create_gatt_table; @@ -388,7 +381,4 @@ agp_bridge.cant_use_aperture = 1; return hp_zx1_ioc_init(); - - (void) pdev; /* unused */ } - diff -Nru a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c --- a/drivers/char/agp/i460-agp.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/agp/i460-agp.c Thu Oct 24 22:22:20 2002 @@ -4,6 +4,9 @@ * Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Xi Graphics, Inc. * + * 460GX support by Chris Ahna + * Clean up & simplification by David Mosberger-Tang + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation @@ -17,55 +20,105 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * TODO: + * TODO: * - Allocate more than order 0 pages to avoid too much linear map splitting. */ +/* + * For documentation on the i460 AGP interface, see Chapter 7 (AGP Subsystem) of + * the "Intel 460GTX Chipset Software Developer's Manual": + * http://developer.intel.com/design/itanium/downloads/24870401s.htm + */ +#include +#include #include #include #include #include -#include "agp.h" -/* BIOS configures the chipset so that one of two apbase registers are used */ -static u8 intel_i460_dynamic_apbase = 0x10; +#include "agp.h" -/* 460 supports multiple GART page sizes, so GART pageshift is dynamic */ -static u8 intel_i460_pageshift = 12; -static u32 intel_i460_pagesize; - -/* Keep track of which is larger, chipset or kernel page size. */ -static u32 intel_i460_cpk = 1; - -/* Structure for tracking partial use of 4MB GART pages */ -static u32 **i460_pg_detail = NULL; -static u32 *i460_pg_count = NULL; +/* + * The i460 can operate with large (4MB) pages, but there is no sane way to support this + * within the current kernel/DRM environment, so we disable the relevant code for now. + * See also comments in ia64_alloc_page()... + */ +#define I460_LARGE_IO_PAGES 0 -#define I460_CPAGES_PER_KPAGE (PAGE_SIZE >> intel_i460_pageshift) -#define I460_KPAGES_PER_CPAGE ((1 << intel_i460_pageshift) >> PAGE_SHIFT) +#if I460_LARGE_IO_PAGES +# define I460_IO_PAGE_SHIFT i460.io_page_shift +#else +# define I460_IO_PAGE_SHIFT 12 +#endif +#define I460_IOPAGES_PER_KPAGE (PAGE_SIZE >> I460_IO_PAGE_SHIFT) +#define I460_KPAGES_PER_IOPAGE (1 << (I460_IO_PAGE_SHIFT - PAGE_SHIFT)) #define I460_SRAM_IO_DISABLE (1 << 4) #define I460_BAPBASE_ENABLE (1 << 3) #define I460_AGPSIZ_MASK 0x7 #define I460_4M_PS (1 << 1) -#define log2(x) ffz(~(x)) +/* Control bits for Out-Of-GART coherency and Burst Write Combining */ +#define I460_GXBCTL_OOG (1UL << 0) +#define I460_GXBCTL_BWC (1UL << 2) + +/* + * gatt_table entries are 32-bits wide on the i460; the generic code ought to declare the + * gatt_table and gatt_table_real pointers a "void *"... + */ +#define RD_GATT(index) readl((u32 *) i460.gatt + (index)) +#define WR_GATT(index, val) writel((val), (u32 *) i460.gatt + (index)) +/* + * The 460 spec says we have to read the last location written to make sure that all + * writes have taken effect + */ +#define WR_FLUSH_GATT(index) RD_GATT(index) + +#define log2(x) ffz(~(x)) + +static struct { + void *gatt; /* ioremap'd GATT area */ + + /* i460 supports multiple GART page sizes, so GART pageshift is dynamic: */ + u8 io_page_shift; + + /* BIOS configures chipset to one of 2 possible apbase values: */ + u8 dynamic_apbase; -static inline void intel_i460_read_back (volatile u32 *entry) + /* structure for tracking partial use of 4MB GART pages: */ + struct lp_desc { + unsigned long *alloced_map; /* bitmap of kernel-pages in use */ + int refcount; /* number of kernel pages using the large page */ + u64 paddr; /* physical address of large page */ + } *lp_desc; +} i460; + +static const struct aper_size_info_8 i460_sizes[3] = { /* - * The 460 spec says we have to read the last location written to - * make sure that all writes have taken effect + * The 32GB aperture is only available with a 4M GART page size. Due to the + * dynamic GART page size, we can't figure out page_order or num_entries until + * runtime. */ - *entry; -} + {32768, 0, 0, 4}, + {1024, 0, 0, 2}, + {256, 0, 0, 1} +}; -static int intel_i460_fetch_size(void) +static struct gatt_mask i460_masks[] = +{ + { + .mask = INTEL_I460_GATT_VALID | INTEL_I460_GATT_COHERENT, + .type = 0 + } +}; + +static int i460_fetch_size (void) { int i; u8 temp; @@ -73,8 +126,15 @@ /* Determine the GART page size */ pci_read_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, &temp); - intel_i460_pageshift = (temp & I460_4M_PS) ? 22 : 12; - intel_i460_pagesize = 1UL << intel_i460_pageshift; + i460.io_page_shift = (temp & I460_4M_PS) ? 22 : 12; + pr_debug("i460_fetch_size: io_page_shift=%d\n", i460.io_page_shift); + + if (i460.io_page_shift != I460_IO_PAGE_SHIFT) { + printk(KERN_ERR PFX + "I/O (GART) page-size %ZuKB doesn't match expected size %ZuKB\n", + 1UL << (i460.io_page_shift - 10), 1UL << (I460_IO_PAGE_SHIFT)); + return 0; + } values = A_SIZE_8(agp_bridge.aperture_sizes); @@ -88,16 +148,16 @@ } /* Make sure we don't try to create an 2 ^ 23 entry GATT */ - if ((intel_i460_pageshift == 0) && ((temp & I460_AGPSIZ_MASK) == 4)) { + if ((i460.io_page_shift == 0) && ((temp & I460_AGPSIZ_MASK) == 4)) { printk(KERN_ERR PFX "We can't have a 32GB aperture with 4KB GART pages\n"); return 0; } /* Determine the proper APBASE register */ if (temp & I460_BAPBASE_ENABLE) - intel_i460_dynamic_apbase = INTEL_I460_BAPBASE; + i460.dynamic_apbase = INTEL_I460_BAPBASE; else - intel_i460_dynamic_apbase = INTEL_I460_APBASE; + i460.dynamic_apbase = INTEL_I460_APBASE; for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { /* @@ -105,7 +165,7 @@ * the define aperture sizes. Take care not to shift off the end of * values[i].size. */ - values[i].num_entries = (values[i].size << 8) >> (intel_i460_pageshift - 12); + values[i].num_entries = (values[i].size << 8) >> (I460_IO_PAGE_SHIFT - 12); values[i].page_order = log2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT); } @@ -122,7 +182,7 @@ } /* There isn't anything to do here since 460 has no GART TLB. */ -static void intel_i460_tlb_flush(agp_memory * mem) +static void i460_tlb_flush (agp_memory * mem) { return; } @@ -131,7 +191,7 @@ * This utility function is needed to prevent corruption of the control bits * which are stored along with the aperture size in 460's AGPSIZ register */ -static void intel_i460_write_agpsiz(u8 size_value) +static void i460_write_agpsiz (u8 size_value) { u8 temp; @@ -140,47 +200,39 @@ ((temp & ~I460_AGPSIZ_MASK) | size_value)); } -static void intel_i460_cleanup(void) +static void i460_cleanup (void) { struct aper_size_info_8 *previous_size; previous_size = A_SIZE_8(agp_bridge.previous_size); - intel_i460_write_agpsiz(previous_size->size_value); + i460_write_agpsiz(previous_size->size_value); - if (intel_i460_cpk == 0) { - vfree(i460_pg_detail); - vfree(i460_pg_count); - } + if (I460_IO_PAGE_SHIFT > PAGE_SHIFT) + kfree(i460.lp_desc); } - -/* Control bits for Out-Of-GART coherency and Burst Write Combining */ -#define I460_GXBCTL_OOG (1UL << 0) -#define I460_GXBCTL_BWC (1UL << 2) - -static int intel_i460_configure(void) +static int i460_configure (void) { union { u32 small[2]; u64 large; } temp; + size_t size; u8 scratch; - int i; - struct aper_size_info_8 *current_size; temp.large = 0; current_size = A_SIZE_8(agp_bridge.current_size); - intel_i460_write_agpsiz(current_size->size_value); + i460_write_agpsiz(current_size->size_value); /* * Do the necessary rigmarole to read all eight bytes of APBASE. * This has to be done since the AGP aperture can be above 4GB on * 460 based systems. */ - pci_read_config_dword(agp_bridge.dev, intel_i460_dynamic_apbase, &(temp.small[0])); - pci_read_config_dword(agp_bridge.dev, intel_i460_dynamic_apbase + 4, &(temp.small[1])); + pci_read_config_dword(agp_bridge.dev, i460.dynamic_apbase, &(temp.small[0])); + pci_read_config_dword(agp_bridge.dev, i460.dynamic_apbase + 4, &(temp.small[1])); /* Clear BAR control bits */ agp_bridge.gart_bus_addr = temp.large & ~((1UL << 3) - 1); @@ -190,406 +242,349 @@ (scratch & 0x02) | I460_GXBCTL_OOG | I460_GXBCTL_BWC); /* - * Initialize partial allocation trackers if a GART page is bigger than - * a kernel page. + * Initialize partial allocation trackers if a GART page is bigger than a kernel + * page. */ - if (I460_CPAGES_PER_KPAGE >= 1) { - intel_i460_cpk = 1; - } else { - intel_i460_cpk = 0; - - i460_pg_detail = vmalloc(sizeof(*i460_pg_detail) * current_size->num_entries); - i460_pg_count = vmalloc(sizeof(*i460_pg_count) * current_size->num_entries); - - for (i = 0; i < current_size->num_entries; i++) { - i460_pg_count[i] = 0; - i460_pg_detail[i] = NULL; - } + if (I460_IO_PAGE_SHIFT > PAGE_SHIFT) { + size = current_size->num_entries * sizeof(i460.lp_desc[0]); + i460.lp_desc = kmalloc(size, GFP_KERNEL); + if (!i460.lp_desc) + return -ENOMEM; + memset(i460.lp_desc, 0, size); } return 0; } -static int intel_i460_create_gatt_table(void) +static int i460_create_gatt_table (void) { - char *table; - int i; - int page_order; - int num_entries; + int page_order, num_entries, i; void *temp; /* - * Load up the fixed address of the GART SRAMS which hold our - * GATT table. + * Load up the fixed address of the GART SRAMS which hold our GATT table. */ - table = (char *) __va(INTEL_I460_ATTBASE); - temp = agp_bridge.current_size; page_order = A_SIZE_8(temp)->page_order; num_entries = A_SIZE_8(temp)->num_entries; - agp_bridge.gatt_table_real = (u32 *) table; - agp_bridge.gatt_table = ioremap_nocache(virt_to_phys(table), - (PAGE_SIZE * (1 << page_order))); - agp_bridge.gatt_bus_addr = virt_to_phys(agp_bridge.gatt_table_real); - - for (i = 0; i < num_entries; i++) { - agp_bridge.gatt_table[i] = 0; - } + i460.gatt = ioremap(INTEL_I460_ATTBASE, PAGE_SIZE << page_order); - intel_i460_read_back(agp_bridge.gatt_table + i - 1); + /* These are no good, the should be removed from the agp_bridge strucure... */ + agp_bridge.gatt_table_real = NULL; + agp_bridge.gatt_table = NULL; + agp_bridge.gatt_bus_addr = 0; + + for (i = 0; i < num_entries; ++i) + WR_GATT(i, 0); + WR_FLUSH_GATT(i - 1); return 0; } -static int intel_i460_free_gatt_table(void) +static int i460_free_gatt_table (void) { - int num_entries; - int i; + int num_entries, i; void *temp; temp = agp_bridge.current_size; num_entries = A_SIZE_8(temp)->num_entries; - for (i = 0; i < num_entries; i++) { - agp_bridge.gatt_table[i] = 0; - } - - intel_i460_read_back(agp_bridge.gatt_table + i - 1); + for (i = 0; i < num_entries; ++i) + WR_GATT(i, 0); + WR_FLUSH_GATT(num_entries - 1); - iounmap(agp_bridge.gatt_table); + iounmap(i460.gatt); return 0; } -/* These functions are called when PAGE_SIZE exceeds the GART page size */ +/* + * The following functions are called when the I/O (GART) page size is smaller than + * PAGE_SIZE. + */ -static int intel_i460_insert_memory_cpk(agp_memory * mem, off_t pg_start, int type) +static int i460_insert_memory_small_io_page (agp_memory *mem, off_t pg_start, int type) { + unsigned long paddr, io_pg_start, io_page_size; int i, j, k, num_entries; void *temp; - unsigned long paddr; - /* - * The rest of the kernel will compute page offsets in terms of - * PAGE_SIZE. - */ - pg_start = I460_CPAGES_PER_KPAGE * pg_start; + pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n", + mem, pg_start, type, mem->memory[0]); + + io_pg_start = I460_IOPAGES_PER_KPAGE * pg_start; temp = agp_bridge.current_size; num_entries = A_SIZE_8(temp)->num_entries; - if ((pg_start + I460_CPAGES_PER_KPAGE * mem->page_count) > num_entries) { + if ((io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count) > num_entries) { printk(KERN_ERR PFX "Looks like we're out of AGP memory\n"); return -EINVAL; } - j = pg_start; - while (j < (pg_start + I460_CPAGES_PER_KPAGE * mem->page_count)) { - if (!PGE_EMPTY(agp_bridge.gatt_table[j])) { + j = io_pg_start; + while (j < (io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count)) { + if (!PGE_EMPTY(RD_GATT(j))) { + pr_debug("i460_insert_memory_small_io_page: GATT[%d]=0x%x is busy\n", + j, RD_GATT(j)); return -EBUSY; } j++; } -#if 0 - /* not necessary since 460 GART is operated in coherent mode... */ - if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); - mem->is_flushed = TRUE; - } -#endif - - for (i = 0, j = pg_start; i < mem->page_count; i++) { + io_page_size = 1UL << I460_IO_PAGE_SHIFT; + for (i = 0, j = io_pg_start; i < mem->page_count; i++) { paddr = mem->memory[i]; - for (k = 0; k < I460_CPAGES_PER_KPAGE; k++, j++, paddr += intel_i460_pagesize) - agp_bridge.gatt_table[j] = (u32) agp_bridge.mask_memory(paddr, mem->type); + for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size) + WR_GATT(j, agp_bridge.mask_memory(paddr, mem->type)); } - - intel_i460_read_back(agp_bridge.gatt_table + j - 1); + WR_FLUSH_GATT(j - 1); return 0; } -static int intel_i460_remove_memory_cpk(agp_memory * mem, off_t pg_start, int type) +static int i460_remove_memory_small_io_page(agp_memory * mem, off_t pg_start, int type) { int i; - pg_start = I460_CPAGES_PER_KPAGE * pg_start; + pr_debug("i460_remove_memory_small_io_page(mem=%p, pg_start=%ld, type=%d)\n", + mem, pg_start, type); - for (i = pg_start; i < (pg_start + I460_CPAGES_PER_KPAGE * mem->page_count); i++) - agp_bridge.gatt_table[i] = 0; + pg_start = I460_IOPAGES_PER_KPAGE * pg_start; - intel_i460_read_back(agp_bridge.gatt_table + i - 1); + for (i = pg_start; i < (pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count); i++) + WR_GATT(i, 0); + WR_FLUSH_GATT(i - 1); return 0; } +#if I460_LARGE_IO_PAGES + /* - * These functions are called when the GART page size exceeds PAGE_SIZE. + * These functions are called when the I/O (GART) page size exceeds PAGE_SIZE. * - * This situation is interesting since AGP memory allocations that are - * smaller than a single GART page are possible. The structures i460_pg_count - * and i460_pg_detail track partial allocation of the large GART pages to - * work around this issue. + * This situation is interesting since AGP memory allocations that are smaller than a + * single GART page are possible. The i460.lp_desc array tracks partial allocation of the + * large GART pages to work around this issue. * - * i460_pg_count[pg_num] tracks the number of kernel pages in use within - * GART page pg_num. i460_pg_detail[pg_num] is an array containing a - * psuedo-GART entry for each of the aforementioned kernel pages. The whole - * of i460_pg_detail is equivalent to a giant GATT with page size equal to - * that of the kernel. + * i460.lp_desc[pg_num].refcount tracks the number of kernel pages in use within GART page + * pg_num. i460.lp_desc[pg_num].paddr is the physical address of the large page and + * i460.lp_desc[pg_num].alloced_map is a bitmap of kernel pages that are in use (allocated). */ -static void *intel_i460_alloc_large_page(int pg_num) +static int i460_alloc_large_page (struct lp_desc *lp) { - int i; - void *bp, *bp_end; - struct page *page; - - i460_pg_detail[pg_num] = (void *) vmalloc(sizeof(u32) * I460_KPAGES_PER_CPAGE); - if (i460_pg_detail[pg_num] == NULL) { - printk(KERN_ERR PFX "Out of memory, we're in trouble...\n"); - return NULL; - } - - for (i = 0; i < I460_KPAGES_PER_CPAGE; i++) - i460_pg_detail[pg_num][i] = 0; + unsigned long order = I460_IO_PAGE_SHIFT - PAGE_SHIFT; + size_t map_size; + void *lpage; - bp = (void *) __get_free_pages(GFP_KERNEL, intel_i460_pageshift - PAGE_SHIFT); - if (bp == NULL) { + lpage = (void *) __get_free_pages(GFP_KERNEL, order); + if (!lpage) { printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n"); - return NULL; + return -ENOMEM; } - bp_end = bp + ((PAGE_SIZE * (1 << (intel_i460_pageshift - PAGE_SHIFT))) - 1); - - for (page = virt_to_page(bp); page <= virt_to_page(bp_end); page++) { - atomic_inc(&agp_bridge.current_memory_agp); + map_size = ((I460_KPAGES_PER_IOPAGE + BITS_PER_LONG - 1) & -BITS_PER_LONG)/8; + lp->alloced_map = kmalloc(map_size, GFP_KERNEL); + if (!lp->alloced_map) { + free_pages((unsigned long) lpage, order); + printk(KERN_ERR PFX "Out of memory, we're in trouble...\n"); + return -ENOMEM; } - return bp; + memset(lp->alloced_map, 0, map_size); + + lp->paddr = virt_to_phys(lpage); + lp->refcount = 0; + atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge.current_memory_agp); + return 0; } -static void intel_i460_free_large_page(int pg_num, unsigned long addr) +static void i460_free_large_page (struct lp_desc *lp) { - struct page *page; - void *bp, *bp_end; - - bp = (void *) __va(addr); - bp_end = bp + (PAGE_SIZE * (1 << (intel_i460_pageshift - PAGE_SHIFT))); + kfree(lp->alloced_map); + lp->alloced_map = NULL; - vfree(i460_pg_detail[pg_num]); - i460_pg_detail[pg_num] = NULL; - - for (page = virt_to_page(bp); page < virt_to_page(bp_end); page++) { - atomic_dec(&agp_bridge.current_memory_agp); - } - - free_pages((unsigned long) bp, intel_i460_pageshift - PAGE_SHIFT); + free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT); + atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge.current_memory_agp); } -static int intel_i460_insert_memory_kpc(agp_memory * mem, off_t pg_start, int type) +static int i460_insert_memory_large_io_page (agp_memory * mem, off_t pg_start, int type) { - int i, pg, start_pg, end_pg, start_offset, end_offset, idx; - int num_entries; + int i, start_offset, end_offset, idx, pg, num_entries; + struct lp_desc *start, *end, *lp; void *temp; - unsigned long paddr; temp = agp_bridge.current_size; num_entries = A_SIZE_8(temp)->num_entries; /* Figure out what pg_start means in terms of our large GART pages */ - start_pg = pg_start / I460_KPAGES_PER_CPAGE; - start_offset = pg_start % I460_KPAGES_PER_CPAGE; - end_pg = (pg_start + mem->page_count - 1) / I460_KPAGES_PER_CPAGE; - end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_CPAGE; + start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE]; + end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE]; + start_offset = pg_start % I460_KPAGES_PER_IOPAGE; + end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE; - if (end_pg > num_entries) { + if (end > i460.lp_desc + num_entries) { printk(KERN_ERR PFX "Looks like we're out of AGP memory\n"); return -EINVAL; } /* Check if the requested region of the aperture is free */ - for (pg = start_pg; pg <= end_pg; pg++) { - /* Allocate new GART pages if necessary */ - if (i460_pg_detail[pg] == NULL) { - temp = intel_i460_alloc_large_page(pg); - if (temp == NULL) - return -ENOMEM; - agp_bridge.gatt_table[pg] = agp_bridge.mask_memory((unsigned long) temp, - 0); - intel_i460_read_back(agp_bridge.gatt_table + pg); - } + for (lp = start; lp <= end; ++lp) { + if (!lp->alloced_map) + continue; /* OK, the entire large page is available... */ - for (idx = ((pg == start_pg) ? start_offset : 0); - idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); + for (idx = ((lp == start) ? start_offset : 0); + idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE); idx++) { - if (i460_pg_detail[pg][idx] != 0) + if (test_bit(idx, lp->alloced_map)) return -EBUSY; } } -#if 0 - /* not necessary since 460 GART is operated in coherent mode... */ - if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); - mem->is_flushed = TRUE; - } -#endif + for (lp = start, i = 0; lp <= end; ++lp) { + if (!lp->alloced_map) { + /* Allocate new GART pages... */ + if (i460_alloc_large_page(lp) < 0) + return -ENOMEM; + pg = lp - i460.lp_desc; + WR_GATT(pg, agp_bridge.mask_memory(lp->paddr, 0)); + WR_FLUSH_GATT(pg); + } - for (pg = start_pg, i = 0; pg <= end_pg; pg++) { - paddr = agp_bridge.unmask_memory(agp_bridge.gatt_table[pg]); - for (idx = ((pg == start_pg) ? start_offset : 0); - idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); + for (idx = ((lp == start) ? start_offset : 0); + idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE); idx++, i++) { - mem->memory[i] = paddr + (idx * PAGE_SIZE); - i460_pg_detail[pg][idx] = agp_bridge.mask_memory(mem->memory[i], - mem->type); - i460_pg_count[pg]++; + mem->memory[i] = lp->paddr + idx*PAGE_SIZE; + __set_bit(idx, lp->alloced_map); + ++lp->refcount; } } - return 0; } -static int intel_i460_remove_memory_kpc(agp_memory * mem, off_t pg_start, int type) +static int i460_remove_memory_large_io_page (agp_memory * mem, off_t pg_start, int type) { - int i, pg, start_pg, end_pg, start_offset, end_offset, idx; - int num_entries; + int i, pg, start_offset, end_offset, idx, num_entries; + struct lp_desc *start, *end, *lp; void *temp; - unsigned long paddr; temp = agp_bridge.current_size; num_entries = A_SIZE_8(temp)->num_entries; /* Figure out what pg_start means in terms of our large GART pages */ - start_pg = pg_start / I460_KPAGES_PER_CPAGE; - start_offset = pg_start % I460_KPAGES_PER_CPAGE; - end_pg = (pg_start + mem->page_count - 1) / I460_KPAGES_PER_CPAGE; - end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_CPAGE; - - for (i = 0, pg = start_pg; pg <= end_pg; pg++) { - for (idx = ((pg == start_pg) ? start_offset : 0); - idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); - idx++, i++) + start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE]; + end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE]; + start_offset = pg_start % I460_KPAGES_PER_IOPAGE; + end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE; + + for (i = 0, lp = start; lp <= end; ++lp) { + for (idx = ((lp == start) ? start_offset : 0); + idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE); + idx++, i++) { mem->memory[i] = 0; - i460_pg_detail[pg][idx] = 0; - i460_pg_count[pg]--; + __clear_bit(idx, lp->alloced_map); + --lp->refcount; } /* Free GART pages if they are unused */ - if (i460_pg_count[pg] == 0) { - paddr = agp_bridge.unmask_memory(agp_bridge.gatt_table[pg]); - agp_bridge.gatt_table[pg] = agp_bridge.scratch_page; - intel_i460_read_back(agp_bridge.gatt_table + pg); - intel_i460_free_large_page(pg, paddr); + if (lp->refcount == 0) { + pg = lp - i460.lp_desc; + WR_GATT(pg, 0); + WR_FLUSH_GATT(pg); + i460_free_large_page(lp); } } return 0; } -/* Dummy routines to call the approriate {cpk,kpc} function */ +/* Wrapper routines to call the approriate {small_io_page,large_io_page} function */ -static int intel_i460_insert_memory(agp_memory * mem, off_t pg_start, int type) +static int i460_insert_memory (agp_memory * mem, off_t pg_start, int type) { - if (intel_i460_cpk) - return intel_i460_insert_memory_cpk(mem, pg_start, type); + if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) + return i460_insert_memory_small_io_page(mem, pg_start, type); else - return intel_i460_insert_memory_kpc(mem, pg_start, type); + return i460_insert_memory_large_io_page(mem, pg_start, type); } -static int intel_i460_remove_memory(agp_memory * mem, off_t pg_start, int type) +static int i460_remove_memory (agp_memory * mem, off_t pg_start, int type) { - if (intel_i460_cpk) - return intel_i460_remove_memory_cpk(mem, pg_start, type); + if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) + return i460_remove_memory_small_io_page(mem, pg_start, type); else - return intel_i460_remove_memory_kpc(mem, pg_start, type); + return i460_remove_memory_large_io_page(mem, pg_start, type); } /* - * If the kernel page size is smaller that the chipset page size, we don't - * want to allocate memory until we know where it is to be bound in the - * aperture (a multi-kernel-page alloc might fit inside of an already - * allocated GART page). Consequently, don't allocate or free anything - * if i460_cpk (meaning chipset pages per kernel page) isn't set. + * If the I/O (GART) page size is bigger than the kernel page size, we don't want to + * allocate memory until we know where it is to be bound in the aperture (a + * multi-kernel-page alloc might fit inside of an already allocated GART page). * - * Let's just hope nobody counts on the allocated AGP memory being there - * before bind time (I don't think current drivers do)... + * Let's just hope nobody counts on the allocated AGP memory being there before bind time + * (I don't think current drivers do)... */ -static void * intel_i460_alloc_page(void) +static void *i460_alloc_page (void) { - if (intel_i460_cpk) - return agp_generic_alloc_page(); + void *page; - /* Returning NULL would cause problems */ - /* AK: really dubious code. */ - return (void *)~0UL; + if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) + page = agp_generic_alloc_page(); + else + /* Returning NULL would cause problems */ + /* AK: really dubious code. */ + page = (void *)~0UL; + return page; } -static void intel_i460_destroy_page(void *page) +static void i460_destroy_page (void *page) { - if (intel_i460_cpk) + if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) agp_generic_destroy_page(page); } -static struct gatt_mask intel_i460_masks[] = -{ - { - .mask = INTEL_I460_GATT_VALID | INTEL_I460_GATT_COHERENT, - .type = 0 - } -}; +#endif /* I460_LARGE_IO_PAGES */ -static unsigned long intel_i460_mask_memory(unsigned long addr, int type) +static unsigned long i460_mask_memory (unsigned long addr, int type) { /* Make sure the returned address is a valid GATT entry */ return (agp_bridge.masks[0].mask - | (((addr & ~((1 << intel_i460_pageshift) - 1)) & 0xffffff000) >> 12)); + | (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12)); } -static unsigned long intel_i460_unmask_memory(unsigned long addr) -{ - /* Turn a GATT entry into a physical address */ - return ((addr & 0xffffff) << 12); -} - -static struct aper_size_info_8 intel_i460_sizes[3] = -{ - /* - * The 32GB aperture is only available with a 4M GART page size. - * Due to the dynamic GART page size, we can't figure out page_order - * or num_entries until runtime. - */ - {32768, 0, 0, 4}, - {1024, 0, 0, 2}, - {256, 0, 0, 1} -}; - int __init intel_i460_setup (struct pci_dev *pdev __attribute__((unused))) { - agp_bridge.masks = intel_i460_masks; - agp_bridge.aperture_sizes = (void *) intel_i460_sizes; + agp_bridge.num_of_masks = 1; + agp_bridge.masks = i460_masks; + agp_bridge.aperture_sizes = (void *) i460_sizes; agp_bridge.size_type = U8_APER_SIZE; agp_bridge.num_aperture_sizes = 3; agp_bridge.dev_private_data = NULL; agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = intel_i460_configure; - agp_bridge.fetch_size = intel_i460_fetch_size; - agp_bridge.cleanup = intel_i460_cleanup; - agp_bridge.tlb_flush = intel_i460_tlb_flush; - agp_bridge.mask_memory = intel_i460_mask_memory; - agp_bridge.unmask_memory = intel_i460_unmask_memory; + agp_bridge.configure = i460_configure; + agp_bridge.fetch_size = i460_fetch_size; + agp_bridge.cleanup = i460_cleanup; + agp_bridge.tlb_flush = i460_tlb_flush; + agp_bridge.mask_memory = i460_mask_memory; agp_bridge.agp_enable = agp_generic_agp_enable; agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = intel_i460_create_gatt_table; - agp_bridge.free_gatt_table = intel_i460_free_gatt_table; - agp_bridge.insert_memory = intel_i460_insert_memory; - agp_bridge.remove_memory = intel_i460_remove_memory; + agp_bridge.create_gatt_table = i460_create_gatt_table; + agp_bridge.free_gatt_table = i460_free_gatt_table; +#if I460_LARGE_IO_PAGES + agp_bridge.insert_memory = i460_insert_memory; + agp_bridge.remove_memory = i460_remove_memory; + agp_bridge.agp_alloc_page = i460_alloc_page; + agp_bridge.agp_destroy_page = i460_destroy_page; +#else + agp_bridge.insert_memory = i460_insert_memory_small_io_page; + agp_bridge.remove_memory = i460_remove_memory_small_io_page; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; +#endif agp_bridge.alloc_by_type = agp_generic_alloc_by_type; agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = intel_i460_alloc_page; - agp_bridge.agp_destroy_page = intel_i460_destroy_page; agp_bridge.suspend = agp_generic_suspend; agp_bridge.resume = agp_generic_resume; agp_bridge.cant_use_aperture = 1; return 0; } - diff -Nru a/drivers/char/agp/i810-agp.c b/drivers/char/agp/i810-agp.c --- a/drivers/char/agp/i810-agp.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/agp/i810-agp.c Thu Oct 24 22:22:20 2002 @@ -179,7 +179,8 @@ CACHE_FLUSH(); for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { OUTREG32(intel_i810_private.registers, - I810_PTE_BASE + (j * 4), mem->memory[i]); + I810_PTE_BASE + (j * 4), agp_bridge.mask_memory(mem->memory[i], + mem->type)); } CACHE_FLUSH(); @@ -246,11 +247,11 @@ agp_free_memory(new); return NULL; } - new->memory[0] = agp_bridge.mask_memory(virt_to_phys(addr), type); + new->memory[0] = virt_to_phys(addr); new->page_count = 1; new->num_scratch_pages = 1; new->type = AGP_PHYS_MEMORY; - new->physical = virt_to_phys((void *) new->memory[0]); + new->physical = virt_to_phys(addr); return new; } @@ -483,7 +484,8 @@ CACHE_FLUSH(); for (i = 0, j = pg_start; i < mem->page_count; i++, j++) - OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),mem->memory[i]); + OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4), + agp_bridge.mask_memory(mem->memory[i], mem->type)); CACHE_FLUSH(); @@ -543,7 +545,7 @@ return(NULL); } - nw->memory[0] = agp_bridge.mask_memory(virt_to_phys(addr),type); + nw->memory[0] = virt_to_phys(addr); nw->page_count = 1; nw->num_scratch_pages = 1; nw->type = AGP_PHYS_MEMORY; diff -Nru a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c --- a/drivers/char/agp/sworks-agp.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/agp/sworks-agp.c Thu Oct 24 22:22:20 2002 @@ -405,7 +405,7 @@ for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr; cur_gatt = SVRWRKS_GET_GATT(addr); - cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i]; + cur_gatt[GET_GATT_OFF(addr)] = agp_bridge.mask_memory(mem->memory[i], mem->type); } agp_bridge.tlb_flush(mem); return 0; diff -Nru a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h --- a/drivers/char/drm/drmP.h Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/drmP.h Thu Oct 24 22:22:20 2002 @@ -230,16 +230,16 @@ if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; } /* Mapping helper macros */ -#define DRM_IOREMAP(map) \ - (map)->handle = DRM(ioremap)( (map)->offset, (map)->size ) +#define DRM_IOREMAP(map, dev) \ + (map)->handle = DRM(ioremap)( (map)->offset, (map)->size, (dev) ) -#define DRM_IOREMAP_NOCACHE(map) \ - (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size) +#define DRM_IOREMAP_NOCACHE(map, dev) \ + (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size, (dev)) -#define DRM_IOREMAPFREE(map) \ - do { \ - if ( (map)->handle && (map)->size ) \ - DRM(ioremapfree)( (map)->handle, (map)->size ); \ +#define DRM_IOREMAPFREE(map, dev) \ + do { \ + if ( (map)->handle && (map)->size ) \ + DRM(ioremapfree)( (map)->handle, (map)->size, (dev) ); \ } while (0) #define DRM_FIND_MAP(_map, _o) \ @@ -681,9 +681,10 @@ extern unsigned long DRM(alloc_pages)(int order, int area); extern void DRM(free_pages)(unsigned long address, int order, int area); -extern void *DRM(ioremap)(unsigned long offset, unsigned long size); -extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size); -extern void DRM(ioremapfree)(void *pt, unsigned long size); +extern void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev); +extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, + drm_device_t *dev); +extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); #if __REALLY_HAVE_AGP extern agp_memory *DRM(alloc_agp)(int pages, u32 type); diff -Nru a/drivers/char/drm/drm_bufs.h b/drivers/char/drm/drm_bufs.h --- a/drivers/char/drm/drm_bufs.h Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/drm_bufs.h Thu Oct 24 22:22:20 2002 @@ -107,7 +107,7 @@ switch ( map->type ) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: -#if !defined(__sparc__) && !defined(__alpha__) +#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) if ( map->offset + map->size < map->offset || map->offset < virt_to_phys(high_memory) ) { DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); @@ -124,7 +124,7 @@ MTRR_TYPE_WRCOMB, 1 ); } #endif - map->handle = DRM(ioremap)( map->offset, map->size ); + map->handle = DRM(ioremap)( map->offset, map->size, dev ); break; case _DRM_SHM: @@ -246,7 +246,7 @@ DRM_DEBUG("mtrr_del = %d\n", retcode); } #endif - DRM(ioremapfree)(map->handle, map->size); + DRM(ioremapfree)(map->handle, map->size, dev); break; case _DRM_SHM: vfree(map->handle); diff -Nru a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h --- a/drivers/char/drm/drm_drv.h Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/drm_drv.h Thu Oct 24 22:22:20 2002 @@ -443,7 +443,7 @@ DRM_DEBUG( "mtrr_del=%d\n", retcode ); } #endif - DRM(ioremapfree)( map->handle, map->size ); + DRM(ioremapfree)( map->handle, map->size, dev ); break; case _DRM_SHM: vfree(map->handle); diff -Nru a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h --- a/drivers/char/drm/drm_memory.h Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/drm_memory.h Thu Oct 24 22:22:20 2002 @@ -33,6 +33,10 @@ #include #include "drmP.h" #include +#include + +#include +#include typedef struct drm_mem_stats { const char *name; @@ -291,17 +295,122 @@ } } -void *DRM(ioremap)(unsigned long offset, unsigned long size) +#if __REALLY_HAVE_AGP + +/* + * Find the drm_map that covers the range [offset, offset+size). + */ +static inline drm_map_t * +drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev) { + struct list_head *list; + drm_map_list_t *r_list; + drm_map_t *map; + + list_for_each(list, &dev->maplist->head) { + r_list = (drm_map_list_t *) list; + map = r_list->map; + if (!map) + continue; + if (map->offset <= offset && (offset + size) <= (map->offset + map->size)) + return map; + } + return NULL; +} + +static inline void * +agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev) +{ + unsigned long *phys_addr_map, i, num_pages = PAGE_ALIGN(size) / PAGE_SIZE; + struct page **page_map, **page_map_ptr; + struct drm_agp_mem *agpmem; + struct vm_struct *area; + + + size = PAGE_ALIGN(size); + + for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) + if (agpmem->bound <= offset + && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= (offset + size)) + break; + if (!agpmem) + return NULL; + + /* + * OK, we're mapping AGP space on a chipset/platform on which memory accesses by + * the CPU do not get remapped by the GART. We fix this by using the kernel's + * page-table instead (that's probably faster anyhow...). + */ + area = get_vm_area(size, VM_IOREMAP); + if (!area) + return NULL; + + flush_cache_all(); + + /* note: use vmalloc() because num_pages could be large... */ + page_map = vmalloc(num_pages * sizeof(struct page *)); + if (!page_map) + return NULL; + + phys_addr_map = agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE; + for (i = 0; i < num_pages; ++i) + page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT); + page_map_ptr = page_map; + if (map_vm_area(area, PAGE_AGP, &page_map_ptr) < 0) { + vunmap(area->addr); + vfree(page_map); + return NULL; + } + vfree(page_map); + + flush_tlb_kernel_range(area->addr, area->addr + size); + return area->addr; +} + +static inline unsigned long +drm_follow_page (void *vaddr) +{ +printk("drm_follow_page: vaddr=%p\n", vaddr); + pgd_t *pgd = pgd_offset_k((unsigned long) vaddr); +printk(" pgd=%p\n", pgd); + pmd_t *pmd = pmd_offset(pgd, (unsigned long) vaddr); +printk(" pmd=%p\n", pmd); + pte_t *ptep = pte_offset_kernel(pmd, (unsigned long) vaddr); +printk(" ptep=%p\n", ptep); +printk(" page=0x%lx\n", pte_pfn(*ptep) << PAGE_SHIFT); + return pte_pfn(*ptep) << PAGE_SHIFT; +} + +#else /* !__REALLY_HAVE_AGP */ + +static inline void * +agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev) { return NULL; } + +#endif /* !__REALLY_HAVE_AGP */ + +void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev) +{ + int remap_aperture = 0; void *pt; if (!size) { - DRM_MEM_ERROR(DRM_MEM_MAPPINGS, - "Mapping 0 bytes at 0x%08lx\n", offset); + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, "Mapping 0 bytes at 0x%08lx\n", offset); return NULL; } - if (!(pt = ioremap(offset, size))) { +#if __REALLY_HAVE_AGP + if (dev->agp->cant_use_aperture) { + drm_map_t *map = drm_lookup_map(offset, size, dev); + + if (map && map->type == _DRM_AGP) + remap_aperture = 1; + } +#endif + if (remap_aperture) + pt = agp_remap(offset, size, dev); + else + pt = ioremap(offset, size); + if (!pt) { spin_lock(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; spin_unlock(&DRM(mem_lock)); @@ -314,8 +423,9 @@ return pt; } -void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) +void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev) { + int remap_aperture = 0; void *pt; if (!size) { @@ -324,7 +434,19 @@ return NULL; } - if (!(pt = ioremap_nocache(offset, size))) { +#if __REALLY_HAVE_AGP + if (dev->agp->cant_use_aperture) { + drm_map_t *map = drm_lookup_map(offset, size, dev); + + if (map && map->type == _DRM_AGP) + remap_aperture = 1; + } +#endif + if (remap_aperture) + pt = agp_remap(offset, size, dev); + else + pt = ioremap_nocache(offset, size); + if (!pt) { spin_lock(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; spin_unlock(&DRM(mem_lock)); @@ -337,16 +459,40 @@ return pt; } -void DRM(ioremapfree)(void *pt, unsigned long size) +void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) { int alloc_count; int free_count; +printk("ioremapfree(pt=%p)\n", pt); if (!pt) DRM_MEM_ERROR(DRM_MEM_MAPPINGS, "Attempt to free NULL pointer\n"); - else - iounmap(pt); + else { + int unmap_aperture = 0; +#if __REALLY_HAVE_AGP + /* + * This is rather ugly. It would be much cleaner if the DRM API would use + * separate routines for handling mappings in the AGP space. Hopefully this + * can be done in a future revision of the interface... + */ + if (dev->agp->cant_use_aperture + && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END)) + { + unsigned long offset = (drm_follow_page(pt) + | ((unsigned long) pt & ~PAGE_MASK)); +printk("offset=0x%lx\n", offset); + drm_map_t *map = drm_lookup_map(offset, size, dev); +printk("map=%p\n", map); + if (map && map->type == _DRM_AGP) + unmap_aperture = 1; + } +#endif + if (unmap_aperture) + vunmap(pt); + else + iounmap(pt); + } spin_lock(&DRM(mem_lock)); DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size; diff -Nru a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h --- a/drivers/char/drm/drm_vm.h Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/drm_vm.h Thu Oct 24 22:22:20 2002 @@ -108,12 +108,12 @@ * Get the page, inc the use count, and return it */ offset = (baddr - agpmem->bound) >> PAGE_SHIFT; - agpmem->memory->memory[offset] &= dev->agp->page_mask; page = virt_to_page(__va(agpmem->memory->memory[offset])); get_page(page); - DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx\n", - baddr, __va(agpmem->memory->memory[offset]), offset); + DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", + baddr, __va(agpmem->memory->memory[offset]), offset, + atomic_read(&page->count)); return page; } @@ -207,7 +207,7 @@ DRM_DEBUG("mtrr_del = %d\n", retcode); } #endif - DRM(ioremapfree)(map->handle, map->size); + DRM(ioremapfree)(map->handle, map->size, dev); break; case _DRM_SHM: vfree(map->handle); @@ -421,15 +421,16 @@ switch (map->type) { case _DRM_AGP: -#if defined(__alpha__) +#if __REALLY_HAVE_AGP + if (dev->agp->cant_use_aperture) { /* - * On Alpha we can't talk to bus dma address from the - * CPU, so for memory of type DRM_AGP, we'll deal with - * sorting out the real physical pages and mappings - * in nopage() + * On some platforms we can't talk to bus dma address from the CPU, so for + * memory of type DRM_AGP, we'll deal with sorting out the real physical + * pages and mappings in nopage() */ vma->vm_ops = &DRM(vm_ops); break; + } #endif /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: @@ -440,15 +441,15 @@ pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; } -#elif defined(__ia64__) - if (map->type != _DRM_AGP) - vma->vm_page_prot = - pgprot_writecombine(vma->vm_page_prot); #elif defined(__powerpc__) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED; #endif vma->vm_flags |= VM_IO; /* not in core dump */ } +#if defined(__ia64__) + if (map->type != _DRM_AGP) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); +#endif offset = DRIVER_GET_REG_OFS(); #ifdef __sparc__ if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, diff -Nru a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c --- a/drivers/char/drm/gamma_dma.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/gamma_dma.c Thu Oct 24 22:22:20 2002 @@ -637,7 +637,7 @@ } else { DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->buffers, dev ); buf = dma->buflist[GLINT_DRI_BUF_COUNT]; pgt = buf->address; @@ -667,7 +667,7 @@ if ( dev->dev_private ) { drm_gamma_private_t *dev_priv = dev->dev_private; - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t), DRM_MEM_DRIVER ); diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c --- a/drivers/char/drm/i810_dma.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/i810_dma.c Thu Oct 24 22:22:20 2002 @@ -313,7 +313,7 @@ if(dev_priv->ring.virtual_start) { DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, - dev_priv->ring.Size); + dev_priv->ring.Size, dev); } if(dev_priv->hw_status_page != 0UL) { i810_free_page(dev, dev_priv->hw_status_page); @@ -327,7 +327,7 @@ for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[ i ]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; - DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total); + DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev); } } return 0; @@ -397,7 +397,7 @@ *buf_priv->in_use = I810_BUF_FREE; buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, - buf->total); + buf->total, dev); } return 0; } @@ -450,7 +450,7 @@ dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + init->ring_start, - init->ring_size); + init->ring_size, dev); if (dev_priv->ring.virtual_start == NULL) { dev->dev_private = (void *) dev_priv; diff -Nru a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c --- a/drivers/char/drm/i830_dma.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/i830_dma.c Thu Oct 24 22:22:20 2002 @@ -306,7 +306,7 @@ if(dev_priv->ring.virtual_start) { DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, - dev_priv->ring.Size); + dev_priv->ring.Size, dev); } if(dev_priv->hw_status_page != 0UL) { i830_free_page(dev, dev_priv->hw_status_page); @@ -320,7 +320,7 @@ for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[ i ]; drm_i830_buf_priv_t *buf_priv = buf->dev_private; - DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total); + DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev); } } return 0; @@ -392,7 +392,7 @@ *buf_priv->in_use = I830_BUF_FREE; buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, - buf->total); + buf->total, dev); } return 0; } @@ -446,7 +446,7 @@ dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + init->ring_start, - init->ring_size); + init->ring_size, dev); if (dev_priv->ring.virtual_start == NULL) { dev->dev_private = (void *) dev_priv; diff -Nru a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c --- a/drivers/char/drm/mga_dma.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/mga_dma.c Thu Oct 24 22:22:20 2002 @@ -554,9 +554,9 @@ (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); - DRM_IOREMAP( dev_priv->warp ); - DRM_IOREMAP( dev_priv->primary ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->warp, dev ); + DRM_IOREMAP( dev_priv->primary, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->warp->handle || !dev_priv->primary->handle || @@ -642,9 +642,9 @@ if ( dev->dev_private ) { drm_mga_private_t *dev_priv = dev->dev_private; - DRM_IOREMAPFREE( dev_priv->warp ); - DRM_IOREMAPFREE( dev_priv->primary ); - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->warp, dev ); + DRM_IOREMAPFREE( dev_priv->primary, dev ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); if ( dev_priv->head != NULL ) { mga_freelist_cleanup( dev ); diff -Nru a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h --- a/drivers/char/drm/mga_drv.h Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/mga_drv.h Thu Oct 24 22:22:20 2002 @@ -235,7 +235,7 @@ if ( MGA_VERBOSE ) { \ DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \ (n), __FUNCTION__ ); \ - DRM_INFO( " space=0x%x req=0x%x\n", \ + DRM_INFO( " space=0x%x req=0x%Zx\n", \ dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \ } \ prim = dev_priv->prim.start; \ @@ -285,7 +285,7 @@ #define DMA_WRITE( offset, val ) \ do { \ if ( MGA_VERBOSE ) { \ - DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04x\n", \ + DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04Zx\n", \ (u32)(val), write + (offset) * sizeof(u32) ); \ } \ *(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \ diff -Nru a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c --- a/drivers/char/drm/r128_cce.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/r128_cce.c Thu Oct 24 22:22:20 2002 @@ -350,8 +350,8 @@ R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", - entry->busaddr[page_ofs], + DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", + (unsigned long) entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -540,9 +540,9 @@ init->sarea_priv_offset); if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cce_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->cce_ring, dev ); + DRM_IOREMAP( dev_priv->ring_rptr, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->cce_ring->handle || !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { @@ -618,9 +618,9 @@ #if __REALLY_HAVE_SG if ( !dev_priv->is_pci ) { #endif - DRM_IOREMAPFREE( dev_priv->cce_ring ); - DRM_IOREMAPFREE( dev_priv->ring_rptr ); - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->cce_ring, dev ); + DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); #if __REALLY_HAVE_SG } else { if (!DRM(ati_pcigart_cleanup)( dev, diff -Nru a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c --- a/drivers/char/drm/radeon_cp.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/drm/radeon_cp.c Thu Oct 24 22:22:20 2002 @@ -904,8 +904,8 @@ RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", - entry->busaddr[page_ofs], + DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", + (unsigned long) entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -1157,9 +1157,9 @@ init->sarea_priv_offset); if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cp_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->cp_ring, dev ); + DRM_IOREMAP( dev_priv->ring_rptr, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->cp_ring->handle || !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { @@ -1278,9 +1278,9 @@ drm_radeon_private_t *dev_priv = dev->dev_private; if ( !dev_priv->is_pci ) { - DRM_IOREMAPFREE( dev_priv->cp_ring ); - DRM_IOREMAPFREE( dev_priv->ring_rptr ); - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->cp_ring, dev ); + DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); } else { #if __REALLY_HAVE_SG if (!DRM(ati_pcigart_cleanup)( dev, diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c Thu Oct 24 22:22:20 2002 +++ b/drivers/char/mem.c Thu Oct 24 22:22:20 2002 @@ -511,10 +511,12 @@ case 0: file->f_pos = offset; ret = file->f_pos; + force_successful_syscall_return(); break; case 1: file->f_pos += offset; ret = file->f_pos; + force_successful_syscall_return(); break; default: ret = -EINVAL; diff -Nru a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile --- a/drivers/media/radio/Makefile Thu Oct 24 22:22:20 2002 +++ b/drivers/media/radio/Makefile Thu Oct 24 22:22:20 2002 @@ -5,6 +5,8 @@ # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. +obj-y := dummy.o + export-objs := miropcm20-rds-core.o miropcm20-objs := miropcm20-rds-core.o miropcm20-radio.o diff -Nru a/drivers/media/radio/dummy.c b/drivers/media/radio/dummy.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/radio/dummy.c Thu Oct 24 22:22:20 2002 @@ -0,0 +1 @@ +/* just so the linker knows what kind of object files it's deadling with... */ diff -Nru a/drivers/media/video/Makefile b/drivers/media/video/Makefile --- a/drivers/media/video/Makefile Thu Oct 24 22:22:20 2002 +++ b/drivers/media/video/Makefile Thu Oct 24 22:22:20 2002 @@ -5,7 +5,8 @@ # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. -export-objs := videodev.o bttv-if.o cpia.o video-buf.o +obj-y := dummy.o + bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ bttv-risc.o bttv-vbi.o diff -Nru a/drivers/media/video/dummy.c b/drivers/media/video/dummy.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/video/dummy.c Thu Oct 24 22:22:20 2002 @@ -0,0 +1 @@ +/* just so the linker knows what kind of object files it's deadling with... */ diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c --- a/drivers/message/fusion/mptscsih.c Thu Oct 24 22:22:20 2002 +++ b/drivers/message/fusion/mptscsih.c Thu Oct 24 22:22:20 2002 @@ -1295,10 +1295,12 @@ #endif sh->this_id = this->pfacts[portnum].PortSCSIID; +#if 0 /* OS entry to allow host drivers to force * a queue depth on a per device basis. */ sh->select_queue_depths = mptscsih_select_queue_depths; +#endif /* Required entry. */ sh->unique_id = this->id; @@ -3668,6 +3670,7 @@ * Called once per device the bus scan. Use it to force the queue_depth * member to 1 if a device does not support Q tags. */ +#if 0 void mptscsih_select_queue_depths(struct Scsi_Host *sh, Scsi_Device *sdList) { @@ -3700,6 +3703,7 @@ } } } +#endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* diff -Nru a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h --- a/drivers/message/fusion/mptscsih.h Thu Oct 24 22:22:20 2002 +++ b/drivers/message/fusion/mptscsih.h Thu Oct 24 22:22:20 2002 @@ -248,53 +248,44 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) #define MPT_SCSIHOST { \ - next: NULL, \ PROC_SCSI_DECL \ - name: "MPT SCSI Host", \ - detect: x_scsi_detect, \ - release: x_scsi_release, \ - info: x_scsi_info, \ - command: NULL, \ - queuecommand: x_scsi_queuecommand, \ - eh_strategy_handler: NULL, \ - eh_abort_handler: x_scsi_abort, \ - eh_device_reset_handler: x_scsi_dev_reset, \ - eh_bus_reset_handler: x_scsi_bus_reset, \ - eh_host_reset_handler: x_scsi_host_reset, \ - bios_param: x_scsi_bios_param, \ - can_queue: MPT_SCSI_CAN_QUEUE, \ - this_id: -1, \ - sg_tablesize: MPT_SCSI_SG_DEPTH, \ - max_sectors: MPT_SCSI_MAX_SECTORS, \ - cmd_per_lun: MPT_SCSI_CMD_PER_LUN, \ - unchecked_isa_dma: 0, \ - use_clustering: ENABLE_CLUSTERING, \ + .name = "MPT SCSI Host", \ + .detect = x_scsi_detect, \ + .release = x_scsi_release, \ + .info = x_scsi_info, \ + .queuecommand = x_scsi_queuecommand, \ + .eh_abort_handler = x_scsi_abort, \ + .eh_device_reset_handler = x_scsi_dev_reset, \ + .eh_bus_reset_handler = x_scsi_bus_reset, \ + .eh_host_reset_handler = x_scsi_host_reset, \ + .bios_param = x_scsi_bios_param, \ + .can_queue = MPT_SCSI_CAN_QUEUE, \ + .this_id = -1, \ + .sg_tablesize = MPT_SCSI_SG_DEPTH, \ + .max_sectors = MPT_SCSI_MAX_SECTORS, \ + .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ + .use_clustering = ENABLE_CLUSTERING, \ } #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) */ #define MPT_SCSIHOST { \ - next: NULL, \ PROC_SCSI_DECL \ - name: "MPT SCSI Host", \ - detect: x_scsi_detect, \ - release: x_scsi_release, \ - info: x_scsi_info, \ - command: NULL, \ - queuecommand: x_scsi_queuecommand, \ - eh_strategy_handler: NULL, \ - eh_abort_handler: x_scsi_abort, \ - eh_device_reset_handler: x_scsi_dev_reset, \ - eh_bus_reset_handler: x_scsi_bus_reset, \ - eh_host_reset_handler: NULL, \ - bios_param: x_scsi_bios_param, \ - can_queue: MPT_SCSI_CAN_QUEUE, \ - this_id: -1, \ - sg_tablesize: MPT_SCSI_SG_DEPTH, \ - cmd_per_lun: MPT_SCSI_CMD_PER_LUN, \ - unchecked_isa_dma: 0, \ - use_clustering: ENABLE_CLUSTERING, \ - use_new_eh_code: 1 \ + .name = "MPT SCSI Host", \ + .detect = x_scsi_detect, \ + .release = x_scsi_release, \ + .info = x_scsi_info, \ + .queuecommand = x_scsi_queuecommand, \ + .eh_abort_handler = x_scsi_abort, \ + .eh_device_reset_handler = x_scsi_dev_reset, \ + .eh_bus_reset_handler = x_scsi_bus_reset, \ + .bios_param = x_scsi_bios_param, \ + .can_queue = MPT_SCSI_CAN_QUEUE, \ + .this_id = -1, \ + .sg_tablesize = MPT_SCSI_SG_DEPTH, \ + .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ + .use_clustering = ENABLE_CLUSTERING, \ + .use_new_eh_code = 1 \ } #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) */ @@ -302,23 +293,20 @@ #else /* MPT_SCSI_USE_NEW_EH */ #define MPT_SCSIHOST { \ - next: NULL, \ PROC_SCSI_DECL \ - name: "MPT SCSI Host", \ - detect: x_scsi_detect, \ - release: x_scsi_release, \ - info: x_scsi_info, \ - command: NULL, \ - queuecommand: x_scsi_queuecommand, \ - abort: x_scsi_old_abort, \ - reset: x_scsi_old_reset, \ - bios_param: x_scsi_bios_param, \ - can_queue: MPT_SCSI_CAN_QUEUE, \ - this_id: -1, \ - sg_tablesize: MPT_SCSI_SG_DEPTH, \ - cmd_per_lun: MPT_SCSI_CMD_PER_LUN, \ - unchecked_isa_dma: 0, \ - use_clustering: ENABLE_CLUSTERING \ + .name = "MPT SCSI Host", \ + .detect = x_scsi_detect, \ + .release = x_scsi_release, \ + .info = x_scsi_info, \ + .queuecommand = x_scsi_queuecommand, \ + .abort = x_scsi_old_abort, \ + .reset = x_scsi_old_reset, \ + .bios_param = x_scsi_bios_param, \ + .can_queue = MPT_SCSI_CAN_QUEUE, \ + .this_id = -1, \ + .sg_tablesize = MPT_SCSI_SG_DEPTH, \ + .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ + .use_clustering = ENABLE_CLUSTERING \ } #endif /* MPT_SCSI_USE_NEW_EH */ diff -Nru a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c --- a/drivers/net/tulip/media.c Thu Oct 24 22:22:20 2002 +++ b/drivers/net/tulip/media.c Thu Oct 24 22:22:20 2002 @@ -278,6 +278,10 @@ for (i = 0; i < init_length; i++) outl(init_sequence[i], ioaddr + CSR12); } + + (void) inl(ioaddr + CSR6); /* flush CSR12 writes */ + udelay(500); /* Give MII time to recover */ + tmp_info = get_u16(&misc_info[1]); if (tmp_info) tp->advertising[phy_num] = tmp_info | 1; diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c --- a/drivers/scsi/megaraid.c Thu Oct 24 22:22:20 2002 +++ b/drivers/scsi/megaraid.c Thu Oct 24 22:22:20 2002 @@ -2047,7 +2047,7 @@ return; mbox = (mega_mailbox *) pScb->mboxData; - printk ("%u cmd:%x id:%x #scts:%x lba:%x addr:%x logdrv:%x #sg:%x\n", + printk ("%lu cmd:%x id:%x #scts:%x lba:%x addr:%x logdrv:%x #sg:%x\n", pScb->SCpnt->pid, mbox->cmd, mbox->cmdid, mbox->numsectors, mbox->lba, mbox->xferaddr, mbox->logdrv, mbox->numsgelements); @@ -3356,9 +3356,13 @@ mbox[0] = IS_BIOS_ENABLED; mbox[2] = GET_BIOS; - mboxpnt->xferaddr = virt_to_bus ((void *) megacfg->mega_buffer); + mboxpnt->xferaddr = pci_map_single(megacfg->dev, + (void *) megacfg->mega_buffer, (2 * 1024L), + PCI_DMA_FROMDEVICE); ret = megaIssueCmd (megacfg, mbox, NULL, 0); + + pci_unmap_single(megacfg->dev, mboxpnt->xferaddr, 2 * 1024L, PCI_DMA_FROMDEVICE); return (*(char *) megacfg->mega_buffer); } diff -Nru a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h --- a/drivers/scsi/qla1280.h Thu Oct 24 22:22:20 2002 +++ b/drivers/scsi/qla1280.h Thu Oct 24 22:22:20 2002 @@ -1323,36 +1323,22 @@ * Device driver Interfaces to mid-level SCSI driver. */ -#define QLA1280_LINUX_TEMPLATE { \ - next: NULL, \ - module: NULL, \ - proc_dir: NULL, \ - proc_info: qla1280_proc_info, \ - name: "Qlogic ISP 1280/12160", \ - detect: qla1280_detect, \ - release: qla1280_release, \ - info: qla1280_info, \ - ioctl: NULL, \ - command: NULL, \ - queuecommand: qla1280_queuecommand, \ - eh_strategy_handler: NULL, \ - eh_abort_handler: NULL, \ - eh_device_reset_handler: NULL, \ - eh_bus_reset_handler: NULL, \ - eh_host_reset_handler: NULL, \ -/* use_new_eh_code: 0, */ \ - abort: qla1280_abort, \ - reset: qla1280_reset, \ - slave_attach: qla1280_slave_attach, \ - bios_param: qla1280_biosparam, \ - can_queue: 255, /* max simultaneous cmds */\ - this_id: -1, /* scsi id of host adapter */\ - sg_tablesize: SG_ALL, /* max scatter-gather cmds */\ - cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ - present: 0, /* number of 1280's present */\ - unchecked_isa_dma: 0, /* no memory DMA restrictions */\ - use_clustering: ENABLE_CLUSTERING, \ - emulated: 0 \ +#define QLA1280_LINUX_TEMPLATE { \ + .proc_info = qla1280_proc_info, \ + .name = "Qlogic ISP 1280/12160", \ + .detect = qla1280_detect, \ + .release = qla1280_release, \ + .info = qla1280_info, \ + .queuecommand = qla1280_queuecommand, \ + .abort = qla1280_abort, \ + .reset = qla1280_reset, \ + .slave_attach = qla1280_slave_attach, \ + .bios_param = qla1280_biosparam, \ + .can_queue = 255, /* max simultaneous cmds */ \ + .this_id = -1, /* scsi id of host adapter */ \ + .sg_tablesize = SG_ALL, /* max scatter-gather cmds */ \ + .cmd_per_lun = 3, /* cmds per lun (linked cmds) */ \ + .use_clustering = ENABLE_CLUSTERING \ } #endif /* _IO_HBA_QLA1280_H */ diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c --- a/drivers/scsi/scsi_ioctl.c Thu Oct 24 22:22:20 2002 +++ b/drivers/scsi/scsi_ioctl.c Thu Oct 24 22:22:20 2002 @@ -219,6 +219,9 @@ unsigned int needed, buf_needed; int timeout, retries, result; int data_direction, gfp_mask = GFP_KERNEL; +#if __GNUC__ < 3 + int foo; +#endif if (!sic) return -EINVAL; @@ -232,11 +235,21 @@ if (verify_area(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command))) return -EFAULT; +#if __GNUC__ < 3 + foo = __get_user(inlen, &sic->inlen); + if (foo) + return -EFAULT; + + foo = __get_user(outlen, &sic->outlen); + if (foo) + return -EFAULT; +#else if(__get_user(inlen, &sic->inlen)) return -EFAULT; if(__get_user(outlen, &sic->outlen)) return -EFAULT; +#endif /* * We do not transfer more than MAX_BUF with this interface. diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c --- a/drivers/scsi/sym53c8xx_2/sym_glue.c Thu Oct 24 22:22:20 2002 +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c Thu Oct 24 22:22:20 2002 @@ -295,11 +295,7 @@ #ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING typedef u_long bus_addr_t; #else -#if SYM_CONF_DMA_ADDRESSING_MODE > 0 -typedef dma64_addr_t bus_addr_t; -#else typedef dma_addr_t bus_addr_t; -#endif #endif /* diff -Nru a/drivers/scsi/sym53c8xx_2/sym_malloc.c b/drivers/scsi/sym53c8xx_2/sym_malloc.c --- a/drivers/scsi/sym53c8xx_2/sym_malloc.c Thu Oct 24 22:22:20 2002 +++ b/drivers/scsi/sym53c8xx_2/sym_malloc.c Thu Oct 24 22:22:20 2002 @@ -143,12 +143,14 @@ a = (m_addr_t) ptr; while (1) { -#ifdef SYM_MEM_FREE_UNUSED if (s == SYM_MEM_CLUSTER_SIZE) { +#ifdef SYM_MEM_FREE_UNUSED M_FREE_MEM_CLUSTER(a); - break; - } +#else + ((m_link_p) a)->next = h[i].next; + h[i].next = (m_link_p) a; #endif + } b = a ^ s; q = &h[i]; while (q->next && q->next != (m_link_p) b) { diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c --- a/drivers/serial/8250.c Thu Oct 24 22:22:20 2002 +++ b/drivers/serial/8250.c Thu Oct 24 22:22:20 2002 @@ -1915,9 +1915,14 @@ return __register_serial(req, -1); } -int __init early_serial_setup(struct serial_struct *req) +int __init early_register_port (struct uart_port *port) { - __register_serial(req, req->line); + if (port->line >= ARRAY_SIZE(serial8250_ports)) + return -ENODEV; + + serial8250_isa_init_ports(); /* force ISA defaults */ + serial8250_ports[port->line].port = *port; + serial8250_ports[port->line].port.ops = &serial8250_pops; return 0; } diff -Nru a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/8250_acpi.c Thu Oct 24 22:22:20 2002 @@ -0,0 +1,179 @@ +/* + * linux/drivers/char/acpi_serial.c + * + * Copyright (C) 2000, 20002 Hewlett-Packard Co. + * Khalid Aziz + * + * Detect and initialize the headless console serial port defined in SPCR table and debug + * serial port defined in DBGP table. + * + * 2002/08/29 davidm Adjust it to new 2.5 serial driver infrastructure. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#undef SERIAL_DEBUG_ACPI + +/* + * Query ACPI tables for a debug and a headless console serial port. If found, add them to + * rs_table[]. A pointer to either SPCR or DBGP table is passed as parameter. This + * function should be called before serial_console_init() is called to make sure the SPCR + * serial console will be available for use. IA-64 kernel calls this function from within + * acpi.c when it encounters SPCR or DBGP tables as it parses the ACPI 2.0 tables during + * bootup. + */ +void __init +setup_serial_acpi (void *tablep) +{ + acpi_ser_t *acpi_ser_p; + struct uart_port port; + unsigned long iobase; + int gsi; + extern int early_register_port (struct uart_port *); /* XXX fix me */ + +#ifdef SERIAL_DEBUG_ACPI + printk("Entering setup_serial_acpi()\n"); +#endif + + /* Now get the table */ + if (!tablep) + return; + + memset(&port, 0, sizeof(port)); + + acpi_ser_p = (acpi_ser_t *) tablep; + + /* + * Perform a sanity check on the table. Table should have a signature of "SPCR" or + * "DBGP" and it should be atleast 52 bytes long. + */ + if (strncmp(acpi_ser_p->signature, ACPI_SPCRT_SIGNATURE, ACPI_SIG_LEN) != 0 && + strncmp(acpi_ser_p->signature, ACPI_DBGPT_SIGNATURE, ACPI_SIG_LEN) != 0) + return; + if (acpi_ser_p->length < 52) + return; + + iobase = (((u64) acpi_ser_p->base_addr.addrh) << 32) | acpi_ser_p->base_addr.addrl; + gsi = ( (acpi_ser_p->global_int[3] << 24) | (acpi_ser_p->global_int[2] << 16) + | (acpi_ser_p->global_int[1] << 8) | (acpi_ser_p->global_int[0] << 0)); + +#ifdef SERIAL_DEBUG_ACPI + printk("setup_serial_acpi(): table pointer = 0x%p\n", acpi_ser_p); + printk(" sig = '%c%c%c%c'\n", acpi_ser_p->signature[0], + acpi_ser_p->signature[1], acpi_ser_p->signature[2], acpi_ser_p->signature[3]); + printk(" length = %d\n", acpi_ser_p->length); + printk(" Rev = %d\n", acpi_ser_p->rev); + printk(" Interface type = %d\n", acpi_ser_p->intfc_type); + printk(" Base address = 0x%lX\n", iobase); + printk(" IRQ = %d\n", acpi_ser_p->irq); + printk(" Global System Int = %d\n", gsi); + printk(" Baud rate = "); + switch (acpi_ser_p->baud) { + case ACPI_SERIAL_BAUD_9600: + printk("9600\n"); + break; + + case ACPI_SERIAL_BAUD_19200: + printk("19200\n"); + break; + + case ACPI_SERIAL_BAUD_57600: + printk("57600\n"); + break; + + case ACPI_SERIAL_BAUD_115200: + printk("115200\n"); + break; + + default: + printk("Huh (%d)\n", acpi_ser_p->baud); + break; + } + if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_PCICONF_SPACE) { + printk(" PCI serial port:\n"); + printk(" Bus %d, Device %d, Vendor ID 0x%x, Dev ID 0x%x\n", + acpi_ser_p->pci_bus, acpi_ser_p->pci_dev, + acpi_ser_p->pci_vendor_id, acpi_ser_p->pci_dev_id); + } +#endif + /* + * Now build a serial_req structure to update the entry in rs_table for the + * headless console port. + */ + switch (acpi_ser_p->intfc_type) { + case ACPI_SERIAL_INTFC_16550: + port.type = PORT_16550; + port.uartclk = BASE_BAUD * 16; + break; + + case ACPI_SERIAL_INTFC_16450: + port.type = PORT_16450; + port.uartclk = BASE_BAUD * 16; + break; + + default: + port.type = PORT_UNKNOWN; + break; + } + if (strncmp(acpi_ser_p->signature, ACPI_SPCRT_SIGNATURE, ACPI_SIG_LEN) == 0) + port.line = ACPI_SERIAL_CONSOLE_PORT; + else if (strncmp(acpi_ser_p->signature, ACPI_DBGPT_SIGNATURE, ACPI_SIG_LEN) == 0) + port.line = ACPI_SERIAL_DEBUG_PORT; + /* + * Check if this is an I/O mapped address or a memory mapped address + */ + if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_MEM_SPACE) { + port.iobase = 0; + port.mapbase = iobase; + port.membase = ioremap(iobase, 64); + port.iotype = SERIAL_IO_MEM; + } else if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_IO_SPACE) { + port.iobase = iobase; + port.mapbase = 0; + port.membase = NULL; + port.iotype = SERIAL_IO_PORT; + } else if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_PCICONF_SPACE) { + printk("WARNING: No support for PCI serial console\n"); + return; + } + + /* + * If the table does not have IRQ information, use 0 for IRQ. This will force + * rs_init() to probe for IRQ. + */ + if (acpi_ser_p->length < 53) + port.irq = 0; + else { + port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ; + if (acpi_ser_p->int_type & (ACPI_SERIAL_INT_APIC | ACPI_SERIAL_INT_SAPIC)) + port.irq = gsi; + else if (acpi_ser_p->int_type & ACPI_SERIAL_INT_PCAT) + port.irq = acpi_ser_p->irq; + else + /* + * IRQ type not being set would mean UART will run in polling + * mode. Do not probe for IRQ in that case. + */ + port.flags &= UPF_AUTO_IRQ; + } + port.fifosize = 0; + port.hub6 = 0; + port.regshift = 0; + if (early_register_port(&port) < 0) { + printk("early_register_port() for ACPI serial console port failed\n"); + return; + } + +#ifdef SERIAL_DEBUG_ACPI + printk("Leaving setup_serial_acpi()\n"); +#endif +} diff -Nru a/drivers/serial/8250_hcdp.c b/drivers/serial/8250_hcdp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/8250_hcdp.c Thu Oct 24 22:22:20 2002 @@ -0,0 +1,242 @@ +/* + * linux/drivers/char/hcdp_serial.c + * + * Copyright (C) 2002 Hewlett-Packard Co. + * Khalid Aziz + * + * Parse the EFI HCDP table to locate serial console and debug ports and initialize them. + * + * 2002/08/29 davidm Adjust it to new 2.5 serial driver infrastructure (untested). + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SERIAL_DEBUG_HCDP + +/* + * Parse the HCDP table to find descriptions for headless console and debug serial ports + * and add them to rs_table[]. A pointer to HCDP table is passed as parameter. This + * function should be called before serial_console_init() is called to make sure the HCDP + * serial console will be available for use. IA-64 kernel calls this function from + * setup_arch() after the EFI and ACPI tables have been parsed. + */ +void __init +setup_serial_hcdp (void *tablep) +{ + hcdp_dev_t *hcdp_dev; + struct uart_port port; + unsigned long iobase; + hcdp_t hcdp; + int gsi, i = 0, nr; +#if 0 + static int shift_once = 1; +#endif + extern int early_register_port (struct uart_port *); /* XXX fix me */ + +#ifdef SERIAL_DEBUG_HCDP + printk("Entering setup_serial_hcdp()\n"); +#endif + + /* Verify we have a valid table pointer */ + if (!tablep) + return; + + memset(&port, 0, sizeof(port)); + + /* + * Don't trust firmware to give us a table starting at an aligned address. Make a + * local copy of the HCDP table with aligned structures. + */ + memcpy(&hcdp, tablep, sizeof(hcdp)); + + /* + * Perform a sanity check on the table. Table should have a signature of "HCDP" + * and it should be atleast 82 bytes long to have any useful information. + */ + if ((strncmp(hcdp.signature, HCDP_SIGNATURE, HCDP_SIG_LEN) != 0)) + return; + if (hcdp.len < 82) + return; + +#ifdef SERIAL_DEBUG_HCDP + printk("setup_serial_hcdp(): table pointer = 0x%p\n", tablep); + printk(" sig = '%c%c%c%c'\n", + hcdp.signature[0], hcdp.signature[1], hcdp.signature[2], hcdp.signature[3]); + printk(" length = %d\n", hcdp.len); + printk(" Rev = %d\n", hcdp.rev); + printk(" OEM ID = %c%c%c%c%c%c\n", + hcdp.oemid[0], hcdp.oemid[1], hcdp.oemid[2], + hcdp.oemid[3], hcdp.oemid[4], hcdp.oemid[5]); + printk(" Number of entries = %d\n", hcdp.num_entries); +#endif + + /* + * Parse each device entry + */ + for (nr = 0; nr < hcdp.num_entries; nr++) { + hcdp_dev = hcdp.hcdp_dev + nr; + /* + * We will parse only the primary console device which is the first entry + * for these devices. We will ignore rest of the entries for the same type + * device that has already been parsed and initialized + */ + if (hcdp_dev->type != HCDP_DEV_CONSOLE) + continue; + + iobase = ((u64) hcdp_dev->base_addr.addrhi << 32) | hcdp_dev->base_addr.addrlo; + gsi = hcdp_dev->global_int; +#ifdef SERIAL_DEBUG_HCDP + printk(" type = %s\n", + ((hcdp_dev->type == HCDP_DEV_CONSOLE) + ? "Headless Console" : ((hcdp_dev->type == HCDP_DEV_DEBUG) + ? "Debug port" : "Huh????"))); + printk(" Base address space = %s\n", + ((hcdp_dev->base_addr.space_id == ACPI_MEM_SPACE) + ? "Memory Space" : ((hcdp_dev->base_addr.space_id == ACPI_IO_SPACE) + ? "I/O space" : "PCI space"))); + printk(" Base address = 0x%lx\n", iobase); + printk(" Global System Int = %d\n", gsi); + printk(" Baud rate = %lu\n", (unsigned long) hcdp_dev->baud); + printk(" Bits = %d\n", hcdp_dev->bits); + printk(" Clock rate = %d\n", hcdp_dev->clock_rate); + if (hcdp_dev->base_addr.space_id == ACPI_PCICONF_SPACE) { + printk(" PCI serial port:\n"); + printk(" Bus %d, Device %d, Vendor ID 0x%x, Dev ID 0x%x\n", + hcdp_dev->pci_bus, hcdp_dev->pci_dev, + hcdp_dev->pci_vendor_id, hcdp_dev->pci_dev_id); + } +#endif + /* + * Now fill in a port structure to update the 8250 port table.. + */ + if (hcdp_dev->clock_rate) + port.uartclk = hcdp_dev->clock_rate; + else + port.uartclk = DEFAULT_UARTCLK; + /* + * Check if this is an I/O mapped address or a memory mapped address + */ + if (hcdp_dev->base_addr.space_id == ACPI_MEM_SPACE) { + port.iobase = 0; + port.mapbase = iobase; + port.membase = ioremap(iobase, 64); + port.iotype = SERIAL_IO_MEM; + } else if (hcdp_dev->base_addr.space_id == ACPI_IO_SPACE) { + port.iobase = iobase; + port.mapbase = 0; + port.membase = NULL; + port.iotype = SERIAL_IO_PORT; + } else if (hcdp_dev->base_addr.space_id == ACPI_PCICONF_SPACE) { + printk("WARNING: No support for PCI serial console\n"); + return; + } + +#if 0 + /* + * Check if HCDP defines a port already in rs_table + */ + for (i = 0; i < serial_nr_ports; i++) { + if ((rs_table[i].port == serial_req.port) && + (rs_table[i].iomem_base==serial_req.iomem_base)) + break; + } + if (i == serial_nr_ports) { + /* + * We have reserved a slot for HCDP defined console port at + * HCDP_SERIAL_CONSOLE_PORT in rs_table which is not 0. This means + * using this slot would put the console at a device other than + * ttyS0. Users expect to see the console at ttyS0. Now that we + * have determined HCDP does describe a serial console and it is + * not one of the compiled in ports, let us move the entries in + * rs_table up by a slot towards HCDP_SERIAL_CONSOLE_PORT to make + * room for the HCDP console at ttyS0. We may go through this loop + * more than once if early_serial_setup() fails. Make sure we + * shift the entries in rs_table only once. + */ + if (shift_once) { + int j; + + for (j = HCDP_SERIAL_CONSOLE_PORT; j > 0; j--) + memcpy(rs_table+j, rs_table+j-1, + sizeof(struct serial_state)); + shift_once = 0; + } + serial_req.line = 0; + } else + serial_req.line = i; +#else + port.line = i++; /* XXX fix me */ +#endif + + port.irq = gsi; + port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + if (gsi) + port.flags |= ASYNC_AUTO_IRQ; + + port.fifosize = 0; + port.hub6 = 0; + port.regshift = 0; + if (early_register_port(&port) < 0) { + printk("setup_serial_hcdp(): early_register_port() for HCDP serial " + "console port failed. Will try any additional consoles in HCDP.\n"); + continue; + } else if (hcdp_dev->type == HCDP_DEV_CONSOLE) + break; +#ifdef SERIAL_DEBUG_HCDP + printk("\n"); +#endif + } + +#ifdef SERIAL_DEBUG_HCDP + printk("Leaving setup_serial_hcdp()\n"); +#endif +} + +#ifdef CONFIG_IA64_EARLY_PRINTK_UART +unsigned long +hcdp_early_uart (void) +{ + efi_system_table_t *systab; + efi_config_table_t *config_tables; + hcdp_t *hcdp = 0; + hcdp_dev_t *dev; + int i; + + systab = (efi_system_table_t *) ia64_boot_param->efi_systab; + if (!systab) + return 0; + systab = __va(systab); + + config_tables = (efi_config_table_t *) systab->tables; + if (!config_tables) + return 0; + config_tables = __va(config_tables); + + for (i = 0; i < systab->nr_tables; i++) { + if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { + hcdp = (hcdp_t *) config_tables[i].table; + break; + } + } + if (!hcdp) + return 0; + hcdp = __va(hcdp); + + for (i = 0, dev = hcdp->hcdp_dev; i < hcdp->num_entries; i++, dev++) { + if (dev->type == HCDP_DEV_CONSOLE) + return (u64) dev->base_addr.addrhi << 32 | dev->base_addr.addrlo; + } + return 0; +} +#endif /* CONFIG_IA64_EARLY_PRINTK_UART */ diff -Nru a/drivers/serial/Config.in b/drivers/serial/Config.in --- a/drivers/serial/Config.in Thu Oct 24 22:22:20 2002 +++ b/drivers/serial/Config.in Thu Oct 24 22:22:20 2002 @@ -11,6 +11,10 @@ dep_tristate '8250/16550 and compatible serial support (EXPERIMENTAL)' CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL dep_bool ' Console on 8250/16550 and compatible serial port (EXPERIMENTAL)' CONFIG_SERIAL_8250_CONSOLE $CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL dep_tristate ' 8250/16550 PCMCIA device support' CONFIG_SERIAL_8250_CS $CONFIG_PCMCIA $CONFIG_SERIAL_8250 +if [ "$CONFIG_IA64" = "y" ]; then + dep_tristate ' 8250/16550 device discovery support via ACPI SPCR/DBGP tables' CONFIG_SERIAL_8250_ACPI + dep_tristate ' 8250/16550 device discovery support via EFI HCDP table' CONFIG_SERIAL_8250_HCDP +fi dep_mbool 'Extended 8250/16550 serial driver options' CONFIG_SERIAL_8250_EXTENDED $CONFIG_SERIAL_8250 dep_bool ' Support more than 4 serial ports' CONFIG_SERIAL_8250_MANY_PORTS $CONFIG_SERIAL_8250_EXTENDED diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile --- a/drivers/serial/Makefile Thu Oct 24 22:22:20 2002 +++ b/drivers/serial/Makefile Thu Oct 24 22:22:20 2002 @@ -9,6 +9,8 @@ serial-8250-y := serial-8250-$(CONFIG_PCI) += 8250_pci.o serial-8250-$(CONFIG_PNP) += 8250_pnp.o +serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o +serial-8250-$(CONFIG_SERIAL_8250_HCDP) += 8250_hcdp.o obj-$(CONFIG_SERIAL_CORE) += core.o obj-$(CONFIG_SERIAL_21285) += 21285.o obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y) diff -Nru a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c --- a/drivers/video/radeonfb.c Thu Oct 24 22:22:20 2002 +++ b/drivers/video/radeonfb.c Thu Oct 24 22:22:20 2002 @@ -233,8 +233,8 @@ u32 mmio_base_phys; u32 fb_base_phys; - u32 mmio_base; - u32 fb_base; + void *mmio_base; + void *fb_base; struct pci_dev *pdev; @@ -727,8 +727,7 @@ } /* map the regions */ - rinfo->mmio_base = (u32) ioremap (rinfo->mmio_base_phys, - RADEON_REGSIZE); + rinfo->mmio_base = ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE); if (!rinfo->mmio_base) { printk ("radeonfb: cannot map MMIO\n"); release_mem_region (rinfo->mmio_base_phys, @@ -858,8 +857,7 @@ } } - rinfo->fb_base = (u32) ioremap (rinfo->fb_base_phys, - rinfo->video_ram); + rinfo->fb_base = ioremap (rinfo->fb_base_phys, rinfo->video_ram); if (!rinfo->fb_base) { printk ("radeonfb: cannot map FB\n"); iounmap ((void*)rinfo->mmio_base); diff -Nru a/fs/binfmt_misc.c b/fs/binfmt_misc.c --- a/fs/binfmt_misc.c Thu Oct 24 22:22:20 2002 +++ b/fs/binfmt_misc.c Thu Oct 24 22:22:20 2002 @@ -36,6 +36,7 @@ static int enabled = 1; enum {Enabled, Magic}; +#define MISC_FMT_PRESERVE_ARGV0 (1<<31) typedef struct { struct list_head list; @@ -124,7 +125,9 @@ bprm->file = NULL; /* Build args for interpreter */ - remove_arg_zero(bprm); + if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) { + remove_arg_zero(bprm); + } retval = copy_strings_kernel(1, &bprm->filename, bprm); if (retval < 0) goto _ret; bprm->argc++; @@ -289,6 +292,11 @@ *p++ = '\0'; if (!e->interpreter[0]) goto Einval; + + if (*p == 'P') { + p++; + e->flags |= MISC_FMT_PRESERVE_ARGV0; + } if (*p == '\n') p++; diff -Nru a/fs/exec.c b/fs/exec.c --- a/fs/exec.c Thu Oct 24 22:22:20 2002 +++ b/fs/exec.c Thu Oct 24 22:22:20 2002 @@ -398,7 +398,7 @@ mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; mpnt->vm_end = STACK_TOP; #endif - mpnt->vm_page_prot = PAGE_COPY; + mpnt->vm_page_prot = protection_map[VM_STACK_FLAGS & 0x7]; mpnt->vm_flags = VM_STACK_FLAGS; mpnt->vm_ops = NULL; mpnt->vm_pgoff = 0; diff -Nru a/fs/fcntl.c b/fs/fcntl.c --- a/fs/fcntl.c Thu Oct 24 22:22:20 2002 +++ b/fs/fcntl.c Thu Oct 24 22:22:20 2002 @@ -328,6 +328,7 @@ * to fix this will be in libc. */ err = filp->f_owner.pid; + force_successful_syscall_return(); break; case F_SETOWN: err = f_setown(filp, arg, 1); diff -Nru a/fs/proc/base.c b/fs/proc/base.c --- a/fs/proc/base.c Thu Oct 24 22:22:20 2002 +++ b/fs/proc/base.c Thu Oct 24 22:22:20 2002 @@ -508,7 +508,24 @@ } #endif +static loff_t mem_lseek(struct file * file, loff_t offset, int orig) +{ + switch (orig) { + case 0: + file->f_pos = offset; + break; + case 1: + file->f_pos += offset; + break; + default: + return -EINVAL; + } + force_successful_syscall_return(); + return file->f_pos; +} + static struct file_operations proc_mem_operations = { + .llseek = mem_lseek, .read = mem_read, .write = mem_write, .open = mem_open, diff -Nru a/fs/select.c b/fs/select.c --- a/fs/select.c Thu Oct 24 22:22:20 2002 +++ b/fs/select.c Thu Oct 24 22:22:20 2002 @@ -182,38 +182,53 @@ wait = NULL; retval = 0; for (;;) { + unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; set_current_state(TASK_INTERRUPTIBLE); - for (i = 0 ; i < n; i++) { - unsigned long bit = BIT(i); - unsigned long mask; - struct file *file; - off = i / __NFDBITS; - if (!(bit & BITS(fds, off))) + inp = fds->in; outp = fds->out; exp = fds->ex; + rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex; + + for (i = 0; i < n; ++rinp, ++routp, ++rexp) { + unsigned long in, out, ex, all_bits, bit = 1, mask, j; + unsigned long res_in = 0, res_out = 0, res_ex = 0; + struct file_operations *f_op; + struct file *file = NULL; + + in = *inp++; out = *outp++; ex = *exp++; + all_bits = in | out | ex; + if (all_bits == 0) continue; - file = fget(i); - mask = POLLNVAL; - if (file) { + + for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) { + if (i >= n) + break; + if (!(bit & all_bits)) + continue; + file = fget(i); + if (file) + f_op = file->f_op; mask = DEFAULT_POLLMASK; - if (file->f_op && file->f_op->poll) - mask = file->f_op->poll(file, wait); - fput(file); - } - if ((mask & POLLIN_SET) && ISSET(bit, __IN(fds,off))) { - SET(bit, __RES_IN(fds,off)); - retval++; - wait = NULL; - } - if ((mask & POLLOUT_SET) && ISSET(bit, __OUT(fds,off))) { - SET(bit, __RES_OUT(fds,off)); - retval++; - wait = NULL; - } - if ((mask & POLLEX_SET) && ISSET(bit, __EX(fds,off))) { - SET(bit, __RES_EX(fds,off)); - retval++; - wait = NULL; + if (file) { + if (f_op && f_op->poll) + mask = (*f_op->poll)(file, retval ? NULL : wait); + fput(file); + if ((mask & POLLIN_SET) && (in & bit)) { + res_in |= bit; + retval++; + } + if ((mask & POLLOUT_SET) && (out & bit)) { + res_out |= bit; + retval++; + } + if ((mask & POLLEX_SET) && (ex & bit)) { + res_ex |= bit; + retval++; + } + } } + if (res_in) *rinp = res_in; + if (res_out) *routp = res_out; + if (res_ex) *rexp = res_ex; } wait = NULL; if (retval || !__timeout || signal_pending(current)) diff -Nru a/include/asm-alpha/agp.h b/include/asm-alpha/agp.h --- a/include/asm-alpha/agp.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-alpha/agp.h Thu Oct 24 22:22:20 2002 @@ -8,4 +8,11 @@ #define flush_agp_mappings() #define flush_agp_cache() mb() +/* + * Page-protection value to be used for AGP memory mapped into kernel space. For + * platforms which use coherent AGP DMA, this can be PAGE_KERNEL. For others, it needs to + * be an uncached mapping (such as write-combining). + */ +#define PAGE_AGP PAGE_KERNEL_NOCACHE /* XXX fix me */ + #endif diff -Nru a/include/asm-i386/agp.h b/include/asm-i386/agp.h --- a/include/asm-i386/agp.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-i386/agp.h Thu Oct 24 22:22:20 2002 @@ -20,4 +20,11 @@ worth it. Would need a page for it. */ #define flush_agp_cache() asm volatile("wbinvd":::"memory") +/* + * Page-protection value to be used for AGP memory mapped into kernel space. For + * platforms which use coherent AGP DMA, this can be PAGE_KERNEL. For others, it needs to + * be an uncached mapping (such as write-combining). + */ +#define PAGE_AGP PAGE_KERNEL_NOCACHE + #endif diff -Nru a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h --- a/include/asm-i386/hw_irq.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-i386/hw_irq.h Thu Oct 24 22:22:20 2002 @@ -140,4 +140,6 @@ static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} #endif +extern irq_desc_t irq_desc [NR_IRQS]; + #endif /* _ASM_HW_IRQ_H */ diff -Nru a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h --- a/include/asm-i386/ptrace.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-i386/ptrace.h Thu Oct 24 22:22:20 2002 @@ -57,6 +57,7 @@ #ifdef __KERNEL__ #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs)) #define instruction_pointer(regs) ((regs)->eip) +#define force_successful_syscall_return() do { } while (0) #endif #endif diff -Nru a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h --- a/include/asm-ia64/acpi.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/acpi.h Thu Oct 24 22:22:20 2002 @@ -97,17 +97,18 @@ } while (0) const char *acpi_get_sysname (void); -int acpi_boot_init (char *cdline); int acpi_request_vector (u32 int_type); int acpi_get_prt (struct pci_vector_struct **vectors, int *count); int acpi_get_interrupt_model (int *type); int acpi_irq_to_vector (u32 irq); -#ifdef CONFIG_DISCONTIGMEM -#define NODE_ARRAY_INDEX(x) ((x) / 8) /* 8 bits/char */ -#define NODE_ARRAY_OFFSET(x) ((x) % 8) /* 8 bits/char */ -#define MAX_PXM_DOMAINS (256) -#endif /* CONFIG_DISCONTIGMEM */ +#ifdef CONFIG_ACPI_NUMA +#include +/* Proximity bitmap length; _PXM is at most 255 (8 bit)*/ +#define MAX_PXM_DOMAINS (256) +extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS]; +extern int __initdata nid_to_pxm_map[NR_NODES]; +#endif #endif /*__KERNEL__*/ diff -Nru a/include/asm-ia64/ia32.h b/include/asm-ia64/ia32.h --- a/include/asm-ia64/ia32.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/ia32.h Thu Oct 24 22:22:20 2002 @@ -73,6 +73,17 @@ unsigned short exponent; }; +struct _fpxreg_ia32 { + unsigned short significand[4]; + unsigned short exponent; + unsigned short padding[3]; +}; + +struct _xmmreg_ia32 { + unsigned int element[4]; +}; + + struct _fpstate_ia32 { unsigned int cw, sw, @@ -82,7 +93,16 @@ dataoff, datasel; struct _fpreg_ia32 _st[8]; - unsigned int status; + unsigned short status; + unsigned short magic; /* 0xffff = regular FPU data only */ + + /* FXSR FPU environment */ + unsigned int _fxsr_env[6]; /* FXSR FPU env is ignored */ + unsigned int mxcsr; + unsigned int reserved; + struct _fpxreg_ia32 _fxsr_st[8]; /* FXSR FPU reg data is ignored */ + struct _xmmreg_ia32 _xmm[8]; + unsigned int padding[56]; }; struct sigcontext_ia32 { @@ -485,6 +505,18 @@ extern int ia32_intercept (struct pt_regs *regs, unsigned long isr); extern unsigned long ia32_do_mmap (struct file *, unsigned long, unsigned long, int, int, loff_t); extern void ia32_load_segment_descriptors (struct task_struct *task); + +#define ia32f2ia64f(dst,src) \ + do { \ + register double f6 asm ("f6"); \ + asm volatile ("ldfe f6=[%2];; stf.spill [%1]=f6" : "=f"(f6): "r"(dst), "r"(src) : "memory"); \ + } while(0) + +#define ia64f2ia32f(dst,src) \ + do { \ + register double f6 asm ("f6"); \ + asm volatile ("ldf.fill f6=[%2];; stfe [%1]=f6" : "=f"(f6): "r"(dst), "r"(src) : "memory"); \ + } while(0) #endif /* !CONFIG_IA32_SUPPORT */ diff -Nru a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h --- a/include/asm-ia64/iosapic.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/iosapic.h Thu Oct 24 22:22:20 2002 @@ -55,6 +55,8 @@ unsigned int gsi_base, int pcat_compat); extern int gsi_to_vector (unsigned int gsi); +extern int gsi_to_irq (unsigned int gsi); +extern void iosapic_parse_prt (void); extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity, unsigned long edge_triggered, u32 gsi_base, char *iosapic_address); diff -Nru a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/mmzone.h Thu Oct 24 22:22:20 2002 @@ -0,0 +1,130 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2000 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2002 NEC Corp. + * Copyright (c) 2002 Erich Focht + * Copyright (c) 2002 Kimio Suganuma + */ +#ifndef _ASM_IA64_MMZONE_H +#define _ASM_IA64_MMZONE_H + +#include +#include + +/* + * Given a kaddr, find the base mem_map address for the start of the mem_map + * entries for the bank containing the kaddr. + */ +#define BANK_MEM_MAP_BASE(kaddr) local_node_data->bank_mem_map_base[BANK_MEM_MAP_INDEX(kaddr)] + +/* + * Given a kaddr, this macro return the relative map number + * within the bank. + */ +#define BANK_MAP_NR(kaddr) (BANK_OFFSET(kaddr) >> PAGE_SHIFT) + +/* + * Given a pte, this macro returns a pointer to the page struct for the pte. + */ +#define pte_page(pte) virt_to_page(PAGE_OFFSET | (pte_val(pte)&_PFN_MASK)) + +/* + * Determine if a kaddr is a valid memory address of memory that + * actually exists. + * + * The check consists of 2 parts: + * - verify that the address is a region 7 address & does not + * contain any bits that preclude it from being a valid platform + * memory address + * - verify that the chunk actually exists. + * + * Note that IO addresses are NOT considered valid addresses. + * + * Note, many platforms can simply check if kaddr exceeds a specific size. + * (However, this wont work on SGI platforms since IO space is embedded + * within the range of valid memory addresses & nodes have holes in the + * address range between banks). + */ +#define kern_addr_valid(kaddr) ({long _kav=(long)(kaddr); \ + VALID_MEM_KADDR(_kav);}) + +/* + * Given a kaddr, return a pointer to the page struct for the page. + * If the kaddr does not represent RAM memory that potentially exists, return + * a pointer the page struct for max_mapnr. IO addresses will + * return the page for max_nr. Addresses in unpopulated RAM banks may + * return undefined results OR may panic the system. + * + */ +#define virt_to_page(kaddr) ({long _kvtp=(long)(kaddr); \ + (VALID_MEM_KADDR(_kvtp)) \ + ? BANK_MEM_MAP_BASE(_kvtp) + BANK_MAP_NR(_kvtp) \ + : NULL;}) + +/* + * Given a page struct entry, return the physical address that the page struct represents. + * Since IA64 has all memory in the DMA zone, the following works: + */ +#define page_to_phys(page) __pa(page_address(page)) + +#define node_mem_map(nid) (NODE_DATA(nid)->node_mem_map) + +#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn) + +#define pfn_to_page(pfn) (struct page *)(node_mem_map(pfn_to_nid(pfn)) + node_localnr(pfn, pfn_to_nid(pfn))) + +#define pfn_to_nid(pfn) local_node_data->node_id_map[(pfn << PAGE_SHIFT) >> DIG_BANKSHIFT] + +#define page_to_pfn(page) (long)((page - page_zone(page)->zone_mem_map) + page_zone(page)->zone_start_pfn) + + +/* + * pfn_valid should be made as fast as possible, and the current definition + * is valid for machines that are NUMA, but still contiguous, which is what + * is currently supported. A more generalised, but slower definition would + * be something like this - mbligh: + * ( pfn_to_pgdat(pfn) && (pfn < node_end_pfn(pfn_to_nid(pfn))) ) + */ +#define pfn_valid(pfn) (pfn < max_low_pfn) +extern unsigned long max_low_pfn; + + +#ifdef CONFIG_IA64_DIG + +/* + * Platform definitions for DIG platform with contiguous memory. + */ +#define MAX_PHYSNODE_ID 8 /* Maximum node number +1 */ +#define NR_NODES 8 /* Maximum number of nodes in SSI */ + +#define MAX_PHYS_MEMORY (1UL << 40) /* 1 TB */ + +/* + * Bank definitions. + * Current settings for DIG: 512MB/bank, 16GB/node. + */ +#define NR_BANKS_PER_NODE 32 +#define BANK_OFFSET(addr) ((unsigned long)(addr) & (BANKSIZE-1)) +#define DIG_BANKSHIFT 29 +#define BANKSIZE (1UL << DIG_BANKSHIFT) +#define NR_BANKS (NR_BANKS_PER_NODE * NR_NODES) + +/* + * VALID_MEM_KADDR returns a boolean to indicate if a kaddr is + * potentially a valid cacheable identity mapped RAM memory address. + * Note that the RAM may or may not actually be present!! + */ +#define VALID_MEM_KADDR(kaddr) 1 + +/* + * Given a nodeid & a bank number, find the address of the mem_map + * entry for the first page of the bank. + */ +#define BANK_MEM_MAP_INDEX(kaddr) \ + (((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> DIG_BANKSHIFT) + +#endif /* CONFIG_IA64_DIG */ +#endif /* _ASM_IA64_MMZONE_H */ diff -Nru a/include/asm-ia64/nodedata.h b/include/asm-ia64/nodedata.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/nodedata.h Thu Oct 24 22:22:20 2002 @@ -0,0 +1,75 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2000 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2002 NEC Corp. + * Copyright (c) 2002 Erich Focht + * Copyright (c) 2002 Kimio Suganuma + */ + + +#ifndef _ASM_IA64_NODEDATA_H +#define _ASM_IA64_NODEDATA_H + + +#include + +/* + * Node Data. One of these structures is located on each node of a NUMA system. + */ + +struct pglist_data; +struct ia64_node_data { + short node; + struct pglist_data *pg_data_ptrs[NR_NODES]; + struct page *bank_mem_map_base[NR_BANKS]; + struct ia64_node_data *node_data_ptrs[NR_NODES]; + short node_id_map[NR_BANKS]; +}; + + +/* + * Return a pointer to the node_data structure for the executing cpu. + */ +#define local_node_data (local_cpu_data->node_data) + + +/* + * Return a pointer to the node_data structure for the specified node. + */ +#define node_data(node) (local_node_data->node_data_ptrs[node]) + +/* + * Get a pointer to the node_id/node_data for the current cpu. + * (boot time only) + */ +extern int boot_get_local_nodeid(void); +extern struct ia64_node_data *get_node_data_ptr(void); + +/* + * Given a node id, return a pointer to the pg_data_t for the node. + * The following 2 macros are similar. + * + * NODE_DATA - should be used in all code not related to system + * initialization. It uses pernode data structures to minimize + * offnode memory references. However, these structure are not + * present during boot. This macro can be used once cpu_init + * completes. + * + * BOOT_NODE_DATA + * - should be used during system initialization + * prior to freeing __initdata. It does not depend on the percpu + * area being present. + * + * NOTE: The names of these macros are misleading but are difficult to change + * since they are used in generic linux & on other architecures. + */ +#define NODE_DATA(nid) (local_node_data->pg_data_ptrs[nid]) +#define BOOT_NODE_DATA(nid) boot_get_pg_data_ptr((long)(nid)) + +struct pglist_data; +extern struct pglist_data * __init boot_get_pg_data_ptr(long); + +#endif /* _ASM_IA64_NODEDATA_H */ diff -Nru a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/numa.h Thu Oct 24 22:22:20 2002 @@ -0,0 +1,65 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * This file contains NUMA specific prototypes and definitions. + * + * 2002/08/05 Erich Focht + * + */ +#ifndef _ASM_IA64_NUMA_H +#define _ASM_IA64_NUMA_H + +#ifdef CONFIG_NUMA + +#ifdef CONFIG_DISCONTIGMEM +# include +# define NR_MEMBLKS (NR_BANKS) +#else +# define NR_NODES (8) +# define NR_MEMBLKS (NR_NODES * 8) +#endif + +extern char cpu_to_node_map[NR_CPUS] __cacheline_aligned; + +/* Stuff below this line could be architecture independent */ + +extern int num_memblks; /* total number of memory chunks */ + +/* + * List of node memory chunks. Filled when parsing SRAT table to + * obtain information about memory nodes. +*/ + +struct node_memblk_s { + unsigned long start_paddr; + unsigned long size; + int nid; /* which logical node contains this chunk? */ + int bank; /* which mem bank on this node */ +}; + +struct node_cpuid_s { + u16 phys_id; /* id << 8 | eid */ + int nid; /* logical node containing this CPU */ +}; + +extern struct node_memblk_s node_memblk[NR_MEMBLKS]; +extern struct node_cpuid_s node_cpuid[NR_CPUS]; + +/* + * ACPI 2.0 SLIT (System Locality Information Table) + * http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf + * + * This is a matrix with "distances" between nodes, they should be + * proportional to the memory access latency ratios. + */ + +extern u8 numa_slit[NR_NODES * NR_NODES]; +#define node_distance(from,to) (numa_slit[from * numnodes + to]) + +extern int paddr_to_nid(unsigned long paddr); + +#endif /* CONFIG_NUMA */ + +#endif /* _ASM_IA64_NUMA_H */ diff -Nru a/include/asm-ia64/numnodes.h b/include/asm-ia64/numnodes.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/numnodes.h Thu Oct 24 22:22:20 2002 @@ -0,0 +1,7 @@ +#ifndef _ASM_MAX_NUMNODES_H +#define _ASM_MAX_NUMNODES_H + +#include +#define MAX_NUMNODES NR_NODES + +#endif /* _ASM_MAX_NUMNODES_H */ diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h --- a/include/asm-ia64/page.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/page.h Thu Oct 24 22:22:20 2002 @@ -82,12 +82,15 @@ flush_dcache_page(page); \ } while (0) -#define pfn_valid(pfn) ((pfn) < max_mapnr) #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) + +#ifndef CONFIG_DISCONTIGMEM +#define pfn_valid(pfn) ((pfn) < max_mapnr) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define page_to_pfn(page) ((unsigned long) (page - mem_map)) #define pfn_to_page(pfn) (mem_map + (pfn)) #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) +#endif typedef union ia64_va { struct { diff -Nru a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h --- a/include/asm-ia64/perfmon.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/perfmon.h Thu Oct 24 22:22:20 2002 @@ -123,7 +123,7 @@ * Define the version numbers for both perfmon as a whole and the sampling buffer format. */ #define PFM_VERSION_MAJ 1U -#define PFM_VERSION_MIN 0U +#define PFM_VERSION_MIN 1U #define PFM_VERSION (((PFM_VERSION_MAJ&0xffff)<<16)|(PFM_VERSION_MIN & 0xffff)) #define PFM_SMPL_VERSION_MAJ 1U diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h --- a/include/asm-ia64/processor.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/processor.h Thu Oct 24 22:22:20 2002 @@ -89,6 +89,9 @@ #include #include #include +#ifdef CONFIG_NUMA +#include +#endif /* like above but expressed as bitfields for more efficient access: */ struct ia64_psr { @@ -174,6 +177,10 @@ __u64 prof_counter; __u64 prof_multiplier; #endif +#ifdef CONFIG_NUMA + struct ia64_node_data *node_data; + int nodeid; +#endif }; DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info); @@ -184,6 +191,10 @@ */ #define local_cpu_data (&__get_cpu_var(cpu_info)) #define cpu_data(cpu) (&per_cpu(cpu_info, cpu)) + +#ifdef CONFIG_NUMA +#define numa_node_id() (local_cpu_data->nodeid) +#endif extern void identify_cpu (struct cpuinfo_ia64 *); extern void print_cpu_info (struct cpuinfo_ia64 *); diff -Nru a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h --- a/include/asm-ia64/siginfo.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/siginfo.h Thu Oct 24 22:22:20 2002 @@ -148,8 +148,8 @@ if (from->si_code < 0) memcpy(to, from, sizeof(siginfo_t)); else - /* _sigchld is currently the largest know union member */ - memcpy(to, from, 4*sizeof(int) + sizeof(from->_sifields._sigchld)); + /* _sigprof is currently the largest know union member */ + memcpy(to, from, 4*sizeof(int) + sizeof(from->_sifields._sigprof)); } extern int copy_siginfo_from_user(siginfo_t *to, siginfo_t *from); diff -Nru a/include/asm-ia64/sn/bte_copy.h b/include/asm-ia64/sn/bte_copy.h --- a/include/asm-ia64/sn/bte_copy.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/sn/bte_copy.h Thu Oct 24 22:22:20 2002 @@ -250,7 +250,7 @@ * status register into the notification area. * This fakes the shub performing the copy. */ - if (jiffies > bte->idealTransferTimeout) { + if (time_after(jiffies, bte->idealTransferTimeout)) { bte->notify = HUB_L(bte->bte_base_addr); bte->idealTransferTimeoutReached++; bte->idealTransferTimeout = jiffies + diff -Nru a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h --- a/include/asm-ia64/thread_info.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/thread_info.h Thu Oct 24 22:22:20 2002 @@ -37,11 +37,11 @@ #define INIT_THREAD_INFO(ti) \ { \ - exec_domain: &default_exec_domain, \ - flags: 0, \ - cpu: 0, \ - addr_limit: KERNEL_DS, \ - preempt_count: 0, \ + .exec_domain = &default_exec_domain, \ + .flags = 0, \ + .cpu = 0, \ + .addr_limit = KERNEL_DS, \ + .preempt_count = 0, \ } /* how to get the thread information struct from C */ diff -Nru a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h --- a/include/asm-ia64/tlb.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/tlb.h Thu Oct 24 22:22:20 2002 @@ -53,9 +53,10 @@ typedef struct { struct mm_struct *mm; - unsigned int nr; /* == ~0U => fast mode */ - unsigned int fullmm; /* non-zero means full mm flush */ - unsigned long freed; /* number of pages freed */ + unsigned int nr; /* == ~0U => fast mode */ + unsigned char fullmm; /* non-zero means full mm flush */ + unsigned char need_flush; /* really unmapped some PTEs? */ + unsigned long freed; /* number of pages freed */ unsigned long start_addr; unsigned long end_addr; struct page *pages[FREE_PTE_NR]; @@ -73,6 +74,10 @@ { unsigned int nr; + if (!tlb->need_flush) + return; + tlb->need_flush = 0; + if (tlb->fullmm) { /* * Tearing down the entire address space. This happens both as a result @@ -168,18 +173,6 @@ } /* - * Remove TLB entry for PTE mapped at virtual address ADDRESS. This is called for any - * PTE, not just those pointing to (normal) physical memory. - */ -static inline void -__tlb_remove_tlb_entry (mmu_gather_t *tlb, pte_t *ptep, unsigned long address) -{ - if (tlb->start_addr == ~0UL) - tlb->start_addr = address; - tlb->end_addr = address + PAGE_SIZE; -} - -/* * Logically, this routine frees PAGE. On MP machines, the actual freeing of the page * must be delayed until after the TLB has been flushed (see comments at the beginning of * this file). @@ -187,6 +180,8 @@ static inline void tlb_remove_page (mmu_gather_t *tlb, struct page *page) { + tlb->need_flush = 1; + if (tlb_fast_mode(tlb)) { free_page_and_swap_cache(page); return; @@ -196,11 +191,37 @@ ia64_tlb_flush_mmu(tlb, tlb->start_addr, tlb->end_addr); } +/* + * Remove TLB entry for PTE mapped at virtual address ADDRESS. This is called for any + * PTE, not just those pointing to (normal) physical memory. + */ +static inline void +__tlb_remove_tlb_entry (mmu_gather_t *tlb, pte_t *ptep, unsigned long address) +{ + if (tlb->start_addr == ~0UL) + tlb->start_addr = address; + tlb->end_addr = address + PAGE_SIZE; +} + #define tlb_start_vma(tlb, vma) do { } while (0) #define tlb_end_vma(tlb, vma) do { } while (0) -#define tlb_remove_tlb_entry(tlb, ptep, addr) __tlb_remove_tlb_entry(tlb, ptep, addr) -#define pte_free_tlb(tlb, ptep) __pte_free_tlb(tlb, ptep) -#define pmd_free_tlb(tlb, ptep) __pmd_free_tlb(tlb, ptep) +#define tlb_remove_tlb_entry(tlb, ptep, addr) \ +do { \ + tlb->need_flush = 1; \ + __tlb_remove_tlb_entry(tlb, ptep, addr); \ +} while (0) + +#define pte_free_tlb(tlb, ptep) \ +do { \ + tlb->need_flush = 1; \ + __pte_free_tlb(tlb, ptep); \ +} while (0) + +#define pmd_free_tlb(tlb, ptep) \ +do { \ + tlb->need_flush = 1; \ + __pmd_free_tlb(tlb, ptep); \ +} while (0) #endif /* _ASM_IA64_TLB_H */ diff -Nru a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h --- a/include/asm-ia64/topology.h Thu Oct 24 22:22:20 2002 +++ b/include/asm-ia64/topology.h Thu Oct 24 22:22:20 2002 @@ -1,6 +1,79 @@ +/* + * linux/include/asm-ia64/topology.h + * + * Copyright (C) 2002, Erich Focht, NEC + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ #ifndef _ASM_IA64_TOPOLOGY_H #define _ASM_IA64_TOPOLOGY_H -#include +#include +#include + +/* Returns the number of the node containing CPU 'cpu' */ +#ifdef CONFIG_NUMA +#define __cpu_to_node(cpu) cpu_to_node_map[cpu] +#else +#define __cpu_to_node(cpu) (0) +#endif + +/* + * Returns the number of the node containing MemBlk 'memblk' + */ +#ifdef CONFIG_ACPI_NUMA +#define __memblk_to_node(memblk) (node_memblk[memblk].nid) +#else +#define __memblk_to_node(memblk) (memblk) +#endif + +/* + * Returns the number of the node containing Node 'nid'. + * Not implemented here. Multi-level hierarchies detected with + * the help of node_distance(). + */ +#define __parent_node(nid) (nid) + +/* + * Returns the number of the first CPU on Node 'node'. + * Slow in the current implementation. + * Who needs this? + */ +/* #define __node_to_first_cpu(node) pool_cpus[pool_ptr[node]] */ +static inline int __node_to_first_cpu(int node) +{ + int i; + + for (i=0; i + extern void setup_serial_acpi(void *); #define ACPI_SIG_LEN 4 diff -Nru a/include/linux/hcdp_serial.h b/include/linux/hcdp_serial.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/hcdp_serial.h Thu Oct 24 22:22:20 2002 @@ -0,0 +1,83 @@ +/* + * linux/include/linux/hcdp_serial.h + * + * Copyright (C) 2002 Hewlett-Packard Co. + * Khalid Aziz + * + * Definitions for HCDP defined serial ports (Serial console and debug + * ports) + */ +#ifndef _LINUX_HCDP_SERIAL_H +#define _LINUX_HCDP_SERIAL_H + +/* ACPI table signatures */ +#define HCDP_SIG_LEN 4 +#define HCDP_SIGNATURE "HCDP" + +/* Space ID as defined in ACPI generic address structure */ +#define ACPI_MEM_SPACE 0 +#define ACPI_IO_SPACE 1 +#define ACPI_PCICONF_SPACE 2 + +/* + * Maximum number of HCDP devices we want to read in + */ +#define MAX_HCDP_DEVICES 6 + +/* + * Default UART clock rate if clock rate is 0 in HCDP table. + */ +#define DEFAULT_UARTCLK 115200 + +/* + * ACPI Generic Address Structure + */ +typedef struct { + u8 space_id; + u8 bit_width; + u8 bit_offset; + u8 resv; + u32 addrlo; + u32 addrhi; +} acpi_gen_addr; + +/* HCDP Device descriptor entry types */ +#define HCDP_DEV_CONSOLE 0 +#define HCDP_DEV_DEBUG 1 + +/* HCDP Device descriptor type */ +typedef struct { + u8 type; + u8 bits; + u8 parity; + u8 stop_bits; + u8 pci_seg; + u8 pci_bus; + u8 pci_dev; + u8 pci_func; + u64 baud; + acpi_gen_addr base_addr; + u16 pci_dev_id; + u16 pci_vendor_id; + u32 global_int; + u32 clock_rate; + u8 pci_prog_intfc; + u8 resv; +} hcdp_dev_t; + +/* HCDP Table format */ +typedef struct { + u8 signature[4]; + u32 len; + u8 rev; + u8 chksum; + u8 oemid[6]; + u8 oem_tabid[8]; + u32 oem_rev; + u8 creator_id[4]; + u32 creator_rev; + u32 num_entries; + hcdp_dev_t hcdp_dev[MAX_HCDP_DEVICES]; +} hcdp_t; + +#endif /* _LINUX_HCDP_SERIAL_H */ diff -Nru a/include/linux/highmem.h b/include/linux/highmem.h --- a/include/linux/highmem.h Thu Oct 24 22:22:20 2002 +++ b/include/linux/highmem.h Thu Oct 24 22:22:20 2002 @@ -3,6 +3,8 @@ #include #include +#include + #include #ifdef CONFIG_HIGHMEM diff -Nru a/include/linux/irq.h b/include/linux/irq.h --- a/include/linux/irq.h Thu Oct 24 22:22:20 2002 +++ b/include/linux/irq.h Thu Oct 24 22:22:20 2002 @@ -56,15 +56,13 @@ * * Pad this out to 32 bytes for cache and indexing reasons. */ -typedef struct { +typedef struct irq_desc { unsigned int status; /* IRQ status */ hw_irq_controller *handler; struct irqaction *action; /* IRQ action list */ unsigned int depth; /* nested irq disables */ spinlock_t lock; } ____cacheline_aligned irq_desc_t; - -extern irq_desc_t irq_desc [NR_IRQS]; #include /* the arch dependent stuff */ diff -Nru a/include/linux/irq_cpustat.h b/include/linux/irq_cpustat.h --- a/include/linux/irq_cpustat.h Thu Oct 24 22:22:20 2002 +++ b/include/linux/irq_cpustat.h Thu Oct 24 22:22:20 2002 @@ -24,7 +24,7 @@ #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) #else #define __IRQ_STAT(cpu, member) ((void)(cpu), irq_stat[0].member) -#endif +#endif #endif /* arch independent irq_stat fields */ @@ -33,5 +33,10 @@ #define ksoftirqd_task(cpu) __IRQ_STAT((cpu), __ksoftirqd_task) /* arch dependent irq_stat fields */ #define nmi_count(cpu) __IRQ_STAT((cpu), __nmi_count) /* i386, ia64 */ + +#define local_softirq_pending() softirq_pending(smp_processor_id()) +#define local_syscall_count() syscall_count(smp_processor_id()) +#define local_ksoftirqd_task() ksoftirqd_task(smp_processor_id()) +#define local_nmi_count() nmi_count(smp_processor_id()) #endif /* __irq_cpustat_h */ diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h --- a/include/linux/kernel.h Thu Oct 24 22:22:20 2002 +++ b/include/linux/kernel.h Thu Oct 24 22:22:20 2002 @@ -38,6 +38,13 @@ #define KERN_INFO "<6>" /* informational */ #define KERN_DEBUG "<7>" /* debug-level messages */ +extern int console_printk[]; + +#define console_loglevel (console_printk[0]) +#define default_message_loglevel (console_printk[1]) +#define minimum_console_loglevel (console_printk[2]) +#define default_console_loglevel (console_printk[3]) + struct completion; #ifdef CONFIG_DEBUG_KERNEL @@ -80,8 +87,6 @@ asmlinkage int printk(const char * fmt, ...) __attribute__ ((format (printf, 1, 2))); - -extern int console_loglevel; static inline void console_silent(void) { diff -Nru a/include/linux/module.h b/include/linux/module.h --- a/include/linux/module.h Thu Oct 24 22:22:20 2002 +++ b/include/linux/module.h Thu Oct 24 22:22:20 2002 @@ -311,7 +311,7 @@ */ #define MODULE_GENERIC_TABLE(gtype,name) \ static const struct gtype##_id * __module_##gtype##_table \ - __attribute__ ((unused, __section__(".data.exit"))) = name + __attribute__ ((unused, __section__(".exit.data"))) = name #ifndef __GENKSYMS__ diff -Nru a/include/linux/percpu.h b/include/linux/percpu.h --- a/include/linux/percpu.h Thu Oct 24 22:22:20 2002 +++ b/include/linux/percpu.h Thu Oct 24 22:22:20 2002 @@ -1,8 +1,7 @@ #ifndef __LINUX_PERCPU_H #define __LINUX_PERCPU_H -#include /* For preempt_disable() */ +#include /* For preempt_disable() */ #include - /* Must be an lvalue. */ #define get_cpu_var(var) (*({ preempt_disable(); &__get_cpu_var(var); })) #define put_cpu_var(var) preempt_enable() diff -Nru a/include/linux/ptrace.h b/include/linux/ptrace.h --- a/include/linux/ptrace.h Thu Oct 24 22:22:20 2002 +++ b/include/linux/ptrace.h Thu Oct 24 22:22:20 2002 @@ -4,6 +4,7 @@ /* structs and defines to help the user use the ptrace system call. */ #include +#include /* has the defines to get at the registers. */ diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h Thu Oct 24 22:22:20 2002 +++ b/include/linux/sched.h Thu Oct 24 22:22:20 2002 @@ -144,8 +144,8 @@ extern void init_idle(task_t *idle, int cpu); extern void show_state(void); -extern void show_trace(unsigned long *stack); -extern void show_stack(unsigned long *stack); +extern void show_trace(struct task_struct *); +extern void show_stack(struct task_struct *); extern void show_regs(struct pt_regs *); @@ -458,14 +458,14 @@ #ifndef INIT_THREAD_SIZE # define INIT_THREAD_SIZE 2048*sizeof(long) -#endif - union thread_union { struct thread_info thread_info; unsigned long stack[INIT_THREAD_SIZE/sizeof(long)]; }; extern union thread_union init_thread_union; +#endif + extern struct task_struct init_task; extern struct mm_struct init_mm; diff -Nru a/include/linux/serial.h b/include/linux/serial.h --- a/include/linux/serial.h Thu Oct 24 22:22:20 2002 +++ b/include/linux/serial.h Thu Oct 24 22:22:20 2002 @@ -178,14 +178,18 @@ extern int register_serial(struct serial_struct *req); extern void unregister_serial(int line); -/* Allow complicated architectures to specify rs_table[] at run time */ -extern int early_serial_setup(struct serial_struct *req); +/* Allow architectures to override entries in serial8250_ports[] at run time: */ +struct uart_port; /* forward declaration */ +extern int early_register_port(struct uart_port *port); #ifdef CONFIG_ACPI /* tty ports reserved for the ACPI serial console port and debug port */ -#define ACPI_SERIAL_CONSOLE_PORT 4 +#define ACPI_SERIAL_CONSOLE_PORT 0 #define ACPI_SERIAL_DEBUG_PORT 5 #endif + +/* tty port reserved for the HCDP serial console port */ +#define HCDP_SERIAL_CONSOLE_PORT 4 #endif /* __KERNEL__ */ #endif /* _LINUX_SERIAL_H */ diff -Nru a/include/linux/smp.h b/include/linux/smp.h --- a/include/linux/smp.h Thu Oct 24 22:22:20 2002 +++ b/include/linux/smp.h Thu Oct 24 22:22:20 2002 @@ -57,10 +57,6 @@ */ extern int smp_threads_ready; -extern volatile unsigned long smp_msg_data; -extern volatile int smp_src_cpu; -extern volatile int smp_msg_id; - #define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */ #define MSG_ALL 0x8001 @@ -94,8 +90,6 @@ #define cpu_online(cpu) ({ BUG_ON((cpu) != 0); 1; }) #define num_online_cpus() 1 #define num_booting_cpus() 1 -#define cpu_possible(cpu) ({ BUG_ON((cpu) != 0); 1; }) - struct notifier_block; /* Need to know about CPUs going up/down? */ diff -Nru a/kernel/exec_domain.c b/kernel/exec_domain.c --- a/kernel/exec_domain.c Thu Oct 24 22:22:20 2002 +++ b/kernel/exec_domain.c Thu Oct 24 22:22:20 2002 @@ -196,8 +196,10 @@ put_exec_domain(oep); +#if 0 printk(KERN_DEBUG "[%s:%d]: set personality to %lx\n", current->comm, current->pid, personality); +#endif return 0; } diff -Nru a/kernel/fork.c b/kernel/fork.c --- a/kernel/fork.c Thu Oct 24 22:22:20 2002 +++ b/kernel/fork.c Thu Oct 24 22:22:20 2002 @@ -49,6 +49,7 @@ rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED; /* outer */ +#if 0 /* * A per-CPU task cache - this relies on the fact that * the very last portion of sys_exit() is executed with @@ -73,6 +74,7 @@ put_cpu(); } } +#endif void add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait) { @@ -175,7 +177,11 @@ init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2; } -static struct task_struct *dup_task_struct(struct task_struct *orig) +#if 1 +extern struct task_struct *dup_task_struct (struct task_struct *orig); +#else + +struct task_struct *dup_task_struct(struct task_struct *orig) { struct task_struct *tsk; struct thread_info *ti; @@ -204,6 +210,8 @@ atomic_set(&tsk->usage,1); return tsk; } + +#endif static inline int dup_mmap(struct mm_struct * mm) { diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c --- a/kernel/ksyms.c Thu Oct 24 22:22:20 2002 +++ b/kernel/ksyms.c Thu Oct 24 22:22:20 2002 @@ -399,7 +399,9 @@ EXPORT_SYMBOL(del_timer); EXPORT_SYMBOL(request_irq); EXPORT_SYMBOL(free_irq); +#if !defined(CONFIG_IA64) EXPORT_SYMBOL(irq_stat); +#endif /* waitqueue handling */ EXPORT_SYMBOL(add_wait_queue); @@ -590,7 +592,9 @@ /* init task, for moving kthread roots - ought to export a function ?? */ EXPORT_SYMBOL(init_task); +#ifndef CONFIG_IA64 EXPORT_SYMBOL(init_thread_union); +#endif EXPORT_SYMBOL(tasklist_lock); EXPORT_SYMBOL(find_task_by_pid); diff -Nru a/kernel/printk.c b/kernel/printk.c --- a/kernel/printk.c Thu Oct 24 22:22:20 2002 +++ b/kernel/printk.c Thu Oct 24 22:22:20 2002 @@ -16,6 +16,7 @@ * 01Mar01 Andrew Morton */ +#include #include #include #include @@ -55,11 +56,12 @@ DECLARE_WAIT_QUEUE_HEAD(log_wait); -/* Keep together for sysctl support */ -int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL; -int default_message_loglevel = DEFAULT_MESSAGE_LOGLEVEL; -int minimum_console_loglevel = MINIMUM_CONSOLE_LOGLEVEL; -int default_console_loglevel = DEFAULT_CONSOLE_LOGLEVEL; +int console_printk[4] = { + DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ + DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ + MINIMUM_CONSOLE_LOGLEVEL, /* minimum_console_loglevel */ + DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */ +}; int oops_in_progress; @@ -341,6 +343,12 @@ __call_console_drivers(start, end); } } +#ifdef CONFIG_IA64_EARLY_PRINTK + if (!console_drivers) { + static void early_printk (const char *str, size_t len); + early_printk(&LOG_BUF(start), end - start); + } +#endif } /* @@ -707,3 +715,110 @@ tty->driver.write(tty, 0, msg, strlen(msg)); return; } + +#ifdef CONFIG_IA64_EARLY_PRINTK + +#include + +# ifdef CONFIG_IA64_EARLY_PRINTK_VGA + + +#define VGABASE ((char *)0xc0000000000b8000) +#define VGALINES 24 +#define VGACOLS 80 + +static int current_ypos = VGALINES, current_xpos = 0; + +static void +early_printk_vga (const char *str, size_t len) +{ + char c; + int i, k, j; + + while (len-- > 0) { + c = *str++; + if (current_ypos >= VGALINES) { + /* scroll 1 line up */ + for (k = 1, j = 0; k < VGALINES; k++, j++) { + for (i = 0; i < VGACOLS; i++) { + writew(readw(VGABASE + 2*(VGACOLS*k + i)), + VGABASE + 2*(VGACOLS*j + i)); + } + } + for (i = 0; i < VGACOLS; i++) { + writew(0x720, VGABASE + 2*(VGACOLS*j + i)); + } + current_ypos = VGALINES-1; + } + if (c == '\n') { + current_xpos = 0; + current_ypos++; + } else if (c != '\r') { + writew(((0x7 << 8) | (unsigned short) c), + VGABASE + 2*(VGACOLS*current_ypos + current_xpos++)); + if (current_xpos >= VGACOLS) { + current_xpos = 0; + current_ypos++; + } + } + } +} + +# endif /* CONFIG_IA64_EARLY_PRINTK_VGA */ + +# ifdef CONFIG_IA64_EARLY_PRINTK_UART + +#include +#include + +static void early_printk_uart(const char *str, size_t len) +{ + static char *uart = NULL; + unsigned long uart_base; + char c; + + if (!uart) { + uart_base = 0; +# ifdef CONFIG_SERIAL_8250_HCDP + { + extern unsigned long hcdp_early_uart(void); + uart_base = hcdp_early_uart(); + } +# endif +# if CONFIG_IA64_EARLY_PRINTK_UART_BASE + if (!uart_base) + uart_base = CONFIG_IA64_EARLY_PRINTK_UART_BASE; +# endif + if (!uart_base) + return; + + uart = ioremap(uart_base, 64); + if (!uart) + return; + } + + while (len-- > 0) { + c = *str++; + while ((readb(uart + UART_LSR) & UART_LSR_TEMT) == 0) + cpu_relax(); /* spin */ + + writeb(c, uart + UART_TX); + + if (c == '\n') + writeb('\r', uart + UART_TX); + } +} + +# endif /* CONFIG_IA64_EARLY_PRINTK_UART */ + +void early_printk(const char *str, size_t len) +{ +#ifdef CONFIG_IA64_EARLY_PRINTK_UART + early_printk_uart(str, len); +#endif +#ifdef CONFIG_IA64_EARLY_PRINTK_VGA + early_printk_vga(str, len); +#endif +} + +#endif /* CONFIG_IA64_EARLY_PRINTK */ diff -Nru a/kernel/softirq.c b/kernel/softirq.c --- a/kernel/softirq.c Thu Oct 24 22:22:20 2002 +++ b/kernel/softirq.c Thu Oct 24 22:22:20 2002 @@ -31,7 +31,10 @@ - Tasklets: serialized wrt itself. */ +/* No separate irq_stat for ia64, it is part of PSA */ +#if !defined(CONFIG_IA64) irq_cpustat_t irq_stat[NR_CPUS] ____cacheline_aligned; +#endif /* CONFIG_IA64 */ static struct softirq_action softirq_vec[32] __cacheline_aligned_in_smp; @@ -62,7 +65,7 @@ local_irq_save(flags); cpu = smp_processor_id(); - pending = softirq_pending(cpu); + pending = local_softirq_pending(); if (pending) { struct softirq_action *h; @@ -71,7 +74,7 @@ local_bh_disable(); restart: /* Reset the pending bitmask before enabling irqs */ - softirq_pending(cpu) = 0; + local_softirq_pending() = 0; local_irq_enable(); @@ -86,7 +89,7 @@ local_irq_disable(); - pending = softirq_pending(cpu); + pending = local_softirq_pending(); if (pending & mask) { mask &= ~pending; goto restart; @@ -94,7 +97,7 @@ __local_bh_enable(); if (pending) - wakeup_softirqd(cpu); + wakeup_softirqd(smp_processor_id()); } local_irq_restore(flags); @@ -285,15 +288,15 @@ __set_current_state(TASK_INTERRUPTIBLE); mb(); - ksoftirqd_task(cpu) = current; + local_ksoftirqd_task() = current; for (;;) { - if (!softirq_pending(cpu)) + if (!local_softirq_pending()) schedule(); __set_current_state(TASK_RUNNING); - while (softirq_pending(cpu)) { + while (local_softirq_pending()) { do_softirq(); cond_resched(); } diff -Nru a/mm/bootmem.c b/mm/bootmem.c --- a/mm/bootmem.c Thu Oct 24 22:22:20 2002 +++ b/mm/bootmem.c Thu Oct 24 22:22:20 2002 @@ -143,6 +143,7 @@ static void * __init __alloc_bootmem_core (bootmem_data_t *bdata, unsigned long size, unsigned long align, unsigned long goal) { + static unsigned long last_success; unsigned long i, start = 0; void *ret; unsigned long offset, remaining_size; @@ -168,6 +169,9 @@ if (goal && (goal >= bdata->node_boot_start) && ((goal >> PAGE_SHIFT) < bdata->node_low_pfn)) { preferred = goal - bdata->node_boot_start; + + if (last_success >= preferred) + preferred = last_success; } else preferred = 0; @@ -179,6 +183,8 @@ restart_scan: for (i = preferred; i < eidx; i += incr) { unsigned long j; + i = find_next_zero_bit((char *)bdata->node_bootmem_map, eidx, i); + i = (i + incr - 1) & -incr; if (test_bit(i, bdata->node_bootmem_map)) continue; for (j = i + 1; j < i + areasize; ++j) { @@ -197,6 +203,7 @@ } return NULL; found: + last_success = start << PAGE_SHIFT; if (start >= eidx) BUG(); @@ -256,21 +263,21 @@ map = bdata->node_bootmem_map; for (i = 0; i < idx; ) { unsigned long v = ~map[i / BITS_PER_LONG]; - if (v) { + if (v) { unsigned long m; - for (m = 1; m && i < idx; m<<=1, page++, i++) { + for (m = 1; m && i < idx; m<<=1, page++, i++) { if (v & m) { - count++; - ClearPageReserved(page); - set_page_count(page, 1); - __free_page(page); - } - } + count++; + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); + } + } } else { i+=BITS_PER_LONG; - page+=BITS_PER_LONG; - } - } + page+=BITS_PER_LONG; + } + } total += count; /* diff -Nru a/mm/memory.c b/mm/memory.c --- a/mm/memory.c Thu Oct 24 22:22:20 2002 +++ b/mm/memory.c Thu Oct 24 22:22:20 2002 @@ -112,7 +112,7 @@ pmd = pmd_offset(dir, 0); pgd_clear(dir); for (j = 0; j < PTRS_PER_PMD ; j++) { - prefetchw(pmd+j+(PREFETCH_STRIDE/16)); + prefetchw(pmd + j + PREFETCH_STRIDE/sizeof(*pmd)); free_one_pmd(tlb, pmd+j); } pmd_free_tlb(tlb, pmd); diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c --- a/net/ipv4/raw.c Thu Oct 24 22:22:20 2002 +++ b/net/ipv4/raw.c Thu Oct 24 22:22:20 2002 @@ -65,6 +65,7 @@ #include #include #include +#include struct sock *raw_v4_htable[RAWV4_HTABLE_SIZE]; rwlock_t raw_v4_lock = RW_LOCK_UNLOCKED; diff -Nru a/sound/oss/cs4281/cs4281m.c b/sound/oss/cs4281/cs4281m.c --- a/sound/oss/cs4281/cs4281m.c Thu Oct 24 22:22:20 2002 +++ b/sound/oss/cs4281/cs4281m.c Thu Oct 24 22:22:20 2002 @@ -1942,8 +1942,8 @@ len -= x; } CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO - "cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n", - (unsigned)c, (unsigned)((char *) buf) + bptr, len)); + "cs4281: clear_advance(): memset %d at %p for %d size \n", + (unsigned)c, ((char *) buf) + bptr, len)); memset(((char *) buf) + bptr, c, len); } @@ -1978,9 +1978,8 @@ wake_up(&s->dma_adc.wait); } CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO - "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", - (unsigned)s, s->dma_adc.hwptr, - s->dma_adc.total_bytes, s->dma_adc.count)); + "cs4281: cs4281_update_ptr(): s=%p hwptr=%d total_bytes=%d count=%d \n", + s, s->dma_adc.hwptr, s->dma_adc.total_bytes, s->dma_adc.count)); } // update DAC pointer // @@ -2012,11 +2011,10 @@ // Continue to play silence until the _release. // CS_DBGOUT(CS_WAVE_WRITE, 6, printk(KERN_INFO - "cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n", + "cs4281: cs4281_update_ptr(): memset %d at %p for %d size \n", (unsigned)(s->prop_dac.fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, - (unsigned)s->dma_dac.rawbuf, - s->dma_dac.dmasize)); + s->dma_dac.rawbuf, s->dma_dac.dmasize)); memset(s->dma_dac.rawbuf, (s->prop_dac. fmt & (AFMT_U8 | AFMT_U16_LE)) ? @@ -2047,9 +2045,8 @@ } } CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO - "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", - (unsigned) s, s->dma_dac.hwptr, - s->dma_dac.total_bytes, s->dma_dac.count)); + "cs4281: cs4281_update_ptr(): s=%p hwptr=%d total_bytes=%d count=%d \n", + s, s->dma_dac.hwptr, s->dma_dac.total_bytes, s->dma_dac.count)); } } @@ -2180,8 +2177,7 @@ VALIDATE_STATE(s); CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO - "cs4281: mixer_ioctl(): s=0x%.8x cmd=0x%.8x\n", - (unsigned) s, cmd)); + "cs4281: mixer_ioctl(): s=%p cmd=0x%.8x\n", s, cmd)); #if CSDEBUG cs_printioctl(cmd); #endif @@ -2746,9 +2742,8 @@ CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: CopySamples()+ ")); CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO - " dst=0x%x src=0x%x count=%d iChannels=%d fmt=0x%x\n", - (unsigned) dst, (unsigned) src, (unsigned) count, - (unsigned) iChannels, (unsigned) fmt)); + " dst=%p src=%p count=%d iChannels=%d fmt=0x%x\n", + dst, src, (unsigned) count, (unsigned) iChannels, (unsigned) fmt)); // Gershwin does format conversion in hardware so normally // we don't do any host based coversion. The data formatter @@ -2828,9 +2823,9 @@ void *src = hwsrc; //default to the standard destination buffer addr CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO - "cs_copy_to_user()+ fmt=0x%x fmt_o=0x%x cnt=%d dest=0x%.8x\n", + "cs_copy_to_user()+ fmt=0x%x fmt_o=0x%x cnt=%d dest=%p\n", s->prop_adc.fmt, s->prop_adc.fmt_original, - (unsigned) cnt, (unsigned) dest)); + (unsigned) cnt, dest)); if (cnt > s->dma_adc.dmasize) { cnt = s->dma_adc.dmasize; @@ -2875,7 +2870,7 @@ unsigned copied = 0; CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, - printk(KERN_INFO "cs4281: cs4281_read()+ %d \n", count)); + printk(KERN_INFO "cs4281: cs4281_read()+ %Zu \n", count)); VALIDATE_STATE(s); if (ppos != &file->f_pos) @@ -2898,7 +2893,7 @@ // while (count > 0) { CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO - "_read() count>0 count=%d .count=%d .swptr=%d .hwptr=%d \n", + "_read() count>0 count=%Zu .count=%d .swptr=%d .hwptr=%d \n", count, s->dma_adc.count, s->dma_adc.swptr, s->dma_adc.hwptr)); spin_lock_irqsave(&s->lock, flags); @@ -2955,11 +2950,10 @@ // the "cnt" is the number of bytes to read. CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO - "_read() copy_to cnt=%d count=%d ", cnt, count)); + "_read() copy_to cnt=%d count=%Zu ", cnt, count)); CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO - " .dmasize=%d .count=%d buffer=0x%.8x ret=%d\n", - s->dma_adc.dmasize, s->dma_adc.count, - (unsigned) buffer, ret)); + " .dmasize=%d .count=%d buffer=%p ret=%Zd\n", + s->dma_adc.dmasize, s->dma_adc.count, buffer, ret)); if (cs_copy_to_user (s, buffer, s->dma_adc.rawbuf + swptr, cnt, &copied)) @@ -2975,7 +2969,7 @@ start_adc(s); } CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, - printk(KERN_INFO "cs4281: cs4281_read()- %d\n", ret)); + printk(KERN_INFO "cs4281: cs4281_read()- %Zd\n", ret)); return ret; } @@ -2991,7 +2985,7 @@ int cnt; CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, - printk(KERN_INFO "cs4281: cs4281_write()+ count=%d\n", + printk(KERN_INFO "cs4281: cs4281_write()+ count=%Zu\n", count)); VALIDATE_STATE(s); @@ -3047,7 +3041,7 @@ start_dac(s); } CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, - printk(KERN_INFO "cs4281: cs4281_write()- %d\n", ret)); + printk(KERN_INFO "cs4281: cs4281_write()- %Zd\n", ret)); return ret; } @@ -3168,8 +3162,7 @@ int val, mapped, ret; CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO - "cs4281: cs4281_ioctl(): file=0x%.8x cmd=0x%.8x\n", - (unsigned) file, cmd)); + "cs4281: cs4281_ioctl(): file=%p cmd=0x%.8x\n", file, cmd)); #if CSDEBUG cs_printioctl(cmd); #endif @@ -3599,8 +3592,8 @@ (struct cs4281_state *) file->private_data; CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk(KERN_INFO - "cs4281: cs4281_release(): inode=0x%.8x file=0x%.8x f_mode=%d\n", - (unsigned) inode, (unsigned) file, file->f_mode)); + "cs4281: cs4281_release(): inode=%p file=%p f_mode=%d\n", + inode, file, file->f_mode)); VALIDATE_STATE(s); @@ -3634,8 +3627,8 @@ struct list_head *entry; CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO - "cs4281: cs4281_open(): inode=0x%.8x file=0x%.8x f_mode=0x%x\n", - (unsigned) inode, (unsigned) file, file->f_mode)); + "cs4281: cs4281_open(): inode=%p file=%p f_mode=0x%x\n", + inode, file, file->f_mode)); list_for_each(entry, &cs4281_devs) { @@ -4344,10 +4337,8 @@ CS_DBGOUT(CS_INIT, 2, printk(KERN_INFO - "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=0x%.8x pBA1=0x%.8x \n", - (unsigned) temp1, (unsigned) temp2, - (unsigned) s->pBA0, (unsigned) s->pBA1)); - + "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=%p pBA1=%p \n", + (unsigned) temp1, (unsigned) temp2, s->pBA0, s->pBA1)); CS_DBGOUT(CS_INIT, 2, printk(KERN_INFO "cs4281: probe() pBA0phys=0x%.8x pBA1phys=0x%.8x\n", @@ -4394,15 +4385,13 @@ if (pmdev) { CS_DBGOUT(CS_INIT | CS_PM, 4, printk(KERN_INFO - "cs4281: probe() pm_register() succeeded (0x%x).\n", - (unsigned)pmdev)); + "cs4281: probe() pm_register() succeeded (%p).\n", pmdev)); pmdev->data = s; } else { CS_DBGOUT(CS_INIT | CS_PM | CS_ERROR, 0, printk(KERN_INFO - "cs4281: probe() pm_register() failed (0x%x).\n", - (unsigned)pmdev)); + "cs4281: probe() pm_register() failed (%p).\n", pmdev)); s->pm.flags |= CS4281_PM_NOT_REGISTERED; } #endif diff -Nru a/sound/oss/cs4281/cs4281pm-24.c b/sound/oss/cs4281/cs4281pm-24.c --- a/sound/oss/cs4281/cs4281pm-24.c Thu Oct 24 22:22:20 2002 +++ b/sound/oss/cs4281/cs4281pm-24.c Thu Oct 24 22:22:20 2002 @@ -38,16 +38,16 @@ #define CS4281_SUSPEND_TBL cs4281_suspend_tbl #define CS4281_RESUME_TBL cs4281_resume_tbl */ -#define CS4281_SUSPEND_TBL cs4281_null -#define CS4281_RESUME_TBL cs4281_null +#define CS4281_SUSPEND_TBL (int (*) (struct pci_dev *, u32)) cs4281_null +#define CS4281_RESUME_TBL (int (*) (struct pci_dev *)) cs4281_null int cs4281_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) { struct cs4281_state *state; CS_DBGOUT(CS_PM, 2, printk(KERN_INFO - "cs4281: cs4281_pm_callback dev=0x%x rqst=0x%x state=%d\n", - (unsigned)dev,(unsigned)rqst,(unsigned)data)); + "cs4281: cs4281_pm_callback dev=%p rqst=0x%x state=%p\n", + dev,(unsigned)rqst,data)); state = (struct cs4281_state *) dev->data; if (state) { switch(rqst) { @@ -78,7 +78,7 @@ } #else /* CS4281_PM */ -#define CS4281_SUSPEND_TBL cs4281_null -#define CS4281_RESUME_TBL cs4281_null +#define CS4281_SUSPEND_TBL (int (*) (struct pci_dev *, u32)) cs4281_null +#define CS4281_RESUME_TBL (int (*) (struct pci_dev *)) cs4281_null #endif /* CS4281_PM */