diff -Nru a/Documentation/filesystems/jfs.txt b/Documentation/filesystems/jfs.txt --- a/Documentation/filesystems/jfs.txt Fri Oct 17 14:43:50 2003 +++ b/Documentation/filesystems/jfs.txt Fri Oct 17 14:43:50 2003 @@ -32,6 +32,10 @@ option to remount a volume where the nointegrity option was previously specified in order to restore normal behavior. +errors=continue Keep going on a filesystem error. +errors=remount-ro Default. Remount the filesystem read-only on an error. +errors=panic Panic and halt the machine if an error occurs. + JFS TODO list: Plans for our near term development items diff -Nru a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt --- a/Documentation/filesystems/xfs.txt Fri Oct 17 14:43:50 2003 +++ b/Documentation/filesystems/xfs.txt Fri Oct 17 14:43:50 2003 @@ -29,6 +29,11 @@ The preferred buffered I/O size can also be altered on an individual file basis using the ioctl(2) system call. + ikeep + When inode clusters are emptied of inodes, keep them around + on the disk, this is the old XFS behavior. Default is now to + return the inode cluster to the free space pool. + logbufs=value Set the number of in-memory log buffers. Valid numbers range from 2-8 inclusive. diff -Nru a/Documentation/ia64/fsys.txt b/Documentation/ia64/fsys.txt --- a/Documentation/ia64/fsys.txt Fri Oct 17 14:43:50 2003 +++ b/Documentation/ia64/fsys.txt Fri Oct 17 14:43:50 2003 @@ -4,7 +4,7 @@ ----------------------------------- Started: 13-Jan-2003 - Last update: 11-Feb-2003 + Last update: 27-Sep-2003 David Mosberger-Tang @@ -146,6 +146,12 @@ task pointer is not considered sensitive: it's already exposed through ar.k6). + o Fsyscall-handlers MUST NOT access user-memory without first + validating access-permission (this can be done typically via + probe.r.fault and/or probe.w.fault) and without guarding against + memory access exceptions (this can be done with the EX() macros + defined by asmmacro.h). + The above restrictions may seem draconian, but remember that it's possible to trade off some of the restrictions by paying a slightly higher overhead. For example, if an fsyscall-handler could benefit @@ -229,3 +235,52 @@ PSR.bn Unchanged. Note: fsys-mode handlers may clear the bit, if needed. Doing so requires clearing PSR.i and PSR.ic as well. PSR.ia Unchanged. Note: the ia64 linux kernel never sets this bit. + +* Using fast system calls + +To use fast system calls, userspace applications need simply call +__kernel_syscall_via_epc(). For example + +-- example fgettimeofday() call -- +-- fgettimeofday.S -- + +#include + +GLOBAL_ENTRY(fgettimeofday) +.prologue +.save ar.pfs, r11 +mov r11 = ar.pfs +.body + +mov r2 = 0xa000000000020660;; // gate address + // found by inspection of System.map for the + // __kernel_syscall_via_epc() function. See + // below for how to do this for real. + +mov b7 = r2 +mov r15 = 1087 // gettimeofday syscall +;; +br.call.sptk.many b6 = b7 +;; + +.restore sp + +mov ar.pfs = r11 +br.ret.sptk.many rp;; // return to caller +END(fgettimeofday) + +-- end fgettimeofday.S -- + +In reality, getting the gate address is accomplished by two extra +values passed via the ELF auxiliary vector (include/asm-ia64/elf.h) + + o AT_SYSINFO : is the address of __kernel_syscall_via_epc() + o AT_SYSINFO_EHDR : is the address of the kernel gate ELF DSO + +The ELF DSO is a pre-linked library that is mapped in by the kernel at +the gate page. It is a proper ELF shared object so, with a dynamic +loader that recognises the library, you should be able to make calls to +the exported functions within it as with any other shared library. +AT_SYSINFO points into the kernel DSO at the +__kernel_syscall_via_epc() function for historical reasons (it was +used before the kernel DSO) and as a convenience. diff -Nru a/Documentation/ide.txt b/Documentation/ide.txt --- a/Documentation/ide.txt Fri Oct 17 14:43:50 2003 +++ b/Documentation/ide.txt Fri Oct 17 14:43:50 2003 @@ -242,9 +242,6 @@ and quite likely to cause trouble with older/odd IDE drives. - "hdx=biostimings" : driver will NOT attempt to tune interface speed - (DMA/PIO) but always honour BIOS timings. - "hdx=slow" : insert a huge pause after each access to the data port. Should be used only as a last resort. @@ -293,9 +290,6 @@ This is the default for most chipsets, except the cmd640. - "idex=biostimings" : driver will NOT attempt to tune interface speed - (DMA/PIO) but always honour BIOS timings. - "idex=serialize" : do not overlap operations on idex. Please note that you will have to specify this option for both the respecitve primary and secondary channel diff -Nru a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt --- a/Documentation/x86_64/boot-options.txt Fri Oct 17 14:43:51 2003 +++ b/Documentation/x86_64/boot-options.txt Fri Oct 17 14:43:51 2003 @@ -20,18 +20,15 @@ APICs - nolocalapic Don't use a local or IO-APIC. This should only - be needed if you have a buggy BIOS. The newer - kernels already turn it off by default if the - BIOS didn't enable the local APIC, so it will - be hopefully not needed. - Note this code path is not very well tested, you are on - your own. - apic Use IO-APIC. Default + Unless you have an NVidia or VIA/Uniprocessor board. + Then it defaults to off. noapic Don't use the IO-APIC. - Also only lightly tested. + + disableapic Don't use the local APIC + + nolapic Don't use the local APIC (alias for i386 compatibility) pirq=... See Documentation/i386/IO-APIC.txt @@ -60,13 +57,16 @@ Report when timer interrupts are lost because some code turned off interrupts for too long. - nmi_watchdog=NUMBER + nmi_watchdog=NUMBER[,panic] NUMBER can be: 0 don't use an NMI watchdog 1 use the IO-APIC timer for the NMI watchdog 2 use the local APIC for the NMI watchdog using a performance counter. Note This will use one performance counter and the local APIC's performance vector. + When panic is specified panic when an NMI watchdog timeout occurs. + This is useful when you use a panic=... timeout and need the box + quickly up again. Idle loop @@ -127,6 +127,9 @@ ACPI acpi=off Don't enable ACPI + acpi=ht Use ACPI boot table parsing, but don't enable ACPI + interpreter + acpi=force Force ACPI on (currently not needed) PCI diff -Nru a/Makefile b/Makefile --- a/Makefile Fri Oct 17 14:43:50 2003 +++ b/Makefile Fri Oct 17 14:43:50 2003 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = -test7 +EXTRAVERSION = -test8 # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile --- a/arch/arm/Makefile Fri Oct 17 14:43:50 2003 +++ b/arch/arm/Makefile Fri Oct 17 14:43:50 2003 @@ -149,16 +149,14 @@ bzImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/zImage -zImage Image bootpImage: vmlinux +zImage Image bootpImage uImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ zinstall install: vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ -MRPROPER_FILES += \ - include/asm-arm/arch include/asm-arm/.arch \ - include/asm-arm/constants.h* \ - include/asm-arm/mach-types.h +CLEAN_FILES += include/asm-arm/constants.h* include/asm-arm/mach-types.h +MRPROPER_FILES += include/asm-arm/arch include/asm-arm/.arch # We use MRPROPER_FILES and CLEAN_FILES now archclean: diff -Nru a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile --- a/arch/arm/boot/Makefile Fri Oct 17 14:43:50 2003 +++ b/arch/arm/boot/Makefile Fri Oct 17 14:43:50 2003 @@ -8,6 +8,8 @@ # Copyright (C) 1995-2002 Russell King # +MKIMAGE := $(srctree)/scripts/mkuboot.sh + # Note: the following conditions must always be true: # ZRELADDR == virt_to_phys(TEXTADDR) # PARAMS_PHYS must be with 4MB of ZRELADDR @@ -42,12 +44,14 @@ ifeq ($(CONFIG_ARCH_SA1100),y) zreladdr-$(CONFIG_SA1111) := 0xc0208000 endif +params_phys-$(CONFIG_ARCH_SA1100) := 0xc0000100 +initrd_phys-$(CONFIG_ARCH_SA1100) := 0xc0800000 zreladdr-$(CONFIG_ARCH_PXA) := 0xa0008000 zreladdr-$(CONFIG_ARCH_ANAKIN) := 0x20008000 zreladdr-$(CONFIG_ARCH_IOP3XX) := 0xa0008000 -params-phys-$(CONFIG_ARCH_IOP3XX) := 0xa0000100 +params_phys-$(CONFIG_ARCH_IOP3XX) := 0xa0000100 zreladdr-$(CONFIG_ARCH_ADIFCC) := 0xc0008000 -params-phys-$(CONFIG_ARCH_ADIFCC) := 0xc0000100 +params_phys-$(CONFIG_ARCH_ADIFCC) := 0xc0000100 ZRELADDR := $(zreladdr-y) ZTEXTADDR := $(ztextaddr-y) @@ -78,6 +82,16 @@ $(call if_changed,objcopy) @echo ' Kernel: $@ is ready' +quite_cmd_uimage = UIMAGE $@ + cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ + -C none -a $(ZRELADDR) -e $(ZRELADDR) \ + -n 'Linux-$(KERNELRELEASE)' -d $< $@ + +targets += uImage +$(obj)/uImage: $(obj)/zImage + $(call if_changed,uimage) + @echo ' Image $@ is ready' + $(obj)/bootpImage: $(obj)/bootp/bootp FORCE $(call if_changed,objcopy) @echo ' Kernel: $@ is ready' @@ -86,7 +100,7 @@ $(Q)$(MAKE) $(build)=$(obj)/compressed $@ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE - $(Q)$(MAKE) $(build)=$(obj)/compressed $@ + $(Q)$(MAKE) $(build)=$(obj)/bootp $@ .PHONY: initrd initrd: diff -Nru a/arch/arm/boot/bootp/bootp.lds b/arch/arm/boot/bootp/bootp.lds --- a/arch/arm/boot/bootp/bootp.lds Fri Oct 17 14:43:50 2003 +++ b/arch/arm/boot/bootp/bootp.lds Fri Oct 17 14:43:50 2003 @@ -16,10 +16,10 @@ .text : { _stext = .; *(.start) - kernel.o + arch/arm/boot/bootp/kernel.o . = ALIGN(32); initrd_start = .; - initrd.o + arch/arm/boot/bootp/initrd.o initrd_len = . - initrd_start; . = ALIGN(32); _etext = .; diff -Nru a/arch/arm/configs/lart_defconfig b/arch/arm/configs/lart_defconfig --- a/arch/arm/configs/lart_defconfig Fri Oct 17 14:43:50 2003 +++ b/arch/arm/configs/lart_defconfig Fri Oct 17 14:43:50 2003 @@ -2,76 +2,107 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set +CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y # # Loadable module support # CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set CONFIG_KMOD=y # # System Type # +# CONFIG_ARCH_ADIFCC is not set # CONFIG_ARCH_ANAKIN is not set -# CONFIG_ARCH_ARCA5K is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_RPC is not set CONFIG_ARCH_SA1100=y # CONFIG_ARCH_SHARK is not set # -# Archimedes/A5000 Implementations +# CLPS711X/EP721X Implementations # # -# Archimedes/A5000 Implementations (select only ONE) +# Epxa10db # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set # # Footbridge Implementations # -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set + +# +# IOP3xx Implementation Options +# +# CONFIG_ARCH_IOP310 is not set +# CONFIG_ARCH_IOP321 is not set + +# +# IOP3xx Chipset Features +# + +# +# Intel PXA250/210 Implementations +# # # SA11x0 Implementations # # CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set # CONFIG_SA1100_ADSBITSY is not set # CONFIG_SA1100_BRUTUS is not set # CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set # CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set # CONFIG_SA1100_EXTENEX1 is not set # CONFIG_SA1100_FLEXANET is not set # CONFIG_SA1100_FREEBIRD is not set # CONFIG_SA1100_GRAPHICSCLIENT is not set # CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set # CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HACKKIT is not set # CONFIG_SA1100_HUW_WEBPANEL is not set # CONFIG_SA1100_ITSY is not set CONFIG_SA1100_LART=y @@ -79,76 +110,72 @@ # CONFIG_SA1100_OMNIMETER is not set # CONFIG_SA1100_PANGOLIN is not set # CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set # CONFIG_SA1100_SHERMAN is not set # CONFIG_SA1100_SIMPAD is not set # CONFIG_SA1100_PFS168 is not set # CONFIG_SA1100_VICTOR is not set # CONFIG_SA1100_XP860 is not set # CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_STORK is not set +# CONFIG_SA1100_SSP is not set CONFIG_SA1100_USB=m CONFIG_SA1100_USB_NETLINK=m CONFIG_SA1100_USB_CHAR=m # -# CLPS711X/EP721X Implementations +# Processor Type # -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set +CONFIG_CPU_SA1100=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4=y +CONFIG_CPU_CACHE_V4WB=y +CONFIG_CPU_TLB_V4WB=y +CONFIG_CPU_MINICACHE=y # -# Processor Type +# Processor Features # -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_SA110 is not set -CONFIG_CPU_SA1100=y -CONFIG_DISCONTIGMEM=y -# CONFIG_CPU_BIG_ENDIAN is not set # # General setup # -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set +CONFIG_DISCONTIGMEM=y +CONFIG_ISA=y +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_SA1100=y +# CONFIG_CPU_FREQ_PROC_INTF is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_24_API=y # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y # # At least one math emulation must be selected # CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set + +# +# Generic Driver Options +# CONFIG_PM=y +# CONFIG_PREEMPT is not set CONFIG_APM=m # CONFIG_ARTHUR is not set CONFIG_CMDLINE="console=ttySA0,9600 root=/dev/ram" -# CONFIG_PFS168_CMDLINE is not set CONFIG_LEDS=y # CONFIG_LEDS_TIMER is not set CONFIG_LEDS_CPU=y @@ -166,8 +193,9 @@ CONFIG_MTD_DEBUG=y CONFIG_MTD_DEBUG_VERBOSE=1 CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set # CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_BOOTLDR_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set # @@ -177,51 +205,26 @@ CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set +# CONFIG_INFTL is not set # # RAM/ROM/Flash chip drivers # # CONFIG_MTD_CFI is not set -# CONFIG_MTD_CFI_INTELEXT is not set -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDECPROBE is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set -# CONFIG_MTD_JEDEC is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set # # Mapping drivers for chip access # -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_SUN_UFLASH is not set -# CONFIG_MTD_NORA is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_RPXLITE is not set -# CONFIG_MTD_TQM8XXL is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_NETSC520 is not set -# CONFIG_MTD_SBC_GXX is not set -# CONFIG_MTD_ELAN_104NC is not set -# CONFIG_MTD_DBOX2 is not set -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_CFI_FLAGADM is not set -# CONFIG_MTD_SOLUTIONENGINE is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set -# CONFIG_MTD_OCELOT is not set -# CONFIG_MTD_L440GX is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_COMPLEX_MAPPINGS is not set # # Self-contained MTD device drivers # -# CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set CONFIG_MTD_LART=y # CONFIG_MTD_MTDRAM is not set @@ -230,10 +233,9 @@ # # Disk-On-Chip Device Drivers # -# CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set +# CONFIG_MTD_DOC2001PLUS is not set # # NAND Flash Device Drivers @@ -241,21 +243,15 @@ # CONFIG_MTD_NAND is not set # -# Plug and Play configuration +# Plug and Play support # # CONFIG_PNP is not set -# CONFIG_ISAPNP is not set -# CONFIG_PNPBIOS is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y @@ -266,44 +262,49 @@ # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=m # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set +# CONFIG_NETLINK_DEV is not set CONFIG_UNIX=y +# CONFIG_NET_KEY is not set 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=y CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER 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_LLC2 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 @@ -316,8 +317,9 @@ # CONFIG_NET_SCHED is not set # -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -333,15 +335,14 @@ # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNGEM is not set +# CONFIG_MII is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -349,16 +350,10 @@ # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set + +# +# Ethernet (10000 Mbit) +# CONFIG_PPP=m # CONFIG_PPP_MULTILINK is not set # CONFIG_PPP_FILTER is not set @@ -381,8 +376,6 @@ # Token Ring devices # # CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -407,10 +400,9 @@ CONFIG_IRNET=m CONFIG_IRCOMM=m # CONFIG_IRDA_ULTRA is not set -CONFIG_IRDA_OPTIONS=y # -# IrDA options +# IrDA options # CONFIG_IRDA_CACHE_LAST_LSAP=y # CONFIG_IRDA_FAST_RR is not set @@ -424,132 +416,145 @@ # SIR device drivers # # CONFIG_IRTTY_SIR is not set -# CONFIG_IRPORT_SIR is not set # # Dongle support # -# CONFIG_DONGLE is not set + +# +# Old SIR device drivers +# +# CONFIG_IRPORT_SIR is not set + +# +# Old Serial dongle support +# # # FIR device drivers # -# CONFIG_USB_IRDA is not set # CONFIG_NSC_FIR is not set # CONFIG_WINBOND_FIR is not set # CONFIG_TOSHIBA_FIR is not set # CONFIG_SMC_IRCC_FIR is not set # CONFIG_ALI_FIR is not set -# CONFIG_VLSI_FIR is not set CONFIG_SA1100_FIR=m +# CONFIG_VIA_FIR is not set # -# ATA/IDE/MFM/RLL support +# Bluetooth support # -CONFIG_IDE=m +# CONFIG_BT is not set # -# IDE, ATA and ATAPI Block devices +# ATA/ATAPI/MFM/RLL support # +CONFIG_IDE=m CONFIG_BLK_DEV_IDE=m # # Please see Documentation/ide.txt for help/info on IDE drives # -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=m # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECS is not set +# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=m # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set # # 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_IDE_CHIPSETS is not set +# CONFIG_BLK_DEV_IDEDMA 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_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device support # # CONFIG_SCSI is not set # # I2O device support # -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Input device support +# +CONFIG_INPUT=y # -# Input core support +# Userland interfaces # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set +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 is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 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_PS2_SYNAPTICS is not set +# 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_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # -# CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers # -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# CONFIG_SERIAL_SA1100=y CONFIG_SERIAL_SA1100_CONSOLE=y -CONFIG_SA1100_DEFAULT_BAUDRATE=9600 -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_HUB6 is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 -CONFIG_UCB1200=m -CONFIG_TOUCHSCREEN_UCB1200=m -CONFIG_AUDIO_UCB1200=m -CONFIG_ADC_UCB1200=m -# CONFIG_TOUCHSCREEN_H3600 is not set -CONFIG_PROFILER=m -# CONFIG_PFS168_SPI is not set -# CONFIG_PFS168_DTMF is not set -# CONFIG_PFS168_MISC is not set # # I2C support @@ -557,55 +562,39 @@ # CONFIG_I2C is not set # -# L3 serial bus support +# I2C Algorithms # -# CONFIG_L3 is not set -# CONFIG_L3_ALGOBIT is not set -# CONFIG_L3_BIT_SA1100_GPIO is not set # -# Other L3 adapters +# I2C Hardware Bus support # -# CONFIG_L3_SA1111 is not set # -# L3 driver support +# I2C Hardware Sensors Chip support # -# CONFIG_L3_DRV_UDA1341 is not set -# CONFIG_BIT_SA1100_GPIO is not set +# CONFIG_I2C_SENSOR is not set # # Mice # # CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set - -# -# Input core support is needed for gameports -# +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -CONFIG_SA1100_RTC=m +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -613,6 +602,7 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set # # Multimedia devices @@ -620,87 +610,104 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y CONFIG_REISERFS_FS=m # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=m + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=m CONFIG_JFFS2_FS_DEBUG=1 +# CONFIG_JFFS2_FS_NAND is not set CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=m -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -CONFIG_UDF_FS=m -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=m CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set +# CONFIG_NFS_V4 is not set CONFIG_NFSD=m CONFIG_NFSD_V3=y -CONFIG_SUNRPC=m +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set CONFIG_LOCKD=m CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=m +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set CONFIG_NLS=y # @@ -728,6 +735,7 @@ # CONFIG_NLS_CODEPAGE_949 is not set # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set CONFIG_NLS_ISO8859_1=m # CONFIG_NLS_ISO8859_2 is not set @@ -745,149 +753,62 @@ CONFIG_NLS_UTF8=m # -# Sound -# -CONFIG_SOUND=m -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -# CONFIG_SOUND_ASSABET_UDA1341 is not set -# CONFIG_SOUND_H3600_UDA1341 is not set -# CONFIG_SOUND_PANGOLIN_UDA1341 is not set -# CONFIG_SOUND_SA1111_UDA1341 is not set -CONFIG_SOUND_SA1100SSP=m -# CONFIG_SOUND_OSS is not set -# CONFIG_SOUND_WAVEARTIST is not set -# CONFIG_SOUND_TVMIXER is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# USB Controllers -# -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set - -# -# USB Device Class drivers +# Graphics support # -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set +# CONFIG_FB is not set # -# USB Human Interface Devices (HID) +# Console display driver support # +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y # -# Input core support is needed for USB HID -# - -# -# USB Imaging devices +# Sound # -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set +CONFIG_SOUND=m # -# USB Multimedia devices +# Advanced Linux Sound Architecture # +# CONFIG_SND is not set # -# Video4Linux support is needed for USB Multimedia device support +# Open Sound System # -# CONFIG_USB_DABUSB is not set +# CONFIG_SOUND_PRIME is not set # -# USB Network adaptors +# Misc devices # -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set # -# USB port drivers +# USB support # -# CONFIG_USB_USS720 is not set +# CONFIG_USB_GADGET is not set # -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT 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 -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# 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_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Bluetooth support +# Cryptographic options # -# CONFIG_BT is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set +CONFIG_CRC32=m +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c --- a/arch/arm/kernel/armksyms.c Fri Oct 17 14:43:50 2003 +++ b/arch/arm/kernel/armksyms.c Fri Oct 17 14:43:50 2003 @@ -131,6 +131,7 @@ EXPORT_SYMBOL(__machine_arch_type); /* networking */ +EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy_nocheck); EXPORT_SYMBOL(__csum_ipv6_magic); diff -Nru a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S --- a/arch/arm/lib/div64.S Fri Oct 17 14:43:51 2003 +++ b/arch/arm/lib/div64.S Fri Oct 17 14:43:51 2003 @@ -30,6 +30,8 @@ moveq lr, #1 @ only divide low bits moveq nh, onl + tst dh, #0x80000000 + bne 2f 1: cmp nh, dh bls 2f add lr, lr, #1 diff -Nru a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c --- a/arch/arm/mach-clps7500/core.c Fri Oct 17 14:43:50 2003 +++ b/arch/arm/mach-clps7500/core.c Fri Oct 17 14:43:50 2003 @@ -187,10 +187,6 @@ .unmask = cl7500_no_action, }; -static void no_action(int cpl, void *dev_id, struct pt_regs *regs) -{ -} - static struct irqaction irq_isa = { no_action, 0, 0, "isa", NULL, NULL }; static void __init clps7500_init_irq(void) diff -Nru a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c --- a/arch/arm/mach-integrator/lm.c Fri Oct 17 14:43:50 2003 +++ b/arch/arm/mach-integrator/lm.c Fri Oct 17 14:43:50 2003 @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include @@ -90,3 +91,6 @@ } return ret; } + +EXPORT_SYMBOL(lm_driver_register); +EXPORT_SYMBOL(lm_driver_unregister); diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c --- a/arch/arm/mach-sa1100/cpu-sa1100.c Fri Oct 17 14:43:50 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1100.c Fri Oct 17 14:43:50 2003 @@ -194,7 +194,7 @@ new_ppcr = sa11x0_freq_to_ppcr(target_freq); if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) && (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min)) - mew_ppcr--; + new_ppcr--; break; } diff -Nru a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c --- a/arch/arm/mach-sa1100/lart.c Fri Oct 17 14:43:51 2003 +++ b/arch/arm/mach-sa1100/lart.c Fri Oct 17 14:43:51 2003 @@ -8,6 +8,7 @@ #include #include +#include #include #include diff -Nru a/arch/h8300/Kconfig b/arch/h8300/Kconfig --- a/arch/h8300/Kconfig Fri Oct 17 14:43:50 2003 +++ b/arch/h8300/Kconfig Fri Oct 17 14:43:50 2003 @@ -341,8 +341,8 @@ endmenu -#source drivers/misc/Config.in source "drivers/media/Kconfig" +source "sound/Kconfig" source "fs/Kconfig" diff -Nru a/arch/h8300/README b/arch/h8300/README --- a/arch/h8300/README Fri Oct 17 14:43:50 2003 +++ b/arch/h8300/README Fri Oct 17 14:43:50 2003 @@ -1,9 +1,8 @@ -uClinux-2.4 for H8/300 README +linux-2.6 for H8/300 README Yoshinori Sato * Supported CPU -H8/300H -H8S is planning. +H8/300H and H8S * Supported Target 1.simulator of GDB @@ -15,8 +14,11 @@ Akizuki Denshi Tsusho Ltd. (Japanese Only) 3.H8MAX - Under development - see http://www.strawberry-linux.com (Japanese Only) + see http://ip-sol.jp/h8max/ (Japanese Only) + +4.EDOSK2674 + see http://www.eu.renesas.com/products/mpumcu/tool/edk/support/edosk2674.html + http://www.azpower.com/H8-uClinux/ * Toolchain Version gcc-3.1 or higher and patch @@ -26,10 +28,10 @@ The environment that can compile a h8300-elf binary is necessary. * Userland Develop environment -Tempolary used h8300-hms(h8300-coff) Toolchain. -I prepare toolchain corresponding to h8300-elf. +used h8300-elf toolchains. +see http://www.uclinux.org/pub/uClinux/ports/h8/ * A few words of thanks -Porting to H8/300H is support of Information-technology Promotion Agency, Japan. +Porting to H8/300 serieses is support of Information-technology Promotion Agency, Japan. I thank support. and All developer/user. diff -Nru a/arch/h8300/lib/romfs.S b/arch/h8300/lib/romfs.S --- a/arch/h8300/lib/romfs.S Fri Oct 17 14:43:50 2003 +++ b/arch/h8300/lib/romfs.S Fri Oct 17 14:43:50 2003 @@ -1,6 +1,7 @@ /* romfs move to __ebss */ #include +#include #if defined(__H8300H__) .h8300h @@ -9,6 +10,8 @@ .h8300s #endif +#define BLKOFFSET 512 + .text .globl __move_romfs _romfs_sig_len = 8 @@ -31,6 +34,9 @@ add.l er0,er1 /* romfs image end */ mov.l #__ebss,er2 add.l er0,er2 /* distination address */ +#if defined(CONFIG_INTELFLASH) + add.l #BLKOFFSET,er2 +#endif adds #2,er0 adds #1,er0 shlr er0 diff -Nru a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c --- a/arch/h8300/platform/h8s/ints.c Fri Oct 17 14:43:50 2003 +++ b/arch/h8300/platform/h8s/ints.c Fri Oct 17 14:43:50 2003 @@ -1,5 +1,5 @@ /* - * linux/arch/h8300/platform/h8sh/ints.c + * linux/arch/h8300/platform/h8s/ints.c * * Yoshinori Sato * @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -75,7 +74,7 @@ {H8300_GPIO_P2,H8300_GPIO_B6},{H8300_GPIO_P2,H8300_GPIO_B7}, }; -static int use_kmalloc; +static short use_kmalloc = 0; extern unsigned long *interrupt_redirect_table; diff -Nru a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S --- a/arch/i386/kernel/acpi/wakeup.S Fri Oct 17 14:43:50 2003 +++ b/arch/i386/kernel/acpi/wakeup.S Fri Oct 17 14:43:50 2003 @@ -172,14 +172,13 @@ .org 0x1000 wakeup_pmode_return: - movl $__KERNEL_DS, %eax - movl %eax, %ds - movw $0x0e00 + 'u', %ds:(0xb8016) - - # restore other segment registers - xorl %eax, %eax + movw $__KERNEL_DS, %ax + movw %ax, %ss + movw %ax, %ds + movw %ax, %es movw %ax, %fs movw %ax, %gs + movw $0x0e00 + 'u', 0xb8016 # reload the gdt, as we need the full 32 bit address lgdt saved_gdt @@ -192,46 +191,30 @@ wbinvd # and restore the stack ... but you need gdt for this to work - movl $__KERNEL_DS, %eax - movw %ax, %ss - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movl saved_esp, %esp + movl saved_context_esp, %esp - movw $0x0e00 + 'W', %ds:(0xb8018) - movl $(1024*1024*3), %ecx - movl $0, %esi - rep lodsb - movw $0x0e00 + 'O', %ds:(0xb8018) + movw $0x0e00 + 'W', 0xb8018 + outl %eax, $0x80 + outl %eax, $0x80 + movw $0x0e00 + 'O', 0xb8018 movl %cs:saved_magic, %eax cmpl $0x12345678, %eax jne bogus_magic - # restore the other general registers - movl saved_ebx, %ebx - movl saved_edi, %edi - movl saved_esi, %esi - movl saved_ebp, %ebp - # jump to place where we left off movl saved_eip,%eax - movw $0x0e00 + 'x', %ds:(0xb8018) - pushl %eax - popl %eax - movw $0x0e00 + '!', %ds:(0xb801a) + movw $0x0e00 + 'x', 0xb8018 + outl %eax, $0x80 + outl %eax, $0x80 + movw $0x0e00 + '!', 0xb801a jmp *%eax bogus_magic: - movw $0x0e00 + 'B', %ds:(0xb8018) - jmp bogus_magic + movw $0x0e00 + 'B', 0xb8018 + jmp bogus_magic + -bogus_magic2: - movw $0x0e00 + '2', %ds:(0xb8018) - jmp bogus_magic2 - ## # acpi_copy_wakeup_routine # @@ -267,80 +250,45 @@ .data ALIGN -ENTRY(saved_ebp) .long 0 -ENTRY(saved_esi) .long 0 -ENTRY(saved_edi) .long 0 -ENTRY(saved_ebx) .long 0 - -ENTRY(saved_eip) .long 0 -ENTRY(saved_esp) .long 0 - ENTRY(saved_magic) .long 0 +ENTRY(saved_eip) .long 0 -ENTRY(do_suspend_lowlevel) - cmpl $0,4(%esp) - jne ret_point - call save_processor_state - - movl %esp, saved_context_esp - movl %eax, saved_context_eax +save_registers: + leal 4(%esp), %eax + movl %eax, saved_context_esp movl %ebx, saved_context_ebx - movl %ecx, saved_context_ecx - movl %edx, saved_context_edx movl %ebp, saved_context_ebp movl %esi, saved_context_esi movl %edi, saved_context_edi pushfl ; popl saved_context_eflags movl $ret_point,saved_eip - movl %esp,saved_esp - movl %ebp,saved_ebp - movl %ebx,saved_ebx - movl %edi,saved_edi - movl %esi,saved_esi - - pushl $3 - call acpi_enter_sleep_state - addl $4,%esp ret - .p2align 4,,7 -ret_point: - movl $__KERNEL_DS,%eax - movw %ax, %ds - movl saved_context_esp, %esp + + +restore_registers: movl saved_context_ebp, %ebp - movl saved_context_eax, %eax movl saved_context_ebx, %ebx - movl saved_context_ecx, %ecx - movl saved_context_edx, %edx movl saved_context_esi, %esi movl saved_context_edi, %edi - call restore_processor_state pushl saved_context_eflags ; popfl + ret + +ENTRY(do_suspend_lowlevel) + call save_processor_state + call save_registers + pushl $3 + call acpi_enter_sleep_state + ret + .p2align 4,,7 +ret_point: + call restore_registers + call restore_processor_state ret ENTRY(do_suspend_lowlevel_s4bios) - cmpl $0,4(%esp) - jne ret_point call save_processor_state - - movl %esp, saved_context_esp - movl %eax, saved_context_eax - movl %ebx, saved_context_ebx - movl %ecx, saved_context_ecx - movl %edx, saved_context_edx - movl %ebp, saved_context_ebp - movl %esi, saved_context_esi - movl %edi, saved_context_edi - pushfl ; popl saved_context_eflags - - movl $ret_point,saved_eip - movl %esp,saved_esp - movl %ebp,saved_ebp - movl %ebx,saved_ebx - movl %edi,saved_edi - movl %esi,saved_esi - + call save_registers call acpi_enter_sleep_state_s4bios ret diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c --- a/arch/i386/kernel/apic.c Fri Oct 17 14:43:51 2003 +++ b/arch/i386/kernel/apic.c Fri Oct 17 14:43:51 2003 @@ -533,14 +533,19 @@ if (!apic_pm_state.active) return 0; - /* XXX: Pavel needs this for S3 resume, but can't explain why */ - set_fixmap_nocache(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE); - local_irq_save(flags); + + /* + * Make sure the APICBASE points to the right address + * + * FIXME! This will be wrong if we ever support suspend on + * SMP! We'll need to do this as part of the CPU restore! + */ rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); + apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); apic_write(APIC_DFR, apic_pm_state.apic_dfr); @@ -680,6 +685,12 @@ } set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; + + /* The BIOS may have set up the APIC at some other address */ + rdmsr(MSR_IA32_APICBASE, l, h); + if (l & MSR_IA32_APICBASE_ENABLE) + mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; + if (nmi_watchdog != NMI_NONE) nmi_watchdog = NMI_LOCAL_APIC; diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c Fri Oct 17 14:43:50 2003 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c Fri Oct 17 14:43:50 2003 @@ -5,17 +5,14 @@ * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by VIA. * - * VIA have currently 3 different versions of Longhaul. - * - * +---------------------+----------+---------------------------------+ - * | Marketing name | Codename | longhaul version / features. | - * +---------------------+----------+---------------------------------+ - * | Samuel/CyrixIII | C5A | v1 : multipliers only | - * | Samuel2/C3 | C3E/C5B | v1 : multiplier only | - * | Ezra | C5C | v2 : multipliers & voltage | - * | Ezra-T | C5M | v3 : multipliers, voltage & FSB | - * | Nehemiah | C5N | v3 : multipliers, voltage & FSB | - * +---------------------+----------+---------------------------------+ + * VIA have currently 2 different versions of Longhaul. + * Version 1 (Longhaul) uses the BCR2 MSR at 0x1147. + * It is present only in Samuel 1, Samuel 2 and Ezra. + * Version 2 (Powersaver) uses the POWERSAVER MSR at 0x110a. + * It is present in Ezra-T, Nehemiah and above. + * In addition to scaling multiplier, it can also scale voltage. + * There is provision for scaling FSB too, but this doesn't work + * too well in practice. * * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* */ @@ -66,7 +63,11 @@ static unsigned int calc_speed (int mult, int fsb) { - return ((mult/10)*fsb) + ((mult%10)*(fsb/2)); + int mhz; + mhz = (mult/10)*fsb; + if (mult%10) + mhz += fsb/2; + return mhz; } @@ -76,7 +77,7 @@ rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22; - if (longhaul_version==3) { + if (longhaul_version==2) { if (lo & (1<<27)) invalue+=16; } @@ -132,32 +133,15 @@ break; /* - * Longhaul v2. (Ezra [C5C]) + * Powersaver. (Ezra-T [C5M], Nehemiah [C5N]) * We can scale voltage with this too, but that's currently * disabled until we come up with a decent 'match freq to voltage' * algorithm. * We also need to do the voltage/freq setting in order depending * on the direction of scaling (like we do in powernow-k7.c) - */ - case 2: - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; - longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; - longhaul.bits.EnableSoftBusRatio = 1; - /* We must program the revision key only with values we - * know about, not blindly copy it from 0:3 */ - longhaul.bits.RevisionKey = 1; - wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); - __hlt(); - - break; - - /* - * Longhaul v3. (Ezra-T [C5M], Nehemiah [C5N]) - * This can also do voltage scaling, but see above. * Ezra-T was alleged to do FSB scaling too, but it never worked in practice. */ - case 3: + case 2: rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; @@ -214,6 +198,7 @@ static int __init longhaul_get_ranges (void) { + struct cpuinfo_x86 *c = cpu_data; unsigned long invalue; unsigned int minmult=0, maxmult=0; unsigned int multipliers[32]= { @@ -232,10 +217,13 @@ maxmult = longhaul_get_cpu_mult(); rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<18|1<<19)) >>18; - fsb = eblcr_fsb_table[invalue]; + if (c->x86_model==6) + fsb = eblcr_fsb_table[invalue]; + else + fsb = guess_fsb(maxmult); break; - case 2 ... 3: + case 2: rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); invalue = longhaul.bits.MaxMHzBR; @@ -378,10 +366,10 @@ break; case 7: /* C5B / C5C */ + longhaul_version=1; switch (c->x86_mask) { case 0: cpuname = "C3 'Samuel 2' [C5B]"; - longhaul_version=1; /* Note, this is not a typo, early Samuel2's had Samuel1 ratios. */ memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio)); memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr)); @@ -391,7 +379,6 @@ cpuname = "C3 'Samuel 2' [C5B]"; else cpuname = "C3 'Ezra' [C5C]"; - longhaul_version=2; memcpy (clock_ratio, ezra_clock_ratio, sizeof(ezra_clock_ratio)); memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr)); break; @@ -399,20 +386,21 @@ break; case 8: - cpuname = "C3 'Ezra-T [C5M]"; - longhaul_version=3; + cpuname = "C3 'Ezra-T' [C5M]"; + longhaul_version=2; numscales=32; memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio)); memcpy (eblcr_table, ezrat_eblcr, sizeof(ezrat_eblcr)); break; - /* + case 9: cpuname = "C3 'Nehemiah' [C5N]"; - longhaul_version=3; + longhaul_version=2; numscales=32; memcpy (clock_ratio, nehemiah_clock_ratio, sizeof(nehemiah_clock_ratio)); memcpy (eblcr_table, nehemiah_eblcr, sizeof(nehemiah_eblcr)); - */ + break; + default: cpuname = "Unknown"; break; @@ -421,7 +409,7 @@ printk (KERN_INFO PFX "VIA %s CPU detected. Longhaul v%d supported.\n", cpuname, longhaul_version); - if ((longhaul_version==2 || longhaul_version==3) && (dont_scale_voltage==0)) + if ((longhaul_version==2) && (dont_scale_voltage==0)) longhaul_setup_voltagescaling(); ret = longhaul_get_ranges(); diff -Nru a/arch/i386/kernel/edd.c b/arch/i386/kernel/edd.c --- a/arch/i386/kernel/edd.c Fri Oct 17 14:43:50 2003 +++ b/arch/i386/kernel/edd.c Fri Oct 17 14:43:50 2003 @@ -13,6 +13,10 @@ * made in setup.S, copied to safe structures in setup.c, * and presents it in sysfs. * + * Please see http://domsch.com/linux/edd30/results.html for + * the list of BIOSs which have been reported to implement EDD. + * If you don't see yours listed, please send a report as described there. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License v2.0 as published by * the Free Software Foundation @@ -55,7 +59,7 @@ MODULE_DESCRIPTION("sysfs interface to BIOS EDD information"); MODULE_LICENSE("GPL"); -#define EDD_VERSION "0.09 2003-Jan-22" +#define EDD_VERSION "0.10 2003-Oct-11" #define EDD_DEVICE_NAME_SIZE 16 #define REPORT_URL "http://domsch.com/linux/edd30/results.html" @@ -75,8 +79,6 @@ /* forward declarations */ static int edd_dev_is_type(struct edd_device *edev, const char *type); static struct pci_dev *edd_get_pci_dev(struct edd_device *edev); -static struct scsi_device *edd_find_matching_scsi_device(struct edd_device *edev); -static int kernel_has_scsi(void); static struct edd_device *edd_devices[EDDMAXNR]; @@ -118,41 +120,6 @@ .show = edd_attr_show, }; -static int -edd_dump_raw_data(char *b, int count, void *data, int length) -{ - char *orig_b = b; - char hexbuf[80], ascbuf[20], *h, *a, c; - unsigned char *p = data; - unsigned long column = 0; - int length_printed = 0, d; - const char maxcolumn = 16; - while (length_printed < length && count > 0) { - h = hexbuf; - a = ascbuf; - for (column = 0; - column < maxcolumn && length_printed < length; column++) { - h += sprintf(h, "%02x ", (unsigned char) *p); - if (!isprint(*p)) - c = '.'; - else - c = *p; - a += sprintf(a, "%c", c); - p++; - length_printed++; - } - /* pad out the line */ - for (; column < maxcolumn; column++) { - h += sprintf(h, " "); - a += sprintf(a, " "); - } - d = snprintf(b, count, "%s\t%s\n", hexbuf, ascbuf); - b += d; - count -= d; - } - return (b - orig_b); -} - static ssize_t edd_show_host_bus(struct edd_device *edev, char *buf) { @@ -161,7 +128,7 @@ int i; if (!edev || !info || !buf) { - return 0; + return -EINVAL; } for (i = 0; i < 4; i++) { @@ -205,7 +172,7 @@ int i; if (!edev || !info || !buf) { - return 0; + return -EINVAL; } for (i = 0; i < 8; i++) { @@ -255,105 +222,28 @@ } /** - * edd_show_raw_data() - unparses EDD information, returned to user-space + * edd_show_raw_data() - copies raw data to buffer for userspace to parse * - * Returns: number of bytes written, or 0 on failure + * Returns: number of bytes written, or -EINVAL on failure */ static ssize_t edd_show_raw_data(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); - int i, warn_padding = 0, nonzero_path = 0, - len = sizeof (*info) - 4, found_pci=0; - uint8_t checksum = 0, c = 0; - char *p = buf; - struct pci_dev *pci_dev=NULL; - struct scsi_device *sd; + ssize_t len = sizeof (*info) - 4; if (!edev || !info || !buf) { - return 0; + return -EINVAL; } if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE)) len = info->params.length; - p += snprintf(p, left, "int13 fn48 returned data:\n\n"); - p += edd_dump_raw_data(p, left, ((char *) info) + 4, len); - - /* Spec violation. Adaptec AIC7899 returns 0xDDBE - here, when it should be 0xBEDD. - */ - p += snprintf(p, left, "\n"); - if (info->params.key == 0xDDBE) { - p += snprintf(p, left, - "Warning: Spec violation. Key should be 0xBEDD, is 0xDDBE\n"); - } + /* In case of buggy BIOSs */ + if (len > (sizeof(*info) - 4)) + len = sizeof(*info) - 4; - if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE)) { - goto out; - } - - for (i = 30; i <= 73; i++) { - c = *(((uint8_t *) info) + i + 4); - if (c) - nonzero_path++; - checksum += c; - } - - if (checksum) { - p += snprintf(p, left, - "Warning: Spec violation. Device Path checksum invalid.\n"); - } - - if (!nonzero_path) { - p += snprintf(p, left, "Error: Spec violation. Empty device path.\n"); - goto out; - } - - for (i = 0; i < 4; i++) { - if (!isprint(info->params.host_bus_type[i])) { - warn_padding++; - } - } - for (i = 0; i < 8; i++) { - if (!isprint(info->params.interface_type[i])) { - warn_padding++; - } - } - - if (warn_padding) { - p += snprintf(p, left, - "Warning: Spec violation. Padding should be 0x20.\n"); - } - - if (edd_dev_is_type(edev, "PCI")) { - pci_dev = edd_get_pci_dev(edev); - if (!pci_dev) { - p += snprintf(p, left, "Error: BIOS says this is a PCI device, but the OS doesn't know\n"); - p += snprintf(p, left, " about a PCI device at %02x:%02x.%d\n", - info->params.interface_path.pci.bus, - info->params.interface_path.pci.slot, - info->params.interface_path.pci.function); - } - else { - found_pci++; - } - } - - if (found_pci && kernel_has_scsi() && edd_dev_is_type(edev, "SCSI")) { - sd = edd_find_matching_scsi_device(edev); - if (!sd) { - p += snprintf(p, left, "Error: BIOS says this is a SCSI device, but\n"); - p += snprintf(p, left, " the OS doesn't know about this SCSI device.\n"); - p += snprintf(p, left, " Do you have it's driver module loaded?\n"); - } - } - -out: - p += snprintf(p, left, "\nPlease check %s\n", REPORT_URL); - p += snprintf(p, left, "to see if this device has been reported. If not,\n"); - p += snprintf(p, left, "please send the information requested there.\n"); - - return (p - buf); + memcpy(buf, ((char *)info) + 4, len); + return len; } static ssize_t @@ -362,7 +252,7 @@ struct edd_info *info = edd_dev_get_info(edev); char *p = buf; if (!edev || !info || !buf) { - return 0; + return -EINVAL; } p += snprintf(p, left, "0x%02x\n", info->version); @@ -375,7 +265,7 @@ struct edd_info *info = edd_dev_get_info(edev); char *p = buf; if (!edev || !info || !buf) { - return 0; + return -EINVAL; } if (info->interface_support & EDD_EXT_FIXED_DISK_ACCESS) { @@ -399,7 +289,7 @@ struct edd_info *info = edd_dev_get_info(edev); char *p = buf; if (!edev || !info || !buf) { - return 0; + return -EINVAL; } if (info->params.info_flags & EDD_INFO_DMA_BOUNDARY_ERROR_TRANSPARENT) @@ -427,7 +317,7 @@ struct edd_info *info = edd_dev_get_info(edev); char *p = buf; if (!edev || !info || !buf) { - return 0; + return -EINVAL; } p += snprintf(p, left, "0x%x\n", info->params.num_default_cylinders); @@ -440,7 +330,7 @@ struct edd_info *info = edd_dev_get_info(edev); char *p = buf; if (!edev || !info || !buf) { - return 0; + return -EINVAL; } p += snprintf(p, left, "0x%x\n", info->params.num_default_heads); @@ -453,7 +343,7 @@ struct edd_info *info = edd_dev_get_info(edev); char *p = buf; if (!edev || !info || !buf) { - return 0; + return -EINVAL; } p += snprintf(p, left, "0x%x\n", info->params.sectors_per_track); @@ -466,7 +356,7 @@ struct edd_info *info = edd_dev_get_info(edev); char *p = buf; if (!edev || !info || !buf) { - return 0; + return -EINVAL; } p += snprintf(p, left, "0x%llx\n", info->params.number_of_sectors); @@ -489,7 +379,7 @@ { struct edd_info *info = edd_dev_get_info(edev); if (!edev || !info) - return 0; + return -EINVAL; return info->params.num_default_cylinders > 0; } @@ -498,7 +388,7 @@ { struct edd_info *info = edd_dev_get_info(edev); if (!edev || !info) - return 0; + return -EINVAL; return info->params.num_default_heads > 0; } @@ -507,7 +397,7 @@ { struct edd_info *info = edd_dev_get_info(edev); if (!edev || !info) - return 0; + return -EINVAL; return info->params.sectors_per_track > 0; } @@ -739,22 +629,7 @@ return rc; } -static int kernel_has_scsi(void) -{ - return 1; -} - #else -static int kernel_has_scsi(void) -{ - return 0; -} - -static struct scsi_device * -edd_find_matching_scsi_device(struct edd_device *edev) -{ - return NULL; -} static int edd_create_symlink_to_scsidev(struct edd_device *edev) { @@ -776,11 +651,11 @@ int i; for (i = 0; (attr = edd_attrs[i]) && !error; i++) { - if (!attr->test || + if (!attr->test || (attr->test && attr->test(edev))) error = sysfs_create_file(&edev->kobj,&attr->attr); } - + if (!error) { edd_create_symlink_to_pcidev(edev); edd_create_symlink_to_scsidev(edev); @@ -820,6 +695,7 @@ printk(KERN_INFO "BIOS EDD facility v%s, %d devices found\n", EDD_VERSION, eddnr); + printk(KERN_INFO "Please report your BIOS at %s\n", REPORT_URL); if (!eddnr) { printk(KERN_INFO "EDD information not available.\n"); diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c --- a/arch/i386/kernel/irq.c Fri Oct 17 14:43:50 2003 +++ b/arch/i386/kernel/irq.c Fri Oct 17 14:43:50 2003 @@ -355,8 +355,10 @@ void disable_irq(unsigned int irq) { + irq_desc_t *desc = irq_desc + irq; disable_irq_nosync(irq); - synchronize_irq(irq); + if (desc->action) + synchronize_irq(irq); } /** @@ -378,7 +380,7 @@ spin_lock_irqsave(&desc->lock, flags); switch (desc->depth) { case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; + unsigned int status = desc->status & ~(IRQ_DISABLED | IRQ_INPROGRESS); desc->status = status; if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { desc->status = status | IRQ_REPLAY; diff -Nru a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c --- a/arch/i386/kernel/microcode.c Fri Oct 17 14:43:50 2003 +++ b/arch/i386/kernel/microcode.c Fri Oct 17 14:43:50 2003 @@ -55,10 +55,18 @@ * Tigran Aivazian , * Serialize updates as required on HT processors due to speculative * nature of implementation. - * 1.11 22 Mar 2001 Tigran Aivazian + * 1.11 22 Mar 2002 Tigran Aivazian * Fix the panic when writing zero-length microcode chunk. + * 1.12 29 Sep 2003 Nitin Kamble , + * Jun Nakajima + * Support for the microcode updates in the new format. + * 1.13 10 Oct 2003 Tigran Aivazian + * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl + * because we no longer hold a copy of applied microcode + * in kernel memory. */ + #include #include #include @@ -72,264 +80,387 @@ #include #include - -static spinlock_t microcode_update_lock = SPIN_LOCK_UNLOCKED; - -#define MICROCODE_VERSION "1.11" - MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver"); MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); -#define MICRO_DEBUG 0 - +#define MICROCODE_VERSION "1.13" +#define MICRO_DEBUG 0 #if MICRO_DEBUG -#define printf(x...) printk(##x) +#define dprintk(x...) printk(KERN_INFO x) #else -#define printf(x...) +#define dprintk(x...) #endif -/* read()/write()/ioctl() are serialized on this */ -static DECLARE_RWSEM(microcode_rwsem); +#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ +#define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ +#define EXT_HEADER_SIZE (sizeof (struct extended_sigtable)) /* 20 bytes */ +#define EXT_SIGNATURE_SIZE (sizeof (struct extended_signature)) /* 12 bytes */ +#define DWSIZE (sizeof (u32)) +#define get_totalsize(mc) \ + (((microcode_t *)mc)->hdr.totalsize ? \ + ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) +#define get_datasize(mc) \ + (((microcode_t *)mc)->hdr.datasize ? \ + ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) +#define sigmatch(s1, s2, p1, p2) (((s1) == (s2)) && ((p1) & (p2))) +#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) -static struct microcode *microcode; /* array of 2048byte microcode blocks */ -static unsigned int microcode_num; /* number of chunks in microcode */ -static char *mc_applied; /* array of applied microcode blocks */ -static unsigned int mc_fsize; /* file size of /dev/cpu/microcode */ +/* serialize access to the physical write to MSR 0x79 */ +static spinlock_t microcode_update_lock = SPIN_LOCK_UNLOCKED; + +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ +static DECLARE_MUTEX(microcode_sem); + +static void *user_buffer; /* user area microcode data buffer */ +static unsigned int user_buffer_size; /* it's size */ -static int microcode_open(struct inode *unused1, struct file *unused2) +typedef enum mc_error_code { + MC_SUCCESS = 0, + MC_NOTFOUND = 1, + MC_MARKED = 2, + MC_ALLOCATED = 3, +} mc_error_code_t; + +static struct ucode_cpu_info { + unsigned int sig; + unsigned int pf; + unsigned int rev; + unsigned int cksum; + mc_error_code_t err; + microcode_t *mc; +} ucode_cpu_info[NR_CPUS]; + +static int microcode_open (struct inode *unused1, struct file *unused2) { return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; } -/* - * update_req[cpu].err is set to 1 if update failed on 'cpu', 0 otherwise - * if err==0, microcode[update_req[cpu].slot] points to applied block of microcode - */ -struct update_req { - int err; - int slot; -} update_req[NR_CPUS]; - -static void do_update_one(void *unused) +static void collect_cpu_info (void *unused) { int cpu_num = smp_processor_id(); struct cpuinfo_x86 *c = cpu_data + cpu_num; - struct update_req *req = update_req + cpu_num; - unsigned int pf = 0, val[2], rev, sig; - unsigned long flags; - int i; + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + unsigned int val[2]; - req->err = 1; /* assume update will fail on this cpu */ + uci->sig = uci->pf = uci->rev = uci->cksum = 0; + uci->err = MC_NOTFOUND; + uci->mc = NULL; if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || cpu_has(c, X86_FEATURE_IA64)) { printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num); return; + } else { + uci->sig = cpuid_eax(0x00000001); + + if ((c->x86_model >= 5) || (c->x86 > 6)) { + /* get processor flags from MSR 0x17 */ + rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); + uci->pf = 1 << ((val[1] >> 18) & 7); + } } - sig = c->x86_mask + (c->x86_model<<4) + (c->x86<<8); + wrmsr(MSR_IA32_UCODE_REV, 0, 0); + __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); + /* get the current revision from MSR 0x8B */ + rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev); + dprintk("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", + uci->sig, uci->pf, uci->rev); +} - if ((c->x86_model >= 5) || (c->x86 > 6)) { - /* get processor flags from MSR 0x17 */ - rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); - pf = 1 << ((val[1] >> 18) & 7); - } - - for (i=0; i> 24 ) & 0xff), - ((microcode[i].date >> 16 ) & 0xff), - (microcode[i].date & 0xFFFF)); - printf(" Type %x Family %x Model %x Stepping %x\n", - ((microcode[i].sig >> 12) & 0x3), - ((microcode[i].sig >> 8) & 0xf), - ((microcode[i].sig >> 4) & 0xf), - ((microcode[i].sig & 0xf))); - printf(" Checksum %x\n",microcode[i].cksum); - printf(" Loader Revision %x\n",microcode[i].ldrver); - printf(" Processor Flags %x\n\n",microcode[i].pf); - - req->slot = i; - - /* serialize access to update decision */ - spin_lock_irqsave(µcode_update_lock, flags); - - /* trick, to work even if there was no prior update by the BIOS */ - wrmsr(MSR_IA32_UCODE_REV, 0, 0); - __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); +static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_header, int sig, int pf, int cksum) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - /* get current (on-cpu) revision into rev (ignore val[0]) */ - rdmsr(MSR_IA32_UCODE_REV, val[0], rev); - - if (microcode[i].rev < rev) { - spin_unlock_irqrestore(µcode_update_lock, flags); - printk(KERN_INFO - "microcode: CPU%d not 'upgrading' to earlier revision" - " %d (current=%d)\n", cpu_num, microcode[i].rev, rev); - return; - } else if (microcode[i].rev == rev) { - /* notify the caller of success on this cpu */ - req->err = 0; - spin_unlock_irqrestore(µcode_update_lock, flags); - printk(KERN_INFO - "microcode: CPU%d already at revision" - " %d (current=%d)\n", cpu_num, microcode[i].rev, rev); - return; - } + dprintk("Microcode Found.\n"); + dprintk(" Header Revision 0x%x\n", mc_header->hdrver); + dprintk(" Loader Revision 0x%x\n", mc_header->ldrver); + dprintk(" Revision 0x%x \n", mc_header->rev); + dprintk(" Date %x/%x/%x\n", + ((mc_header->date >> 24 ) & 0xff), + ((mc_header->date >> 16 ) & 0xff), + (mc_header->date & 0xFFFF)); + dprintk(" Signature 0x%x\n", sig); + dprintk(" Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n", + ((sig >> 12) & 0x3), + ((sig >> 8) & 0xf), + ((sig >> 4) & 0xf), + ((sig & 0xf))); + dprintk(" Processor Flags 0x%x\n", pf); + dprintk(" Checksum 0x%x\n", cksum); + + if (mc_header->rev < uci->rev) { + printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision" + " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); + goto out; + } else if (mc_header->rev == uci->rev) { + /* notify the caller of success on this cpu */ + uci->err = MC_SUCCESS; + printk(KERN_ERR "microcode: CPU%d already at revision" + " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); + goto out; + } - /* Verify the checksum */ - while (--sump >= (unsigned int *)m) - sum += *sump; - if (sum != 0) { - req->err = 1; - spin_unlock_irqrestore(µcode_update_lock, flags); - printk(KERN_ERR "microcode: CPU%d aborting, " - "bad checksum\n", cpu_num); - return; - } - - /* write microcode via MSR 0x79 */ - wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(m->bits), 0); + dprintk("microcode: CPU%d found a matching microcode update with " + " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); + uci->cksum = cksum; + uci->pf = pf; /* keep the original mc pf for cksum calculation */ + uci->err = MC_MARKED; /* found the match */ +out: + return; +} - /* serialize */ - __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); +static int find_matching_ucodes (void) +{ + int cursor = 0; + int error = 0; - /* get the current revision from MSR 0x8B */ - rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); + while (cursor + MC_HEADER_SIZE < user_buffer_size) { + microcode_header_t mc_header; + void *newmc = NULL; + int i, sum, cpu_num, allocated_flag, total_size, data_size, ext_table_size; + + if (copy_from_user(&mc_header, user_buffer + cursor, MC_HEADER_SIZE)) { + printk(KERN_ERR "microcode: error! Can not read user data\n"); + error = -EFAULT; + goto out; + } - /* notify the caller of success on this cpu */ - req->err = 0; - spin_unlock_irqrestore(µcode_update_lock, flags); - printk(KERN_INFO "microcode: CPU%d updated from revision " - "%d to %d, date=%08x\n", - cpu_num, rev, val[1], microcode[i].date); - return; + total_size = get_totalsize(&mc_header); + if ((cursor + total_size > user_buffer_size) || (total_size < DEFAULT_UCODE_TOTALSIZE)) { + printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); + error = -EINVAL; + goto out; } - - printk(KERN_ERR - "microcode: CPU%d no microcode found! (sig=%x, pflags=%d)\n", - cpu_num, sig, pf); -} + data_size = get_datasize(&mc_header); + if ((data_size + MC_HEADER_SIZE > total_size) || (data_size < DEFAULT_UCODE_DATASIZE)) { + printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); + error = -EINVAL; + goto out; + } -static int do_microcode_update(void) -{ - int i, error = 0, err; - struct microcode *m; + if (mc_header.ldrver != 1 || mc_header.hdrver != 1) { + printk(KERN_ERR "microcode: error! Unknown microcode update format\n"); + error = -EINVAL; + goto out; + } + + for (cpu_num = 0; cpu_num < num_online_cpus(); cpu_num++) { + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/ + continue; - if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) { - printk(KERN_ERR "microcode: IPI timeout, giving up\n"); - return -EIO; - } + if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->pf)) + mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum); + } + + ext_table_size = total_size - (MC_HEADER_SIZE + data_size); + if (ext_table_size) { + struct extended_sigtable ext_header; + struct extended_signature ext_sig; + int ext_sigcount; + + if ((ext_table_size < EXT_HEADER_SIZE) + || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { + printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); + error = -EINVAL; + goto out; + } + if (copy_from_user(&ext_header, user_buffer + cursor + + MC_HEADER_SIZE + data_size, EXT_HEADER_SIZE)) { + printk(KERN_ERR "microcode: error! Can not read user data\n"); + error = -EFAULT; + goto out; + } + if (ext_table_size != exttable_size(&ext_header)) { + printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); + error = -EFAULT; + goto out; + } - for (i=0; ierr != MC_NOTFOUND) /* already found a match or not an online cpu*/ + continue; + if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->pf)) { + mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum); + } + } + } } - } + /* now check if any cpu has matched */ + for (cpu_num = 0, allocated_flag = 0, sum = 0; cpu_num < num_online_cpus(); cpu_num++) { + if (ucode_cpu_info[cpu_num].err == MC_MARKED) { + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + if (!allocated_flag) { + allocated_flag = 1; + newmc = vmalloc(total_size); + if (!newmc) { + printk(KERN_ERR "microcode: error! Can not allocate memory\n"); + error = -ENOMEM; + goto out; + } + if (copy_from_user(newmc + MC_HEADER_SIZE, + user_buffer + cursor + MC_HEADER_SIZE, + total_size - MC_HEADER_SIZE)) { + printk(KERN_ERR "microcode: error! Can not read user data\n"); + vfree(newmc); + error = -EFAULT; + goto out; + } + memcpy(newmc, &mc_header, MC_HEADER_SIZE); + /* check extended table checksum */ + if (ext_table_size) { + int ext_table_sum = 0; + i = ext_table_size / DWSIZE; + int * ext_tablep = (((void *) newmc) + MC_HEADER_SIZE + data_size); + while (i--) ext_table_sum += ext_tablep[i]; + if (ext_table_sum) { + printk(KERN_WARNING "microcode: aborting, bad extended signature table checksum\n"); + vfree(newmc); + error = -EINVAL; + goto out; + } + } + + /* calculate the checksum */ + i = (MC_HEADER_SIZE + data_size) / DWSIZE; + while (i--) sum += ((int *)newmc)[i]; + sum -= (mc_header.sig + mc_header.pf + mc_header.cksum); + } + ucode_cpu_info[cpu_num].mc = newmc; + ucode_cpu_info[cpu_num].err = MC_ALLOCATED; /* mc updated */ + if (sum + uci->sig + uci->pf + uci->cksum != 0) { + printk(KERN_ERR "microcode: CPU%d aborting, bad checksum\n", cpu_num); + error = -EINVAL; + goto out; + } + } + } + cursor += total_size; /* goto the next update patch */ + } /* end of while */ +out: return error; } -static ssize_t microcode_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) +static void do_update_one (void * unused) { - ssize_t ret = 0; + unsigned long flags; + unsigned int val[2]; + int cpu_num = smp_processor_id(); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - down_read(µcode_rwsem); - if (*ppos >= mc_fsize) - goto out; - if (*ppos + len > mc_fsize) - len = mc_fsize - *ppos; - ret = -EFAULT; - if (copy_to_user(buf, mc_applied + *ppos, len)) + if (uci->mc == NULL) { + printk(KERN_INFO "microcode: No suitable data for cpu %d\n", cpu_num); + return; + } + + /* serialize access to the physical write to MSR 0x79 */ + spin_lock_irqsave(µcode_update_lock, flags); + + /* write microcode via MSR 0x79 */ + wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(uci->mc->bits), 0); + wrmsr(MSR_IA32_UCODE_REV, 0, 0); + + __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); + /* get the current revision from MSR 0x8B */ + rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); + + /* notify the caller of success on this cpu */ + uci->err = MC_SUCCESS; + spin_unlock_irqrestore(µcode_update_lock, flags); + printk(KERN_INFO "microcode: CPU%d updated from revision " + "0x%x to 0x%x, date = %08x \n", + cpu_num, uci->rev, val[1], uci->mc->hdr.date); + return; +} + +static int do_microcode_update (void) +{ + int i, error; + + if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) { + printk(KERN_ERR "microcode: Error! Could not run on all processors\n"); + error = -EIO; goto out; - *ppos += len; - ret = len; + } + + if ((error = find_matching_ucodes())) { + printk(KERN_ERR "microcode: Error in the microcode data\n"); + goto out_free; + } + + if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) { + printk(KERN_ERR "microcode: Error! Could not run on all processors\n"); + error = -EIO; + } + +out_free: + for (i = 0; i < num_online_cpus(); i++) { + if (ucode_cpu_info[i].mc) { + int j; + void *tmp = ucode_cpu_info[i].mc; + vfree(tmp); + for (j = i; j < num_online_cpus(); j++) { + if (ucode_cpu_info[j].mc == tmp) + ucode_cpu_info[j].mc = NULL; + } + } + } out: - up_read(µcode_rwsem); - return ret; + return error; } -static ssize_t microcode_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos) +static ssize_t microcode_write (struct file *file, const char *buf, size_t len, loff_t *ppos) { ssize_t ret; - if (!len || len % sizeof(struct microcode) != 0) { - printk(KERN_ERR "microcode: can only write in N*%d bytes units\n", - sizeof(struct microcode)); + if (len < DEFAULT_UCODE_TOTALSIZE) { + printk(KERN_ERR "microcode: not enough data\n"); return -EINVAL; } + if ((len >> PAGE_SHIFT) > num_physpages) { printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); return -EINVAL; } - down_write(µcode_rwsem); - if (!mc_applied) { - mc_applied = kmalloc(NR_CPUS*sizeof(struct microcode), - GFP_KERNEL); - if (!mc_applied) { - up_write(µcode_rwsem); - printk(KERN_ERR "microcode: out of memory for saved microcode\n"); - return -ENOMEM; - } - } - - microcode_num = len/sizeof(struct microcode); - microcode = vmalloc(len); - if (!microcode) { - ret = -ENOMEM; - goto out_unlock; - } - - if (copy_from_user(microcode, buf, len)) { - ret = -EFAULT; - goto out_fsize; - } - - if(do_microcode_update()) { - ret = -EIO; - goto out_fsize; - } else { - mc_fsize = NR_CPUS * sizeof(struct microcode); + + down(µcode_sem); + + user_buffer = (void *) buf; + user_buffer_size = (int) len; + + ret = do_microcode_update(); + if (!ret) ret = (ssize_t)len; - } -out_fsize: - vfree(microcode); -out_unlock: - up_write(µcode_rwsem); + + up(µcode_sem); + return ret; } -static int microcode_ioctl(struct inode *inode, struct file *file, +static int microcode_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - switch(cmd) { + switch (cmd) { + /* + * XXX: will be removed after microcode_ctl + * is updated to ignore failure of this ioctl() + */ case MICROCODE_IOCFREE: - down_write(µcode_rwsem); - if (mc_applied) { - int bytes = NR_CPUS * sizeof(struct microcode); - - kfree(mc_applied); - mc_applied = NULL; - printk(KERN_INFO "microcode: freed %d bytes\n", bytes); - mc_fsize = 0; - up_write(µcode_rwsem); - return 0; - } - up_write(µcode_rwsem); - return -ENODATA; - + return 0; default: return -EINVAL; } @@ -338,7 +469,6 @@ static struct file_operations microcode_fops = { .owner = THIS_MODULE, - .read = microcode_read, .write = microcode_write, .ioctl = microcode_ioctl, .open = microcode_open, @@ -347,17 +477,20 @@ static struct miscdevice microcode_dev = { .minor = MICROCODE_MINOR, .name = "microcode", - .devfs_name = "cpu/microcode", .fops = µcode_fops, }; -static int __init microcode_init(void) +static int __init microcode_init (void) { int error; error = misc_register(µcode_dev); - if (error) + if (error) { + printk(KERN_ERR + "microcode: can't misc_register on minor=%d\n", + MICROCODE_MINOR); return error; + } printk(KERN_INFO "IA-32 Microcode Update Driver: v%s \n", @@ -365,14 +498,12 @@ return 0; } -static void __exit microcode_exit(void) +static void __exit microcode_exit (void) { misc_deregister(µcode_dev); - kfree(mc_applied); printk(KERN_INFO "IA-32 Microcode Update Driver v%s unregistered\n", MICROCODE_VERSION); } module_init(microcode_init) module_exit(microcode_exit) - diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c Fri Oct 17 14:43:50 2003 +++ b/arch/i386/kernel/mpparse.c Fri Oct 17 14:43:50 2003 @@ -337,6 +337,16 @@ } } } + +static inline void mps_oem_check(struct mp_config_table *mpc, char *oem, + char *productid) +{ + if (strncmp(oem, "IBM NUMA", 8)) + printk("Warning! May not be a NUMA-Q system!\n"); + if (mpc->mpc_oemptr) + smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr, + mpc->mpc_oemsize); +} #endif /* CONFIG_X86_NUMAQ */ /* diff -Nru a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c --- a/arch/i386/kernel/timers/timer_tsc.c Fri Oct 17 14:43:50 2003 +++ b/arch/i386/kernel/timers/timer_tsc.c Fri Oct 17 14:43:50 2003 @@ -321,7 +321,7 @@ { struct cpufreq_freqs *freq = data; - write_seqlock(&xtime_lock); + write_seqlock_irq(&xtime_lock); if (!ref_freq) { ref_freq = freq->old; loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; @@ -342,7 +342,7 @@ } #endif } - write_sequnlock(&xtime_lock); + write_sequnlock_irq(&xtime_lock); return 0; } diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Fri Oct 17 14:43:50 2003 +++ b/arch/i386/kernel/traps.c Fri Oct 17 14:43:50 2003 @@ -104,7 +104,7 @@ #ifdef CONFIG_KALLSYMS printk("\n"); #endif - while (((long) stack & (THREAD_SIZE-1)) != 0) { + while (!kstack_end(stack)) { addr = *stack++; if (kernel_text_address(addr)) { printk(" [<%08lx>] ", addr); @@ -138,7 +138,7 @@ stack = esp; for(i = 0; i < kstack_depth_to_print; i++) { - if (((long) stack & (THREAD_SIZE-1)) == 0) + if (kstack_end(stack)) break; if (i && ((i % 8) == 0)) printk("\n "); @@ -374,6 +374,9 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { + if (regs->eflags & X86_EFLAGS_IF) + local_irq_enable(); + if (regs->eflags & VM_MASK) goto gp_in_vm86; @@ -386,6 +389,7 @@ return; gp_in_vm86: + local_irq_enable(); handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); return; diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c Fri Oct 17 14:43:50 2003 +++ b/arch/i386/mm/fault.c Fri Oct 17 14:43:50 2003 @@ -19,6 +19,7 @@ #include #include #include /* For unblank_screen() */ +#include #include #include @@ -55,6 +56,147 @@ console_loglevel = loglevel_save; } +/* + * Return EIP plus the CS segment base. The segment limit is also + * adjusted, clamped to the kernel/user address space (whichever is + * appropriate), and returned in *eip_limit. + * + * The segment is checked, because it might have been changed by another + * task between the original faulting instruction and here. + * + * If CS is no longer a valid code segment, or if EIP is beyond the + * limit, or if it is a kernel address when CS is not a kernel segment, + * then the returned value will be greater than *eip_limit. + * + * This is slow, but is very rarely executed. + */ +static inline unsigned long get_segment_eip(struct pt_regs *regs, + unsigned long *eip_limit) +{ + unsigned long eip = regs->eip; + unsigned seg = regs->xcs & 0xffff; + u32 seg_ar, seg_limit, base, *desc; + + /* The standard kernel/user address space limit. */ + *eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg; + + /* Unlikely, but must come before segment checks. */ + if (unlikely((regs->eflags & VM_MASK) != 0)) + return eip + (seg << 4); + + /* By far the most common cases. */ + if (likely(seg == __USER_CS || seg == __KERNEL_CS)) + return eip; + + /* Check the segment exists, is within the current LDT/GDT size, + that kernel/user (ring 0..3) has the appropriate privilege, + that it's a code segment, and get the limit. */ + __asm__ ("larl %3,%0; lsll %3,%1" + : "=&r" (seg_ar), "=r" (seg_limit) : "0" (0), "rm" (seg)); + if ((~seg_ar & 0x9800) || eip > seg_limit) { + *eip_limit = 0; + return 1; /* So that returned eip > *eip_limit. */ + } + + /* Get the GDT/LDT descriptor base. + When you look for races in this code remember that + LDT and other horrors are only used in user space. */ + if (seg & (1<<2)) { + /* Must lock the LDT while reading it. */ + down(¤t->mm->context.sem); + desc = current->mm->context.ldt; + desc = (void *)desc + (seg & ~7); + } else { + /* Must disable preemption while reading the GDT. */ + desc = (u32 *)&cpu_gdt_table[get_cpu()]; + desc = (void *)desc + (seg & ~7); + } + + /* Decode the code segment base from the descriptor */ + base = (desc[0] >> 16) | + ((desc[1] & 0xff) << 16) | + (desc[1] & 0xff000000); + + if (seg & (1<<2)) { + up(¤t->mm->context.sem); + } else + put_cpu(); + + /* Adjust EIP and segment limit, and clamp at the kernel limit. + It's legitimate for segments to wrap at 0xffffffff. */ + seg_limit += base; + if (seg_limit < *eip_limit && seg_limit >= base) + *eip_limit = seg_limit; + return eip + base; +} + +/* + * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch. + * Check that here and ignore it. + */ +static int __is_prefetch(struct pt_regs *regs, unsigned long addr) +{ + unsigned long limit; + unsigned long instr = get_segment_eip (regs, &limit); + int scan_more = 1; + int prefetch = 0; + int i; + + for (i = 0; scan_more && i < 15; i++) { + unsigned char opcode; + unsigned char instr_hi; + unsigned char instr_lo; + + if (instr > limit) + break; + if (__get_user(opcode, (unsigned char *) instr)) + break; + + instr_hi = opcode & 0xf0; + instr_lo = opcode & 0x0f; + instr++; + + switch (instr_hi) { + case 0x20: + case 0x30: + /* Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes. */ + scan_more = ((instr_lo & 7) == 0x6); + break; + + case 0x60: + /* 0x64 thru 0x67 are valid prefixes in all modes. */ + scan_more = (instr_lo & 0xC) == 0x4; + break; + case 0xF0: + /* 0xF0, 0xF2, and 0xF3 are valid prefixes */ + scan_more = !instr_lo || (instr_lo>>1) == 1; + break; + case 0x00: + /* Prefetch instruction is 0x0F0D or 0x0F18 */ + scan_more = 0; + if (instr > limit) + break; + if (__get_user(opcode, (unsigned char *) instr)) + break; + prefetch = (instr_lo == 0xF) && + (opcode == 0x0D || opcode == 0x18); + break; + default: + scan_more = 0; + break; + } + } + return prefetch; +} + +static inline int is_prefetch(struct pt_regs *regs, unsigned long addr) +{ + if (unlikely(boot_cpu_data.x86_vendor == X86_VENDOR_AMD && + boot_cpu_data.x86 >= 6)) + return __is_prefetch(regs, addr); + return 0; +} + asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); /* @@ -81,11 +223,13 @@ __asm__("movl %%cr2,%0":"=r" (address)); /* It's safe to allow irq's after cr2 has been saved */ - if (regs->eflags & X86_EFLAGS_IF) + if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) local_irq_enable(); tsk = current; + info.si_code = SEGV_MAPERR; + /* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd. @@ -99,18 +243,24 @@ * (error_code & 4) == 0, and that the fault was not a * protection error (error_code & 1) == 0. */ - if (address >= TASK_SIZE && !(error_code & 5)) - goto vmalloc_fault; + if (unlikely(address >= TASK_SIZE)) { + if (!(error_code & 5)) + goto vmalloc_fault; + /* + * Don't take the mm semaphore here. If we fixup a prefetch + * fault we could otherwise deadlock. + */ + goto bad_area_nosemaphore; + } mm = tsk->mm; - info.si_code = SEGV_MAPERR; /* * If we're in an interrupt, have no user context or are running in an * atomic region then we must not take the fault.. */ if (in_atomic() || !mm) - goto no_context; + goto bad_area_nosemaphore; down_read(&mm->mmap_sem); @@ -198,8 +348,16 @@ bad_area: up_read(&mm->mmap_sem); +bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { + /* + * Valid to do another page fault here because this one came + * from user space. + */ + if (is_prefetch(regs, address)) + return; + tsk->thread.cr2 = address; tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; @@ -232,6 +390,14 @@ if (fixup_exception(regs)) return; + /* + * Valid to do another page fault here, because if this fault + * had been triggered by is_prefetch fixup_exception would have + * handled it. + */ + if (is_prefetch(regs, address)) + return; + /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. @@ -286,10 +452,14 @@ do_sigbus: up_read(&mm->mmap_sem); - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ + /* Kernel mode? Handle exceptions or die */ + if (!(error_code & 4)) + goto no_context; + + /* User space => ok to do another page fault */ + if (is_prefetch(regs, address)) + return; + tsk->thread.cr2 = address; tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; @@ -298,10 +468,6 @@ info.si_code = BUS_ADRERR; info.si_addr = (void *)address; force_sig_info(SIGBUS, &info, tsk); - - /* Kernel mode? Handle exceptions or die */ - if (!(error_code & 4)) - goto no_context; return; vmalloc_fault: diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Fri Oct 17 14:43:51 2003 +++ b/arch/ia64/Kconfig Fri Oct 17 14:43:51 2003 @@ -57,6 +57,10 @@ config IA64_GENERIC bool "generic" + select NUMA + select ACPI_NUMA + select VIRTUAL_MEM_MAP + select DISCONTIGMEM ---help--- This selects the system type of your hardware. A "generic" kernel will run on any supported IA-64 system. However, if you configure @@ -220,24 +224,8 @@ Access). This option is for configuring high-end multiprocessor server systems. If in doubt, say N. -choice - prompt "Maximum Memory per NUMA Node" if NUMA && IA64_DIG - depends on NUMA && IA64_DIG - default IA64_NODESIZE_16GB - -config IA64_NODESIZE_16GB - bool "16GB" - -config IA64_NODESIZE_64GB - bool "64GB" - -config IA64_NODESIZE_256GB - bool "256GB" - -endchoice - config DISCONTIGMEM - bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA + bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA && VIRTUAL_MEM_MAP default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA help Say Y to support efficient handling of discontiguous physical memory, @@ -250,14 +238,10 @@ default y if !IA64_HP_SIM help Say Y to compile the kernel with support for a virtual mem map. - This is an alternate method of supporting large holes in the - physical address space on non NUMA machines. Since the DISCONTIGMEM - option is not supported on machines with the ZX1 chipset, this is - the only way of supporting more than 1 Gb of memory on those - machines. This code also only takes effect if a memory hole of - greater than 1 Gb is found during boot, so it is safe to enable - unless you require the DISCONTIGMEM option for your machine. If you - are unsure, say Y. + This code also only takes effect if a memory hole of greater than + 1 Gb is found during boot. You must turn this option on if you + require the DISCONTIGMEM option for your machine. If you are + unsure, say Y. config IA64_MCA bool "Enable IA-64 Machine Check Abort" diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/Makefile Fri Oct 17 14:43:50 2003 @@ -64,7 +64,7 @@ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ -drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ +drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/ drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/ boot := arch/ia64/hp/sim/boot diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c --- a/arch/ia64/ia32/sys_ia32.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/ia32/sys_ia32.c Fri Oct 17 14:43:50 2003 @@ -2486,11 +2486,14 @@ putstat64 (struct stat64 *ubuf, struct kstat *kbuf) { int err; + u64 hdev; if (clear_user(ubuf, sizeof(*ubuf))) return -EFAULT; - err = __put_user(huge_encode_dev(kbuf->dev), &ubuf->st_dev); + hdev = huge_encode_dev(kbuf->dev); + err = __put_user(hdev, (u32*)&ubuf->st_dev); + err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_dev) + 1); err |= __put_user(kbuf->ino, &ubuf->__st_ino); err |= __put_user(kbuf->ino, &ubuf->st_ino_lo); err |= __put_user(kbuf->ino >> 32, &ubuf->st_ino_hi); @@ -2498,7 +2501,9 @@ err |= __put_user(kbuf->nlink, &ubuf->st_nlink); err |= __put_user(kbuf->uid, &ubuf->st_uid); err |= __put_user(kbuf->gid, &ubuf->st_gid); - err |= __put_user(huge_encode_dev(kbuf->rdev), &ubuf->st_rdev); + hdev = huge_encode_dev(kbuf->rdev); + err = __put_user(hdev, (u32*)&ubuf->st_rdev); + err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_rdev) + 1); err |= __put_user(kbuf->size, &ubuf->st_size_lo); err |= __put_user((kbuf->size >> 32), &ubuf->st_size_hi); err |= __put_user(kbuf->atime.tv_sec, &ubuf->st_atime); @@ -2724,8 +2729,8 @@ struct epoll_event32 { u32 events; - u64 data; -} __attribute__((packed)); + u32 data[2]; +}; asmlinkage long sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 *event) @@ -2740,10 +2745,10 @@ return error; __get_user(event64.events, &event->events); - __get_user(data_halfword, (u32*)(&event->data)); + __get_user(data_halfword, &event->data[0]); event64.data = data_halfword; - __get_user(data_halfword, ((u32*)(&event->data) + 1)); - event64.data |= ((u64)data_halfword) << 32; + __get_user(data_halfword, &event->data[1]); + event64.data |= (u64)data_halfword << 32; set_fs(KERNEL_DS); error = sys_epoll_ctl(epfd, op, fd, &event64); @@ -2758,8 +2763,9 @@ { struct epoll_event *events64 = NULL; mm_segment_t old_fs = get_fs(); - int error; + int error, numevents, size; int evt_idx; + int do_free_pages = 0; if (maxevents <= 0) { return -EINVAL; @@ -2770,43 +2776,45 @@ maxevents * sizeof(struct epoll_event32)))) return error; - /* Allocate the space needed for the intermediate copy */ - events64 = kmalloc(maxevents * sizeof(struct epoll_event), GFP_KERNEL); + /* + * Allocate space for the intermediate copy. If the space needed + * is large enough to cause kmalloc to fail, then try again with + * __get_free_pages. + */ + size = maxevents * sizeof(struct epoll_event); + events64 = kmalloc(size, GFP_KERNEL); if (events64 == NULL) { - return -ENOMEM; - } - - /* Expand the 32-bit structures into the 64-bit structures */ - for (evt_idx = 0; evt_idx < maxevents; evt_idx++) { - u32 data_halfword; - __get_user(events64[evt_idx].events, &events[evt_idx].events); - __get_user(data_halfword, (u32*)(&events[evt_idx].data)); - events64[evt_idx].data = data_halfword; - __get_user(data_halfword, ((u32*)(&events[evt_idx].data) + 1)); - events64[evt_idx].data |= ((u64)data_halfword) << 32; + events64 = (struct epoll_event *) + __get_free_pages(GFP_KERNEL, get_order(size)); + if (events64 == NULL) + return -ENOMEM; + do_free_pages = 1; } /* Do the system call */ set_fs(KERNEL_DS); /* copy_to/from_user should work on kernel mem*/ - error = sys_epoll_wait(epfd, events64, maxevents, timeout); + numevents = sys_epoll_wait(epfd, events64, maxevents, timeout); set_fs(old_fs); /* Don't modify userspace memory if we're returning an error */ - if (!error) { + if (numevents > 0) { /* Translate the 64-bit structures back into the 32-bit structures */ - for (evt_idx = 0; evt_idx < maxevents; evt_idx++) { + for (evt_idx = 0; evt_idx < numevents; evt_idx++) { __put_user(events64[evt_idx].events, &events[evt_idx].events); - __put_user((u32)(events64[evt_idx].data), - (u32*)(&events[evt_idx].data)); + __put_user((u32)events64[evt_idx].data, + &events[evt_idx].data[0]); __put_user((u32)(events64[evt_idx].data >> 32), - ((u32*)(&events[evt_idx].data) + 1)); + &events[evt_idx].data[1]); } } - kfree(events64); - return error; + if (do_free_pages) + free_pages((unsigned long) events64, get_order(size)); + else + kfree(events64); + return numevents; } #ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */ diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/acpi.c Fri Oct 17 14:43:50 2003 @@ -56,6 +56,7 @@ void (*pm_power_off) (void); unsigned char acpi_kbd_controller_present = 1; +unsigned char acpi_legacy_devices; int acpi_disabled; /* XXX this shouldn't be needed---we can't boot without ACPI! */ @@ -380,7 +381,7 @@ void __init acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma) { - unsigned long paddr, size, hole_size, min_hole_size; + unsigned long paddr, size; u8 pxm; struct node_memblk_s *p, *q, *pend; @@ -402,34 +403,6 @@ 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(KERN_ERR "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); @@ -454,6 +427,12 @@ { int i, j, node_from, node_to; + /* If there's no SRAT, fix the phys_id */ + if (srat_num_cpus == 0) { + node_cpuid[0].phys_id = hard_smp_processor_id(); + return; + } + /* calculate total number of nodes in system from PXM bitmap */ numnodes = 0; /* init total nodes in system */ @@ -531,6 +510,9 @@ if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER)) acpi_kbd_controller_present = 0; + if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES) + acpi_legacy_devices = 1; + acpi_register_irq(fadt->sci_int, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE); return 0; } @@ -614,6 +596,12 @@ smp_build_cpu_map(); # ifdef CONFIG_NUMA + if (srat_num_cpus == 0) { + int cpu, i = 1; + for (cpu = 0; cpu < smp_boot_data.cpu_count; cpu++) + if (smp_boot_data.cpu_phys_id[cpu] != hard_smp_processor_id()) + node_cpuid[i++].phys_id = smp_boot_data.cpu_phys_id[cpu]; + } build_cpu_to_node_map(); # endif #endif diff -Nru a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c --- a/arch/ia64/kernel/asm-offsets.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/asm-offsets.c Fri Oct 17 14:43:50 2003 @@ -33,16 +33,30 @@ BLANK(); + DEFINE(IA64_TASK_BLOCKED_OFFSET,offsetof (struct task_struct, blocked)); DEFINE(IA64_TASK_CLEAR_CHILD_TID_OFFSET,offsetof (struct task_struct, clear_child_tid)); DEFINE(IA64_TASK_GROUP_LEADER_OFFSET, offsetof (struct task_struct, group_leader)); + DEFINE(IA64_TASK_PENDING_OFFSET,offsetof (struct task_struct, pending)); DEFINE(IA64_TASK_PID_OFFSET, offsetof (struct task_struct, pid)); DEFINE(IA64_TASK_REAL_PARENT_OFFSET, offsetof (struct task_struct, real_parent)); + DEFINE(IA64_TASK_SIGHAND_OFFSET,offsetof (struct task_struct, sighand)); + DEFINE(IA64_TASK_SIGNAL_OFFSET,offsetof (struct task_struct, signal)); DEFINE(IA64_TASK_TGID_OFFSET, offsetof (struct task_struct, tgid)); DEFINE(IA64_TASK_THREAD_KSP_OFFSET, offsetof (struct task_struct, thread.ksp)); DEFINE(IA64_TASK_THREAD_ON_USTACK_OFFSET, offsetof (struct task_struct, thread.on_ustack)); BLANK(); + DEFINE(IA64_SIGHAND_SIGLOCK_OFFSET,offsetof (struct sighand_struct, siglock)); + + BLANK(); + + DEFINE(IA64_SIGNAL_GROUP_STOP_COUNT_OFFSET,offsetof (struct signal_struct, + group_stop_count)); + DEFINE(IA64_SIGNAL_SHARED_PENDING_OFFSET,offsetof (struct signal_struct, shared_pending)); + + BLANK(); + DEFINE(IA64_PT_REGS_B6_OFFSET, offsetof (struct pt_regs, b6)); DEFINE(IA64_PT_REGS_B7_OFFSET, offsetof (struct pt_regs, b7)); DEFINE(IA64_PT_REGS_AR_CSD_OFFSET, offsetof (struct pt_regs, ar_csd)); @@ -155,6 +169,10 @@ DEFINE(IA64_SIGCONTEXT_R12_OFFSET, offsetof (struct sigcontext, sc_gr[12])); DEFINE(IA64_SIGCONTEXT_RBS_BASE_OFFSET,offsetof (struct sigcontext, sc_rbs_base)); DEFINE(IA64_SIGCONTEXT_LOADRS_OFFSET, offsetof (struct sigcontext, sc_loadrs)); + + BLANK(); + + DEFINE(IA64_SIGPENDING_SIGNAL_OFFSET, offsetof (struct sigpending, signal)); BLANK(); diff -Nru a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S --- a/arch/ia64/kernel/fsys.S Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/fsys.S Fri Oct 17 14:43:50 2003 @@ -4,6 +4,7 @@ * Copyright (C) 2003 Hewlett-Packard Co * David Mosberger-Tang * + * 25-Sep-03 davidm Implement fsys_rt_sigprocmask(). * 18-Feb-03 louisk Implement fsys_gettimeofday(). * 28-Feb-03 davidm Fixed several bugs in fsys_gettimeofday(). Tuned it some more, * probably broke it along the way... ;-) @@ -15,6 +16,7 @@ #include #include #include +#include #include #include @@ -48,8 +50,7 @@ .body mov r8=ENOSYS mov r10=-1 - MCKINLEY_E9_WORKAROUND - br.ret.sptk.many b6 + FSYS_RETURN END(fsys_ni_syscall) ENTRY(fsys_getpid) @@ -66,8 +67,7 @@ ;; cmp.ne p8,p0=0,r9 (p8) br.spnt.many fsys_fallback_syscall - MCKINLEY_E9_WORKAROUND - br.ret.sptk.many b6 + FSYS_RETURN END(fsys_getpid) ENTRY(fsys_getppid) @@ -114,8 +114,7 @@ mov r18=0 // i must not leak kernel bits... mov r19=0 // i must not leak kernel bits... #endif - MCKINLEY_E9_WORKAROUND - br.ret.sptk.many b6 + FSYS_RETURN END(fsys_getppid) ENTRY(fsys_set_tid_address) @@ -141,8 +140,7 @@ ;; mov r17=0 // i must not leak kernel bits... mov r18=0 // i must not leak kernel bits... - MCKINLEY_E9_WORKAROUND - br.ret.sptk.many b6 + FSYS_RETURN END(fsys_set_tid_address) /* @@ -199,7 +197,7 @@ adds r10=IA64_CPUINFO_ITM_DELTA_OFFSET, r10 (p7) tnat.nz p6,p0=r33 -(p6) br.cond.spnt.few .fail +(p6) br.cond.spnt.few .fail_einval adds r8=IA64_CPUINFO_NSEC_PER_CYC_OFFSET, r3 movl r24=2361183241434822607 // for division hack (only for / 1000) @@ -225,8 +223,8 @@ * to store the result. That's OK as long as the stores are also * protect by EX(). */ -EX(.fail, probe.w.fault r32, 3) // this must come _after_ NaT-check -EX(.fail, probe.w.fault r10, 3) // this must come _after_ NaT-check +EX(.fail_efault, probe.w.fault r32, 3) // this must come _after_ NaT-check +EX(.fail_efault, probe.w.fault r10, 3) // this must come _after_ NaT-check nop 0 ldf8 f10=[r8] // f10 <- local_cpu_data->nsec_per_cyc value @@ -311,14 +309,13 @@ (p7) br.spnt.many 1b // finally: r2 = sec, r3 = usec -EX(.fail, st8 [r32]=r2) +EX(.fail_efault, st8 [r32]=r2) adds r9=8, r32 mov r8=r0 // success ;; -EX(.fail, st8 [r9]=r3) // store them in the timeval struct +EX(.fail_efault, st8 [r9]=r3) // store them in the timeval struct mov r10=0 - MCKINLEY_E9_WORKAROUND - br.ret.sptk.many b6 // return to caller + FSYS_RETURN /* * Note: We are NOT clearing the scratch registers here. Since the only things * in those registers are time-related variables and some addresses (which @@ -326,12 +323,183 @@ * and we should be fine. */ -.fail: adds r8=EINVAL, r0 // r8 = EINVAL - adds r10=-1, r0 // r10 = -1 - MCKINLEY_E9_WORKAROUND - br.ret.spnt.many b6 // return with r8 set to EINVAL +.fail_einval: + mov r8=EINVAL // r8 = EINVAL + mov r10=-1 // r10 = -1 + FSYS_RETURN + +.fail_efault: + mov r8=EFAULT // r8 = EFAULT + mov r10=-1 // r10 = -1 + FSYS_RETURN END(fsys_gettimeofday) +/* + * long fsys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, size_t sigsetsize). + */ +#if _NSIG_WORDS != 1 +# error Sorry, fsys_rt_sigprocmask() needs to be updated for _NSIG_WORDS != 1. +#endif +ENTRY(fsys_rt_sigprocmask) + .prologue + .altrp b6 + .body + + mf // ensure reading of current->blocked is ordered + add r2=IA64_TASK_BLOCKED_OFFSET,r16 + add r9=TI_FLAGS+IA64_TASK_SIZE,r16 + ;; + /* + * Since we're only reading a single word, we can do it + * atomically without acquiring current->sighand->siglock. To + * be on the safe side, we need a fully-ordered load, though: + */ + ld8.acq r3=[r2] // read/prefetch current->blocked + ld4 r9=[r9] + add r31=IA64_TASK_SIGHAND_OFFSET,r16 + ;; +#ifdef CONFIG_SMP + ld8 r31=[r31] // r31 <- current->sighand +#endif + and r9=TIF_ALLWORK_MASK,r9 + tnat.nz p6,p0=r32 + ;; + cmp.ne p7,p0=0,r9 + tnat.nz.or p6,p0=r35 + tnat.nz p8,p0=r34 + ;; + cmp.ne p15,p0=r0,r34 // oset != NULL? + cmp.ne.or p6,p0=_NSIG_WORDS*8,r35 + tnat.nz.or p8,p0=r33 + +(p6) br.spnt.few .fail_einval // fail with EINVAL +(p7) br.spnt.many fsys_fallback_syscall // got pending kernel work... +(p8) br.spnt.few .fail_efault // fail with EFAULT + ;; + + cmp.eq p6,p7=r0,r33 // set == NULL? + add r31=IA64_SIGHAND_SIGLOCK_OFFSET,r31 // r31 <- current->sighand->siglock +(p6) br.dpnt.many .store_mask // -> short-circuit to just reading the signal mask + + /* Argh, we actually have to do some work and _update_ the signal mask: */ + +EX(.fail_efault, probe.r.fault r33, 3) // verify user has read-access to *set +EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set + mov r17=(1 << (SIGKILL - 1)) | (1 << (SIGSTOP - 1)) + ;; + + rsm psr.i // mask interrupt delivery + mov ar.ccv=0 + andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP + +#ifdef CONFIG_SMP + mov r17=1 + ;; + cmpxchg4.acq r18=[r31],r17,ar.ccv // try to acquire the lock + mov r8=EINVAL // default to EINVAL + ;; + ld8 r3=[r2] // re-read current->blocked now that we hold the lock + cmp4.ne p6,p0=r18,r0 +(p6) br.cond.spnt.many .lock_contention + ;; +#else + ld8 r3=[r2] // re-read current->blocked now that we hold the lock + mov r8=EINVAL // default to EINVAL +#endif + add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16 + add r19=IA64_TASK_SIGNAL_OFFSET,r16 + cmp4.eq p6,p0=SIG_BLOCK,r32 + ;; + ld8 r19=[r19] // r19 <- current->signal + cmp4.eq p7,p0=SIG_UNBLOCK,r32 + cmp4.eq p8,p0=SIG_SETMASK,r32 + ;; + ld8 r18=[r18] // r18 <- current->pending.signal + .pred.rel.mutex p6,p7,p8 +(p6) or r3=r3,r14 // SIG_BLOCK +(p7) andcm r3=r3,r14 // SIG_UNBLOCK + +(p8) mov r3=r14 // SIG_SETMASK +(p6) mov r8=0 // clear error code + // recalc_sigpending() + add r17=IA64_SIGNAL_GROUP_STOP_COUNT_OFFSET,r19 + + add r19=IA64_SIGNAL_SHARED_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r19 + ;; + ld4 r17=[r17] // r17 <- current->signal->group_stop_count +(p7) mov r8=0 // clear error code + + ld8 r19=[r19] // r19 <- current->signal->shared_pending + ;; + cmp4.gt p6,p7=r17,r0 // p6/p7 <- (current->signal->group_stop_count > 0)? +(p8) mov r8=0 // clear error code + + or r18=r18,r19 // r18 <- current->pending | current->signal->shared_pending + ;; + // r18 <- (current->pending | current->signal->shared_pending) & ~current->blocked: + andcm r18=r18,r3 + add r9=TI_FLAGS+IA64_TASK_SIZE,r16 + ;; + +(p7) cmp.ne.or.andcm p6,p7=r18,r0 // p6/p7 <- signal pending + mov r19=0 // i must not leak kernel bits... +(p6) br.cond.dpnt.many .sig_pending + ;; + +1: ld4 r17=[r9] // r17 <- current->thread_info->flags + ;; + mov ar.ccv=r17 + and r18=~_TIF_SIGPENDING,r17 // r18 <- r17 & ~(1 << TIF_SIGPENDING) + ;; + + st8 [r2]=r3 // update current->blocked with new mask + cmpxchg4.acq r14=[r9],r18,ar.ccv // current->thread_info->flags <- r18 + ;; + cmp.ne p6,p0=r17,r14 // update failed? +(p6) br.cond.spnt.few 1b // yes -> retry + +#ifdef CONFIG_SMP + st4.rel [r31]=r0 // release the lock +#endif + ssm psr.i + cmp.ne p9,p0=r8,r0 // check for bad HOW value + ;; + + srlz.d // ensure psr.i is set again + mov r18=0 // i must not leak kernel bits... +(p9) br.spnt.few .fail_einval // bail out for bad HOW value + +.store_mask: +EX(.fail_efault, (p15) probe.w.fault r34, 3) // verify user has write-access to *oset +EX(.fail_efault, (p15) st8 [r34]=r3) + mov r2=0 // i must not leak kernel bits... + mov r3=0 // i must not leak kernel bits... + mov r8=0 // return 0 + mov r9=0 // i must not leak kernel bits... + mov r14=0 // i must not leak kernel bits... + mov r17=0 // i must not leak kernel bits... + mov r31=0 // i must not leak kernel bits... + FSYS_RETURN + +.sig_pending: +#ifdef CONFIG_SMP + st4.rel [r31]=r0 // release the lock +#endif + ssm psr.i + ;; + srlz.d + br.sptk.many fsys_fallback_syscall // with signal pending, do the heavy-weight syscall + +#ifdef CONFIG_SMP +.lock_contention: + /* Rather than spinning here, fall back on doing a heavy-weight syscall. */ + ssm psr.i + ;; + srlz.d + br.sptk.many fsys_fallback_syscall +#endif +END(fsys_rt_sigprocmask) + ENTRY(fsys_fallback_syscall) .prologue .altrp b6 @@ -600,7 +768,7 @@ data8 0 // sigaltstack data8 0 // rt_sigaction data8 0 // rt_sigpending - data8 0 // rt_sigprocmask + data8 fsys_rt_sigprocmask // rt_sigprocmask data8 0 // rt_sigqueueinfo // 1180 data8 0 // rt_sigreturn data8 0 // rt_sigsuspend diff -Nru a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S --- a/arch/ia64/kernel/gate.S Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/gate.S Fri Oct 17 14:43:50 2003 @@ -118,8 +118,7 @@ mov r10=-1 mov r8=ENOSYS - MCKINLEY_E9_WORKAROUND - br.ret.sptk.many b6 + FSYS_RETURN END(__kernel_syscall_via_epc) # define ARG0_OFF (16 + IA64_SIGFRAME_ARG0_OFFSET) diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S --- a/arch/ia64/kernel/head.S Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/head.S Fri Oct 17 14:43:50 2003 @@ -797,6 +797,25 @@ br.ret.sptk.many rp END(ia64_switch_mode_virt) +GLOBAL_ENTRY(ia64_delay_loop) + .prologue +{ nop 0 // work around GAS unwind info generation bug... + .save ar.lc,r2 + mov r2=ar.lc + .body + ;; + mov ar.lc=r32 +} + ;; + // force loop to be 32-byte aligned (GAS bug means we cannot use .align + // inside function body without corrupting unwind info). +{ nop 0 } +1: br.cloop.sptk.few 1b + ;; + mov ar.lc=r2 + br.ret.sptk.many rp +END(ia64_delay_loop) + #ifdef CONFIG_IA64_BRL_EMU /* diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/mca.c Fri Oct 17 14:43:50 2003 @@ -81,8 +81,6 @@ u64 ia64_mca_sal_data_area[1356]; u64 ia64_tlb_functional; u64 ia64_os_mca_recovery_successful; -/* TODO: need to assign min-state structure to UC memory */ -u64 ia64_mca_min_state_save_info[MIN_STATE_AREA_SIZE] __attribute__((aligned(512))); static void ia64_mca_wakeup_ipi_wait(void); static void ia64_mca_wakeup(int cpu); static void ia64_mca_wakeup_all(void); @@ -466,26 +464,6 @@ #endif /* PLATFORM_MCA_HANDLERS */ /* - * routine to process and prepare to dump min_state_save - * information for debugging purposes. - */ -void -ia64_process_min_state_save (pal_min_state_area_t *pmss) -{ - int i, max = MIN_STATE_AREA_SIZE; - u64 *tpmss_ptr = (u64 *)pmss; - u64 *return_min_state_ptr = ia64_mca_min_state_save_info; - - for (i=0;ivalid.psi_static_struct) { spsi = (sal_processor_static_info_t *)p_data; - - /* copy interrupted context PAL min-state info */ - ia64_process_min_state_save(&spsi->min_state_area); /* Print branch register contents if valid */ if (spsi->valid.br) diff -Nru a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S --- a/arch/ia64/kernel/mca_asm.S Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/mca_asm.S Fri Oct 17 14:43:50 2003 @@ -77,12 +77,11 @@ (p6) movl r10=IA64_MCA_SAME_CONTEXT; \ (p6) add _tmp=0x18,_tmp;; \ (p6) ld8 r9=[_tmp],0x10; \ -(p6) movl r22=ia64_mca_min_state_save_info;; \ +(p6) mov r22=r0;; \ (p7) ld8 r8=[_tmp],0x08;; \ (p7) ld8 r9=[_tmp],0x08;; \ (p7) ld8 r10=[_tmp],0x08;; \ -(p7) ld8 r22=[_tmp],0x08;; \ - DATA_VA_TO_PA(r22) +(p7) ld8 r22=[_tmp],0x08;; // now _tmp is pointing to SAL rtn save location @@ -97,7 +96,6 @@ .global ia64_init_stack .global ia64_mca_sal_data_area .global ia64_tlb_functional - .global ia64_mca_min_state_save_info .text .align 16 @@ -265,15 +263,15 @@ add r4=8,r2 // duplicate r2 in r4 add r6=2*8,r2 // duplicate r2 in r4 - mov r3=cr0 // cr.dcr - mov r5=cr1 // cr.itm - mov r7=cr2;; // cr.iva + mov r3=cr.dcr + mov r5=cr.itm + mov r7=cr.iva;; st8 [r2]=r3,8*8 st8 [r4]=r5,3*8 st8 [r6]=r7,3*8;; // 48 byte rements - mov r3=cr8;; // cr.pta + mov r3=cr.pta;; st8 [r2]=r3,8*8;; // 64 byte rements // if PSR.ic=0, reading interruption registers causes an illegal operation fault @@ -286,23 +284,23 @@ add r4=8,r2 // duplicate r2 in r4 add r6=2*8,r2 // duplicate r2 in r6 - mov r3=cr16 // cr.ipsr - mov r5=cr17 // cr.isr - mov r7=r0;; // cr.ida => cr18 (reserved) + mov r3=cr.ipsr + mov r5=cr.isr + mov r7=r0;; st8 [r2]=r3,3*8 st8 [r4]=r5,3*8 st8 [r6]=r7,3*8;; - mov r3=cr19 // cr.iip - mov r5=cr20 // cr.idtr - mov r7=cr21;; // cr.iitr + mov r3=cr.iip + mov r5=cr.ifa + mov r7=cr.itir;; st8 [r2]=r3,3*8 st8 [r4]=r5,3*8 st8 [r6]=r7,3*8;; - mov r3=cr22 // cr.iipa - mov r5=cr23 // cr.ifs - mov r7=cr24;; // cr.iim + mov r3=cr.iipa + mov r5=cr.ifs + mov r7=cr.iim;; st8 [r2]=r3,3*8 st8 [r4]=r5,3*8 st8 [r6]=r7,3*8;; @@ -311,104 +309,101 @@ st8 [r2]=r3,160;; // 160 byte rement SkipIntrRegs: - st8 [r2]=r0,168 // another 168 byte . + st8 [r2]=r0,152;; // another 152 byte . - mov r3=cr66;; // cr.lid - st8 [r2]=r3,40 // 40 byte rement + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2 // duplicate r2 in r6 - mov r3=cr71;; // cr.ivr - st8 [r2]=r3,8 - - mov r3=cr72;; // cr.tpr - st8 [r2]=r3,24 // 24 byte increment - - mov r3=r0;; // cr.eoi => cr75 - st8 [r2]=r3,168 // 168 byte inc. - - mov r3=r0;; // cr.irr0 => cr96 - st8 [r2]=r3,16 // 16 byte inc. - - mov r3=r0;; // cr.irr1 => cr98 - st8 [r2]=r3,16 // 16 byte inc. - - mov r3=r0;; // cr.irr2 => cr100 - st8 [r2]=r3,16 // 16 byte inc - - mov r3=r0;; // cr.irr3 => cr100 - st8 [r2]=r3,16 // 16b inc. - - mov r3=r0;; // cr.itv => cr114 - st8 [r2]=r3,16 // 16 byte inc. + mov r3=cr.lid +// mov r5=cr.ivr // cr.ivr, don't read it + mov r7=cr.tpr;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; - mov r3=r0;; // cr.pmv => cr116 - st8 [r2]=r3,8 + mov r3=r0 // cr.eoi => cr67 + mov r5=r0 // cr.irr0 => cr68 + mov r7=r0;; // cr.irr1 => cr69 + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; - mov r3=r0;; // cr.lrr0 => cr117 - st8 [r2]=r3,8 + mov r3=r0 // cr.irr2 => cr70 + mov r5=r0 // cr.irr3 => cr71 + mov r7=cr.itv;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; - mov r3=r0;; // cr.lrr1 => cr118 - st8 [r2]=r3,8 + mov r3=cr.pmv + mov r5=cr.cmcv;; + st8 [r2]=r3,7*8 + st8 [r4]=r5,7*8;; + + mov r3=r0 // cr.lrr0 => cr80 + mov r5=r0;; // cr.lrr1 => cr81 + st8 [r2]=r3,23*8 + st8 [r4]=r5,23*8;; - mov r3=r0;; // cr.cmcv => cr119 - st8 [r2]=r3,8*10;; + adds r2=25*8,r2;; cSaveARs: // save ARs add r4=8,r2 // duplicate r2 in r4 add r6=2*8,r2 // duplicate r2 in r6 - mov r3=ar0 // ar.kro - mov r5=ar1 // ar.kr1 - mov r7=ar2;; // ar.kr2 + mov r3=ar.k0 + mov r5=ar.k1 + mov r7=ar.k2;; st8 [r2]=r3,3*8 st8 [r4]=r5,3*8 st8 [r6]=r7,3*8;; - mov r3=ar3 // ar.kr3 - mov r5=ar4 // ar.kr4 - mov r7=ar5;; // ar.kr5 + mov r3=ar.k3 + mov r5=ar.k4 + mov r7=ar.k5;; st8 [r2]=r3,3*8 st8 [r4]=r5,3*8 st8 [r6]=r7,3*8;; - mov r3=ar6 // ar.kr6 - mov r5=ar7 // ar.kr7 + mov r3=ar.k6 + mov r5=ar.k7 mov r7=r0;; // ar.kr8 st8 [r2]=r3,10*8 st8 [r4]=r5,10*8 st8 [r6]=r7,10*8;; // rement by 72 bytes - mov r3=ar16 // ar.rsc - mov ar16=r0 // put RSE in enforced lazy mode - mov r5=ar17 // ar.bsp + mov r3=ar.rsc + mov ar.rsc=r0 // put RSE in enforced lazy mode + mov r5=ar.bsp ;; - mov r7=ar18;; // ar.bspstore + mov r7=ar.bspstore;; st8 [r2]=r3,3*8 st8 [r4]=r5,3*8 st8 [r6]=r7,3*8;; - mov r3=ar19;; // ar.rnat + mov r3=ar.rnat;; st8 [r2]=r3,8*13 // increment by 13x8 bytes - mov r3=ar32;; // ar.ccv + mov r3=ar.ccv;; st8 [r2]=r3,8*4 - mov r3=ar36;; // ar.unat + mov r3=ar.unat;; st8 [r2]=r3,8*4 - mov r3=ar40;; // ar.fpsr + mov r3=ar.fpsr;; st8 [r2]=r3,8*4 - mov r3=ar44;; // ar.itc + mov r3=ar.itc;; st8 [r2]=r3,160 // 160 - mov r3=ar64;; // ar.pfs + mov r3=ar.pfs;; st8 [r2]=r3,8 - mov r3=ar65;; // ar.lc + mov r3=ar.lc;; st8 [r2]=r3,8 - mov r3=ar66;; // ar.ec + mov r3=ar.ec;; st8 [r2]=r3 add r2=8*62,r2 //padding @@ -417,7 +412,8 @@ movl r4=0x00;; cStRR: - mov r3=rr[r4];; + dep.z r5=r4,61,3;; + mov r3=rr[r5];; st8 [r2]=r3,8 add r4=1,r4 br.cloop.sptk.few cStRR @@ -501,12 +497,12 @@ ld8 r3=[r2],8*8 ld8 r5=[r4],3*8 ld8 r7=[r6],3*8;; // 48 byte increments - mov cr0=r3 // cr.dcr - mov cr1=r5 // cr.itm - mov cr2=r7;; // cr.iva + mov cr.dcr=r3 + mov cr.itm=r5 + mov cr.iva=r7;; ld8 r3=[r2],8*8;; // 64 byte increments -// mov cr8=r3 // cr.pta +// mov cr.pta=r3 // if PSR.ic=1, reading interruption registers causes an illegal operation fault @@ -523,64 +519,66 @@ ld8 r3=[r2],3*8 ld8 r5=[r4],3*8 ld8 r7=[r6],3*8;; - mov cr16=r3 // cr.ipsr - mov cr17=r5 // cr.isr is read only -// mov cr18=r7;; // cr.ida (reserved - don't restore) + mov cr.ipsr=r3 +// mov cr.isr=r5 // cr.isr is read only ld8 r3=[r2],3*8 ld8 r5=[r4],3*8 ld8 r7=[r6],3*8;; - mov cr19=r3 // cr.iip - mov cr20=r5 // cr.idtr - mov cr21=r7;; // cr.iitr + mov cr.iip=r3 + mov cr.ifa=r5 + mov cr.itir=r7;; ld8 r3=[r2],3*8 ld8 r5=[r4],3*8 ld8 r7=[r6],3*8;; - mov cr22=r3 // cr.iipa - mov cr23=r5 // cr.ifs - mov cr24=r7 // cr.iim + mov cr.iipa=r3 + mov cr.ifs=r5 + mov cr.iim=r7 ld8 r3=[r2],160;; // 160 byte increment - mov cr25=r3 // cr.iha + mov cr.iha=r3 rSkipIntrRegs: - ld8 r3=[r2],168;; // another 168 byte inc. - - ld8 r3=[r2],40;; // 40 byte increment - mov cr66=r3 // cr.lid - - ld8 r3=[r2],8;; -// mov cr71=r3 // cr.ivr is read only - ld8 r3=[r2],24;; // 24 byte increment - mov cr72=r3 // cr.tpr - - ld8 r3=[r2],168;; // 168 byte inc. -// mov cr75=r3 // cr.eoi + ld8 r3=[r2],152;; // another 152 byte inc. - ld8 r3=[r2],16;; // 16 byte inc. -// mov cr96=r3 // cr.irr0 is read only + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2;; // duplicate r2 in r6 - ld8 r3=[r2],16;; // 16 byte inc. -// mov cr98=r3 // cr.irr1 is read only + ld8 r3=[r2],8*3 + ld8 r5=[r4],8*3 + ld8 r7=[r6],8*3;; + mov cr.lid=r3 +// mov cr.ivr=r5 // cr.ivr is read only + mov cr.tpr=r7;; + + ld8 r3=[r2],8*3 + ld8 r5=[r4],8*3 + ld8 r7=[r6],8*3;; +// mov cr.eoi=r3 +// mov cr.irr0=r5 // cr.irr0 is read only +// mov cr.irr1=r7;; // cr.irr1 is read only + + ld8 r3=[r2],8*3 + ld8 r5=[r4],8*3 + ld8 r7=[r6],8*3;; +// mov cr.irr2=r3 // cr.irr2 is read only +// mov cr.irr3=r5 // cr.irr3 is read only + mov cr.itv=r7;; + + ld8 r3=[r2],8*7 + ld8 r5=[r4],8*7;; + mov cr.pmv=r3 + mov cr.cmcv=r5;; + + ld8 r3=[r2],8*23 + ld8 r5=[r4],8*23;; + adds r2=8*23,r2 + adds r4=8*23,r4;; +// mov cr.lrr0=r3 +// mov cr.lrr1=r5 - ld8 r3=[r2],16;; // 16 byte inc -// mov cr100=r3 // cr.irr2 is read only - - ld8 r3=[r2],16;; // 16b inc. -// mov cr102=r3 // cr.irr3 is read only - - ld8 r3=[r2],16;; // 16 byte inc. -// mov cr114=r3 // cr.itv - - ld8 r3=[r2],8;; -// mov cr116=r3 // cr.pmv - ld8 r3=[r2],8;; -// mov cr117=r3 // cr.lrr0 - ld8 r3=[r2],8;; -// mov cr118=r3 // cr.lrr1 - ld8 r3=[r2],8*10;; -// mov cr119=r3 // cr.cmcv + adds r2=8*2,r2;; restore_ARs: add r4=8,r2 // duplicate r2 in r4 @@ -589,67 +587,67 @@ ld8 r3=[r2],3*8 ld8 r5=[r4],3*8 ld8 r7=[r6],3*8;; - mov ar0=r3 // ar.kro - mov ar1=r5 // ar.kr1 - mov ar2=r7;; // ar.kr2 + mov ar.k0=r3 + mov ar.k1=r5 + mov ar.k2=r7;; ld8 r3=[r2],3*8 ld8 r5=[r4],3*8 ld8 r7=[r6],3*8;; - mov ar3=r3 // ar.kr3 - mov ar4=r5 // ar.kr4 - mov ar5=r7;; // ar.kr5 + mov ar.k3=r3 + mov ar.k4=r5 + mov ar.k5=r7;; ld8 r3=[r2],10*8 ld8 r5=[r4],10*8 ld8 r7=[r6],10*8;; - mov ar6=r3 // ar.kr6 - mov ar7=r5 // ar.kr7 -// mov ar8=r6 // ar.kr8 + mov ar.k6=r3 + mov ar.k7=r5 ;; ld8 r3=[r2],3*8 ld8 r5=[r4],3*8 ld8 r7=[r6],3*8;; -// mov ar16=r3 // ar.rsc -// mov ar17=r5 // ar.bsp is read only - mov ar16=r0 // make sure that RSE is in enforced lazy mode +// mov ar.rsc=r3 +// mov ar.bsp=r5 // ar.bsp is read only + mov ar.rsc=r0 // make sure that RSE is in enforced lazy mode ;; - mov ar18=r7;; // ar.bspstore + mov ar.bspstore=r7;; ld8 r9=[r2],8*13;; - mov ar19=r9 // ar.rnat + mov ar.rnat=r9 - mov ar16=r3 // ar.rsc + mov ar.rsc=r3 ld8 r3=[r2],8*4;; - mov ar32=r3 // ar.ccv + mov ar.ccv=r3 ld8 r3=[r2],8*4;; - mov ar36=r3 // ar.unat + mov ar.unat=r3 ld8 r3=[r2],8*4;; - mov ar40=r3 // ar.fpsr + mov ar.fpsr=r3 ld8 r3=[r2],160;; // 160 -// mov ar44=r3 // ar.itc +// mov ar.itc=r3 ld8 r3=[r2],8;; - mov ar64=r3 // ar.pfs + mov ar.pfs=r3 ld8 r3=[r2],8;; - mov ar65=r3 // ar.lc + mov ar.lc=r3 ld8 r3=[r2];; - mov ar66=r3 // ar.ec + mov ar.ec=r3 add r2=8*62,r2;; // padding restore_RRs: mov r5=ar.lc mov ar.lc=0x08-1 - movl r4=0x00 + movl r4=0x00;; cStRRr: + dep.z r7=r4,61,3 ld8 r3=[r2],8;; -// mov rr[r4]=r3 // what are its access previledges? + mov rr[r7]=r3 // what are its access previledges? add r4=1,r4 br.cloop.sptk.few cStRRr ;; diff -Nru a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c --- a/arch/ia64/kernel/patch.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/patch.c Fri Oct 17 14:43:50 2003 @@ -130,9 +130,11 @@ while (offp < (s32 *) end) { wp = (u64 *) ia64_imva((char *) offp + *offp); - wp[0] = 0x0000000100000000; + wp[0] = 0x0000000100000000; /* nop.m 0; nop.i 0; nop.i 0 */ wp[1] = 0x0004000000000200; - ia64_fc(wp); + wp[2] = 0x0000000100000011; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */ + wp[3] = 0x0084006880000200; + ia64_fc(wp); ia64_fc(wp + 2); ++offp; } ia64_sync_i(); diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/perfmon.c Fri Oct 17 14:43:50 2003 @@ -140,7 +140,7 @@ * in UP: * - we need to protect against PMU overflow interrupts (local_irq_disable) * - * spin_lock_irqsave()/spin_unlock_irqrestore(): + * spin_lock_irqsave()/spin_lock_irqrestore(): * in SMP: local_irq_disable + spin_lock * in UP : local_irq_disable * @@ -254,7 +254,6 @@ unsigned long seed; /* seed for random-number generator */ unsigned long mask; /* mask for random-number generator */ unsigned int flags; /* notify/do not notify */ - int next_reset_type;/* PFM_PMD_NO_RESET, PFM_PMD_LONG_RESET, PFM_PMD_SHORT_RESET */ unsigned long eventid; /* overflow event identifier */ } pfm_counter_t; @@ -267,10 +266,10 @@ unsigned int using_dbreg:1; /* using range restrictions (debug registers) */ unsigned int is_sampling:1; /* true if using a custom format */ unsigned int excl_idle:1; /* exclude idle task in system wide session */ - unsigned int unsecure:1; /* exclude idle task in system wide session */ unsigned int going_zombie:1; /* context is zombie (MASKED+blocking) */ unsigned int trap_reason:2; /* reason for going into pfm_handle_work() */ unsigned int no_msg:1; /* no message sent on overflow */ + unsigned int can_restart:1; /* allowed to issue a PFM_RESTART */ unsigned int reserved:22; } pfm_context_flags_t; @@ -356,10 +355,10 @@ #define ctx_fl_using_dbreg ctx_flags.using_dbreg #define ctx_fl_is_sampling ctx_flags.is_sampling #define ctx_fl_excl_idle ctx_flags.excl_idle -#define ctx_fl_unsecure ctx_flags.unsecure #define ctx_fl_going_zombie ctx_flags.going_zombie #define ctx_fl_trap_reason ctx_flags.trap_reason #define ctx_fl_no_msg ctx_flags.no_msg +#define ctx_fl_can_restart ctx_flags.can_restart #define PFM_SET_WORK_PENDING(t, v) do { (t)->thread.pfm_needs_checking = v; } while(0); #define PFM_GET_WORK_PENDING(t) (t)->thread.pfm_needs_checking @@ -493,12 +492,11 @@ typedef struct { unsigned long pfm_spurious_ovfl_intr_count; /* keep track of spurious ovfl interrupts */ + unsigned long pfm_replay_ovfl_intr_count; /* keep track of replayed ovfl interrupts */ unsigned long pfm_ovfl_intr_count; /* keep track of ovfl interrupts */ unsigned long pfm_ovfl_intr_cycles; /* cycles spent processing ovfl interrupts */ unsigned long pfm_ovfl_intr_cycles_min; /* min cycles spent processing ovfl interrupts */ unsigned long pfm_ovfl_intr_cycles_max; /* max cycles spent processing ovfl interrupts */ - unsigned long pfm_sysupdt_count; - unsigned long pfm_sysupdt_cycles; unsigned long pfm_smpl_handler_calls; unsigned long pfm_smpl_handler_cycles; char pad[SMP_CACHE_BYTES] ____cacheline_aligned; @@ -513,10 +511,8 @@ static struct proc_dir_entry *perfmon_dir; static pfm_uuid_t pfm_null_uuid = {0,}; -static spinlock_t pfm_smpl_fmt_lock; -static pfm_buffer_fmt_t *pfm_buffer_fmt_list; -#define LOCK_BUF_FMT_LIST() spin_lock(&pfm_smpl_fmt_lock) -#define UNLOCK_BUF_FMT_LIST() spin_unlock(&pfm_smpl_fmt_lock) +static spinlock_t pfm_buffer_fmt_lock; +static LIST_HEAD(pfm_buffer_fmt_list); /* sysctl() controls */ static pfm_sysctl_t pfm_sysctl; @@ -544,14 +540,8 @@ close: pfm_vm_close }; -#define pfm_wait_task_inactive(t) wait_task_inactive(t) #define pfm_get_cpu_var(v) __ia64_per_cpu_var(v) #define pfm_get_cpu_data(a,b) per_cpu(a, b) -typedef irqreturn_t pfm_irq_handler_t; -#define PFM_IRQ_HANDLER_RET(v) do { \ - put_cpu_no_resched(); \ - return IRQ_HANDLED; \ - } while(0); static inline void pfm_put_task(struct task_struct *task) @@ -628,7 +618,6 @@ .get_sb = pfmfs_get_sb, .kill_sb = kill_anon_super, }; - DEFINE_PER_CPU(unsigned long, pfm_syst_info); DEFINE_PER_CPU(struct task_struct *, pmu_owner); DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); @@ -734,12 +723,14 @@ static inline void pfm_write_soft_counter(pfm_context_t *ctx, int i, unsigned long val) { - ctx->ctx_pmds[i].val = val & ~pmu_conf.ovfl_val; + unsigned long ovfl_val = pmu_conf.ovfl_val; + + ctx->ctx_pmds[i].val = val & ~ovfl_val; /* * writing to unimplemented part is ignore, so we do not need to * mask off top part */ - ia64_set_pmd(i, val & pmu_conf.ovfl_val); + ia64_set_pmd(i, val & ovfl_val); } static pfm_msg_t * @@ -870,11 +861,12 @@ { pfm_context_t *ctx = PFM_GET_CTX(task); struct thread_struct *th = &task->thread; - unsigned long mask, val; + unsigned long mask, val, ovfl_mask; int i; - DPRINT(("[%d] masking monitoring for [%d]\n", current->pid, task->pid)); + DPRINT_ovfl(("[%d] masking monitoring for [%d]\n", current->pid, task->pid)); + ovfl_mask = pmu_conf.ovfl_val; /* * monitoring can only be masked as a result of a valid * counter overflow. In UP, it means that the PMU still @@ -904,14 +896,14 @@ /* * we rebuild the full 64 bit value of the counter */ - ctx->ctx_pmds[i].val += (val & pmu_conf.ovfl_val); + ctx->ctx_pmds[i].val += (val & ovfl_mask); } else { ctx->ctx_pmds[i].val = val; } - DPRINT(("pmd[%d]=0x%lx hw_pmd=0x%lx\n", + DPRINT_ovfl(("pmd[%d]=0x%lx hw_pmd=0x%lx\n", i, ctx->ctx_pmds[i].val, - val & pmu_conf.ovfl_val)); + val & ovfl_mask)); } /* * mask monitoring by setting the privilege level to 0 @@ -926,6 +918,7 @@ if ((mask & 0x1) == 0UL) continue; ia64_set_pmc(i, th->pmcs[i] & ~0xfUL); th->pmcs[i] &= ~0xfUL; + DPRINT_ovfl(("pmc[%d]=0x%lx\n", i, th->pmcs[i])); } /* * make all of this visible @@ -943,11 +936,12 @@ { pfm_context_t *ctx = PFM_GET_CTX(task); struct thread_struct *th = &task->thread; - unsigned long mask; + unsigned long mask, ovfl_mask; unsigned long psr, val; int i, is_system; is_system = ctx->ctx_fl_system; + ovfl_mask = pmu_conf.ovfl_val; if (task != current) { printk(KERN_ERR "perfmon.%d: invalid task[%d] current[%d]\n", __LINE__, task->pid, current->pid); @@ -989,8 +983,8 @@ * we split the 64bit value according to * counter width */ - val = ctx->ctx_pmds[i].val & pmu_conf.ovfl_val; - ctx->ctx_pmds[i].val &= ~pmu_conf.ovfl_val; + val = ctx->ctx_pmds[i].val & ovfl_mask; + ctx->ctx_pmds[i].val &= ~ovfl_mask; } else { val = ctx->ctx_pmds[i].val; } @@ -1206,12 +1200,36 @@ return ret; } +static pfm_buffer_fmt_t * +__pfm_find_buffer_fmt(pfm_uuid_t uuid) +{ + struct list_head * pos; + pfm_buffer_fmt_t * entry; - + list_for_each(pos, &pfm_buffer_fmt_list) { + entry = list_entry(pos, pfm_buffer_fmt_t, fmt_list); + if (pfm_uuid_cmp(uuid, entry->fmt_uuid) == 0) + return entry; + } + return NULL; +} + +/* + * find a buffer format based on its uuid + */ +static pfm_buffer_fmt_t * +pfm_find_buffer_fmt(pfm_uuid_t uuid) +{ + pfm_buffer_fmt_t * fmt; + spin_lock(&pfm_buffer_fmt_lock); + fmt = __pfm_find_buffer_fmt(uuid); + spin_unlock(&pfm_buffer_fmt_lock); + return fmt; +} + int pfm_register_buffer_fmt(pfm_buffer_fmt_t *fmt) { - pfm_buffer_fmt_t *p; int ret = 0; /* some sanity checks */ @@ -1224,80 +1242,44 @@ * XXX: need check validity of fmt_arg_size */ - LOCK_BUF_FMT_LIST(); - p = pfm_buffer_fmt_list; - + spin_lock(&pfm_buffer_fmt_lock); - while (p) { - if (pfm_uuid_cmp(fmt->fmt_uuid, p->fmt_uuid) == 0) break; - p = p->fmt_next; - } - - if (p) { + if (__pfm_find_buffer_fmt(fmt->fmt_uuid)) { printk(KERN_ERR "perfmon: duplicate sampling format: %s\n", fmt->fmt_name); ret = -EBUSY; - } else { - fmt->fmt_prev = NULL; - fmt->fmt_next = pfm_buffer_fmt_list; - pfm_buffer_fmt_list = fmt; - printk(KERN_ERR "perfmon: added sampling format %s\n", fmt->fmt_name); - } - UNLOCK_BUF_FMT_LIST(); + goto out; + } + list_add(&fmt->fmt_list, &pfm_buffer_fmt_list); + printk(KERN_INFO "perfmon: added sampling format %s\n", fmt->fmt_name); - return ret; +out: + spin_unlock(&pfm_buffer_fmt_lock); + return ret; } int pfm_unregister_buffer_fmt(pfm_uuid_t uuid) { - pfm_buffer_fmt_t *p; + pfm_buffer_fmt_t *fmt; int ret = 0; - LOCK_BUF_FMT_LIST(); - p = pfm_buffer_fmt_list; - while (p) { - if (memcmp(uuid, p->fmt_uuid, sizeof(pfm_uuid_t)) == 0) break; - p = p->fmt_next; - } - if (p) { - if (p->fmt_prev) - p->fmt_prev->fmt_next = p->fmt_next; - else - pfm_buffer_fmt_list = p->fmt_next; - - if (p->fmt_next) - p->fmt_next->fmt_prev = p->fmt_prev; + spin_lock(&pfm_buffer_fmt_lock); - printk(KERN_ERR "perfmon: removed sampling format: %s\n", p->fmt_name); - p->fmt_next = p->fmt_prev = NULL; - } else { + fmt = __pfm_find_buffer_fmt(uuid); + if (!fmt) { printk(KERN_ERR "perfmon: cannot unregister format, not found\n"); ret = -EINVAL; + goto out; } - UNLOCK_BUF_FMT_LIST(); + list_del_init(&fmt->fmt_list); + printk(KERN_INFO "perfmon: removed sampling format: %s\n", fmt->fmt_name); +out: + spin_unlock(&pfm_buffer_fmt_lock); return ret; } -/* - * find a buffer format based on its uuid - */ -static pfm_buffer_fmt_t * -pfm_find_buffer_fmt(pfm_uuid_t uuid, int nolock) -{ - pfm_buffer_fmt_t *p; - - LOCK_BUF_FMT_LIST(); - for (p = pfm_buffer_fmt_list; p ; p = p->fmt_next) { - if (pfm_uuid_cmp(uuid, p->fmt_uuid) == 0) break; - } - - UNLOCK_BUF_FMT_LIST(); - - return p; -} - static int pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu) { @@ -2113,7 +2095,7 @@ return 1; } static struct dentry_operations pfmfs_dentry_operations = { - .d_delete = pfmfs_delete_dentry, + .d_delete = pfmfs_delete_dentry, }; @@ -2420,7 +2402,7 @@ #define PFM_CTXARG_BUF_ARG(a) (pfm_buffer_fmt_t *)(a+1) /* invoke and lock buffer format, if found */ - fmt = pfm_find_buffer_fmt(arg->ctx_smpl_buf_id, 0); + fmt = pfm_find_buffer_fmt(arg->ctx_smpl_buf_id); if (fmt == NULL) { DPRINT(("[%d] cannot find buffer format\n", task->pid)); return -EINVAL; @@ -2528,8 +2510,7 @@ if (!pfm_uuid_cmp(req->ctx_smpl_buf_id, pfm_null_uuid)) return 0; - /* no buffer locking here, will be called again */ - fmt = pfm_find_buffer_fmt(req->ctx_smpl_buf_id, 1); + fmt = pfm_find_buffer_fmt(req->ctx_smpl_buf_id); if (fmt == NULL) { DPRINT(("cannot find buffer format\n")); return -EINVAL; @@ -2588,7 +2569,7 @@ /* * make sure the task is off any CPU */ - pfm_wait_task_inactive(task); + wait_task_inactive(task); /* more to come... */ @@ -2679,7 +2660,6 @@ */ ctx->ctx_fl_block = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0; ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0; - ctx->ctx_fl_unsecure = (ctx_flags & PFM_FL_UNSECURE) ? 1: 0; ctx->ctx_fl_is_sampling = ctx->ctx_buf_fmt ? 1 : 0; /* assume record() is defined */ ctx->ctx_fl_no_msg = (ctx_flags & PFM_FL_OVFL_NO_MSG) ? 1: 0; /* @@ -2705,13 +2685,12 @@ init_waitqueue_head(&ctx->ctx_msgq_wait); init_waitqueue_head(&ctx->ctx_zombieq); - DPRINT(("ctx=%p flags=0x%x system=%d notify_block=%d excl_idle=%d unsecure=%d no_msg=%d ctx_fd=%d \n", + DPRINT(("ctx=%p flags=0x%x system=%d notify_block=%d excl_idle=%d no_msg=%d ctx_fd=%d \n", ctx, ctx_flags, ctx->ctx_fl_system, ctx->ctx_fl_block, ctx->ctx_fl_excl_idle, - ctx->ctx_fl_unsecure, ctx->ctx_fl_no_msg, ctx->ctx_fd)); @@ -2755,14 +2734,12 @@ } static void -pfm_reset_regs_masked(pfm_context_t *ctx, unsigned long *ovfl_regs, int flag) +pfm_reset_regs_masked(pfm_context_t *ctx, unsigned long *ovfl_regs, int is_long_reset) { unsigned long mask = ovfl_regs[0]; unsigned long reset_others = 0UL; unsigned long val; - int i, is_long_reset = (flag == PFM_PMD_LONG_RESET); - - DPRINT_ovfl(("ovfl_regs=0x%lx flag=%d\n", ovfl_regs[0], flag)); + int i; /* * now restore reset value on sampling overflowed counters @@ -2793,19 +2770,17 @@ } static void -pfm_reset_regs(pfm_context_t *ctx, unsigned long *ovfl_regs, int flag) +pfm_reset_regs(pfm_context_t *ctx, unsigned long *ovfl_regs, int is_long_reset) { unsigned long mask = ovfl_regs[0]; unsigned long reset_others = 0UL; unsigned long val; - int i, is_long_reset = (flag == PFM_PMD_LONG_RESET); - - DPRINT_ovfl(("ovfl_regs=0x%lx flag=%d\n", ovfl_regs[0], flag)); + int i; - if (flag == PFM_PMD_NO_RESET) return; + DPRINT_ovfl(("ovfl_regs=0x%lx is_long_reset=%d\n", ovfl_regs[0], is_long_reset)); if (ctx->ctx_state == PFM_CTX_MASKED) { - pfm_reset_regs_masked(ctx, ovfl_regs, flag); + pfm_reset_regs_masked(ctx, ovfl_regs, is_long_reset); return; } @@ -3084,7 +3059,7 @@ { struct thread_struct *thread = NULL; pfarg_reg_t *req = (pfarg_reg_t *)arg; - unsigned long value, hw_value; + unsigned long value, hw_value, ovfl_mask; unsigned int cnum; int i, can_access_pmu = 0, state; int is_counting, is_loaded, is_system; @@ -3094,6 +3069,7 @@ state = ctx->ctx_state; is_loaded = state == PFM_CTX_LOADED ? 1 : 0; is_system = ctx->ctx_fl_system; + ovfl_mask = pmu_conf.ovfl_val; if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; @@ -3162,22 +3138,21 @@ * when context is load we use the split value */ if (is_loaded) { - hw_value = value & pmu_conf.ovfl_val; - value = value & ~pmu_conf.ovfl_val; + hw_value = value & ovfl_mask; + value = value & ~ovfl_mask; } - - /* - * update sampling periods - */ - ctx->ctx_pmds[cnum].long_reset = req->reg_long_reset; - ctx->ctx_pmds[cnum].short_reset = req->reg_short_reset; - - /* - * update randomization parameters - */ - ctx->ctx_pmds[cnum].seed = req->reg_random_seed; - ctx->ctx_pmds[cnum].mask = req->reg_random_mask; } + /* + * update reset values (not just for counters) + */ + ctx->ctx_pmds[cnum].long_reset = req->reg_long_reset; + ctx->ctx_pmds[cnum].short_reset = req->reg_short_reset; + + /* + * update randomization parameters (not just for counters) + */ + ctx->ctx_pmds[cnum].seed = req->reg_random_seed; + ctx->ctx_pmds[cnum].mask = req->reg_random_mask; /* * update context value @@ -3284,7 +3259,7 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct thread_struct *thread = NULL; - unsigned long val = 0UL, lval ; + unsigned long val = 0UL, lval, ovfl_mask; pfarg_reg_t *req = (pfarg_reg_t *)arg; unsigned int cnum, reg_flags = 0; int i, can_access_pmu = 0, state; @@ -3299,6 +3274,7 @@ state = ctx->ctx_state; is_loaded = state == PFM_CTX_LOADED ? 1 : 0; is_system = ctx->ctx_fl_system; + ovfl_mask = pmu_conf.ovfl_val; if (state == PFM_CTX_ZOMBIE) return -EINVAL; @@ -3368,7 +3344,7 @@ /* * XXX: need to check for overflow when loaded */ - val &= pmu_conf.ovfl_val; + val &= ovfl_mask; val += ctx->ctx_pmds[cnum].val; lval = ctx->ctx_pmds[cnum].lval; @@ -3672,22 +3648,48 @@ */ ctx->ctx_state = PFM_CTX_LOADED; + /* + * XXX: not really useful for self monitoring + */ + ctx->ctx_fl_can_restart = 0; + return 0; } - /* restart another task */ + + /* + * restart another task + */ + + /* + * When PFM_CTX_MASKED, we cannot issue a restart before the previous + * one is seen by the task. + */ + if (state == PFM_CTX_MASKED) { + if (ctx->ctx_fl_can_restart == 0) return -EINVAL; + /* + * will prevent subsequent restart before this one is + * seen by other task + */ + ctx->ctx_fl_can_restart = 0; + } /* - * if blocking, then post the semaphore. + * if blocking, then post the semaphore is PFM_CTX_MASKED, i.e. + * the task is blocked or on its way to block. That's the normal + * restart path. If the monitoring is not masked, then the task + * can be actively monitoring and we cannot directly intervene. + * Therefore we use the trap mechanism to catch the task and + * force it to reset the buffer/reset PMDs. + * * if non-blocking, then we ensure that the task will go into * pfm_handle_work() before returning to user mode. + * * We cannot explicitely reset another task, it MUST always * be done by the task itself. This works for system wide because - * the tool that is controlling the session is doing "self-monitoring". - * - * XXX: what if the task never goes back to user? - * + * the tool that is controlling the session is logically doing + * "self-monitoring". */ - if (CTX_OVFL_NOBLOCK(ctx) == 0) { + if (CTX_OVFL_NOBLOCK(ctx) == 0 && state == PFM_CTX_MASKED) { DPRINT(("unblocking [%d] \n", task->pid)); up(&ctx->ctx_restart_sem); } else { @@ -3725,6 +3727,9 @@ return 0; } +/* + * arg can be NULL and count can be zero for this function + */ static int pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { @@ -3783,21 +3788,22 @@ /* * check for debug registers in system wide mode * - * We make the reservation even when context is not loaded - * to make sure we get our slot. Note that the PFM_LOAD_CONTEXT - * may still fail if the task has DBG_VALID set. + * If though a check is done in pfm_context_load(), + * we must repeat it here, in case the registers are + * written after the context is loaded */ - LOCK_PFS(); + if (is_loaded) { + LOCK_PFS(); - if (first_time && is_system) { - if (pfm_sessions.pfs_ptrace_use_dbregs) - ret = -EBUSY; - else - pfm_sessions.pfs_sys_use_dbregs++; + if (first_time && is_system) { + if (pfm_sessions.pfs_ptrace_use_dbregs) + ret = -EBUSY; + else + pfm_sessions.pfs_sys_use_dbregs++; + } + UNLOCK_PFS(); } - UNLOCK_PFS(); - if (ret != 0) return ret; /* @@ -4158,7 +4164,7 @@ unsigned long *pmcs_source, *pmds_source; int the_cpu; int ret = 0; - int state, is_system; + int state, is_system, set_dbregs = 0; state = ctx->ctx_state; is_system = ctx->ctx_fl_system; @@ -4173,7 +4179,7 @@ return -EINVAL; } - DPRINT(("load_pid [%d]\n", req->load_pid)); + DPRINT(("load_pid [%d] using_dbreg=%d\n", req->load_pid, ctx->ctx_fl_using_dbreg)); if (CTX_OVFL_NOBLOCK(ctx) == 0 && req->load_pid == current->pid) { DPRINT(("cannot use blocking mode on self for [%d]\n", current->pid)); @@ -4200,15 +4206,33 @@ thread = &task->thread; - ret = -EBUSY; - + ret = 0; /* * cannot load a context which is using range restrictions, * into a task that is being debugged. */ - if (ctx->ctx_fl_using_dbreg && (thread->flags & IA64_THREAD_DBG_VALID)) { - DPRINT(("load_pid [%d] task is debugged, cannot load range restrictions\n", req->load_pid)); - goto error; + if (ctx->ctx_fl_using_dbreg) { + if (thread->flags & IA64_THREAD_DBG_VALID) { + ret = -EBUSY; + DPRINT(("load_pid [%d] task is debugged, cannot load range restrictions\n", req->load_pid)); + goto error; + } + LOCK_PFS(); + + if (is_system) { + if (pfm_sessions.pfs_ptrace_use_dbregs) { + DPRINT(("cannot load [%d] dbregs in use\n", task->pid)); + ret = -EBUSY; + } else { + pfm_sessions.pfs_sys_use_dbregs++; + DPRINT(("load [%d] increased sys_use_dbreg=%lu\n", task->pid, pfm_sessions.pfs_sys_use_dbregs)); + set_dbregs = 1; + } + } + + UNLOCK_PFS(); + + if (ret) goto error; } /* @@ -4228,13 +4252,13 @@ */ the_cpu = ctx->ctx_cpu = smp_processor_id(); + ret = -EBUSY; /* * now reserve the session */ ret = pfm_reserve_session(current, is_system, the_cpu); if (ret) goto error; - ret = -EBUSY; /* * task is necessarily stopped at this point. * @@ -4342,11 +4366,6 @@ /* initial saved psr (stopped) */ ctx->ctx_saved_psr_up = 0UL; ia64_psr(regs)->up = ia64_psr(regs)->pp = 0; - - if (ctx->ctx_fl_unsecure) { - ia64_psr(regs)->sp = 0; - DPRINT(("context unsecured for [%d]\n", task->pid)); - } } ret = 0; @@ -4355,6 +4374,14 @@ if (ret) pfm_unreserve_session(ctx, ctx->ctx_fl_system, the_cpu); error: /* + * we must undo the dbregs setting (for system-wide) + */ + if (ret && set_dbregs) { + LOCK_PFS(); + pfm_sessions.pfs_sys_use_dbregs--; + UNLOCK_PFS(); + } + /* * release task, there is now a link with the context */ if (is_system == 0 && task != current) { @@ -4455,7 +4482,7 @@ */ tregs = task == current ? regs : ia64_task_regs(task); - if (task == current || ctx->ctx_fl_unsecure) { + if (task == current) { /* * cancel user level control */ @@ -4493,7 +4520,10 @@ ctx->ctx_task = NULL; PFM_SET_WORK_PENDING(task, 0); - ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; + + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; + ctx->ctx_fl_can_restart = 0; + ctx->ctx_fl_going_zombie = 0; DPRINT(("disconnected [%d] from context\n", task->pid)); @@ -4686,7 +4716,7 @@ UNPROTECT_CTX(ctx, flags); - pfm_wait_task_inactive(task); + wait_task_inactive(task); PROTECT_CTX(ctx, flags); @@ -4725,7 +4755,8 @@ PFM_CMD_IDX(cmd), PFM_CMD_IS_VALID(cmd), PFM_CMD_NARG(cmd), - PFM_CMD_ARG_SIZE(cmd), count)); + PFM_CMD_ARG_SIZE(cmd), + count)); /* * check if number of arguments matches what the command expects @@ -4842,8 +4873,10 @@ { pfm_buffer_fmt_t *fmt = ctx->ctx_buf_fmt; pfm_ovfl_ctrl_t rst_ctrl; + int state; int ret = 0; + state = ctx->ctx_state; /* * Unlock sampling buffer and reset index atomically * XXX: not really needed when blocking @@ -4853,9 +4886,10 @@ rst_ctrl.bits.mask_monitoring = 0; rst_ctrl.bits.reset_ovfl_pmds = 1; - /* XXX: check return value */ - if (fmt->fmt_restart) - ret = (*fmt->fmt_restart)(current, &rst_ctrl, ctx->ctx_smpl_hdr, regs); + if (state == PFM_CTX_LOADED) + ret = pfm_buf_fmt_restart_active(fmt, current, &rst_ctrl, ctx->ctx_smpl_hdr, regs); + else + ret = pfm_buf_fmt_restart(fmt, current, &rst_ctrl, ctx->ctx_smpl_hdr, regs); } else { rst_ctrl.bits.mask_monitoring = 0; rst_ctrl.bits.reset_ovfl_pmds = 1; @@ -4876,7 +4910,6 @@ } } - /* * context MUST BE LOCKED when calling * can only be called for current @@ -4954,7 +4987,7 @@ reason = ctx->ctx_fl_trap_reason; ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; - DPRINT(("[%d] reason=%d\n", current->pid, reason)); + DPRINT(("[%d] reason=%d state=%d\n", current->pid, reason, ctx->ctx_state)); /* * must be done before we check non-blocking mode @@ -5085,7 +5118,7 @@ { pfm_ovfl_arg_t ovfl_arg; unsigned long mask; - unsigned long old_val; + unsigned long old_val, ovfl_val; unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL; unsigned long tstamp; pfm_ovfl_ctrl_t ovfl_ctrl; @@ -5101,7 +5134,8 @@ tstamp = ia64_get_itc(); - mask = pmc0 >> PMU_FIRST_COUNTER; + mask = pmc0 >> PMU_FIRST_COUNTER; + ovfl_val = pmu_conf.ovfl_val; DPRINT_ovfl(("pmc0=0x%lx pid=%d iip=0x%lx, %s " "used_pmds=0x%lx reload_pmcs=0x%lx\n", @@ -5133,7 +5167,7 @@ * pfm_read_pmds(). */ old_val = ctx->ctx_pmds[i].val; - ctx->ctx_pmds[i].val += 1 + pmu_conf.ovfl_val; + ctx->ctx_pmds[i].val += 1 + ovfl_val; /* * check for overflow condition @@ -5145,7 +5179,7 @@ DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx smpl_pmds=0x%lx\n", i, ctx->ctx_pmds[i].val, old_val, - ia64_get_pmd(i) & pmu_conf.ovfl_val, ovfl_pmds, ovfl_notify, smpl_pmds)); + ia64_get_pmd(i) & ovfl_val, ovfl_pmds, ovfl_notify, smpl_pmds)); } /* @@ -5196,6 +5230,7 @@ for(j=0, k=0; smpl_pmds; j++, smpl_pmds >>=1) { if ((smpl_pmds & 0x1) == 0) continue; ovfl_arg.smpl_pmds_values[k++] = PMD_IS_COUNTING(j) ? pfm_read_soft_counter(ctx, j) : ia64_get_pmd(j); + DPRINT_ovfl(("smpl_pmd[%d]=pmd%u=0x%lx\n", k-1, j, ovfl_arg.smpl_pmds_values[k-1])); } } @@ -5294,6 +5329,7 @@ if (ovfl_ctrl.bits.mask_monitoring) { pfm_mask_monitoring(task); ctx->ctx_state = PFM_CTX_MASKED; + ctx->ctx_fl_can_restart = 1; } /* @@ -5376,12 +5412,10 @@ */ /* sanity check */ - if (!ctx) goto report_spurious; + if (!ctx) goto report_spurious1; - if (ctx->ctx_fl_system == 0 && (task->thread.flags & IA64_THREAD_PM_VALID) == 0) { - printk("perfmon: current [%d] owner = [%d] PMVALID=0 state=%d\n", current->pid, task->pid, ctx->ctx_state); - goto report_spurious; - } + if (ctx->ctx_fl_system == 0 && (task->thread.flags & IA64_THREAD_PM_VALID) == 0) + goto report_spurious2; PROTECT_CTX_NOPRINT(ctx, flags); @@ -5400,14 +5434,20 @@ return retval; -report_spurious: +report_spurious1: printk(KERN_INFO "perfmon: spurious overflow interrupt on CPU%d: process %d has no PFM context\n", this_cpu, task->pid); pfm_unfreeze_pmu(); return -1; +report_spurious2: + printk(KERN_INFO "perfmon: spurious overflow interrupt on CPU%d: process %d, invalid flag\n", + this_cpu, + task->pid); + pfm_unfreeze_pmu(); + return -1; } -static pfm_irq_handler_t +static irqreturn_t pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs) { unsigned long start_cycles, total_cycles; @@ -5436,7 +5476,8 @@ pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles; } - PFM_IRQ_HANDLER_RET(); + put_cpu_no_resched(); + return IRQ_HANDLED; } @@ -5445,10 +5486,13 @@ pfm_proc_info(char *page) { char *p = page; - pfm_buffer_fmt_t *b; + struct list_head * pos; + pfm_buffer_fmt_t * entry; unsigned long psr; + int online_cpus = 0; int i; + p += sprintf(p, "perfmon version : %u.%u\n", PFM_VERSION_MAJ, PFM_VERSION_MIN); p += sprintf(p, "model : %s\n", pmu_conf.pmu_name); p += sprintf(p, "fastctxsw : %s\n", pfm_sysctl.fastctxsw > 0 ? "Yes": "No"); p += sprintf(p, "ovfl_mask : 0x%lx\n", pmu_conf.ovfl_val); @@ -5462,17 +5506,17 @@ p += sprintf(p, "CPU%-2d smpl handler calls : %lu\n", i, pfm_stats[i].pfm_smpl_handler_calls); p += sprintf(p, "CPU%-2d smpl handler cycles : %lu\n", i, pfm_stats[i].pfm_smpl_handler_cycles); p += sprintf(p, "CPU%-2d spurious intrs : %lu\n", i, pfm_stats[i].pfm_spurious_ovfl_intr_count); - p += sprintf(p, "CPU%-2d sysupdt count : %lu\n", i, pfm_stats[i].pfm_sysupdt_count); - p += sprintf(p, "CPU%-2d sysupdt cycles : %lu\n", i, pfm_stats[i].pfm_sysupdt_cycles); + p += sprintf(p, "CPU%-2d replay intrs : %lu\n", i, pfm_stats[i].pfm_replay_ovfl_intr_count); p += sprintf(p, "CPU%-2d syst_wide : %d\n" , i, pfm_get_cpu_data(pfm_syst_info, i) & PFM_CPUINFO_SYST_WIDE ? 1 : 0); p += sprintf(p, "CPU%-2d dcr_pp : %d\n" , i, pfm_get_cpu_data(pfm_syst_info, i) & PFM_CPUINFO_DCR_PP ? 1 : 0); p += sprintf(p, "CPU%-2d exclude idle : %d\n" , i, pfm_get_cpu_data(pfm_syst_info, i) & PFM_CPUINFO_EXCL_IDLE ? 1 : 0); p += sprintf(p, "CPU%-2d owner : %d\n" , i, pfm_get_cpu_data(pmu_owner, i) ? pfm_get_cpu_data(pmu_owner, i)->pid: -1); p += sprintf(p, "CPU%-2d context : %p\n" , i, pfm_get_cpu_data(pmu_ctx, i)); p += sprintf(p, "CPU%-2d activations : %lu\n", i, pfm_get_cpu_data(pmu_activation_number,i)); + online_cpus++; } - if (num_online_cpus() == 1) + if (online_cpus == 1) { psr = pfm_get_psr(); ia64_srlz_d(); @@ -5485,7 +5529,7 @@ } LOCK_PFS(); - p += sprintf(p, "proc_sessions : %u\n" + p += sprintf(p, "proc_sessions : %u\n" "sys_sessions : %u\n" "sys_use_dbregs : %u\n" "ptrace_use_dbregs : %u\n", @@ -5495,29 +5539,30 @@ pfm_sessions.pfs_ptrace_use_dbregs); UNLOCK_PFS(); - LOCK_BUF_FMT_LIST(); + spin_lock(&pfm_buffer_fmt_lock); - for (b = pfm_buffer_fmt_list; b ; b = b->fmt_next) { + list_for_each(pos, &pfm_buffer_fmt_list) { + entry = list_entry(pos, pfm_buffer_fmt_t, fmt_list); p += sprintf(p, "format : %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x %s\n", - b->fmt_uuid[0], - b->fmt_uuid[1], - b->fmt_uuid[2], - b->fmt_uuid[3], - b->fmt_uuid[4], - b->fmt_uuid[5], - b->fmt_uuid[6], - b->fmt_uuid[7], - b->fmt_uuid[8], - b->fmt_uuid[9], - b->fmt_uuid[10], - b->fmt_uuid[11], - b->fmt_uuid[12], - b->fmt_uuid[13], - b->fmt_uuid[14], - b->fmt_uuid[15], - b->fmt_name); + entry->fmt_uuid[0], + entry->fmt_uuid[1], + entry->fmt_uuid[2], + entry->fmt_uuid[3], + entry->fmt_uuid[4], + entry->fmt_uuid[5], + entry->fmt_uuid[6], + entry->fmt_uuid[7], + entry->fmt_uuid[8], + entry->fmt_uuid[9], + entry->fmt_uuid[10], + entry->fmt_uuid[11], + entry->fmt_uuid[12], + entry->fmt_uuid[13], + entry->fmt_uuid[14], + entry->fmt_uuid[15], + entry->fmt_name); } - UNLOCK_BUF_FMT_LIST(); + spin_unlock(&pfm_buffer_fmt_lock); return p - page; } @@ -5546,7 +5591,7 @@ * local_cpu_data->pfm_syst_info */ void -pfm_do_syst_wide_update_task(struct task_struct *task, unsigned long info, int is_ctxswin) +pfm_syst_wide_update_task(struct task_struct *task, unsigned long info, int is_ctxswin) { struct pt_regs *regs; unsigned long dcr; @@ -5591,21 +5636,10 @@ } } -void -pfm_syst_wide_update_task(struct task_struct *task, unsigned long info, int is_ctxswin) -{ - unsigned long start, end; - - pfm_stats[smp_processor_id()].pfm_sysupdt_count++; - start = ia64_get_itc(); - - pfm_do_syst_wide_update_task(task, info, is_ctxswin); - - end = ia64_get_itc(); - pfm_stats[smp_processor_id()].pfm_sysupdt_cycles += end-start; -} - #ifdef CONFIG_SMP +/* + * in 2.6, interrupts are masked when we come here and the runqueue lock is held + */ void pfm_save_regs(struct task_struct *task) { @@ -5706,14 +5740,11 @@ /* * unfreeze PMU if had pending overflows */ - if (t->pmcs[0] & ~1UL) pfm_unfreeze_pmu(); + if (t->pmcs[0] & ~0x1UL) pfm_unfreeze_pmu(); /* - * finally, unmask interrupts and allow context - * access. - * Any pended overflow interrupt may be delivered - * here and will be treated as spurious because we - * have have no PMU owner anymore. + * finally, allow context access. + * interrupts will still be masked after this call. */ pfm_unprotect_ctx_ctxsw(ctx, flags); @@ -5726,10 +5757,6 @@ } #else /* !CONFIG_SMP */ - -/* - * in 2.5, interrupts are masked when we come here - */ void pfm_save_regs(struct task_struct *task) { @@ -5836,6 +5863,9 @@ #endif /* CONFIG_SMP */ #ifdef CONFIG_SMP +/* + * in 2.6, interrupts are masked when we come here and the runqueue lock is held + */ void pfm_load_regs (struct task_struct *task) { @@ -5959,20 +5989,24 @@ * was saved. */ if (unlikely(PMC0_HAS_OVFL(t->pmcs[0]))) { - struct pt_regs *regs = ia64_task_regs(task); - pfm_overflow_handler(task, ctx, t->pmcs[0], regs); + /* + * reload pmc0 with the overflow information + * On McKinley PMU, this will trigger a PMU interrupt + */ + ia64_set_pmc(0, t->pmcs[0]); + ia64_srlz_d(); + t->pmcs[0] = 0UL; +#ifndef CONFIG_MCKINLEY + /* + * will replay the PMU interrupt + */ + DPRINT(("perfmon: resend irq for [%d]\n", task->pid)); + hw_resend_irq(NULL, IA64_PERFMON_VECTOR); +#endif + pfm_stats[smp_processor_id()].pfm_replay_ovfl_intr_count++; } /* - * we clear PMC0, to ensure that any in flight interrupt - * will not be attributed to the new context we are installing - * because the actual overflow has been processed above already. - * No real effect until we unmask interrupts at the end of the - * function. - */ - pfm_unfreeze_pmu(); - - /* * we just did a reload, so we reset the partial reload fields */ ctx->ctx_reload_pmcs[0] = 0UL; @@ -5990,13 +6024,15 @@ SET_ACTIVATION(ctx); /* - * establish new ownership. Interrupts - * are still masked at this point. + * establish new ownership. */ SET_PMU_OWNER(task, ctx); /* - * restore the psr.up bit + * restore the psr.up bit. measurement + * is active again. + * no PMU interrupt can happen at this point + * because we still have interrupts disabled. */ if (likely(psr_up)) pfm_set_psr_up(); @@ -6091,42 +6127,39 @@ pfm_restore_pmcs(t->pmcs, pmc_mask); /* - * Check for pending overflow when state was last saved. - * invoked handler is overflow status bits set. - * - * Any PMU overflow in flight at this point, will still - * be treated as spurious because we have no declared - * owner. Note that the first level interrupt handler - * DOES NOT TOUCH any PMC except PMC0 for which we have - * a copy already. + * check for pending overflow at the time the state + * was saved. */ if (unlikely(PMC0_HAS_OVFL(t->pmcs[0]))) { - struct pt_regs *regs = ia64_task_regs(task); - pfm_overflow_handler(task, ctx, t->pmcs[0], regs); - } + /* + * reload pmc0 with the overflow information + * On McKinley PMU, this will trigger a PMU interrupt + */ + ia64_set_pmc(0, t->pmcs[0]); + ia64_srlz_d(); - /* - * we clear PMC0, to ensure that any in flight interrupt - * will not be attributed to the new context we are installing - * because the actual overflow has been processed above already. - * - * This is an atomic operation. - */ - pfm_unfreeze_pmu(); + t->pmcs[0] = 0UL; + +#ifndef CONFIG_MCKINLEY + /* + * will replay the PMU interrupt + */ + DPRINT(("perfmon: resend irq for [%d]\n", task->pid)); + hw_resend_irq(NULL, IA64_PERFMON_VECTOR); +#endif + pfm_stats[smp_processor_id()].pfm_replay_ovfl_intr_count++; + } /* - * establish new ownership. If there was an in-flight - * overflow interrupt, it will be treated as spurious - * before and after the call, because no overflow - * status bit can possibly be set. No new overflow - * can be generated because, at this point, psr.up - * is still cleared. + * establish new ownership. */ SET_PMU_OWNER(task, ctx); /* - * restore the psr. This is the point at which - * new overflow interrupts can be generated again. + * restore the psr.up bit. measurement + * is active again. + * no PMU interrupt can happen at this point + * because we still have interrupts disabled. */ if (likely(psr_up)) pfm_set_psr_up(); } @@ -6139,7 +6172,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx) { u64 pmc0; - unsigned long mask2, val, pmd_val; + unsigned long mask2, val, pmd_val, ovfl_val; int i, can_access_pmu = 0; int is_self; @@ -6187,7 +6220,7 @@ */ task->thread.pmcs[0] &= ~0x1; } - + ovfl_val = pmu_conf.ovfl_val; /* * we save all the used pmds * we take care of overflows for counting PMDs @@ -6210,12 +6243,12 @@ task->pid, i, ctx->ctx_pmds[i].val, - val & pmu_conf.ovfl_val)); + val & ovfl_val)); /* * we rebuild the full 64 bit value of the counter */ - val = ctx->ctx_pmds[i].val + (val & pmu_conf.ovfl_val); + val = ctx->ctx_pmds[i].val + (val & ovfl_val); /* * now everything is in ctx_pmds[] and we need @@ -6228,7 +6261,7 @@ * take care of overflow inline */ if (pmc0 & (1UL << i)) { - val += 1 + pmu_conf.ovfl_val; + val += 1 + ovfl_val; DPRINT(("[%d] pmd[%d] overflowed\n", task->pid, i)); } } @@ -6338,7 +6371,7 @@ * initialize all our spinlocks */ spin_lock_init(&pfm_sessions.pfs_lock); - spin_lock_init(&pfm_smpl_fmt_lock); + spin_lock_init(&pfm_buffer_fmt_lock); init_pfm_fs(); @@ -6352,6 +6385,9 @@ __initcall(pfm_init); +/* + * this function is called before pfm_init() + */ void pfm_init_percpu (void) { @@ -6363,7 +6399,6 @@ */ pfm_clear_psr_pp(); pfm_clear_psr_up(); - if (smp_processor_id() == 0) register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction); diff -Nru a/arch/ia64/kernel/perfmon_itanium.h b/arch/ia64/kernel/perfmon_itanium.h --- a/arch/ia64/kernel/perfmon_itanium.h Fri Oct 17 14:43:51 2003 +++ b/arch/ia64/kernel/perfmon_itanium.h Fri Oct 17 14:43:51 2003 @@ -81,6 +81,8 @@ */ if (cnum == 13 && ((*val & 0x1) == 0UL) && ctx->ctx_fl_using_dbreg == 0) { + DPRINT(("pmc[%d]=0x%lx has active pmc13.ta cleared, clearing ibr\n", cnum, *val)); + /* don't mix debug with perfmon */ if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL; @@ -97,6 +99,8 @@ * before they are written (fl_using_dbreg==0) to avoid picking up stale information. */ if (cnum == 11 && ((*val >> 28)& 0x1) == 0 && ctx->ctx_fl_using_dbreg == 0) { + + DPRINT(("pmc[%d]=0x%lx has active pmc11.pt cleared, clearing dbr\n", cnum, *val)); /* don't mix debug with perfmon */ if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL; diff -Nru a/arch/ia64/kernel/perfmon_mckinley.h b/arch/ia64/kernel/perfmon_mckinley.h --- a/arch/ia64/kernel/perfmon_mckinley.h Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/perfmon_mckinley.h Fri Oct 17 14:43:50 2003 @@ -109,10 +109,20 @@ if (ctx == NULL) return -EINVAL; /* - * 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. + * we must clear the debug registers if pmc13 has a value which enable + * memory pipeline event constraints. In this case we need to clear the + * the debug registers if they have not yet been accessed. This is required + * to avoid picking stale state. + * PMC13 is "active" if: + * one of the pmc13.cfg_dbrpXX field is different from 0x3 + * AND + * at the corresponding pmc13.ena_dbrpXX is set. + * + * For now, we just check on cfg_dbrXX != 0x3. */ - if (cnum == 13 && (*val & (0xfUL << 45)) && ctx->ctx_fl_using_dbreg == 0) { + if (cnum == 13 && ((*val & 0x18181818UL) != 0x18181818UL) && ctx->ctx_fl_using_dbreg == 0) { + + DPRINT(("pmc[%d]=0x%lx has active pmc13 settings, clearing dbr\n", cnum, *val)); /* don't mix debug with perfmon */ if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL; @@ -128,7 +138,9 @@ * we must clear the (instruction) debug registers if any pmc14.ibrpX bit is enabled * before they are (fl_using_dbreg==0) to avoid picking up stale information. */ - if (cnum == 14 && ((*val & 0x2222) != 0x2222) && ctx->ctx_fl_using_dbreg == 0) { + if (cnum == 14 && ((*val & 0x2222UL) != 0x2222UL) && ctx->ctx_fl_using_dbreg == 0) { + + DPRINT(("pmc[%d]=0x%lx has active pmc14 settings, clearing ibr\n", cnum, *val)); /* don't mix debug with perfmon */ if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL; @@ -170,7 +182,7 @@ && ((((val14>>1) & 0x3) == 0x2 || ((val14>>1) & 0x3) == 0x0) ||(((val14>>4) & 0x3) == 0x2 || ((val14>>4) & 0x3) == 0x0)); - if (ret) printk("perfmon: failure check_case1\n"); + if (ret) DPRINT((KERN_DEBUG "perfmon: failure check_case1\n")); } return ret ? -EINVAL : 0; diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c --- a/arch/ia64/kernel/setup.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/setup.c Fri Oct 17 14:43:50 2003 @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -43,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -101,7 +104,7 @@ 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); + void (*func)(unsigned long, unsigned long, int); int i; #if IGNORE_PFN0 @@ -122,11 +125,7 @@ range_end = min(end, rsvd_region[i].start); if (range_start < range_end) -#ifdef CONFIG_DISCONTIGMEM - call_pernode_memory(__pa(range_start), __pa(range_end), func); -#else - (*func)(__pa(range_start), range_end - range_start); -#endif + call_pernode_memory(__pa(range_start), range_end - range_start, func); /* nothing more available in this segment */ if (range_end == end) return 0; @@ -225,6 +224,25 @@ #endif } +#ifdef CONFIG_SERIAL_8250_CONSOLE +static void __init +setup_serial_legacy (void) +{ + struct uart_port port; + unsigned int i, iobase[] = {0x3f8, 0x2f8}; + + printk(KERN_INFO "Registering legacy COM ports for serial console\n"); + memset(&port, 0, sizeof(port)); + port.iotype = SERIAL_IO_PORT; + port.uartclk = BASE_BAUD * 16; + for (i = 0; i < ARRAY_SIZE(iobase); i++) { + port.line = i; + port.iobase = iobase[i]; + early_serial_setup(&port); + } +} +#endif + void __init setup_arch (char **cmdline_p) { @@ -239,7 +257,6 @@ strlcpy(saved_command_line, *cmdline_p, sizeof(saved_command_line)); efi_init(); - find_memory(); #ifdef CONFIG_ACPI_BOOT /* Initialize the ACPI boot-time table parser */ @@ -253,6 +270,8 @@ # endif #endif /* CONFIG_APCI_BOOT */ + find_memory(); + /* process SAL system table: */ ia64_sal_init(efi.sal_systab); @@ -297,11 +316,22 @@ #ifdef CONFIG_SERIAL_8250_HCDP if (efi.hcdp) { void setup_serial_hcdp(void *); - - /* Setup the serial ports described by HCDP */ setup_serial_hcdp(efi.hcdp); } #endif +#ifdef CONFIG_SERIAL_8250_CONSOLE + /* + * Without HCDP, we won't discover any serial ports until the serial driver looks + * in the ACPI namespace. If ACPI claims there are some legacy devices, register + * the legacy COM ports so serial console works earlier. This is slightly dangerous + * because we don't *really* know whether there's anything there, but we hope that + * all new boxes will implement HCDP. + */ + extern unsigned char acpi_legacy_devices; + if (!efi.hcdp && acpi_legacy_devices) + setup_serial_legacy(); +#endif + #ifdef CONFIG_VT # if defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; @@ -544,28 +574,7 @@ struct cpuinfo_ia64 *cpu_info; void *cpu_data; -#ifdef CONFIG_SMP - int cpu; - - /* - * 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 (smp_processor_id() == 0) { - cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, PERCPU_PAGE_SIZE, - __pa(MAX_DMA_ADDRESS)); - for (cpu = 0; cpu < NR_CPUS; cpu++) { - memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); - __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; - cpu_data += PERCPU_PAGE_SIZE; - - per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; - } - } - cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id()]; -#else /* !CONFIG_SMP */ - cpu_data = __phys_per_cpu_start; -#endif /* !CONFIG_SMP */ + cpu_data = per_cpu_init(); get_max_cacheline_size(); @@ -576,9 +585,6 @@ * accessing cpu_data() through the canonical per-CPU address. */ cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var(cpu_info) - __per_cpu_start); -#ifdef CONFIG_NUMA - cpu_info->node_data = get_node_data_ptr(); -#endif identify_cpu(cpu_info); #ifdef CONFIG_MCKINLEY diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c --- a/arch/ia64/kernel/time.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/time.c Fri Oct 17 14:43:50 2003 @@ -65,8 +65,12 @@ } /* - * Return the number of nano-seconds that elapsed since the last update to jiffy. The - * xtime_lock must be at least read-locked when calling this routine. + * Return the number of nano-seconds that elapsed since the last + * update to jiffy. It is quite possible that the timer interrupt + * will interrupt this and result in a race for any of jiffies, + * wall_jiffies or itm_next. Thus, the xtime_lock must be at least + * read synchronised when calling this routine (see do_gettimeofday() + * below for an example). */ unsigned long itc_get_offset (void) @@ -77,11 +81,6 @@ last_tick = (cpu_data(TIME_KEEPER_ID)->itm_next - (lost + 1)*cpu_data(TIME_KEEPER_ID)->itm_delta); - if (unlikely((long) (now - last_tick) < 0)) { - printk(KERN_ERR "CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n", - smp_processor_id(), now, last_tick); - return last_nsec_offset; - } elapsed_cycles = now - last_tick; return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT; } diff -Nru a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c --- a/arch/ia64/kernel/unaligned.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/kernel/unaligned.c Fri Oct 17 14:43:50 2003 @@ -1347,7 +1347,7 @@ * be holding locks... */ if (user_mode(regs)) - tty_write_message(process_tty(current), buf); + tty_write_message(current->tty, buf); buf[len-1] = '\0'; /* drop '\r' */ printk(KERN_WARNING "%s", buf); /* watch for command names containing %s */ } diff -Nru a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c --- a/arch/ia64/mm/contig.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/mm/contig.c Fri Oct 17 14:43:50 2003 @@ -25,6 +25,10 @@ #include #include +#ifdef CONFIG_VIRTUAL_MEM_MAP +static unsigned long num_dma_physpages; +#endif + /** * show_mem - display a memory statistics summary * @@ -160,4 +164,134 @@ reserve_bootmem(bootmap_start, bootmap_size); find_initrd(); +} + +#ifdef CONFIG_SMP +/** + * per_cpu_init - setup per-cpu variables + * + * Allocate and setup per-cpu data areas. + */ +void * +per_cpu_init (void) +{ + void *cpu_data; + int cpu; + + /* + * 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 (smp_processor_id() == 0) { + cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, + PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); + for (cpu = 0; cpu < NR_CPUS; cpu++) { + memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); + __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; + cpu_data += PERCPU_PAGE_SIZE; + per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; + } + } + return __per_cpu_start + __per_cpu_offset[smp_processor_id()]; +} +#endif /* CONFIG_SMP */ + +static int +count_pages (u64 start, u64 end, void *arg) +{ + unsigned long *count = arg; + + *count += (end - start) >> PAGE_SHIFT; + return 0; +} + +#ifdef CONFIG_VIRTUAL_MEM_MAP +static int +count_dma_pages (u64 start, u64 end, void *arg) +{ + unsigned long *count = arg; + + if (end <= MAX_DMA_ADDRESS) + *count += (end - start) >> PAGE_SHIFT; + return 0; +} +#endif + +/* + * Set up the page tables. + */ + +void +paging_init (void) +{ + unsigned long max_dma; + unsigned long zones_size[MAX_NR_ZONES]; +#ifdef CONFIG_VIRTUAL_MEM_MAP + unsigned long zholes_size[MAX_NR_ZONES]; + unsigned long max_gap; +#endif + + /* initialize mem_map[] */ + + memset(zones_size, 0, sizeof(zones_size)); + + num_physpages = 0; + efi_memmap_walk(count_pages, &num_physpages); + + max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT; + +#ifdef CONFIG_VIRTUAL_MEM_MAP + memset(zholes_size, 0, sizeof(zholes_size)); + + num_dma_physpages = 0; + efi_memmap_walk(count_dma_pages, &num_dma_physpages); + + if (max_low_pfn < max_dma) { + zones_size[ZONE_DMA] = max_low_pfn; + zholes_size[ZONE_DMA] = max_low_pfn - num_dma_physpages; + } else { + zones_size[ZONE_DMA] = max_dma; + zholes_size[ZONE_DMA] = max_dma - num_dma_physpages; + if (num_physpages > num_dma_physpages) { + zones_size[ZONE_NORMAL] = max_low_pfn - max_dma; + zholes_size[ZONE_NORMAL] = + ((max_low_pfn - max_dma) - + (num_physpages - num_dma_physpages)); + } + } + + max_gap = 0; + efi_memmap_walk(find_largest_hole, (u64 *)&max_gap); + if (max_gap < LARGE_GAP) { + vmem_map = (struct page *) 0; + free_area_init_node(0, &contig_page_data, NULL, zones_size, 0, + zholes_size); + mem_map = contig_page_data.node_mem_map; + } else { + unsigned long map_size; + + /* allocate virtual_mem_map */ + + map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page)); + vmalloc_end -= map_size; + vmem_map = (struct page *) vmalloc_end; + efi_memmap_walk(create_mem_map_page_table, 0); + + free_area_init_node(0, &contig_page_data, vmem_map, zones_size, + 0, zholes_size); + + mem_map = contig_page_data.node_mem_map; + printk("Virtual mem_map starts at 0x%p\n", mem_map); + } +#else /* !CONFIG_VIRTUAL_MEM_MAP */ + if (max_low_pfn < max_dma) + zones_size[ZONE_DMA] = max_low_pfn; + else { + zones_size[ZONE_DMA] = max_dma; + zones_size[ZONE_NORMAL] = max_low_pfn - max_dma; + } + free_area_init(zones_size); +#endif /* !CONFIG_VIRTUAL_MEM_MAP */ + zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page)); } diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c --- a/arch/ia64/mm/discontig.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/mm/discontig.c Fri Oct 17 14:43:50 2003 @@ -17,72 +17,57 @@ #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[MAX_NUMNODES]; -static long boot_pg_data[8*MAX_NUMNODES+sizeof(pg_data_t)] __initdata; -static pg_data_t *pg_data_ptr[MAX_NUMNODES] __initdata; -static bootmem_data_t bdata[MAX_NUMNODES][NR_BANKS_PER_NODE+1] __initdata; -/* - * 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; -} +#include +#include /* - * 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. + * Track per-node information needed to setup the boot memory allocator, the + * per-node areas, and the real VM. */ -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 early_node_data { + struct ia64_node_data *node_data; + pg_data_t *pgdat; + unsigned long pernode_addr; + unsigned long pernode_size; + struct bootmem_data bootmem_data; + unsigned long num_physpages; + unsigned long num_dma_physpages; + unsigned long min_pfn; + unsigned long max_pfn; +}; + +static struct early_node_data mem_data[NR_NODES] __initdata; + +/* + * To prevent cache aliasing effects, align per-node structures so that they + * start at addresses that are strided by node number. + */ +#define NODEDATA_ALIGN(addr, node) \ + ((((addr) + 1024*1024-1) & ~(1024*1024-1)) + (node)*PERCPU_PAGE_SIZE) + +/** + * build_node_maps - callback to setup bootmem structs for each node + * @start: physical start of range + * @len: length of range + * @node: node where this range resides + * + * We allocate a struct bootmem_data for each piece of memory that we wish to + * treat as a virtually contiguous block (i.e. each node). Each such block + * must start on an %IA64_GRANULE_SIZE boundary, so we round the address down + * if necessary. Any non-existent pages will simply be part of the virtual + * memmap. We also update min_low_pfn and max_low_pfn here as we receive + * memory ranges from the caller. */ -struct ia64_node_data * -get_node_data_ptr(void) +static int __init build_node_maps(unsigned long start, unsigned long len, + int node) { - return node_data[boot_get_local_nodeid()]; -} + unsigned long cstart, epfn, end = start + len; + struct bootmem_data *bdp = &mem_data[node].bootmem_data; -/* - * 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); + epfn = GRANULEROUNDUP(end) >> PAGE_SHIFT; + cstart = GRANULEROUNDDOWN(start); if (!bdp->node_low_pfn) { bdp->node_boot_start = cstart; @@ -98,34 +83,143 @@ return 0; } -/* - * Find space on each node for the bootmem map. +/** + * early_nr_cpus_node - return number of cpus on a given node + * @node: node to check * - * 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). + * Count the number of cpus on @node. We can't use nr_cpus_node() yet because + * acpi_boot_init() (which builds the node_to_cpu_mask array) hasn't been + * called yet. */ -static int __init -find_bootmap_space(unsigned long pstart, unsigned long length, int node) +static int early_nr_cpus_node(int node) { - unsigned long mapsize, pages, epfn; - bootmem_data_t *bdp; + int cpu, n = 0; - epfn = (pstart + length) >> PAGE_SHIFT; - bdp = &pg_data_ptr[node]->bdata[0]; + for (cpu = 0; cpu < NR_CPUS; cpu++) + if (node == node_cpuid[cpu].nid) + n++; + + return n; +} - if (pstart < bdp->node_boot_start || epfn > bdp->node_low_pfn) +/** + * find_pernode_space - allocate memory for memory map and per-node structures + * @start: physical start of range + * @len: length of range + * @node: node where this range resides + * + * This routine reserves space for the per-cpu data struct, the list of + * pg_data_ts and the per-node data struct. Each node will have something like + * the following in the first chunk of addr. space large enough to hold it. + * + * ________________________ + * | | + * |~~~~~~~~~~~~~~~~~~~~~~~~| <-- NODEDATA_ALIGN(start, node) for the first + * | PERCPU_PAGE_SIZE * | start and length big enough + * | NR_CPUS | + * |------------------------| + * | local pg_data_t * | + * |------------------------| + * | local ia64_node_data | + * |------------------------| + * | ??? | + * |________________________| + * + * Once this space has been set aside, the bootmem maps are initialized. We + * could probably move the allocation of the per-cpu and ia64_node_data space + * outside of this function and use alloc_bootmem_node(), but doing it here + * is straightforward and we get the alignments we want so... + */ +static int __init find_pernode_space(unsigned long start, unsigned long len, + int node) +{ + unsigned long epfn, cpu, cpus; + unsigned long pernodesize = 0, pernode; + void *cpu_data; + struct bootmem_data *bdp = &mem_data[node].bootmem_data; + + epfn = (start + len) >> PAGE_SHIFT; + + /* + * Make sure this memory falls within this node's usable memory + * since we may have thrown some away in build_maps(). + */ + if (start < 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); + /* Don't setup this node's local space twice... */ + if (!mem_data[node].pernode_addr) { + /* + * Calculate total size needed, incl. what's necessary + * for good alignment and alias prevention. + */ + cpus = early_nr_cpus_node(node); + pernodesize += PERCPU_PAGE_SIZE * cpus; + pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t)); + pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data)); + pernodesize = PAGE_ALIGN(pernodesize); + pernode = NODEDATA_ALIGN(start, node); + + /* Is this range big enough for what we want to store here? */ + if (start + len > (pernode + pernodesize)) { + mem_data[node].pernode_addr = pernode; + mem_data[node].pernode_size = pernodesize; + memset(__va(pernode), 0, pernodesize); + + cpu_data = (void *)pernode; + pernode += PERCPU_PAGE_SIZE * cpus; + + mem_data[node].pgdat = __va(pernode); + pernode += L1_CACHE_ALIGN(sizeof(pg_data_t)); + + mem_data[node].node_data = __va(pernode); + pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data)); + + mem_data[node].pgdat->bdata = bdp; + pernode += L1_CACHE_ALIGN(sizeof(pg_data_t)); + + /* + * Copy the static per-cpu data into the region we + * just set aside and then setup __per_cpu_offset + * for each CPU on this node. + */ + for (cpu = 0; cpu < NR_CPUS; cpu++) { + if (node == node_cpuid[cpu].nid) { + memcpy(cpu_data, __phys_per_cpu_start, + __per_cpu_end-__per_cpu_start); + __per_cpu_offset[cpu] = + (char*)__va(cpu_data) - + __per_cpu_start; + cpu_data += PERCPU_PAGE_SIZE; + } + } + } + } + + pernode = mem_data[node].pernode_addr; + pernodesize = mem_data[node].pernode_size; + if (pernode && !bdp->node_bootmem_map) { + unsigned long pages, mapsize, map = 0; + + 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); + + /* + * The map will either contain the pernode area or begin + * after it. + */ + if (pernode - start > mapsize) + map = start; + else if (start + len - pernode - pernodesize > mapsize) + map = pernode + pernodesize; + + if (map) { + init_bootmem_node(mem_data[node].pgdat, + map>>PAGE_SHIFT, + bdp->node_boot_start>>PAGE_SHIFT, + bdp->node_low_pfn); } } @@ -133,85 +227,93 @@ 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). +/** + * free_node_bootmem - free bootmem allocator memory for use + * @start: physical start of range + * @len: length of range + * @node: node where this range resides * + * Simply calls the bootmem allocator to free the specified ranged from + * the given pg_data_t's bdata struct. After this function has been called + * for all the entries in the EFI memory map, the bootmem allocator will + * be ready to service allocation requests. */ -static int __init -discontig_free_bootmem_node(unsigned long pstart, unsigned long length, int node) +static int __init free_node_bootmem(unsigned long start, unsigned long len, + int node) { - free_bootmem_node(BOOT_NODE_DATA(node), pstart, length); + free_bootmem_node(mem_data[node].pgdat, start, len); 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; +/** + * reserve_pernode_space - reserve memory for per-node space + * + * Reserve the space used by the bootmem maps & per-node space in the boot + * allocator so that when we actually create the real mem maps we don't + * use their memory. + */ +static void __init reserve_pernode_space(void) +{ + unsigned long base, size, pages; + struct bootmem_data *bdp; + int node; for (node = 0; node < numnodes; node++) { - bdp = BOOT_NODE_DATA(node)->bdata; + pg_data_t *pdp = mem_data[node].pgdat; + bdp = pdp->bdata; + + /* First the bootmem_map itself */ 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); + size = bootmem_bootmap_pages(pages) << PAGE_SHIFT; + base = __pa(bdp->node_bootmem_map); + reserve_bootmem_node(pdp, base, size); + + /* Now the per-node space */ + size = mem_data[node].pernode_size; + base = __pa(mem_data[node].pernode_addr); + reserve_bootmem_node(pdp, base, size); } } -/* - * 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; - } +/** + * initialize_pernode_data - fixup per-cpu & per-node pointers + * + * Each node's per-node area has a copy of the global pg_data_t list, so + * we copy that to each node here, as well as setting the per-cpu pointer + * to the local node data structure. The active_cpus field of the per-node + * structure gets setup by the platform_cpu_init() function later. + */ +static void __init initialize_pernode_data(void) +{ + int cpu, node; + pg_data_t *pgdat_list[NR_NODES]; - 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)); + for (node = 0; node < numnodes; node++) + pgdat_list[node] = mem_data[node].pgdat; - pgdat_list = new_pgdat_list; + /* Copy the pg_data_t list to each node and init the node field */ + for (node = 0; node < numnodes; node++) { + memcpy(mem_data[node].node_data->pg_data_ptrs, pgdat_list, + sizeof(pgdat_list)); + } + + /* Set the node_data pointer for each per-cpu struct */ + for (cpu = 0; cpu < NR_CPUS; cpu++) { + node = node_cpuid[cpu].nid; + per_cpu(cpu_info, cpu).node_data = mem_data[node].node_data; + } } -/* - * Called early in boot to setup the boot memory allocator, and to - * allocate the node-local pg_data & node-directory data structures.. +/** + * find_memory - walk the EFI memory map and setup the bootmem allocator + * + * Called early in boot to setup the bootmem allocator, and to + * allocate the per-cpu and per-node structures. */ void __init find_memory(void) { - int node; - reserve_memory(); if (numnodes == 0) { @@ -219,94 +321,48 @@ 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(); - - find_initrd(); -} - -/* - * 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 doesn't 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; + /* These actually end up getting called by call_pernode_memory() */ + efi_memmap_walk(filter_rsvd_memory, build_node_maps); + efi_memmap_walk(filter_rsvd_memory, find_pernode_space); + efi_memmap_walk(filter_rsvd_memory, free_node_bootmem); - mynode = boot_get_local_nodeid(); - for (node = 0; node < numnodes; node++) { - long pfn, startpfn; + reserve_pernode_space(); + initialize_pernode_data(); - memset(zones_size, 0, sizeof(zones_size)); + max_pfn = max_low_pfn; - 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; + find_initrd(); +} - bdp = BOOT_NODE_DATA(node)->bdata; +/** + * per_cpu_init - setup per-cpu variables + * + * find_pernode_space() does most of this already, we just need to set + * local_per_cpu_offset + */ +void *per_cpu_init(void) +{ + int cpu; - kaddr = (unsigned long)__va(bdp->node_boot_start); - ekaddr = (unsigned long)__va(bdp->node_low_pfn << PAGE_SHIFT); - while (kaddr < ekaddr) { - if (paddr_to_nid(__pa(kaddr)) == node) { - 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; + if (smp_processor_id() == 0) { + for (cpu = 0; cpu < NR_CPUS; cpu++) { + per_cpu(local_per_cpu_offset, cpu) = + __per_cpu_offset[cpu]; } } - /* - * 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; - } + return __per_cpu_start + __per_cpu_offset[smp_processor_id()]; } +/** + * show_mem - give short summary of memory stats + * + * Shows a simple page count of reserved and used pages in the system. + * For discontig machines, it does this on a per-pgdat basis. + */ void show_mem(void) { int i, reserved = 0; @@ -335,7 +391,12 @@ printk("%d free buffer pages\n", nr_free_buffer_pages()); } -/* +/** + * call_pernode_memory - use SRAT to call callback functions with node info + * @start: physical start of range + * @len: length of range + * @arg: function to call for each range + * * 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. @@ -343,10 +404,10 @@ * Take this opportunity to round the start address up and the end address * down to page boundaries. */ -void call_pernode_memory(unsigned long start, unsigned long end, void *arg) +void call_pernode_memory(unsigned long start, unsigned long len, void *arg) { - unsigned long rs, re; - void (*func)(unsigned long, unsigned long, int, int); + unsigned long rs, re, end = start + len; + void (*func)(unsigned long, unsigned long, int); int i; start = PAGE_ALIGN(start); @@ -357,21 +418,127 @@ func = arg; if (!num_memblks) { - /* - * This machine doesn't have SRAT, so call func with - * nid=0, bank=0. - */ + /* No SRAT table, to assume one node (node 0) */ if (start < end) - (*func)(start, end - start, 0, 0); + (*func)(start, len, 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); + 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); + (*func)(rs, re - rs, node_memblk[i].nid); + + if (re == end) + break; + } +} + +/** + * count_node_pages - callback to build per-node memory info structures + * @start: physical start of range + * @len: length of range + * @node: node where this range resides + * + * Each node has it's own number of physical pages, DMAable pages, start, and + * end page frame number. This routine will be called by call_pernode_memory() + * for each piece of usable memory and will setup these values for each node. + * Very similar to build_maps(). + */ +static int count_node_pages(unsigned long start, unsigned long len, int node) +{ + unsigned long end = start + len; + + mem_data[node].num_physpages += len >> PAGE_SHIFT; + if (start <= __pa(MAX_DMA_ADDRESS)) + mem_data[node].num_dma_physpages += + (min(end, __pa(MAX_DMA_ADDRESS)) - start) >>PAGE_SHIFT; + start = GRANULEROUNDDOWN(start); + start = ORDERROUNDDOWN(start); + end = GRANULEROUNDUP(end); + mem_data[node].max_pfn = max(mem_data[node].max_pfn, + end >> PAGE_SHIFT); + mem_data[node].min_pfn = min(mem_data[node].min_pfn, + start >> PAGE_SHIFT); + + return 0; +} + +/** + * paging_init - setup page tables + * + * paging_init() sets up the page tables for each node of the system and frees + * the bootmem allocator memory for general use. + */ +void paging_init(void) +{ + unsigned long max_dma; + unsigned long zones_size[MAX_NR_ZONES]; + unsigned long zholes_size[MAX_NR_ZONES]; + unsigned long max_gap, pfn_offset = 0; + int node; + + max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT; + max_gap = 0; + efi_memmap_walk(find_largest_hole, &max_gap); + + /* so min() will work in count_node_pages */ + for (node = 0; node < numnodes; node++) + mem_data[node].min_pfn = ~0UL; + + efi_memmap_walk(filter_rsvd_memory, count_node_pages); + + for (node = 0; node < numnodes; node++) { + memset(zones_size, 0, sizeof(zones_size)); + memset(zholes_size, 0, sizeof(zholes_size)); + + num_physpages += mem_data[node].num_physpages; + + if (mem_data[node].min_pfn >= max_dma) { + /* All of this node's memory is above ZONE_DMA */ + zones_size[ZONE_NORMAL] = mem_data[node].max_pfn - + mem_data[node].min_pfn; + zholes_size[ZONE_NORMAL] = mem_data[node].max_pfn - + mem_data[node].min_pfn - + mem_data[node].num_physpages; + } else if (mem_data[node].max_pfn < max_dma) { + /* All of this node's memory is in ZONE_DMA */ + zones_size[ZONE_DMA] = mem_data[node].max_pfn - + mem_data[node].min_pfn; + zholes_size[ZONE_DMA] = mem_data[node].max_pfn - + mem_data[node].min_pfn - + mem_data[node].num_dma_physpages; + } else { + /* This node has memory in both zones */ + zones_size[ZONE_DMA] = max_dma - + mem_data[node].min_pfn; + zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] - + mem_data[node].num_dma_physpages; + zones_size[ZONE_NORMAL] = mem_data[node].max_pfn - + max_dma; + zholes_size[ZONE_NORMAL] = zones_size[ZONE_NORMAL] - + (mem_data[node].num_physpages - + mem_data[node].num_dma_physpages); + } + + if (node == 0) { + vmalloc_end -= + PAGE_ALIGN(max_low_pfn * sizeof(struct page)); + vmem_map = (struct page *) vmalloc_end; + + efi_memmap_walk(create_mem_map_page_table, 0); + printk("Virtual mem_map starts at 0x%p\n", vmem_map); + } + + pfn_offset = mem_data[node].min_pfn; + + free_area_init_node(node, NODE_DATA(node), + vmem_map + pfn_offset, zones_size, + pfn_offset, zholes_size); } + + zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page)); } diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c --- a/arch/ia64/mm/hugetlbpage.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/mm/hugetlbpage.c Fri Oct 17 14:43:50 2003 @@ -20,13 +20,46 @@ #define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT) -static long htlbpagemem; -int htlbpage_max; -static long htlbzone_pages; +static long htlbpagemem; +int htlbpage_max; +static long htlbzone_pages; -static LIST_HEAD(htlbpage_freelist); +static struct list_head hugepage_freelists[MAX_NUMNODES]; static spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED; +static void enqueue_huge_page(struct page *page) +{ + list_add(&page->list, + &hugepage_freelists[page_zone(page)->zone_pgdat->node_id]); +} + +static struct page *dequeue_huge_page(void) +{ + int nid = numa_node_id(); + struct page *page = NULL; + + if (list_empty(&hugepage_freelists[nid])) { + for (nid = 0; nid < MAX_NUMNODES; ++nid) + if (!list_empty(&hugepage_freelists[nid])) + break; + } + if (nid >= 0 && nid < MAX_NUMNODES && + !list_empty(&hugepage_freelists[nid])) { + page = list_entry(hugepage_freelists[nid].next, struct page, list); + list_del(&page->list); + } + return page; +} + +static struct page *alloc_fresh_huge_page(void) +{ + static int nid = 0; + struct page *page; + page = alloc_pages_node(nid, GFP_HIGHUSER, HUGETLB_PAGE_ORDER); + nid = (nid + 1) % numnodes; + return page; +} + void free_huge_page(struct page *page); static struct page *alloc_hugetlb_page(void) @@ -35,13 +68,11 @@ struct page *page; spin_lock(&htlbpage_lock); - if (list_empty(&htlbpage_freelist)) { + page = dequeue_huge_page(); + if (!page) { spin_unlock(&htlbpage_lock); return NULL; } - - page = list_entry(htlbpage_freelist.next, struct page, list); - list_del(&page->list); htlbpagemem--; spin_unlock(&htlbpage_lock); set_page_count(page, 1); @@ -228,7 +259,7 @@ INIT_LIST_HEAD(&page->list); spin_lock(&htlbpage_lock); - list_add(&page->list, &htlbpage_freelist); + enqueue_huge_page(page); htlbpagemem++; spin_unlock(&htlbpage_lock); } @@ -371,7 +402,7 @@ map = NULL; spin_lock(&htlbpage_lock); - list_for_each(p, &htlbpage_freelist) { + list_for_each(p, &hugepage_freelists[0]) { if (map) { list_del(&map->list); update_and_free_page(map); @@ -408,11 +439,11 @@ return (int)htlbzone_pages; if (lcount > 0) { /* Increase the mem size. */ while (lcount--) { - page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER); + page = alloc_fresh_huge_page(); if (page == NULL) break; spin_lock(&htlbpage_lock); - list_add(&page->list, &htlbpage_freelist); + enqueue_huge_page(page); htlbpagemem++; htlbzone_pages++; spin_unlock(&htlbpage_lock); @@ -449,17 +480,18 @@ static int __init hugetlb_init(void) { - int i, j; + int i; struct page *page; + for (i = 0; i < MAX_NUMNODES; ++i) + INIT_LIST_HEAD(&hugepage_freelists[i]); + for (i = 0; i < htlbpage_max; ++i) { - page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER); + page = alloc_fresh_huge_page(); if (!page) break; - for (j = 0; j < HPAGE_SIZE/PAGE_SIZE; ++j) - SetPageReserved(&page[j]); spin_lock(&htlbpage_lock); - list_add(&page->list, &htlbpage_freelist); + enqueue_huge_page(page); spin_unlock(&htlbpage_lock); } htlbpage_max = htlbpagemem = htlbzone_pages = i; diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c --- a/arch/ia64/mm/init.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/mm/init.c Fri Oct 17 14:43:50 2003 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -40,10 +41,8 @@ unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL; #ifdef CONFIG_VIRTUAL_MEM_MAP -# define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */ unsigned long vmalloc_end = VMALLOC_END_INIT; - static struct page *vmem_map; - static unsigned long num_dma_physpages; + struct page *vmem_map; #endif static int pgt_cache_water[2] = { 25, 50 }; @@ -337,11 +336,12 @@ #ifdef CONFIG_VIRTUAL_MEM_MAP -static int +int create_mem_map_page_table (u64 start, u64 end, void *arg) { unsigned long address, start_page, end_page; struct page *map_start, *map_end; + int node; pgd_t *pgd; pmd_t *pmd; pte_t *pte; @@ -351,19 +351,20 @@ start_page = (unsigned long) map_start & PAGE_MASK; end_page = PAGE_ALIGN((unsigned long) map_end); + node = paddr_to_nid(__pa(start)); for (address = start_page; address < end_page; address += PAGE_SIZE) { pgd = pgd_offset_k(address); if (pgd_none(*pgd)) - pgd_populate(&init_mm, pgd, alloc_bootmem_pages(PAGE_SIZE)); + pgd_populate(&init_mm, pgd, alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE)); pmd = pmd_offset(pgd, address); if (pmd_none(*pmd)) - pmd_populate_kernel(&init_mm, pmd, alloc_bootmem_pages(PAGE_SIZE)); + pmd_populate_kernel(&init_mm, pmd, alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE)); pte = pte_offset_kernel(pmd, address); if (pte_none(*pte)) - set_pte(pte, pfn_pte(__pa(alloc_bootmem_pages(PAGE_SIZE)) >> PAGE_SHIFT, + set_pte(pte, pfn_pte(__pa(alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE)) >> PAGE_SHIFT, PAGE_KERNEL)); } return 0; @@ -433,17 +434,7 @@ return __get_user(byte, (char *) pfn_to_page(pfn)) == 0; } -static int -count_dma_pages (u64 start, u64 end, void *arg) -{ - unsigned long *count = arg; - - if (end <= MAX_DMA_ADDRESS) - *count += (end - start) >> PAGE_SHIFT; - return 0; -} - -static int +int find_largest_hole (u64 start, u64 end, void *arg) { u64 *max_gap = arg; @@ -458,103 +449,6 @@ return 0; } #endif /* CONFIG_VIRTUAL_MEM_MAP */ - -static int -count_pages (u64 start, u64 end, void *arg) -{ - unsigned long *count = arg; - - *count += (end - start) >> PAGE_SHIFT; - return 0; -} - -/* - * Set up the page tables. - */ - -#ifdef CONFIG_DISCONTIGMEM -void -paging_init (void) -{ - extern void discontig_paging_init(void); - - discontig_paging_init(); - efi_memmap_walk(count_pages, &num_physpages); - zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page)); -} -#else /* !CONFIG_DISCONTIGMEM */ -void -paging_init (void) -{ - unsigned long max_dma; - unsigned long zones_size[MAX_NR_ZONES]; -# ifdef CONFIG_VIRTUAL_MEM_MAP - unsigned long zholes_size[MAX_NR_ZONES]; - unsigned long max_gap; -# endif - - /* initialize mem_map[] */ - - memset(zones_size, 0, sizeof(zones_size)); - - num_physpages = 0; - efi_memmap_walk(count_pages, &num_physpages); - - max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT; - -# ifdef CONFIG_VIRTUAL_MEM_MAP - memset(zholes_size, 0, sizeof(zholes_size)); - - num_dma_physpages = 0; - efi_memmap_walk(count_dma_pages, &num_dma_physpages); - - if (max_low_pfn < max_dma) { - zones_size[ZONE_DMA] = max_low_pfn; - zholes_size[ZONE_DMA] = max_low_pfn - num_dma_physpages; - } else { - zones_size[ZONE_DMA] = max_dma; - zholes_size[ZONE_DMA] = max_dma - num_dma_physpages; - if (num_physpages > num_dma_physpages) { - zones_size[ZONE_NORMAL] = max_low_pfn - max_dma; - zholes_size[ZONE_NORMAL] = ((max_low_pfn - max_dma) - - (num_physpages - num_dma_physpages)); - } - } - - max_gap = 0; - efi_memmap_walk(find_largest_hole, (u64 *)&max_gap); - if (max_gap < LARGE_GAP) { - vmem_map = (struct page *) 0; - free_area_init_node(0, &contig_page_data, NULL, zones_size, 0, zholes_size); - mem_map = contig_page_data.node_mem_map; - } - else { - unsigned long map_size; - - /* allocate virtual_mem_map */ - - map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page)); - vmalloc_end -= map_size; - vmem_map = (struct page *) vmalloc_end; - efi_memmap_walk(create_mem_map_page_table, 0); - - free_area_init_node(0, &contig_page_data, vmem_map, zones_size, 0, zholes_size); - - mem_map = contig_page_data.node_mem_map; - printk("Virtual mem_map starts at 0x%p\n", mem_map); - } -# else /* !CONFIG_VIRTUAL_MEM_MAP */ - if (max_low_pfn < max_dma) - zones_size[ZONE_DMA] = max_low_pfn; - else { - zones_size[ZONE_DMA] = max_dma; - zones_size[ZONE_NORMAL] = max_low_pfn - max_dma; - } - free_area_init(zones_size); -# endif /* !CONFIG_VIRTUAL_MEM_MAP */ - zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page)); -} -#endif /* !CONFIG_DISCONTIGMEM */ static int count_reserved_pages (u64 start, u64 end, void *arg) diff -Nru a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c --- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c Fri Oct 17 14:43:50 2003 @@ -867,6 +867,9 @@ int i = 0; struct pci_controller *controller; + if (!ia64_platform_is("sn2")) + return 0; + /* * set pci_raw_ops, etc. */ diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_intr.c b/arch/ia64/sn/io/sn2/ml_SN_intr.c --- a/arch/ia64/sn/io/sn2/ml_SN_intr.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/sn/io/sn2/ml_SN_intr.c Fri Oct 17 14:43:50 2003 @@ -285,7 +285,6 @@ cpuid_t intr_heuristic(vertex_hdl_t dev, int req_bit, int *resp_bit) { cpuid_t cpuid; - cpuid_t candidate = CPU_NONE; vertex_hdl_t pconn_vhdl; pcibr_soft_t pcibr_soft; int bit; @@ -293,30 +292,32 @@ /* XXX: gross layering violation.. */ if (hwgraph_edge_get(dev, EDGE_LBL_PCI, &pconn_vhdl) == GRAPH_SUCCESS) { pcibr_soft = pcibr_soft_get(pconn_vhdl); - if (pcibr_soft && pcibr_soft->bsi_err_intr) - candidate = ((hub_intr_t)pcibr_soft->bsi_err_intr)->i_cpuid; - } - - if (candidate != CPU_NONE) { - /* - * The cpu was chosen already when we assigned - * the error interrupt. - */ - bit = intr_reserve_level(candidate, req_bit); - if (bit >= 0) { - *resp_bit = bit; - return candidate; + if (pcibr_soft && pcibr_soft->bsi_err_intr) { + /* + * The cpu was chosen already when we assigned + * the error interrupt. + */ + cpuid = ((hub_intr_t)pcibr_soft->bsi_err_intr)->i_cpuid; + goto done; } - - printk("Cannot target interrupt to target node (%ld).\n",candidate); - return CPU_NONE; } /* * Need to choose one. Try the controlling c-brick first. */ cpuid = intr_cpu_choose_from_node(master_node_get(dev)); - if (cpuid != CPU_NONE) - return cpuid; - return intr_cpu_choose_node(); + if (cpuid == CPU_NONE) + cpuid = intr_cpu_choose_node(); + + done: + if (cpuid != CPU_NONE) { + bit = intr_reserve_level(cpuid, req_bit); + if (bit >= 0) { + *resp_bit = bit; + return cpuid; + } + } + + printk("Cannot target interrupt to target cpu (%ld).\n", cpuid); + return CPU_NONE; } diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c --- a/arch/ia64/sn/kernel/setup.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/sn/kernel/setup.c Fri Oct 17 14:43:50 2003 @@ -147,7 +147,6 @@ * Sets up an initial console to aid debugging. Intended primarily * for bringup. See start_kernel() in init/main.c. */ -#if defined(CONFIG_IA64_EARLY_PRINTK_SGI_SN) || defined(CONFIG_IA64_SGI_SN_SIM) void __init early_sn_setup(void) @@ -189,7 +188,6 @@ printk(KERN_DEBUG "early_sn_setup: setting master_node_bedrock_address to 0x%lx\n", master_node_bedrock_address); } } -#endif /* CONFIG_IA64_EARLY_PRINTK_SGI_SN */ #ifdef CONFIG_IA64_MCA extern int platform_intr_list[]; diff -Nru a/arch/ia64/sn/kernel/sn2/io.c b/arch/ia64/sn/kernel/sn2/io.c --- a/arch/ia64/sn/kernel/sn2/io.c Fri Oct 17 14:43:50 2003 +++ b/arch/ia64/sn/kernel/sn2/io.c Fri Oct 17 14:43:50 2003 @@ -11,6 +11,8 @@ #include +#ifdef CONFIG_IA64_GENERIC + #undef __sn_inb #undef __sn_inw #undef __sn_inl @@ -81,3 +83,5 @@ { return ___sn_readq (addr); } + +#endif diff -Nru a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c --- a/arch/m68k/lib/checksum.c Fri Oct 17 14:43:51 2003 +++ b/arch/m68k/lib/checksum.c Fri Oct 17 14:43:51 2003 @@ -125,6 +125,7 @@ return(sum); } +EXPORT_SYMBOL(csum_partial); /* diff -Nru a/arch/m68k/sun3/sbus.c b/arch/m68k/sun3/sbus.c --- a/arch/m68k/sun3/sbus.c Fri Oct 17 14:43:50 2003 +++ b/arch/m68k/sun3/sbus.c Fri Oct 17 14:43:50 2003 @@ -10,6 +10,7 @@ */ #include +#include #include int __init sbus_init(void) diff -Nru a/arch/ppc/8260_io/Kconfig b/arch/ppc/8260_io/Kconfig --- a/arch/ppc/8260_io/Kconfig Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/8260_io/Kconfig Fri Oct 17 14:43:50 2003 @@ -57,14 +57,5 @@ bool "QS6612" endchoice - -comment "Generic MPC8260 Options" - -config DCACHE_DISABLE - bool "Disable data cache" - help - This option allows you to run the kernel with data cache disabled. - Say Y if you experience CPM lock-ups. - endmenu diff -Nru a/arch/ppc/Makefile b/arch/ppc/Makefile --- a/arch/ppc/Makefile Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/Makefile Fri Oct 17 14:43:50 2003 @@ -65,7 +65,13 @@ $(Q)$(MAKE) $(build)=$(boot)/images $(boot)/images/$@ define archhelp + @echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/images/zImage.*)' @echo ' uImage - Create a bootable image for U-Boot / PPCBoot' + @echo ' install - Install kernel using' + @echo ' (your) ~/bin/installkernel or' + @echo ' (distribution) /sbin/installkernel or' + @echo ' install to $$(INSTALL_PATH) and run lilo' + @echo ' *_defconfig - Select default config from arch/$(ARCH)/ppc/configs' endef archclean: diff -Nru a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c --- a/arch/ppc/boot/common/ns16550.c Fri Oct 17 14:43:51 2003 +++ b/arch/ppc/boot/common/ns16550.c Fri Oct 17 14:43:51 2003 @@ -3,6 +3,8 @@ */ #include +#include +#include #include #include #include diff -Nru a/arch/ppc/boot/of1275/map.c b/arch/ppc/boot/of1275/map.c --- a/arch/ppc/boot/of1275/map.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/boot/of1275/map.c Fri Oct 17 14:43:50 2003 @@ -23,11 +23,10 @@ char *method; ihandle mmu_ihandle; int misc; - unsigned int phys; - unsigned int virt; unsigned int size; + unsigned int virt; + unsigned int phys; int ret0; - int ret1; } args; if (of_prom_mmu == 0) { @@ -36,10 +35,10 @@ } args.service = "call-method"; args.nargs = 6; - args.nret = 2; + args.nret = 1; args.method = "map"; args.mmu_ihandle = of_prom_mmu; - args.misc = -1; + args.misc = 0; args.phys = phys; args.virt = virt; args.size = size; diff -Nru a/arch/ppc/boot/openfirmware/coffmain.c b/arch/ppc/boot/openfirmware/coffmain.c --- a/arch/ppc/boot/openfirmware/coffmain.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/boot/openfirmware/coffmain.c Fri Oct 17 14:43:50 2003 @@ -38,9 +38,9 @@ static unsigned long ram_start = 0; static unsigned long ram_end = 0x1000000; -static unsigned long prog_start = 0x800000; -static unsigned long prog_size = 0x800000; +static unsigned long prog_start = 0x900000; +static unsigned long prog_size = 0x700000; typedef void (*kernel_start_t)(int, int, void *); diff -Nru a/arch/ppc/configs/TQM8260_defconfig b/arch/ppc/configs/TQM8260_defconfig --- a/arch/ppc/configs/TQM8260_defconfig Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/configs/TQM8260_defconfig Fri Oct 17 14:43:50 2003 @@ -469,11 +469,6 @@ # CONFIG_FCC3_ENET is not set # -# Generic MPC8260 Options -# -CONFIG_DCACHE_DISABLE=y - -# # USB support # # CONFIG_USB_GADGET is not set diff -Nru a/arch/ppc/configs/est8260_defconfig b/arch/ppc/configs/est8260_defconfig --- a/arch/ppc/configs/est8260_defconfig Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/configs/est8260_defconfig Fri Oct 17 14:43:50 2003 @@ -461,11 +461,6 @@ CONFIG_SCC_CONSOLE=y # -# Generic MPC8260 Options -# -# CONFIG_DCACHE_DISABLE is not set - -# # USB support # # CONFIG_USB_GADGET is not set diff -Nru a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S --- a/arch/ppc/kernel/cpu_setup_6xx.S Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/kernel/cpu_setup_6xx.S Fri Oct 17 14:43:50 2003 @@ -75,11 +75,7 @@ setup_common_caches: mfspr r11,HID0 andi. r0,r11,HID0_DCE -#ifdef CONFIG_DCACHE_DISABLE - ori r11,r11,HID0_ICE -#else ori r11,r11,HID0_ICE|HID0_DCE -#endif ori r8,r11,HID0_ICFI bne 1f /* don't invalidate the D-cache */ ori r8,r8,HID0_DCI /* unless it wasn't enabled */ diff -Nru a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S --- a/arch/ppc/kernel/head.S Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/kernel/head.S Fri Oct 17 14:43:50 2003 @@ -181,26 +181,8 @@ bl setup_disp_bat #endif #else /* CONFIG_POWER4 */ -/* - * Load up the SDR1 and segment register values now - * since we don't have the BATs. - * Also make sure we are running in 32-bit mode. - */ bl reloc_offset - addis r14,r3,_SDR1@ha /* get the value from _SDR1 */ - lwz r14,_SDR1@l(r14) /* assume hash table below 4GB */ - mtspr SDR1,r14 - slbia - lis r4,0x2000 /* set pseudo-segment reg 12 */ - ori r5,r4,0x0ccc - mtsr 12,r5 - ori r4,r4,0x0888 /* set pseudo-segment reg 8 */ - mtsr 8,r4 /* (for access to serial port) */ - mfmsr r0 - clrldi r0,r0,1 - sync - mtmsr r0 - isync + bl initial_mm_power4 #endif /* CONFIG_POWER4 */ /* @@ -1637,6 +1619,34 @@ #endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */ #else /* CONFIG_POWER4 */ +/* + * Load up the SDR1 and segment register values now + * since we don't have the BATs. + * Also make sure we are running in 32-bit mode. + */ + +initial_mm_power4: + addis r14,r3,_SDR1@ha /* get the value from _SDR1 */ + lwz r14,_SDR1@l(r14) /* assume hash table below 4GB */ + mtspr SDR1,r14 + slbia + lis r4,0x2000 /* set pseudo-segment reg 12 */ + ori r5,r4,0x0ccc + mtsr 12,r5 + ori r5,r4,0x0888 /* set pseudo-segment reg 8 */ + mtsr 8,r5 /* (for access to serial port) */ + ori r5,r4,0x0999 /* set pseudo-segment reg 8 */ + mtsr 9,r5 /* (for access to screen) */ + mfmsr r0 + clrldi r0,r0,1 + sync + mtmsr r0 + isync + blr + +/* + * On 970 (G5), we pre-set a few bits in HID0 & HID1 + */ ppc970_setup_hid: li r0,0 sync diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c --- a/arch/ppc/kernel/ppc_ksyms.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/kernel/ppc_ksyms.c Fri Oct 17 14:43:50 2003 @@ -123,7 +123,7 @@ EXPORT_SYMBOL(strcasecmp); EXPORT_SYMBOL(__div64_32); -/* EXPORT_SYMBOL(csum_partial); already in net/netsyms.c */ +EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy_generic); EXPORT_SYMBOL(ip_fast_csum); EXPORT_SYMBOL(csum_tcpudp_magic); @@ -367,11 +367,17 @@ EXPORT_SYMBOL(set_context); EXPORT_SYMBOL(handle_mm_fault); /* For MOL */ EXPORT_SYMBOL_NOVERS(disarm_decr); +extern long mol_trampoline; +EXPORT_SYMBOL(mol_trampoline); /* For MOL */ #ifdef CONFIG_PPC_STD_MMU EXPORT_SYMBOL(flush_hash_pages); /* For MOL */ +#ifdef CONFIG_SMP +extern int mmu_hash_lock; +EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */ +#endif /* CONFIG_SMP */ extern long *intercept_table; EXPORT_SYMBOL(intercept_table); -#endif +#endif /* CONFIG_PPC_STD_MMU */ EXPORT_SYMBOL(cur_cpu_spec); #ifdef CONFIG_PPC_PMAC extern unsigned long agp_special_page; diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/kernel/process.c Fri Oct 17 14:43:50 2003 @@ -56,6 +56,7 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct mm_struct init_mm = INIT_MM(init_mm); +EXPORT_SYMBOL(init_mm); /* this is 8kB-aligned so we can get to the thread_info struct at the base of it from the stack pointer with 1 integer instruction. */ @@ -65,6 +66,7 @@ /* initial task structure */ struct task_struct init_task = INIT_TASK(init_task); +EXPORT_SYMBOL(init_task); /* only used to get secondary processor up */ struct task_struct *current_set[NR_CPUS] = {&init_task, }; diff -Nru a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c --- a/arch/ppc/kernel/setup.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/kernel/setup.c Fri Oct 17 14:43:50 2003 @@ -171,12 +171,12 @@ return 0; pvr = cpu_data[i].pvr; lpj = cpu_data[i].loops_per_jiffy; - seq_printf(m, "processor\t: %d\n", i); #else pvr = mfspr(PVR); lpj = loops_per_jiffy; #endif + seq_printf(m, "processor\t: %d\n", i); seq_printf(m, "cpu\t\t: "); if (cur_cpu_spec[i]->pvr_mask) diff -Nru a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S --- a/arch/ppc/mm/hashtable.S Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/mm/hashtable.S Fri Oct 17 14:43:50 2003 @@ -417,6 +417,21 @@ lwz r6,next_slot@l(r4) addi r6,r6,PTE_SIZE andi. r6,r6,7*PTE_SIZE +#ifdef CONFIG_POWER4 + /* + * Since we don't have BATs on POWER4, we rely on always having + * PTEs in the hash table to map the hash table and the code + * that manipulates it in virtual mode, namely flush_hash_page and + * flush_hash_segments. Otherwise we can get a DSI inside those + * routines which leads to a deadlock on the hash_table_lock on + * SMP machines. We avoid this by never overwriting the first + * PTE of each PTEG if it is already valid. + * -- paulus. + */ + bne 102f + li r6,PTE_SIZE +102: +#endif /* CONFIG_POWER4 */ stw r6,next_slot@l(r4) add r4,r3,r6 diff -Nru a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c --- a/arch/ppc/mm/ppc_mmu.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/mm/ppc_mmu.c Fri Oct 17 14:43:50 2003 @@ -211,6 +211,17 @@ #define MIN_N_HPTEG 1024 /* min 64kB hash table */ #endif +#ifdef CONFIG_POWER4 + /* The hash table has already been allocated and initialized + in prom.c */ + n_hpteg = Hash_size >> LG_HPTEG_SIZE; + lg_n_hpteg = __ilog2(n_hpteg); + + /* Remove the hash table from the available memory */ + if (Hash) + reserve_phys_mem(__pa(Hash), Hash_size); + +#else /* CONFIG_POWER4 */ /* * Allow 1 HPTE (1/8 HPTEG) for each page of memory. * This is less than the recommended amount, but then @@ -224,13 +235,7 @@ ++lg_n_hpteg; /* round up if not power of 2 */ n_hpteg = 1 << lg_n_hpteg; } - Hash_size = n_hpteg << LG_HPTEG_SIZE; - Hash_mask = n_hpteg - 1; - hmask = Hash_mask >> (16 - LG_HPTEG_SIZE); - mb2 = mb = 32 - LG_HPTEG_SIZE - lg_n_hpteg; - if (lg_n_hpteg > 16) - mb2 = 16 - LG_HPTEG_SIZE; /* * Find some memory for the hash table. @@ -240,6 +245,7 @@ cacheable_memzero(Hash, Hash_size); _SDR1 = __pa(Hash) | SDR1_LOW_BITS; Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); +#endif /* CONFIG_POWER4 */ printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", total_memory >> 20, Hash_size >> 10, Hash); @@ -249,6 +255,12 @@ * Patch up the instructions in hashtable.S:create_hpte */ if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345); + Hash_mask = n_hpteg - 1; + hmask = Hash_mask >> (16 - LG_HPTEG_SIZE); + mb2 = mb = 32 - LG_HPTEG_SIZE - lg_n_hpteg; + if (lg_n_hpteg > 16) + mb2 = 16 - LG_HPTEG_SIZE; + hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff) | ((unsigned int)(Hash) >> 16); hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) | (mb << 6); diff -Nru a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c --- a/arch/ppc/platforms/pmac_smp.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/platforms/pmac_smp.c Fri Oct 17 14:43:50 2003 @@ -51,6 +51,7 @@ #include #include #include +#include /* * Powersurge (old powermac SMP) support. @@ -108,9 +109,16 @@ /* what sort of powersurge board we have */ static int psurge_type = PSURGE_NONE; +/* L2 and L3 cache settings to pass from CPU0 to CPU1 */ volatile static long int core99_l2_cache; volatile static long int core99_l3_cache; +/* Timebase freeze GPIO */ +static unsigned int core99_tb_gpio; + +/* Sync flag for HW tb sync */ +static volatile int sec_tb_reset = 0; + static void __init core99_init_caches(int cpu) { @@ -380,7 +388,6 @@ */ static void __init psurge_dual_sync_tb(int cpu_nr) { - static volatile int sec_tb_reset = 0; int t; set_dec(tb_ticks_per_jiffy); @@ -408,8 +415,15 @@ { if (cpu_nr == 0) { - if (num_online_cpus() < 2) + /* If we failed to start the second CPU, we should still + * send it an IPI to start the timebase & DEC or we might + * have them stuck. + */ + if (num_online_cpus() < 2) { + if (psurge_type == PSURGE_DUAL) + psurge_set_ipi(1); return; + } /* reset the entry point so if we get another intr we won't * try to startup again */ out_be32(psurge_start, 0x100); @@ -421,19 +435,42 @@ psurge_dual_sync_tb(cpu_nr); } +void __init +smp_psurge_take_timebase(void) +{ + /* Dummy implementation */ +} + +void __init +smp_psurge_give_timebase(void) +{ + /* Dummy implementation */ +} + static int __init smp_core99_probe(void) { + extern int powersave_nap; struct device_node *cpus; int i, ncpus = 1; - extern int powersave_nap; + u32 *tbprop; if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); cpus = find_type_devices("cpu"); - if (cpus) - while ((cpus = cpus->next) != NULL) - ++ncpus; + if (cpus == NULL) + return 0; + + tbprop = (u32 *)get_property(cpus, "timebase-enable", NULL); + if (tbprop) + core99_tb_gpio = *tbprop; + else + core99_tb_gpio = KL_GPIO_TB_ENABLE; + + while ((cpus = cpus->next) != NULL) + ++ncpus; + printk("smp_core99_probe: found %d cpus\n", ncpus); + if (ncpus > 1) { openpic_request_IPIs(); for (i = 1; i < ncpus; ++i) @@ -517,14 +554,59 @@ if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); } +void __init +smp_core99_take_timebase(void) +{ + /* Secondary processor "takes" the timebase by freezing + * it, resetting its local TB and telling CPU 0 to go on + */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4); + pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); + mb(); + + set_dec(tb_ticks_per_jiffy); + set_tb(0, 0); + last_jiffy_stamp(smp_processor_id()) = 0; + + mb(); + sec_tb_reset = 1; +} + +void __init +smp_core99_give_timebase(void) +{ + unsigned int t; + + /* Primary processor waits for secondary to have frozen + * the timebase, resets local TB, and kick timebase again + */ + /* wait for the secondary to have reset its TB before proceeding */ + for (t = 1000; t > 0 && !sec_tb_reset; --t) + udelay(1000); + if (t == 0) + printk(KERN_WARNING "Timeout waiting sync on second CPU\n"); + + set_dec(tb_ticks_per_jiffy); + set_tb(0, 0); + last_jiffy_stamp(smp_processor_id()) = 0; + mb(); + + /* Now, restart the timebase by leaving the GPIO to an open collector */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); + pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); + + smp_tb_synchronized = 1; +} + + /* PowerSurge-style Macs */ struct smp_ops_t psurge_smp_ops __pmacdata = { .message_pass = smp_psurge_message_pass, .probe = smp_psurge_probe, .kick_cpu = smp_psurge_kick_cpu, .setup_cpu = smp_psurge_setup_cpu, - .give_timebase = smp_generic_give_timebase, - .take_timebase = smp_generic_take_timebase, + .give_timebase = smp_psurge_give_timebase, + .take_timebase = smp_psurge_take_timebase, }; /* Core99 Macs (dual G4s) */ @@ -533,6 +615,6 @@ .probe = smp_core99_probe, .kick_cpu = smp_core99_kick_cpu, .setup_cpu = smp_core99_setup_cpu, - .give_timebase = smp_generic_give_timebase, - .take_timebase = smp_generic_take_timebase, + .give_timebase = smp_core99_give_timebase, + .take_timebase = smp_core99_take_timebase, }; diff -Nru a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c --- a/arch/ppc/platforms/pmac_time.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc/platforms/pmac_time.c Fri Oct 17 14:43:50 2003 @@ -166,7 +166,7 @@ { struct device_node *vias; volatile unsigned char *via; - int count = VIA_TIMER_FREQ_6 / HZ; + int count = VIA_TIMER_FREQ_6 / 100; unsigned int dstart, dend; vias = find_devices("via-cuda"); @@ -196,7 +196,7 @@ ; dend = get_dec(); - tb_ticks_per_jiffy = (dstart - dend) / 6; + tb_ticks_per_jiffy = (dstart - dend) / (6 * (HZ/100)); tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", @@ -260,7 +260,9 @@ * calibration. That's better since the VIA itself seems * to be slightly off. --BenH */ - if (!machine_is_compatible("MacRISC2")) + if (!machine_is_compatible("MacRISC2") && + !machine_is_compatible("MacRISC3") && + !machine_is_compatible("MacRISC4")) if (via_calibrate_decr()) return; diff -Nru a/arch/ppc/syslib/of_device.c b/arch/ppc/syslib/of_device.c --- a/arch/ppc/syslib/of_device.c Fri Oct 17 14:43:51 2003 +++ b/arch/ppc/syslib/of_device.c Fri Oct 17 14:43:51 2003 @@ -97,9 +97,9 @@ static int of_device_remove(struct device *dev) { struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(of_dev->dev.driver); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - if (drv && drv->remove) + if (dev->driver && drv->remove) drv->remove(of_dev); return 0; } @@ -107,10 +107,10 @@ static int of_device_suspend(struct device *dev, u32 state) { struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(of_dev->dev.driver); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); int error = 0; - if (drv && drv->suspend) + if (dev->driver && drv->suspend) error = drv->suspend(of_dev, state); return error; } @@ -118,10 +118,10 @@ static int of_device_resume(struct device * dev) { struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(of_dev->dev.driver); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); int error = 0; - if (drv && drv->resume) + if (dev->driver && drv->resume) error = drv->resume(of_dev); return error; } diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/kernel/head.S Fri Oct 17 14:43:50 2003 @@ -937,7 +937,6 @@ mfspr r20,SPRG2 mfspr r21,SPRG1 rfid -_TRACEBACK(do_stab_bolted) /* * r20 points to the PACA, r21 to the exception frame, @@ -1052,7 +1051,6 @@ mfspr r20,SPRG2 mfspr r21,SPRG1 rfid -_TRACEBACK(do_slb_bolted) _GLOBAL(do_stab_SI) mflr r21 /* Save LR in r21 */ diff -Nru a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c --- a/arch/ppc64/kernel/idle.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/kernel/idle.c Fri Oct 17 14:43:50 2003 @@ -84,8 +84,6 @@ lpaca = get_paca(); while (1) { - irq_stat[smp_processor_id()].idle_timestamp = jiffies; - if (lpaca->xLpPaca.xSharedProc) { if (ItLpQueue_isLpIntPending(lpaca->lpQueuePtr)) process_iSeries_events(); @@ -125,7 +123,6 @@ long oldval; while (1) { - irq_stat[smp_processor_id()].idle_timestamp = jiffies; oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); if (!oldval) { diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/kernel/irq.c Fri Oct 17 14:43:50 2003 @@ -55,9 +55,6 @@ #include #include -void enable_irq(unsigned int irq_nr); -void disable_irq(unsigned int irq_nr); - #ifdef CONFIG_SMP extern void iSeries_smp_message_recv( struct pt_regs * ); #endif @@ -123,7 +120,7 @@ if (!shared) { desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); unmask_irq(irq); } spin_unlock_irqrestore(&desc->lock,flags); @@ -140,6 +137,8 @@ cpu_relax(); } +EXPORT_SYMBOL(synchronize_irq); + #endif /* CONFIG_SMP */ /* XXX Make this into free_irq() - Anton */ @@ -244,7 +243,7 @@ * This function may be called from IRQ context. */ - void disable_irq_nosync(unsigned int irq) +inline void disable_irq_nosync(unsigned int irq) { irq_desc_t *desc = irq_desc + irq; unsigned long flags; @@ -258,6 +257,8 @@ spin_unlock_irqrestore(&desc->lock, flags); } +EXPORT_SYMBOL(disable_irq_nosync); + /** * disable_irq - disable an irq and wait for completion * @irq: Interrupt to disable @@ -273,10 +274,14 @@ void disable_irq(unsigned int irq) { + irq_desc_t *desc = irq_desc + irq; disable_irq_nosync(irq); - synchronize_irq(irq); + if (desc->action) + synchronize_irq(irq); } +EXPORT_SYMBOL(disable_irq); + /** * enable_irq - enable interrupt handling on an irq * @irq: Interrupt to enable @@ -295,7 +300,7 @@ spin_lock_irqsave(&desc->lock, flags); switch (desc->depth) { case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; + unsigned int status = desc->status & ~(IRQ_DISABLED | IRQ_INPROGRESS); desc->status = status; if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { desc->status = status | IRQ_REPLAY; @@ -308,11 +313,14 @@ desc->depth--; break; case 0: - printk("enable_irq(%u) unbalanced\n", irq); + printk("enable_irq(%u) unbalanced from %p\n", irq, + __builtin_return_address(0)); } spin_unlock_irqrestore(&desc->lock, flags); } +EXPORT_SYMBOL(enable_irq); + int show_interrupts(struct seq_file *p, void *v) { int i, j; @@ -668,7 +676,7 @@ static unsigned int parse_hex_value (const char *buffer, unsigned long count, cpumask_t *ret) { - unsigned char hexnum [HEX_DIGITS]; + unsigned char hexnum[HEX_DIGITS]; cpumask_t value = CPU_MASK_NONE; int i; @@ -680,7 +688,7 @@ return -EFAULT; /* - * Parse the first 16 characters as a hex string, any non-hex char + * Parse the first HEX_DIGITS characters as a hex string, any non-hex char * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same. */ @@ -699,7 +707,6 @@ for (k = 0; k < 4; ++k) if (test_bit(k, (unsigned long *)&c)) cpu_set(k, value); - } out: *ret = value; @@ -716,6 +723,8 @@ return -EIO; err = parse_hex_value(buffer, count, &new_value); + if (err) + return err; /* * Do not allow disabling IRQs completely - it's a too easy @@ -741,7 +750,7 @@ return sprintf (page, "%08lx\n", *mask); } -static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, +static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer, unsigned long count, void *data) { cpumask_t *mask = (cpumask_t *)data; @@ -789,10 +798,12 @@ /* create /proc/irq/1234/smp_affinity */ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); - entry->nlink = 1; - entry->data = (void *)(long)irq; - entry->read_proc = irq_affinity_read_proc; - entry->write_proc = irq_affinity_write_proc; + if (entry) { + entry->nlink = 1; + entry->data = (void *)(long)irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + } smp_affinity_entry[irq] = entry; } @@ -809,6 +820,9 @@ /* create /proc/irq/prof_cpu_mask */ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); + + if (!entry) + return; entry->nlink = 1; entry->data = (void *)&prof_cpu_mask; diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/kernel/misc.S Fri Oct 17 14:43:50 2003 @@ -359,7 +359,7 @@ bdnz 00b blr -_GLOBAL(ide_insw) +/* _GLOBAL(ide_insw) now in drivers/ide/ide-iops.c */ _GLOBAL(_insw_ns) cmpwi 0,r5,0 mtctr r5 @@ -371,7 +371,7 @@ bdnz 00b blr -_GLOBAL(ide_outsw) +/* _GLOBAL(ide_outsw) now in drivers/ide/ide-iops.c */ _GLOBAL(_outsw_ns) cmpwi 0,r5,0 mtctr r5 @@ -742,7 +742,7 @@ .llong .sys32_getdents .llong .ppc32_select .llong .sys_flock - .llong .sys32_msync + .llong .sys_msync .llong .sys32_readv /* 145 */ .llong .sys32_writev .llong .sys32_getsid @@ -750,7 +750,7 @@ .llong .sys32_sysctl .llong .sys_mlock /* 150 */ .llong .sys_munlock - .llong .sys32_mlockall + .llong .sys_mlockall .llong .sys_munlockall .llong .sys32_sched_setparam .llong .sys32_sched_getparam /* 155 */ diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c --- a/arch/ppc64/kernel/pacaData.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/kernel/pacaData.c Fri Oct 17 14:43:50 2003 @@ -64,7 +64,7 @@ (&paca[number].exception_stack[0]) - EXC_FRAME_SIZE, \ } -struct paca_struct paca[NR_CPUS] __page_aligned = { +struct paca_struct paca[] __page_aligned = { #ifdef CONFIG_PPC_ISERIES PACAINITDATA( 0, 1, &xItLpQueue, 0, STAB0_VIRT_ADDR), #else diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c --- a/arch/ppc64/kernel/pci_dma.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/kernel/pci_dma.c Fri Oct 17 14:43:50 2003 @@ -98,7 +98,7 @@ unsigned order ); /* allocates a range of tces and sets them to the pages */ -static inline dma_addr_t get_tces( struct TceTable *, +inline dma_addr_t get_tces( struct TceTable *, unsigned order, void *page, unsigned numPages, @@ -210,7 +210,7 @@ * Build a TceTable structure. This contains a multi-level bit map which * is used to manage allocation of the tce space. */ -static struct TceTable *build_tce_table( struct TceTable * tbl ) +struct TceTable *build_tce_table( struct TceTable * tbl ) { unsigned long bits, bytes, totalBytes; unsigned long numBits[NUM_TCE_LEVELS], numBytes[NUM_TCE_LEVELS]; @@ -518,7 +518,7 @@ return retval; } -static inline dma_addr_t get_tces( struct TceTable *tbl, unsigned order, void *page, unsigned numPages, int direction ) +inline dma_addr_t get_tces( struct TceTable *tbl, unsigned order, void *page, unsigned numPages, int direction ) { long tcenum; unsigned long uaddr; @@ -581,7 +581,7 @@ } #endif -static void tce_free(struct TceTable *tbl, dma_addr_t dma_addr, +void tce_free(struct TceTable *tbl, dma_addr_t dma_addr, unsigned order, unsigned num_pages) { long tcenum, total_tces, free_tce; diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c --- a/arch/ppc64/kernel/ppc_ksyms.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/kernel/ppc_ksyms.c Fri Oct 17 14:43:50 2003 @@ -57,12 +57,6 @@ EXPORT_SYMBOL(do_signal); EXPORT_SYMBOL(sys_ioctl); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); -EXPORT_SYMBOL(disable_irq_nosync); -#ifdef CONFIG_SMP -EXPORT_SYMBOL(synchronize_irq); -#endif /* CONFIG_SMP */ EXPORT_SYMBOL(isa_io_base); EXPORT_SYMBOL(pci_io_base); @@ -227,3 +221,4 @@ #endif EXPORT_SYMBOL(tb_ticks_per_usec); +EXPORT_SYMBOL(paca); diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Fri Oct 17 14:43:50 2003 @@ -2340,32 +2340,6 @@ return sys_mkdir(pathname, (int)mode); } - -extern asmlinkage long sys_mlockall(int flags); - -/* Note: it is necessary to treat flags as an unsigned int, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage long sys32_mlockall(u32 flags) -{ - return sys_mlockall((int)flags); -} - - -extern asmlinkage long sys_msync(unsigned long start, size_t len, int flags); - -/* Note: it is necessary to treat flags as an unsigned int, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage long sys32_msync(unsigned long start, size_t len, u32 flags) -{ - return sys_msync(start, len, (int)flags); -} - extern asmlinkage long sys_nice(int increment); long sys32_nice(u32 increment) diff -Nru a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c --- a/arch/ppc64/mm/hugetlbpage.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/mm/hugetlbpage.c Fri Oct 17 14:43:50 2003 @@ -507,14 +507,21 @@ + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT)); page = find_get_page(mapping, idx); if (!page) { + /* charge the fs quota first */ + if (hugetlb_get_quota(mapping)) { + ret = -ENOMEM; + goto out; + } page = alloc_hugetlb_page(); if (!page) { + hugetlb_put_quota(mapping); ret = -ENOMEM; goto out; } ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); unlock_page(page); if (ret) { + hugetlb_put_quota(mapping); free_huge_page(page); goto out; } diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/mm/init.c Fri Oct 17 14:43:50 2003 @@ -726,3 +726,22 @@ __hash_page(ea, pte_val(pte) & (_PAGE_USER|_PAGE_RW), vsid, ptep, 0x300, local); } + +kmem_cache_t *zero_cache; + +static void zero_ctor(void *pte, kmem_cache_t *cache, unsigned long flags) +{ + memset(pte, 0, PAGE_SIZE); +} + +void pgtable_cache_init(void) +{ + zero_cache = kmem_cache_create("zero", + PAGE_SIZE, + 0, + SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN, + zero_ctor, + NULL); + if (!zero_cache) + panic("pgtable_cache_init(): could not create zero_cache!\n"); +} diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c --- a/arch/ppc64/mm/numa.c Fri Oct 17 14:43:50 2003 +++ b/arch/ppc64/mm/numa.c Fri Oct 17 14:43:50 2003 @@ -13,6 +13,7 @@ #include #include #include +#include #include #if 1 @@ -306,6 +307,7 @@ { unsigned long zones_size[MAX_NR_ZONES]; int i, nid; + struct page *node_mem_map; for (i = 1; i < MAX_NR_ZONES; i++) zones_size[i] = 0; @@ -314,16 +316,24 @@ unsigned long start_pfn; unsigned long end_pfn; - if (node_data[nid].node_spanned_pages == 0) - continue; - start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT; end_pfn = plat_node_bdata[nid].node_low_pfn; zones_size[ZONE_DMA] = end_pfn - start_pfn; dbg("free_area_init node %d %lx %lx\n", nid, zones_size[ZONE_DMA], start_pfn); - free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, - start_pfn, NULL); + + /* + * Give this empty node a dummy struct page to avoid + * us from trying to allocate a node local mem_map + * in free_area_init_node (which will fail). + */ + if (!node_data[nid].node_spanned_pages) + node_mem_map = alloc_bootmem(sizeof(struct page)); + else + node_mem_map = NULL; + + free_area_init_node(nid, NODE_DATA(nid), node_mem_map, + zones_size, start_pfn, NULL); } } diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig --- a/arch/sparc64/defconfig Fri Oct 17 14:43:50 2003 +++ b/arch/sparc64/defconfig Fri Oct 17 14:43:50 2003 @@ -570,6 +570,7 @@ CONFIG_BRIDGE_EBT_T_FILTER=m CONFIG_BRIDGE_EBT_T_NAT=m CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m CONFIG_BRIDGE_EBT_ARP=m CONFIG_BRIDGE_EBT_IP=m CONFIG_BRIDGE_EBT_LIMIT=m @@ -799,11 +800,9 @@ # CONFIG_ATM_ENI is not set # CONFIG_ATM_FIRESTREAM is not set # CONFIG_ATM_ZATM is not set -# CONFIG_ATM_NICSTAR is not set # CONFIG_ATM_IDT77252 is not set # CONFIG_ATM_AMBASSADOR is not set # CONFIG_ATM_HORIZON is not set -# CONFIG_ATM_IA is not set CONFIG_ATM_FORE200E_MAYBE=m CONFIG_ATM_FORE200E_PCA=y CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y @@ -835,7 +834,6 @@ # CONFIG_BAYCOM_SER_FDX is not set # CONFIG_BAYCOM_SER_HDX is not set # CONFIG_BAYCOM_PAR is not set -# CONFIG_BAYCOM_EPP is not set # CONFIG_YAM is not set # @@ -1037,7 +1035,6 @@ CONFIG_I2C_I810=m CONFIG_I2C_NFORCE2=m CONFIG_I2C_PHILIPSPAR=m -CONFIG_I2C_PIIX4=m CONFIG_I2C_PROSAVAGE=m CONFIG_I2C_SAVAGE4=m CONFIG_SCx200_ACB=m @@ -1148,6 +1145,7 @@ CONFIG_NFS_FS=m CONFIG_NFS_V3=y CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y CONFIG_NFSD=m CONFIG_NFSD_V3=y CONFIG_NFSD_V4=y @@ -1273,7 +1271,7 @@ # Supported Frontend Modules # CONFIG_DVB_STV0299=m -CONFIG_DVB_ALPS_BSRV2=m +CONFIG_DVB_SP887X=m CONFIG_DVB_ALPS_TDLB7=m CONFIG_DVB_ALPS_TDMB7=m CONFIG_DVB_ATMEL_AT76C651=m @@ -1282,6 +1280,7 @@ CONFIG_DVB_GRUNDIG_29504_401=m CONFIG_DVB_MT312=m CONFIG_DVB_VES1820=m +CONFIG_DVB_VES1X93=m # # Supported SAA7146 based PCI Adapters @@ -1302,6 +1301,7 @@ # CONFIG_DVB_B2C2_SKYSTAR=m CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m CONFIG_VIDEO_VIDEOBUF=m CONFIG_VIDEO_TUNER=m CONFIG_VIDEO_BUF=m diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c --- a/arch/sparc64/kernel/smp.c Fri Oct 17 14:43:50 2003 +++ b/arch/sparc64/kernel/smp.c Fri Oct 17 14:43:50 2003 @@ -720,8 +720,9 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page) { cpumask_t mask = cpu_online_map; - cpu_clear(smp_processor_id(), mask); u64 data0; + + cpu_clear(smp_processor_id(), mask); #ifdef CONFIG_DEBUG_DCFLUSH atomic_inc(&dcpage_flushes); diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c --- a/arch/sparc64/kernel/sparc64_ksyms.c Fri Oct 17 14:43:50 2003 +++ b/arch/sparc64/kernel/sparc64_ksyms.c Fri Oct 17 14:43:50 2003 @@ -68,7 +68,6 @@ extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); void _sigpause_common (unsigned int set, struct pt_regs *); extern void *__bzero(void *, size_t); -extern void *__bzero_noasi(void *, size_t); extern void *__memscan_zero(void *, size_t); extern void *__memscan_generic(void *, int, size_t); extern int __memcmp(const void *, const void *, __kernel_size_t); diff -Nru a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c --- a/arch/sparc64/kernel/unaligned.c Fri Oct 17 14:43:50 2003 +++ b/arch/sparc64/kernel/unaligned.c Fri Oct 17 14:43:50 2003 @@ -73,6 +73,14 @@ else { printk("Impossible unaligned trap. insn=%08x\n", insn); die_if_kernel("Byte sized unaligned access?!?!", current_thread_info()->kregs); + + /* GCC should never warn that control reaches the end + * of this function without returning a value because + * die_if_kernel() is marked with attribute 'noreturn'. + * Alas, some versions do... + */ + + return 0; } } diff -Nru a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c --- a/arch/sparc64/solaris/misc.c Fri Oct 17 14:43:51 2003 +++ b/arch/sparc64/solaris/misc.c Fri Oct 17 14:43:51 2003 @@ -402,7 +402,7 @@ Solaris setpgrp and setsid? */ ret = sys_setpgid(0, 0); if (ret) return ret; - current->signal->tty = NULL; + current->tty = NULL; return process_group(current); } case 2: /* getsid */ diff -Nru a/arch/x86_64/kernel/acpi/boot.c b/arch/x86_64/kernel/acpi/boot.c --- a/arch/x86_64/kernel/acpi/boot.c Fri Oct 17 14:43:50 2003 +++ b/arch/x86_64/kernel/acpi/boot.c Fri Oct 17 14:43:50 2003 @@ -46,10 +46,8 @@ #include #include -extern int acpi_disabled; int acpi_lapic = 0; int acpi_ioapic = 0; -extern int disable_apic; #define PREFIX "ACPI: " @@ -316,7 +314,7 @@ { int result = 0; - if (acpi_disabled) + if (acpi_disabled && !acpi_ht) return 1; /* @@ -339,9 +337,10 @@ return result; } - extern int disable_apic; - if (disable_apic) + if (disable_apic) { + printk(KERN_INFO PREFIX "Skipping MADT probe because local APIC is disabled\n"); return 0; + } #ifdef CONFIG_X86_LOCAL_APIC @@ -423,7 +422,7 @@ /* * if "noapic" boot option, don't look for IO-APICs */ - if (disable_apic) { + if (skip_ioapic_setup) { printk(KERN_INFO PREFIX "Skipping IOAPIC probe " "due to 'noapic' option.\n"); return 1; diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c --- a/arch/x86_64/kernel/apic.c Fri Oct 17 14:43:50 2003 +++ b/arch/x86_64/kernel/apic.c Fri Oct 17 14:43:50 2003 @@ -1023,8 +1023,11 @@ return 0; } +/* dummy parsing: see setup.c */ + __setup("disableapic", setup_disableapic); __setup("nolapic", setup_nolapic); /* same as disableapic, for compatibility */ + __setup("noapictimer", setup_noapictimer); /* no "lapic" flag - we only use the lapic when the BIOS tells us so. */ diff -Nru a/arch/x86_64/kernel/cpufreq/Makefile b/arch/x86_64/kernel/cpufreq/Makefile --- a/arch/x86_64/kernel/cpufreq/Makefile Fri Oct 17 14:43:50 2003 +++ b/arch/x86_64/kernel/cpufreq/Makefile Fri Oct 17 14:43:50 2003 @@ -4,9 +4,4 @@ obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o -$(obj)/powernow-k8.c: $(obj)/powernow-k8.h - @ln -sf ../../../i386/kernel/cpu/cpufreq/powernow-k8.c $(obj)/powernow-k8.c -$(obj)/powernow-k8.h: - @ln -sf ../../../i386/kernel/cpu/cpufreq/powernow-k8.h $(obj)/powernow-k8.h - -clean-files += powernow-k8.c powernow-k8.h +powernow-k8-objs := ../../../i386/kernel/cpu/cpufreq/powernow-k8.o diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c --- a/arch/x86_64/kernel/io_apic.c Fri Oct 17 14:43:50 2003 +++ b/arch/x86_64/kernel/io_apic.c Fri Oct 17 14:43:50 2003 @@ -176,14 +176,79 @@ int pirq_entries [MAX_PIRQS]; int pirqs_enabled; int skip_ioapic_setup; +int ioapic_force; -static int __init ioapic_setup(char *str) +/* dummy parsing: see setup.c */ + +static int __init disable_ioapic_setup(char *str) { skip_ioapic_setup = 1; return 1; } -__setup("noapic", ioapic_setup); +static int __init enable_ioapic_setup(char *str) +{ + ioapic_force = 1; + skip_ioapic_setup = 0; + return 1; +} + +__setup("noapic", disable_ioapic_setup); +__setup("apic", enable_ioapic_setup); + +#ifndef CONFIG_SMP +#include +#include +#include + +/* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC + off. Check for an Nvidia or VIA PCI bridge and turn it off. + Use pci direct infrastructure because this runs before the PCI subsystem. + + Can be overwritten with "apic" */ +void __init check_ioapic(void) +{ + int num,slot,func; + if (ioapic_force) + return; + + /* Poor man's PCI discovery */ + for (num = 0; num < 32; num++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { + u32 class; + u32 vendor; + class = read_pci_config(num,slot,func, + PCI_CLASS_REVISION); + if (class == 0xffffffff) + break; + + if ((class >> 16) != PCI_CLASS_BRIDGE_PCI) + continue; + + vendor = read_pci_config(num, slot, func, + PCI_VENDOR_ID); + vendor &= 0xffff; + switch (vendor) { + case PCI_VENDOR_ID_NVIDIA: + case PCI_VENDOR_ID_VIA: + printk(KERN_INFO + "PCI bridge %02x:%02x from %x found. Setting \"noapic\". Overwrite with \"apic\"\n", + num,slot,vendor); + skip_ioapic_setup = 1; + return; + } + + /* No multi-function device? */ + u8 type = read_pci_config_byte(num,slot,func, + PCI_HEADER_TYPE); + if (!(type & 0x80)) + break; + } + } + } +} +#endif static int __init ioapic_pirq_setup(char *str) { diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c --- a/arch/x86_64/kernel/setup.c Fri Oct 17 14:43:50 2003 +++ b/arch/x86_64/kernel/setup.c Fri Oct 17 14:43:50 2003 @@ -65,6 +65,7 @@ EXPORT_SYMBOL_GPL(mmu_cr4_features); int acpi_disabled = 0; +int acpi_ht = 0; /* For PCI or other memory-mapped resources */ unsigned long pci_mem_start = 0x10000000; @@ -204,9 +205,24 @@ acpi_disabled = 0; } - if (!memcmp(from, "disableapic", 11)) + /* acpi=ht just means: do ACPI MADT parsing + at bootup, but don't enable the full ACPI interpreter */ + if (!memcmp(from, "acpi=ht", 7)) { + acpi_ht = 1; + } + + if (!memcmp(from, "nolapic", 7) || + !memcmp(from, "disableapic", 11)) disable_apic = 1; + if (!memcmp(from, "noapic", 6)) + skip_ioapic_setup = 1; + + if (!memcmp(from, "apic", 6)) { + skip_ioapic_setup = 0; + ioapic_force = 1; + } + if (!memcmp(from, "mem=", 4)) parse_memopt(from+4, &from); @@ -417,6 +433,13 @@ #endif paging_init(); + +#ifndef CONFIG_SMP + /* Temporary hack: disable the IO-APIC for UP Nvidia and + This is until we sort out the ACPI problems. */ + if (!acpi_disabled) + check_ioapic(); +#endif #ifdef CONFIG_ACPI_BOOT /* * Initialize the ACPI boot-time table parser (gets the RSDP and SDT). diff -Nru a/arch/x86_64/mm/Makefile b/arch/x86_64/mm/Makefile --- a/arch/x86_64/mm/Makefile Fri Oct 17 14:43:50 2003 +++ b/arch/x86_64/mm/Makefile Fri Oct 17 14:43:50 2003 @@ -7,7 +7,4 @@ obj-$(CONFIG_DISCONTIGMEM) += numa.o obj-$(CONFIG_K8_NUMA) += k8topology.o -$(obj)/hugetlbpage.c: - @ln -sf ../../i386/mm/hugetlbpage.c $(obj)/hugetlbpage.c - -clean-files += hugetlbpage.c +hugetlbpage-y = ../../i386/mm/hugetlbpage.o diff -Nru a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c --- a/drivers/acpi/asus_acpi.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/asus_acpi.c Fri Oct 17 14:43:50 2003 @@ -33,7 +33,6 @@ */ #include - #include #include #include diff -Nru a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c --- a/drivers/acpi/executer/exconfig.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/executer/exconfig.c Fri Oct 17 14:43:50 2003 @@ -92,6 +92,9 @@ /* Install the new table into the local data structures */ + ACPI_MEMSET (&table_info, 0, sizeof (struct acpi_table_desc)); + + table_info.type = 5; table_info.pointer = table; table_info.length = (acpi_size) table->length; table_info.allocation = ACPI_MEM_ALLOCATED; @@ -178,7 +181,7 @@ return_ACPI_STATUS (status); } - /* Not found, return an Integer=0 and AE_OK */ + /* Table not found, return an Integer=0 and AE_OK */ ddb_handle = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); if (!ddb_handle) { @@ -248,9 +251,11 @@ walk_state); if (ACPI_FAILURE (status)) { (void) acpi_ex_unload_table (ddb_handle); + return_ACPI_STATUS (status); } } + *return_desc = ddb_handle; return_ACPI_STATUS (status); } @@ -417,7 +422,7 @@ acpi_ex_unload_table ( union acpi_operand_object *ddb_handle) { - acpi_status status = AE_NOT_IMPLEMENTED; + acpi_status status = AE_OK; union acpi_operand_object *table_desc = ddb_handle; struct acpi_table_desc *table_info; diff -Nru a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c --- a/drivers/acpi/executer/exfield.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/executer/exfield.c Fri Oct 17 14:43:50 2003 @@ -160,10 +160,10 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Obj=%p Type=%X Buf=%p Len=%X\n", + "field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %X\n", obj_desc, ACPI_GET_OBJECT_TYPE (obj_desc), buffer, (u32) length)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "field_write: bit_len=%X bit_off=%X byte_off=%X\n", + "field_read [FROM]: bit_len %X, bit_off %X, byte_off %X\n", obj_desc->common_field.bit_length, obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); @@ -335,10 +335,13 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Obj=%p Type=%X Buf=%p Len=%X\n", - obj_desc, ACPI_GET_OBJECT_TYPE (obj_desc), buffer, length)); + "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %X\n", + source_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (source_desc)), + ACPI_GET_OBJECT_TYPE (source_desc), buffer, length)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "field_read: bit_len=%X bit_off=%X byte_off=%X\n", + "field_write [TO]: Obj %p (%s:%X), bit_len %X, bit_off %X, byte_off %X\n", + obj_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (obj_desc)), + ACPI_GET_OBJECT_TYPE (obj_desc), obj_desc->common_field.bit_length, obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); diff -Nru a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c --- a/drivers/acpi/executer/exfldio.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/executer/exfldio.c Fri Oct 17 14:43:50 2003 @@ -64,7 +64,8 @@ * RETURN: Status * * DESCRIPTION: Common processing for acpi_ex_extract_from_field and - * acpi_ex_insert_into_field. Initialize the + * acpi_ex_insert_into_field. Initialize the Region if necessary and + * validate the request. * ******************************************************************************/ @@ -96,7 +97,7 @@ * If the Region Address and Length have not been previously evaluated, * evaluate them now and save the results. */ - if (!(rgn_desc->region.flags & AOPOBJ_DATA_VALID)) { + if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_region_arguments (rgn_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -109,6 +110,18 @@ return_ACPI_STATUS (AE_OK); } +#ifdef ACPI_UNDER_DEVELOPMENT + /* + * If the Field access is any_acc, we can now compute the optimal + * access (because we know know the length of the parent region) + */ + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } +#endif + /* * Validate the request. The entire request from the byte offset for a * length of one field datum (access width) must fit within the region. @@ -242,7 +255,7 @@ } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD, - " Region[%s-%X] Access %X Base:Off %X:%X at %8.8X%8.8X\n", + " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n", acpi_ut_get_region_name (rgn_desc->region.space_id), rgn_desc->region.space_id, obj_desc->common_field.access_byte_width, @@ -365,10 +378,10 @@ /* * The four types of fields are: * - * buffer_fields - Read/write from/to a Buffer - * region_fields - Read/write from/to a Operation Region. - * bank_fields - Write to a Bank Register, then read/write from/to an op_region - * index_fields - Write to an Index Register, then read/write from/to a Data Register + * buffer_field - Read/write from/to a Buffer + * region_field - Read/write from/to a Operation Region. + * bank_field - Write to a Bank Register, then read/write from/to an op_region + * index_field - Write to an Index Register, then read/write from/to a Data Register */ switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { case ACPI_TYPE_BUFFER_FIELD: @@ -458,24 +471,34 @@ /* Write the index value to the index_register (itself a region_field) */ + field_datum_byte_offset += obj_desc->index_field.value; + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Write to Index Register: Value %8.8X\n", + field_datum_byte_offset)); + status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj, - &obj_desc->index_field.value, - sizeof (obj_desc->index_field.value)); + &field_datum_byte_offset, + sizeof (field_datum_byte_offset)); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "I/O to Data Register: value_ptr %p\n", + value)); + if (read_write == ACPI_READ) { /* Read the datum from the data_register */ status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj, - value, obj_desc->common_field.access_byte_width); + value, sizeof (acpi_integer)); } else { - /* Write the datum to the Data register */ + /* Write the datum to the data_register */ status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj, - value, obj_desc->common_field.access_byte_width); + value, sizeof (acpi_integer)); } break; @@ -490,12 +513,14 @@ if (ACPI_SUCCESS (status)) { if (read_write == ACPI_READ) { - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read=%8.8X%8.8X\n", - ACPI_HIDWORD (*value), ACPI_LODWORD (*value))); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n", + ACPI_HIDWORD (*value), ACPI_LODWORD (*value), + obj_desc->common_field.access_byte_width)); } else { - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written=%8.8X%8.8X\n", - ACPI_HIDWORD (*value), ACPI_LODWORD (*value))); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n", + ACPI_HIDWORD (*value), ACPI_LODWORD (*value), + obj_desc->common_field.access_byte_width)); } } @@ -554,6 +579,10 @@ */ status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, ¤t_value, ACPI_READ); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + merged_value |= (current_value & ~mask); } break; @@ -573,6 +602,7 @@ break; default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "write_with_update_rule: Unknown update_rule setting: %X\n", (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK))); @@ -580,18 +610,19 @@ } } - /* Write the merged value */ - - status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, - &merged_value, ACPI_WRITE); - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Mask %8.8X%8.8X datum_offset %X Value %8.8X%8.8X, merged_value %8.8X%8.8X\n", + "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n", ACPI_HIDWORD (mask), ACPI_LODWORD (mask), field_datum_byte_offset, + obj_desc->common_field.access_byte_width, ACPI_HIDWORD (field_value), ACPI_LODWORD (field_value), ACPI_HIDWORD (merged_value),ACPI_LODWORD (merged_value))); + /* Write the merged value */ + + status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, + &merged_value, ACPI_WRITE); + return_ACPI_STATUS (status); } @@ -625,7 +656,7 @@ u32 index; - ACPI_FUNCTION_ENTRY (); + ACPI_FUNCTION_TRACE_U32 ("ex_get_buffer_datum", byte_granularity); /* Get proper index into buffer (handles big/little endian) */ @@ -659,6 +690,8 @@ /* Should not get here */ break; } + + return_VOID; } @@ -690,7 +723,8 @@ { u32 index; - ACPI_FUNCTION_ENTRY (); + + ACPI_FUNCTION_TRACE_U32 ("ex_set_buffer_datum", byte_granularity); /* Get proper index into buffer (handles big/little endian) */ @@ -724,6 +758,8 @@ /* Should not get here */ break; } + + return_VOID; } @@ -777,7 +813,7 @@ obj_desc->common_field.access_byte_width); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "byte_len=%X, datum_len=%X, byte_gran=%X\n", + "byte_len %X, datum_len %X, byte_gran %X\n", byte_field_length, datum_count,obj_desc->common_field.access_byte_width)); /* @@ -942,20 +978,27 @@ * larger than the field, this typically happens when an integer is * written to a field that is actually smaller than an integer. */ - byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length); + byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES ( + obj_desc->common_field.bit_length); if (buffer_length < byte_field_length) { - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Buffer length %X too small for field %X\n", + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Buffer length %X too small for field %X\n", buffer_length, byte_field_length)); return_ACPI_STATUS (AE_BUFFER_OVERFLOW); } + byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES ( + obj_desc->common_field.start_field_bit_offset + + obj_desc->common_field.bit_length); + /* Convert byte count to datum count, round up if necessary */ - datum_count = ACPI_ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width); + datum_count = ACPI_ROUND_UP_TO (byte_field_length, + obj_desc->common_field.access_byte_width); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "byte_len=%X, datum_len=%X, byte_gran=%X\n", + "Bytes %X, Datums %X, byte_gran %X\n", byte_field_length, datum_count, obj_desc->common_field.access_byte_width)); /* @@ -1006,6 +1049,10 @@ return_ACPI_STATUS (status); } + /* We just wrote the first datum */ + + datum_offset++; + /* If the entire field fits within one datum, we are done. */ if ((datum_count == 1) && @@ -1025,7 +1072,6 @@ * applied in Part3 below. */ while (datum_offset < datum_count) { - datum_offset++; field_datum_byte_offset += obj_desc->common_field.access_byte_width; /* @@ -1057,33 +1103,34 @@ * a datum boundary. Update Rule must be applied to the bits outside * the field. */ - if (datum_offset == datum_count) { + datum_offset++; + if ((datum_offset == datum_count) && + (obj_desc->common_field.end_field_valid_bits)) { /* * If there are dangling non-aligned bits, perform one more merged write * Else - field is aligned at the end, no need for any more writes */ - if (obj_desc->common_field.end_field_valid_bits) { - /* - * Part3: - * This is the last datum and the field does not end on a datum boundary. - * Build the partial datum and write with the update rule. - * - * Mask off the unused bits above (after) the end-of-field - */ - mask = ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits); - merged_datum &= mask; - /* Write the last datum with the update rule */ + /* + * Part3: + * This is the last datum and the field does not end on a datum boundary. + * Build the partial datum and write with the update rule. + * + * Mask off the unused bits above (after) the end-of-field + */ + mask = ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits); + merged_datum &= mask; + + /* Write the last datum with the update rule */ - status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, - field_datum_byte_offset); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, + field_datum_byte_offset); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } } else { - /* Normal case -- write the completed datum */ + /* Normal (aligned) case -- write the completed datum */ status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, &merged_datum, ACPI_WRITE); diff -Nru a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c --- a/drivers/acpi/executer/exoparg1.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/executer/exoparg1.c Fri Oct 17 14:43:50 2003 @@ -524,7 +524,7 @@ acpi_integer value; - ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); /* Examine the AML opcode */ diff -Nru a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c --- a/drivers/acpi/executer/exprep.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/executer/exprep.c Fri Oct 17 14:43:50 2003 @@ -53,6 +53,133 @@ ACPI_MODULE_NAME ("exprep") +#ifdef ACPI_UNDER_DEVELOPMENT +/******************************************************************************* + * + * FUNCTION: acpi_ex_generate_access + * + * PARAMETERS: field_bit_offset - Start of field within parent region/buffer + * field_bit_length - Length of field in bits + * region_length - Length of parent in bytes + * + * RETURN: Field granularity (8, 16, 32 or 64) and + * byte_alignment (1, 2, 3, or 4) + * + * DESCRIPTION: Generate an optimal access width for fields defined with the + * any_acc keyword. + * + * NOTE: Need to have the region_length in order to check for boundary + * conditions (end-of-region). However, the region_length is a deferred + * operation. Therefore, to complete this implementation, the generation + * of this access width must be deferred until the region length has + * been evaluated. + * + ******************************************************************************/ + +static u32 +acpi_ex_generate_access ( + u32 field_bit_offset, + u32 field_bit_length, + u32 region_length) +{ + u32 field_byte_length; + u32 field_byte_offset; + u32 field_byte_end_offset; + u32 access_byte_width; + u32 field_start_offset; + u32 field_end_offset; + u32 minimum_access_width = 0xFFFFFFFF; + u32 minimum_accesses = 0xFFFFFFFF; + u32 accesses; + + + ACPI_FUNCTION_TRACE ("ex_generate_access"); + + + /* Round Field start offset and length to "minimal" byte boundaries */ + + field_byte_offset = ACPI_DIV_8 (ACPI_ROUND_DOWN (field_bit_offset, 8)); + field_byte_end_offset = ACPI_DIV_8 (ACPI_ROUND_UP (field_bit_length + field_bit_offset, 8)); + field_byte_length = field_byte_end_offset - field_byte_offset; + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Bit length %d, Bit offset %d\n", + field_bit_length, field_bit_offset)); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Byte Length %d, Byte Offset %d, End Offset %d\n", + field_byte_length, field_byte_offset, field_byte_end_offset)); + + /* + * Iterative search for the maximum access width that is both aligned + * and does not go beyond the end of the region + * + * Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes) + */ + for (access_byte_width = 1; access_byte_width <= 8; access_byte_width <<= 1) { + /* + * 1) Round end offset up to next access boundary and make sure that this + * does not go beyond the end of the parent region. + * 2) When the Access width is greater than the field_byte_length, we are done. + * (This does not optimize for the perfectly aligned case yet). + */ + if (ACPI_ROUND_UP (field_byte_end_offset, access_byte_width) <= region_length) { + field_start_offset = ACPI_ROUND_DOWN (field_byte_offset, access_byte_width) / + access_byte_width; + field_end_offset = ACPI_ROUND_UP ((field_byte_length + field_byte_offset), + access_byte_width) / access_byte_width; + accesses = field_end_offset - field_start_offset; + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "access_width %d end is within region\n", access_byte_width)); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Field Start %d, Field End %d -- requires %d accesses\n", + field_start_offset, field_end_offset, accesses)); + + /* Single access is optimal */ + + if (accesses <= 1) { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Entire field can be accessed with one operation of size %d\n", + access_byte_width)); + return_VALUE (access_byte_width); + } + + /* + * Fits in the region, but requires more than one read/write. + * try the next wider access on next iteration + */ + if (accesses < minimum_accesses) { + minimum_accesses = accesses; + minimum_access_width = access_byte_width; + } + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "access_width %d end is NOT within region\n", access_byte_width)); + if (access_byte_width == 1) { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Field goes beyond end-of-region!\n")); + return_VALUE (0); /* Field does not fit in the region at all */ + } + + /* This width goes beyond the end-of-region, back off to previous access */ + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Backing off to previous optimal access width of %d\n", + minimum_access_width)); + return_VALUE (minimum_access_width); + } + } + + /* Could not read/write field with one operation, just use max access width */ + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Cannot access field in one operation, using width 8\n")); + return_VALUE (8); +} +#endif /* ACPI_UNDER_DEVELOPMENT */ + + /******************************************************************************* * * FUNCTION: acpi_ex_decode_field_access @@ -74,12 +201,11 @@ u32 *return_byte_alignment) { u32 access; - u8 byte_alignment; - u8 bit_length; -/* u32 Length; */ + u32 byte_alignment; + u32 bit_length; - ACPI_FUNCTION_NAME ("ex_decode_field_access"); + ACPI_FUNCTION_TRACE ("ex_decode_field_access"); access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK); @@ -87,41 +213,15 @@ switch (access) { case AML_FIELD_ACCESS_ANY: +#ifdef ACPI_UNDER_DEVELOPMENT + byte_alignment = acpi_ex_generate_access (obj_desc->common_field.start_field_bit_offset, + obj_desc->common_field.bit_length, + 0xFFFFFFFF /* Temp until we pass region_length as param */); + bit_length = byte_alignment * 8; +#endif + byte_alignment = 1; bit_length = 8; - -#if 0 - /* - * TBD: optimize - * - * Any attempt to optimize the access size to the size of the field - * must take into consideration the length of the region and take - * care that an access to the field will not attempt to access - * beyond the end of the region. - */ - - /* Use the length to set the access type */ - - length = obj_desc->common_field.bit_length; - - if (length <= 8) { - bit_length = 8; - } - else if (length <= 16) { - bit_length = 16; - } - else if (length <= 32) { - bit_length = 32; - } - else if (length <= 64) { - bit_length = 64; - } - else { - /* Larger than Qword - just use byte-size chunks */ - - bit_length = 8; - } -#endif break; case AML_FIELD_ACCESS_BYTE: @@ -151,7 +251,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown field access type %X\n", access)); - return (0); + return_VALUE (0); } if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) { @@ -164,7 +264,7 @@ } *return_byte_alignment = byte_alignment; - return (bit_length); + return_VALUE (bit_length); } @@ -336,7 +436,7 @@ type = acpi_ns_get_type (info->region_node); if (type != ACPI_TYPE_REGION) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Needed Region, found type %X %s\n", + "Needed Region, found type %X (%s)\n", type, acpi_ut_get_type_name (type))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); @@ -372,7 +472,7 @@ acpi_ut_add_reference (obj_desc->field.region_obj); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "region_field: Bitoff=%X Off=%X Gran=%X Region %p\n", + "region_field: bit_off %X, Off %X, Gran %X, Region %p\n", obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset, obj_desc->field.access_byte_width, obj_desc->field.region_obj)); break; @@ -390,7 +490,7 @@ acpi_ut_add_reference (obj_desc->bank_field.bank_obj); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Bank Field: bit_off=%X Off=%X Gran=%X Region %p bank_reg %p\n", + "Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n", obj_desc->bank_field.start_field_bit_offset, obj_desc->bank_field.base_byte_offset, obj_desc->field.access_byte_width, @@ -417,9 +517,10 @@ acpi_ut_add_reference (obj_desc->index_field.index_obj); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "index_field: bitoff=%X off=%X gran=%X Index %p Data %p\n", + "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", obj_desc->index_field.start_field_bit_offset, obj_desc->index_field.base_byte_offset, + obj_desc->index_field.value, obj_desc->field.access_byte_width, obj_desc->index_field.index_obj, obj_desc->index_field.data_obj)); @@ -437,7 +538,7 @@ status = acpi_ns_attach_object (info->field_node, obj_desc, acpi_ns_get_type (info->field_node)); - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "set named_obj %p (%4.4s) val = %p\n", + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set named_obj %p [%4.4s], obj_desc %p\n", info->field_node, info->field_node->name.ascii, obj_desc)); /* Remove local reference to the object */ diff -Nru a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c --- a/drivers/acpi/executer/exresnte.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/executer/exresnte.c Fri Oct 17 14:43:50 2003 @@ -47,6 +47,8 @@ #include #include #include +#include +#include #define _COMPONENT ACPI_EXECUTER @@ -243,12 +245,26 @@ case ACPI_TYPE_LOCAL_REFERENCE: - /* No named references are allowed here */ + switch (source_desc->reference.opcode) { + case AML_LOAD_OP: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported Reference opcode %X\n", - source_desc->reference.opcode)); + /* This is a ddb_handle */ + /* Return an additional reference to the object */ + + obj_desc = source_desc; + acpi_ut_add_reference (obj_desc); + break; + + default: + /* No named references are allowed here */ - return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported Reference opcode %X (%s)\n", + source_desc->reference.opcode, + acpi_ps_get_opcode_name (source_desc->reference.opcode))); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + break; /* Default case is for unknown types */ diff -Nru a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c --- a/drivers/acpi/executer/exresolv.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/executer/exresolv.c Fri Oct 17 14:43:50 2003 @@ -48,6 +48,7 @@ #include #include #include +#include #define _COMPONENT ACPI_EXECUTER @@ -248,6 +249,7 @@ case AML_REF_OF_OP: case AML_DEBUG_OP: + case AML_LOAD_OP: /* Just leave the object as-is */ @@ -256,8 +258,8 @@ default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference opcode %X in %p\n", - opcode, stack_desc)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference opcode %X (%s) in %p\n", + opcode, acpi_ps_get_opcode_name (opcode), stack_desc)); status = AE_AML_INTERNAL; break; } diff -Nru a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c --- a/drivers/acpi/executer/exresop.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/executer/exresop.c Fri Oct 17 14:43:50 2003 @@ -224,6 +224,7 @@ case AML_REF_OF_OP: case AML_ARG_OP: case AML_LOCAL_OP: + case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */ ACPI_DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Reference Opcode: %s\n", op_info->name))); @@ -231,8 +232,9 @@ default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unknown Reference Opcode %X\n", - obj_desc->reference.opcode)); + "Unknown Reference Opcode %X [%s]\n", + obj_desc->reference.opcode, + (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } @@ -376,6 +378,13 @@ /* Any operand type will do */ type_needed = ACPI_TYPE_ANY; + break; + + case ARGI_DDBHANDLE: + + /* Need an operand of type ACPI_TYPE_DDB_HANDLE */ + + type_needed = ACPI_TYPE_LOCAL_REFERENCE; break; diff -Nru a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c --- a/drivers/acpi/executer/exstoren.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/executer/exstoren.c Fri Oct 17 14:43:50 2003 @@ -46,6 +46,7 @@ #include #include +#include #define _COMPONENT ACPI_EXECUTER @@ -114,9 +115,10 @@ /* * Must have a Integer, Buffer, or String */ - if ((ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) && - (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) && - (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING)) { + if ((ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) && + (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) && + (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) && + !((ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) && (source_desc->reference.opcode == AML_LOAD_OP))) { /* * Conversion successful but still not a valid type */ diff -Nru a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c --- a/drivers/acpi/executer/exsystem.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/executer/exsystem.c Fri Oct 17 14:43:50 2003 @@ -129,18 +129,13 @@ ACPI_FUNCTION_ENTRY (); - if (how_long > 1000) /* 1 millisecond */ { - /* Since this thread will sleep, we must release the interpreter */ - - acpi_ex_exit_interpreter (); - - acpi_os_sleep (0, (how_long / 1000) + 1); - - /* And now we must get the interpreter again */ - - status = acpi_ex_enter_interpreter (); + if (how_long > 100) /* 100 microseconds */ { + /* + * Longer than 100 usec, use sleep instead + * (according to ACPI specification) + */ + status = acpi_ex_system_do_suspend ((how_long / 1000) + 1); } - else { acpi_os_stall (how_long); } diff -Nru a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c --- a/drivers/acpi/hardware/hwacpi.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/hardware/hwacpi.c Fri Oct 17 14:43:50 2003 @@ -208,6 +208,15 @@ ACPI_FUNCTION_TRACE ("hw_get_mode"); + + /* + * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, + * system does not support mode transition. + */ + if (!acpi_gbl_FADT->smi_cmd) { + return_VALUE (ACPI_SYS_MODE_ACPI); + } + status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK); if (ACPI_FAILURE (status)) { return_VALUE (ACPI_SYS_MODE_LEGACY); diff -Nru a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c --- a/drivers/acpi/resources/rsaddr.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/resources/rsaddr.c Fri Oct 17 14:43:50 2003 @@ -94,6 +94,12 @@ buffer += 1; ACPI_MOVE_16_TO_16 (&temp16, buffer); + /* Validate minimum descriptor length */ + + if (temp16 < 13) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + *bytes_consumed = temp16 + 3; output_struct->id = ACPI_RSTYPE_ADDRESS16; @@ -199,8 +205,11 @@ * pointer to where the null terminated string goes: * Each Interrupt takes 32-bits + the 5 bytes of the * stream that are default. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the length. */ - if (*bytes_consumed > 16) { + if (*bytes_consumed > (16 + 1)) { /* Dereference the Index */ temp8 = *buffer; @@ -401,7 +410,7 @@ /* * Buffer needs to be set to the length of the sting + one for the - * terminating null + * terminating null */ buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address16.resource_source.string_ptr) + 1); } @@ -470,8 +479,14 @@ */ buffer += 1; ACPI_MOVE_16_TO_16 (&temp16, buffer); - *bytes_consumed = temp16 + 3; + /* Validate minimum descriptor length */ + + if (temp16 < 23) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + + *bytes_consumed = temp16 + 3; output_struct->id = ACPI_RSTYPE_ADDRESS32; /* @@ -578,8 +593,11 @@ * This will leave us pointing to the Resource Source Index * If it is present, then save it off and calculate the * pointer to where the null terminated string goes: + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the length. */ - if (*bytes_consumed > 26) { + if (*bytes_consumed > (26 + 1)) { /* Dereference the Index */ temp8 = *buffer; @@ -616,8 +634,8 @@ /* * In order for the struct_size to fall on a 32-bit boundary, - * calculate the length of the string and expand the - * struct_size to the next 32-bit boundary. + * calculate the length of the string and expand the + * struct_size to the next 32-bit boundary. */ temp8 = (u8) (index + 1); struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); @@ -848,6 +866,12 @@ buffer += 1; ACPI_MOVE_16_TO_16 (&temp16, buffer); + /* Validate minimum descriptor length */ + + if (temp16 < 43) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + *bytes_consumed = temp16 + 3; output_struct->id = ACPI_RSTYPE_ADDRESS64; @@ -958,8 +982,11 @@ * pointer to where the null terminated string goes: * Each Interrupt takes 32-bits + the 5 bytes of the * stream that are default. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the length. */ - if (*bytes_consumed > 46) { + if (*bytes_consumed > (46 + 1)) { /* Dereference the Index */ temp8 = *buffer; @@ -992,7 +1019,6 @@ * Add the terminating null */ *temp_ptr = 0x00; - output_struct->data.address64.resource_source.string_length = index + 1; /* @@ -1064,7 +1090,6 @@ /* * Set a pointer to the Length field - to be filled in later */ - length_field = ACPI_CAST_PTR (u16, buffer); buffer += 2; @@ -1161,7 +1186,7 @@ /* * Buffer needs to be set to the length of the sting + one for the - * terminating null + * terminating null */ buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address64.resource_source.string_ptr) + 1); } diff -Nru a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c --- a/drivers/acpi/resources/rsirq.c Fri Oct 17 14:43:51 2003 +++ b/drivers/acpi/resources/rsirq.c Fri Oct 17 14:43:51 2003 @@ -319,6 +319,12 @@ buffer += 1; ACPI_MOVE_16_TO_16 (&temp16, buffer); + /* Validate minimum descriptor length */ + + if (temp16 < 6) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + *bytes_consumed = temp16 + 3; output_struct->id = ACPI_RSTYPE_EXT_IRQ; @@ -357,6 +363,12 @@ buffer += 1; temp8 = *buffer; + /* Must have at least one IRQ */ + + if (temp8 < 1) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + output_struct->data.extended_irq.number_of_interrupts = temp8; /* @@ -388,9 +400,12 @@ * pointer to where the null terminated string goes: * Each Interrupt takes 32-bits + the 5 bytes of the * stream that are default. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the length. */ if (*bytes_consumed > - ((acpi_size) output_struct->data.extended_irq.number_of_interrupts * 4) + 5) { + ((acpi_size) output_struct->data.extended_irq.number_of_interrupts * 4) + (5 + 1)) { /* Dereference the Index */ temp8 = *buffer; diff -Nru a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c --- a/drivers/acpi/sleep/main.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/sleep/main.c Fri Oct 17 14:43:50 2003 @@ -20,8 +20,8 @@ static struct pm_ops acpi_pm_ops; -extern void do_suspend_lowlevel_s4bios(int); -extern void do_suspend_lowlevel(int); +extern void do_suspend_lowlevel_s4bios(void); +extern void do_suspend_lowlevel(void); static u32 acpi_suspend_states[] = { [PM_SUSPEND_ON] = ACPI_STATE_S0, @@ -95,14 +95,14 @@ break; case PM_SUSPEND_MEM: - do_suspend_lowlevel(0); + do_suspend_lowlevel(); break; case PM_SUSPEND_DISK: if (acpi_pm_ops.pm_disk_mode == PM_DISK_PLATFORM) status = acpi_enter_sleep_state(acpi_state); else - do_suspend_lowlevel_s4bios(0); + do_suspend_lowlevel_s4bios(); break; default: return -EINVAL; diff -Nru a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c --- a/drivers/acpi/tables/tbconvrt.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/tables/tbconvrt.c Fri Oct 17 14:43:50 2003 @@ -131,7 +131,7 @@ /* Copy the header and set the length */ ACPI_MEMCPY (new_table, table_info->pointer, sizeof (struct acpi_table_header)); - new_table->header.length = (u32) table_size; + new_table->length = (u32) table_size; /* Copy the table pointers */ @@ -430,17 +430,17 @@ * FADT length and version validation. The table must be at least as * long as the version 1.0 FADT */ - if (acpi_gbl_FADT->header.length < sizeof (struct fadt_descriptor_rev1)) { - ACPI_REPORT_ERROR (("Invalid FADT table length: 0x%X\n", acpi_gbl_FADT->header.length)); + if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev1)) { + ACPI_REPORT_ERROR (("Invalid FADT table length: 0x%X\n", acpi_gbl_FADT->length)); return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); } - if (acpi_gbl_FADT->header.revision >= FADT2_REVISION_ID) { - if (acpi_gbl_FADT->header.length < sizeof (struct fadt_descriptor_rev2)) { + if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) { + if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev2)) { /* Length is too short to be a V2.0 table */ ACPI_REPORT_WARNING (("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n", - acpi_gbl_FADT->header.length, acpi_gbl_FADT->header.revision)); + acpi_gbl_FADT->length, acpi_gbl_FADT->revision)); acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT); } @@ -460,7 +460,7 @@ * Global FADT pointer will point to the new common V2.0 FADT */ acpi_gbl_FADT = local_fadt; - acpi_gbl_FADT->header.length = sizeof (FADT_DESCRIPTOR); + acpi_gbl_FADT->length = sizeof (FADT_DESCRIPTOR); /* Free the original table */ @@ -477,8 +477,8 @@ ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Hex dump of common internal FADT, size %d (%X)\n", - acpi_gbl_FADT->header.length, acpi_gbl_FADT->header.length)); - ACPI_DUMP_BUFFER ((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->header.length); + acpi_gbl_FADT->length, acpi_gbl_FADT->length)); + ACPI_DUMP_BUFFER ((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length); return_ACPI_STATUS (AE_OK); } diff -Nru a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c --- a/drivers/acpi/tables/tbinstal.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/tables/tbinstal.c Fri Oct 17 14:43:50 2003 @@ -350,7 +350,7 @@ void acpi_tb_delete_all_tables (void) { - acpi_table_type type; + acpi_table_type type; /* @@ -378,7 +378,7 @@ void acpi_tb_delete_tables_by_type ( - acpi_table_type type) + acpi_table_type type) { struct acpi_table_desc *table_desc; u32 count; @@ -425,15 +425,16 @@ break; } - /* Free the table */ - /* Get the head of the list */ - + /* + * Free the table + * 1) Get the head of the list + */ table_desc = acpi_gbl_table_lists[type].next; count = acpi_gbl_table_lists[type].count; /* - * Walk the entire list, deleting both the allocated tables - * and the table descriptors + * 2) Walk the entire list, deleting both the allocated tables + * and the table descriptors */ for (i = 0; i < count; i++) { table_desc = acpi_tb_uninstall_table (table_desc); diff -Nru a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c --- a/drivers/acpi/utilities/utalloc.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/utilities/utalloc.c Fri Oct 17 14:43:50 2003 @@ -795,7 +795,7 @@ ACPI_MEMSET (&allocation->user_space, 0xEA, allocation->size); - ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size %X\n", allocation->size)); + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n", allocation->size)); status = acpi_ut_release_mutex (ACPI_MTX_MEMORY); return_ACPI_STATUS (status); diff -Nru a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c --- a/drivers/acpi/utilities/utglobal.c Fri Oct 17 14:43:50 2003 +++ b/drivers/acpi/utilities/utglobal.c Fri Oct 17 14:43:50 2003 @@ -307,8 +307,8 @@ /*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */ /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof (RSDP_SIG)-1, ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE}, - /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void *) &acpi_gbl_DSDT, sizeof (DSDT_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE | ACPI_TABLE_EXECUTABLE}, - /* FADT 2 */ {FADT_SIG, FADT_SIG, (void *) &acpi_gbl_FADT, sizeof (FADT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE}, + /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void *) &acpi_gbl_DSDT, sizeof (DSDT_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE | ACPI_TABLE_EXECUTABLE}, + /* FADT 2 */ {FADT_SIG, FADT_SIG, (void *) &acpi_gbl_FADT, sizeof (FADT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE}, /* FACS 3 */ {FACS_SIG, FACS_SIG, (void *) &acpi_gbl_FACS, sizeof (FACS_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE}, /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, NULL, sizeof (PSDT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE}, /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, NULL, sizeof (SSDT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE}, diff -Nru a/drivers/atm/Kconfig b/drivers/atm/Kconfig --- a/drivers/atm/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/atm/Kconfig Fri Oct 17 14:43:50 2003 @@ -166,7 +166,7 @@ # fi config ATM_NICSTAR tristate "IDT 77201 (NICStAR) (ForeRunnerLE)" - depends on PCI && ATM + depends on PCI && ATM && !64BIT help The NICStAR chipset family is used in a large number of ATM NICs for 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE @@ -282,7 +282,7 @@ config ATM_IA tristate "Interphase ATM PCI x575/x525/x531" - depends on PCI && ATM + depends on PCI && ATM && !64BIT ---help--- This is a driver for the Interphase (i)ChipSAR adapter cards which include a variety of variants in term of the size of the diff -Nru a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c --- a/drivers/atm/fore200e.c Fri Oct 17 14:43:51 2003 +++ b/drivers/atm/fore200e.c Fri Oct 17 14:43:51 2003 @@ -1071,7 +1071,6 @@ struct sock *s; struct atm_vcc* vcc; struct hlist_node *node; - int i; read_lock(&vcc_sklist_lock); diff -Nru a/drivers/atm/he.c b/drivers/atm/he.c --- a/drivers/atm/he.c Fri Oct 17 14:43:50 2003 +++ b/drivers/atm/he.c Fri Oct 17 14:43:50 2003 @@ -157,7 +157,7 @@ static short nvcibits = -1; static short rx_skb_reserve = 16; static short irq_coalesce = 1; -static short sdh = 1; +static short sdh = 0; static struct atmdev_ops he_ops = { @@ -1547,11 +1547,10 @@ if (sdh) { /* this really should be in suni.c but for now... */ - int val; val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM); - val = (val & ~SUNI_TPOP_APM_S) | ( 0x2 << SUNI_TPOP_APM_S_SHIFT); + val = (val & ~SUNI_TPOP_APM_S) | (SUNI_TPOP_S_SDH << SUNI_TPOP_APM_S_SHIFT); he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM); } diff -Nru a/drivers/atm/lanai.c b/drivers/atm/lanai.c --- a/drivers/atm/lanai.c Fri Oct 17 14:43:50 2003 +++ b/drivers/atm/lanai.c Fri Oct 17 14:43:50 2003 @@ -2432,11 +2432,11 @@ return result; } +#if 0 /* ioctl operations for card */ /* NOTE: these are all DEBUGGING ONLY currently */ static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void *arg) { -#if 0 int result = 0; struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data; switch(cmd) { @@ -2514,11 +2514,10 @@ result = -ENOIOCTLCMD; } return result; +} #else /* !0 */ - (void) atmdev; (void) cmd; (void) arg; /* no compiler warnings */ - return -ENOIOCTLCMD; +#define lanai_ioctl NULL #endif /* 0 */ -} static int lanai_send(struct atm_vcc *atmvcc, struct sk_buff *skb) { diff -Nru a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c --- a/drivers/atm/nicstar.c Fri Oct 17 14:43:50 2003 +++ b/drivers/atm/nicstar.c Fri Oct 17 14:43:50 2003 @@ -1676,6 +1676,25 @@ free_scq(vc->scq, vcc); } + /* remove all references to vcc before deleting it */ + if (vcc->qos.txtp.traffic_class != ATM_NONE) + { + unsigned long flags; + scq_info *scq = card->scq0; + + ns_grab_scq_lock(card, scq, flags); + + for(i = 0; i < scq->num_entries; i++) { + if(scq->skb[i] && ATM_SKB(scq->skb[i])->vcc == vcc) { + ATM_SKB(scq->skb[i])->vcc = NULL; + atm_return(vcc, scq->skb[i]->truesize); + PRINTK("nicstar: deleted pending vcc mapping\n"); + } + } + + spin_unlock_irqrestore(&scq->lock, flags); + } + vcc->dev_data = NULL; clear_bit(ATM_VF_PARTIAL,&vcc->flags); clear_bit(ATM_VF_ADDR,&vcc->flags); @@ -2074,7 +2093,7 @@ if (skb != NULL) { vcc = ATM_SKB(skb)->vcc; - if (vcc->pop != NULL) { + if (vcc && vcc->pop != NULL) { vcc->pop(vcc, skb); } else { dev_kfree_skb_irq(skb); diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c --- a/drivers/base/bus.c Fri Oct 17 14:43:50 2003 +++ b/drivers/base/bus.c Fri Oct 17 14:43:50 2003 @@ -459,10 +459,6 @@ driver_attach(drv); up_write(&bus->subsys.rwsem); - if (error) { - kobject_unregister(&drv->kobj); - put_bus(bus); - } } return error; } diff -Nru a/drivers/base/core.c b/drivers/base/core.c --- a/drivers/base/core.c Fri Oct 17 14:43:50 2003 +++ b/drivers/base/core.c Fri Oct 17 14:43:50 2003 @@ -76,6 +76,8 @@ static void device_release(struct kobject * kobj) { struct device * dev = to_dev(kobj); + struct completion * c = dev->complete; + if (dev->release) dev->release(dev); else { @@ -84,6 +86,8 @@ dev->bus_id); WARN_ON(1); } + if (c) + complete(c); } static struct kobj_type ktype_device = { @@ -349,6 +353,26 @@ put_device(dev); } + +/** + * device_unregister_wait - Unregister device and wait for it to be freed. + * @dev: Device to unregister. + * + * For the cases where the caller needs to wait for all references to + * be dropped from the device before continuing (e.g. modules with + * statically allocated devices), this function uses a completion struct + * to wait, along with a matching complete() in device_release() above. + */ + +void device_unregister_wait(struct device * dev) +{ + struct completion c; + init_completion(&c); + dev->complete = &c; + device_unregister(dev); + wait_for_completion(&c); +} + /** * device_for_each_child - device child iterator. * @dev: parent struct device. @@ -389,6 +413,7 @@ EXPORT_SYMBOL(device_del); EXPORT_SYMBOL(device_unregister); +EXPORT_SYMBOL(device_unregister_wait); EXPORT_SYMBOL(get_device); EXPORT_SYMBOL(put_device); diff -Nru a/drivers/block/Kconfig b/drivers/block/Kconfig --- a/drivers/block/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/block/Kconfig Fri Oct 17 14:43:50 2003 @@ -6,7 +6,7 @@ config BLK_DEV_FD tristate "Normal floppy disk support" - depends on ISA || M68 || SPARC64 + depends on !X86_PC9800 && !ARCH_S390 ---help--- If you want to use the floppy disk drive(s) of your PC under Linux, say Y. Information about this driver, especially important for IBM diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile --- a/drivers/block/Makefile Fri Oct 17 14:43:50 2003 +++ b/drivers/block/Makefile Fri Oct 17 14:43:50 2003 @@ -28,7 +28,6 @@ obj-$(CONFIG_ATARI_SLM) += acsi_slm.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_BLK_DEV_RAM) += rd.o -obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_BLK_DEV_LOOP) += loop.o obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o obj-$(CONFIG_BLK_DEV_XD) += xd.o diff -Nru a/drivers/block/initrd.c b/drivers/block/initrd.c --- a/drivers/block/initrd.c Fri Oct 17 14:43:51 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,100 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include - - -unsigned long initrd_start, initrd_end; -int initrd_below_start_ok; - -static int initrd_users; -static spinlock_t initrd_users_lock = SPIN_LOCK_UNLOCKED; - -static struct gendisk *initrd_disk; - -static ssize_t initrd_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - int left = initrd_end - initrd_start - *ppos; - - if (count > left) - count = left; - if (count == 0) - return 0; - if (copy_to_user(buf, (char *)initrd_start + *ppos, count)) - return -EFAULT; - - *ppos += count; - return count; -} - -static int initrd_release(struct inode *inode,struct file *file) -{ - - blkdev_put(inode->i_bdev, BDEV_FILE); - - spin_lock(&initrd_users_lock); - if (!--initrd_users) { - spin_unlock(&initrd_users_lock); - del_gendisk(initrd_disk); - free_initrd_mem(initrd_start, initrd_end); - initrd_start = 0; - } else - spin_unlock(&initrd_users_lock); - - return 0; -} - -static struct file_operations initrd_fops = { - .read = initrd_read, - .release = initrd_release, -}; - -static int initrd_open(struct inode *inode, struct file *filp) -{ - if (!initrd_start) - return -ENODEV; - - spin_lock(&initrd_users_lock); - initrd_users++; - spin_unlock(&initrd_users_lock); - - filp->f_op = &initrd_fops; - return 0; -} - -static struct block_device_operations initrd_bdops = { - .owner = THIS_MODULE, - .open = initrd_open, -}; - -static int __init initrd_init(void) -{ - initrd_disk = alloc_disk(1); - if (!initrd_disk) - return -ENOMEM; - - initrd_disk->major = RAMDISK_MAJOR; - initrd_disk->first_minor = INITRD_MINOR; - initrd_disk->fops = &initrd_bdops; - - sprintf(initrd_disk->disk_name, "initrd"); - sprintf(initrd_disk->devfs_name, "rd/initrd"); - - set_capacity(initrd_disk, (initrd_end-initrd_start+511) >> 9); - add_disk(initrd_disk); - return 0; -} - -static void __exit initrd_exit(void) -{ - put_disk(initrd_disk); -} - -module_init(initrd_init); -module_exit(initrd_exit); diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c --- a/drivers/cdrom/sjcd.c Fri Oct 17 14:43:50 2003 +++ b/drivers/cdrom/sjcd.c Fri Oct 17 14:43:50 2003 @@ -842,8 +842,9 @@ CDROM_AUDIO_NO_STATUS; } - copy_from_user(&sjcd_msf, (void *) arg, - sizeof(sjcd_msf)); + if (copy_from_user(&sjcd_msf, (void *) arg, + sizeof(sjcd_msf))) + return (-EFAULT); sjcd_playing.start.min = bin2bcd(sjcd_msf.cdmsf_min0); @@ -893,9 +894,9 @@ sizeof(toc_entry))) == 0) { struct sjcd_hw_disk_info *tp; - copy_from_user(&toc_entry, (void *) arg, - sizeof(toc_entry)); - + if (copy_from_user(&toc_entry, (void *) arg, + sizeof(toc_entry))) + return (-EFAULT); if (toc_entry.cdte_track == CDROM_LEADOUT) tp = &sjcd_table_of_contents[0]; else if (toc_entry.cdte_track < @@ -948,8 +949,10 @@ sizeof(subchnl))) == 0) { struct sjcd_hw_qinfo q_info; - copy_from_user(&subchnl, (void *) arg, - sizeof(subchnl)); + if (copy_from_user(&subchnl, (void *) arg, + sizeof(subchnl))) + return (-EFAULT); + if (sjcd_get_q_info(&q_info) < 0) return (-EIO); @@ -1005,8 +1008,9 @@ sizeof(vol_ctrl))) == 0) { unsigned char dummy[4]; - copy_from_user(&vol_ctrl, (void *) arg, - sizeof(vol_ctrl)); + if (copy_from_user(&vol_ctrl, (void *) arg, + sizeof(vol_ctrl))) + return (-EFAULT); sjcd_send_4_cmd(SCMD_SET_VOLUME, vol_ctrl.channel0, 0xFF, vol_ctrl.channel1, 0xFF); diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig --- a/drivers/char/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/char/Kconfig Fri Oct 17 14:43:50 2003 @@ -851,7 +851,7 @@ config SONYPI tristate "Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)" - depends on EXPERIMENTAL && X86 && PCI + depends on EXPERIMENTAL && X86 && PCI && !64BIT ---help--- This driver enables access to the Sony Programmable I/O Control Device which can be found in many (all ?) Sony Vaio laptops. diff -Nru a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c --- a/drivers/char/agp/ali-agp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/agp/ali-agp.c Fri Oct 17 14:43:50 2003 @@ -231,7 +231,7 @@ }; -static struct agp_device_ids ali_agp_device_ids[] __initdata = +static struct agp_device_ids ali_agp_device_ids[] __devinitdata = { { .device_id = PCI_DEVICE_ID_AL_M1541, @@ -272,7 +272,7 @@ { }, /* dummy final entry, always present */ }; -static int __init agp_ali_probe(struct pci_dev *pdev, +static int __devinit agp_ali_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct agp_device_ids *devs = ali_agp_device_ids; diff -Nru a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c --- a/drivers/char/agp/amd-k7-agp.c Fri Oct 17 14:43:51 2003 +++ b/drivers/char/agp/amd-k7-agp.c Fri Oct 17 14:43:51 2003 @@ -365,7 +365,7 @@ .agp_destroy_page = agp_generic_destroy_page, }; -static struct agp_device_ids amd_agp_device_ids[] __initdata = +static struct agp_device_ids amd_agp_device_ids[] __devinitdata = { { .device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006, @@ -382,8 +382,8 @@ { }, /* dummy final entry, always present */ }; -static int __init agp_amdk7_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit agp_amdk7_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_device_ids *devs = amd_agp_device_ids; struct agp_bridge_data *bridge; diff -Nru a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c --- a/drivers/char/agp/amd64-agp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/agp/amd64-agp.c Fri Oct 17 14:43:50 2003 @@ -248,7 +248,7 @@ }; /* Some basic sanity checks for the aperture. */ -static int __init aperture_valid(u64 aper, u32 size) +static int __devinit aperture_valid(u64 aper, u32 size) { static int not_first_call; u32 pfn, c; @@ -297,7 +297,7 @@ * to allocate that much memory. But at least error out cleanly instead of * crashing. */ -static __init int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, +static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, u16 cap) { u32 aper_low, aper_hi; @@ -339,7 +339,7 @@ return 0; } -static __init int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) +static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) { struct pci_dev *loop_dev = NULL; int i = 0; @@ -365,8 +365,8 @@ return i == 0 ? -1 : 0; } -static int __init agp_amd64_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit agp_amd64_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 rev_id; diff -Nru a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c --- a/drivers/char/agp/ati-agp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/agp/ati-agp.c Fri Oct 17 14:43:50 2003 @@ -403,7 +403,7 @@ }; -static struct agp_device_ids ati_agp_device_ids[] __initdata = +static struct agp_device_ids ati_agp_device_ids[] __devinitdata = { { .device_id = PCI_DEVICE_ID_ATI_RS100, @@ -436,8 +436,8 @@ { }, /* dummy final entry, always present */ }; -static int __init agp_ati_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit agp_ati_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_device_ids *devs = ati_agp_device_ids; struct agp_bridge_data *bridge; diff -Nru a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c --- a/drivers/char/agp/i460-agp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/agp/i460-agp.c Fri Oct 17 14:43:50 2003 @@ -560,8 +560,8 @@ .cant_use_aperture = 1, }; -static int __init agp_intel_i460_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit agp_intel_i460_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 cap_ptr; diff -Nru a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c --- a/drivers/char/agp/intel-agp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/agp/intel-agp.c Fri Oct 17 14:43:50 2003 @@ -1232,8 +1232,8 @@ return 1; } -static int __init agp_intel_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit agp_intel_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; char *name = "(unknown)"; diff -Nru a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c --- a/drivers/char/agp/nvidia-agp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/agp/nvidia-agp.c Fri Oct 17 14:43:50 2003 @@ -250,8 +250,8 @@ .agp_destroy_page = agp_generic_destroy_page, }; -static int __init agp_nvidia_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit agp_nvidia_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 cap_ptr; diff -Nru a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c --- a/drivers/char/agp/sis-agp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/agp/sis-agp.c Fri Oct 17 14:43:50 2003 @@ -95,7 +95,7 @@ .agp_destroy_page = agp_generic_destroy_page, }; -static struct agp_device_ids sis_agp_device_ids[] __initdata = +static struct agp_device_ids sis_agp_device_ids[] __devinitdata = { { .device_id = PCI_DEVICE_ID_SI_530, @@ -164,8 +164,8 @@ { }, /* dummy final entry, always present */ }; -static int __init agp_sis_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit agp_sis_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_device_ids *devs = sis_agp_device_ids; struct agp_bridge_data *bridge; diff -Nru a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c --- a/drivers/char/agp/sworks-agp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/agp/sworks-agp.c Fri Oct 17 14:43:50 2003 @@ -437,8 +437,8 @@ .agp_destroy_page = agp_generic_destroy_page, }; -static int __init agp_serverworks_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit agp_serverworks_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; struct pci_dev *bridge_dev; diff -Nru a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c --- a/drivers/char/agp/uninorth-agp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/agp/uninorth-agp.c Fri Oct 17 14:43:50 2003 @@ -282,7 +282,7 @@ .cant_use_aperture = 1, }; -static struct agp_device_ids uninorth_agp_device_ids[] __initdata = { +static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = { { .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP, .chipset_name = "UniNorth", @@ -301,8 +301,8 @@ }, }; -static int __init agp_uninorth_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit agp_uninorth_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_device_ids *devs = uninorth_agp_device_ids; struct agp_bridge_data *bridge; diff -Nru a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c --- a/drivers/char/agp/via-agp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/agp/via-agp.c Fri Oct 17 14:43:50 2003 @@ -211,7 +211,7 @@ .agp_destroy_page = agp_generic_destroy_page, }; -static struct agp_device_ids via_agp_device_ids[] __initdata = +static struct agp_device_ids via_agp_device_ids[] __devinitdata = { { .device_id = PCI_DEVICE_ID_VIA_82C597_0, @@ -371,8 +371,8 @@ } -static int __init agp_via_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit agp_via_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_device_ids *devs = via_agp_device_ids; struct agp_bridge_data *bridge; diff -Nru a/drivers/char/applicom.c b/drivers/char/applicom.c --- a/drivers/char/applicom.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/applicom.c Fri Oct 17 14:43:50 2003 @@ -214,6 +214,7 @@ if (!RamIO) { printk(KERN_INFO "ac.o: Failed to ioremap PCI memory space at 0x%lx\n", dev->resource[0].start); + pci_disable_device(dev); return -EIO; } @@ -225,12 +226,14 @@ (unsigned long)RamIO,0))) { printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n"); iounmap(RamIO); + pci_disable_device(dev); continue; } if (request_irq(dev->irq, &ac_interrupt, SA_SHIRQ, "Applicom PCI", &dummy)) { printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq); iounmap(RamIO); + pci_disable_device(dev); apbs[boardno - 1].RamIO = 0; continue; } @@ -257,12 +260,6 @@ /* Now try the specified ISA cards */ -#warning "LEAK" - RamIO = ioremap(mem, LEN_RAM_IO * MAX_ISA_BOARD); - - if (!RamIO) - printk(KERN_INFO "ac.o: Failed to ioremap ISA memory space at 0x%lx\n", mem); - for (i = 0; i < MAX_ISA_BOARD; i++) { RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO); @@ -285,7 +282,8 @@ iounmap((void *) RamIO); apbs[boardno - 1].RamIO = 0; } - apbs[boardno - 1].irq = irq; + else + apbs[boardno - 1].irq = irq; } else apbs[boardno - 1].irq = 0; diff -Nru a/drivers/char/ftape/lowlevel/ftape-proc.c b/drivers/char/ftape/lowlevel/ftape-proc.c --- a/drivers/char/ftape/lowlevel/ftape-proc.c Fri Oct 17 14:43:51 2003 +++ b/drivers/char/ftape/lowlevel/ftape-proc.c Fri Oct 17 14:43:51 2003 @@ -207,11 +207,9 @@ ftape_read_proc, NULL) != NULL; } -#ifdef MODULE void ftape_proc_destroy(void) { remove_proc_entry("ftape", &proc_root); } -#endif #endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) */ diff -Nru a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig --- a/drivers/char/ipmi/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/char/ipmi/Kconfig Fri Oct 17 14:43:50 2003 @@ -24,6 +24,18 @@ generate an IPMI event describing the panic to each interface registered with the message handler. +config IPMI_PANIC_STRING + bool 'Generate OEM events containing the panic string' + depends on IPMI_PANIC_EVENT + help + When a panic occurs, this will cause the IPMI message handler to + generate IPMI OEM type f0 events holding the IPMB address of the + panic generator (byte 4 of the event), a sequence number for the + string (byte 5 of the event) and part of the string (the rest of the + event). Bytes 1, 2, and 3 are the normal usage for an OEM event. + You can fetch these events and use the sequence numbers to piece the + string together. + config IPMI_DEVICE_INTERFACE tristate 'Device interface for IPMI' depends on IPMI_HANDLER diff -Nru a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c --- a/drivers/char/ipmi/ipmi_msghandler.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/ipmi/ipmi_msghandler.c Fri Oct 17 14:43:50 2003 @@ -169,6 +169,19 @@ /* My LUN. This should generally stay the SMS LUN, but just in case... */ unsigned char my_lun; + + /* The event receiver for my BMC, only really used at panic + shutdown as a place to store this. */ + unsigned char event_receiver; + unsigned char event_receiver_lun; + unsigned char local_sel_device; + unsigned char local_event_generator; + + /* A cheap hack, if this is non-null and a message to an + interface comes in with a NULL user, call this routine with + it. Note that the message will still be freed by the + caller. This only works on the system interface. */ + void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg); }; int @@ -1465,6 +1478,9 @@ } if (!found) { + /* Special handling for NULL users. */ + if (!recv_msg->user && intf->null_user_handler) + intf->null_user_handler(intf, msg); /* The user for the message went away, so give up. */ ipmi_free_recv_msg(recv_msg); } else { @@ -1733,7 +1749,7 @@ /* Call every 100 ms. */ #define IPMI_TIMEOUT_TIME 100 -#define IPMI_TIMEOUT_JIFFIES (IPMI_TIMEOUT_TIME/(1000/HZ)) +#define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ)/1000) /* Request events from the queue every second. Hopefully, in the future, IPMI will add a way to know immediately if an event is @@ -1813,18 +1829,48 @@ { } -static void send_panic_events(void) +#ifdef CONFIG_IPMI_PANIC_STRING +static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) +{ + if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2)) + && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD) + && (msg->rsp[2] == IPMI_CC_NO_ERROR)) + { + /* A get event receiver command, save it. */ + intf->event_receiver = msg->rsp[3]; + intf->event_receiver_lun = msg->rsp[4] & 0x3; + } +} + +static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) +{ + if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2)) + && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD) + && (msg->rsp[2] == IPMI_CC_NO_ERROR)) + { + /* A get device id command, save if we are an event + receiver or generator. */ + intf->local_sel_device = (msg->rsp[8] >> 2) & 1; + intf->local_event_generator = (msg->rsp[8] >> 5) & 1; + } +} +#endif + +static void send_panic_events(char *str) { struct ipmi_msg msg; ipmi_smi_t intf; - unsigned char data[8]; + unsigned char data[16]; int i; - struct ipmi_system_interface_addr addr; + struct ipmi_system_interface_addr *si; + struct ipmi_addr addr; struct ipmi_smi_msg smi_msg; struct ipmi_recv_msg recv_msg; - addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; - addr.channel = IPMI_BMC_CHANNEL; + si = (struct ipmi_system_interface_addr *) &addr; + si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + si->channel = IPMI_BMC_CHANNEL; + si->lun = 0; /* Fill in an event telling that we have failed. */ msg.netfn = 0x04; /* Sensor or Event. */ @@ -1837,12 +1883,13 @@ data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */ data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */ - /* These used to have the first three bytes of the panic string, - but not only is that not terribly useful, it's not available - any more. */ - data[3] = 0; - data[6] = 0; - data[7] = 0; + /* Put a few breadcrumbs in. Hopefully later we can add more things + to make the panic events more useful. */ + if (str) { + data[3] = str[0]; + data[6] = str[1]; + data[7] = str[2]; + } smi_msg.done = dummy_smi_done_handler; recv_msg.done = dummy_recv_done_handler; @@ -1853,10 +1900,11 @@ if (intf == NULL) continue; + /* Send the event announcing the panic. */ intf->handlers->set_run_to_completion(intf->send_info, 1); i_ipmi_request(NULL, intf, - (struct ipmi_addr *) &addr, + &addr, 0, &msg, &smi_msg, @@ -1865,6 +1913,130 @@ intf->my_address, intf->my_lun); } + +#ifdef CONFIG_IPMI_PANIC_STRING + /* On every interface, dump a bunch of OEM event holding the + string. */ + if (!str) + return; + + for (i=0; ilocal_sel_device = 0; + intf->local_event_generator = 0; + intf->event_receiver = 0; + + /* Request the device info from the local MC. */ + msg.netfn = IPMI_NETFN_APP_REQUEST; + msg.cmd = IPMI_GET_DEVICE_ID_CMD; + msg.data = NULL; + msg.data_len = 0; + intf->null_user_handler = device_id_fetcher; + i_ipmi_request(NULL, + intf, + &addr, + 0, + &msg, + &smi_msg, + &recv_msg, + 0, + intf->my_address, + intf->my_lun); + + if (intf->local_event_generator) { + /* Request the event receiver from the local MC. */ + msg.netfn = IPMI_NETFN_SENSOR_EVENT_REQUEST; + msg.cmd = IPMI_GET_EVENT_RECEIVER_CMD; + msg.data = NULL; + msg.data_len = 0; + intf->null_user_handler = event_receiver_fetcher; + i_ipmi_request(NULL, + intf, + &addr, + 0, + &msg, + &smi_msg, + &recv_msg, + 0, + intf->my_address, + intf->my_lun); + } + intf->null_user_handler = NULL; + + /* Validate the event receiver. The low bit must not + be 1 (it must be a valid IPMB address), it cannot + be zero, and it must not be my address. */ + if (((intf->event_receiver & 1) == 0) + && (intf->event_receiver != 0) + && (intf->event_receiver != intf->my_address)) + { + /* The event receiver is valid, send an IPMB + message. */ + ipmb = (struct ipmi_ipmb_addr *) &addr; + ipmb->addr_type = IPMI_IPMB_ADDR_TYPE; + ipmb->channel = 0; /* FIXME - is this right? */ + ipmb->lun = intf->event_receiver_lun; + ipmb->slave_addr = intf->event_receiver; + } else if (intf->local_sel_device) { + /* The event receiver was not valid (or was + me), but I am an SEL device, just dump it + in my SEL. */ + si = (struct ipmi_system_interface_addr *) &addr; + si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + si->channel = IPMI_BMC_CHANNEL; + si->lun = 0; + } else + continue; /* No where to send the event. */ + + + msg.netfn = IPMI_NETFN_STORAGE_REQUEST; /* Storage. */ + msg.cmd = IPMI_ADD_SEL_ENTRY_CMD; + msg.data = data; + msg.data_len = 16; + + j = 0; + while (*p) { + int size = strlen(p); + + if (size > 11) + size = 11; + data[0] = 0; + data[1] = 0; + data[2] = 0xf0; /* OEM event without timestamp. */ + data[3] = intf->my_address; + data[4] = j++; /* sequence # */ + /* Always give 11 bytes, so strncpy will fill + it with zeroes for me. */ + strncpy(data+5, p, 11); + p += size; + + i_ipmi_request(NULL, + intf, + &addr, + 0, + &msg, + &smi_msg, + &recv_msg, + 0, + intf->my_address, + intf->my_lun); + } + } +#endif /* CONFIG_IPMI_PANIC_STRING */ } #endif /* CONFIG_IPMI_PANIC_EVENT */ @@ -1891,7 +2063,7 @@ } #ifdef CONFIG_IPMI_PANIC_EVENT - send_panic_events(); + send_panic_events(ptr); #endif return NOTIFY_DONE; diff -Nru a/drivers/char/ite_gpio.c b/drivers/char/ite_gpio.c --- a/drivers/char/ite_gpio.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/ite_gpio.c Fri Oct 17 14:43:50 2003 @@ -242,21 +242,12 @@ if (minor != GPIO_MINOR) return -ENODEV; -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - return 0; } static int ite_gpio_release(struct inode *inode, struct file *file) { - -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - return 0; } diff -Nru a/drivers/char/n_tty.c b/drivers/char/n_tty.c --- a/drivers/char/n_tty.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/n_tty.c Fri Oct 17 14:43:50 2003 @@ -974,8 +974,7 @@ /* NOTE: not yet done after every sleep pending a thorough check of the logic of this change. -- jlc */ /* don't stop on /dev/console */ - if (file->f_op->write != redirected_tty_write && - process_tty(current) == tty) { + if (file->f_op->write != redirected_tty_write && current->tty == tty) { if (tty->pgrp <= 0) printk("read_chan: tty->pgrp <= 0!\n"); else if (process_group(current) != tty->pgrp) { diff -Nru a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c --- a/drivers/char/pcmcia/synclink_cs.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/pcmcia/synclink_cs.c Fri Oct 17 14:43:50 2003 @@ -4232,7 +4232,7 @@ d->tx_timeout = mgslpc_sppp_tx_timeout; d->watchdog_timeo = 10*HZ; - if (register_netdev(d) == -1) { + if (register_netdev(d)) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); sppp_detach(info->netdev); return; diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c --- a/drivers/char/rocket.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/rocket.c Fri Oct 17 14:43:50 2003 @@ -953,7 +953,7 @@ /* * Info->count is now 1; so it's safe to sleep now. */ - info->session = process_session(current); + info->session = current->session; info->pgrp = process_group(current); if ((info->flags & ROCKET_INITIALIZED) == 0) { diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c --- a/drivers/char/synclink.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/synclink.c Fri Oct 17 14:43:50 2003 @@ -7847,7 +7847,7 @@ d->tx_timeout = mgsl_sppp_tx_timeout; d->watchdog_timeo = 10*HZ; - if (register_netdev(d) == -1) { + if (register_netdev(d)) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); sppp_detach(info->netdev); return; @@ -8020,8 +8020,8 @@ #endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */ -static int __init synclink_init_one (struct pci_dev *dev, - const struct pci_device_id *ent) +static int __devinit synclink_init_one (struct pci_dev *dev, + const struct pci_device_id *ent) { struct mgsl_struct *info; diff -Nru a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c --- a/drivers/char/synclinkmp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/synclinkmp.c Fri Oct 17 14:43:50 2003 @@ -1653,7 +1653,7 @@ d->tx_timeout = sppp_cb_tx_timeout; d->watchdog_timeo = 10*HZ; - if (register_netdev(d) == -1) { + if (register_netdev(d)) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); sppp_detach(info->netdev); return; @@ -5451,8 +5451,8 @@ } -static int __init synclinkmp_init_one (struct pci_dev *dev, - const struct pci_device_id *ent) +static int __devinit synclinkmp_init_one (struct pci_dev *dev, + const struct pci_device_id *ent) { if (pci_enable_device(dev)) { printk("error enabling pci device %p\n", dev); diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/tty_io.c Fri Oct 17 14:43:50 2003 @@ -316,7 +316,7 @@ */ int tty_check_change(struct tty_struct * tty) { - if (process_tty(current) != tty) + if (current->tty != tty) return 0; if (tty->pgrp <= 0) { printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n"); @@ -483,14 +483,14 @@ if (tty->session > 0) { struct list_head *l; for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) { - if (process_tty(p) == tty) - p->signal->tty = NULL; - if (!process_session_leader(p)) + if (p->tty == tty) + p->tty = NULL; + if (!p->leader) continue; send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p); send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p); if (tty->pgrp > 0) - p->signal->tty_old_pgrp = tty->pgrp; + p->tty_old_pgrp = tty->pgrp; } } read_unlock(&tasklist_lock); @@ -567,15 +567,15 @@ lock_kernel(); - tty = process_tty(current); + tty = current->tty; if (tty) { tty_pgrp = tty->pgrp; if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); } else { - if (current->signal->tty_old_pgrp) { - kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); - kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); + if (current->tty_old_pgrp) { + kill_pg(current->tty_old_pgrp, SIGHUP, on_exit); + kill_pg(current->tty_old_pgrp, SIGCONT, on_exit); } unlock_kernel(); return; @@ -586,13 +586,13 @@ kill_pg(tty_pgrp, SIGCONT, on_exit); } - current->signal->tty_old_pgrp = 0; + current->tty_old_pgrp = 0; tty->session = 0; tty->pgrp = -1; read_lock(&tasklist_lock); - for_each_task_pid(process_session(current), PIDTYPE_SID, p, l, pid) - p->signal->tty = NULL; + for_each_task_pid(current->session, PIDTYPE_SID, p, l, pid) + p->tty = NULL; read_unlock(&tasklist_lock); unlock_kernel(); } @@ -1220,10 +1220,10 @@ read_lock(&tasklist_lock); for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) - p->signal->tty = NULL; + p->tty = NULL; if (o_tty) for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid) - p->signal->tty = NULL; + p->tty = NULL; read_unlock(&tasklist_lock); } @@ -1294,10 +1294,10 @@ retry_open: noctty = filp->f_flags & O_NOCTTY; if (device == MKDEV(TTYAUX_MAJOR,0)) { - if (!process_tty(current)) + if (!current->tty) return -ENXIO; - driver = process_tty(current)->driver; - index = process_tty(current)->index; + driver = current->tty->driver; + index = current->tty->index; filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ /* noctty = 1; */ goto got_driver; @@ -1391,13 +1391,15 @@ filp->f_op = &tty_fops; goto retry_open; } - if (!noctty && process_session_leader(current) && - !process_tty(current) && tty->session == 0) { + if (!noctty && + current->leader && + !current->tty && + tty->session == 0) { task_lock(current); - current->signal->tty = tty; + current->tty = tty; task_unlock(current); - current->signal->tty_old_pgrp = 0; - tty->session = process_session(current); + current->tty_old_pgrp = 0; + tty->session = current->session; tty->pgrp = process_group(current); } return 0; @@ -1455,7 +1457,7 @@ { char ch, mbz = 0; - if ((process_tty(current) != tty) && !capable(CAP_SYS_ADMIN)) + if ((current->tty != tty) && !capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(ch, arg)) return -EFAULT; @@ -1541,14 +1543,14 @@ struct pid *pid; task_t *p; - if (process_session_leader(current) && - (process_session(current) == tty->session)) + if (current->leader && + (current->session == tty->session)) return 0; /* * The process must be a session leader and * not have a controlling tty already. */ - if (!process_session_leader(current) || process_tty(current)) + if (!current->leader || current->tty) return -EPERM; if (tty->session > 0) { /* @@ -1562,16 +1564,16 @@ read_lock(&tasklist_lock); for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) - p->signal->tty = NULL; + p->tty = NULL; read_unlock(&tasklist_lock); } else return -EPERM; } task_lock(current); - current->signal->tty = tty; + current->tty = tty; task_unlock(current); - current->signal->tty_old_pgrp = 0; - tty->session = process_session(current); + current->tty_old_pgrp = 0; + tty->session = current->session; tty->pgrp = process_group(current); return 0; } @@ -1582,13 +1584,12 @@ * (tty == real_tty) is a cheap way of * testing if the tty is NOT a master pty. */ - if (tty == real_tty && process_tty(current) != real_tty) + if (tty == real_tty && current->tty != real_tty) return -ENOTTY; return put_user(real_tty->pgrp, arg); } -static int tiocspgrp(struct tty_struct *tty, - struct tty_struct *real_tty, pid_t *arg) +static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t *arg) { pid_t pgrp; int retval = tty_check_change(real_tty); @@ -1597,14 +1598,15 @@ return -ENOTTY; if (retval) return retval; - if (!process_tty(current) || (process_tty(current) != real_tty) || - (real_tty->session != process_session(current))) + if (!current->tty || + (current->tty != real_tty) || + (real_tty->session != current->session)) return -ENOTTY; if (get_user(pgrp, (pid_t *) arg)) return -EFAULT; if (pgrp < 0) return -EINVAL; - if (session_of_pgrp(pgrp) != process_session(current)) + if (session_of_pgrp(pgrp) != current->session) return -EPERM; real_tty->pgrp = pgrp; return 0; @@ -1616,7 +1618,7 @@ * (tty == real_tty) is a cheap way of * testing if the tty is NOT a master pty. */ - if (tty == real_tty && process_tty(current) != real_tty) + if (tty == real_tty && current->tty != real_tty) return -ENOTTY; if (real_tty->session <= 0) return -ENOTTY; @@ -1774,12 +1776,12 @@ clear_bit(TTY_EXCLUSIVE, &tty->flags); return 0; case TIOCNOTTY: - if (process_tty(current) != tty) + if (current->tty != tty) return -ENOTTY; - if (process_session_leader(current)) + if (current->leader) disassociate_ctty(0); task_lock(current); - current->signal->tty = NULL; + current->tty = NULL; task_unlock(current); return 0; case TIOCSCTTY: @@ -1883,10 +1885,10 @@ tty->driver->flush_buffer(tty); read_lock(&tasklist_lock); for_each_task_pid(session, PIDTYPE_SID, p, l, pid) { - if (process_tty(p) == tty || session > 0) { + if (p->tty == tty || session > 0) { printk(KERN_NOTICE "SAK: killed process %d" - " (%s): process_session(p)==tty->session\n", - p->pid, p->comm); + " (%s): p->session==tty->session\n", + p->pid, p->comm); send_sig(SIGKILL, p, 1); continue; } diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c --- a/drivers/char/vt.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/vt.c Fri Oct 17 14:43:50 2003 @@ -2226,7 +2226,7 @@ if (tty->driver->type != TTY_DRIVER_TYPE_CONSOLE) return -EINVAL; - if (process_tty(current) != tty && !capable(CAP_SYS_ADMIN)) + if (current->tty != tty && !capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(type, (char *)arg)) return -EFAULT; diff -Nru a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c --- a/drivers/char/vt_ioctl.c Fri Oct 17 14:43:50 2003 +++ b/drivers/char/vt_ioctl.c Fri Oct 17 14:43:50 2003 @@ -380,7 +380,7 @@ * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. */ perm = 0; - if (process_tty(current) == tty || capable(CAP_SYS_TTY_CONFIG)) + if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) perm = 1; kbd = kbd_table + console; @@ -1188,3 +1188,4 @@ complete_change_console(new_console); } + diff -Nru a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c --- a/drivers/i2c/algos/i2c-algo-ite.c Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/algos/i2c-algo-ite.c Fri Oct 17 14:43:50 2003 @@ -779,10 +779,6 @@ adap->retries = 3; /* be replaced by defines */ adap->flags = 0; -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - i2c_add_adapter(adap); iic_init(iic_adap); @@ -815,9 +811,6 @@ return res; DEB2(printk("i2c-algo-ite: adapter unregistered: %s\n",adap->name)); -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif return 0; } diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig --- a/drivers/i2c/busses/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/busses/Kconfig Fri Oct 17 14:43:50 2003 @@ -157,7 +157,7 @@ config I2C_PIIX4 tristate "Intel PIIX4" - depends on I2C && PCI && EXPERIMENTAL + depends on I2C && PCI && EXPERIMENTAL && !64BIT help If you say yes to this option, support will be included for the Intel PIIX4 family of mainboard I2C interfaces. Specifically, the following @@ -248,11 +248,11 @@ will be called i2c-sis5595. config I2C_SIS630 - tristate "SiS 630" + tristate "SiS 630/730" depends on I2C && PCI && EXPERIMENTAL help If you say yes to this option, support will be included for the - SiS630 SMBus (a subset of I2C) interface. + SiS630 and SiS730 SMBus (a subset of I2C) interface. This driver can also be built as a module. If so, the module will be called i2c-sis630. diff -Nru a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c --- a/drivers/i2c/busses/i2c-sis630.c Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/busses/i2c-sis630.c Fri Oct 17 14:43:50 2003 @@ -25,10 +25,10 @@ Fixed the typo in sis630_access (Thanks to Mark M. Hoffman) Changed sis630_transaction.(Thanks to Mark M. Hoffman) 18.09.2002 - Added SIS730 as supported + Added SIS730 as supported. 21.09.2002 Added high_clock module option.If this option is set - used Host Master Clock 56KHz (default 14KHz).For now we are save old Host + used Host Master Clock 56KHz (default 14KHz).For now we save old Host Master Clock and after transaction completed restore (otherwise it's confuse BIOS and hung Machine). 24.09.2002 @@ -95,12 +95,22 @@ /* insmod parameters */ static int high_clock = 0; +static int force = 0; MODULE_PARM(high_clock, "i"); MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz)."); +MODULE_PARM(force, "i"); +MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!"); - +/* acpi base address */ static unsigned short acpi_base = 0; +/* supported chips */ +static int supported[] = { + PCI_DEVICE_ID_SI_630, + PCI_DEVICE_ID_SI_730, + 0 /* terminates the list */ +}; + static inline u8 sis630_read(u8 reg) { return inb(acpi_base + reg); @@ -277,6 +287,10 @@ if (len == 0) data->block[0] = sis630_read(SMB_COUNT); + /* just to be sure */ + if (data->block[0] > 32) + data->block[0] = 32; + dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]); for (i=0; i < 8 && len < data->block[0]; i++,len++) { @@ -372,16 +386,26 @@ I2C_FUNC_SMBUS_BLOCK_DATA; } -static int sis630_setup(struct pci_dev *dummy) +static int sis630_setup(struct pci_dev *sis630_dev) { unsigned char b; - struct pci_dev *sis630_dev = NULL; - int retval = -ENODEV; + struct pci_dev *dummy = NULL; + int retval = -ENODEV, i; - /* We need ISA bridge and not pci device passed in. */ - sis630_dev = pci_get_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, sis630_dev); - if (!sis630_dev) { - dev_err(&dummy->dev, "Error: Can't detect 85C503/5513 ISA bridge!\n"); + /* check for supported SiS devices */ + for (i=0; supported[i] > 0 ; i++) { + if ((dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy))) + break; /* found */ + } + + if (dummy) { + pci_dev_put(dummy); + } + else if (force > 0) { + dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but " + "loading because of force option enabled\n"); + } + else { return -ENODEV; } @@ -389,19 +413,19 @@ Enable ACPI first , so we can accsess reg 74-75 in acpi io space and read acpi base addr */ - if (!pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) { + if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) { dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n"); goto exit; } - /* if ACPI already enabled , do nothing */ if (!(b & 0x80) && - !pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) { + pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) { dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n"); goto exit; } + /* Determine the ACPI base address */ - if (!pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) { + if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) { dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n"); goto exit; } @@ -418,7 +442,8 @@ retval = 0; exit: - pci_dev_put(sis630_dev); + if (retval) + acpi_base = 0; return retval; } @@ -432,19 +457,18 @@ static struct i2c_adapter sis630_adapter = { .owner = THIS_MODULE, + .class = I2C_ADAP_CLASS_SMBUS, .name = "unset", .algo = &smbus_algorithm, }; static struct pci_device_id sis630_ids[] __devinitdata = { - { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630) }, - { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_730) }, + { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, { 0, } }; static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) { - if (sis630_setup(dev)) { dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n"); return -ENODEV; @@ -461,7 +485,11 @@ static void __devexit sis630_remove(struct pci_dev *dev) { - i2c_del_adapter(&sis630_adapter); + if (acpi_base) { + i2c_del_adapter(&sis630_adapter); + release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION); + acpi_base = 0; + } } @@ -481,7 +509,6 @@ static void __exit i2c_sis630_exit(void) { pci_unregister_driver(&sis630_driver); - release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION); } diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig --- a/drivers/i2c/chips/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/chips/Kconfig Fri Oct 17 14:43:50 2003 @@ -15,7 +15,7 @@ help If you say yes here you get support for Analog Devices ADM1021 and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A, - Genesys Logic GL523SM, National Semi LM84, TI THMC10, + Genesys Logic GL523SM, National Semiconductor LM84, TI THMC10, and the XEON processor built-in sensor. This driver can also be built as a module. If so, the module @@ -34,30 +34,30 @@ will be called eeprom. config SENSORS_IT87 - tristate "National Semiconductors IT87 and compatibles" + tristate "ITE IT87xx and compatibles" depends on I2C && EXPERIMENTAL select I2C_SENSOR help - If you say yes here you get support for National Semiconductor IT87 - sensor chips and clones: IT8705F, IT8712F and SiS960. + If you say yes here you get support for ITE IT87xx sensor chips + and clones: SiS960. This driver can also be built as a module. If so, the module will be called it87. config SENSORS_LM75 - tristate "National Semiconductors LM75 and compatibles" + tristate "National Semiconductor LM75 and compatibles" depends on I2C && EXPERIMENTAL select I2C_SENSOR help If you say yes here you get support for National Semiconductor LM75 sensor chips and clones: Dallas Semi DS75 and DS1775, TelCon - TCN75, and National Semi LM77. + TCN75, and National Semiconductor LM77. This driver can also be built as a module. If so, the module will be called lm75. config SENSORS_LM78 - tristate "National Semiconductors LM78 and compatibles" + tristate "National Semiconductor LM78 and compatibles" depends on I2C && EXPERIMENTAL select I2C_SENSOR help @@ -69,7 +69,7 @@ will be called lm78. config SENSORS_LM85 - tristate "National Semiconductors LM85 and compatibles" + tristate "National Semiconductor LM85 and compatibles" depends on I2C && EXPERIMENTAL select I2C_SENSOR help diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c --- a/drivers/i2c/chips/adm1021.c Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/chips/adm1021.c Fri Oct 17 14:43:50 2003 @@ -322,6 +322,10 @@ if ((err = i2c_attach_client(new_client))) goto error3; + /* Initialize the ADM1021 chip */ + adm1021_init_client(new_client); + + /* Register sysfs hooks */ device_create_file(&new_client->dev, &dev_attr_temp_max1); device_create_file(&new_client->dev, &dev_attr_temp_min1); device_create_file(&new_client->dev, &dev_attr_temp_input1); @@ -332,8 +336,6 @@ if (data->type == adm1021) device_create_file(&new_client->dev, &dev_attr_die_code); - /* Initialize the ADM1021 chip */ - adm1021_init_client(new_client); return 0; error3: diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c --- a/drivers/i2c/chips/it87.c Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/chips/it87.c Fri Oct 17 14:43:50 2003 @@ -701,7 +701,10 @@ if ((err = i2c_attach_client(new_client))) goto ERROR1; - /* register sysfs hooks */ + /* Initialize the IT87 chip */ + it87_init_client(new_client, data); + + /* Register sysfs hooks */ device_create_file(&new_client->dev, &dev_attr_in_input0); device_create_file(&new_client->dev, &dev_attr_in_input1); device_create_file(&new_client->dev, &dev_attr_in_input2); @@ -750,8 +753,6 @@ device_create_file(&new_client->dev, &dev_attr_fan_div3); device_create_file(&new_client->dev, &dev_attr_alarm); - /* Initialize the IT87 chip */ - it87_init_client(new_client, data); return 0; ERROR1: diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c --- a/drivers/i2c/chips/lm75.c Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/chips/lm75.c Fri Oct 17 14:43:50 2003 @@ -204,11 +204,14 @@ if ((err = i2c_attach_client(new_client))) goto exit_free; + /* Initialize the LM75 chip */ + lm75_init_client(new_client); + + /* Register sysfs hooks */ device_create_file(&new_client->dev, &dev_attr_temp_max); device_create_file(&new_client->dev, &dev_attr_temp_min); device_create_file(&new_client->dev, &dev_attr_temp_input); - lm75_init_client(new_client); return 0; exit_free: diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c --- a/drivers/i2c/chips/lm78.c Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/chips/lm78.c Fri Oct 17 14:43:50 2003 @@ -648,7 +648,10 @@ if ((err = i2c_attach_client(new_client))) goto ERROR2; - /* register sysfs hooks */ + /* Initialize the LM78 chip */ + lm78_init_client(new_client); + + /* Register sysfs hooks */ device_create_file(&new_client->dev, &dev_attr_in_input0); device_create_file(&new_client->dev, &dev_attr_in_min0); device_create_file(&new_client->dev, &dev_attr_in_max0); @@ -685,8 +688,6 @@ device_create_file(&new_client->dev, &dev_attr_alarms); device_create_file(&new_client->dev, &dev_attr_vid); - /* Initialize the LM78 chip */ - lm78_init_client(new_client); return 0; ERROR2: diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c --- a/drivers/i2c/chips/lm85.c Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/chips/lm85.c Fri Oct 17 14:43:50 2003 @@ -888,6 +888,10 @@ /* Set the VRM version */ data->vrm = LM85_INIT_VRM ; + /* Initialize the LM85 chip */ + lm85_init_client(new_client); + + /* Register sysfs hooks */ device_create_file(&new_client->dev, &dev_attr_fan_input1); device_create_file(&new_client->dev, &dev_attr_fan_input2); device_create_file(&new_client->dev, &dev_attr_fan_input3); @@ -930,8 +934,6 @@ device_create_file(&new_client->dev, &dev_attr_vid); device_create_file(&new_client->dev, &dev_attr_alarms); - /* Initialize the LM85 chip */ - lm85_init_client(new_client); return 0; /* Error out and cleanup code */ diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c --- a/drivers/i2c/chips/via686a.c Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/chips/via686a.c Fri Oct 17 14:43:50 2003 @@ -735,7 +735,10 @@ if ((err = i2c_attach_client(new_client))) goto ERROR3; - /* register sysfs hooks */ + /* Initialize the VIA686A chip */ + via686a_init_client(new_client); + + /* Register sysfs hooks */ device_create_file(&new_client->dev, &dev_attr_in_input0); device_create_file(&new_client->dev, &dev_attr_in_input1); device_create_file(&new_client->dev, &dev_attr_in_input2); @@ -768,8 +771,6 @@ device_create_file(&new_client->dev, &dev_attr_fan_div2); device_create_file(&new_client->dev, &dev_attr_alarm); - /* Initialize the VIA686A chip */ - via686a_init_client(new_client); return 0; ERROR3: diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c --- a/drivers/i2c/chips/w83781d.c Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/chips/w83781d.c Fri Oct 17 14:43:50 2003 @@ -422,9 +422,11 @@ sysfs_in_offsets(8); #define device_create_file_in(client, offset) \ +do { \ device_create_file(&client->dev, &dev_attr_in_input##offset); \ device_create_file(&client->dev, &dev_attr_in_min##offset); \ -device_create_file(&client->dev, &dev_attr_in_max##offset); +device_create_file(&client->dev, &dev_attr_in_max##offset); \ +} while (0) #define show_fan_reg(reg) \ static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ @@ -482,8 +484,10 @@ sysfs_fan_min_offset(3); #define device_create_file_fan(client, offset) \ +do { \ device_create_file(&client->dev, &dev_attr_fan_input##offset); \ device_create_file(&client->dev, &dev_attr_fan_min##offset); \ +} while (0) #define show_temp_reg(reg) \ static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ @@ -566,9 +570,11 @@ sysfs_temp_offsets(3); #define device_create_file_temp(client, offset) \ +do { \ device_create_file(&client->dev, &dev_attr_temp_input##offset); \ device_create_file(&client->dev, &dev_attr_temp_max##offset); \ -device_create_file(&client->dev, &dev_attr_temp_min##offset); +device_create_file(&client->dev, &dev_attr_temp_min##offset); \ +} while (0) static ssize_t show_vid_reg(struct device *dev, char *buf) @@ -691,8 +697,10 @@ sysfs_beep(MASK, mask); #define device_create_file_beep(client) \ +do { \ device_create_file(&client->dev, &dev_attr_beep_enable); \ -device_create_file(&client->dev, &dev_attr_beep_mask); +device_create_file(&client->dev, &dev_attr_beep_mask); \ +} while (0) /* w83697hf only has two fans */ static ssize_t @@ -769,7 +777,9 @@ sysfs_fan_div(3); #define device_create_file_fan_div(client, offset) \ +do { \ device_create_file(&client->dev, &dev_attr_fan_div##offset); \ +} while (0) /* w83697hf only has two fans */ static ssize_t @@ -881,10 +891,14 @@ sysfs_pwm(4); #define device_create_file_pwm(client, offset) \ +do { \ device_create_file(&client->dev, &dev_attr_pwm##offset); \ +} while (0) #define device_create_file_pwmenable(client, offset) \ +do { \ device_create_file(&client->dev, &dev_attr_pwm_enable##offset); \ +} while (0) static ssize_t show_sensor_reg(struct device *dev, char *buf, int nr) @@ -957,7 +971,9 @@ sysfs_sensor(3); #define device_create_file_sensor(client, offset) \ +do { \ device_create_file(&client->dev, &dev_attr_sensor##offset); \ +} while (0) #ifdef W83781D_RT static ssize_t @@ -1016,7 +1032,9 @@ sysfs_rt(3); #define device_create_file_rt(client, offset) \ +do { \ device_create_file(&client->dev, &dev_attr_rt##offset); \ +} while (0) #endif /* ifdef W83781D_RT */ @@ -1346,6 +1364,10 @@ data->lm75[1] = NULL; } + /* Initialize the chip */ + w83781d_init_client(new_client); + + /* Register sysfs hooks */ device_create_file_in(new_client, 0); if (kind != w83783s && kind != w83697hf) device_create_file_in(new_client, 1); @@ -1408,8 +1430,6 @@ } #endif - /* Initialize the chip */ - w83781d_init_client(new_client); return 0; ERROR3: diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c --- a/drivers/i2c/i2c-dev.c Fri Oct 17 14:43:50 2003 +++ b/drivers/i2c/i2c-dev.c Fri Oct 17 14:43:50 2003 @@ -49,6 +49,7 @@ int minor; struct i2c_adapter *adap; struct class_device class_dev; + struct completion released; /* FIXME, we need a class_device_unregister() */ }; #define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev) @@ -112,7 +113,6 @@ spin_lock(&i2c_dev_array_lock); i2c_dev_array[i2c_dev->minor] = NULL; spin_unlock(&i2c_dev_array_lock); - kfree(i2c_dev); } static ssize_t show_dev(struct class_device *class_dev, char *buf) @@ -421,8 +421,15 @@ .release = i2cdev_release, }; +static void release_i2c_dev(struct class_device *dev) +{ + struct i2c_dev *i2c_dev = to_i2c_dev(dev); + complete(&i2c_dev->released); +} + static struct class i2c_dev_class = { - .name = "i2c-dev", + .name = "i2c-dev", + .release = &release_i2c_dev, }; static int i2cdev_attach_adapter(struct i2c_adapter *adap) @@ -453,6 +460,7 @@ return 0; error: return_i2c_dev(i2c_dev); + kfree(i2c_dev); return retval; } @@ -464,9 +472,12 @@ if (!i2c_dev) return -ENODEV; - class_device_unregister(&i2c_dev->class_dev); + init_completion(&i2c_dev->released); devfs_remove("i2c/%d", i2c_dev->minor); return_i2c_dev(i2c_dev); + class_device_unregister(&i2c_dev->class_dev); + wait_for_completion(&i2c_dev->released); + kfree(i2c_dev); dev_dbg(&adap->dev, "Adapter unregistered\n"); return 0; diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c --- a/drivers/ide/ide-dma.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/ide-dma.c Fri Oct 17 14:43:50 2003 @@ -1105,18 +1105,9 @@ if (hwif->chipset != ide_trm290) { u8 dma_stat = hwif->INB(hwif->dma_status); - printk(", BIOS settings: %s:%s%s, %s:%s%s", + printk(", BIOS settings: %s:%s, %s:%s", hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio", - hwif->drives[0].autotune == IDE_TUNE_BIOS ? - " (used)" : "", - hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio", - hwif->drives[1].autotune == IDE_TUNE_BIOS ? - " (used)" : ""); - - if (hwif->drives[0].autotune == IDE_TUNE_BIOS) - hwif->drives[0].using_dma = (dma_stat & 0x20); - if (hwif->drives[1].autotune == IDE_TUNE_BIOS) - hwif->drives[1].using_dma = (dma_stat & 0x40); + hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio"); } printk("\n"); diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/ide-floppy.c Fri Oct 17 14:43:50 2003 @@ -1796,7 +1796,7 @@ * we'll leave the limitation below for the 2.2.x tree. */ - if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0) { + if (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) { set_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags); /* This value will be visible in the /proc/ide/hdx/settings */ floppy->ticks = IDEFLOPPY_TICKS_DELAY; diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/ide.c Fri Oct 17 14:43:50 2003 @@ -1846,8 +1846,6 @@ * Not fully supported by all chipset types, * and quite likely to cause trouble with * older/odd IDE drives. - * "hdx=biostimings" : driver will NOT attempt to tune interface speed - * (DMA/PIO) but always honour BIOS timings. * "hdx=slow" : insert a huge pause after each access to the data * port. Should be used only as a last resort. * @@ -1884,8 +1882,6 @@ * "idex=noautotune" : driver will NOT attempt to tune interface speed * This is the default for most chipsets, * except the cmd640. - * "idex=biostimings" : driver will NOT attempt to tune interface speed - * (DMA/PIO) but always honour BIOS timings. * "idex=serialize" : do not overlap operations on idex and ide(x^1) * "idex=four" : four drives on idex and ide(x^1) share same ports * "idex=reset" : reset interface before first use @@ -1961,8 +1957,7 @@ const char *hd_words[] = { "none", "noprobe", "nowerr", "cdrom", "serialize", "autotune", "noautotune", "slow", "swapdata", "bswap", - "flash", "remap", "remap63", "scsi", "biostimings", - NULL }; + "flash", "remap", "remap63", "scsi", NULL }; unit = s[2] - 'a'; hw = unit / MAX_DRIVES; unit = unit % MAX_DRIVES; @@ -2028,9 +2023,6 @@ case -14: /* "scsi" */ drive->scsi = 1; goto done; - case -15: /* "biostimings" */ - drive->autotune = IDE_TUNE_BIOS; - goto done; case 3: /* cyl,head,sect */ drive->media = ide_disk; drive->cyl = drive->bios_cyl = vals[0]; @@ -2065,11 +2057,11 @@ if (s[3] >= '0' && s[3] <= max_hwif) { /* * Be VERY CAREFUL changing this: note hardcoded indexes below - * -9,-10 : are reserved for future idex calls to ease the hardcoding. + * (-8, -9, -10) are reserved to ease the hardcoding. */ const char *ide_words[] = { "noprobe", "serialize", "autotune", "noautotune", - "reset", "dma", "ata66", "biostimings", "minus9", + "reset", "dma", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; hw = s[3] - '0'; @@ -2149,11 +2141,8 @@ #endif /* CONFIG_BLK_DEV_4DRIVES */ case -10: /* minus10 */ case -9: /* minus9 */ + case -8: /* minus8 */ goto bad_option; - case -8: /* "biostimings" */ - hwif->drives[0].autotune = IDE_TUNE_BIOS; - hwif->drives[1].autotune = IDE_TUNE_BIOS; - goto done; case -7: /* ata66 */ #ifdef CONFIG_BLK_DEV_IDEPCI hwif->udma_four = 1; diff -Nru a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c --- a/drivers/ide/pci/aec62xx.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/aec62xx.c Fri Oct 17 14:43:50 2003 @@ -355,13 +355,15 @@ } else { goto fast_ata_pio; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: aec62xx_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } static int aec62xx_irq_timeout (ide_drive_t *drive) diff -Nru a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c --- a/drivers/ide/pci/cmd64x.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/cmd64x.c Fri Oct 17 14:43:50 2003 @@ -484,13 +484,15 @@ } else { goto fast_ata_pio; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: config_chipset_for_pio(drive, 1); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } static int cmd64x_alt_dma_status (struct pci_dev *dev) diff -Nru a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c --- a/drivers/ide/pci/hpt34x.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/hpt34x.c Fri Oct 17 14:43:50 2003 @@ -215,17 +215,19 @@ } else { goto fast_ata_pio; } +#ifndef CONFIG_HPT34X_AUTODMA + return hwif->ide_dma_off_quietly(drive); +#else + return hwif->ide_dma_on(drive); +#endif } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: hpt34x_tune_drive(drive, 255); return hwif->ide_dma_off_quietly(drive); } - -#ifndef CONFIG_HPT34X_AUTODMA - return hwif->ide_dma_off_quietly(drive); -#endif /* CONFIG_HPT34X_AUTODMA */ - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } /* diff -Nru a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c --- a/drivers/ide/pci/hpt366.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/hpt366.c Fri Oct 17 14:43:50 2003 @@ -538,13 +538,15 @@ } else { goto fast_ata_pio; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: hpt3xx_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } /* diff -Nru a/drivers/ide/pci/it8172.c b/drivers/ide/pci/it8172.c --- a/drivers/ide/pci/it8172.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/it8172.c Fri Oct 17 14:43:50 2003 @@ -227,13 +227,15 @@ } else { goto fast_ata_pio; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: it8172_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } static unsigned int __init init_chipset_it8172 (struct pci_dev *dev, const char *name) diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c --- a/drivers/ide/pci/pdc202xx_new.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/pdc202xx_new.c Fri Oct 17 14:43:50 2003 @@ -414,13 +414,15 @@ } else { goto fast_ata_pio; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: hwif->tuneproc(drive, 5); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } static int pdcnew_quirkproc (ide_drive_t *drive) diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c --- a/drivers/ide/pci/pdc202xx_old.c Fri Oct 17 14:43:51 2003 +++ b/drivers/ide/pci/pdc202xx_old.c Fri Oct 17 14:43:51 2003 @@ -518,13 +518,15 @@ } else { goto fast_ata_pio; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: hwif->tuneproc(drive, 5); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } static int pdc202xx_quirkproc (ide_drive_t *drive) diff -Nru a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c --- a/drivers/ide/pci/piix.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/piix.c Fri Oct 17 14:43:50 2003 @@ -588,13 +588,15 @@ } else { goto fast_ata_pio; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: hwif->tuneproc(drive, 255); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } /** diff -Nru a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c --- a/drivers/ide/pci/serverworks.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/serverworks.c Fri Oct 17 14:43:50 2003 @@ -272,7 +272,7 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(svwks_ratemask(drive), xferspeed); + u8 speed; u8 pio = ide_get_best_pio_mode(drive, 255, 5, NULL); u8 unit = (drive->select.b.unit & 0x01); u8 csb5 = svwks_csb_check(dev); @@ -280,6 +280,11 @@ u8 dma_timing = 0, pio_timing = 0; u16 csb5_pio = 0; + if (xferspeed == 255) /* PIO auto-tuning */ + speed = XFER_PIO_0 + pio; + else + speed = ide_rate_filter(svwks_ratemask(drive), xferspeed); + /* If we are about to put a disk into UDMA mode we screwed up. Our code assumes we never _ever_ do this on an OSB4 */ @@ -484,6 +489,7 @@ } else { goto no_dma_set; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: @@ -491,7 +497,8 @@ // hwif->tuneproc(drive, 5); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } /* This can go soon */ diff -Nru a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c --- a/drivers/ide/pci/siimage.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/siimage.c Fri Oct 17 14:43:50 2003 @@ -515,13 +515,15 @@ } else { goto fast_ata_pio; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: config_chipset_for_pio(drive, 1); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } /* returns 1 if dma irq issued, 0 otherwise */ diff -Nru a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c --- a/drivers/ide/pci/sis5513.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/sis5513.c Fri Oct 17 14:43:50 2003 @@ -696,13 +696,15 @@ } else { goto fast_ata_pio; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: sis5513_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } /* initiates/aborts (U)DMA read/write operations on a drive. */ diff -Nru a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c --- a/drivers/ide/pci/slc90e66.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/pci/slc90e66.c Fri Oct 17 14:43:50 2003 @@ -301,13 +301,15 @@ } else { goto fast_ata_pio; } + return hwif->ide_dma_on(drive); } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: no_dma_set: hwif->tuneproc(drive, 5); return hwif->ide_dma_off_quietly(drive); } - return hwif->ide_dma_on(drive); + /* IORDY not supported */ + return 0; } #endif /* CONFIG_BLK_DEV_IDEDMA */ diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c --- a/drivers/ide/setup-pci.c Fri Oct 17 14:43:50 2003 +++ b/drivers/ide/setup-pci.c Fri Oct 17 14:43:50 2003 @@ -587,7 +587,6 @@ int at_least_one_hwif_enabled = 0; ide_hwif_t *hwif, *mate = NULL; static int secondpdc = 0; - int drive0_tune, drive1_tune; u8 tmp; index->all = 0xf0f0; @@ -648,26 +647,11 @@ else ide_hwif_setup_dma(dev, d, hwif); bypass_legacy_dma: - - drive0_tune = hwif->drives[0].autotune; - drive1_tune = hwif->drives[1].autotune; - if (d->init_hwif) /* Call chipset-specific routine * for each enabled hwif */ d->init_hwif(hwif); - - /* - * This is in the wrong place. The driver may - * do set up based on the autotune value and this - * will then trash it. Torben please move it and - * propagate the fixes into the drivers - */ - if (drive0_tune == IDE_TUNE_BIOS) /* biostimings */ - hwif->drives[0].autotune = IDE_TUNE_BIOS; - if (drive1_tune == IDE_TUNE_BIOS) - hwif->drives[1].autotune = IDE_TUNE_BIOS; mate = hwif; at_least_one_hwif_enabled = 1; diff -Nru a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c --- a/drivers/isdn/hardware/eicon/divasmain.c Fri Oct 17 14:43:50 2003 +++ b/drivers/isdn/hardware/eicon/divasmain.c Fri Oct 17 14:43:50 2003 @@ -1,4 +1,4 @@ -/* $Id: divasmain.c,v 1.43 2003/09/22 08:57:31 schindler Exp $ +/* $Id: divasmain.c,v 1.46 2003/10/10 12:28:14 armin Exp $ * * Low level driver for Eicon DIVA Server ISDN cards. * @@ -41,7 +41,7 @@ #include "diva_dma.h" #include "diva_pci.h" -static char *main_revision = "$Revision: 1.43 $"; +static char *main_revision = "$Revision: 1.46 $"; static int major; @@ -69,7 +69,7 @@ extern void divasfunc_exit(void); typedef struct _diva_os_thread_dpc { - struct tasklet_struct divas_task; + struct work_struct divas_task; struct work_struct trap_script_task; diva_os_soft_isr_t *psoft_isr; int card_failed; @@ -552,7 +552,7 @@ /* -------------------------------------------------------------------------- DPC framework implementation -------------------------------------------------------------------------- */ -static void diva_os_dpc_proc(unsigned long context) +static void diva_os_dpc_proc(void *context) { diva_os_thread_dpc_t *psoft_isr = (diva_os_thread_dpc_t *) context; diva_os_soft_isr_t *pisr = psoft_isr->psoft_isr; @@ -575,8 +575,7 @@ psoft_isr->callback_context = callback_context; pdpc->psoft_isr = psoft_isr; INIT_WORK(&pdpc->trap_script_task, diva_adapter_trapped, pdpc); - tasklet_init(&pdpc->divas_task, diva_os_dpc_proc, - (unsigned long) pdpc); + INIT_WORK(&pdpc->divas_task, diva_os_dpc_proc, pdpc); return (0); } @@ -587,7 +586,7 @@ diva_os_thread_dpc_t *pdpc = (diva_os_thread_dpc_t *) psoft_isr->object; - tasklet_schedule(&pdpc->divas_task); + schedule_work(&pdpc->divas_task); } return (1); @@ -595,26 +594,18 @@ int diva_os_cancel_soft_isr(diva_os_soft_isr_t * psoft_isr) { - if (psoft_isr && psoft_isr->object) { - diva_os_thread_dpc_t *pdpc = - (diva_os_thread_dpc_t *) psoft_isr->object; - tasklet_kill(&pdpc->divas_task); - } + flush_scheduled_work(); return (0); } void diva_os_remove_soft_isr(diva_os_soft_isr_t * psoft_isr) { if (psoft_isr && psoft_isr->object) { - diva_os_thread_dpc_t *pdpc = - (diva_os_thread_dpc_t *) psoft_isr->object; void *mem; - tasklet_kill(&pdpc->divas_task); - + flush_scheduled_work(); mem = psoft_isr->object; psoft_isr->object = 0; - flush_scheduled_work(); diva_os_free(0, mem); } } diff -Nru a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c --- a/drivers/macintosh/adbhid.c Fri Oct 17 14:43:51 2003 +++ b/drivers/macintosh/adbhid.c Fri Oct 17 14:43:51 2003 @@ -611,8 +611,8 @@ /* HACK WARNING!! This should go away as soon there is an utility * to control that for event devices. */ - adbhid[id]->input.rep[REP_DELAY] = HZ/2; /* input layer default: HZ/4 */ - adbhid[id]->input.rep[REP_PERIOD] = HZ/15; /* input layer default: HZ/33 */ + adbhid[id]->input.rep[REP_DELAY] = 500; /* input layer default: 250 */ + adbhid[id]->input.rep[REP_PERIOD] = 66; /* input layer default: 33 */ } } diff -Nru a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c --- a/drivers/media/common/saa7146_fops.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/common/saa7146_fops.c Fri Oct 17 14:43:50 2003 @@ -61,8 +61,14 @@ } DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state)); + DEB_EE(("q->curr:%p\n",q->curr)); /* finish current buffer */ + if (NULL == q->curr) { + DEB_D(("aiii. no current buffer\n")); + return; + } + q->curr->vb.state = state; do_gettimeofday(&q->curr->vb.ts); wake_up(&q->curr->vb.done); @@ -221,9 +227,12 @@ fh->dev = dev; fh->type = type; - saa7146_video_uops.open(dev,fh); - if( 0 != BOARD_CAN_DO_VBI(dev) ) { + if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + DEB_S(("initializing vbi...\n")); saa7146_vbi_uops.open(dev,fh); + } else { + DEB_S(("initializing video...\n")); + saa7146_video_uops.open(dev,fh); } result = 0; @@ -245,9 +254,10 @@ if (down_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; - saa7146_video_uops.release(dev,fh,file); - if( 0 != BOARD_CAN_DO_VBI(dev) ) { + if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { saa7146_vbi_uops.release(dev,fh,file); + } else { + saa7146_video_uops.release(dev,fh,file); } module_put(dev->ext->module); @@ -332,11 +342,11 @@ switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count)); +// DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count)); return saa7146_video_uops.read(file,data,count,ppos); } case V4L2_BUF_TYPE_VBI_CAPTURE: { - DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count)); +// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count)); return saa7146_vbi_uops.read(file,data,count,ppos); } break; @@ -443,7 +453,7 @@ { struct saa7146_vv *vv = dev->vv_data; - DEB_EE(("dev:%p, name:'%s'\n",dev,name)); + DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type)); *vid = device_template; strlcpy(vid->name, name, sizeof(vid->name)); @@ -451,7 +461,7 @@ // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); if (video_register_device(vid,type,-1) < 0) { - ERR(("cannot register vbi v4l2 device. skipping.\n")); + ERR(("cannot register v4l2 device. skipping.\n")); return -1; } diff -Nru a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c --- a/drivers/media/common/saa7146_vbi.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/common/saa7146_vbi.c Fri Oct 17 14:43:50 2003 @@ -38,8 +38,14 @@ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4)); /* BXO = 1h, BRS to outbound */ WRITE_RPS1(0xc000008c); - /* wait for vbi_a */ + /* wait for vbi_a or vbi_b*/ + if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) { + DEB_D(("...using port b\n")); + WRITE_RPS1(CMD_PAUSE | MASK_09); + } else { + DEB_D(("...using port a\n")); WRITE_RPS1(CMD_PAUSE | MASK_10); + } /* upload brs */ WRITE_RPS1(CMD_UPLOAD | MASK_08); /* load brs-control register */ @@ -106,7 +112,7 @@ if(signal_pending(current)) { - DEB_VBI(("aborted.\n")); + DEB_VBI(("aborted (rps:0x%08x).\n",saa7146_read(dev,RPS_ADDR1))); /* stop rps1 for sure */ saa7146_write(dev, MC1, MASK_29); @@ -316,6 +322,11 @@ saa7146_write(dev, MC1, MASK_20); vv->vbi_streaming = NULL; + + del_timer(&vv->vbi_q.timeout); + del_timer(&fh->vbi_read_timeout); + + DEB_VBI(("out\n")); spin_unlock_irqrestore(&dev->slock, flags); } @@ -371,7 +382,10 @@ fh->vbi_read_timeout.function = vbi_read_timeout; fh->vbi_read_timeout.data = (unsigned long)fh; + /* fixme: enable this again, if the dvb-c w/ analog module work properly */ +/* vbi_workaround(dev); +*/ } static void vbi_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file) diff -Nru a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c --- a/drivers/media/common/saa7146_video.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/common/saa7146_video.c Fri Oct 17 14:43:50 2003 @@ -1319,7 +1319,7 @@ saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); } - err = videobuf_iolock(dev->pci,&buf->vb,NULL); + err = videobuf_iolock(dev->pci,&buf->vb, &vv->ov_fb); if (err) goto oops; err = saa7146_pgtable_build(dev,buf); diff -Nru a/drivers/media/dvb/dvb-core/dvb_i2c.c b/drivers/media/dvb/dvb-core/dvb_i2c.c --- a/drivers/media/dvb/dvb-core/dvb_i2c.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/dvb-core/dvb_i2c.c Fri Oct 17 14:43:50 2003 @@ -32,8 +32,9 @@ struct dvb_i2c_device { struct list_head list_head; struct module *owner; - int (*attach) (struct dvb_i2c_bus *i2c); - void (*detach) (struct dvb_i2c_bus *i2c); + int (*attach) (struct dvb_i2c_bus *i2c, void **data); + void (*detach) (struct dvb_i2c_bus *i2c, void *data); + void *data; }; LIST_HEAD(dvb_i2c_buslist); @@ -66,7 +67,7 @@ return; } - if (dev->attach (i2c) == 0) { + if (dev->attach (i2c, &dev->data) == 0) { register_i2c_client (i2c, dev); } else { if (dev->owner) @@ -77,7 +78,7 @@ static void detach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev) { - dev->detach (i2c); + dev->detach (i2c, dev->data); if (dev->owner) module_put (dev->owner); @@ -229,8 +230,8 @@ int dvb_register_i2c_device (struct module *owner, - int (*attach) (struct dvb_i2c_bus *i2c), - void (*detach) (struct dvb_i2c_bus *i2c)) + int (*attach) (struct dvb_i2c_bus *i2c, void **data), + void (*detach) (struct dvb_i2c_bus *i2c, void *data)) { struct dvb_i2c_device *entry; @@ -256,7 +257,7 @@ } -int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c)) +int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c, void **data)) { struct list_head *entry, *n; diff -Nru a/drivers/media/dvb/dvb-core/dvb_i2c.h b/drivers/media/dvb/dvb-core/dvb_i2c.h --- a/drivers/media/dvb/dvb-core/dvb_i2c.h Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/dvb-core/dvb_i2c.h Fri Oct 17 14:43:50 2003 @@ -54,10 +54,10 @@ extern int dvb_register_i2c_device (struct module *owner, - int (*attach) (struct dvb_i2c_bus *i2c), - void (*detach) (struct dvb_i2c_bus *i2c)); + int (*attach) (struct dvb_i2c_bus *i2c, void **data), + void (*detach) (struct dvb_i2c_bus *i2c, void *data)); -extern int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c)); +extern int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c, void **data)); #endif diff -Nru a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig --- a/drivers/media/dvb/frontends/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/Kconfig Fri Oct 17 14:43:50 2003 @@ -16,16 +16,6 @@ DVB adapter simply enable all supported frontends, the right one will get autodetected. -config DVB_ALPS_BSRV2 - tristate "Alps BSRV2 (QPSK)" - depends on DVB_CORE - help - A DVB-S tuner module. Say Y when you want to support this frontend. - - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. - config DVB_SP887X tristate "Frontends with sp887x demodulators, e.g. Microtune DTF7072" depends on DVB_CORE @@ -120,6 +110,16 @@ The VES1820 Demodulator is used on many DVB-C PCI cards and in some DVB-C SetTopBoxes. Say Y when you see this demodulator chip near your tuner module. + + If you don't know what tuner module is soldered on your + DVB adapter simply enable all supported frontends, the + right one will get autodetected. + +config DVB_VES1X93 + tristate "Frontends with VES1893 or VES1993 demodulator (QPSK)" + depends on DVB_CORE + help + A DVB-S tuner module. Say Y when you want to support this frontend. If you don't know what tuner module is soldered on your DVB adapter simply enable all supported frontends, the diff -Nru a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile --- a/drivers/media/dvb/frontends/Makefile Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/Makefile Fri Oct 17 14:43:50 2003 @@ -5,7 +5,6 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ obj-$(CONFIG_DVB_STV0299) += stv0299.o -obj-$(CONFIG_DVB_ALPS_BSRV2) += alps_bsrv2.o obj-$(CONFIG_DVB_ALPS_TDLB7) += alps_tdlb7.o obj-$(CONFIG_DVB_ALPS_TDMB7) += alps_tdmb7.o obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o @@ -14,5 +13,6 @@ obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o obj-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_VES1820) += ves1820.o +obj-$(CONFIG_DVB_VES1X93) += ves1x93.o obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o obj-$(CONFIG_DVB_SP887X) += sp887x.o diff -Nru a/drivers/media/dvb/frontends/alps_bsrv2.c b/drivers/media/dvb/frontends/alps_bsrv2.c --- a/drivers/media/dvb/frontends/alps_bsrv2.c Fri Oct 17 14:43:50 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,469 +0,0 @@ -/* - Driver for Alps BSRV2 QPSK Frontend - - Copyright (C) 1999 Convergence Integrated Media GmbH - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "dvb_frontend.h" - -static int debug = 0; -#define dprintk if (debug) printk - - -static struct dvb_frontend_info bsrv2_info = { - .name = "Alps BSRV2", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 250, /* kHz for QPSK frontends */ - .frequency_tolerance = 29500, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, -/* . symbol_rate_tolerance = ???,*/ - .notifier_delay = 50, /* 1/20 s */ - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK -}; - - - -static u8 init_1893_tab [] = { - 0x01, 0xA4, 0x35, 0x81, 0x2A, 0x0d, 0x55, 0xC4, - 0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7F, 0x00, - 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xDC, 0x00, - 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x55, 0x00, 0x00, 0x7f, 0x00 -}; - - -static u8 init_1893_wtab[] = -{ - 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0, - 0,1,0,0,0,0,0,0, 1,0,1,1,0,0,0,1, - 1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0, - 1,1,1,0,1,1 -}; - - -static int ves1893_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) -{ - u8 buf [] = { 0x00, reg, data }; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 3 }; - int err; - - if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { - dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); - return -EREMOTEIO; - } - - return 0; -} - - -static u8 ves1893_readreg (struct dvb_i2c_bus *i2c, u8 reg) -{ - int ret; - u8 b0 [] = { 0x00, reg }; - u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b0, .len = 2 }, - { .addr = 0x08, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - - ret = i2c->xfer (i2c, msg, 2); - - if (ret != 2) - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - - return b1[0]; -} - - -static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4]) -{ - int ret; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = 4 }; - - ret = i2c->xfer (i2c, &msg, 1); - - if (ret != 1) - printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); - - return (ret != 1) ? -1 : 0; -} - - - -/** - * set up the downconverter frequency divisor for a - * reference clock comparision frequency of 125 kHz. - */ -static int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) -{ - u32 div = (freq + 479500) / 125; - u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x95, (pwr << 5) | 0x30 }; - - return sp5659_write (i2c, buf); -} - - -static int ves1893_init (struct dvb_i2c_bus *i2c) -{ - int i; - - dprintk("%s: init chip\n", __FUNCTION__); - - for (i=0; i<54; i++) - if (init_1893_wtab[i]) - ves1893_writereg (i2c, i, init_1893_tab[i]); - - return 0; -} - - -static int ves1893_clr_bit (struct dvb_i2c_bus *i2c) -{ - ves1893_writereg (i2c, 0, init_1893_tab[0] & 0xfe); - ves1893_writereg (i2c, 0, init_1893_tab[0]); - ves1893_writereg (i2c, 3, 0x00); - return ves1893_writereg (i2c, 3, init_1893_tab[3]); -} - - -static int ves1893_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion_t inversion) -{ - u8 val; - - /* - * inversion on/off are interchanged because i and q seem to - * be swapped on the hardware - */ - - switch (inversion) { - case INVERSION_OFF: - val = 0xc0; - break; - case INVERSION_ON: - val = 0x80; - break; - case INVERSION_AUTO: - val = 0x00; - break; - default: - return -EINVAL; - } - - /* needs to be saved for FE_GET_FRONTEND */ - init_1893_tab[0x0c] = (init_1893_tab[0x0c] & 0x3f) | val; - - return ves1893_writereg (i2c, 0x0c, init_1893_tab[0x0c]); -} - - -static int ves1893_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) -{ - if (fec == FEC_AUTO) - return ves1893_writereg (i2c, 0x0d, 0x08); - else if (fec < FEC_1_2 || fec > FEC_8_9) - return -EINVAL; - else - return ves1893_writereg (i2c, 0x0d, fec - FEC_1_2); -} - - -static fe_code_rate_t ves1893_get_fec (struct dvb_i2c_bus *i2c) -{ - return FEC_1_2 + ((ves1893_readreg (i2c, 0x0d) >> 4) & 0x7); -} - - -static int ves1893_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) -{ - u32 BDR; - u32 ratio; - u8 ADCONF, FCONF, FNR; - u32 BDRI; - u32 tmp; - - dprintk("%s: srate == %ud\n", __FUNCTION__, (unsigned int) srate); - - if (srate > 90100000UL/2) - srate = 90100000UL/2; - - if (srate < 500000) - srate = 500000; - -#define MUL (1UL<<26) -#define FIN (90106000UL>>4) - - tmp = srate << 6; - ratio = tmp / FIN; - - tmp = (tmp % FIN) << 8; - ratio = (ratio << 8) + tmp / FIN; - - tmp = (tmp % FIN) << 8; - ratio = (ratio << 8) + tmp / FIN; - - FNR = 0xff; - - if (ratio < MUL/3) FNR = 0; - if (ratio < (MUL*11)/50) FNR = 1; - if (ratio < MUL/6) FNR = 2; - if (ratio < MUL/9) FNR = 3; - if (ratio < MUL/12) FNR = 4; - if (ratio < (MUL*11)/200) FNR = 5; - if (ratio < MUL/24) FNR = 6; - if (ratio < (MUL*27)/1000) FNR = 7; - if (ratio < MUL/48) FNR = 8; - if (ratio < (MUL*137)/10000) FNR = 9; - - if (FNR == 0xff) { - ADCONF = 0x89; - FCONF = 0x80; - FNR = 0; - } else { - ADCONF = 0x81; - FCONF = 0x88 | (FNR >> 1) | ((FNR & 0x01) << 5); - } - - BDR = (( (ratio << (FNR >> 1)) >> 4) + 1) >> 1; - BDRI = ( ((FIN << 8) / ((srate << (FNR >> 1)) >> 2)) + 1) >> 1; - - dprintk("FNR= %d\n", FNR); - dprintk("ratio= %08x\n", (unsigned int) ratio); - dprintk("BDR= %08x\n", (unsigned int) BDR); - dprintk("BDRI= %02x\n", (unsigned int) BDRI); - - if (BDRI > 0xff) - BDRI = 0xff; - - ves1893_writereg (i2c, 0x06, 0xff & BDR); - ves1893_writereg (i2c, 0x07, 0xff & (BDR >> 8)); - ves1893_writereg (i2c, 0x08, 0x0f & (BDR >> 16)); - - ves1893_writereg (i2c, 0x09, BDRI); - ves1893_writereg (i2c, 0x20, ADCONF); - ves1893_writereg (i2c, 0x21, FCONF); - - if (srate < 6000000) - ves1893_writereg (i2c, 0x05, init_1893_tab[0x05] | 0x80); - else - ves1893_writereg (i2c, 0x05, init_1893_tab[0x05] & 0x7f); - - ves1893_writereg (i2c, 0x00, 0x00); - ves1893_writereg (i2c, 0x00, 0x01); - - ves1893_clr_bit (i2c); - - return 0; -} - - -static int ves1893_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) -{ - switch (voltage) { - case SEC_VOLTAGE_13: - return ves1893_writereg (i2c, 0x1f, 0x20); - case SEC_VOLTAGE_18: - return ves1893_writereg (i2c, 0x1f, 0x30); - case SEC_VOLTAGE_OFF: - return ves1893_writereg (i2c, 0x1f, 0x00); - default: - return -EINVAL; - } -} - - -static int bsrv2_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct dvb_i2c_bus *i2c = fe->i2c; - - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &bsrv2_info, sizeof(struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: - { - fe_status_t *status = arg; - u8 sync = ves1893_readreg (i2c, 0x0e); - - *status = 0; - - if (sync & 1) - *status |= FE_HAS_SIGNAL; - - if (sync & 2) - *status |= FE_HAS_CARRIER; - - if (sync & 4) - *status |= FE_HAS_VITERBI; - - if (sync & 8) - *status |= FE_HAS_SYNC; - - if ((sync & 0x1f) == 0x1f) - *status |= FE_HAS_LOCK; - - break; - } - - case FE_READ_BER: - { - u32 *ber = (u32 *) arg; - - *ber = ves1893_readreg (i2c, 0x15); - *ber |= (ves1893_readreg (i2c, 0x16) << 8); - *ber |= ((ves1893_readreg (i2c, 0x17) & 0x0f) << 16); - *ber *= 10; - break; - } - - case FE_READ_SIGNAL_STRENGTH: - { - u8 signal = ~ves1893_readreg (i2c, 0x0b); - *((u16*) arg) = (signal << 8) | signal; - break; - } - - case FE_READ_SNR: - { - u8 snr = ~ves1893_readreg (i2c, 0x1c); - *(u16*) arg = (snr << 8) | snr; - break; - } - - case FE_READ_UNCORRECTED_BLOCKS: - { - *(u32*) arg = ves1893_readreg (i2c, 0x18) & 0x7f; - - if (*(u32*) arg == 0x7f) - *(u32*) arg = 0xffffffff; /* counter overflow... */ - - ves1893_writereg (i2c, 0x18, 0x00); /* reset the counter */ - ves1893_writereg (i2c, 0x18, 0x80); /* dto. */ - break; - } - - case FE_SET_FRONTEND: - { - struct dvb_frontend_parameters *p = arg; - - sp5659_set_tv_freq (i2c, p->frequency, 0); - ves1893_set_inversion (i2c, p->inversion); - ves1893_set_fec (i2c, p->u.qpsk.fec_inner); -// sp5659_set_tv_freq (i2c, p->frequency, 0); - ves1893_set_symbolrate (i2c, p->u.qpsk.symbol_rate); - break; - } - - case FE_GET_FRONTEND: - { - struct dvb_frontend_parameters *p = arg; - int afc; - - afc = ((int)((char)(ves1893_readreg (i2c, 0x0a) << 1)))/2; - afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16; - - p->frequency -= afc; - - /* - * inversion indicator is only valid - * if auto inversion was used - */ - if (!(init_1893_tab[0x0c] & 0x80)) - p->inversion = (ves1893_readreg (i2c, 0x0f) & 2) ? - INVERSION_OFF : INVERSION_ON; - p->u.qpsk.fec_inner = ves1893_get_fec (i2c); - /* XXX FIXME: timing offset !! */ - break; - } - - case FE_SLEEP: - ves1893_writereg (i2c, 0x1f, 0x00); /* LNB power off */ - return ves1893_writereg (i2c, 0x00, 0x08); - - case FE_INIT: - return ves1893_init (i2c); - - case FE_RESET: - return ves1893_clr_bit (i2c); - - case FE_SET_TONE: - return -EOPNOTSUPP; /* the ves1893 can generate the 22k */ - /* let's implement this when we have */ - /* a box that uses the 22K_0 pin... */ - case FE_SET_VOLTAGE: - return ves1893_set_voltage (i2c, (fe_sec_voltage_t) arg); - - default: - return -EOPNOTSUPP; - }; - - return 0; -} - - -static int bsrv2_attach (struct dvb_i2c_bus *i2c) -{ - if ((ves1893_readreg (i2c, 0x1e) & 0xf0) != 0xd0) - return -ENODEV; - - dvb_register_frontend (bsrv2_ioctl, i2c, NULL, &bsrv2_info); - - return 0; -} - - -static void bsrv2_detach (struct dvb_i2c_bus *i2c) -{ - dvb_unregister_frontend (bsrv2_ioctl, i2c); -} - - -static int __init init_bsrv2 (void) -{ - return dvb_register_i2c_device (THIS_MODULE, bsrv2_attach, bsrv2_detach); -} - - -static void __exit exit_bsrv2 (void) -{ - dvb_unregister_i2c_device (bsrv2_attach); -} - - -module_init(init_bsrv2); -module_exit(exit_bsrv2); - - -MODULE_DESCRIPTION("BSRV2 DVB-S Frontend"); -MODULE_AUTHOR("Ralph Metzler"); -MODULE_LICENSE("GPL"); -MODULE_PARM(debug,"i"); - diff -Nru a/drivers/media/dvb/frontends/alps_tdlb7.c b/drivers/media/dvb/frontends/alps_tdlb7.c --- a/drivers/media/dvb/frontends/alps_tdlb7.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/alps_tdlb7.c Fri Oct 17 14:43:50 2003 @@ -1,7 +1,7 @@ /* Driver for Alps TDLB7 Frontend - Copyright (C) 1999 Juergen Peitz + Copyright (C) 1999 Juergen Peitz 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 @@ -22,23 +22,9 @@ /* - - Wrote this code mainly to get my own card running. It's working for me, but I - hope somebody who knows more about linux programming and the DVB driver can - improve it. - - Reused a lot from the existing driver and tuner code. - Thanks to everybody who worked on it! - - This driver needs a copy of the microcode file 'Sc_main.mc' from the Haupauge - windows driver in the 'usr/lib/DVB/driver/frontends' directory. - You can also pass the complete file name with the module parameter 'mcfile'. - - The code only needs to be loaded once after a power on. Because loading the - microcode to the card takes some time, you can use the 'loadcode=0' module - parameter, if you only want to reload the dvb driver. - - Juergen Peitz + This driver needs a copy of the firmware file 'Sc_main.mc' from the Haupauge + windows driver in the '/usr/lib/DVB/driver/frontends' directory. + You can also pass the complete file name with the module parameter 'firmware_file'. */ @@ -50,49 +36,46 @@ #include #include #include +#include #include "dvb_frontend.h" +#include "dvb_functions.h" -static int debug = 0; - -static int loadcode = 1; +#ifndef CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION +#define CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION "/usr/lib/DVB/driver/frontends/Sc_main.mc" +#endif -static char * mcfile = "/usr/lib/DVB/driver/frontends/Sc_main.mc"; +static char * firmware_file = CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION; +static int debug = 0; #define dprintk if (debug) printk -/* microcode size for sp8870 */ -#define SP8870_CODE_SIZE 16382 +/* firmware size for sp8870 */ +#define SP8870_FIRMWARE_SIZE 16382 -/* starting point for microcode in file 'Sc_main.mc' */ -#define SP8870_CODE_OFFSET 0x0A +/* starting point for firmware in file 'Sc_main.mc' */ +#define SP8870_FIRMWARE_OFFSET 0x0A static int errno; static struct dvb_frontend_info tdlb7_info = { - .name = "Alps TDLB7", - .type = FE_OFDM, - .frequency_min = 470000000, - .frequency_max = 860000000, - .frequency_stepsize = 166666, -#if 0 - .frequency_tolerance = ???, - .symbol_rate_min = ???, - .symbol_rate_max = ???, - .symbol_rate_tolerance = ???, - .notifier_delay = 0, -#endif - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + name: "Alps TDLB7", + type: FE_OFDM, + frequency_min: 470000000, + frequency_max: 860000000, + frequency_stepsize: 166666, + caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER }; static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data) { u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff }; - struct i2c_msg msg = { .addr = 0x71, .flags = 0, .buf = buf, .len = 4 }; + struct i2c_msg msg = { addr: 0x71, flags: 0, buf: buf, len: 4 }; int err; if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { @@ -109,13 +92,15 @@ int ret; u8 b0 [] = { reg >> 8 , reg & 0xff }; u8 b1 [] = { 0, 0 }; - struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 }, - { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } }; + struct i2c_msg msg [] = { { addr: 0x71, flags: 0, buf: b0, len: 2 }, + { addr: 0x71, flags: I2C_M_RD, buf: b1, len: 2 } }; ret = i2c->xfer (i2c, msg, 2); - if (ret != 2) + if (ret != 2) { dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + return -1; + } return (b1[0] << 8 | b1[1]); } @@ -124,7 +109,7 @@ static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4]) { int ret; - struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = 4 }; + struct i2c_msg msg = { addr: 0x60, flags: 0, buf: data, len: 4 }; ret = i2c->xfer (i2c, &msg, 1); @@ -135,7 +120,7 @@ } -static int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +static void sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) { u32 div = (freq + 36200000) / 166666; u8 buf [4]; @@ -151,102 +136,146 @@ buf[2] = 0x85; buf[3] = pwr << 6; - return sp5659_write (i2c, buf); + /* open i2c gate for PLL message transmission... */ + sp8870_writereg(i2c, 0x206, 0x001); + sp5659_write (i2c, buf); + sp8870_writereg(i2c, 0x206, 0x000); } -static int sp8870_read_code(const char *fn, char **fp) +static int sp8870_read_firmware_file (const char *fn, char **fp) { int fd; - loff_t l; + loff_t filesize; char *dp; fd = open(fn, 0, 0); if (fd == -1) { - printk(KERN_INFO "%s: Unable to load '%s'.\n", __FUNCTION__, fn); - return -1; + printk("%s: unable to open '%s'.\n", __FUNCTION__, fn); + return -EIO; } - l = lseek(fd, 0L, 2); - if (l <= 0 || l < SP8870_CODE_OFFSET+SP8870_CODE_SIZE) { - printk(KERN_INFO "%s: code file too small '%s'\n", __FUNCTION__, fn); + + filesize = lseek(fd, 0L, 2); + if (filesize <= 0 || filesize < SP8870_FIRMWARE_OFFSET + SP8870_FIRMWARE_SIZE) { + printk("%s: firmware filesize to small '%s'\n", __FUNCTION__, fn); sys_close(fd); - return -1; + return -EIO; } - lseek(fd, SP8870_CODE_OFFSET, 0); - *fp= dp = vmalloc(SP8870_CODE_SIZE); + + *fp= dp = vmalloc(SP8870_FIRMWARE_SIZE); if (dp == NULL) { - printk(KERN_INFO "%s: Out of memory loading '%s'.\n", __FUNCTION__, fn); + printk("%s: out of memory loading '%s'.\n", __FUNCTION__, fn); sys_close(fd); - return -1; + return -EIO; } - if (read(fd, dp, SP8870_CODE_SIZE) != SP8870_CODE_SIZE) { - printk(KERN_INFO "%s: Failed to read '%s'.\n",__FUNCTION__, fn); + + lseek(fd, SP8870_FIRMWARE_OFFSET, 0); + if (read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) { + printk("%s: failed to read '%s'.\n",__FUNCTION__, fn); vfree(dp); sys_close(fd); - return -1; + return -EIO; } + sys_close(fd); *fp = dp; + return 0; } -static int sp8870_load_code(struct dvb_i2c_bus *i2c) +static int sp8870_firmware_upload (struct dvb_i2c_bus *i2c) { - /* this takes a long time. is there a way to do it faster? */ - char *lcode; struct i2c_msg msg; - unsigned char buf[255]; - int err; - int p=0; - int c; + char *fw_buf = NULL; + int fw_pos; + u8 tx_buf[255]; + int tx_len; + int err = 0; mm_segment_t fs = get_fs(); + dprintk ("%s: ...\n", __FUNCTION__); + // system controller stop sp8870_writereg(i2c,0x0F00,0x0000); // instruction RAM register hiword - sp8870_writereg(i2c,0x8F08,((SP8870_CODE_SIZE/2) & 0xFFFF)); + sp8870_writereg(i2c, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF)); // instruction RAM MWR - sp8870_writereg(i2c,0x8F0A,((SP8870_CODE_SIZE/2) >> 16)); + sp8870_writereg(i2c, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16)); + // reading firmware file to buffer set_fs(get_ds()); - if (sp8870_read_code(mcfile,(char**) &lcode)<0) return -1; + err = sp8870_read_firmware_file(firmware_file, (char**) &fw_buf); set_fs(fs); - while (pxfer (i2c, &msg, 1)) != 1) { - dprintk ("%s: i2c error (err == %i)\n", - __FUNCTION__, err); - vfree(lcode); - return -EREMOTEIO; + printk("%s: firmware upload failed!\n", __FUNCTION__); + printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err); + vfree(fw_buf); + return err; } - - p+=252; + fw_pos += tx_len; } - vfree(lcode); + + vfree(fw_buf); + + dprintk ("%s: done!\n", __FUNCTION__); return 0; }; -static int sp8870_init (struct dvb_i2c_bus *i2c) +static void sp8870_microcontroller_stop (struct dvb_i2c_bus *i2c) +{ + sp8870_writereg(i2c, 0x0F08, 0x000); + sp8870_writereg(i2c, 0x0F09, 0x000); + + // microcontroller STOP + sp8870_writereg(i2c, 0x0F00, 0x000); +} + + +static void sp8870_microcontroller_start (struct dvb_i2c_bus *i2c) { + sp8870_writereg(i2c, 0x0F08, 0x000); + sp8870_writereg(i2c, 0x0F09, 0x000); + + // microcontroller START + sp8870_writereg(i2c, 0x0F00, 0x001); + // not documented but if we don't read 0x0D01 out here + // we don't get a correct data valid signal + sp8870_readreg(i2c, 0x0D01); +} + +static int sp8870_init (struct dvb_i2c_bus *i2c) +{ dprintk ("%s\n", __FUNCTION__); + /* enable TS output and interface pins */ + sp8870_writereg(i2c, 0xc18, 0x00d); + // system controller stop - sp8870_writereg(i2c,0x0F00,0x0000); + sp8870_microcontroller_stop(i2c); - // ADC mode: 2 for MT8872, 3 for MT8870/8871 + // ADC mode sp8870_writereg(i2c,0x0301,0x0003); // Reed Solomon parity bytes passed to output @@ -255,103 +284,214 @@ // MPEG clock is suppressed if no valid data sp8870_writereg(i2c,0x0C14,0x0001); - // sample rate correction bit [23..17] - sp8870_writereg(i2c,0x0319,0x000A); + /* bit 0x010: enable data valid signal */ + sp8870_writereg(i2c, 0x0D00, 0x010); + sp8870_writereg(i2c, 0x0D01, 0x000); - // sample rate correction bit [16..0] - sp8870_writereg(i2c,0x031A,0x0AAB); + return 0; +} - // integer carrier offset - sp8870_writereg(i2c,0x0309,0x0400); - // fractional carrier offset - sp8870_writereg(i2c,0x030A,0x0000); +static int sp8870_read_status (struct dvb_i2c_bus *i2c, fe_status_t * fe_status) +{ + int status; + int signal; - // filter for 8 Mhz channel - sp8870_writereg(i2c,0x0311,0x0000); + *fe_status = 0; - // scan order: 2k first = 0x0000, 8k first = 0x0001 - sp8870_writereg(i2c,0x0338,0x0000); + status = sp8870_readreg (i2c, 0x0200); + if (status < 0) + return -EIO; + + signal = sp8870_readreg (i2c, 0x0303); + if (signal < 0) + return -EIO; + + if (signal > 0x0F) + *fe_status |= FE_HAS_SIGNAL; + if (status & 0x08) + *fe_status |= FE_HAS_SYNC; + if (status & 0x04) + *fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI; return 0; } -static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int sp8870_read_ber (struct dvb_i2c_bus *i2c, u32 * ber) { - struct dvb_i2c_bus *i2c = fe->i2c; + int ret; + u32 tmp; - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &tdlb7_info, sizeof(struct dvb_frontend_info)); - break; + *ber = 0; - case FE_READ_STATUS: - { - fe_status_t *status = arg; - int sync = sp8870_readreg (i2c, 0x0200); - int signal = 0xff-sp8870_readreg (i2c, 0x303); + ret = sp8870_readreg(i2c, 0xC08); + if (ret < 0) + return -EIO; - *status=0; - if (signal>10) // FIXME: is 10 the right value ? - *status |= FE_HAS_SIGNAL; + tmp = ret & 0x3F; - if (sync&0x04) // FIXME: find criteria - *status |= FE_HAS_CARRIER; + ret = sp8870_readreg(i2c, 0xC07); + if (ret < 0) + return -EIO; - if (sync&0x04) // FIXME - *status |= FE_HAS_VITERBI; + tmp = ret << 6; - if (sync&0x08) // FIXME - *status |= FE_HAS_SYNC; + if (tmp >= 0x3FFF0) + tmp = ~0; - if (sync&0x04) - *status |= FE_HAS_LOCK; - break; + *ber = tmp; + return 0; } - case FE_READ_BER: + +static int sp8870_read_signal_strength (struct dvb_i2c_bus *i2c, u16 * signal) { - u32 *ber=(u32 *) arg; - // bit error rate before Viterbi - *ber=sp8870_readreg(i2c,0x0C07); - break; + int ret; + u16 tmp; - } + *signal = 0; - case FE_READ_SIGNAL_STRENGTH: // FIXME: correct registers ? - { - *((u16*) arg) = 0xffff-((sp8870_readreg (i2c, 0x306) << 8) | sp8870_readreg (i2c, 0x303)); - break; + ret = sp8870_readreg (i2c, 0x306); + if (ret < 0) + return -EIO; + + tmp = ret << 8; + + ret = sp8870_readreg (i2c, 0x303); + if (ret < 0) + return -EIO; + + tmp |= ret; + + if (tmp) + *signal = 0xFFFF - tmp; + + return 0; } - case FE_READ_SNR: // not supported by hardware? + +static int sp8870_read_snr(struct dvb_i2c_bus *i2c, u32* snr) { - s32 *snr=(s32 *) arg; *snr=0; return -EOPNOTSUPP; } - case FE_READ_UNCORRECTED_BLOCKS: // not supported by hardware? + +static int sp8870_read_uncorrected_blocks (struct dvb_i2c_bus *i2c, u32* ublocks) { - u32 *ublocks=(u32 *) arg; + int ret; + *ublocks=0; - return -EOPNOTSUPP; + + ret = sp8870_readreg(i2c, 0xC0C); + if (ret < 0) + return -EIO; + + if (ret == 0xFFFF) + ret = ~0; + + *ublocks = ret; + + return 0; } - case FE_SET_FRONTEND: + +static int sp8870_read_data_valid_signal(struct dvb_i2c_bus *i2c) +{ + return (sp8870_readreg(i2c, 0x0D02) > 0); +} + + +static +int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05) +{ + int known_parameters = 1; + + *reg0xc05 = 0x000; + + switch (p->u.ofdm.constellation) { + case QPSK: + break; + case QAM_16: + *reg0xc05 |= (1 << 10); + break; + case QAM_64: + *reg0xc05 |= (2 << 10); + break; + case QAM_AUTO: + known_parameters = 0; + break; + default: + return -EINVAL; + }; + + switch (p->u.ofdm.hierarchy_information) { + case HIERARCHY_NONE: + break; + case HIERARCHY_1: + *reg0xc05 |= (1 << 7); + break; + case HIERARCHY_2: + *reg0xc05 |= (2 << 7); + break; + case HIERARCHY_4: + *reg0xc05 |= (3 << 7); + break; + case HIERARCHY_AUTO: + known_parameters = 0; + break; + default: + return -EINVAL; + }; + + switch (p->u.ofdm.code_rate_HP) { + case FEC_1_2: + break; + case FEC_2_3: + *reg0xc05 |= (1 << 3); + break; + case FEC_3_4: + *reg0xc05 |= (2 << 3); + break; + case FEC_5_6: + *reg0xc05 |= (3 << 3); + break; + case FEC_7_8: + *reg0xc05 |= (4 << 3); + break; + case FEC_AUTO: + known_parameters = 0; + break; + default: + return -EINVAL; + }; + + if (known_parameters) + *reg0xc05 |= (2 << 1); /* use specified parameters */ + else + *reg0xc05 |= (1 << 1); /* enable autoprobing */ + + return 0; +} + + +static int sp8870_set_frontend_parameters (struct dvb_i2c_bus *i2c, + struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = arg; + int err; + u16 reg0xc05; + + if ((err = configure_reg0xc05(p, ®0xc05))) + return err; // system controller stop - sp8870_writereg(i2c,0x0F00,0x0000); + sp8870_microcontroller_stop(i2c); + // set tuner parameters sp5659_set_tv_freq (i2c, p->frequency); - // read status reg in order to clear pending irqs - sp8870_readreg(i2c, 0x200); - // sample rate correction bit [23..17] sp8870_writereg(i2c,0x0319,0x000A); @@ -378,28 +518,141 @@ else sp8870_writereg(i2c,0x0338,0x0001); - // instruction RAM register loword - sp8870_writereg(i2c,0x0F09,0x0000); + sp8870_writereg(i2c, 0xc05, reg0xc05); - // instruction RAM register hiword - sp8870_writereg(i2c,0x0F08,0x0000); + // read status reg in order to clear pending irqs + sp8870_readreg(i2c, 0x200); // system controller start - sp8870_writereg(i2c,0x0F00,0x0001); + sp8870_microcontroller_start(i2c); - break; + return 0; } - case FE_GET_FRONTEND: // FIXME: read known values back from Hardware... + +// number of trials to recover from lockup +#define MAXTRIALS 5 +// maximum checks for data valid signal +#define MAXCHECKS 100 + +// only for debugging: counter for detected lockups +static int lockups = 0; +// only for debugging: counter for channel switches +static int switches = 0; + +static int sp8870_set_frontend (struct dvb_i2c_bus *i2c, struct dvb_frontend_parameters *p) { + /* + The firmware of the sp8870 sometimes locks up after setting frontend parameters. + We try to detect this by checking the data valid signal. + If it is not set after MAXCHECKS we try to recover the lockup by setting + the frontend parameters again. + */ + + int err = 0; + int valid = 0; + int trials = 0; + int check_count = 0; + + dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency); + + for (trials = 1; trials <= MAXTRIALS; trials++) { + + if ((err = sp8870_set_frontend_parameters(i2c, p))) + return err; + + for (check_count = 0; check_count < MAXCHECKS; check_count++) { +// valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0); + valid = sp8870_read_data_valid_signal(i2c); + if (valid) { + dprintk("%s: delay = %i usec\n", + __FUNCTION__, check_count * 10); + break; + } + udelay(10); + } + if (valid) break; } - case FE_SLEEP: // is this supported by hardware? + if (!valid) { + printk("%s: firmware crash!!!!!!\n", __FUNCTION__); + return -EIO; + } + + if (debug) { + if (valid) { + if (trials > 1) { + printk("%s: firmware lockup!!!\n", __FUNCTION__); + printk("%s: recovered after %i trial(s))\n", __FUNCTION__, trials - 1); + lockups++; + } + } + switches++; + printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups); + } + + return 0; +} + + +static int sp8870_sleep(struct dvb_i2c_bus *i2c) +{ + // tristate TS output and disable interface pins + return sp8870_writereg(i2c, 0xC18, 0x000); +} + + +static int sp8870_wake_up(struct dvb_i2c_bus *i2c) +{ + // enable TS output and interface pins + return sp8870_writereg(i2c, 0xC18, 0x00D); +} + + +static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct dvb_i2c_bus *i2c = fe->i2c; + + switch (cmd) { + case FE_GET_INFO: + memcpy (arg, &tdlb7_info, sizeof(struct dvb_frontend_info)); + break; + + case FE_READ_STATUS: + return sp8870_read_status(i2c, (fe_status_t *) arg); + + case FE_READ_BER: + return sp8870_read_ber(i2c, (u32 *) arg); + + case FE_READ_SIGNAL_STRENGTH: + return sp8870_read_signal_strength(i2c, (u16 *) arg); + + case FE_READ_SNR: // not supported by hardware? + return sp8870_read_snr(i2c, (u32 *) arg); + + case FE_READ_UNCORRECTED_BLOCKS: + return sp8870_read_uncorrected_blocks(i2c, (u32 *) arg); + + case FE_SET_FRONTEND: + return sp8870_set_frontend(i2c, (struct dvb_frontend_parameters*) arg); + + case FE_RESET: return -EOPNOTSUPP; + case FE_GET_FRONTEND: // FIXME: read known values back from Hardware... + return -EOPNOTSUPP; + + case FE_SLEEP: + return sp8870_sleep(i2c); + case FE_INIT: - return sp8870_init (i2c); + sp8870_wake_up(i2c); + if (fe->data == NULL) { // first time initialisation... + fe->data = (void*) ~0; + sp8870_init (i2c); + } + break; default: return -EOPNOTSUPP; @@ -409,31 +662,22 @@ } -static int tdlb7_attach (struct dvb_i2c_bus *i2c) +static int tdlb7_attach (struct dvb_i2c_bus *i2c, void **data) { - - struct i2c_msg msg = { .addr = 0x71, .flags = 0, .buf = NULL, .len = 0 }; + struct i2c_msg msg = { addr: 0x71, flags: 0, buf: NULL, len: 0 }; dprintk ("%s\n", __FUNCTION__); if (i2c->xfer (i2c, &msg, 1) != 1) return -ENODEV; - if (loadcode) { - dprintk("%s: loading mcfile '%s' !\n", __FUNCTION__, mcfile); - if (sp8870_load_code(i2c)==0) - dprintk("%s: microcode loaded!\n", __FUNCTION__); - }else{ - dprintk("%s: without loading mcfile!\n", __FUNCTION__); - } - - dvb_register_frontend (tdlb7_ioctl, i2c, NULL, &tdlb7_info); + sp8870_firmware_upload(i2c); - return 0; + return dvb_register_frontend (tdlb7_ioctl, i2c, NULL, &tdlb7_info); } -static void tdlb7_detach (struct dvb_i2c_bus *i2c) +static void tdlb7_detach (struct dvb_i2c_bus *i2c, void *data) { dprintk ("%s\n", __FUNCTION__); @@ -464,11 +708,8 @@ MODULE_PARM(debug,"i"); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -MODULE_PARM(loadcode,"i"); -MODULE_PARM_DESC(loadcode, "load tuner microcode"); - -MODULE_PARM(mcfile,"s"); -MODULE_PARM_DESC(mcfile, "where to find the microcode file"); +MODULE_PARM(firmware_file,"s"); +MODULE_PARM_DESC(firmware_file, "where to find the firmware file"); MODULE_DESCRIPTION("TDLB7 DVB-T Frontend"); MODULE_AUTHOR("Juergen Peitz"); diff -Nru a/drivers/media/dvb/frontends/alps_tdmb7.c b/drivers/media/dvb/frontends/alps_tdmb7.c --- a/drivers/media/dvb/frontends/alps_tdmb7.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/alps_tdmb7.c Fri Oct 17 14:43:50 2003 @@ -402,7 +402,7 @@ -static int tdmb7_attach (struct dvb_i2c_bus *i2c) +static int tdmb7_attach (struct dvb_i2c_bus *i2c, void **data) { struct i2c_msg msg = { .addr = 0x43, .flags = 0, .buf = NULL,. len = 0 }; @@ -411,13 +411,11 @@ if (i2c->xfer (i2c, &msg, 1) != 1) return -ENODEV; - dvb_register_frontend (tdmb7_ioctl, i2c, NULL, &tdmb7_info); - - return 0; + return dvb_register_frontend (tdmb7_ioctl, i2c, NULL, &tdmb7_info); } -static void tdmb7_detach (struct dvb_i2c_bus *i2c) +static void tdmb7_detach (struct dvb_i2c_bus *i2c, void *data) { dprintk ("%s\n", __FUNCTION__); diff -Nru a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c --- a/drivers/media/dvb/frontends/at76c651.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/at76c651.c Fri Oct 17 14:43:50 2003 @@ -37,6 +37,8 @@ #include "dvb_functions.h" static int debug = 0; +static u8 at76c651_qam; +static u8 at76c651_revision; #define dprintk if (debug) printk @@ -53,7 +55,7 @@ static struct dvb_frontend_info at76c651_info = { - .name = "Atmel AT76c651(B) with DAT7021", + .name = "Atmel AT76C651(B) with DAT7021", .type = FE_QAM, .frequency_min = 48250000, .frequency_max = 863250000, @@ -126,46 +128,70 @@ } +static int at76c651_reset(struct dvb_i2c_bus *i2c) +{ + + return at76c651_writereg(i2c, 0x07, 0x01); + +} + +static int at76c651_disable_interrupts(struct dvb_i2c_bus *i2c) +{ + + return at76c651_writereg(i2c, 0x0b, 0x00); + +} + static int at76c651_set_auto_config(struct dvb_i2c_bus *i2c) { + /* + * Autoconfig + */ + at76c651_writereg(i2c, 0x06, 0x01); /* - * performance optimizations + * Performance optimizations, should be done after autoconfig */ at76c651_writereg(i2c, 0x10, 0x06); - at76c651_writereg(i2c, 0x11, 0x10); + at76c651_writereg(i2c, 0x11, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0x12 : 0x10); at76c651_writereg(i2c, 0x15, 0x28); at76c651_writereg(i2c, 0x20, 0x09); - at76c651_writereg(i2c, 0x24, 0x90); + at76c651_writereg(i2c, 0x24, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0xC0 : 0x90); + at76c651_writereg(i2c, 0x30, 0x90); + if (at76c651_qam == 5) + at76c651_writereg(i2c, 0x35, 0x2A); - return 0; + /* + * Initialize A/D-converter + */ + if (at76c651_revision == 0x11) { + at76c651_writereg(i2c, 0x2E, 0x38); + at76c651_writereg(i2c, 0x2F, 0x13); } -static int at76c651_set_bbfreq(struct dvb_i2c_bus *i2c) -{ + at76c651_disable_interrupts(i2c); - at76c651_writereg(i2c, 0x04, 0x3f); - at76c651_writereg(i2c, 0x05, 0xee); + /* + * Restart operation + */ + + at76c651_reset(i2c); return 0; } -static int at76c651_reset(struct dvb_i2c_bus *i2c) +static int at76c651_set_bbfreq(struct dvb_i2c_bus *i2c) { - return at76c651_writereg(i2c, 0x07, 0x01); - -} - -static int at76c651_disable_interrupts(struct dvb_i2c_bus *i2c) -{ + at76c651_writereg(i2c, 0x04, 0x3f); + at76c651_writereg(i2c, 0x05, 0xee); - return at76c651_writereg(i2c, 0x0b, 0x00); + return 0; } @@ -186,6 +212,10 @@ struct i2c_msg msg = { .addr = 0xc2 >> 1, .flags = 0, .buf = (u8 *) & tw, .len = sizeof (tw) }; +#ifdef __LITTLE_ENDIAN + tw = __cpu_to_be32(tw); +#endif + at76c651_switch_tuner_i2c(i2c, 1); ret = i2c->xfer(i2c, &msg, 1); @@ -236,7 +266,7 @@ u32 mantissa; if (symbolrate > 9360000) - return -1; + return -EINVAL; /* * FREF = 57800 kHz @@ -258,34 +288,31 @@ static int at76c651_set_qam(struct dvb_i2c_bus *i2c, fe_modulation_t qam) { - u8 qamsel = 0; - switch (qam) { - case QPSK: - qamsel = 0x02; + at76c651_qam = 0x02; break; case QAM_16: - qamsel = 0x04; + at76c651_qam = 0x04; break; case QAM_32: - qamsel = 0x05; + at76c651_qam = 0x05; break; case QAM_64: - qamsel = 0x06; + at76c651_qam = 0x06; break; case QAM_128: - qamsel = 0x07; + at76c651_qam = 0x07; break; case QAM_256: - qamsel = 0x08; + at76c651_qam = 0x08; break; #if 0 case QAM_512: - qamsel = 0x09; + at76c651_qam = 0x09; break; case QAM_1024: - qamsel = 0x0A; + at76c651_qam = 0x0A; break; #endif default: @@ -293,7 +320,7 @@ } - return at76c651_writereg(i2c, 0x03, qamsel); + return at76c651_writereg(i2c, 0x03, at76c651_qam); } @@ -345,7 +372,6 @@ at76c651_set_qam(i2c, QAM_64); at76c651_set_bbfreq(i2c); at76c651_set_auto_config(i2c); - at76c651_disable_interrupts(i2c); return 0; @@ -408,13 +434,12 @@ { u8 gain = ~at76c651_readreg(fe->i2c, 0x91); - *(s32 *) arg = (gain << 8) | gain; - *(s32 *) arg = 0x0FFF; + *(u16 *) arg = (gain << 8) | gain; break; } case FE_READ_SNR: - *(s32 *) arg = + *(u16 *) arg = 0xFFFF - ((at76c651_readreg(fe->i2c, 0x8F) << 8) | at76c651_readreg(fe->i2c, 0x90)); @@ -440,59 +465,44 @@ return at76c651_reset(fe->i2c); default: - return -ENOSYS; + return -ENOIOCTLCMD; } return 0; } -static int at76c651_attach(struct dvb_i2c_bus *i2c) +static int at76c651_attach(struct dvb_i2c_bus *i2c, void **data) +{ + if ( (at76c651_readreg(i2c, 0x0E) != 0x65) || + ( ( (at76c651_revision = at76c651_readreg(i2c, 0x0F)) & 0xFE) != 0x10) ) { - - if (at76c651_readreg(i2c, 0x0e) != 0x65) { - dprintk("no AT76C651(B) found\n"); - return -ENODEV; - } - if (at76c651_readreg(i2c, 0x0F) != 0x10) { - - if (at76c651_readreg(i2c, 0x0F) == 0x11) { - - dprintk("AT76C651B found\n"); - - } else { - - dprintk("no AT76C651(B) found\n"); - - return -ENODEV; - + if (at76c651_revision == 0x10) + { + dprintk("AT76C651A found\n"); + strcpy(at76c651_info.name,"Atmel AT76C651A with DAT7021"); } - - } else { - + else + { + strcpy(at76c651_info.name,"Atmel AT76C651B with DAT7021"); dprintk("AT76C651B found\n"); - } at76c651_set_defaults(i2c); - dvb_register_frontend(at76c651_ioctl, i2c, NULL, &at76c651_info); - - return 0; + return dvb_register_frontend(at76c651_ioctl, i2c, NULL, &at76c651_info); } -static void at76c651_detach(struct dvb_i2c_bus *i2c) +static void at76c651_detach(struct dvb_i2c_bus *i2c, void *data) { dvb_unregister_frontend(at76c651_ioctl, i2c); - at76c651_disable_interrupts(i2c); - } static int __init at76c651_init(void) @@ -513,11 +523,7 @@ module_init(at76c651_init); module_exit(at76c651_exit); -#ifdef MODULE MODULE_DESCRIPTION("at76c651/dat7021 dvb-c frontend driver"); MODULE_AUTHOR("Andreas Oberritter "); -#ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); -#endif MODULE_PARM(debug, "i"); -#endif diff -Nru a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c --- a/drivers/media/dvb/frontends/cx24110.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/cx24110.c Fri Oct 17 14:43:50 2003 @@ -643,7 +643,7 @@ } -static int cx24110_attach (struct dvb_i2c_bus *i2c) +static int cx24110_attach (struct dvb_i2c_bus *i2c, void **data) { u8 sig; @@ -651,13 +651,11 @@ if ( sig != 0x5a && sig != 0x69 ) return -ENODEV; - dvb_register_frontend (cx24110_ioctl, i2c, NULL, &cx24110_info); - - return 0; + return dvb_register_frontend (cx24110_ioctl, i2c, NULL, &cx24110_info); } -static void cx24110_detach (struct dvb_i2c_bus *i2c) +static void cx24110_detach (struct dvb_i2c_bus *i2c, void *data) { dvb_unregister_frontend (cx24110_ioctl, i2c); } diff -Nru a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c Fri Oct 17 14:43:50 2003 @@ -173,14 +173,13 @@ } -static int dvbdummyfe_attach (struct dvb_i2c_bus *i2c) +static int dvbdummyfe_attach (struct dvb_i2c_bus *i2c, void **data) { - dvb_register_frontend (dvbdummyfe_ioctl, i2c, NULL, frontend_info()); - return 0; + return dvb_register_frontend (dvbdummyfe_ioctl, i2c, NULL, frontend_info()); } -static void dvbdummyfe_detach (struct dvb_i2c_bus *i2c) +static void dvbdummyfe_detach (struct dvb_i2c_bus *i2c, void *data) { dvb_unregister_frontend (dvbdummyfe_ioctl, i2c); } @@ -191,14 +190,12 @@ return dvb_register_i2c_device (THIS_MODULE, dvbdummyfe_attach, dvbdummyfe_detach); - return 0; } static void __exit exit_dvbdummyfe (void) { dvb_unregister_i2c_device (dvbdummyfe_attach); - return; } diff -Nru a/drivers/media/dvb/frontends/grundig_29504-401.c b/drivers/media/dvb/frontends/grundig_29504-401.c --- a/drivers/media/dvb/frontends/grundig_29504-401.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/grundig_29504-401.c Fri Oct 17 14:43:50 2003 @@ -415,7 +415,7 @@ } -static int l64781_attach (struct dvb_i2c_bus *i2c) +static int l64781_attach (struct dvb_i2c_bus *i2c, void **data) { u8 reg0x3e; u8 b0 [] = { 0x1a }; @@ -465,9 +465,8 @@ goto bailout; } - dvb_register_frontend (grundig_29504_401_ioctl, i2c, NULL, + return dvb_register_frontend (grundig_29504_401_ioctl, i2c, NULL, &grundig_29504_401_info); - return 0; bailout: l64781_writereg (i2c, 0x3e, reg0x3e); /* restore reg 0x3e */ @@ -475,7 +474,8 @@ } -static void l64781_detach (struct dvb_i2c_bus *i2c) + +static void l64781_detach (struct dvb_i2c_bus *i2c, void *data) { dvb_unregister_frontend (grundig_29504_401_ioctl, i2c); } diff -Nru a/drivers/media/dvb/frontends/grundig_29504-491.c b/drivers/media/dvb/frontends/grundig_29504-491.c --- a/drivers/media/dvb/frontends/grundig_29504-491.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/grundig_29504-491.c Fri Oct 17 14:43:50 2003 @@ -433,19 +433,17 @@ } -static int tda8083_attach (struct dvb_i2c_bus *i2c) +static int tda8083_attach (struct dvb_i2c_bus *i2c, void **data) { if ((tda8083_readreg (i2c, 0x00)) != 0x05) return -ENODEV; - dvb_register_frontend (grundig_29504_491_ioctl, i2c, NULL, + return dvb_register_frontend (grundig_29504_491_ioctl, i2c, NULL, &grundig_29504_491_info); - - return 0; } -static void tda8083_detach (struct dvb_i2c_bus *i2c) +static void tda8083_detach (struct dvb_i2c_bus *i2c, void *data) { dvb_unregister_frontend (grundig_29504_491_ioctl, i2c); } diff -Nru a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c --- a/drivers/media/dvb/frontends/mt312.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/mt312.c Fri Oct 17 14:43:50 2003 @@ -714,7 +714,7 @@ return 0; } -static int mt312_attach(struct dvb_i2c_bus *i2c) +static int mt312_attach(struct dvb_i2c_bus *i2c, void **data) { int ret; u8 id; @@ -734,7 +734,7 @@ return 0; } -static void mt312_detach(struct dvb_i2c_bus *i2c) +static void mt312_detach(struct dvb_i2c_bus *i2c, void *data) { dvb_unregister_frontend(mt312_ioctl, i2c); diff -Nru a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c --- a/drivers/media/dvb/frontends/nxt6000.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/nxt6000.c Fri Oct 17 14:43:50 2003 @@ -829,7 +829,7 @@ static u8 demod_addr_tbl[] = {0x14, 0x18, 0x24, 0x28}; -static int nxt6000_attach(struct dvb_i2c_bus *i2c) +static int nxt6000_attach(struct dvb_i2c_bus *i2c, void **data) { u8 addr_nr; @@ -881,13 +881,14 @@ dvb_register_frontend(nxt6000_ioctl, i2c, (void *)(*((u32 *)&nxt)), &nxt6000_info); + fe_count++; } return (fe_count > 0) ? 0 : -ENODEV; } -static void nxt6000_detach(struct dvb_i2c_bus *i2c) +static void nxt6000_detach(struct dvb_i2c_bus *i2c, void *data) { dprintk("nxt6000: detach\n"); diff -Nru a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c --- a/drivers/media/dvb/frontends/sp887x.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/sp887x.c Fri Oct 17 14:43:50 2003 @@ -561,7 +561,7 @@ static -int sp887x_attach (struct dvb_i2c_bus *i2c) +int sp887x_attach (struct dvb_i2c_bus *i2c, void **data) { struct i2c_msg msg = { addr: 0x70, flags: 0, buf: NULL, len: 0 }; @@ -570,14 +570,12 @@ if (i2c->xfer (i2c, &msg, 1) != 1) return -ENODEV; - dvb_register_frontend (sp887x_ioctl, i2c, NULL, &sp887x_info); - - return 0; + return dvb_register_frontend (sp887x_ioctl, i2c, NULL, &sp887x_info); } static -void sp887x_detach (struct dvb_i2c_bus *i2c) +void sp887x_detach (struct dvb_i2c_bus *i2c, void *data) { dprintk ("%s\n", __FUNCTION__); dvb_unregister_frontend (sp887x_ioctl, i2c); diff -Nru a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c --- a/drivers/media/dvb/frontends/stv0299.c Fri Oct 17 14:43:51 2003 +++ b/drivers/media/dvb/frontends/stv0299.c Fri Oct 17 14:43:51 2003 @@ -910,7 +910,7 @@ } -static int uni0299_attach (struct dvb_i2c_bus *i2c) +static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data) { long tuner_type; u8 id; @@ -928,17 +928,14 @@ if ((tuner_type = probe_tuner(i2c)) < 0) return -ENODEV; - dvb_register_frontend (uni0299_ioctl, i2c, (void*) tuner_type, + return dvb_register_frontend (uni0299_ioctl, i2c, (void*) tuner_type, &uni0299_info); - - return 0; } -static void uni0299_detach (struct dvb_i2c_bus *i2c) +static void uni0299_detach (struct dvb_i2c_bus *i2c, void *data) { dprintk ("%s\n", __FUNCTION__); - dvb_unregister_frontend (uni0299_ioctl, i2c); } diff -Nru a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c --- a/drivers/media/dvb/frontends/tda1004x.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/tda1004x.c Fri Oct 17 14:43:50 2003 @@ -1055,7 +1055,7 @@ } -static int tda1004x_attach(struct dvb_i2c_bus *i2c) +static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data) { int tda1004x_address = -1; int tuner_address = -1; @@ -1113,17 +1113,15 @@ // register switch(tda_state.tda1004x_address) { case TDA10045H_ADDRESS: - dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10045h_info); - break; + return dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10045h_info); + default: + return -ENODEV; } - - // success - return 0; } static -void tda1004x_detach(struct dvb_i2c_bus *i2c) +void tda1004x_detach(struct dvb_i2c_bus *i2c, void *data) { dprintk("%s\n", __FUNCTION__); diff -Nru a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c --- a/drivers/media/dvb/frontends/ves1820.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/frontends/ves1820.c Fri Oct 17 14:43:50 2003 @@ -507,9 +507,9 @@ } -static int ves1820_attach (struct dvb_i2c_bus *i2c) +static int ves1820_attach (struct dvb_i2c_bus *i2c, void **data) { - void *data = NULL; + void *priv = NULL; long demod_addr; long tuner_type; @@ -522,21 +522,19 @@ if ((i2c->adapter->num < MAX_UNITS) && pwm[i2c->adapter->num] != -1) { printk("DVB: VES1820(%d): pwm=0x%02x (user specified)\n", i2c->adapter->num, pwm[i2c->adapter->num]); - SET_PWM(data, pwm[i2c->adapter->num]); + SET_PWM(priv, pwm[i2c->adapter->num]); } else - SET_PWM(data, read_pwm(i2c)); - SET_REG0(data, ves1820_inittab[0]); - SET_TUNER(data, tuner_type); - SET_DEMOD_ADDR(data, demod_addr); + SET_PWM(priv, read_pwm(i2c)); + SET_REG0(priv, ves1820_inittab[0]); + SET_TUNER(priv, tuner_type); + SET_DEMOD_ADDR(priv, demod_addr); - dvb_register_frontend (ves1820_ioctl, i2c, data, &ves1820_info); - - return 0; + return dvb_register_frontend (ves1820_ioctl, i2c, priv, &ves1820_info); } -static void ves1820_detach (struct dvb_i2c_bus *i2c) +static void ves1820_detach (struct dvb_i2c_bus *i2c, void *data) { dvb_unregister_frontend (ves1820_ioctl, i2c); } diff -Nru a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/frontends/ves1x93.c Fri Oct 17 14:43:50 2003 @@ -0,0 +1,619 @@ +/* + Driver for VES1893 and VES1993 QPSK Frontends + + Copyright (C) 1999 Convergence Integrated Media GmbH + Copyright (C) 2001 Ronny Strutz <3des@tuxbox.org> + Copyright (C) 2002 Dennis Noermann + Copyright (C) 2002-2003 Andreas Oberritter + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" + +static int debug = 0; +#define dprintk if (debug) printk + +static int board_type = 0; +#define BOARD_SIEMENS_PCI 0 +#define BOARD_NOKIA_DBOX2 1 +#define BOARD_SAGEM_DBOX2 2 + +static int demod_type = 0; +#define DEMOD_VES1893 0 +#define DEMOD_VES1993 1 + +static struct dvb_frontend_info ves1x93_info = { + .name = "VES1x93", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 250, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, +/* .symbol_rate_tolerance = ???,*/ + .notifier_delay = 50, /* 1/20 s */ + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK +}; + + +/** + * nokia dbox2 (ves1893) and sagem dbox2 (ves1993) + * need bit AGCR[PWMS] set to 1 + */ + +static u8 init_1893_tab [] = { + 0x01, 0xa4, 0x35, 0x81, 0x2a, 0x0d, 0x55, 0xc4, + 0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7f, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xdc, 0x00, + 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x7f, 0x00 +}; + + +static u8 init_1993_tab [] = { + 0x00, 0x9c, 0x35, 0x80, 0x6a, 0x09, 0x72, 0x8c, + 0x09, 0x6b, 0x00, 0x00, 0x4c, 0x08, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x40, 0x21, 0xb0, 0x00, 0x00, 0x00, 0x10, + 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x0e, 0x80, 0x00 +}; + + +static u8 * init_1x93_tab; + + +static u8 init_1893_wtab[] = +{ + 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0, + 0,1,0,0,0,0,0,0, 1,0,1,1,0,0,0,1, + 1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0, + 1,1,1,0,1,1 +}; + + +static u8 init_1993_wtab[] = +{ + 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0, + 0,1,0,0,0,0,0,0, 1,1,1,1,0,0,0,1, + 1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0, + 1,1,1,0,1,1,1,1, 1,1,1,1,1 +}; + + +static int ves1x93_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +{ + u8 buf [] = { 0x00, reg, data }; + struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 3 }; + int err; + + if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { + dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); + return -EREMOTEIO; + } + + return 0; +} + + +static u8 ves1x93_readreg (struct dvb_i2c_bus *i2c, u8 reg) +{ + int ret; + u8 b0 [] = { 0x00, reg }; + u8 b1 [] = { 0 }; + struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b0, .len = 2 }, + { .addr = 0x08, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + + ret = i2c->xfer (i2c, msg, 2); + + if (ret != 2) + dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + + return b1[0]; +} + + +static int tuner_write (struct dvb_i2c_bus *i2c, u8 *data, u8 len) +{ + int ret; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = len }; + + ves1x93_writereg(i2c, 0x00, 0x11); + ret = i2c->xfer (i2c, &msg, 1); + ves1x93_writereg(i2c, 0x00, 0x01); + + if (ret != 1) + printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); + + return (ret != 1) ? -1 : 0; +} + + + +/** + * set up the downconverter frequency divisor for a + * reference clock comparision frequency of 125 kHz. + */ +static int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) +{ + u32 div = (freq + 479500) / 125; + u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x95, (pwr << 5) | 0x30 }; + + return tuner_write (i2c, buf, sizeof(buf)); +} + + +static int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +{ + int ret; + u8 buf [2]; + + freq /= 1000; + + buf[0] = (freq >> 8) & 0x7F; + buf[1] = freq & 0xFF; + + ret = tuner_write(i2c, buf, sizeof(buf)); + + return ret; +} + + +static int tuner_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) +{ + if ((demod_type == DEMOD_VES1893) && (board_type == BOARD_SIEMENS_PCI)) + return sp5659_set_tv_freq (i2c, freq, pwr); + else if (demod_type == DEMOD_VES1993) + return tsa5059_set_tv_freq (i2c, freq); + + return -EINVAL; +} + + +static int ves1x93_init (struct dvb_i2c_bus *i2c) +{ + int i; + int size; + u8 *init_1x93_wtab; + + dprintk("%s: init chip\n", __FUNCTION__); + + switch (demod_type) { + case DEMOD_VES1893: + init_1x93_tab = init_1893_tab; + init_1x93_wtab = init_1893_wtab; + size = sizeof(init_1893_tab); + if (board_type == BOARD_NOKIA_DBOX2) + init_1x93_tab[0x05] |= 0x20; /* invert PWM */ + break; + + case DEMOD_VES1993: + init_1x93_tab = init_1993_tab; + init_1x93_wtab = init_1993_wtab; + size = sizeof(init_1993_tab); + if (board_type == BOARD_SAGEM_DBOX2) + init_1x93_tab[0x05] |= 0x20; /* invert PWM */ + break; + + default: + return -EINVAL; + } + + for (i = 0; i < size; i++) + if (init_1x93_wtab[i]) + ves1x93_writereg (i2c, i, init_1x93_tab[i]); + + if (demod_type == DEMOD_VES1993) { + if (board_type == BOARD_NOKIA_DBOX2) + tuner_write(i2c, "\x06\x5c\x83\x60", 4); + else if (board_type == BOARD_SAGEM_DBOX2) + tuner_write(i2c, "\x25\x70\x92\x40", 4); + } + + return 0; +} + + +static int ves1x93_clr_bit (struct dvb_i2c_bus *i2c) +{ + ves1x93_writereg (i2c, 0, init_1x93_tab[0] & 0xfe); + ves1x93_writereg (i2c, 0, init_1x93_tab[0]); + ves1x93_writereg (i2c, 3, 0x00); + return ves1x93_writereg (i2c, 3, init_1x93_tab[3]); +} + + +static int ves1x93_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion_t inversion) +{ + u8 val; + + /* + * inversion on/off are interchanged because i and q seem to + * be swapped on the hardware + */ + + switch (inversion) { + case INVERSION_OFF: + val = 0xc0; + break; + case INVERSION_ON: + val = 0x80; + break; + case INVERSION_AUTO: + val = 0x00; + break; + default: + return -EINVAL; + } + + /* needs to be saved for FE_GET_FRONTEND */ + init_1x93_tab[0x0c] = (init_1x93_tab[0x0c] & 0x3f) | val; + + return ves1x93_writereg (i2c, 0x0c, init_1x93_tab[0x0c]); +} + + +static int ves1x93_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) +{ + if (fec == FEC_AUTO) + return ves1x93_writereg (i2c, 0x0d, 0x08); + else if (fec < FEC_1_2 || fec > FEC_8_9) + return -EINVAL; + else + return ves1x93_writereg (i2c, 0x0d, fec - FEC_1_2); +} + + +static fe_code_rate_t ves1x93_get_fec (struct dvb_i2c_bus *i2c) +{ + return FEC_1_2 + ((ves1x93_readreg (i2c, 0x0d) >> 4) & 0x7); +} + + +static int ves1x93_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +{ + u32 BDR; + u32 ratio; + u8 ADCONF, FCONF, FNR; + u32 BDRI; + u32 tmp; + u32 XIN, FIN; + + dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate); + + switch (board_type) { + case BOARD_SIEMENS_PCI: + XIN = 90100000UL; + break; + case BOARD_NOKIA_DBOX2: + if (demod_type == DEMOD_VES1893) + XIN = 91000000UL; + else if (demod_type == DEMOD_VES1993) + XIN = 96000000UL; + else + return -EINVAL; + break; + case BOARD_SAGEM_DBOX2: + XIN = 92160000UL; + break; + default: + return -EINVAL; + } + + if (srate > XIN/2) + srate = XIN/2; + + if (srate < 500000) + srate = 500000; + +#define MUL (1UL<<26) + + FIN = (XIN + 6000) >> 4; + + tmp = srate << 6; + ratio = tmp / FIN; + + tmp = (tmp % FIN) << 8; + ratio = (ratio << 8) + tmp / FIN; + + tmp = (tmp % FIN) << 8; + ratio = (ratio << 8) + tmp / FIN; + + FNR = 0xff; + + if (ratio < MUL/3) FNR = 0; + if (ratio < (MUL*11)/50) FNR = 1; + if (ratio < MUL/6) FNR = 2; + if (ratio < MUL/9) FNR = 3; + if (ratio < MUL/12) FNR = 4; + if (ratio < (MUL*11)/200) FNR = 5; + if (ratio < MUL/24) FNR = 6; + if (ratio < (MUL*27)/1000) FNR = 7; + if (ratio < MUL/48) FNR = 8; + if (ratio < (MUL*137)/10000) FNR = 9; + + if (FNR == 0xff) { + ADCONF = 0x89; + FCONF = 0x80; + FNR = 0; + } else { + ADCONF = 0x81; + FCONF = 0x88 | (FNR >> 1) | ((FNR & 0x01) << 5); + /*FCONF = 0x80 | ((FNR & 0x01) << 5) | (((FNR > 1) & 0x03) << 3) | ((FNR >> 1) & 0x07);*/ + } + + BDR = (( (ratio << (FNR >> 1)) >> 4) + 1) >> 1; + BDRI = ( ((FIN << 8) / ((srate << (FNR >> 1)) >> 2)) + 1) >> 1; + + dprintk("FNR= %d\n", FNR); + dprintk("ratio= %08x\n", (unsigned int) ratio); + dprintk("BDR= %08x\n", (unsigned int) BDR); + dprintk("BDRI= %02x\n", (unsigned int) BDRI); + + if (BDRI > 0xff) + BDRI = 0xff; + + ves1x93_writereg (i2c, 0x06, 0xff & BDR); + ves1x93_writereg (i2c, 0x07, 0xff & (BDR >> 8)); + ves1x93_writereg (i2c, 0x08, 0x0f & (BDR >> 16)); + + ves1x93_writereg (i2c, 0x09, BDRI); + ves1x93_writereg (i2c, 0x20, ADCONF); + ves1x93_writereg (i2c, 0x21, FCONF); + + if (srate < 6000000) + ves1x93_writereg (i2c, 0x05, init_1x93_tab[0x05] | 0x80); + else + ves1x93_writereg (i2c, 0x05, init_1x93_tab[0x05] & 0x7f); + + ves1x93_writereg (i2c, 0x00, 0x00); + ves1x93_writereg (i2c, 0x00, 0x01); + + /* ves1993 hates this, will lose lock */ + if (demod_type != DEMOD_VES1993) + ves1x93_clr_bit (i2c); + + return 0; +} + + +static int ves1x93_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) +{ + switch (voltage) { + case SEC_VOLTAGE_13: + return ves1x93_writereg (i2c, 0x1f, 0x20); + case SEC_VOLTAGE_18: + return ves1x93_writereg (i2c, 0x1f, 0x30); + case SEC_VOLTAGE_OFF: + return ves1x93_writereg (i2c, 0x1f, 0x00); + default: + return -EINVAL; + } +} + + +static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct dvb_i2c_bus *i2c = fe->i2c; + + switch (cmd) { + case FE_GET_INFO: + memcpy (arg, &ves1x93_info, sizeof(struct dvb_frontend_info)); + break; + + case FE_READ_STATUS: + { + fe_status_t *status = arg; + u8 sync = ves1x93_readreg (i2c, 0x0e); + + *status = 0; + + if (sync & 1) + *status |= FE_HAS_SIGNAL; + + if (sync & 2) + *status |= FE_HAS_CARRIER; + + if (sync & 4) + *status |= FE_HAS_VITERBI; + + if (sync & 8) + *status |= FE_HAS_SYNC; + + if ((sync & 0x1f) == 0x1f) + *status |= FE_HAS_LOCK; + + break; + } + + case FE_READ_BER: + { + u32 *ber = (u32 *) arg; + + *ber = ves1x93_readreg (i2c, 0x15); + *ber |= (ves1x93_readreg (i2c, 0x16) << 8); + *ber |= ((ves1x93_readreg (i2c, 0x17) & 0x0F) << 16); + *ber *= 10; + break; + } + + case FE_READ_SIGNAL_STRENGTH: + { + u8 signal = ~ves1x93_readreg (i2c, 0x0b); + *((u16*) arg) = (signal << 8) | signal; + break; + } + + case FE_READ_SNR: + { + u8 snr = ~ves1x93_readreg (i2c, 0x1c); + *(u16*) arg = (snr << 8) | snr; + break; + } + + case FE_READ_UNCORRECTED_BLOCKS: + { + *(u32*) arg = ves1x93_readreg (i2c, 0x18) & 0x7f; + + if (*(u32*) arg == 0x7f) + *(u32*) arg = 0xffffffff; /* counter overflow... */ + + ves1x93_writereg (i2c, 0x18, 0x00); /* reset the counter */ + ves1x93_writereg (i2c, 0x18, 0x80); /* dto. */ + break; + } + + case FE_SET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + + tuner_set_tv_freq (i2c, p->frequency, 0); + ves1x93_set_inversion (i2c, p->inversion); + ves1x93_set_fec (i2c, p->u.qpsk.fec_inner); + ves1x93_set_symbolrate (i2c, p->u.qpsk.symbol_rate); + break; + } + + case FE_GET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + int afc; + + afc = ((int)((char)(ves1x93_readreg (i2c, 0x0a) << 1)))/2; + afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16; + + p->frequency -= afc; + + /* + * inversion indicator is only valid + * if auto inversion was used + */ + if (!(init_1x93_tab[0x0c] & 0x80)) + p->inversion = (ves1x93_readreg (i2c, 0x0f) & 2) ? + INVERSION_OFF : INVERSION_ON; + p->u.qpsk.fec_inner = ves1x93_get_fec (i2c); + /* XXX FIXME: timing offset !! */ + break; + } + + case FE_SLEEP: + if (board_type == BOARD_SIEMENS_PCI) + ves1x93_writereg (i2c, 0x1f, 0x00); /* LNB power off */ + return ves1x93_writereg (i2c, 0x00, 0x08); + + case FE_INIT: + return ves1x93_init (i2c); + + case FE_RESET: + return ves1x93_clr_bit (i2c); + + case FE_SET_TONE: + return -EOPNOTSUPP; /* the ves1893 can generate the 22k */ + /* let's implement this when we have */ + /* a box that uses the 22K_0 pin... */ + + case FE_SET_VOLTAGE: + return ves1x93_set_voltage (i2c, (fe_sec_voltage_t) arg); + + default: + return -EOPNOTSUPP; + }; + + return 0; +} + + +static int ves1x93_attach (struct dvb_i2c_bus *i2c, void **data) +{ + u8 identity = ves1x93_readreg(i2c, 0x1e); + + switch (identity) { + case 0xdc: /* VES1893A rev1 */ + case 0xdd: /* VES1893A rev2 */ + demod_type = DEMOD_VES1893; + ves1x93_info.name[4] = '8'; + break; + case 0xde: /* VES1993 */ + demod_type = DEMOD_VES1993; + ves1x93_info.name[4] = '9'; + break; + default: + dprintk("VES1x93 not found (identity %02x)\n", identity); + return -ENODEV; + } + + return dvb_register_frontend (ves1x93_ioctl, i2c, NULL, &ves1x93_info); +} + + +static void ves1x93_detach (struct dvb_i2c_bus *i2c, void *data) +{ + dvb_unregister_frontend (ves1x93_ioctl, i2c); +} + + +static int __init init_ves1x93 (void) +{ + switch (board_type) { + case BOARD_NOKIA_DBOX2: + dprintk("%s: NOKIA_DBOX2\n", __FILE__); + break; + case BOARD_SAGEM_DBOX2: + dprintk("%s: SAGEM_DBOX2\n", __FILE__); + break; + case BOARD_SIEMENS_PCI: + dprintk("%s: SIEMENS_PCI\n", __FILE__); + break; + default: + return -EIO; + } + + return dvb_register_i2c_device (THIS_MODULE, ves1x93_attach, ves1x93_detach); +} + + +static void __exit exit_ves1x93 (void) +{ + dvb_unregister_i2c_device (ves1x93_attach); +} + + +module_init(init_ves1x93); +module_exit(exit_ves1x93); + + +MODULE_DESCRIPTION("VES1x93 DVB-S Frontend"); +MODULE_AUTHOR("Ralph Metzler"); +MODULE_LICENSE("GPL"); +MODULE_PARM(debug,"i"); +MODULE_PARM(board_type,"i"); + diff -Nru a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c --- a/drivers/media/dvb/ttpci/av7110.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/ttpci/av7110.c Fri Oct 17 14:43:50 2003 @@ -55,8 +55,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -2704,9 +2706,9 @@ buf[1] = div & 0xff; buf[2] = 0x8e; - if (freq < 16*168.25 ) + if (freq < (u32) (16*168.25) ) config = 0xa0; - else if (freq < 16*447.25) + else if (freq < (u32) (16*447.25)) config = 0x90; else config = 0x30; @@ -4520,28 +4522,6 @@ DEB_EE(("dev: %p, av7110: %p\n",dev,av7110)); - /* special case DVB-C: these cards have an analog tuner - plus need some special handling, so we have separate - saa7146_ext_vv data for these... */ - if (dev->pci->subsystem_vendor == 0x110a) { - ret = saa7146_vv_init(dev, &av7110_vv_data_c); - } else { - ret = saa7146_vv_init(dev, &av7110_vv_data_st); - } - - if ( 0 != ret) { - ERR(("cannot init capture device. skipping.\n")); - kfree(av7110); - return -1; - } - - if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) { - ERR(("cannot register capture device. skipping.\n")); - saa7146_vv_release(dev); - kfree(av7110); - return -1; - } - av7110->dev=(struct saa7146_dev *)dev; dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name); @@ -4555,8 +4535,6 @@ av7110->dvb_adapter, 0); if (!av7110->i2c_bus) { - saa7146_unregister_device(&av7110->v4l_dev, dev); - saa7146_vv_release(dev); dvb_unregister_adapter (av7110->dvb_adapter); kfree(av7110); return -ENOMEM; @@ -4727,7 +4705,7 @@ memcpy(standard,dvb_standard,sizeof(struct saa7146_standard)*2); /* set dd1 stream a & b */ saa7146_write(dev, DD1_STREAM_B, 0x00000000); - saa7146_write(dev, DD1_INIT, 0x0200700); + saa7146_write(dev, DD1_INIT, 0x02000700); saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); } else if (dev->pci->subsystem_vendor == 0x110a) { @@ -4754,17 +4732,52 @@ av7110_setup_irc_config (av7110, 0); av7110_register(av7110); + /* special case DVB-C: these cards have an analog tuner + plus need some special handling, so we have separate + saa7146_ext_vv data for these... */ + if (0 != av7110->has_analog_tuner) { + ret = saa7146_vv_init(dev, &av7110_vv_data_c); + } else { + ret = saa7146_vv_init(dev, &av7110_vv_data_st); + } + + if ( 0 != ret) { + ERR(("cannot init capture device. skipping.\n")); + ret = -ENODEV; + goto err; + } + + if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) { + ERR(("cannot register capture device. skipping.\n")); + ret = -ENODEV; + goto video_err; + } + + if (0 != av7110->has_analog_tuner) { + if( 0 != saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) { + ERR(("cannot register vbi v4l2 device. skipping.\n")); + } + /* we use this to remember that this dvb-c card cannot do vbi */ + av7110->has_analog_tuner = 2; + } + printk(KERN_INFO "av7110: found av7110-%d.\n",av7110_num); av7110_num++; return 0; +video_err: + saa7146_vv_release(dev); + err: - if (av7110 ) + if (NULL != av7110 ) { kfree(av7110); - - /* FIXME: error handling is pretty bogus: memory does not get freed...*/ - saa7146_unregister_device(&av7110->v4l_dev, dev); - saa7146_vv_release(dev); + } + if (NULL != av7110->debi_virt) { + pci_free_consistent(dev->pci, 8192, av7110->debi_virt, av7110->debi_bus); + } + if (NULL != av7110->iobuf) { + vfree(av7110->iobuf); + } dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id); @@ -4780,6 +4793,9 @@ DEB_EE(("av7110: %p\n",av7110)); saa7146_unregister_device(&av7110->v4l_dev, saa); + if (2 == av7110->has_analog_tuner) { + saa7146_unregister_device(&av7110->vbi_dev, saa); + } av7110->arm_rmmod=1; wake_up_interruptible(&av7110->arm_wait); @@ -4948,8 +4964,8 @@ static struct saa7146_ext_vv av7110_vv_data_c = { .inputs = 1, .audios = 1, - .capabilities = V4L2_CAP_TUNER, - .flags = 0, + .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, + .flags = SAA7146_USE_PORT_B_FOR_VBI, .stds = &standard[0], .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), diff -Nru a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h --- a/drivers/media/dvb/ttpci/av7110.h Fri Oct 17 14:43:50 2003 +++ b/drivers/media/dvb/ttpci/av7110.h Fri Oct 17 14:43:50 2003 @@ -399,7 +399,9 @@ struct dvb_device dvb_dev; struct dvb_net dvb_net; + struct video_device v4l_dev; + struct video_device vbi_dev; struct saa7146_dev *dev; diff -Nru a/drivers/media/dvb/ttusb-dec/dec2000_frontend.c b/drivers/media/dvb/ttusb-dec/dec2000_frontend.c --- a/drivers/media/dvb/ttusb-dec/dec2000_frontend.c Fri Oct 17 14:43:51 2003 +++ b/drivers/media/dvb/ttusb-dec/dec2000_frontend.c Fri Oct 17 14:43:51 2003 @@ -140,17 +140,15 @@ return 0; } -static int dec2000_frontend_attach(struct dvb_i2c_bus *i2c) +static int dec2000_frontend_attach(struct dvb_i2c_bus *i2c, void **data) { dprintk("%s\n", __FUNCTION__); - dvb_register_frontend(dec2000_frontend_ioctl, i2c, NULL, + return dvb_register_frontend(dec2000_frontend_ioctl, i2c, NULL, &dec2000_frontend_info); - - return 0; } -static void dec2000_frontend_detach(struct dvb_i2c_bus *i2c) +static void dec2000_frontend_detach(struct dvb_i2c_bus *i2c, void *data) { dprintk("%s\n", __FUNCTION__); diff -Nru a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c --- a/drivers/media/video/saa7134/saa7134-core.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/video/saa7134/saa7134-core.c Fri Oct 17 14:43:50 2003 @@ -95,7 +95,7 @@ unsigned int saa7134_devcount; #define dprintk(fmt, arg...) if (core_debug) \ - printk(KERN_DEBUG "%s/core: " fmt, dev->name, ## arg) + printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) /* ------------------------------------------------------------------ */ /* debug help functions */ diff -Nru a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c --- a/drivers/media/video/zoran_card.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/video/zoran_card.c Fri Oct 17 14:43:50 2003 @@ -47,6 +47,8 @@ #include #include +#include + #include "videocodec.h" #include "zoran.h" #include "zoran_card.h" diff -Nru a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c --- a/drivers/media/video/zoran_device.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/video/zoran_device.c Fri Oct 17 14:43:50 2003 @@ -46,6 +46,8 @@ #include #include +#include + #include "videocodec.h" #include "zoran.h" #include "zoran_device.h" diff -Nru a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c --- a/drivers/media/video/zoran_driver.c Fri Oct 17 14:43:50 2003 +++ b/drivers/media/video/zoran_driver.c Fri Oct 17 14:43:50 2003 @@ -73,6 +73,7 @@ #include #include "videocodec.h" +#include #include #include diff -Nru a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c --- a/drivers/mtd/devices/lart.c Fri Oct 17 14:43:50 2003 +++ b/drivers/mtd/devices/lart.c Fri Oct 17 14:43:50 2003 @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #ifdef HAVE_PARTITIONS diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c --- a/drivers/net/8139too.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/8139too.c Fri Oct 17 14:43:50 2003 @@ -248,6 +248,8 @@ {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, #ifdef CONFIG_SH_SECUREEDGE5410 /* Bogus 8139 silicon reports 8129 without external PROM :-( */ diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig --- a/drivers/net/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/net/Kconfig Fri Oct 17 14:43:50 2003 @@ -1616,7 +1616,7 @@ config TLAN tristate "TI ThunderLAN support" - depends on NET_PCI && (PCI || EISA) + depends on NET_PCI && (PCI || EISA) && !64BIT ---help--- If you have a PCI Ethernet network card based on the ThunderLAN chip which is supported by this driver, say Y and read the @@ -2412,7 +2412,7 @@ config RCPCI tristate "Red Creek Hardware VPN (EXPERIMENTAL)" - depends on NETDEVICES && EXPERIMENTAL && PCI + depends on NETDEVICES && EXPERIMENTAL && PCI && !64BIT help This is a driver for hardware which provides a Virtual Private Network (VPN). Say Y if you have it. diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c --- a/drivers/net/Space.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/Space.c Fri Oct 17 14:43:50 2003 @@ -433,17 +433,15 @@ #ifdef CONFIG_SBNI for (num = 0; num < 8; ++num) - if (sbni_probe(num)) - break; + sbni_probe(num); #endif #ifdef CONFIG_TR for (num = 0; num < 8; ++num) - if (trif_probe(num)) - break; + trif_probe(num); #endif for (num = 0; num < 8; ++num) - if (ethif_probe(num)) - break; + ethif_probe(num); + #ifdef CONFIG_COPS cops_probe(0); cops_probe(1); diff -Nru a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c --- a/drivers/net/amd8111e.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/amd8111e.c Fri Oct 17 14:43:50 2003 @@ -1698,7 +1698,7 @@ /* Restart ipg timer */ if(lp->options & OPTION_DYN_IPG_ENABLE) mod_timer(&lp->ipg_data.ipg_timer, - jiffies + (IPG_CONVERGE_TIME * HZ)); + jiffies + IPG_CONVERGE_JIFFIES); spin_unlock_irq(&lp->lock); return 0; @@ -1772,7 +1772,7 @@ writew((u32)tmp_ipg, mmio + IPG); writew((u32)(tmp_ipg - IFS1_DELTA), mmio + IFS1); } - mod_timer(&lp->ipg_data.ipg_timer, jiffies + (IPG_CONVERGE_TIME * HZ)); + mod_timer(&lp->ipg_data.ipg_timer, jiffies + IPG_CONVERGE_JIFFIES); return; } @@ -1909,7 +1909,7 @@ lp->ipg_data.ipg_timer.data = (unsigned long) dev; lp->ipg_data.ipg_timer.function = (void *)&amd8111e_config_ipg; lp->ipg_data.ipg_timer.expires = jiffies + - IPG_CONVERGE_TIME * HZ; + IPG_CONVERGE_JIFFIES; lp->ipg_data.ipg = DEFAULT_IPG; lp->ipg_data.ipg_state = CSTATE; }; diff -Nru a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h --- a/drivers/net/amd8111e.h Fri Oct 17 14:43:50 2003 +++ b/drivers/net/amd8111e.h Fri Oct 17 14:43:50 2003 @@ -606,7 +606,7 @@ /* ipg parameters */ #define DEFAULT_IPG 0x60 #define IFS1_DELTA 36 -#define IPG_CONVERGE_TIME 0.5 +#define IPG_CONVERGE_JIFFIES (HZ / 2) #define IPG_STABLE_TIME 5 #define MIN_IPG 96 #define MAX_IPG 255 diff -Nru a/drivers/net/b44.c b/drivers/net/b44.c --- a/drivers/net/b44.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/b44.c Fri Oct 17 14:43:50 2003 @@ -25,8 +25,8 @@ #define DRV_MODULE_NAME "b44" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "0.9" -#define DRV_MODULE_RELDATE "Jul 14, 2003" +#define DRV_MODULE_VERSION "0.91" +#define DRV_MODULE_RELDATE "Oct 3, 2003" #define B44_DEF_MSG_ENABLE \ (NETIF_MSG_DRV | \ @@ -80,15 +80,6 @@ static int b44_debug = -1; /* -1 == use B44_DEF_MSG_ENABLE as value */ -#ifndef PCI_DEVICE_ID_BCM4401 -#define PCI_DEVICE_ID_BCM4401 0x4401 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#define IRQ_RETVAL(x) -#define irqreturn_t void -#endif - static struct pci_device_id b44_pci_tbl[] = { { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, @@ -869,6 +860,8 @@ b44_init_hw(bp); spin_unlock_irq(&bp->lock); + + b44_enable_ints(bp); netif_wake_queue(dev); } diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c --- a/drivers/net/defxx.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/defxx.c Fri Oct 17 14:43:50 2003 @@ -2664,8 +2664,8 @@ static void my_skb_align(struct sk_buff *skb, int n) { - u32 x=(u32)skb->data; /* We only want the low bits .. */ - u32 v; + unsigned long x=(unsigned long)skb->data; + unsigned long v; v=(x+n-1)&~(n-1); /* Where we want to be */ diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/e1000/e1000_main.c Fri Oct 17 14:43:50 2003 @@ -30,7 +30,7 @@ /* Change Log * - * 5.2.18 9/13/03 + * 5.2.20 9/30/03 * o Bug fix: SERDES devices might be connected to a back-plane * switch that doesn't support auto-neg, so add the capability * to force 1000/Full. @@ -39,6 +39,9 @@ * Jumbo Frames or with the reduced FIFO in 82547. * o Better propagation of error codes. [Janice Girouard * (janiceg@us.ibm.com)]. + * o Bug fix: hang under heavy Tx stress when running out of Tx + * descriptors; wasn't clearing context descriptor when backing + * out of send because of no-resource condition. * * 5.2.16 8/8/03 * o Added support for new controllers: 82545GM, 82546GB, 82541/7_B1 @@ -61,7 +64,7 @@ char e1000_driver_name[] = "e1000"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -char e1000_driver_version[] = "5.2.19-k1"; +char e1000_driver_version[] = "5.2.20-k1"; char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table @@ -1545,6 +1548,7 @@ unsigned int first) { struct e1000_desc_ring *tx_ring = &adapter->tx_ring; + struct e1000_tx_desc *tx_desc; struct e1000_buffer *buffer_info; unsigned int len = skb->len, max_per_txd = E1000_MAX_DATA_PER_TXD; unsigned int offset = 0, size, count = 0, i; @@ -1640,17 +1644,29 @@ } } - if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) { + if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2) { /* There aren't enough descriptors available to queue up - * this send, so undo the mapping and abort the send. - * We could have done the check before we mapped the skb, - * but because of all the workarounds (above), it's too - * difficult to predict how many we're going to need.*/ - i = first; + * this send (need: count + 1 context desc + 1 desc gap + * to keep tail from touching head), so undo the mapping + * and abort the send. We could have done the check before + * we mapped the skb, but because of all the workarounds + * (above), it's too difficult to predict how many we're + * going to need.*/ + i = adapter->tx_ring.next_to_use; + + if(i == first) { + /* Cleanup after e1000_tx_[csum|tso] scribbling + * on descriptors. */ + tx_desc = E1000_TX_DESC(*tx_ring, first); + tx_desc->buffer_addr = 0; + tx_desc->lower.data = 0; + tx_desc->upper.data = 0; + } while(count--) { buffer_info = &tx_ring->buffer_info[i]; + if(buffer_info->dma) { pci_unmap_page(adapter->pdev, buffer_info->dma, @@ -1658,8 +1674,11 @@ PCI_DMA_TODEVICE); buffer_info->dma = 0; } + if(++i == tx_ring->count) i = 0; } + + adapter->tx_ring.next_to_use = first; return 0; } diff -Nru a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig --- a/drivers/net/hamradio/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/net/hamradio/Kconfig Fri Oct 17 14:43:50 2003 @@ -159,7 +159,7 @@ config BAYCOM_EPP tristate "BAYCOM epp driver for AX.25" - depends on PARPORT && AX25 + depends on PARPORT && AX25 && !64BIT ---help--- This is a driver for Baycom style simple amateur radio modems that connect to a parallel interface. The driver supports the EPP diff -Nru a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c --- a/drivers/net/hamradio/bpqether.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/hamradio/bpqether.c Fri Oct 17 14:43:50 2003 @@ -196,12 +196,8 @@ eth = (struct ethhdr *)skb->mac.raw; if (!(bpq->acpt_addr[0] & 0x01) && - memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN)) { - if (net_ratelimit()) - printk(KERN_DEBUG "bpqether: wrong dest %s\n", - bpq_print_ethaddr(eth->h_source)); + memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN)) goto drop_unlock; - } if (skb_cow(skb, sizeof(struct ethhdr))) goto drop_unlock; diff -Nru a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c --- a/drivers/net/hamradio/scc.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/hamradio/scc.c Fri Oct 17 14:43:50 2003 @@ -1762,7 +1762,7 @@ #ifndef SCC_DONT_CHECK - if(request_region(scc->ctrl, 1, "scc-probe")) + if(request_region(hwcfg.ctrl_a, 1, "scc-probe")) { disable_irq(hwcfg.irq); Outb(hwcfg.ctrl_a, 0); @@ -1774,7 +1774,7 @@ if (InReg(hwcfg.ctrl_a,R13) != 0x55) found = 0; enable_irq(hwcfg.irq); - release_region(scc->ctrl, 1); + release_region(hwcfg.ctrl_a, 1); } else found = 0; diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c --- a/drivers/net/hp100.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/hp100.c Fri Oct 17 14:43:50 2003 @@ -1265,9 +1265,9 @@ { /* pdlptr is starting address for this pdl */ - if (0 != (((unsigned) pdlptr) & 0xf)) - printk("hp100: %s: Init rxpdl: Unaligned pdlptr 0x%x.\n", - dev->name, (unsigned) pdlptr); + if (0 != (((unsigned long) pdlptr) & 0xf)) + printk("hp100: %s: Init rxpdl: Unaligned pdlptr 0x%lx.\n", + dev->name, (unsigned long) pdlptr); ringptr->pdl = pdlptr + 1; ringptr->pdl_paddr = virt_to_whatever(dev, pdlptr + 1); @@ -1292,8 +1292,8 @@ register hp100_ring_t * ringptr, register u32 * pdlptr) { - if (0 != (((unsigned) pdlptr) & 0xf)) - printk("hp100: %s: Init txpdl: Unaligned pdlptr 0x%x.\n", dev->name, (unsigned) pdlptr); + if (0 != (((unsigned long) pdlptr) & 0xf)) + printk("hp100: %s: Init txpdl: Unaligned pdlptr 0x%lx.\n", dev->name, (unsigned long) pdlptr); ringptr->pdl = pdlptr; /* +1; */ ringptr->pdl_paddr = virt_to_whatever(dev, pdlptr); /* +1 */ diff -Nru a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c --- a/drivers/net/irda/sa1100_ir.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/irda/sa1100_ir.c Fri Oct 17 14:43:50 2003 @@ -1132,12 +1132,8 @@ release_mem_region(__PREG(Ser2HSCR0), 0x1c); release_mem_region(__PREG(Ser2UTCR0), 0x24); - /* - * We now know that the netdevice is no longer in use, and all - * references to our driver have been removed. The only structure - * which may still be present is the netdevice, which will get - * cleaned up by net/core/dev.c - */ + if(dev) + free_netdev(dev); } static int __init sa1100ir_setup(char *line) diff -Nru a/drivers/net/loopback.c b/drivers/net/loopback.c --- a/drivers/net/loopback.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/loopback.c Fri Oct 17 14:43:50 2003 @@ -125,19 +125,7 @@ { struct net_device_stats *stats = (struct net_device_stats *)dev->priv; - /* - * Optimise so buffers with skb->free=1 are not copied but - * instead are lobbed from tx queue to rx queue - */ - - if (skb_shared(skb)) { - struct sk_buff *skb2=skb; - skb=skb_clone(skb, GFP_ATOMIC); /* Clone the buffer */ - kfree_skb(skb2); - if (unlikely(skb==NULL)) - return 0; - } else - skb_orphan(skb); + skb_orphan(skb); skb->protocol=eth_type_trans(skb,dev); skb->dev=dev; diff -Nru a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c --- a/drivers/net/myri_sbus.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/myri_sbus.c Fri Oct 17 14:43:50 2003 @@ -888,15 +888,16 @@ } #endif -static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, int num) +static int __init myri_ether_init(struct sbus_dev *sdev, int num) { static unsigned version_printed; + struct net_device *dev; struct myri_eth *mp; unsigned char prop_buf[32]; int i; - DET(("myri_ether_init(%p,%p,%d):\n", dev, sdev, num)); - dev = init_etherdev(0, sizeof(struct myri_eth)); + DET(("myri_ether_init(%p,%d):\n", sdev, num)); + dev = alloc_etherdev(sizeof(struct myri_eth)); if (!dev) return -ENOMEM; @@ -904,8 +905,6 @@ if (version_printed++ == 0) printk(version); - printk("%s: MyriCOM MyriNET Ethernet ", dev->name); - mp = (struct myri_eth *) dev->priv; spin_lock_init(&mp->irq_lock); mp->myri_sdev = sdev; @@ -974,10 +973,7 @@ #endif for (i = 0; i < 6; i++) - printk("%2.2x%c", - dev->dev_addr[i] = mp->eeprom.id[i], - i == 5 ? ' ' : ':'); - printk("\n"); + dev->dev_addr[i] = mp->eeprom.id[i]; determine_reg_space_size(mp); @@ -1072,9 +1068,6 @@ goto err; } - DET(("ether_setup()\n")); - ether_setup(dev); - dev->mtu = MYRINET_MTU; dev->change_mtu = myri_change_mtu; dev->hard_header = myri_header; @@ -1087,15 +1080,30 @@ DET(("Loading LANAI firmware\n")); myri_load_lanai(mp); + if (register_netdev(dev)) { + printk("MyriCOM: Cannot register device.\n"); + goto err_free_irq; + } + #ifdef MODULE - dev->ifindex = dev_new_index(); mp->next_module = root_myri_dev; root_myri_dev = mp; #endif + + printk("%s: MyriCOM MyriNET Ethernet ", dev->name); + + for (i = 0; i < 6; i++) + printk("%2.2x%c", dev->dev_addr[i], + i == 5 ? ' ' : ':'); + printk("\n"); + return 0; -err: unregister_netdev(dev); + +err_free_irq: + free_irq(dev->irq, dev); +err: /* This will also free the co-allocated 'dev->priv' */ - kfree(dev); + free_netdev(dev); return -ENODEV; } @@ -1112,7 +1120,6 @@ static int __init myri_sbus_probe(void) { - struct net_device *dev = NULL; struct sbus_bus *bus; struct sbus_dev *sdev = 0; static int called; @@ -1128,12 +1135,10 @@ for_each_sbus(bus) { for_each_sbusdev(sdev, bus) { - if (cards) - dev = NULL; if (myri_sbus_match(sdev)) { cards++; DET(("Found myricom myrinet as %s\n", sdev->prom_name)); - if ((v = myri_ether_init(dev, sdev, (cards - 1)))) + if ((v = myri_ether_init(sdev, (cards - 1)))) return v; } } diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c --- a/drivers/net/natsemi.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/natsemi.c Fri Oct 17 14:43:50 2003 @@ -1530,7 +1530,7 @@ for (i = 0; i < TX_RING_SIZE; i++) { if (np->tx_skbuff[i]) { pci_unmap_single(np->pci_dev, - np->rx_dma[i], np->rx_skbuff[i]->len, + np->tx_dma[i], np->tx_skbuff[i]->len, PCI_DMA_TODEVICE); dev_kfree_skb(np->tx_skbuff[i]); np->stats.tx_dropped++; diff -Nru a/drivers/net/net_init.c b/drivers/net/net_init.c --- a/drivers/net/net_init.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/net_init.c Fri Oct 17 14:43:50 2003 @@ -148,11 +148,14 @@ if (dev->name[0] == '\0' || dev->name[0] == ' ') { strcpy(dev->name, mask); + rtnl_lock(); if (dev_alloc_name(dev, mask)<0) { + rtnl_unlock(); if (new_device) kfree(dev); return NULL; } + rtnl_unlock(); } netdev_boot_setup_check(dev); @@ -194,9 +197,13 @@ * * If an empty string area is passed as dev->name, or a new structure is made, * a new name string is constructed. + * + * Deprecated because of exposed window between device registration + * and interfaces pointers that need to be set by driver. + * Use alloc_etherdev and register_netdev instead. */ -struct net_device *init_etherdev(struct net_device *dev, int sizeof_priv) +struct net_device *__init_etherdev(struct net_device *dev, int sizeof_priv) { return init_netdev(dev, sizeof_priv, "eth%d", ether_setup); } @@ -219,7 +226,7 @@ return alloc_netdev(sizeof_priv, "eth%d", ether_setup); } -EXPORT_SYMBOL(init_etherdev); +EXPORT_SYMBOL(__init_etherdev); EXPORT_SYMBOL(alloc_etherdev); static int eth_mac_addr(struct net_device *dev, void *p) diff -Nru a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c --- a/drivers/net/pcmcia/pcnet_cs.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/pcmcia/pcnet_cs.c Fri Oct 17 14:43:50 2003 @@ -681,10 +681,6 @@ } else { dev->if_port = 0; } - if (register_netdev(dev) != 0) { - printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n"); - goto failed; - } hw_info = get_hwinfo(link); if (hw_info == NULL) @@ -699,7 +695,6 @@ if (hw_info == NULL) { printk(KERN_NOTICE "pcnet_cs: unable to read hardware net" " address for io base %#3lx\n", dev->base_addr); - unregister_netdev(dev); goto failed; } @@ -733,8 +728,6 @@ ei_status.word16 = 1; ei_status.reset_8390 = &pcnet_reset_8390; - strcpy(info->node.dev_name, dev->name); - link->dev = &info->node; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); if (info->flags & (IS_DL10019|IS_DL10022)) { @@ -743,6 +736,21 @@ mii_phy_probe(dev); if ((id == 0x30) && !info->pna_phy && (info->eth_phy == 4)) info->eth_phy = 0; + } + + link->dev = &info->node; + link->state &= ~DEV_CONFIG_PENDING; + + if (register_netdev(dev) != 0) { + printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n"); + link->dev = NULL; + goto failed; + } + + strcpy(info->node.dev_name, dev->name); + + if (info->flags & (IS_DL10019|IS_DL10022)) { + u_char id = inb(dev->base_addr + 0x1a); printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ", dev->name, ((info->flags & IS_DL10022) ? 22 : 19), id); if (info->pna_phy) @@ -758,7 +766,6 @@ printk(" hw_addr "); for (i = 0; i < 6; i++) printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); - link->state &= ~DEV_CONFIG_PENDING; return; cs_failed: diff -Nru a/drivers/net/sis190.c b/drivers/net/sis190.c --- a/drivers/net/sis190.c Fri Oct 17 14:43:51 2003 +++ b/drivers/net/sis190.c Fri Oct 17 14:43:51 2003 @@ -451,8 +451,6 @@ *ioaddr_out = NULL; *dev_out = NULL; - // dev zeroed in init_etherdev - dev = alloc_etherdev(sizeof (*tp)); if (dev == NULL) { printk(KERN_ERR PFX "unable to alloc new ethernet\n"); diff -Nru a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c --- a/drivers/net/sk98lin/skge.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/sk98lin/skge.c Fri Oct 17 14:43:50 2003 @@ -653,24 +653,16 @@ continue; - if ((dev = init_etherdev(dev, sizeof(DEV_NET))) == NULL) { + if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) { printk(KERN_ERR "Unable to allocate etherdev " "structure!\n"); break; } - if (dev->priv == NULL) { - printk(KERN_ERR "Unable to allocate adapter " - "structure!\n"); - break; - } - pNet = dev->priv; pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); if (pNet->pAC == NULL){ - dev->get_stats = NULL; - unregister_netdev(dev); - kfree(dev->priv); + free_netdev(dev); printk(KERN_ERR "Unable to allocate adapter " "structure!\n"); break; @@ -699,9 +691,7 @@ retval = SkGeInitPCI(pAC); if (retval) { printk("SKGE: PCI setup failed: %i\n", retval); - dev->get_stats = NULL; - unregister_netdev(dev); - kfree(dev); + free_netdev(dev); continue; } @@ -730,13 +720,20 @@ pAC->Index = boards_found; if (SkGeBoardInit(dev, pAC)) { FreeResources(dev); - kfree(dev); + free_netdev(dev); continue; } memcpy((caddr_t) &dev->dev_addr, (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); + if (register_netdev(dev)) { + printk(KERN_ERR "SKGE: Could not register device.\n"); + FreeResources(dev); + free_netdev(dev); + continue; + } + /* First adapter... Create proc and print message */ #ifdef CONFIG_PROC_FS if (!DeviceFound) { @@ -767,21 +764,11 @@ pNet->PortNr = 0; pNet->NetNr = 0; - -#ifdef SK_ZEROCOPY -#ifdef USE_SK_TX_CHECKSUM - if (pAC->ChipsetType) { - /* SG and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif -#endif - boards_found++; /* More then one port found */ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - if ((dev = init_etherdev(NULL, sizeof(DEV_NET))) == 0) { + if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) { printk(KERN_ERR "Unable to allocate etherdev " "structure!\n"); break; @@ -814,22 +801,28 @@ #endif #endif + if (register_netdev(dev)) { + printk(KERN_ERR "SKGE: Could not register " + "second port.\n"); + free_netdev(dev); + pAC->dev[1] = pAC->dev[0]; + } else { #ifdef CONFIG_PROC_FS - if (pSkRootDir - && (pProcFile = create_proc_entry(dev->name, - S_IRUGO, - pSkRootDir))) { - pProcFile->proc_fops = &sk_proc_fops; - pProcFile->data = dev; - } + if (pSkRootDir + && (pProcFile = create_proc_entry(dev->name, + S_IRUGO, + pSkRootDir))) { + pProcFile->proc_fops = &sk_proc_fops; + pProcFile->data = dev; + } #endif - memcpy((caddr_t) &dev->dev_addr, - (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); + memcpy((caddr_t) &dev->dev_addr, + (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); - printk("%s: %s\n", dev->name, pAC->DeviceStr); - printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); - + printk("%s: %s\n", dev->name, pAC->DeviceStr); + printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); + } } diff -Nru a/drivers/net/slip.c b/drivers/net/slip.c --- a/drivers/net/slip.c Fri Oct 17 14:43:51 2003 +++ b/drivers/net/slip.c Fri Oct 17 14:43:51 2003 @@ -1307,7 +1307,7 @@ /* Resolve race condition, when ioctl'ing hanged up and opened by another process device. */ - if (sl->tty != process_tty(current) && sl->pid != current->pid) { + if (sl->tty != current->tty && sl->pid != current->pid) { spin_unlock_bh(&sl->lock); return -EPERM; } diff -Nru a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c --- a/drivers/net/sunbmac.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/sunbmac.c Fri Oct 17 14:43:50 2003 @@ -1072,7 +1072,7 @@ int i; /* Get a new device struct for this interface. */ - dev = init_etherdev(NULL, sizeof(struct bigmac)); + dev = alloc_etherdev(sizeof(struct bigmac)); if (!dev) return -ENOMEM; SET_MODULE_OWNER(dev); @@ -1080,13 +1080,9 @@ if (version_printed++ == 0) printk(KERN_INFO "%s", version); - /* Report what we have found to the user. */ - printk(KERN_INFO "%s: BigMAC 100baseT Ethernet ", dev->name); dev->base_addr = (long) qec_sdev; for (i = 0; i < 6; i++) - printk("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i], - i == 5 ? ' ' : ':'); - printk("\n"); + dev->dev_addr[i] = idprom->id_ethaddr[i]; /* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */ bp = dev->priv; @@ -1210,12 +1206,23 @@ dev->irq = bp->bigmac_sdev->irqs[0]; dev->dma = 0; + if (register_netdev(dev)) { + printk(KERN_ERR "BIGMAC: Cannot register device.\n"); + goto fail_and_cleanup; + } + /* Put us into the list of instances attached for later driver * exit. */ bp->next_module = root_bigmac_dev; root_bigmac_dev = bp; + printk(KERN_INFO "%s: BigMAC 100baseT Ethernet ", dev->name); + for (i = 0; i < 6; i++) + printk("%2.2x%c", dev->dev_addr[i], + i == 5 ? ' ' : ':'); + printk("\n"); + return 0; fail_and_cleanup: @@ -1236,9 +1243,8 @@ bp->bmac_block, bp->bblock_dvma); - unregister_netdev(dev); /* This also frees the co-located 'dev->priv' */ - kfree(dev); + free_netdev(dev); return -ENODEV; } diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c --- a/drivers/net/sungem.c Fri Oct 17 14:43:51 2003 +++ b/drivers/net/sungem.c Fri Oct 17 14:43:51 2003 @@ -2731,6 +2731,19 @@ if (gem_get_device_address(gp)) goto err_out_free_consistent; + dev->open = gem_open; + dev->stop = gem_close; + dev->hard_start_xmit = gem_start_xmit; + dev->get_stats = gem_get_stats; + dev->set_multicast_list = gem_set_multicast; + dev->do_ioctl = gem_ioctl; + dev->ethtool_ops = &gem_ethtool_ops; + dev->tx_timeout = gem_tx_timeout; + dev->watchdog_timeo = 5 * HZ; + dev->change_mtu = gem_change_mtu; + dev->irq = pdev->irq; + dev->dma = 0; + if (register_netdev(dev)) { printk(KERN_ERR PFX "Cannot register net device, " "aborting.\n"); @@ -2758,19 +2771,6 @@ gp->phy_mii.def ? gp->phy_mii.def->name : "no"); pci_set_drvdata(pdev, dev); - - dev->open = gem_open; - dev->stop = gem_close; - dev->hard_start_xmit = gem_start_xmit; - dev->get_stats = gem_get_stats; - dev->set_multicast_list = gem_set_multicast; - dev->do_ioctl = gem_ioctl; - dev->ethtool_ops = &gem_ethtool_ops; - dev->tx_timeout = gem_tx_timeout; - dev->watchdog_timeo = 5 * HZ; - dev->change_mtu = gem_change_mtu; - dev->irq = pdev->irq; - dev->dma = 0; /* GEM can do it all... */ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c --- a/drivers/net/sunhme.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/sunhme.c Fri Oct 17 14:43:50 2003 @@ -2996,7 +2996,7 @@ dev_addr[0] = 0x08; dev_addr[1] = 0x00; dev_addr[2] = 0x20; - get_random_bytes(dev_addr, 3); + get_random_bytes(&dev_addr[3], 3); return; } #endif /* !(__sparc__) */ diff -Nru a/drivers/net/sunlance.c b/drivers/net/sunlance.c --- a/drivers/net/sunlance.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/sunlance.c Fri Oct 17 14:43:50 2003 @@ -1312,32 +1312,24 @@ .get_link = sparc_lance_get_link, }; -static int __init sparc_lance_init(struct net_device *dev, - struct sbus_dev *sdev, +static int __init sparc_lance_init(struct sbus_dev *sdev, struct sbus_dma *ledma, struct sbus_dev *lebuffer) { static unsigned version_printed; - struct lance_private *lp = NULL; + struct net_device *dev; + struct lance_private *lp; int i; - if (dev == NULL) { - dev = init_etherdev (0, sizeof (struct lance_private) + 8); - } else { - dev->priv = kmalloc(sizeof (struct lance_private) + 8, - GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof (struct lance_private) + 8); - } + dev = alloc_etherdev(sizeof(struct lance_private) + 8); + if (!dev) + return -ENOMEM; + + lp = dev->priv; + if (sparc_lance_debug && version_printed++ == 0) printk (KERN_INFO "%s", version); - printk(KERN_INFO "%s: LANCE ", dev->name); - - /* Make certain the data structures used by the LANCE are aligned. */ - dev->priv = (void *)(((unsigned long)dev->priv + 7) & ~7); - lp = (struct lance_private *) dev->priv; spin_lock_init(&lp->lock); /* Copy the IDPROM ethernet address to the device structure, later we @@ -1345,16 +1337,13 @@ * initialization block. */ for (i = 0; i < 6; i++) - printk("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i], - i == 5 ? ' ': ':'); - printk("\n"); + dev->dev_addr[i] = idprom->id_ethaddr[i]; /* Get the IO region */ lp->lregs = sbus_ioremap(&sdev->resource[0], 0, LANCE_REG_SIZE, lancestr); if (lp->lregs == 0UL) { - printk(KERN_ERR "%s: Cannot map SunLance registers.\n", - dev->name); + printk(KERN_ERR "SunLance: Cannot map registers.\n"); goto fail; } @@ -1364,8 +1353,7 @@ sbus_ioremap(&lebuffer->resource[0], 0, sizeof(struct lance_init_block), "lebuffer"); if (lp->init_block == NULL) { - printk(KERN_ERR "%s: Cannot map SunLance PIO buffer.\n", - dev->name); + printk(KERN_ERR "SunLance: Cannot map PIO buffer.\n"); goto fail; } lp->init_block_dvma = 0; @@ -1379,8 +1367,7 @@ &lp->init_block_dvma); if (lp->init_block == NULL || lp->init_block_dvma == 0) { - printk(KERN_ERR "%s: Cannot allocate consistent DMA memory.\n", - dev->name); + printk(KERN_ERR "SunLance: Cannot allocate consistent DMA memory.\n"); goto fail; } lp->pio_buffer = 0; @@ -1418,8 +1405,7 @@ if (prop[0] == 0) { int topnd, nd; - printk(KERN_INFO "%s: using auto-carrier-detection.\n", - dev->name); + printk(KERN_INFO "SunLance: using auto-carrier-detection.\n"); /* Is this found at /options .attributes in all * Prom versions? XXX @@ -1438,10 +1424,10 @@ sizeof(prop)); if (strcmp(prop, "true")) { - printk(KERN_NOTICE "%s: warning: overriding option " - "'tpe-link-test?'\n", dev->name); - printk(KERN_NOTICE "%s: warning: mail any problems " - "to ecd@skynet.be\n", dev->name); + printk(KERN_NOTICE "SunLance: warning: overriding option " + "'tpe-link-test?'\n"); + printk(KERN_NOTICE "SunLance: warning: mail any problems " + "to ecd@skynet.be\n"); auxio_set_lte(AUXIO_LTE_ON); } no_link_test: @@ -1467,8 +1453,7 @@ /* This should never happen. */ if ((unsigned long)(lp->init_block->brx_ring) & 0x07) { - printk(KERN_ERR "%s: ERROR: Rx and Tx rings not on even boundary.\n", - dev->name); + printk(KERN_ERR "SunLance: ERROR: Rx and Tx rings not on even boundary.\n"); goto fail; } @@ -1486,7 +1471,6 @@ dev->irq = sdev->irqs[0]; dev->dma = 0; - ether_setup(dev); /* We cannot sleep if the chip is busy during a * multicast list update event, because such events @@ -1497,15 +1481,27 @@ lp->multicast_timer.data = (unsigned long) dev; lp->multicast_timer.function = &lance_set_multicast_retry; - dev->ifindex = dev_new_index(); + if (register_netdev(dev)) { + printk(KERN_ERR "SunLance: Cannot register device.\n"); + goto fail; + } + lp->next_module = root_lance_dev; root_lance_dev = lp; + printk(KERN_INFO "%s: LANCE ", dev->name); + + for (i = 0; i < 6; i++) + printk("%2.2x%c", dev->dev_addr[i], + i == 5 ? ' ': ':'); + printk("\n"); + return 0; fail: if (lp != NULL) lance_free_hwresources(lp); + free_netdev(dev); return -ENODEV; } @@ -1543,7 +1539,7 @@ memset(&sdev, 0, sizeof(sdev)); sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; sdev.irqs[0] = 6; - return sparc_lance_init(NULL, &sdev, 0, 0); + return sparc_lance_init(&sdev, 0, 0); } return -ENODEV; } @@ -1555,7 +1551,6 @@ { struct sbus_bus *bus; struct sbus_dev *sdev = 0; - struct net_device *dev = NULL; struct sbus_dma *ledma = 0; static int called; int cards = 0, v; @@ -1568,25 +1563,23 @@ for_each_sbus (bus) { for_each_sbusdev (sdev, bus) { - if (cards) - dev = NULL; if (strcmp(sdev->prom_name, "le") == 0) { cards++; - if ((v = sparc_lance_init(dev, sdev, 0, 0))) + if ((v = sparc_lance_init(sdev, 0, 0))) return v; continue; } if (strcmp(sdev->prom_name, "ledma") == 0) { cards++; ledma = find_ledma(sdev); - if ((v = sparc_lance_init(dev, sdev->child, + if ((v = sparc_lance_init(sdev->child, ledma, 0))) return v; continue; } if (strcmp(sdev->prom_name, "lebuffer") == 0){ cards++; - if ((v = sparc_lance_init(dev, sdev->child, + if ((v = sparc_lance_init(sdev->child, 0, sdev))) return v; continue; diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c --- a/drivers/net/tulip/tulip_core.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/tulip/tulip_core.c Fri Oct 17 14:43:50 2003 @@ -224,6 +224,7 @@ { 0x1186, 0x1561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1737, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, /* ALi 1563 integrated ethernet */ { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */ diff -Nru a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c --- a/drivers/net/tulip/xircom_cb.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/tulip/xircom_cb.c Fri Oct 17 14:43:50 2003 @@ -230,7 +230,8 @@ This way, we can fail gracefully if not enough memory is available. */ - if ((dev = init_etherdev(NULL, sizeof(struct xircom_private))) == NULL) { + dev = alloc_etherdev(sizeof(struct xircom_private)); + if (!dev) { printk(KERN_ERR "xircom_probe: failed to allocate etherdev\n"); goto device_fail; } @@ -250,7 +251,7 @@ SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq); + private->dev = dev; private->pdev = pdev; @@ -259,7 +260,6 @@ dev->irq = pdev->irq; dev->base_addr = private->io_port; - initialize_card(private); read_mac_address(private); setup_descriptors(private); @@ -272,7 +272,12 @@ SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); pci_set_drvdata(pdev, dev); - + if (register_netdev(dev)) { + printk(KERN_ERR "xircom_probe: netdevice registration failed.\n"); + goto reg_fail; + } + + printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq); /* start the transmitter to get a heartbeat */ /* TODO: send 2 dummy packets here */ transceiver_voodoo(private); @@ -287,10 +292,12 @@ leave("xircom_probe"); return 0; +reg_fail: + kfree(private->tx_buffer); tx_buf_fail: kfree(private->rx_buffer); rx_buf_fail: - kfree(dev); + free_netdev(dev); device_fail: return -ENODEV; } @@ -305,22 +312,16 @@ static void __devexit xircom_remove(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct xircom_private *card; + struct xircom_private *card = dev->priv; + enter("xircom_remove"); - if (dev!=NULL) { - card=dev->priv; - if (card!=NULL) { - if (card->rx_buffer!=NULL) - pci_free_consistent(pdev,8192,card->rx_buffer,card->rx_dma_handle); - card->rx_buffer = NULL; - if (card->tx_buffer!=NULL) - pci_free_consistent(pdev,8192,card->tx_buffer,card->tx_dma_handle); - card->tx_buffer = NULL; - } - } + pci_free_consistent(pdev,8192,card->rx_buffer,card->rx_dma_handle); + pci_free_consistent(pdev,8192,card->tx_buffer,card->tx_dma_handle); + release_region(dev->base_addr, 128); unregister_netdev(dev); free_netdev(dev); + pci_set_drvdata(pdev, NULL); leave("xircom_remove"); } diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c --- a/drivers/net/wan/cosa.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/wan/cosa.c Fri Oct 17 14:43:50 2003 @@ -615,7 +615,7 @@ d->get_stats = cosa_net_stats; d->tx_timeout = cosa_sppp_timeout; d->watchdog_timeo = TX_TIMEOUT; - if (register_netdev(d) == -1) { + if (register_netdev(d)) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); sppp_detach(chan->pppdev.dev); free_netdev(chan->pppdev.dev); diff -Nru a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c --- a/drivers/net/wan/hdlc_cisco.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/wan/hdlc_cisco.c Fri Oct 17 14:43:50 2003 @@ -311,7 +311,9 @@ hdlc->proto.id = IF_PROTO_CISCO; dev->hard_start_xmit = hdlc->xmit; dev->hard_header = cisco_hard_header; + dev->hard_header_cache = NULL; dev->type = ARPHRD_CISCO; + dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->addr_len = 0; return 0; } diff -Nru a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c --- a/drivers/net/wan/hostess_sv11.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/wan/hostess_sv11.c Fri Oct 17 14:43:50 2003 @@ -337,7 +337,7 @@ d->neigh_setup = hostess_neigh_setup_dev; d->set_mac_address = NULL; - if(register_netdev(d)==-1) + if(register_netdev(d)) { printk(KERN_ERR "%s: unable to register device.\n", d->name); diff -Nru a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c --- a/drivers/net/wan/sealevel.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/wan/sealevel.c Fri Oct 17 14:43:50 2003 @@ -31,6 +31,7 @@ struct slvl_device { + void *if_ptr; /* General purpose pointer (used by SPPP) */ struct z8530_channel *chan; struct ppp_device pppdev; int channel; @@ -238,6 +239,7 @@ return NULL; sv = d->priv; + sv->if_ptr = &sv->pppdev; sv->pppdev.dev = d; d->base_addr = iobase; d->irq = irq; diff -Nru a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c --- a/drivers/net/wan/syncppp.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/wan/syncppp.c Fri Oct 17 14:43:50 2003 @@ -1069,6 +1069,9 @@ struct sppp *sp = &pd->sppp; unsigned long flags; + /* Make sure embedding is safe for sppp_of */ + BUG_ON(sppp_of(dev) != sp); + spin_lock_irqsave(&spppq_lock, flags); /* Initialize keepalive handler. */ if (! spppq) diff -Nru a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c --- a/drivers/net/wireless/atmel.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/wireless/atmel.c Fri Oct 17 14:43:50 2003 @@ -37,7 +37,6 @@ ******************************************************************************/ #include -#include #include #include diff -Nru a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c --- a/drivers/net/wireless/atmel_cs.c Fri Oct 17 14:43:50 2003 +++ b/drivers/net/wireless/atmel_cs.c Fri Oct 17 14:43:50 2003 @@ -84,7 +84,7 @@ static int irq_list[4] = { -1 }; MODULE_AUTHOR("Simon Kelley"); -MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethnet cards."); +MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards."); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards"); MODULE_PARM(irq_mask, "i"); @@ -404,9 +404,12 @@ goto mismatch; for (k = 0; k < j; k++) { while ((*p != '\0') && (*p != '/')) p++; - if (*p == '\0') - goto mismatch; - p++; + if (*p == '\0') { + if (*q != '\0') + goto mismatch; + } else { + p++; + } } while((*q != '\0') && (*p != '\0') && (*p != '/') && (*p == *q)) p++, q++; diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig --- a/drivers/pci/hotplug/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/pci/hotplug/Kconfig Fri Oct 17 14:43:50 2003 @@ -44,7 +44,7 @@ config HOTPLUG_PCI_COMPAQ tristate "Compaq PCI Hotplug driver" - depends on HOTPLUG_PCI && X86 + depends on HOTPLUG_PCI && X86 && PCI_BIOS help Say Y here if you have a motherboard with a Compaq PCI Hotplug controller. @@ -66,7 +66,7 @@ config HOTPLUG_PCI_IBM tristate "IBM PCI Hotplug driver" - depends on HOTPLUG_PCI && X86_IO_APIC && X86 + depends on HOTPLUG_PCI && X86_IO_APIC && X86 && PCI_BIOS help Say Y here if you have a motherboard with a IBM PCI Hotplug controller. diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c --- a/drivers/pcmcia/tcic.c Fri Oct 17 14:43:50 2003 +++ b/drivers/pcmcia/tcic.c Fri Oct 17 14:43:50 2003 @@ -643,7 +643,7 @@ reg = tcic_getb(TCIC_PWR); if (reg & (TCIC_PWR_VCC(psock)|TCIC_PWR_VPP(psock))) *value |= SS_POWERON; - DEBUG(1, "tcic: GetStatus(%d) = %#2.2x\n", lsock, *value); + DEBUG(1, "tcic: GetStatus(%d) = %#2.2x\n", psock, *value); return 0; } /* tcic_get_status */ @@ -695,7 +695,7 @@ } DEBUG(1, "tcic: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, " - "io_irq %d, csc_mask %#2.2x\n", lsock, state->flags, + "io_irq %d, csc_mask %#2.2x\n", psock, state->flags, state->Vcc, state->Vpp, state->io_irq, state->csc_mask); return 0; } /* tcic_get_socket */ @@ -709,7 +709,7 @@ u_short scf1, scf2; DEBUG(1, "tcic: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " - "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags, + "io_irq %d, csc_mask %#2.2x)\n", psock, state->flags, state->Vcc, state->Vpp, state->io_irq, state->csc_mask); tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG); @@ -784,7 +784,7 @@ u_short base, len, ioctl; DEBUG(1, "tcic: SetIOMap(%d, %d, %#2.2x, %d ns, " - "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags, + "%#4.4x-%#4.4x)\n", psock, io->map, io->flags, io->speed, io->start, io->stop); if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)) return -EINVAL; @@ -821,7 +821,7 @@ u_long base, len, mmap; DEBUG(1, "tcic: SetMemMap(%d, %d, %#2.2x, %d ns, " - "%#5.5lx-%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags, + "%#5.5lx-%#5.5lx, %#5.5x)\n", psock, mem->map, mem->flags, mem->speed, mem->sys_start, mem->sys_stop, mem->card_start); if ((mem->map > 3) || (mem->card_start > 0x3ffffff) || (mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff) || diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- a/drivers/scsi/scsi_sysfs.c Fri Oct 17 14:43:50 2003 +++ b/drivers/scsi/scsi_sysfs.c Fri Oct 17 14:43:50 2003 @@ -412,7 +412,7 @@ set_bit(SDEV_DEL, &sdev->sdev_state); if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); - if (atomic_read(&sdev->access_count)) + if (!atomic_read(&sdev->access_count)) device_del(&sdev->sdev_gendev); up_write(&class->subsys.rwsem); } diff -Nru a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c --- a/drivers/serial/8250_acpi.c Fri Oct 17 14:43:51 2003 +++ b/drivers/serial/8250_acpi.c Fri Oct 17 14:43:51 2003 @@ -38,8 +38,11 @@ static acpi_status acpi_serial_port(struct serial_struct *req, struct acpi_resource_io *io) { - req->port = io->min_base_address; - req->io_type = SERIAL_IO_PORT; + if (io->range_length) { + req->port = io->min_base_address; + req->io_type = SERIAL_IO_PORT; + } else + printk(KERN_ERR "%s: zero-length IO port range?\n", __FUNCTION__); return AE_OK; } diff -Nru a/drivers/usb/README b/drivers/usb/README --- a/drivers/usb/README Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/README Fri Oct 17 14:43:50 2003 @@ -8,7 +8,7 @@ includes UHCI, OHCI, EHCI, and any others that might be created in the future. -device/ - This is for all of the USB device controller drivers. +gadget/ - This is for all of the USB device controller drivers. Individual USB driver directories. A new driver should be added to the @@ -16,7 +16,7 @@ image/ - This is for still image drivers, like scanners or digital cameras. -input/ - This if for any driver that uses the input subsystem, +input/ - This is for any driver that uses the input subsystem, like keyboard, mice, touchscreens, tablets, etc. media/ - This is for multimedia drivers, like video cameras, radios, and any other drivers that talk to the v4l @@ -29,5 +29,3 @@ of USB Class specified devices. misc/ - This is for all USB device drivers that do not fit into any of the above categories. - - diff -Nru a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig --- a/drivers/usb/class/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/class/Kconfig Fri Oct 17 14:43:50 2003 @@ -71,7 +71,7 @@ driver. To compile this driver as a module, choose M here: the - module will be called acm. + module will be called cdc-acm. config USB_PRINTER tristate "USB Printer support" diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c --- a/drivers/usb/core/devio.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/core/devio.c Fri Oct 17 14:43:50 2003 @@ -384,7 +384,7 @@ err = -EINVAL; dev = ps->dev; down(&dev->serialize); - if (dev && test_and_clear_bit(intf, &ps->ifclaimed)) { + if (test_and_clear_bit(intf, &ps->ifclaimed)) { iface = dev->actconfig->interface[intf]; usb_driver_release_interface(&usbdevfs_driver, iface); err = 0; diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/core/hcd-pci.c Fri Oct 17 14:43:50 2003 @@ -295,6 +295,8 @@ if (retval) dev_dbg (hcd->controller, "suspend fail, retval %d\n", retval); + else + hcd->state = USB_STATE_SUSPENDED; } pci_set_power_state (dev, state); diff -Nru a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig --- a/drivers/usb/gadget/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/gadget/Kconfig Fri Oct 17 14:43:50 2003 @@ -110,7 +110,7 @@ config USB_ETH tristate "Ethernet Gadget" - depends on USB_GADGET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA2XX || USB_SA1100) + depends on USB_GADGET && NET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA2XX || USB_SA1100) help This driver implements Ethernet style communication, in either of two ways: diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c --- a/drivers/usb/gadget/net2280.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/gadget/net2280.c Fri Oct 17 14:43:50 2003 @@ -50,7 +50,6 @@ #define DEBUG 1 // #define VERBOSE /* extra debug messages (success too) */ -#include #include #include #include @@ -431,6 +430,9 @@ #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) #define USE_KMALLOC +#elif defined(CONFIG_MIPS) && !defined(CONFIG_NONCOHERENT_IO) +#define USE_KMALLOC + /* FIXME there are other cases, including an x86-64 one ... */ #endif @@ -452,31 +454,23 @@ ep = container_of (_ep, struct net2280_ep, ep); if (!_ep) return 0; - *dma = DMA_ADDR_INVALID; - if (ep->dma) { -#if defined(USE_KMALLOC) - retval = kmalloc (bytes, gfp_flags); - if (retval) - *dma = virt_to_phys (retval); -#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,5,58) -#warning Using dma_alloc_consistent even with sub-page allocations +#if defined(USE_KMALLOC) + retval = kmalloc(bytes, gfp_flags); + if (retval) + *dma = virt_to_phys(retval); +#else + if (ep->dma) { /* the main problem with this call is that it wastes memory * on typical 1/N page allocations: it allocates 1-N pages. */ - retval = dma_alloc_coherent (&ep->dev->pdev->dev, +#warning Using dma_alloc_coherent even with buffers smaller than a page. + retval = dma_alloc_coherent(&ep->dev->pdev->dev, bytes, dma, gfp_flags); -#else -#error No dma-coherent memory allocator is available - /* pci_alloc_consistent works, but pci_free_consistent() - * isn't safe in_interrupt(). plus, in addition to the - * 1/Nth page weakness, it doesn't understand gfp_flags. - */ -#endif } else - retval = kmalloc (bytes, gfp_flags); - + retval = kmalloc(bytes, gfp_flags); +#endif return retval; } @@ -489,9 +483,14 @@ ) { /* free memory into the right allocator */ #ifndef USE_KMALLOC - if (dma != DMA_ADDR_INVALID) - dma_free_coherent (ep->dev->pdev, bytes, dma); - else + if (dma != DMA_ADDR_INVALID) { + struct net2280_ep *ep; + + ep = container_of(_ep, struct net2280_ep, ep); + if (!_ep) + return; + dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma); + } else #endif kfree (buf); } @@ -516,8 +515,9 @@ /* INVARIANT: fifo is currently empty. (testable) */ if (req) { - total = req->length - req->actual; buf = req->buf + req->actual; + prefetch (buf); + total = req->length - req->actual; } else { total = 0; buf = 0; @@ -615,6 +615,7 @@ /* never overflow the rx buffer. the fifo reads packets until * it sees a short one; we might not be ready for them all. */ + prefetchw (buf); count = readl (®s->ep_avail); tmp = req->req.length - req->req.actual; if (count > tmp) { diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c --- a/drivers/usb/host/ehci-dbg.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/host/ehci-dbg.c Fri Oct 17 14:43:50 2003 @@ -465,7 +465,7 @@ spin_lock_irqsave (&ehci->lock, flags); for (i = 0; i < ehci->periodic_size; i++) { p = ehci->pshadow [i]; - if (!p.ptr) + if (likely (!p.ptr)) continue; tag = Q_NEXT_TYPE (ehci->periodic [i]); @@ -495,7 +495,7 @@ break; } /* show more info the first time around */ - if (temp == seen_count) { + if (temp == seen_count && p.ptr) { u32 scratch = cpu_to_le32p ( &p.qh->hw_info1); struct ehci_qtd *qtd; @@ -528,8 +528,10 @@ seen [seen_count++].qh = p.qh; } else temp = 0; - tag = Q_NEXT_TYPE (p.qh->hw_next); - p = p.qh->qh_next; + if (p.qh) { + tag = Q_NEXT_TYPE (p.qh->hw_next); + p = p.qh->qh_next; + } break; case Q_TYPE_FSTN: temp = snprintf (next, size, diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c --- a/drivers/usb/host/ehci-q.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/host/ehci-q.c Fri Oct 17 14:43:50 2003 @@ -184,7 +184,7 @@ struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; /* S-mask in a QH means it's an interrupt urb */ - if ((qh->hw_info2 & cpu_to_le32 (0x00ff)) != 0) { + if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) { /* ... update hc-wide periodic stats (for usbfs) */ hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs--; @@ -224,7 +224,7 @@ * Chases up to qh->hw_current. Returns number of completions called, * indicating how much "real" work we did. */ -#define HALT_BIT cpu_to_le32(QTD_STS_HALT) +#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT) static unsigned qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs) { @@ -377,10 +377,14 @@ return count; } -#undef HALT_BIT /*-------------------------------------------------------------------------*/ +// high bandwidth multiplier, as encoded in highspeed endpoint descriptors +#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) +// ... and packet size, for any kind of endpoint descriptor +#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) + /* * reverse of qh_urb_transaction: free a list of TDs. * used for cleanup after errors, before HC sees an URB's TDs. @@ -461,7 +465,7 @@ token |= (1 /* "in" */ << 8); /* else it's already initted to "out" pid (0 << 8) */ - maxpacket = usb_maxpacket (urb->dev, urb->pipe, !is_input) & 0x03ff; + maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); /* * buffer gets wrapped in one or more qtds; @@ -564,11 +568,6 @@ // That'd mean updating how usbcore talks to HCDs. (2.5?) -// high bandwidth multiplier, as encoded in highspeed endpoint descriptors -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) -// ... and packet size, for any kind of endpoint descriptor -#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x03ff) - /* * Each QH holds a qtd list; a QH is used for everything except iso. * @@ -728,7 +727,7 @@ } } - qh->hw_token &= ~__constant_cpu_to_le32 (QTD_STS_HALT); + qh->hw_token &= ~HALT_BIT; /* splice right after start */ qh->qh_next = head->qh_next; @@ -744,6 +743,8 @@ /*-------------------------------------------------------------------------*/ +#define QH_ADDR_MASK __constant_le32_to_cpu(0x7f) + /* * For control/bulk/interrupt, return QH with these TDs appended. * Allocates and initializes the QH if necessary. @@ -778,12 +779,13 @@ /* control qh may need patching after enumeration */ if (unlikely (epnum == 0)) { /* set_address changes the address */ - if (le32_to_cpu (qh->hw_info1 & 0x7f) == 0) + if ((qh->hw_info1 & QH_ADDR_MASK) == 0) qh->hw_info1 |= cpu_to_le32 ( usb_pipedevice (urb->pipe)); /* for full speed, ep0 maxpacket can grow */ - else if (!(qh->hw_info1 & cpu_to_le32 (0x3 << 12))) { + else if (!(qh->hw_info1 + & __constant_cpu_to_le32 (0x3 << 12))) { u32 info, max; info = le32_to_cpu (qh->hw_info1); @@ -797,7 +799,7 @@ /* usb_reset_device() briefly reverts to address 0 */ if (usb_pipedevice (urb->pipe) == 0) - qh->hw_info1 &= cpu_to_le32(~0x7f); + qh->hw_info1 &= ~QH_ADDR_MASK; } /* usb_clear_halt() means qh data toggle gets reset */ @@ -833,7 +835,7 @@ * HC is allowed to fetch the old dummy (4.10.2). */ token = qtd->hw_token; - qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); + qtd->hw_token = HALT_BIT; wmb (); dummy = qh->dummy; diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h --- a/drivers/usb/host/ehci.h Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/host/ehci.h Fri Oct 17 14:43:50 2003 @@ -325,6 +325,7 @@ struct ehci_itd *itd; /* Q_TYPE_ITD */ struct ehci_sitd *sitd; /* Q_TYPE_SITD */ struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ + u32 *hw_next; /* (all types) */ void *ptr; }; @@ -469,26 +470,11 @@ /*-------------------------------------------------------------------------*/ -#include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32) - -#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb) -#define STUB_DEBUG_FILES - -static inline int hcd_register_root (struct usb_hcd *hcd) -{ - return usb_new_device (hcd_to_bus (hcd)->root_hub); -} - -#else /* LINUX_VERSION_CODE */ - #define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags) #ifndef DEBUG #define STUB_DEBUG_FILES #endif /* DEBUG */ - -#endif /* LINUX_VERSION_CODE */ /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/host/ohci-hcd.c Fri Oct 17 14:43:50 2003 @@ -102,14 +102,8 @@ #include #include -/* - * TO DO: - * - * - "disabled" and "sleeping" should be in hcd->state - * - lots more testing!! - */ -#define DRIVER_VERSION "2003 Feb 24" +#define DRIVER_VERSION "2003 Oct 13" #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" @@ -125,13 +119,12 @@ /*-------------------------------------------------------------------------*/ -static const char hcd_name [] = "ohci-hcd"; +static const char hcd_name [] = "ohci_hcd"; #include "ohci.h" static inline void disable (struct ohci_hcd *ohci) { - ohci->disabled = 1; ohci->hcd.state = USB_STATE_HALT; } @@ -222,7 +215,7 @@ spin_lock_irqsave (&ohci->lock, flags); /* don't submit to a dead HC */ - if (ohci->disabled || ohci->sleeping) { + if (!HCD_IS_RUNNING(ohci->hcd.state)) { retval = -ENODEV; goto fail; } @@ -278,7 +271,7 @@ #endif spin_lock_irqsave (&ohci->lock, flags); - if (!ohci->disabled) { + if (HCD_IS_RUNNING(ohci->hcd.state)) { urb_priv_t *urb_priv; /* Unless an IRQ completed the unlink while it was being @@ -287,7 +280,6 @@ */ urb_priv = urb->hcpriv; if (urb_priv) { - urb_priv->state = URB_DEL; if (urb_priv->ed->state == ED_OPER) start_urb_unlink (ohci, urb_priv->ed); } @@ -334,7 +326,7 @@ if (!ed) goto done; - if (!HCD_IS_RUNNING (ohci->hcd.state) || ohci->disabled) + if (!HCD_IS_RUNNING (ohci->hcd.state)) ed->state = ED_IDLE; switch (ed->state) { case ED_UNLINK: /* wait for hw to finish? */ @@ -355,9 +347,9 @@ /* caller was supposed to have unlinked any requests; * that's not our job. can't recover; must leak ed. */ - ohci_err (ohci, "ed %p (#%d) state %d%s\n", + ohci_err (ohci, "leak ed %p (#%d) state %d%s\n", ed, epnum, ed->state, - list_empty (&ed->td_list) ? "" : "(has tds)"); + list_empty (&ed->td_list) ? "" : " (has tds)"); td_free (ohci, ed->dummy); break; } @@ -466,8 +458,7 @@ struct usb_bus *bus; spin_lock_init (&ohci->lock); - ohci->disabled = 1; - ohci->sleeping = 0; + disable (ohci); /* Tell the controller where the control and bulk lists are * The lists are empty now. */ @@ -496,8 +487,8 @@ /* start controller operations */ ohci->hc_control &= OHCI_CTRL_RWC; ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; - ohci->disabled = 0; writel (ohci->hc_control, &ohci->regs->control); + ohci->hcd.state = USB_STATE_RUNNING; /* Choose the interrupts we care about now, others later on demand */ mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH; @@ -586,9 +577,11 @@ } if (ints & OHCI_INTR_WDH) { - writel (OHCI_INTR_WDH, ®s->intrdisable); + if (HCD_IS_RUNNING(hcd->state)) + writel (OHCI_INTR_WDH, ®s->intrdisable); dl_done_list (ohci, dl_reverse_done_list (ohci), ptregs); - writel (OHCI_INTR_WDH, ®s->intrenable); + if (HCD_IS_RUNNING(hcd->state)) + writel (OHCI_INTR_WDH, ®s->intrenable); } /* could track INTR_SO to reduce available PCI/... bandwidth */ @@ -600,14 +593,17 @@ if (ohci->ed_rm_list) finish_unlinks (ohci, le16_to_cpu (ohci->hcca->frame_no), ptregs); - if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list) + if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list + && HCD_IS_RUNNING(ohci->hcd.state)) writel (OHCI_INTR_SF, ®s->intrdisable); spin_unlock (&ohci->lock); - writel (ints, ®s->intrstatus); - writel (OHCI_INTR_MIE, ®s->intrenable); - // flush those pci writes - (void) readl (&ohci->regs->control); + if (HCD_IS_RUNNING(ohci->hcd.state)) { + writel (ints, ®s->intrstatus); + writel (OHCI_INTR_MIE, ®s->intrenable); + // flush those pci writes + (void) readl (&ohci->regs->control); + } } /*-------------------------------------------------------------------------*/ @@ -616,13 +612,12 @@ { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - ohci_dbg (ohci, "stop %s controller%s\n", + ohci_dbg (ohci, "stop %s controller (state 0x%02x)\n", hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), - ohci->disabled ? " (disabled)" : "" - ); + ohci->hcd.state); ohci_dump (ohci, 1); - if (!ohci->disabled) + if (HCD_IS_RUNNING(ohci->hcd.state)) hc_reset (ohci); remove_debug_files (ohci); @@ -649,8 +644,7 @@ int temp; int i; - ohci->disabled = 1; - ohci->sleeping = 0; + disable (ohci); if (hcd_to_bus (&ohci->hcd)->root_hub) usb_disconnect (&hcd_to_bus (&ohci->hcd)->root_hub); diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c --- a/drivers/usb/host/ohci-hub.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/host/ohci-hub.c Fri Oct 17 14:43:50 2003 @@ -73,7 +73,7 @@ ports = roothub_a (ohci) & RH_A_NDP; if (ports > MAX_ROOT_PORTS) { - if (ohci->disabled) + if (!HCD_IS_RUNNING(ohci->hcd.state)) return -ESHUTDOWN; ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, readl (&ohci->regs->roothub.a) & RH_A_NDP); diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c --- a/drivers/usb/host/ohci-pci.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/host/ohci-pci.c Fri Oct 17 14:43:50 2003 @@ -117,7 +117,6 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - unsigned long flags; u16 cmd; u32 tmp; @@ -129,16 +128,15 @@ /* act as if usb suspend can always be used */ ohci_dbg (ohci, "suspend to %d\n", state); - ohci->sleeping = 1; - + /* First stop processing */ - spin_lock_irqsave (&ohci->lock, flags); + spin_lock_irq (&ohci->lock); ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); writel (ohci->hc_control, &ohci->regs->control); writel (OHCI_INTR_SF, &ohci->regs->intrstatus); (void) readl (&ohci->regs->intrstatus); - spin_unlock_irqrestore (&ohci->lock, flags); + spin_unlock_irq (&ohci->lock); /* Wait a frame or two */ mdelay (1); @@ -156,10 +154,14 @@ &ohci->regs->intrenable); /* Suspend chip and let things settle down a bit */ + spin_lock_irq (&ohci->lock); ohci->hc_control = OHCI_USB_SUSPEND; writel (ohci->hc_control, &ohci->regs->control); (void) readl (&ohci->regs->control); - mdelay (500); /* No schedule here ! */ + spin_unlock_irq (&ohci->lock); + + set_current_state (TASK_UNINTERRUPTIBLE); + schedule_timeout (HZ/2); tmp = readl (&ohci->regs->control) | OHCI_CTRL_HCFS; switch (tmp) { @@ -199,7 +201,6 @@ struct ohci_hcd *ohci = hcd_to_ohci (hcd); int temp; int retval = 0; - unsigned long flags; #ifdef CONFIG_PMAC_PBOOK { @@ -226,6 +227,7 @@ switch (temp) { case OHCI_USB_RESET: // lost power +restart: ohci_info (ohci, "USB restart\n"); retval = hc_restart (ohci); break; @@ -235,31 +237,28 @@ ohci_info (ohci, "USB continue from %s wakeup\n", (temp == OHCI_USB_SUSPEND) ? "host" : "remote"); + + /* we "should" only need RESUME if we're SUSPENDed ... */ ohci->hc_control = OHCI_USB_RESUME; writel (ohci->hc_control, &ohci->regs->control); (void) readl (&ohci->regs->control); - mdelay (20); /* no schedule here ! */ - /* Some controllers (lucent) need a longer delay here */ - mdelay (15); + /* Some controllers (lucent) need extra-long delays */ + mdelay (35); /* no schedule here ! */ temp = readl (&ohci->regs->control); temp = ohci->hc_control & OHCI_CTRL_HCFS; if (temp != OHCI_USB_RESUME) { ohci_err (ohci, "controller won't resume\n"); - ohci->disabled = 1; - retval = -EIO; - break; + /* maybe we can reset */ + goto restart; } - /* Some chips likes being resumed first */ + /* Then re-enable operations */ writel (OHCI_USB_OPER, &ohci->regs->control); (void) readl (&ohci->regs->control); mdelay (3); - /* Then re-enable operations */ - spin_lock_irqsave (&ohci->lock, flags); - ohci->disabled = 0; - ohci->sleeping = 0; + spin_lock_irq (&ohci->lock); ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; if (!ohci->ed_rm_list) { if (ohci->ed_controltail) @@ -274,25 +273,22 @@ writel (OHCI_INTR_SF, &ohci->regs->intrstatus); writel (OHCI_INTR_SF, &ohci->regs->intrenable); - /* Check for a pending done list */ writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); (void) readl (&ohci->regs->intrdisable); - spin_unlock_irqrestore (&ohci->lock, flags); + spin_unlock_irq (&ohci->lock); #ifdef CONFIG_PMAC_PBOOK if (_machine == _MACH_Pmac) enable_irq (hcd->pdev->irq); #endif + + /* Check for a pending done list */ if (ohci->hcca->done_head) dl_done_list (ohci, dl_reverse_done_list (ohci), NULL); writel (OHCI_INTR_WDH, &ohci->regs->intrenable); /* assume there are TDs on the bulk and control lists */ writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus); - -// ohci_dump_status (ohci); -ohci_dbg (ohci, "sleeping = %d, disabled = %d\n", - ohci->sleeping, ohci->disabled); break; default: diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/host/ohci-q.c Fri Oct 17 14:43:50 2003 @@ -449,7 +449,7 @@ ohci->ed_rm_list = ed; /* enable SOF interrupt */ - if (!ohci->sleeping) { + if (HCD_IS_RUNNING (ohci->hcd.state)) { writel (OHCI_INTR_SF, &ohci->regs->intrstatus); writel (OHCI_INTR_SF, &ohci->regs->intrenable); // flush those pci writes @@ -794,7 +794,16 @@ * looks odd ... that doesn't include protocol stalls * (or maybe some other things) */ - if (cc != TD_CC_STALL || !usb_pipecontrol (urb->pipe)) + switch (cc) { + case TD_DATAUNDERRUN: + if ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0) + break; + /* fallthrough */ + case TD_CC_STALL: + if (usb_pipecontrol (urb->pipe)) + break; + /* fallthrough */ + default: ohci_dbg (ohci, "urb %p path %s ep%d%s %08x cc %d --> status %d\n", urb, urb->dev->devpath, @@ -802,6 +811,7 @@ usb_pipein (urb->pipe) ? "in" : "out", le32_to_cpu (td->hwINFO), cc, cc_to_error [cc]); + } return rev; } @@ -871,7 +881,8 @@ /* only take off EDs that the HC isn't using, accounting for * frame counter wraps. */ - if (tick_before (tick, ed->tick) && !ohci->disabled) { + if (tick_before (tick, ed->tick) + && HCD_IS_RUNNING(ohci->hcd.state)) { last = &ed->ed_next; continue; } @@ -901,7 +912,7 @@ urb = td->urb; urb_priv = td->urb->hcpriv; - if (urb_priv->state != URB_DEL) { + if (urb->status == -EINPROGRESS) { prev = &td->hwNextTD; continue; } @@ -938,7 +949,7 @@ /* but if there's work queued, reschedule */ if (!list_empty (&ed->td_list)) { - if (!ohci->disabled && !ohci->sleeping) + if (HCD_IS_RUNNING(ohci->hcd.state)) ed_schedule (ohci, ed); } @@ -947,7 +958,7 @@ } /* maybe reenable control and bulk lists */ - if (!ohci->disabled && !ohci->ed_rm_list) { + if (HCD_IS_RUNNING(ohci->hcd.state) && !ohci->ed_rm_list) { u32 command = 0, control = 0; if (ohci->ed_controltail) { diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h --- a/drivers/usb/host/ohci.h Fri Oct 17 14:43:51 2003 +++ b/drivers/usb/host/ohci.h Fri Oct 17 14:43:51 2003 @@ -314,13 +314,10 @@ struct ed *ed; __u16 length; // # tds in this request __u16 td_cnt; // tds already serviced - int state; struct td *td [0]; // all TDs in this request } urb_priv_t; -#define URB_DEL 1 - #define TD_HASH_SIZE 64 /* power'o'two */ // sizeof (struct td) ~= 64 == 2^6 ... #define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE) @@ -365,8 +362,6 @@ /* * driver state */ - int disabled; /* e.g. got a UE, we're hung */ - int sleeping; int load [NUM_INTS]; u32 hc_control; /* copy of hc control reg */ diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c --- a/drivers/usb/host/uhci-hcd.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/host/uhci-hcd.c Fri Oct 17 14:43:50 2003 @@ -2518,7 +2518,7 @@ return uhci_get_current_frame_number(hcd_to_uhci(hcd)); } -static const char hcd_name[] = "uhci-hcd"; +static const char hcd_name[] = "uhci_hcd"; static const struct hc_driver uhci_driver = { .description = hcd_name, diff -Nru a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig --- a/drivers/usb/input/Kconfig Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/input/Kconfig Fri Oct 17 14:43:50 2003 @@ -28,6 +28,7 @@ config USB_HIDINPUT bool "HID input layer support" + default y depends on INPUT && USB_HID help Say Y here if you want to use a USB keyboard, mouse or joystick, diff -Nru a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig --- a/drivers/usb/misc/Kconfig Fri Oct 17 14:43:51 2003 +++ b/drivers/usb/misc/Kconfig Fri Oct 17 14:43:51 2003 @@ -15,7 +15,7 @@ USB Audio driver. To compile this driver as a module, choose M here: the - module will be called audio. + module will be called emi26. config USB_TIGL tristate "Texas Instruments Graph Link USB (aka SilverLink) cable support" diff -Nru a/drivers/usb/serial/keyspan_usa90msg.h b/drivers/usb/serial/keyspan_usa90msg.h --- a/drivers/usb/serial/keyspan_usa90msg.h Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/serial/keyspan_usa90msg.h Fri Oct 17 14:43:50 2003 @@ -182,14 +182,14 @@ // MSR bits -#define MSR_dCTS 0x01 // CTS has changed since last report -#define MSR_dDSR 0x02 -#define MSR_dRI 0x04 -#define MSR_dDCD 0x08 +#define USA_MSR_dCTS 0x01 // CTS has changed since last report +#define USA_MSR_dDSR 0x02 +#define USA_MSR_dRI 0x04 +#define USA_MSR_dDCD 0x08 -#define MSR_CTS 0x10 // current state of CTS -#define MSR_DSR 0x20 -#define MSR_RI 0x40 +#define USA_MSR_CTS 0x10 // current state of CTS +#define USA_MSR_DSR 0x20 +#define USA_USA_MSR_RI 0x40 #define MSR_DCD 0x80 // ie: the maximum length of an endpoint buffer diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c --- a/drivers/usb/serial/visor.c Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/serial/visor.c Fri Oct 17 14:43:50 2003 @@ -201,6 +201,8 @@ .driver_info = (kernel_ulong_t)&palm_os_3_probe }, { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID), @@ -247,6 +249,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) }, + { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) }, @@ -775,9 +778,6 @@ serial->dev->actconfig->desc.bConfigurationValue); return -ENODEV; } - dbg("%s - reset config", __FUNCTION__); - retval = usb_reset_configuration (serial->dev); - if (id->driver_info) { startup = (void *)id->driver_info; diff -Nru a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h --- a/drivers/usb/serial/visor.h Fri Oct 17 14:43:50 2003 +++ b/drivers/usb/serial/visor.h Fri Oct 17 14:43:50 2003 @@ -20,6 +20,7 @@ #define HANDSPRING_VENDOR_ID 0x082d #define HANDSPRING_VISOR_ID 0x0100 #define HANDSPRING_TREO_ID 0x0200 +#define HANDSPRING_TREO600_ID 0x0300 #define PALM_VENDOR_ID 0x0830 #define PALM_M500_ID 0x0001 diff -Nru a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig --- a/drivers/usb/storage/Kconfig Fri Oct 17 14:43:51 2003 +++ b/drivers/usb/storage/Kconfig Fri Oct 17 14:43:51 2003 @@ -41,7 +41,7 @@ config USB_STORAGE_ISD200 bool "ISD-200 USB/ATA Bridge support" - depends on USB_STORAGE + depends on USB_STORAGE && BLK_DEV_IDE ---help--- Say Y here if you want to use USB Mass Store devices based on the In-Systems Design ISD-200 USB/ATA bridge. diff -Nru a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c --- a/drivers/video/aty/aty128fb.c Fri Oct 17 14:43:50 2003 +++ b/drivers/video/aty/aty128fb.c Fri Oct 17 14:43:50 2003 @@ -2041,9 +2041,9 @@ #define ATY_MIRROR_CRT_ON 0x00000002 /* out param: u32* backlight value: 0 to 15 */ -#define FBIO_ATY128_GET_MIRROR _IOR('@', 1, sizeof(__u32*)) +#define FBIO_ATY128_GET_MIRROR _IOR('@', 1, __u32*) /* in param: u32* backlight value: 0 to 15 */ -#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, sizeof(__u32*)) +#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32*) static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, struct fb_info *info) diff -Nru a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c --- a/drivers/video/imsttfb.c Fri Oct 17 14:43:50 2003 +++ b/drivers/video/imsttfb.c Fri Oct 17 14:43:50 2003 @@ -1461,6 +1461,15 @@ unsigned long addr, size; struct imstt_par *par; struct fb_info *info; +#ifdef CONFIG_PPC_OF + struct device_node *dp; + + dp = pci_device_to_OF_node(pdev); + if(dp) + printk(KERN_INFO "%s: OF name %s\n",__FUNCTION__, dp->name); + else + printk(KERN_ERR "imsttfb: no OF node for pci device\n"); +#endif /* CONFIG_PPC_OF */ size = sizeof(struct fb_info) + sizeof(struct imstt_par) + sizeof(u32) * 16; @@ -1488,6 +1497,11 @@ switch (pdev->device) { case PCI_DEVICE_ID_IMS_TT128: /* IMS,tt128mbA */ par->ramdac = IBM; +#ifdef CONFIG_PPC_OF + if (dp && ((strcmp(dp->name, "IMS,tt128mb8") == 0) || + (strcmp(dp->name, "IMS,tt128mb8A") == 0))) + par->ramdac = TVP; +#endif /* CONFIG_PPC_OF */ break; case PCI_DEVICE_ID_IMS_TT3D: /* IMS,tt3d */ par->ramdac = TVP; diff -Nru a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h --- a/drivers/video/matrox/matroxfb_base.h Fri Oct 17 14:43:50 2003 +++ b/drivers/video/matrox/matroxfb_base.h Fri Oct 17 14:43:50 2003 @@ -55,7 +55,7 @@ #if defined(CONFIG_PPC_PMAC) #include #include -#include