## Automatically generated incremental diff ## From: linux-2.5.69-bk16 ## To: linux-2.5.69-bk17 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.5.69-bk16/Makefile linux-2.5.69-bk17/Makefile --- linux-2.5.69-bk16/Makefile 2003-05-24 04:33:28.000000000 -0700 +++ linux-2.5.69-bk17/Makefile 2003-05-24 04:33:33.000000000 -0700 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 69 -EXTRAVERSION = -bk16 +EXTRAVERSION = -bk17 # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -urN linux-2.5.69-bk16/arch/i386/kernel/mpparse.c linux-2.5.69-bk17/arch/i386/kernel/mpparse.c --- linux-2.5.69-bk16/arch/i386/kernel/mpparse.c 2003-05-24 04:33:28.000000000 -0700 +++ linux-2.5.69-bk17/arch/i386/kernel/mpparse.c 2003-05-24 04:33:33.000000000 -0700 @@ -1086,7 +1086,7 @@ /* * Parsing through the PCI Interrupt Routing Table (PRT) and program - * routing for all static (IOAPIC-direct) entries. + * routing for all entries. */ list_for_each(node, &acpi_prt.entries) { entry = list_entry(node, struct acpi_prt_entry, node); @@ -1100,6 +1100,10 @@ else irq = entry->link.index; + /* Don't set up the ACPI SCI because it's already set up */ + if (acpi_fadt.sci_int == irq) + continue; + ioapic = mp_find_ioapic(irq); if (ioapic < 0) continue; diff -urN linux-2.5.69-bk16/arch/x86_64/Kconfig linux-2.5.69-bk17/arch/x86_64/Kconfig --- linux-2.5.69-bk16/arch/x86_64/Kconfig 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/Kconfig 2003-05-24 04:33:33.000000000 -0700 @@ -652,6 +652,7 @@ config IOMMU_LEAK bool "IOMMU leak tracing" depends on DEBUG_KERNEL + depends on IOMMU_DEBUG help Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. diff -urN linux-2.5.69-bk16/arch/x86_64/Makefile linux-2.5.69-bk17/arch/x86_64/Makefile --- linux-2.5.69-bk16/arch/x86_64/Makefile 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/Makefile 2003-05-24 04:33:33.000000000 -0700 @@ -46,6 +46,7 @@ CFLAGS += -fno-reorder-blocks # should lower this a lot and see how much .text is saves CFLAGS += -finline-limit=2000 +CFLAGS += -Wno-sign-compare #CFLAGS += -g # don't enable this when you use kgdb: ifneq ($(CONFIG_X86_REMOTE_DEBUG),y) diff -urN linux-2.5.69-bk16/arch/x86_64/defconfig linux-2.5.69-bk17/arch/x86_64/defconfig --- linux-2.5.69-bk16/arch/x86_64/defconfig 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/defconfig 2003-05-24 04:33:33.000000000 -0700 @@ -4,7 +4,6 @@ CONFIG_X86_64=y CONFIG_X86=y CONFIG_MMU=y -CONFIG_SWAP=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_X86_CMPXCHG=y CONFIG_EARLY_PRINTK=y @@ -18,6 +17,7 @@ # # General setup # +CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y @@ -47,8 +47,12 @@ CONFIG_X86_IO_APIC=y CONFIG_X86_LOCAL_APIC=y CONFIG_MTRR=y -CONFIG_HUGETLB_PAGE=y +# CONFIG_HUGETLB_PAGE is not set CONFIG_SMP=y +# CONFIG_PREEMPT is not set +CONFIG_K8_NUMA=y +CONFIG_DISCONTIGMEM=y +CONFIG_NUMA=y CONFIG_HAVE_DEC_LOCK=y CONFIG_NR_CPUS=8 CONFIG_GART_IOMMU=y @@ -222,9 +226,8 @@ # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y +# CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set -CONFIG_FILTER=y CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -239,8 +242,9 @@ # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set -# CONFIG_XFRM_USER is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set # # SCTP Configuration (EXPERIMENTAL) @@ -331,6 +335,11 @@ # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set CONFIG_TIGON3=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PPP is not set @@ -405,15 +414,7 @@ CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y # CONFIG_MOUSE_SERIAL is not set -CONFIG_INPUT_JOYSTICK=y -# CONFIG_JOYSTICK_IFORCE is not set -# CONFIG_JOYSTICK_WARRIOR is not set -# CONFIG_JOYSTICK_MAGELLAN is not set -# CONFIG_JOYSTICK_SPACEORB is not set -# CONFIG_JOYSTICK_SPACEBALL is not set -# CONFIG_JOYSTICK_STINGER is not set -# CONFIG_JOYSTICK_TWIDDLER is not set -# CONFIG_INPUT_JOYDUMP is not set +# CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -452,6 +453,7 @@ # # I2C Hardware Sensors Chip support # +# CONFIG_I2C_SENSOR is not set # # Mice @@ -468,8 +470,7 @@ # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_AMD_RNG is not set +CONFIG_HW_RANDOM=y # CONFIG_NVRAM is not set CONFIG_RTC=y # CONFIG_DTLK is not set @@ -481,8 +482,8 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_AGP_GART is not set +CONFIG_AGP=y +CONFIG_AGP_AMD_8151=y # CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y @@ -498,57 +499,75 @@ # 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=y -# CONFIG_AUTOFS4_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set CONFIG_REISERFS_FS=y # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_XFS_FS=m +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# 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_TMPFS=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS 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_EXT3_FS=y -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_HUGETLBFS=y -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_JFS_FS is not set -# CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set # CONFIG_UFS_FS is not set -CONFIG_XFS_FS=m -# CONFIG_XFS_RT is not set -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_POSIX_ACL is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V4 is not set @@ -556,14 +575,16 @@ CONFIG_NFSD_V3=y # CONFIG_NFSD_V4 is not set CONFIG_NFSD_TCP=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y -# CONFIG_CIFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -594,6 +615,7 @@ # USB support # # CONFIG_USB is not set +# CONFIG_USB_GADGET is not set # # Bluetooth support @@ -615,6 +637,9 @@ # CONFIG_INIT_DEBUG is not set CONFIG_KALLSYMS=y # CONFIG_FRAME_POINTER is not set +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_LEAK=y +CONFIG_MCE_DEBUG=y # # Security options diff -urN linux-2.5.69-bk16/arch/x86_64/ia32/Makefile linux-2.5.69-bk17/arch/x86_64/ia32/Makefile --- linux-2.5.69-bk16/arch/x86_64/ia32/Makefile 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/ia32/Makefile 2003-05-24 04:33:33.000000000 -0700 @@ -5,3 +5,12 @@ obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \ ia32_signal.o tls32.o \ ia32_binfmt.o fpu32.o ptrace32.o ipc32.o syscall32.o + +$(obj)/syscall32.o: $(src)/syscall32.c $(obj)/vsyscall.so + +# The DSO images are built using a special linker script. +$(obj)/vsyscall.so: $(src)/vsyscall.lds $(obj)/vsyscall.o + $(CC) -m32 -nostdlib -shared -s -Wl,-soname=linux-vsyscall.so.1 \ + -o $@ -Wl,-T,$^ + +AFLAGS_vsyscall.o = -m32 diff -urN linux-2.5.69-bk16/arch/x86_64/ia32/ia32_binfmt.c linux-2.5.69-bk17/arch/x86_64/ia32/ia32_binfmt.c --- linux-2.5.69-bk16/arch/x86_64/ia32/ia32_binfmt.c 2003-05-24 04:33:28.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/ia32/ia32_binfmt.c 2003-05-24 04:33:33.000000000 -0700 @@ -6,11 +6,11 @@ * of ugly preprocessor tricks. Talk about very very poor man's inheritance. */ #include -#include #include #include #include #include +#include #include #include #include @@ -23,12 +23,17 @@ #include #include #include +#include #define ELF_NAME "elf/i386" #define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 -#define ARCH_DLINFO NEW_AUX_ENT(AT_SYSINFO, 0xffffe000) +#define ARCH_DLINFO do { \ + NEW_AUX_ENT(AT_SYSINFO, (u32)(u64)VSYSCALL32_VSYSCALL); \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL32_BASE); \ +} while(0) struct file; struct elf_phdr; @@ -54,6 +59,47 @@ #define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t)) typedef elf_greg_t elf_gregset_t[ELF_NGREG]; +/* + * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out + * extra segments containing the vsyscall DSO contents. Dumping its + * contents makes post-mortem fully interpretable later without matching up + * the same kernel and hardware config to see what PC values meant. + * Dumping its extra ELF program headers includes all the other information + * a debugger needs to easily find how the vsyscall DSO was being used. + */ +#define ELF_CORE_EXTRA_PHDRS (VSYSCALL32_EHDR->e_phnum) +#define ELF_CORE_WRITE_EXTRA_PHDRS \ +do { \ + const struct elf32_phdr *const vsyscall_phdrs = \ + (const struct elf32_phdr *) (VSYSCALL32_BASE \ + + VSYSCALL32_EHDR->e_phoff); \ + int i; \ + Elf32_Off ofs = 0; \ + for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ + struct elf_phdr phdr = vsyscall_phdrs[i]; \ + if (phdr.p_type == PT_LOAD) { \ + ofs = phdr.p_offset = offset; \ + offset += phdr.p_filesz; \ + } \ + else \ + phdr.p_offset += ofs; \ + phdr.p_paddr = 0; /* match other core phdrs */ \ + DUMP_WRITE(&phdr, sizeof(phdr)); \ + } \ +} while (0) +#define ELF_CORE_WRITE_EXTRA_DATA \ +do { \ + const struct elf32_phdr *const vsyscall_phdrs = \ + (const struct elf32_phdr *) (VSYSCALL32_BASE \ + + VSYSCALL32_EHDR->e_phoff); \ + int i; \ + for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ + if (vsyscall_phdrs[i].p_type == PT_LOAD) \ + DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr, \ + vsyscall_phdrs[i].p_filesz); \ + } \ +} while (0) + struct elf_siginfo { int si_signo; /* signal number */ @@ -157,7 +203,6 @@ struct _fpstate_ia32 *fpstate = (void*)fpu; struct pt_regs *regs = (struct pt_regs *)(tsk->thread.rsp0); mm_segment_t oldfs = get_fs(); - int ret; if (!tsk->used_math) return 0; @@ -165,12 +210,12 @@ if (tsk == current) unlazy_fpu(tsk); set_fs(KERNEL_DS); - ret = save_i387_ia32(tsk, fpstate, regs, 1); + save_i387_ia32(tsk, fpstate, regs, 1); /* Correct for i386 bug. It puts the fop into the upper 16bits of the tag word (like FXSAVE), not into the fcs*/ fpstate->cssel |= fpstate->tag & 0xffff0000; set_fs(oldfs); - return ret; + return 1; } #define ELF_CORE_COPY_XFPREGS 1 @@ -302,8 +347,9 @@ mpnt->vm_mm = mm; mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; mpnt->vm_end = IA32_STACK_TOP; - mpnt->vm_page_prot = PAGE_COPY_EXEC; - mpnt->vm_flags = VM_STACK_FLAGS; + mpnt->vm_flags = vm_stack_flags32; + mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? + PAGE_COPY_EXEC : PAGE_COPY; mpnt->vm_ops = NULL; mpnt->vm_pgoff = 0; mpnt->vm_file = NULL; @@ -333,7 +379,7 @@ struct task_struct *me = current; if (prot & PROT_READ) - prot |= PROT_EXEC; + prot |= vm_force_exec32; down_write(&me->mm->mmap_sem); map_addr = do_mmap(filep, ELF_PAGESTART(addr), diff -urN linux-2.5.69-bk16/arch/x86_64/ia32/ia32_ioctl.c linux-2.5.69-bk17/arch/x86_64/ia32/ia32_ioctl.c --- linux-2.5.69-bk16/arch/x86_64/ia32/ia32_ioctl.c 2003-05-24 04:33:28.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/ia32/ia32_ioctl.c 2003-05-24 04:33:33.000000000 -0700 @@ -10,10 +10,10 @@ */ #include +#include #include #include #include -#include #include #include #include @@ -108,10 +108,6 @@ #include - -#define A(__x) ((void *)(unsigned long)(__x)) -#define AA(__x) A(__x) - /* Aiee. Someone does not find a difference between int and long */ #define EXT2_IOC32_GETFLAGS _IOR('f', 1, int) #define EXT2_IOC32_SETFLAGS _IOW('f', 2, int) @@ -163,10 +159,10 @@ } struct video_tuner32 { - s32 tuner; - u8 name[32]; - u32 rangelow, rangehigh; - u32 flags; + compat_int_t tuner; + char name[32]; + compat_ulong_t rangelow, rangehigh; + u32 flags; /* It is really u32 in videodev.h */ u16 mode, signal; }; @@ -203,8 +199,8 @@ } struct video_buffer32 { - /* void * */ u32 base; - s32 height, width, depth, bytesperline; + compat_caddr_t base; + compat_int_t height, width, depth, bytesperline; }; static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up) @@ -235,14 +231,14 @@ } struct video_clip32 { - s32 x, y, width, height; - /* struct video_clip32 * */ u32 next; + s32 x, y, width, height; /* Its really s32 in videodev.h */ + compat_caddr_t next; }; struct video_window32 { u32 x, y, width, height, chromakey, flags; - /* struct video_clip32 * */ u32 clips; - s32 clipcount; + compat_caddr_t clips; + compat_int_t clipcount; }; static void free_kvideo_clips(struct video_window *kp) @@ -270,7 +266,7 @@ __get_user(kp->flags, &up->flags); __get_user(kp->clipcount, &up->clipcount); __get_user(tmp, &up->clips); - ucp = (struct video_clip32 *)A(tmp); + ucp = compat_ptr(tmp); kp->clips = NULL; nclips = kp->clipcount; @@ -421,8 +417,8 @@ } struct ifmap32 { - u32 mem_start; - u32 mem_end; + compat_ulong_t mem_start; + compat_ulong_t mem_end; unsigned short base_addr; unsigned char irq; unsigned char dma; @@ -442,17 +438,18 @@ struct sockaddr ifru_netmask; struct sockaddr ifru_hwaddr; short ifru_flags; - int ifru_ivalue; - int ifru_mtu; + compat_int_t ifru_ivalue; + compat_int_t ifru_mtu; struct ifmap32 ifru_map; char ifru_slave[IFNAMSIZ]; /* Just fits the size */ char ifru_newname[IFNAMSIZ]; compat_caddr_t ifru_data; + /* XXXX? ifru_settings should be here */ } ifr_ifru; }; struct ifconf32 { - int ifc_len; /* size of buffer */ + compat_int_t ifc_len; /* size of buffer */ compat_caddr_t ifcbuf; }; @@ -504,7 +501,7 @@ return -ENOMEM; } ifr = ifc.ifc_req; - ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); + ifr32 = compat_ptr(ifc32.ifcbuf); for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { if (copy_from_user(ifr, ifr32, sizeof (struct ifreq32))) { kfree (ifc.ifc_buf); @@ -518,7 +515,7 @@ set_fs (old_fs); if (!err) { ifr = ifc.ifc_req; - ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); + ifr32 = compat_ptr(ifc32.ifcbuf); for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len; i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { int k = copy_to_user(ifr32, ifr, sizeof (struct ifreq32)); @@ -568,7 +565,7 @@ __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - if (get_user(ethcmd, (u32 *)A(data))) { + if (get_user(ethcmd, (u32 *)compat_ptr(data))) { err = -EFAULT; goto out; } @@ -579,12 +576,16 @@ case ETHTOOL_GLINK: case ETHTOOL_NWAY_RST: len = sizeof(struct ethtool_value); break; case ETHTOOL_GREGS: { - struct ethtool_regs *regaddr = (struct ethtool_regs *)A(data); + struct ethtool_regs *regaddr = compat_ptr(data); /* darned variable size arguments */ if (get_user(len, (u32 *)®addr->len)) { err = -EFAULT; goto out; } + if (len > PAGE_SIZE - sizeof(struct ethtool_regs)) { + err = -EINVAL; + goto out; + } len += sizeof(struct ethtool_regs); break; } @@ -595,7 +596,7 @@ goto out; } - if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { + if (copy_from_user(ifr.ifr_data, compat_ptr(data), len)) { err = -EFAULT; goto out; } @@ -608,7 +609,7 @@ u32 data; __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - len = copy_to_user((char *)A(data), ifr.ifr_data, len); + len = copy_to_user(compat_ptr(data), ifr.ifr_data, len); if (len) err = -EFAULT; } @@ -651,7 +652,7 @@ }; __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { + if (copy_from_user(ifr.ifr_data, compat_ptr(data), len)) { err = -EFAULT; goto out; } @@ -661,7 +662,7 @@ err = sys_ioctl (fd, cmd, (unsigned long)&ifr); set_fs (old_fs); if (!err) { - len = copy_to_user((char *)A(data), ifr.ifr_data, len); + len = copy_to_user(compat_ptr(data), ifr.ifr_data, len); if (len) err = -EFAULT; } @@ -684,7 +685,7 @@ return -EFAULT; if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) return -EFAULT; - data64 = (void *) A(data32); + data64 = compat_ptr(data32); u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); @@ -821,7 +822,7 @@ ret |= __get_user (r4.rt_irtt, &(((struct rtentry32 *)arg)->rt_irtt)); ret |= __get_user (rtdev, &(((struct rtentry32 *)arg)->rt_dev)); if (rtdev) { - ret |= copy_from_user (devname, (char *)A(rtdev), 15); + ret |= copy_from_user (devname, compat_ptr(rtdev), 15); r4.rt_dev = devname; devname[15] = 0; } else r4.rt_dev = 0; @@ -868,23 +869,23 @@ struct fb_fix_screeninfo32 { char id[16]; compat_caddr_t smem_start; - __u32 smem_len; - __u32 type; - __u32 type_aux; - __u32 visual; - __u16 xpanstep; - __u16 ypanstep; - __u16 ywrapstep; - __u32 line_length; + u32 smem_len; + u32 type; + u32 type_aux; + u32 visual; + u16 xpanstep; + u16 ypanstep; + u16 ywrapstep; + u32 line_length; compat_caddr_t mmio_start; - __u32 mmio_len; - __u32 accel; - __u16 reserved[3]; + u32 mmio_len; + u32 accel; + u16 reserved[3]; }; struct fb_cmap32 { - __u32 start; - __u32 len; + u32 start; + u32 len; compat_caddr_t red; compat_caddr_t green; compat_caddr_t blue; @@ -918,6 +919,10 @@ err = -EFAULT; goto out; } + if (cmap.len > PAGE_SIZE/sizeof(u16)) { + err = -EINVAL; + goto out; + } err = -ENOMEM; cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); if (!cmap.red) @@ -937,10 +942,10 @@ if (cmd == FBIOGETCMAP) break; - err = __copy_from_user(cmap.red, (char *)A(red), cmap.len * sizeof(__u16)); - err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16)); - err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16)); - if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16)); + err = __copy_from_user(cmap.red, compat_ptr(red), cmap.len * sizeof(__u16)); + err |= __copy_from_user(cmap.green, compat_ptr(green), cmap.len * sizeof(__u16)); + err |= __copy_from_user(cmap.blue, compat_ptr(blue), cmap.len * sizeof(__u16)); + if (cmap.transp) err |= __copy_from_user(cmap.transp, compat_ptr(transp), cmap.len * sizeof(__u16)); if (err) { err = -EFAULT; goto out; @@ -979,11 +984,11 @@ err |= __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->reserved, (char *)fix.reserved, sizeof(fix.reserved)); break; case FBIOGETCMAP: - err = __copy_to_user((char *)A(red), cmap.red, cmap.len * sizeof(__u16)); - err |= __copy_to_user((char *)A(green), cmap.blue, cmap.len * sizeof(__u16)); - err |= __copy_to_user((char *)A(blue), cmap.blue, cmap.len * sizeof(__u16)); + err = __copy_to_user(compat_ptr(red), cmap.red, cmap.len * sizeof(__u16)); + err |= __copy_to_user(compat_ptr(green), cmap.blue, cmap.len * sizeof(__u16)); + err |= __copy_to_user(compat_ptr(blue), cmap.blue, cmap.len * sizeof(__u16)); if (cmap.transp) - err |= __copy_to_user((char *)A(transp), cmap.transp, cmap.len * sizeof(__u16)); + err |= __copy_to_user(compat_ptr(transp), cmap.transp, cmap.len * sizeof(__u16)); break; case FBIOPUTCMAP: break; @@ -1018,11 +1023,11 @@ } struct floppy_struct32 { - unsigned int size; - unsigned int sect; - unsigned int head; - unsigned int track; - unsigned int stretch; + compat_uint_t size; + compat_uint_t sect; + compat_uint_t head; + compat_uint_t track; + compat_uint_t stretch; unsigned char gap; unsigned char rate; unsigned char spec1; @@ -1032,51 +1037,51 @@ struct floppy_drive_params32 { char cmos; - u32 max_dtr; - u32 hlt; - u32 hut; - u32 srt; - u32 spinup; - u32 spindown; + compat_ulong_t max_dtr; + compat_ulong_t hlt; + compat_ulong_t hut; + compat_ulong_t srt; + compat_ulong_t spinup; + compat_ulong_t spindown; unsigned char spindown_offset; unsigned char select_delay; unsigned char rps; unsigned char tracks; - u32 timeout; + compat_ulong_t timeout; unsigned char interleave_sect; struct floppy_max_errors max_errors; char flags; char read_track; short autodetect[8]; - int checkfreq; - int native_format; + compat_int_t checkfreq; + compat_int_t native_format; }; struct floppy_drive_struct32 { signed char flags; - u32 spinup_date; - u32 select_date; - u32 first_read_date; + compat_ulong_t spinup_date; + compat_ulong_t select_date; + compat_ulong_t first_read_date; short probed_format; short track; short maxblock; short maxtrack; - int generation; - int keep_data; - int fd_ref; - int fd_device; - int last_checked; + compat_int_t generation; + compat_int_t keep_data; + compat_int_t fd_ref; + compat_int_t fd_device; + compat_int_t last_checked; compat_caddr_t dmabuf; - int bufblocks; + compat_int_t bufblocks; }; struct floppy_fdc_state32 { - int spec1; - int spec2; - int dtr; + compat_int_t spec1; + compat_int_t spec2; + compat_int_t dtr; unsigned char version; unsigned char dor; - u32 address; + compat_ulong_t address; unsigned int rawcmd:2; unsigned int reset:1; unsigned int need_configure:1; @@ -1088,11 +1093,11 @@ struct floppy_write_errors32 { unsigned int write_errors; - u32 first_error_sector; - int first_error_generation; - u32 last_error_sector; - int last_error_generation; - unsigned int badness; + compat_ulong_t first_error_sector; + compat_int_t first_error_generation; + compat_ulong_t last_error_sector; + compat_int_t last_error_generation; + compat_uint_t badness; }; #define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32) @@ -1329,42 +1334,46 @@ typedef struct sg_io_hdr32 { - s32 interface_id; /* [i] 'S' for SCSI generic (required) */ - s32 dxfer_direction; /* [i] data transfer direction */ - u8 cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ - u8 mx_sb_len; /* [i] max length to write to sbp */ - u16 iovec_count; /* [i] 0 implies no scatter gather */ - u32 dxfer_len; /* [i] byte count of data transfer */ - u32 dxferp; /* [i], [*io] points to data transfer memory + compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ + compat_int_t dxfer_direction; /* [i] data transfer direction */ + unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + unsigned char mx_sb_len; /* [i] max length to write to sbp */ + unsigned short iovec_count; /* [i] 0 implies no scatter gather */ + compat_uint_t dxfer_len; /* [i] byte count of data transfer */ + compat_uint_t dxferp; /* [i], [*io] points to data transfer memory or scatter gather list */ - u32 cmdp; /* [i], [*i] points to command to perform */ - u32 sbp; /* [i], [*o] points to sense_buffer memory */ - u32 timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ - u32 flags; /* [i] 0 -> default, see SG_FLAG... */ - s32 pack_id; /* [i->o] unused internally (normally) */ - u32 usr_ptr; /* [i->o] unused internally */ - u8 status; /* [o] scsi status */ - u8 masked_status; /* [o] shifted, masked scsi status */ - u8 msg_status; /* [o] messaging level data (optional) */ - u8 sb_len_wr; /* [o] byte count actually written to sbp */ - u16 host_status; /* [o] errors from host adapter */ - u16 driver_status; /* [o] errors from software driver */ - s32 resid; /* [o] dxfer_len - actual_transferred */ - u32 duration; /* [o] time taken by cmd (unit: millisec) */ - u32 info; /* [o] auxiliary information */ + compat_uptr_t cmdp; /* [i], [*i] points to command to perform */ + compat_uptr_t sbp; /* [i], [*o] points to sense_buffer memory */ + compat_uint_t timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ + compat_uint_t flags; /* [i] 0 -> default, see SG_FLAG... */ + compat_int_t pack_id; /* [i->o] unused internally (normally) */ + compat_uptr_t usr_ptr; /* [i->o] unused internally */ + unsigned char status; /* [o] scsi status */ + unsigned char masked_status; /* [o] shifted, masked scsi status */ + unsigned char msg_status; /* [o] messaging level data (optional) */ + unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ + unsigned short host_status; /* [o] errors from host adapter */ + unsigned short driver_status; /* [o] errors from software driver */ + compat_int_t resid; /* [o] dxfer_len - actual_transferred */ + compat_uint_t duration; /* [o] time taken by cmd (unit: millisec) */ + compat_uint_t info; /* [o] auxiliary information */ } sg_io_hdr32_t; /* 64 bytes long (on sparc32) */ typedef struct sg_iovec32 { - u32 iov_base; - u32 iov_len; + compat_uint_t iov_base; + compat_uint_t iov_len; } sg_iovec32_t; +#define EMU_SG_MAX 128 + static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32) { - sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); + sg_iovec32_t *uiov = compat_ptr(uptr32); sg_iovec_t *kiov; int i; + if (sgp->iovec_count > EMU_SG_MAX) + return -EINVAL; sgp->dxferp = kmalloc(sgp->iovec_count * sizeof(sg_iovec_t), GFP_KERNEL); if (!sgp->dxferp) @@ -1378,39 +1387,9 @@ if (__get_user(iov_base32, &uiov->iov_base) || __get_user(kiov->iov_len, &uiov->iov_len)) return -EFAULT; - - kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL); - if (!kiov->iov_base) - return -ENOMEM; - if (copy_from_user(kiov->iov_base, - (void *) A(iov_base32), - kiov->iov_len)) + if (verify_area(VERIFY_WRITE, compat_ptr(iov_base32), kiov->iov_len)) return -EFAULT; - - uiov++; - kiov++; - } - - return 0; -} - -static int copy_back_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32) -{ - sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); - sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; - int i; - - for (i = 0; i < sgp->iovec_count; i++) { - u32 iov_base32; - - if (__get_user(iov_base32, &uiov->iov_base)) - return -EFAULT; - - if (copy_to_user((void *) A(iov_base32), - kiov->iov_base, - kiov->iov_len)) - return -EFAULT; - + kiov->iov_base = compat_ptr(iov_base32); uiov++; kiov++; } @@ -1420,16 +1399,6 @@ static void free_sg_iovec(sg_io_hdr_t *sgp) { - sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; - int i; - - for (i = 0; i < sgp->iovec_count; i++) { - if (kiov->iov_base) { - kfree(kiov->iov_base); - kiov->iov_base = NULL; - } - kiov++; - } kfree(sgp->dxferp); sgp->dxferp = NULL; } @@ -1459,12 +1428,8 @@ err |= __get_user(cmdp32, &sg_io32->cmdp); sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL); - if (!sg_io64.cmdp) { - err = -ENOMEM; - goto out; - } if (copy_from_user(sg_io64.cmdp, - (void *) A(cmdp32), + compat_ptr(cmdp32), sg_io64.cmd_len)) { err = -EFAULT; goto out; @@ -1477,7 +1442,7 @@ goto out; } if (copy_from_user(sg_io64.sbp, - (void *) A(sbp32), + compat_ptr(sbp32), sg_io64.mx_sb_len)) { err = -EFAULT; goto out; @@ -1492,17 +1457,11 @@ goto out; } } else { - sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL); - if (!sg_io64.dxferp) { - err = -ENOMEM; + err = verify_area(VERIFY_WRITE, compat_ptr(dxferp32), sg_io64.dxfer_len); + if (err) goto out; - } - if (copy_from_user(sg_io64.dxferp, - (void *) A(dxferp32), - sg_io64.dxfer_len)) { - err = -EFAULT; - goto out; - } + + sg_io64.dxferp = compat_ptr(dxferp32); } /* Unused internally, do not even bother to copy it over. */ @@ -1529,15 +1488,7 @@ err |= __put_user(sg_io64.resid, &sg_io32->resid); err |= __put_user(sg_io64.duration, &sg_io32->duration); err |= __put_user(sg_io64.info, &sg_io32->info); - err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len); - if (sg_io64.dxferp) { - if (sg_io64.iovec_count) - err |= copy_back_sg_iovec(&sg_io64, dxferp32); - else - err |= copy_to_user((void *)A(dxferp32), - sg_io64.dxferp, - sg_io64.dxfer_len); - } + err |= copy_to_user(compat_ptr(sbp32), sg_io64.sbp, sg_io64.mx_sb_len); if (err) err = -EFAULT; @@ -1546,19 +1497,14 @@ kfree(sg_io64.cmdp); if (sg_io64.sbp) kfree(sg_io64.sbp); - if (sg_io64.dxferp) { - if (sg_io64.iovec_count) { + if (sg_io64.dxferp && sg_io64.iovec_count) free_sg_iovec(&sg_io64); - } else { - kfree(sg_io64.dxferp); - } - } return err; } struct sock_fprog32 { - __u16 len; - __u32 filter; + unsigned short len; + compat_caddr_t filter; }; #define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32) @@ -1576,7 +1522,7 @@ get_user(fptr32, &u_fprog32->filter)) return -EFAULT; - fptr64 = (void *) A(fptr32); + fptr64 = compat_ptr(fptr32); if (put_user(flen, &u_fprog64->len) || put_user(fptr64, &u_fprog64->filter)) @@ -1592,8 +1538,8 @@ struct ppp_option_data32 { compat_caddr_t ptr; - __u32 length; - int transmit; + u32 length; + compat_int_t transmit; }; #define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32) @@ -1622,10 +1568,12 @@ case PPPIOCSCOMPRESS32: if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32))) return -EFAULT; + if (data32.length > PAGE_SIZE) + return -EINVAL; data.ptr = kmalloc (data32.length, GFP_KERNEL); if (!data.ptr) return -ENOMEM; - if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) { + if (copy_from_user(data.ptr, compat_ptr(data32.ptr), data32.length)) { kfree(data.ptr); return -EFAULT; } @@ -1667,40 +1615,40 @@ struct mtget32 { - __u32 mt_type; - __u32 mt_resid; - __u32 mt_dsreg; - __u32 mt_gstat; - __u32 mt_erreg; + compat_long_t mt_type; + compat_long_t mt_resid; + compat_long_t mt_dsreg; + compat_long_t mt_gstat; + compat_long_t mt_erreg; compat_daddr_t mt_fileno; compat_daddr_t mt_blkno; }; #define MTIOCGET32 _IOR('m', 2, struct mtget32) struct mtpos32 { - __u32 mt_blkno; + compat_long_t mt_blkno; }; #define MTIOCPOS32 _IOR('m', 3, struct mtpos32) struct mtconfiginfo32 { - __u32 mt_type; - __u32 ifc_type; - __u16 irqnr; - __u16 dmanr; - __u16 port; - __u32 debug; - __u32 have_dens:1; - __u32 have_bsf:1; - __u32 have_fsr:1; - __u32 have_bsr:1; - __u32 have_eod:1; - __u32 have_seek:1; - __u32 have_tell:1; - __u32 have_ras1:1; - __u32 have_ras2:1; - __u32 have_ras3:1; - __u32 have_qfa:1; - __u32 pad1:5; + compat_long_t mt_type; + compat_long_t ifc_type; + unsigned short irqnr; + unsigned short dmanr; + unsigned short port; + compat_ulong_t debug; + compat_uint_t have_dens:1; + compat_uint_t have_bsf:1; + compat_uint_t have_fsr:1; + compat_uint_t have_bsr:1; + compat_uint_t have_eod:1; + compat_uint_t have_seek:1; + compat_uint_t have_tell:1; + compat_uint_t have_ras1:1; + compat_uint_t have_ras2:1; + compat_uint_t have_ras3:1; + compat_uint_t have_qfa:1; + compat_uint_t pad1:5; char reserved[10]; }; #define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32) @@ -1790,25 +1738,25 @@ } struct cdrom_read32 { - int cdread_lba; + compat_int_t cdread_lba; compat_caddr_t cdread_bufaddr; - int cdread_buflen; + compat_int_t cdread_buflen; }; struct cdrom_read_audio32 { union cdrom_addr addr; - u_char addr_format; - int nframes; + u8 addr_format; + compat_int_t nframes; compat_caddr_t buf; }; struct cdrom_generic_command32 { unsigned char cmd[CDROM_PACKET_SIZE]; compat_caddr_t buffer; - unsigned int buflen; - int stat; + compat_uint_t buflen; + compat_int_t stat; compat_caddr_t sense; - compat_caddr_t reserved[3]; + compat_caddr_t reserved[3]; /* Oops? it has data_direction, quiet and timeout fields? */ }; static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) @@ -1833,10 +1781,9 @@ err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen); if (err) return -EFAULT; - data = kmalloc(cdread.cdread_buflen, GFP_KERNEL); - if (!data) - return -ENOMEM; - cdread.cdread_bufaddr = data; + if (verify_area(VERIFY_WRITE, compat_ptr(addr), cdread.cdread_buflen)) + return -EFAULT; + cdread.cdread_bufaddr = compat_ptr(addr); break; case CDROMREADAUDIO: karg = &cdreadaudio; @@ -1846,10 +1793,11 @@ err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf); if (err) return -EFAULT; - data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL); - if (!data) - return -ENOMEM; - cdreadaudio.buf = data; + + + if (verify_area(VERIFY_WRITE, compat_ptr(addr), cdreadaudio.nframes*2352)) + return -EFAULT; + cdreadaudio.buf = compat_ptr(addr); break; case CDROM_SEND_PACKET: karg = &cgc; @@ -1858,9 +1806,9 @@ err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen); if (err) return -EFAULT; - if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL) - return -ENOMEM; - cgc.buffer = data; + if (verify_area(VERIFY_WRITE, compat_ptr(addr), cgc.buflen)) + return -EFAULT; + cgc.buffer = compat_ptr(addr); break; default: do { @@ -1875,41 +1823,23 @@ set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)karg); set_fs (old_fs); - if (err) - goto out; - switch (cmd) { - case CDROMREADMODE2: - case CDROMREADMODE1: - case CDROMREADRAW: - case CDROMREADCOOKED: - err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen); - break; - case CDROMREADAUDIO: - err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352); - break; - case CDROM_SEND_PACKET: - err = copy_to_user((char *)A(addr), data, cgc.buflen); - break; - default: - break; - } -out: if (data) + if (data) kfree(data); return err ? -EFAULT : 0; } struct loop_info32 { - int lo_number; /* ioctl r/o */ + compat_int_t lo_number; /* ioctl r/o */ compat_dev_t lo_device; /* ioctl r/o */ - unsigned int lo_inode; /* ioctl r/o */ + compat_ulong_t lo_inode; /* ioctl r/o */ compat_dev_t lo_rdevice; /* ioctl r/o */ - int lo_offset; - int lo_encrypt_type; - int lo_encrypt_key_size; /* ioctl w/o */ - int lo_flags; /* ioctl r/o */ + compat_int_t lo_offset; + compat_int_t lo_encrypt_type; + compat_int_t lo_encrypt_key_size; /* ioctl w/o */ + compat_int_t lo_flags; /* ioctl r/o */ char lo_name[LO_NAME_SIZE]; unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ - unsigned int lo_init[2]; + compat_ulong_t lo_init[2]; char reserved[4]; }; @@ -1925,6 +1855,7 @@ err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); + err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset, 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); if (err) { @@ -1990,7 +1921,7 @@ struct consolefontdesc32 { unsigned short charcount; /* characters in font (256 or 512) */ unsigned short charheight; /* scan lines per character (1-32) */ - u32 chardata; /* font data in expanded form */ + compat_caddr_t chardata; /* font data in expanded form */ }; static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file) @@ -2005,7 +1936,7 @@ if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32))) return -EFAULT; - cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata); + cfdarg.chardata = compat_ptr(((struct consolefontdesc32 *)&cfdarg)->chardata); switch (cmd) { case PIO_FONTX: @@ -2041,11 +1972,11 @@ } struct console_font_op32 { - unsigned int op; /* operation code KD_FONT_OP_* */ - unsigned int flags; /* KD_FONT_FLAG_* */ - unsigned int width, height; /* font size */ - unsigned int charcount; - u32 data; /* font data with height fixed to 32 */ + compat_uint_t op; /* operation code KD_FONT_OP_* */ + compat_uint_t flags; /* KD_FONT_FLAG_* */ + compat_uint_t width, height; /* font size */ + compat_uint_t charcount; + compat_caddr_t data; /* font data with height fixed to 32 */ }; static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file) @@ -2060,7 +1991,7 @@ return -EFAULT; if (!perm && op.op != KD_FONT_OP_GET) return -EPERM; - op.data = (unsigned char *)A(((struct console_font_op32 *)&op)->data); + op.data = compat_ptr(((struct console_font_op32 *)&op)->data); op.flags |= KD_FONT_FLAG_OLD; vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data; i = con_font_op(vt->vc_num, &op); @@ -2073,7 +2004,7 @@ struct unimapdesc32 { unsigned short entry_ct; - u32 entries; + compat_caddr_t entries; }; static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, struct unimapdesc32 *user_ud, struct file *file) @@ -2087,9 +2018,9 @@ switch (cmd) { case PIO_UNIMAP: if (!perm) return -EPERM; - return con_set_unimap(fg_console, tmp.entry_ct, (struct unipair *)A(tmp.entries)); + return con_set_unimap(fg_console, tmp.entry_ct, compat_ptr(tmp.entries)); case GIO_UNIMAP: - return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), (struct unipair *)A(tmp.entries)); + return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries)); } return 0; } @@ -2113,13 +2044,13 @@ } struct atmif_sioc32 { - int number; - int length; + compat_int_t number; + compat_int_t length; compat_caddr_t arg; }; struct atm_iobuf32 { - int length; + compat_int_t length; compat_caddr_t buffer; }; @@ -2184,38 +2115,17 @@ if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) { iobuf.buffer = (void*)(unsigned long)iobuf32.buffer; } else { - iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL); - if (iobuf.buffer == NULL) { - err = -ENOMEM; - goto out; - } - - err = copy_from_user(iobuf.buffer, A(iobuf32.buffer), iobuf.length); - if (err) { - err = -EFAULT; - goto out; - } + iobuf.buffer = compat_ptr(iobuf32.buffer); + if (verify_area(VERIFY_WRITE, iobuf.buffer, iobuf.length)) + return -EINVAL; } old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)&iobuf); set_fs (old_fs); - if(err) - goto out; - - if(iobuf.buffer && iobuf.length > 0) { - err = copy_to_user(A(iobuf32.buffer), iobuf.buffer, iobuf.length); - if (err) { - err = -EFAULT; - goto out; - } - } + if(!err) err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length)); - out: - if(iobuf32.buffer && iobuf32.length > 0) - kfree(iobuf.buffer); - return err; } @@ -2238,39 +2148,16 @@ if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) { sioc.arg = (void*)(unsigned long)sioc32.arg; } else { - sioc.arg = kmalloc(sioc.length, GFP_KERNEL); - if (sioc.arg == NULL) { - err = -ENOMEM; - goto out; - } - - err = copy_from_user(sioc.arg, A(sioc32.arg), sioc32.length); - if (err) { - err = -EFAULT; - goto out; - } + sioc.arg = compat_ptr(sioc32.arg); + if (verify_area(VERIFY_WRITE, sioc.arg, sioc32.length)) + return -EFAULT; } old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)&sioc); set_fs (old_fs); - if(err) { - goto out; - } - - if(sioc.arg && sioc.length > 0) { - err = copy_to_user(A(sioc32.arg), sioc.arg, sioc.length); - if (err) { - err = -EFAULT; - goto out; - } - } + if (!err) err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length)); - - out: - if(sioc32.arg && sioc32.length > 0) - kfree(sioc.arg); - return err; } @@ -2340,10 +2227,10 @@ } struct blkpg_ioctl_arg32 { - int op; - int flags; - int datalen; - u32 data; + compat_int_t op; + compat_int_t flags; + compat_int_t datalen; + compat_caddr_t data; }; static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioctl_arg32 *arg) @@ -2402,7 +2289,7 @@ struct raw32_config_request { - int raw_minor; + compat_int_t raw_minor; __u64 block_major; __u64 block_minor; } __attribute__((packed)); @@ -2434,24 +2321,24 @@ } struct serial_struct32 { - int type; - int line; - unsigned int port; - int irq; - int flags; - int xmit_fifo_size; - int custom_divisor; - int baud_base; + compat_int_t type; + compat_int_t line; + compat_uint_t port; + compat_int_t irq; + compat_int_t flags; + compat_int_t xmit_fifo_size; + compat_int_t custom_divisor; + compat_int_t baud_base; unsigned short close_delay; char io_type; char reserved_char[1]; - int hub6; + compat_int_t hub6; unsigned short closing_wait; /* time to wait before closing */ unsigned short closing_wait2; /* no longer used... */ - __u32 iomem_base; + compat_uint_t iomem_base; unsigned short iomem_reg_shift; unsigned int port_high; - int reserved[1]; + compat_int_t reserved[1]; }; static int serial_struct_ioctl(unsigned fd, unsigned cmd, void *ptr) @@ -2494,7 +2381,7 @@ } struct dirent32 { - unsigned int d_ino; + compat_int_t d_ino; compat_off_t d_off; unsigned short d_reclen; char d_name[256]; /* We must not include limits.h! */ @@ -2600,13 +2487,13 @@ #define BNEPGETCONNINFO _IOR('B', 211, int) struct usbdevfs_ctrltransfer32 { - __u8 bRequestType; - __u8 bRequest; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - __u32 timeout; /* in milliseconds */ - __u32 data; + u8 bRequestType; + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; + u32 timeout; /* in milliseconds */ + compat_caddr_t data; }; #define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) @@ -2629,7 +2516,7 @@ if (get_user(udata, &uctrl->data)) return -EFAULT; - uptr = (void *) A(udata); + uptr = compat_ptr(udata); /* In usbdevice_fs, it limits the control buffer to a page, * for simplicity so do we. @@ -2664,10 +2551,10 @@ } struct usbdevfs_bulktransfer32 { - unsigned int ep; - unsigned int len; - unsigned int timeout; /* in milliseconds */ - __u32 data; + compat_uint_t ep; + compat_uint_t len; + compat_uint_t timeout; /* in milliseconds */ + compat_caddr_t data; }; #define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) @@ -2689,7 +2576,7 @@ get_user(udata, &ubulk->data)) return -EFAULT; - uptr = (void *) A(udata); + uptr = compat_ptr(udata); /* In usbdevice_fs, it limits the control buffer to a page, * for simplicity so do we. @@ -2765,18 +2652,18 @@ */ #if 0 struct usbdevfs_urb32 { - __u8 type; - __u8 endpoint; - __s32 status; - __u32 flags; - __u32 buffer; - __s32 buffer_length; - __s32 actual_length; - __s32 start_frame; - __s32 number_of_packets; - __s32 error_count; - __u32 signr; - __u32 usercontext; /* unused */ + unsigned char type; + unsigned char endpoint; + compat_int_t status; + compat_uint_t flags; + compat_caddr_t buffer; + compat_int_t buffer_length; + compat_int_t actual_length; + compat_int_t start_frame; + compat_int_t number_of_packets; + compat_int_t error_count; + compat_uint_t signr; + compat_caddr_t usercontext; /* unused */ struct usbdevfs_iso_packet_desc iso_frame_desc[0]; }; @@ -2896,19 +2783,13 @@ err = -EFAULT; if (__get_user(udata, &uurb->buffer)) goto out; - uptr = (void *) A(udata); + uptr = compat_ptr(udata); - err = -ENOMEM; buflen = kurb->buffer_length; - kptr = kmalloc(buflen, GFP_KERNEL); - if (!kptr) + err = verify_area(VERIFY_WRITE, uptr, buflen); + if (err) goto out; - kurb->buffer = kptr; - - err = -EFAULT; - if (copy_from_user(kptr, uptr, buflen)) - goto out_kptr; old_fs = get_fs(); set_fs(KERNEL_DS); @@ -2919,15 +2800,9 @@ /* RED-PEN Shit, this doesn't work for async URBs :-( XXX */ if (put_urb32(kurb, uurb)) { err = -EFAULT; - } else if ((kurb->endpoint & USB_DIR_IN) != 0) { - if (copy_to_user(uptr, kptr, buflen)) - err = -EFAULT; } } -out_kptr: - kfree(kptr); - out: kfree(kurb); return err; @@ -2953,15 +2828,15 @@ set_fs(old_fs); if (err >= 0 && - put_user(((u32)(long)kptr), (u32 *) A(arg))) + put_user(((u32)(long)kptr), compat_ptr(arg))) err = -EFAULT; return err; } struct usbdevfs_disconnectsignal32 { - unsigned int signr; - u32 context; + compat_int_t signr; + compat_caddr_t context; }; #define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) @@ -2991,9 +2866,9 @@ } struct mtd_oob_buf32 { - u32 start; - u32 length; - u32 ptr; /* unsigned char* */ + u_int32_t start; + u_int32_t length; + compat_caddr_t ptr; /* unsigned char* */ }; #define MEMWRITEOOB32 _IOWR('M',3,struct mtd_oob_buf32) @@ -3005,7 +2880,6 @@ struct mtd_oob_buf32 *uarg = (struct mtd_oob_buf32 *)arg; struct mtd_oob_buf karg; u32 tmp; - char *ptr; int ret; if (get_user(karg.start, &uarg->start) || @@ -3013,18 +2887,9 @@ get_user(tmp, &uarg->ptr)) return -EFAULT; - ptr = (char *)A(tmp); - if (0 >= karg.length) - return -EINVAL; - - karg.ptr = kmalloc(karg.length, GFP_KERNEL); - if (NULL == karg.ptr) - return -ENOMEM; - - if (copy_from_user(karg.ptr, ptr, karg.length)) { - kfree(karg.ptr); + karg.ptr = compat_ptr(tmp); + if (verify_area(VERIFY_WRITE, karg.ptr, karg.length)) return -EFAULT; - } set_fs(KERNEL_DS); if (MEMREADOOB32 == cmd) @@ -3036,13 +2901,11 @@ set_fs(old_fs); if (0 == ret && cmd == MEMREADOOB32) { - ret = copy_to_user(ptr, karg.ptr, karg.length); - ret |= put_user(karg.start, &uarg->start); + ret = put_user(karg.start, &uarg->start); ret |= put_user(karg.length, &uarg->length); } - kfree(karg.ptr); - return ((0 == ret) ? 0 : -EFAULT); + return ret; } /* /proc/mtrr ioctls */ @@ -3050,17 +2913,17 @@ struct mtrr_sentry32 { - unsigned int base; /* Base address */ - unsigned int size; /* Size of region */ - unsigned int type; /* Type of region */ + compat_ulong_t base; /* Base address */ + compat_uint_t size; /* Size of region */ + compat_uint_t type; /* Type of region */ }; struct mtrr_gentry32 { - unsigned int regnum; /* Register number */ - unsigned int base; /* Base address */ - unsigned int size; /* Size of region */ - unsigned int type; /* Type of region */ + compat_ulong_t regnum; /* Register number */ + compat_uint_t base; /* Base address */ + compat_uint_t size; /* Size of region */ + compat_uint_t type; /* Type of region */ }; #define MTRR_IOCTL_BASE 'M' @@ -3131,7 +2994,7 @@ } #define REF_SYMBOL(handler) if (0) (void)handler; -#define HANDLE_IOCTL2(cmd,handler) REF_SYMBOL(handler); asm volatile(".quad %c0, " #handler ",0"::"i" (cmd)); +#define HANDLE_IOCTL2(cmd,handler) REF_SYMBOL(handler); asm volatile(".quad %P0, " #handler ",0"::"i" (cmd)); #define HANDLE_IOCTL(cmd,handler) HANDLE_IOCTL2(cmd,handler) #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) #define IOCTL_TABLE_START void ioctl_dummy(void) { asm volatile("\n.global ioctl_start\nioctl_start:\n\t" ); diff -urN linux-2.5.69-bk16/arch/x86_64/ia32/ia32_signal.c linux-2.5.69-bk17/arch/x86_64/ia32/ia32_signal.c --- linux-2.5.69-bk16/arch/x86_64/ia32/ia32_signal.c 2003-05-04 16:53:42.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/ia32/ia32_signal.c 2003-05-24 04:33:33.000000000 -0700 @@ -33,6 +33,7 @@ #include #include #include +#include #define ptr_to_u32(x) ((u32)(u64)(x)) /* avoid gcc warning */ @@ -428,7 +429,7 @@ /* Return stub is in 32bit vsyscall page */ { - void *restorer = syscall32_page + 32; + void *restorer = VSYSCALL32_SIGRETURN; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; err |= __put_user(ptr_to_u32(restorer), &frame->pretcode); @@ -521,7 +522,7 @@ { - void *restorer = syscall32_page + 32; + void *restorer = VSYSCALL32_RTSIGRETURN; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; err |= __put_user(ptr_to_u32(restorer), &frame->pretcode); diff -urN linux-2.5.69-bk16/arch/x86_64/ia32/ia32entry.S linux-2.5.69-bk17/arch/x86_64/ia32/ia32entry.S --- linux-2.5.69-bk16/arch/x86_64/ia32/ia32entry.S 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/ia32/ia32entry.S 2003-05-24 04:33:33.000000000 -0700 @@ -182,9 +182,9 @@ PTREGSCALL stub32_sigaltstack, sys32_sigaltstack PTREGSCALL stub32_sigsuspend, sys32_sigsuspend PTREGSCALL stub32_execve, sys32_execve - PTREGSCALL stub32_fork, sys32_fork + PTREGSCALL stub32_fork, sys_fork PTREGSCALL stub32_clone, sys32_clone - PTREGSCALL stub32_vfork, sys32_vfork + PTREGSCALL stub32_vfork, sys_vfork PTREGSCALL stub32_iopl, sys_iopl PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend diff -urN linux-2.5.69-bk16/arch/x86_64/ia32/ptrace32.c linux-2.5.69-bk17/arch/x86_64/ia32/ptrace32.c --- linux-2.5.69-bk16/arch/x86_64/ia32/ptrace32.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/ia32/ptrace32.c 2003-05-24 04:33:33.000000000 -0700 @@ -78,12 +78,24 @@ case offsetof(struct user32, u_debugreg[5]): return -EIO; - case offsetof(struct user32, u_debugreg[0]) ... - offsetof(struct user32, u_debugreg[3]): + case offsetof(struct user32, u_debugreg[0]): + child->thread.debugreg0 = val; + break; + + case offsetof(struct user32, u_debugreg[1]): + child->thread.debugreg1 = val; + break; + + case offsetof(struct user32, u_debugreg[2]): + child->thread.debugreg2 = val; + break; + + case offsetof(struct user32, u_debugreg[3]): + child->thread.debugreg3 = val; + break; + case offsetof(struct user32, u_debugreg[6]): - child->thread.debugreg - [(regno-offsetof(struct user32, u_debugreg[0]))/4] - = val; + child->thread.debugreg6 = val; break; case offsetof(struct user32, u_debugreg[7]): @@ -92,7 +104,7 @@ for(i=0; i<4; i++) if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1) return -EIO; - child->thread.debugreg[7] = val; + child->thread.debugreg7 = val; break; default: @@ -142,8 +154,23 @@ R32(eflags, eflags); R32(esp, rsp); - case offsetof(struct user32, u_debugreg[0]) ... offsetof(struct user32, u_debugreg[7]): - *val = child->thread.debugreg[(regno-offsetof(struct user32, u_debugreg[0]))/4]; + case offsetof(struct user32, u_debugreg[0]): + *val = child->thread.debugreg0; + break; + case offsetof(struct user32, u_debugreg[1]): + *val = child->thread.debugreg1; + break; + case offsetof(struct user32, u_debugreg[2]): + *val = child->thread.debugreg2; + break; + case offsetof(struct user32, u_debugreg[3]): + *val = child->thread.debugreg3; + break; + case offsetof(struct user32, u_debugreg[6]): + *val = child->thread.debugreg6; + break; + case offsetof(struct user32, u_debugreg[7]): + *val = child->thread.debugreg7; break; default: diff -urN linux-2.5.69-bk16/arch/x86_64/ia32/sys_ia32.c linux-2.5.69-bk17/arch/x86_64/ia32/sys_ia32.c --- linux-2.5.69-bk16/arch/x86_64/ia32/sys_ia32.c 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/ia32/sys_ia32.c 2003-05-24 04:33:33.000000000 -0700 @@ -234,7 +234,7 @@ } if (a.prot & PROT_READ) - a.prot |= PROT_EXEC; + a.prot |= vm_force_exec32; mm = current->mm; down_write(&mm->mmap_sem); @@ -253,7 +253,7 @@ sys32_mprotect(unsigned long start, size_t len, unsigned long prot) { if (prot & PROT_READ) - prot |= PROT_EXEC; + prot |= vm_force_exec32; return sys_mprotect(start,len,prot); } @@ -929,7 +929,11 @@ u32 totalswap; u32 freeswap; unsigned short procs; - char _f[22]; + unsigned short pad; + u32 totalhigh; + u32 freehigh; + u32 mem_unit; + char _f[20-2*sizeof(u32)-sizeof(int)]; }; extern asmlinkage long sys_sysinfo(struct sysinfo *info); @@ -955,7 +959,10 @@ __put_user (s.bufferram, &info->bufferram) || __put_user (s.totalswap, &info->totalswap) || __put_user (s.freeswap, &info->freeswap) || - __put_user (s.procs, &info->procs)) + __put_user (s.procs, &info->procs) || + __put_user (s.totalhigh, &info->totalhigh) || + __put_user (s.freehigh, &info->freehigh) || + __put_user (s.mem_unit, &info->mem_unit)) return -EFAULT; return 0; } @@ -1419,7 +1426,7 @@ } if (prot & PROT_READ) - prot |= PROT_EXEC; + prot |= vm_force_exec32; down_write(&mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); @@ -1587,40 +1594,14 @@ return ret; } -asmlinkage long sys32_fork(struct pt_regs regs) -{ - struct task_struct *p; - p = do_fork(SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; -} - asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, struct pt_regs regs) { - struct task_struct *p; void *parent_tid = (void *)regs.rdx; void *child_tid = (void *)regs.rdi; if (!newsp) newsp = regs.rsp; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tid, child_tid); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; -} - -/* - * This is trivial, and on the face of it looks like it - * could equally well be done in user mode. - * - * Not so, for quite unobvious reasons - register pressure. - * In user mode vfork() cannot have a stack frame, and if - * done by calling the "clone()" system call directly, you - * do not have enough call-clobbered registers to hold all - * the information you need. - */ -asmlinkage long sys32_vfork(struct pt_regs regs) -{ - struct task_struct *p; - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; } /* diff -urN linux-2.5.69-bk16/arch/x86_64/ia32/syscall32.c linux-2.5.69-bk17/arch/x86_64/ia32/syscall32.c --- linux-2.5.69-bk16/arch/x86_64/ia32/syscall32.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/ia32/syscall32.c 2003-05-24 04:33:33.000000000 -0700 @@ -13,33 +13,14 @@ #include #include -/* 32bit SYSCALL stub mapped into user space. */ -asm(" .code32\n" - "\nsyscall32:\n" - " pushl %ebp\n" - " movl %ecx,%ebp\n" - " syscall\n" - " popl %ebp\n" - " ret\n" +/* 32bit VDSO mapped into user space. */ +asm(".section \".init.data\",\"aw\"\n" + "syscall32:\n" + ".incbin \"arch/x86_64/ia32/vsyscall.so\"\n" "syscall32_end:\n" - - /* signal trampolines */ - - "sig32_rt_tramp:\n" - " movl $" __stringify(__NR_ia32_rt_sigreturn) ",%eax\n" - " syscall\n" - "sig32_rt_tramp_end:\n" - - "sig32_tramp:\n" - " popl %eax\n" - " movl $" __stringify(__NR_ia32_sigreturn) ",%eax\n" - " syscall\n" - "sig32_tramp_end:\n" - " .code64\n"); + ".previous"); extern unsigned char syscall32[], syscall32_end[]; -extern unsigned char sig32_rt_tramp[], sig32_rt_tramp_end[]; -extern unsigned char sig32_tramp[], sig32_tramp_end[]; char *syscall32_page; @@ -76,10 +57,6 @@ panic("Cannot allocate syscall32 page"); SetPageReserved(virt_to_page(syscall32_page)); memcpy(syscall32_page, syscall32, syscall32_end - syscall32); - memcpy(syscall32_page + 32, sig32_rt_tramp, - sig32_rt_tramp_end - sig32_rt_tramp); - memcpy(syscall32_page + 64, sig32_tramp, - sig32_tramp_end - sig32_tramp); return 0; } diff -urN linux-2.5.69-bk16/arch/x86_64/ia32/vsyscall.S linux-2.5.69-bk17/arch/x86_64/ia32/vsyscall.S --- linux-2.5.69-bk16/arch/x86_64/ia32/vsyscall.S 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.69-bk17/arch/x86_64/ia32/vsyscall.S 2003-05-24 04:33:33.000000000 -0700 @@ -0,0 +1,172 @@ +/* + * Code for the vsyscall page. This version uses the syscall instruction. + */ + +#include +#include + + .text + .section .text.vsyscall,"ax" + .globl __kernel_vsyscall + .type __kernel_vsyscall,@function +__kernel_vsyscall: +.LSTART_vsyscall: + push %ebp +.Lpush_ebp: + movl %ecx, %ebp + syscall + popl %ebp +.Lpop_ebp: + ret +.LEND_vsyscall: + .size __kernel_vsyscall,.-.LSTART_vsyscall + + .section .text.sigreturn,"ax" + .balign 32 + .globl __kernel_sigreturn + .type __kernel_sigreturn,@function +__kernel_sigreturn: +.LSTART_sigreturn: + popl %eax + movl $__NR_ia32_sigreturn, %eax + syscall +.LEND_sigreturn: + .size __kernel_sigreturn,.-.LSTART_sigreturn + + .section .text.rtsigreturn,"ax" + .balign 32 + .globl __kernel_rt_sigreturn,"ax" + .type __kernel_rt_sigreturn,@function +__kernel_rt_sigreturn: +.LSTART_rt_sigreturn: + movl $__NR_ia32_rt_sigreturn, %eax + syscall +.LEND_rt_sigreturn: + .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE +.LSTARTCIE: + .long 0 /* CIE ID */ + .byte 1 /* Version number */ + .string "zR" /* NUL-terminated augmentation string */ + .uleb128 1 /* Code alignment factor */ + .sleb128 -4 /* Data alignment factor */ + .byte 8 /* Return address register column */ + .uleb128 1 /* Augmentation value length */ + .byte 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */ + .byte 0x0c /* DW_CFA_def_cfa */ + .uleb128 4 + .uleb128 4 + .byte 0x88 /* DW_CFA_offset, column 0x8 */ + .uleb128 1 + .align 4 +.LENDCIE: + + .long .LENDFDE1-.LSTARTFDE1 /* Length FDE */ +.LSTARTFDE1: + .long .LSTARTFDE1-.LSTARTFRAME /* CIE pointer */ + .long .LSTART_vsyscall-. /* PC-relative start address */ + .long .LEND_vsyscall-.LSTART_vsyscall + .uleb128 0 /* Augmentation length */ + /* What follows are the instructions for the table generation. + We have to record all changes of the stack pointer. */ + .byte 0x40 + .Lpush_ebp-.LSTART_vsyscall /* DW_CFA_advance_loc */ + .byte 0x0e /* DW_CFA_def_cfa_offset */ + .uleb128 8 + .byte 0x85, 0x02 /* DW_CFA_offset %ebp -8 */ + .byte 0x40 + .Lpop_ebp-.Lpush_ebp /* DW_CFA_advance_loc */ + .byte 0xc5 /* DW_CFA_restore %ebp */ + .byte 0x0e /* DW_CFA_def_cfa_offset */ + .uleb128 4 + .align 4 +.LENDFDE1: + + .long .LENDFDE2-.LSTARTFDE2 /* Length FDE */ +.LSTARTFDE2: + .long .LSTARTFDE2-.LSTARTFRAME /* CIE pointer */ + /* HACK: The dwarf2 unwind routines will subtract 1 from the + return address to get an address in the middle of the + presumed call instruction. Since we didn't get here via + a call, we need to include the nop before the real start + to make up for it. */ + .long .LSTART_sigreturn-1-. /* PC-relative start address */ + .long .LEND_sigreturn-.LSTART_sigreturn+1 + .uleb128 0 /* Augmentation length */ + /* What follows are the instructions for the table generation. + We record the locations of each register saved. This is + complicated by the fact that the "CFA" is always assumed to + be the value of the stack pointer in the caller. This means + that we must define the CFA of this body of code to be the + saved value of the stack pointer in the sigcontext. Which + also means that there is no fixed relation to the other + saved registers, which means that we must use DW_CFA_expression + to compute their addresses. It also means that when we + adjust the stack with the popl, we have to do it all over again. */ + +#define do_cfa_expr(offset) \ + .byte 0x0f; /* DW_CFA_def_cfa_expression */ \ + .uleb128 1f-0f; /* length */ \ +0: .byte 0x74; /* DW_OP_breg4 */ \ + .sleb128 offset; /* offset */ \ + .byte 0x06; /* DW_OP_deref */ \ +1: + +#define do_expr(regno, offset) \ + .byte 0x10; /* DW_CFA_expression */ \ + .uleb128 regno; /* regno */ \ + .uleb128 1f-0f; /* length */ \ +0: .byte 0x74; /* DW_OP_breg4 */ \ + .sleb128 offset; /* offset */ \ +1: + + do_cfa_expr(IA32_SIGCONTEXT_esp+4) + do_expr(0, IA32_SIGCONTEXT_eax+4) + do_expr(1, IA32_SIGCONTEXT_ecx+4) + do_expr(2, IA32_SIGCONTEXT_edx+4) + do_expr(3, IA32_SIGCONTEXT_ebx+4) + do_expr(5, IA32_SIGCONTEXT_ebp+4) + do_expr(6, IA32_SIGCONTEXT_esi+4) + do_expr(7, IA32_SIGCONTEXT_edi+4) + do_expr(8, IA32_SIGCONTEXT_eip+4) + + .byte 0x42 /* DW_CFA_advance_loc 2 -- nop; popl eax. */ + + do_cfa_expr(IA32_SIGCONTEXT_esp) + do_expr(0, IA32_SIGCONTEXT_eax) + do_expr(1, IA32_SIGCONTEXT_ecx) + do_expr(2, IA32_SIGCONTEXT_edx) + do_expr(3, IA32_SIGCONTEXT_ebx) + do_expr(5, IA32_SIGCONTEXT_ebp) + do_expr(6, IA32_SIGCONTEXT_esi) + do_expr(7, IA32_SIGCONTEXT_edi) + do_expr(8, IA32_SIGCONTEXT_eip) + + .align 4 +.LENDFDE2: + + .long .LENDFDE3-.LSTARTFDE3 /* Length FDE */ +.LSTARTFDE3: + .long .LSTARTFDE3-.LSTARTFRAME /* CIE pointer */ + /* HACK: See above wrt unwind library assumptions. */ + .long .LSTART_rt_sigreturn-1-. /* PC-relative start address */ + .long .LEND_rt_sigreturn-.LSTART_rt_sigreturn+1 + .uleb128 0 /* Augmentation */ + /* What follows are the instructions for the table generation. + We record the locations of each register saved. This is + slightly less complicated than the above, since we don't + modify the stack pointer in the process. */ + + do_cfa_expr(IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_esp) + do_expr(0, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_eax) + do_expr(1, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ecx) + do_expr(2, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_edx) + do_expr(3, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ebx) + do_expr(5, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ebp) + do_expr(6, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_esi) + do_expr(7, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_edi) + do_expr(8, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_eip) + + .align 4 +.LENDFDE3: diff -urN linux-2.5.69-bk16/arch/x86_64/ia32/vsyscall.lds linux-2.5.69-bk17/arch/x86_64/ia32/vsyscall.lds --- linux-2.5.69-bk16/arch/x86_64/ia32/vsyscall.lds 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.69-bk17/arch/x86_64/ia32/vsyscall.lds 2003-05-24 04:33:33.000000000 -0700 @@ -0,0 +1,77 @@ +/* + * Linker script for vsyscall DSO. The vsyscall page is an ELF shared + * object prelinked to its virtual address. This script controls its layout. + */ + +/* This must match . */ +VSYSCALL_BASE = 0xffffe000; + +SECTIONS +{ + . = VSYSCALL_BASE + SIZEOF_HEADERS; + + .hash : { *(.hash) } :text + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + + /* This linker script is used both with -r and with -shared. + For the layouts to match, we need to skip more than enough + space for the dynamic symbol table et al. If this amount + is insufficient, ld -shared will barf. Just increase it here. */ + . = VSYSCALL_BASE + 0x400; + + .text.vsyscall : { *(.text.vsyscall) } :text =0x90909090 + + /* This is an 32bit object and we cannot easily get the offsets + into the 64bit kernel. Just hardcode them here. This assumes + that all the stubs don't need more than 0x100 bytes. */ + . = VSYSCALL_BASE + 0x500; + + .text.sigreturn : { *(.text.sigreturn) } :text =0x90909090 + + . = VSYSCALL_BASE + 0x600; + + .text.rtsigreturn : { *(.text.rtsigreturn) } :text =0x90909090 + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + .dynamic : { *(.dynamic) } :text :dynamic + .useless : { + *(.got.plt) *(.got) + *(.data .data.* .gnu.linkonce.d.*) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + } :text +} + +/* + * We must supply the ELF program headers explicitly to get just one + * PT_LOAD segment, and set the flags explicitly to make segments read-only. + */ +PHDRS +{ + text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ +} + +/* + * This controls what symbols we export from the DSO. + */ +VERSION +{ + LINUX_2.5 { + global: + __kernel_vsyscall; + __kernel_sigreturn; + __kernel_rt_sigreturn; + + local: *; + }; +} + +/* The ELF entry point can be used to set the AT_SYSINFO value. */ +ENTRY(__kernel_vsyscall); diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/Makefile linux-2.5.69-bk17/arch/x86_64/kernel/Makefile --- linux-2.5.69-bk16/arch/x86_64/kernel/Makefile 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/Makefile 2003-05-24 04:33:33.000000000 -0700 @@ -7,7 +7,7 @@ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \ pci-dma.o x8664_ksyms.o i387.o syscall.o vsyscall.o \ - setup64.o bluesmoke.o bootflag.o e820.o reboot.o + setup64.o bluesmoke.o bootflag.o e820.o reboot.o warmreboot.o obj-$(CONFIG_MTRR) += mtrr/ obj-$(CONFIG_ACPI) += acpi/ diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/acpi/wakeup.S linux-2.5.69-bk17/arch/x86_64/kernel/acpi/wakeup.S --- linux-2.5.69-bk16/arch/x86_64/kernel/acpi/wakeup.S 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/acpi/wakeup.S 2003-05-24 04:33:33.000000000 -0700 @@ -94,12 +94,6 @@ movw %ax, %ss mov $(wakeup_stack - __START_KERNEL_map), %esp - - call 1f -1: popl %eax - movl $0xb8040, %ebx - call early_print - movl saved_magic - __START_KERNEL_map, %eax cmpl $0x9abcdef0, %eax jne bogus_32_magic @@ -115,11 +109,7 @@ movl %eax, %cr4 /* Setup early boot stage 4 level pagetables */ -#if 1 movl $(wakeup_level4_pgt - __START_KERNEL_map), %eax -#else - movl saved_cr3 - __START_KERNEL_map, %eax -#endif movl %eax, %cr3 /* Setup EFER (Extended Feature Enable Register) */ @@ -223,19 +213,6 @@ .code32 -early_print: - movl $16, %edx -1: - movl %eax, %ecx - andl $0xf, %ecx - shrl $4, %eax - addw $0x0e00 + '0', %ecx - movw %ecx, %ds:(%edx, %ebx) - decl %edx - decl %edx - jnz 1b - ret - .align 64 gdta: .word 0, 0, 0, 0 # dummy diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/acpi.c linux-2.5.69-bk17/arch/x86_64/kernel/acpi.c --- linux-2.5.69-bk16/arch/x86_64/kernel/acpi.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/acpi.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,512 +0,0 @@ -/* - * acpi.c - Architecture-Specific Low-Level ACPI Support - * - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * Copyright (C) 2001 Jun Nakajima - * Copyright (C) 2001 Patrick Mochel - * Copyright (C) 2002 Andi Kleen, SuSE Labs (x86-64 port) - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern int acpi_disabled; - -#define PREFIX "ACPI: " - - -/* -------------------------------------------------------------------------- - Boot-time Configuration - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_BOOT - -enum acpi_irq_model_id acpi_irq_model; - -/* rely on all ACPI tables being in the direct mapping */ -char * -__acpi_map_table ( - unsigned long phys_addr, - unsigned long size) -{ - if (!phys_addr || !size) - return NULL; - - if (phys_addr < (end_pfn_map << PAGE_SHIFT)) - return __va(phys_addr); - - return NULL; -} - -#ifdef CONFIG_X86_LOCAL_APIC - -int acpi_lapic; - -static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; - - -static int __init -acpi_parse_madt ( - unsigned long phys_addr, - unsigned long size) -{ - struct acpi_table_madt *madt = NULL; - - if (!phys_addr || !size) - return -EINVAL; - - madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size); - if (!madt) { - printk(KERN_WARNING PREFIX "Unable to map MADT\n"); - return -ENODEV; - } - - if (madt->lapic_address) - acpi_lapic_addr = (u64) madt->lapic_address; - - printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n", - madt->lapic_address); - - return 0; -} - - -static int __init -acpi_parse_lapic ( - acpi_table_entry_header *header) -{ - struct acpi_table_lapic *processor = NULL; - - processor = (struct acpi_table_lapic*) header; - if (!processor) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - mp_register_lapic ( - processor->id, /* APIC ID */ - processor->flags.enabled); /* Enabled? */ - - return 0; -} - - -static int __init -acpi_parse_lapic_addr_ovr ( - acpi_table_entry_header *header) -{ - struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL; - - lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header; - if (!lapic_addr_ovr) - return -EINVAL; - - acpi_lapic_addr = lapic_addr_ovr->address; - - return 0; -} - - -static int __init -acpi_parse_lapic_nmi ( - acpi_table_entry_header *header) -{ - struct acpi_table_lapic_nmi *lapic_nmi = NULL; - - lapic_nmi = (struct acpi_table_lapic_nmi*) header; - if (!lapic_nmi) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - if (lapic_nmi->lint != 1) - printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); - - return 0; -} - -#endif /*CONFIG_X86_LOCAL_APIC*/ - -#ifdef CONFIG_X86_IO_APIC - -int acpi_ioapic; - -static int __init -acpi_parse_ioapic ( - acpi_table_entry_header *header) -{ - struct acpi_table_ioapic *ioapic = NULL; - - ioapic = (struct acpi_table_ioapic*) header; - if (!ioapic) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - mp_register_ioapic ( - ioapic->id, - ioapic->address, - ioapic->global_irq_base); - - return 0; -} - - -static int __init -acpi_parse_int_src_ovr ( - acpi_table_entry_header *header) -{ - struct acpi_table_int_src_ovr *intsrc = NULL; - - intsrc = (struct acpi_table_int_src_ovr*) header; - if (!intsrc) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - mp_override_legacy_irq ( - intsrc->bus_irq, - intsrc->flags.polarity, - intsrc->flags.trigger, - intsrc->global_irq); - - return 0; -} - - -static int __init -acpi_parse_nmi_src ( - acpi_table_entry_header *header) -{ - struct acpi_table_nmi_src *nmi_src = NULL; - - nmi_src = (struct acpi_table_nmi_src*) header; - if (!nmi_src) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - /* TBD: Support nimsrc entries? */ - - return 0; -} - -#endif /*CONFIG_X86_IO_APIC*/ - -#ifdef CONFIG_HPET_TIMER -static int __init -acpi_parse_hpet ( - unsigned long phys_addr, - unsigned long size) -{ - struct acpi_table_hpet *hpet_tbl; - - hpet_tbl = __va(phys_addr); - - if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) { - printk(KERN_WARNING "acpi: HPET timers must be located in memory.\n"); - return -1; - } - - hpet.address = hpet_tbl->addr.addrl | ((long) hpet_tbl->addr.addrh << 32); - - printk(KERN_INFO "acpi: HPET id: %#x base: %#lx\n", hpet_tbl->id, hpet.address); - - return 0; -} -#endif - -static unsigned long __init -acpi_scan_rsdp ( - unsigned long start, - unsigned long length) -{ - unsigned long offset = 0; - unsigned long sig_len = sizeof("RSD PTR ") - 1; - - /* - * Scan all 16-byte boundaries of the physical memory region for the - * RSDP signature. - */ - for (offset = 0; offset < length; offset += 16) { - if (strncmp((char *) (start + offset), "RSD PTR ", sig_len)) - continue; - return (start + offset); - } - - return 0; -} - - -unsigned long __init -acpi_find_rsdp (void) -{ - unsigned long rsdp_phys = 0; - - /* - * Scan memory looking for the RSDP signature. First search EBDA (low - * memory) paragraphs and then search upper memory (E0000-FFFFF). - */ - rsdp_phys = acpi_scan_rsdp (0, 0x400); - if (!rsdp_phys) - rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF); - - return rsdp_phys; -} - - -int __init -acpi_boot_init (void) -{ - int result = 0; - - /* - * The default interrupt routing model is PIC (8259). This gets - * overridden if IOAPICs are enumerated (below). - */ - acpi_irq_model = ACPI_IRQ_MODEL_PIC; - - /* - * Initialize the ACPI boot-time table parser. - */ - result = acpi_table_init(); - if (result) - return result; - - result = acpi_blacklisted(); - if (result) { - acpi_disabled = 1; - return result; - } else - printk(KERN_NOTICE PREFIX "BIOS passes blacklist\n"); - - extern int disable_apic; - if (disable_apic) - return 0; - -#ifdef CONFIG_X86_LOCAL_APIC - - /* - * MADT - * ---- - * Parse the Multiple APIC Description Table (MADT), if exists. - * Note that this table provides platform SMP configuration - * information -- the successor to MPS tables. - */ - - result = acpi_table_parse(ACPI_APIC, acpi_parse_madt); - if (!result) { - printk(KERN_WARNING PREFIX "MADT not present\n"); - return 0; - } - else if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing MADT\n"); - return result; - } - else if (result > 1) - printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n"); - - /* - * Local APIC - * ---------- - * Note that the LAPIC address is obtained from the MADT (32-bit value) - * and (optionally) overridden by a LAPIC_ADDR_OVR entry (64-bit value). - */ - - result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); - return result; - } - - mp_register_lapic_address(acpi_lapic_addr); - - result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic); - if (!result) { - printk(KERN_ERR PREFIX "No LAPIC entries present\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return -ENODEV; - } - else if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - acpi_lapic = 1; - -#endif /*CONFIG_X86_LOCAL_APIC*/ - -#ifdef CONFIG_X86_IO_APIC - - /* - * I/O APIC - * -------- - */ - - result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic); - if (!result) { - printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); - return -ENODEV; - } - else if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n"); - return result; - } - - /* Build a default routing table for legacy (ISA) interrupts. */ - mp_config_acpi_legacy_irqs(); - - result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; - - acpi_ioapic = 1; - -#endif /*CONFIG_X86_IO_APIC*/ - -#ifdef CONFIG_X86_LOCAL_APIC - if (acpi_lapic && acpi_ioapic) - smp_found_config = 1; -#endif - -#ifdef CONFIG_HPET_TIMER - result = acpi_table_parse(ACPI_HPET, acpi_parse_hpet); - if (result < 0) - printk("ACPI: no HPET table found (%d).\n", result); -#endif - - return 0; -} - -#endif /*CONFIG_ACPI_BOOT*/ - - -/* -------------------------------------------------------------------------- - Low-Level Sleep Support - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_SLEEP - -extern void acpi_prepare_wakeup(void); -extern unsigned char acpi_wakeup[], acpi_wakeup_end[], s3_prot16[]; - -/* address in low memory of the wakeup routine. */ -unsigned long acpi_wakeup_address; - -/** - * acpi_save_state_mem - save kernel state - */ -int acpi_save_state_mem (void) -{ - if (!acpi_wakeup_address) - return -1; - - memcpy((void*)acpi_wakeup_address, acpi_wakeup, acpi_wakeup_end - acpi_wakeup); - return 0; -} - -/** - * acpi_save_state_disk - save kernel state to disk - * - * Assume preemption/interrupts are already turned off and that we're running - * on the BP (note this doesn't imply SMP is handled correctly) - */ -int acpi_save_state_disk (void) -{ - unsigned long pbase = read_cr3() & PAGE_MASK; - if (pbase >= 0xffffffffUL) { - printk(KERN_ERR "ACPI: High page table. Suspend disabled.\n"); - return 1; - } - set_seg_base(smp_processor_id(), GDT_ENTRY_KERNELCS16, s3_prot16); - swap_low_mappings(); - acpi_prepare_wakeup(); - return 0; -} - -/* - * acpi_restore_state - */ -void acpi_restore_state_mem (void) -{ - swap_low_mappings(); -} - -/** - * acpi_reserve_bootmem - do _very_ early ACPI initialisation - * - * We allocate a page in 1MB low memory for the real-mode wakeup - * routine for when we come back from a sleep state. The - * runtime allocator allows specification of <16M pages, but not - * <1M pages. - */ -void __init acpi_reserve_bootmem(void) -{ - acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE); - if (!acpi_wakeup_address) { - printk(KERN_ERR "ACPI: Cannot allocate lowmem. S3 disabled.\n"); - return; - } -} - -#endif /*CONFIG_ACPI_SLEEP*/ - -void acpi_pci_link_exit(void) {} diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/apic.c linux-2.5.69-bk17/arch/x86_64/kernel/apic.c --- linux-2.5.69-bk16/arch/x86_64/kernel/apic.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/apic.c 2003-05-24 04:33:33.000000000 -0700 @@ -385,10 +385,10 @@ value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; if (!smp_processor_id() && (pic_mode || !value)) { value = APIC_DM_EXTINT; - printk("enabled ExtINT on CPU#%d\n", smp_processor_id()); + Dprintk(KERN_INFO "enabled ExtINT on CPU#%d\n", smp_processor_id()); } else { value = APIC_DM_EXTINT | APIC_LVT_MASKED; - printk("masked ExtINT on CPU#%d\n", smp_processor_id()); + Dprintk(KERN_INFO "masked ExtINT on CPU#%d\n", smp_processor_id()); } apic_write_around(APIC_LVT0, value); diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/asm-offsets.c linux-2.5.69-bk17/arch/x86_64/kernel/asm-offsets.c --- linux-2.5.69-bk16/arch/x86_64/kernel/asm-offsets.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/asm-offsets.c 2003-05-24 04:33:33.000000000 -0700 @@ -12,6 +12,7 @@ #include #include #include +#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -43,5 +44,21 @@ ENTRY(irqstackptr); BLANK(); #undef ENTRY +#define ENTRY(entry) DEFINE(IA32_SIGCONTEXT_ ## entry, offsetof(struct sigcontext_ia32, entry)) + ENTRY(eax); + ENTRY(ebx); + ENTRY(ecx); + ENTRY(edx); + ENTRY(esi); + ENTRY(edi); + ENTRY(ebp); + ENTRY(esp); + ENTRY(eip); + BLANK(); +#undef ENTRY + DEFINE(IA32_RT_SIGFRAME_sigcontext, + offsetof (struct rt_sigframe32, uc.uc_mcontext)); + BLANK(); + return 0; } diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/bluesmoke.c linux-2.5.69-bk17/arch/x86_64/kernel/bluesmoke.c --- linux-2.5.69-bk16/arch/x86_64/kernel/bluesmoke.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/bluesmoke.c 2003-05-24 04:33:33.000000000 -0700 @@ -129,12 +129,75 @@ int cpu = smp_processor_id(); pci_for_each_dev(dev) { if (dev->bus->number==0 && PCI_FUNC(dev->devfn)==3 && - PCI_SLOT(dev->devfn) == (24+cpu)) + PCI_SLOT(dev->devfn) == (24U+cpu)) return dev; } return NULL; } +/* When we have kallsyms we can afford kmcedecode too. */ + +static char *transaction[] = { + "instruction", "data", "generic", "reserved" +}; +static char *cachelevel[] = { + "level 0", "level 1", "level 2", "level generic" +}; +static char *memtrans[] = { + "generic error", "generic read", "generic write", "data read", + "data write", "instruction fetch", "prefetch", "snoop", + "?", "?", "?", "?", "?", "?", "?" +}; +static char *partproc[] = { + "local node origin", "local node response", + "local node observed", "generic" +}; +static char *timeout[] = { + "request didn't time out", + "request timed out" +}; +static char *memoryio[] = { + "memory access", "res.", "i/o access", "generic" +}; +static char *extendederr[] = { + "ecc error", + "crc error", + "sync error", + "mst abort", + "tgt abort", + "gart error", + "rmw error", + "wdog error", + "chipkill ecc error", + "<9>","<10>","<11>","<12>", + "<13>","<14>","<15>" +}; +static char *highbits[32] = { + [31] = "previous error lost", + [30] = "error overflow", + [29] = "error uncorrected", + [28] = "error enable", + [27] = "misc error valid", + [26] = "error address valid", + [25] = "processor context corrupt", + [24] = "res24", + [23] = "res23", + /* 22-15 ecc syndrome bits */ + [14] = "corrected ecc error", + [13] = "uncorrected ecc error", + [12] = "res12", + [11] = "res11", + [10] = "res10", + [9] = "res9", + [8] = "dram scrub error", + [7] = "res7", + /* 6-4 ht link number of error */ + [3] = "res3", + [2] = "res2", + [1] = "err cpu0", + [0] = "err cpu1", +}; + static void check_k8_nb(void) { struct pci_dev *nb; @@ -149,20 +212,52 @@ return; printk(KERN_ERR "Northbridge status %08x%08x\n", statushigh,statuslow); - if (statuslow & 0x10) - printk(KERN_ERR "GART error %d\n", statuslow & 0xf); - if (statushigh & (1<<31)) - printk(KERN_ERR "Lost an northbridge error\n"); - if (statushigh & (1<<25)) - printk(KERN_EMERG "NB status: unrecoverable\n"); + + unsigned short errcode = statuslow & 0xffff; + switch (errcode >> 8) { + case 0: + printk(KERN_ERR " GART TLB error %s %s\n", + transaction[(errcode >> 2) & 3], + cachelevel[errcode & 3]); + break; + case 1: + if (errcode & (1<<11)) { + printk(KERN_ERR " bus error %s %s %s %s %s\n", + partproc[(errcode >> 10) & 0x3], + timeout[(errcode >> 9) & 1], + memtrans[(errcode >> 4) & 0xf], + memoryio[(errcode >> 2) & 0x3], + cachelevel[(errcode & 0x3)]); + } else if (errcode & (1<<8)) { + printk(KERN_ERR " memory error %s %s %s\n", + memtrans[(errcode >> 4) & 0xf], + transaction[(errcode >> 2) & 0x3], + cachelevel[(errcode & 0x3)]); + } else { + printk(KERN_ERR " unknown error code %x\n", errcode); + } + break; + } + if (statushigh & ((1<<14)|(1<<13))) + printk(KERN_ERR " ECC syndrome bits %x\n", + (((statuslow >> 24) & 0xff) << 8) | ((statushigh >> 15) & 0x7f)); + errcode = (statuslow >> 16) & 0xf; + printk(KERN_ERR " extended error %s\n", extendederr[(statuslow >> 16) & 0xf]); + + /* should only print when it was a HyperTransport related error. */ + printk(KERN_ERR " link number %x\n", (statushigh >> 4) & 3); + + int i; + for (i = 0; i < 32; i++) + if (highbits[i] && (statushigh & (1< arg1 */ call schedule_tail GET_THREAD_INFO(%rcx) bt $TIF_SYSCALL_TRACE,threadinfo_flags(%rcx) @@ -414,6 +414,7 @@ .previous .section .fixup,"ax" /* force a signal here? this matches i386 behaviour */ + /* running with kernel gs */ bad_iret: movq $-9999,%rdi /* better code? */ jmp do_exit @@ -519,21 +520,27 @@ */ ENTRY(error_entry) /* rdi slot contains rax, oldrax contains error code */ - pushq %rsi - movq 8(%rsp),%rsi /* load rax */ - pushq %rdx - pushq %rcx - pushq %rsi /* store rax */ - pushq %r8 - pushq %r9 - pushq %r10 - pushq %r11 cld - SAVE_REST + subq $14*8,%rsp + movq %rsi,13*8(%rsp) + movq 14*8(%rsp),%rsi /* load rax from rdi slot */ + movq %rdx,12*8(%rsp) + movq %rcx,11*8(%rsp) + movq %rsi,10*8(%rsp) /* store rax */ + movq %r8, 9*8(%rsp) + movq %r9, 8*8(%rsp) + movq %r10,7*8(%rsp) + movq %r11,6*8(%rsp) + movq %rbx,5*8(%rsp) + movq %rbp,4*8(%rsp) + movq %r12,3*8(%rsp) + movq %r13,2*8(%rsp) + movq %r14,1*8(%rsp) + movq %r15,(%rsp) + xorl %ebx,%ebx testl $3,CS(%rsp) je error_kernelspace error_swapgs: - xorl %ebx,%ebx swapgs error_sti: movq %rdi,RDI(%rsp) @@ -557,13 +564,14 @@ iretq error_kernelspace: + incl %ebx /* There are two places in the kernel that can potentially fault with - usergs. Handle them here. */ + usergs. Handle them here. The exception handlers after + iret run with kernel gs again, so don't set the user space flag. */ cmpq $iret_label,RIP(%rsp) je error_swapgs cmpq $gs_change,RIP(%rsp) je error_swapgs - movl $1,%ebx jmp error_sti /* Reload gs selector with exception handling */ @@ -584,7 +592,9 @@ .quad gs_change,bad_gs .previous .section .fixup,"ax" + /* running with kernelgs */ bad_gs: + swapgs /* switch back to user gs */ xorl %eax,%eax movl %eax,%gs jmp 2b @@ -614,12 +624,8 @@ # clone now call do_fork - + movq %rax,RAX(%rsp) xorl %edi,%edi - cmpq $-1000,%rax - jnb 1f - movl tsk_pid(%rax),%eax -1: movq %rax,RAX(%rsp) /* * It isn't worth to check for reschedule here, diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/head.S linux-2.5.69-bk17/arch/x86_64/kernel/head.S --- linux-2.5.69-bk16/arch/x86_64/kernel/head.S 2003-05-04 16:53:33.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/head.S 2003-05-24 04:33:33.000000000 -0700 @@ -351,7 +351,7 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ - .quad 0x0000000000000000 /* unused */ + .quad 0x00af9a000000ffff ^ (1<<21) /* __KERNEL_COMPAT32_CS */ .quad 0x00af9a000000ffff /* __KERNEL_CS */ .quad 0x00cf92000000ffff /* __KERNEL_DS */ .quad 0x00cffe000000ffff /* __USER32_CS */ diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/io_apic.c linux-2.5.69-bk17/arch/x86_64/kernel/io_apic.c --- linux-2.5.69-bk16/arch/x86_64/kernel/io_apic.c 2003-05-04 16:53:29.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/io_apic.c 2003-05-24 04:33:33.000000000 -0700 @@ -1060,7 +1060,8 @@ phys_id_present_map |= 1 << i; mp_ioapics[apic].mpc_apicid = i; } else { - printk("Setting %d in the phys_id_present_map\n", mp_ioapics[apic].mpc_apicid); + printk(KERN_INFO + "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid); phys_id_present_map |= 1 << mp_ioapics[apic].mpc_apicid; } diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/ioport.c linux-2.5.69-bk17/arch/x86_64/kernel/ioport.c --- linux-2.5.69-bk16/arch/x86_64/kernel/ioport.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/ioport.c 2003-05-24 04:33:33.000000000 -0700 @@ -1,5 +1,5 @@ /* - * linux/arch/i386/kernel/ioport.c + * linux/arch/x86_64/kernel/ioport.c * * This contains the io-permission bitmap code - written by obz, with changes * by Linus. @@ -15,34 +15,35 @@ #include #include #include +#include /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) { - int mask; - unsigned long *bitmap_base = bitmap + (base >> 6); + unsigned long mask; + unsigned long *bitmap_base = bitmap + (base / sizeof(unsigned long)); unsigned short low_index = base & 0x3f; int length = low_index + extent; if (low_index != 0) { - mask = (~0 << low_index); + mask = (~0UL << low_index); if (length < 64) - mask &= ~(~0 << length); + mask &= ~(~0UL << length); if (new_value) *bitmap_base++ |= mask; else *bitmap_base++ &= ~mask; - length -= 32; + length -= 64; } - mask = (new_value ? ~0 : 0); + mask = (new_value ? ~0UL : 0UL); while (length >= 64) { *bitmap_base++ = mask; length -= 64; } if (length > 0) { - mask = ~(~0 << length); + mask = ~(~0UL << length); if (new_value) *bitmap_base++ |= mask; else @@ -113,3 +114,10 @@ regs.eflags = (regs.eflags & 0xffffffffffffcfff) | (level << 12); return 0; } + +void eat_key(void) +{ + if (inb(0x60) & 1) + inb(0x64); +} + diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/irq.c linux-2.5.69-bk17/arch/x86_64/kernel/irq.c --- linux-2.5.69-bk16/arch/x86_64/kernel/irq.c 2003-05-24 04:33:28.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/irq.c 2003-05-24 04:33:33.000000000 -0700 @@ -795,7 +795,7 @@ { unsigned char hexnum [HEX_DIGITS]; unsigned long value; - int i; + unsigned i; if (!count) return -EINVAL; diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/ldt.c linux-2.5.69-bk17/arch/x86_64/kernel/ldt.c --- linux-2.5.69-bk16/arch/x86_64/kernel/ldt.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/ldt.c 2003-05-24 04:33:33.000000000 -0700 @@ -32,13 +32,13 @@ } #endif -static int alloc_ldt(mm_context_t *pc, int mincount, int reload) +static int alloc_ldt(mm_context_t *pc, unsigned mincount, int reload) { void *oldldt; void *newldt; - int oldsize; + unsigned oldsize; - if (mincount <= pc->size) + if (mincount <= (unsigned)pc->size) return 0; oldsize = pc->size; mincount = (mincount+511)&(~511); @@ -63,7 +63,7 @@ #ifdef CONFIG_SMP preempt_disable(); load_LDT(pc); - if (current->mm->cpu_vm_mask != (1<mm->cpu_vm_mask != (1UL<context.size) { - if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE) + if ((unsigned)mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE) vfree(mm->context.ldt); else kfree(mm->context.ldt); @@ -190,7 +190,7 @@ } down(&mm->context.sem); - if (ldt_info.entry_number >= mm->context.size) { + if (ldt_info.entry_number >= (unsigned)mm->context.size) { error = alloc_ldt(¤t->mm->context, ldt_info.entry_number+1, 1); if (error < 0) goto out_unlock; diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/mpparse.c linux-2.5.69-bk17/arch/x86_64/kernel/mpparse.c --- linux-2.5.69-bk16/arch/x86_64/kernel/mpparse.c 2003-05-04 16:53:09.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/mpparse.c 2003-05-24 04:33:33.000000000 -0700 @@ -892,11 +892,15 @@ list_for_each(node, &acpi_prt.entries) { entry = list_entry(node, struct acpi_prt_entry, node); - /* We're only interested in static (non-link) entries. */ - if (entry->link.handle) + /* Need to get irq for dynamic entry */ + if (entry->link.handle) { + irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index); + if (!irq) continue; - + } + else irq = entry->link.index; + ioapic = mp_find_ioapic(irq); if (ioapic < 0) continue; diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/pci-dma.c linux-2.5.69-bk17/arch/x86_64/kernel/pci-dma.c --- linux-2.5.69-bk16/arch/x86_64/kernel/pci-dma.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/pci-dma.c 2003-05-24 04:33:33.000000000 -0700 @@ -32,7 +32,6 @@ int i; BUG_ON(direction == PCI_DMA_NONE); - for (i = 0; i < nents; i++ ) { struct scatterlist *s = &sg[i]; diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/pci-gart.c linux-2.5.69-bk17/arch/x86_64/kernel/pci-gart.c --- linux-2.5.69-bk16/arch/x86_64/kernel/pci-gart.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/pci-gart.c 2003-05-24 04:33:33.000000000 -0700 @@ -14,15 +14,10 @@ /* * Notebook: -agpgart_be - check if the simple reservation scheme is enough. - possible future tuning: - fast path for sg streaming mappings - more intelligent flush strategy - flush only a single NB? flush only when - gart area fills up and alloc_iommu wraps. - don't flush on allocation - need to unmap the gart area first to avoid prefetches - by the CPU + fast path for sg streaming mappings - only take the locks once. + more intelligent flush strategy - flush only the NB of the CPU directly + connected to the device? move boundary between IOMMU and AGP in GART dynamically */ @@ -67,7 +62,8 @@ #define GPTE_VALID 1 #define GPTE_COHERENT 2 -#define GPTE_ENCODE(x) (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT) +#define GPTE_ENCODE(x) \ + (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT) #define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28)) #define for_all_nb(dev) \ @@ -90,20 +86,23 @@ static unsigned long next_bit; /* protected by iommu_bitmap_lock */ -static unsigned long alloc_iommu(int size) +static unsigned long alloc_iommu(int size, int *flush) { unsigned long offset, flags; spin_lock_irqsave(&iommu_bitmap_lock, flags); - offset = find_next_zero_string(iommu_gart_bitmap,next_bit,iommu_pages,size); - if (offset == -1) + if (offset == -1) { + *flush = 1; offset = find_next_zero_string(iommu_gart_bitmap,0,next_bit,size); + } if (offset != -1) { set_bit_string(iommu_gart_bitmap, offset, size); next_bit = offset+size; - if (next_bit >= iommu_pages) + if (next_bit >= iommu_pages) { next_bit = 0; + *flush = 1; + } } spin_unlock_irqrestore(&iommu_bitmap_lock, flags); return offset; @@ -114,7 +113,6 @@ unsigned long flags; spin_lock_irqsave(&iommu_bitmap_lock, flags); clear_bit_string(iommu_gart_bitmap, offset, size); - next_bit = offset; spin_unlock_irqrestore(&iommu_bitmap_lock, flags); } @@ -137,6 +135,7 @@ int gfp = GFP_ATOMIC; int i; unsigned long iommu_page; + int flush = 0; if (hwdev == NULL || hwdev->dma_mask < 0xffffffff || no_iommu) gfp |= GFP_DMA; @@ -150,9 +149,10 @@ if (memory == NULL) { return NULL; } else { - int high = (unsigned long)virt_to_bus(memory) + size - >= 0xffffffff; - int mmu = high; + int high = 0, mmu; + if (((unsigned long)virt_to_bus(memory) + size) > 0xffffffffUL) + high = 1; + mmu = 1; if (force_mmu && !(gfp & GFP_DMA)) mmu = 1; if (no_iommu) { @@ -168,7 +168,7 @@ size >>= PAGE_SHIFT; - iommu_page = alloc_iommu(size); + iommu_page = alloc_iommu(size, &flush); if (iommu_page == -1) goto error; @@ -183,6 +183,7 @@ iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem); } + if (flush) flush_gart(); *dma_handle = iommu_bus_base + (iommu_page << PAGE_SHIFT); return memory; @@ -199,25 +200,24 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t bus) { - u64 pte; unsigned long iommu_page; - int i; size = round_up(size, PAGE_SIZE); - if (bus < iommu_bus_base || bus > iommu_bus_base + iommu_size) { - free_pages((unsigned long)vaddr, get_order(size)); - return; - } - size >>= PAGE_SHIFT; - iommu_page = (bus - iommu_bus_base) / PAGE_SIZE; - for (i = 0; i < size; i++) { - pte = iommu_gatt_base[iommu_page + i]; + if (bus >= iommu_bus_base && bus <= iommu_bus_base + iommu_size) { + unsigned pages = size >> PAGE_SHIFT; + iommu_page = (bus - iommu_bus_base) >> PAGE_SHIFT; + vaddr = __va(GPTE_DECODE(iommu_gatt_base[iommu_page])); +#ifdef CONFIG_IOMMU_DEBUG + int i; + for (i = 0; i < pages; i++) { + u64 pte = iommu_gatt_base[iommu_page + i]; BUG_ON((pte & GPTE_VALID) == 0); iommu_gatt_base[iommu_page + i] = 0; - free_page((unsigned long) __va(GPTE_DECODE(pte))); } - flush_gart(); - free_iommu(iommu_page, size); +#endif + free_iommu(iommu_page, pages); + } + free_pages((unsigned long)vaddr, get_order(size)); } #ifdef CONFIG_IOMMU_LEAK @@ -257,7 +257,7 @@ */ printk(KERN_ERR - "PCI-DMA: Error: ran out out IOMMU space for %p size %lu at device %s[%s]\n", + "PCI-DMA: Out of IOMMU space for %p size %lu at device %s[%s]\n", addr,size, dev ? dev->dev.name : "?", dev ? dev->slot_name : "?"); if (size > PAGE_SIZE*EMERGENCY_PAGES) { @@ -287,12 +287,12 @@ return mmu; } -dma_addr_t __pci_map_single(struct pci_dev *dev, void *addr, size_t size, - int dir, int flush) +dma_addr_t pci_map_single(struct pci_dev *dev, void *addr, size_t size, int dir) { unsigned long iommu_page; unsigned long phys_mem, bus; int i, npages; + int flush = 0; BUG_ON(dir == PCI_DMA_NONE); @@ -302,7 +302,7 @@ npages = round_up(size + ((u64)addr & ~PAGE_MASK), PAGE_SIZE) >> PAGE_SHIFT; - iommu_page = alloc_iommu(npages); + iommu_page = alloc_iommu(npages, &flush); if (iommu_page == -1) { iommu_full(dev, addr, size, dir); return iommu_bus_base; @@ -343,12 +343,14 @@ size_t size, int direction) { unsigned long iommu_page; - int i, npages; + int npages; if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || dma_addr > iommu_bus_base + iommu_size) return; iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT; npages = round_up(size + (dma_addr & ~PAGE_MASK), PAGE_SIZE) >> PAGE_SHIFT; +#ifdef CONFIG_IOMMU_DEBUG + int i; for (i = 0; i < npages; i++) { iommu_gatt_base[iommu_page + i] = 0; #ifdef CONFIG_IOMMU_LEAK @@ -356,11 +358,11 @@ iommu_leak_tab[iommu_page + i] = 0; #endif } - flush_gart(); +#endif free_iommu(iommu_page, npages); } -EXPORT_SYMBOL(__pci_map_single); +EXPORT_SYMBOL(pci_map_single); EXPORT_SYMBOL(pci_unmap_single); static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) @@ -407,7 +409,7 @@ * Private Northbridge GATT initialization in case we cannot use the * AGP driver for some reason. */ -static __init int init_k8_gatt(agp_kern_info *info) +static __init int init_k8_gatt(struct agp_kern_info *info) { struct pci_dev *dev; void *gatt; @@ -443,7 +445,7 @@ u32 ctl; u32 gatt_reg; - gatt_reg = ((u64)gatt) >> 12; + gatt_reg = __pa(gatt) >> 12; gatt_reg <<= 4; pci_write_config_dword(dev, 0x98, gatt_reg); pci_read_config_dword(dev, 0x90, &ctl); @@ -465,9 +467,11 @@ return -1; } +extern int agp_amdk8_init(void); + void __init pci_iommu_init(void) { - agp_kern_info info; + struct agp_kern_info info; unsigned long aper_size; unsigned long iommu_start; @@ -476,7 +480,6 @@ #else /* Add other K8 AGP bridge drivers here */ no_agp = no_agp || - (agp_init() < 0) || (agp_amdk8_init() < 0) || (agp_copy_info(&info) < 0); #endif @@ -536,8 +539,17 @@ iommu_gatt_base = agp_gatt_table + (iommu_start>>PAGE_SHIFT); bad_dma_address = iommu_bus_base; - change_page_attr(virt_to_page(__va(iommu_start)), iommu_pages, PAGE_KERNEL); - global_flush_tlb(); + /* + * Unmap the IOMMU part of the GART. The alias of the page is always mapped + * with cache enabled and there is no full cache coherency across the GART + * remapping. The unmapping avoids automatic prefetches from the CPU + * allocating cache lines in there. All CPU accesses are done via the + * direct mapping to the backing memory. The GART address is only used by PCI + * devices. + */ + clear_kernel_mapping((unsigned long)__va(iommu_bus_base), iommu_size); + + flush_gart(); } /* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]] diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/process.c linux-2.5.69-bk17/arch/x86_64/kernel/process.c --- linux-2.5.69-bk16/arch/x86_64/kernel/process.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/process.c 2003-05-24 04:33:33.000000000 -0700 @@ -216,7 +216,12 @@ { struct task_struct *tsk = current; - memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); + tsk->thread.debugreg0 = 0; + tsk->thread.debugreg1 = 0; + tsk->thread.debugreg2 = 0; + tsk->thread.debugreg3 = 0; + tsk->thread.debugreg6 = 0; + tsk->thread.debugreg7 = 0; memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); /* * Forget coprocessor state.. @@ -285,7 +290,7 @@ childregs->rax = 0; childregs->rsp = rsp; - if (rsp == ~0) { + if (rsp == ~0UL) { childregs->rsp = (unsigned long)childregs; } p->set_child_tid = p->clear_child_tid = NULL; @@ -294,7 +299,7 @@ p->thread.rsp0 = (unsigned long) (childregs+1); p->thread.userrsp = me->thread.userrsp; - p->thread.rip = (unsigned long) ret_from_fork; + set_ti_thread_flag(p->thread_info, TIF_FORK); p->thread.fs = me->thread.fs; p->thread.gs = me->thread.gs; @@ -335,8 +340,7 @@ /* * This special macro can be used to load a debugging register */ -#define loaddebug(thread,register) \ - set_debug(thread->debugreg[register], register) +#define loaddebug(thread,r) set_debug(thread->debugreg ## r, r) /* * switch_to(x,y) should switch tasks from x to y. @@ -422,7 +426,7 @@ /* * Now maybe reload the debug registers */ - if (unlikely(next->debugreg[7])) { + if (unlikely(next->debugreg7)) { loaddebug(next, 0); loaddebug(next, 1); loaddebug(next, 2); @@ -490,19 +494,15 @@ asmlinkage long sys_fork(struct pt_regs regs) { - struct task_struct *p; - p = do_fork(SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); } asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void *parent_tid, void *child_tid, struct pt_regs regs) { - struct task_struct *p; if (!newsp) newsp = regs.rsp; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tid, child_tid); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; } /* @@ -517,10 +517,8 @@ */ asmlinkage long sys_vfork(struct pt_regs regs) { - struct task_struct *p; - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, ®s, 0, + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; } /* diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/ptrace.c linux-2.5.69-bk17/arch/x86_64/kernel/ptrace.c --- linux-2.5.69-bk16/arch/x86_64/kernel/ptrace.c 2003-05-04 16:53:09.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/ptrace.c 2003-05-24 04:33:33.000000000 -0700 @@ -178,11 +178,11 @@ } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data) { struct task_struct *child; - struct user * dummy = NULL; long i, ret; + unsigned ui; /* This lock_kernel fixes a subtle race with suid exec */ lock_kernel(); @@ -240,18 +240,35 @@ unsigned long tmp; ret = -EIO; - if ((addr & 7) || addr < 0 || + if ((addr & 7) || addr > sizeof(struct user) - 7) break; - tmp = 0; /* Default return condition */ - if(addr < sizeof(struct user_regs_struct)) + switch (addr) { + case 0 ... sizeof(struct user_regs_struct): tmp = getreg(child, addr); - if(addr >= (long) &dummy->u_debugreg[0] && - addr <= (long) &dummy->u_debugreg[7]){ - addr -= (long) &dummy->u_debugreg[0]; - addr = addr >> 3; - tmp = child->thread.debugreg[addr]; + break; + case offsetof(struct user, u_debugreg[0]): + tmp = child->thread.debugreg0; + break; + case offsetof(struct user, u_debugreg[1]): + tmp = child->thread.debugreg1; + break; + case offsetof(struct user, u_debugreg[2]): + tmp = child->thread.debugreg2; + break; + case offsetof(struct user, u_debugreg[3]): + tmp = child->thread.debugreg3; + break; + case offsetof(struct user, u_debugreg[6]): + tmp = child->thread.debugreg6; + break; + case offsetof(struct user, u_debugreg[7]): + tmp = child->thread.debugreg7; + break; + default: + tmp = 0; + break; } ret = put_user(tmp,(unsigned long *) data); break; @@ -268,47 +285,53 @@ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ ret = -EIO; - if ((addr & 7) || addr < 0 || + if ((addr & 7) || addr > sizeof(struct user) - 7) break; - if (addr < sizeof(struct user_regs_struct)) { + switch (addr) { + case 0 ... sizeof(struct user_regs_struct): ret = putreg(child, addr, data); break; - } - /* We need to be very careful here. We implicitly - want to modify a portion of the task_struct, and we - have to be selective about what portions we allow someone - to modify. */ - - ret = -EIO; - if(addr >= (long) &dummy->u_debugreg[0] && - addr <= (long) &dummy->u_debugreg[7]){ - - if(addr == (long) &dummy->u_debugreg[4]) break; - if(addr == (long) &dummy->u_debugreg[5]) break; - if(addr < (long) &dummy->u_debugreg[4] && - ((unsigned long) data) >= TASK_SIZE-3) break; - - if (addr == (long) &dummy->u_debugreg[6]) { + /* Disallows to set a breakpoint into the vsyscall */ + case offsetof(struct user, u_debugreg[0]): + if (data >= TASK_SIZE-7) break; + child->thread.debugreg0 = data; + ret = 0; + break; + case offsetof(struct user, u_debugreg[1]): + if (data >= TASK_SIZE-7) break; + child->thread.debugreg1 = data; + ret = 0; + break; + case offsetof(struct user, u_debugreg[2]): + if (data >= TASK_SIZE-7) break; + child->thread.debugreg2 = data; + ret = 0; + break; + case offsetof(struct user, u_debugreg[3]): + if (data >= TASK_SIZE-7) break; + child->thread.debugreg3 = data; + ret = 0; + break; + case offsetof(struct user, u_debugreg[6]): if (data >> 32) - goto out_tsk; - } - - if(addr == (long) &dummy->u_debugreg[7]) { + break; + child->thread.debugreg6 = data; + ret = 0; + break; + case offsetof(struct user, u_debugreg[7]): data &= ~DR_CONTROL_RESERVED; for(i=0; i<4; i++) if ((0x5454 >> ((data >> (16 + 4*i)) & 0xf)) & 1) - goto out_tsk; - } - - addr -= (long) &dummy->u_debugreg; - addr = addr >> 3; - child->thread.debugreg[addr] = data; + break; + if (i == 4) { + child->thread.debugreg7 = data; ret = 0; } break; - + } + break; case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ long tmp; @@ -408,8 +431,8 @@ ret = -EIO; break; } - for ( i = 0; i < sizeof(struct user_regs_struct); i += sizeof(long) ) { - __put_user(getreg(child, i),(unsigned long *) data); + for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) { + __put_user(getreg(child, ui),(unsigned long *) data); data += sizeof(long); } ret = 0; @@ -422,9 +445,9 @@ ret = -EIO; break; } - for ( i = 0; i < sizeof(struct user_regs_struct); i += sizeof(long) ) { + for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) { __get_user(tmp, (unsigned long *) data); - putreg(child, i, tmp); + putreg(child, ui, tmp); data += sizeof(long); } ret = 0; diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/reboot.c linux-2.5.69-bk17/arch/x86_64/kernel/reboot.c --- linux-2.5.69-bk16/arch/x86_64/kernel/reboot.c 2003-05-24 04:33:28.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/reboot.c 2003-05-24 04:33:33.000000000 -0700 @@ -9,7 +9,9 @@ #include #include #include - +#include +#include +#include /* * Power off function, if any @@ -17,35 +19,37 @@ void (*pm_power_off)(void); static long no_idt[3]; -static int reboot_mode; - -#ifdef CONFIG_SMP -int reboot_smp = 0; -static int reboot_cpu = -1; -#endif - +static enum { + BOOT_BIOS = 'b', + BOOT_TRIPLE = 't', + BOOT_KBD = 'k' +} reboot_type = BOOT_KBD; +static int reboot_mode = 0; + +/* reboot=b[ios] | t[riple] | k[bd] [, [w]arm | [c]old] + bios Use the CPU reboto vector for warm reset + warm Don't set the cold reboot flag + cold Set the cold reboto flag + triple Force a triple fault (init) + kbd Use the keyboard controller. cold reset (default) + */ static int __init reboot_setup(char *str) { - while(1) { + for (;;) { switch (*str) { - case 'w': /* "warm" reboot (no memory testing etc) */ + case 'w': reboot_mode = 0x1234; break; - case 'c': /* "cold" reboot (with memory testing etc) */ - reboot_mode = 0x0; + + case 'c': + reboot_mode = 0; break; -#ifdef CONFIG_SMP - case 's': /* "smp" reboot by executing reset on BSP or other CPU*/ - reboot_smp = 1; - if (isdigit(str[1])) - sscanf(str+1, "%d", &reboot_cpu); - else if (!strncmp(str,"smp",3)) - sscanf(str+3, "%d", &reboot_cpu); - /* we will leave sorting out the final value - when we are ready to reboot, since we might not - have set up boot_cpu_id or smp_num_cpu */ + + case 't': + case 'b': + case 'k': + reboot_type = *str; break; -#endif } if((str = strchr(str,',')) != NULL) str++; @@ -57,6 +61,56 @@ __setup("reboot=", reboot_setup); +/* overwrites random kernel memory. Should not be kernel .text */ +#define WARMBOOT_TRAMP 0x1000UL + +static void reboot_warm(void) +{ + extern unsigned char warm_reboot[], warm_reboot_end[]; + printk("warm reboot\n"); + + local_irq_disable(); + + /* restore identity mapping */ + init_level4_pgt[0] = __pml4(__pa(level3_ident_pgt) | 7); + __flush_tlb_all(); + + /* Move the trampoline to low memory */ + memcpy(__va(WARMBOOT_TRAMP), warm_reboot, warm_reboot_end - warm_reboot); + + /* Start it in compatibility mode. */ + asm volatile( " pushq $0\n" /* ss */ + " pushq $0x2000\n" /* rsp */ + " pushfq\n" /* eflags */ + " pushq %[cs]\n" + " pushq %[target]\n" + " iretq" :: + [cs] "i" (__KERNEL_COMPAT32_CS), + [target] "b" (WARMBOOT_TRAMP)); +} + +#ifdef CONFIG_SMP +static void smp_halt(void) +{ + int cpuid = safe_smp_processor_id(); + + /* Only run this on the boot processor */ + if (cpuid != boot_cpu_id) { + static int first_entry = 1; + if (first_entry) { + first_entry = 0; + smp_call_function((void *)machine_restart, NULL, 1, 0); + } else { + /* AP reentering. just halt */ + for(;;) + asm volatile("hlt"); + } + + } + smp_send_stop(); +} +#endif + static inline void kb_wait(void) { int i; @@ -68,48 +122,24 @@ void machine_restart(char * __unused) { -#ifdef CONFIG_SMP - int cpuid; - - cpuid = GET_APIC_ID(apic_read(APIC_ID)); - - if (reboot_smp) { + int i; - /* check to see if reboot_cpu is valid - if its not, default to the BSP */ - if ((reboot_cpu == -1) || - (reboot_cpu > (NR_CPUS -1)) || - !(phys_cpu_present_map & (1<x86_power & (1 << i)) { if (i < ARRAY_SIZE(x86_power_flags)) diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/setup64.c linux-2.5.69-bk17/arch/x86_64/kernel/setup64.c --- linux-2.5.69-bk16/arch/x86_64/kernel/setup64.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/setup64.c 2003-05-24 04:33:33.000000000 -0700 @@ -23,6 +23,7 @@ #include #include #include +#include char x86_boot_params[2048] __initdata = {0,}; @@ -40,22 +41,79 @@ char boot_cpu_stack[IRQSTACKSIZE] __cacheline_aligned; unsigned long __supported_pte_mask = ~0UL; -static int do_not_nx = 1; +static int do_not_nx __initdata = 0; +unsigned long vm_stack_flags = __VM_STACK_FLAGS; +unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; +unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; +unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; +unsigned long vm_force_exec32 = PROT_EXEC; + +/* noexec=on|off +Control non executable mappings for 64bit processes. + +on Enable +off Disable +noforce (default) Don't enable by default for heap/stack/data, + but allow PROT_EXEC to be effective +*/ static int __init nonx_setup(char *str) { - if (!strncmp(str,"off",3)) { - __supported_pte_mask &= ~_PAGE_NX; - do_not_nx = 1; - } else if (!strncmp(str, "on",3)) { - do_not_nx = 0; + if (!strncmp(str, "on",3)) { __supported_pte_mask |= _PAGE_NX; + do_not_nx = 0; + vm_data_default_flags &= ~VM_EXEC; + vm_stack_flags &= ~VM_EXEC; + } else if (!strncmp(str, "noforce",7) || !strncmp(str,"off",3)) { + do_not_nx = (str[0] == 'o'); + if (do_not_nx) + __supported_pte_mask &= ~_PAGE_NX; + vm_data_default_flags |= VM_EXEC; + vm_stack_flags |= VM_EXEC; } return 1; } __setup("noexec=", nonx_setup); +/* noexec32=opt{,opt} + +Control the no exec default for 32bit processes. Can be also overwritten +per executable using ELF header flags (e.g. needed for the X server) +Requires noexec=on or noexec=noforce to be effective. + +Valid options: + all,on Heap,stack,data is non executable. + off (default) Heap,stack,data is executable + stack Stack is non executable, heap/data is. + force Don't imply PROT_EXEC for PROT_READ + compat (default) Imply PROT_EXEC for PROT_READ + +*/ + static int __init nonx32_setup(char *str) + { + char *s; + while ((s = strsep(&str, ",")) != NULL) { + if (!strcmp(s, "all") || !strcmp(s,"on")) { + vm_data_default_flags32 &= ~VM_EXEC; + vm_stack_flags32 &= ~VM_EXEC; + } else if (!strcmp(s, "off")) { + vm_data_default_flags32 |= VM_EXEC; + vm_stack_flags32 |= VM_EXEC; + } else if (!strcmp(s, "stack")) { + vm_data_default_flags32 |= VM_EXEC; + vm_stack_flags32 &= ~VM_EXEC; + } else if (!strcmp(s, "force")) { + vm_force_exec32 = 0; + } else if (!strcmp(s, "compat")) { + vm_force_exec32 = PROT_EXEC; + } + } + return 1; +} + +__setup("noexec32=", nonx32_setup); + #ifndef __GENERIC_PER_CPU unsigned long __per_cpu_offset[NR_CPUS]; diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/signal.c linux-2.5.69-bk17/arch/x86_64/kernel/signal.c --- linux-2.5.69-bk16/arch/x86_64/kernel/signal.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/signal.c 2003-05-24 04:33:33.000000000 -0700 @@ -371,7 +371,7 @@ regs->rax = regs->orig_rax; regs->rip -= 2; } - if (regs->rax == -ERESTART_RESTARTBLOCK){ + if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK){ regs->rax = __NR_restart_syscall; regs->rip -= 2; } @@ -434,8 +434,8 @@ * have been cleared if the watchpoint triggered * inside the kernel. */ - if (current->thread.debugreg[7]) - asm volatile("movq %0,%%db7" : : "r" (current->thread.debugreg[7])); + if (current->thread.debugreg7) + asm volatile("movq %0,%%db7" : : "r" (current->thread.debugreg7)); /* Whee! Actually deliver the signal. */ handle_signal(signr, &info, oldset, regs); @@ -446,9 +446,10 @@ /* Did we come from a system call? */ if (regs->orig_rax >= 0) { /* Restart the system call - no handlers present */ - if (regs->rax == -ERESTARTNOHAND || - regs->rax == -ERESTARTSYS || - regs->rax == -ERESTARTNOINTR) { + long res = regs->rax; + if (res == -ERESTARTNOHAND || + res == -ERESTARTSYS || + res == -ERESTARTNOINTR) { regs->rax = regs->orig_rax; regs->rip -= 2; } diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/smpboot.c linux-2.5.69-bk17/arch/x86_64/kernel/smpboot.c --- linux-2.5.69-bk16/arch/x86_64/kernel/smpboot.c 2003-05-04 16:53:57.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/smpboot.c 2003-05-24 04:33:33.000000000 -0700 @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -123,7 +124,7 @@ unsigned long long t0; unsigned long long sum, avg; long long delta; - unsigned long one_usec; + long one_usec; int buggy = 0; extern unsigned cpu_khz; @@ -339,7 +340,7 @@ /* * Activate a secondary processor. */ -int __init start_secondary(void *unused) +void __init start_secondary(void) { /* * Dont put anything before smp_callin(), SMP @@ -380,29 +381,7 @@ set_bit(smp_processor_id(), &cpu_online_map); wmb(); - return cpu_idle(); -} - -/* - * Everything has been set up for the secondary - * CPUs - they just need to reload everything - * from the task structure - * This function must not return. - */ -void __init initialize_secondary(void) -{ - struct task_struct *me = stack_current(); - - /* - * We don't actually need to load the full TSS, - * basically just the stack pointer and the eip. - */ - - asm volatile( - "movq %0,%%rsp\n\t" - "jmp *%1" - : - :"r" (me->thread.rsp),"r" (me->thread.rip)); + cpu_idle(); } extern volatile unsigned long init_rsp; @@ -412,16 +391,16 @@ { struct pt_regs regs; /* - * don't care about the rip and regs settings since + * don't care about the eip and regs settings since * we'll never reschedule the forked task. */ - return do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); } #if APIC_DEBUG static inline void inquire_remote_apic(int apicid) { - int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; + unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; char *names[] = { "ID", "VERSION", "SPIV" }; int timeout, status; @@ -596,6 +575,7 @@ idle = fork_by_hand(); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); + wake_up_forked_process(idle); /* * We remove it from the pidhash and the runqueue @@ -603,22 +583,19 @@ */ init_idle(idle,cpu); - idle->thread.rip = (unsigned long)start_secondary; -// idle->thread.rsp = (unsigned long)idle->thread_info + THREAD_SIZE - 512; - unhash_process(idle); cpu_pda[cpu].pcurrent = idle; - /* start_eip had better be page-aligned! */ start_rip = setup_trampoline(); - init_rsp = (unsigned long)idle->thread_info + PAGE_SIZE + 1024; + init_rsp = idle->thread.rsp; init_tss[cpu].rsp0 = init_rsp; - initial_code = initialize_secondary; + initial_code = start_secondary; + clear_ti_thread_flag(idle->thread_info, TIF_FORK); - printk(KERN_INFO "Booting processor %d/%d rip %lx rsp %lx rsp2 %lx\n", cpu, apicid, - start_rip, idle->thread.rsp, init_rsp); + printk(KERN_INFO "Booting processor %d/%d rip %lx rsp %lx\n", cpu, apicid, + start_rip, init_rsp); /* * This grunge runs the startup process for @@ -676,7 +653,7 @@ if (test_bit(cpu, &cpu_callin_map)) { /* number CPUs logically, starting from 1 (BSP is 0) */ Dprintk("OK.\n"); - printk("KERN_INFO CPU%d: ", cpu); + printk(KERN_INFO "CPU%d: ", cpu); print_cpu_info(&cpu_data[cpu]); Dprintk("CPU has booted.\n"); } else { @@ -708,7 +685,7 @@ static void smp_tune_scheduling (void) { - unsigned long cachesize; /* kB */ + int cachesize; /* kB */ unsigned long bandwidth = 1000; /* MB/s */ /* * Rough estimation for SMP scheduling, this is the number of @@ -753,7 +730,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) { - int apicid, cpu; + unsigned apicid, cpu; /* * Setup boot CPU information diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/sys_x86_64.c linux-2.5.69-bk17/arch/x86_64/kernel/sys_x86_64.c --- linux-2.5.69-bk16/arch/x86_64/kernel/sys_x86_64.c 2003-05-04 16:53:33.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/sys_x86_64.c 2003-05-24 04:33:33.000000000 -0700 @@ -117,5 +117,5 @@ asmlinkage long wrap_sys_shmat(int shmid, char *shmaddr, int shmflg) { unsigned long raddr; - return sys_shmat(shmid,shmaddr,shmflg,&raddr) ?: raddr; + return sys_shmat(shmid,shmaddr,shmflg,&raddr) ?: (long)raddr; } diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/traps.c linux-2.5.69-bk17/arch/x86_64/kernel/traps.c --- linux-2.5.69-bk16/arch/x86_64/kernel/traps.c 2003-05-24 04:33:28.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/traps.c 2003-05-24 04:33:33.000000000 -0700 @@ -584,12 +584,12 @@ /* Mask out spurious debug traps due to lazy DR7 setting */ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { - if (!tsk->thread.debugreg[7]) { + if (!tsk->thread.debugreg7) { goto clear_dr7; } } - tsk->thread.debugreg[6] = condition; + tsk->thread.debugreg6 = condition; /* Mask out spurious TF errors due to lazy TF clearing */ if (condition & DR_STEP) { diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/vsyscall.S linux-2.5.69-bk17/arch/x86_64/kernel/vsyscall.S --- linux-2.5.69-bk16/arch/x86_64/kernel/vsyscall.S 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.69-bk17/arch/x86_64/kernel/vsyscall.S 2003-05-24 04:33:33.000000000 -0700 @@ -0,0 +1,169 @@ +/* + * Code for the vsyscall page. This version uses the syscall instruction. + */ + +#include +#include + + .text + .globl __kernel_vsyscall + .type __kernel_vsyscall,@function +__kernel_vsyscall: +.LSTART_vsyscall: + push %ebp +.Lpush_ebp: + movl %ecx, %ebp + syscall + popl %ebp +.Lpop_ebp: + ret +.LEND_vsyscall: + .size __kernel_vsyscall,.-.LSTART_vsyscall + + .balign 32 + .globl __kernel_sigreturn + .type __kernel_sigreturn,@function +__kernel_sigreturn: +.LSTART_sigreturn: + popl %eax + movl $__NR_ia32_sigreturn, %eax + syscall +.LEND_sigreturn: + .size __kernel_sigreturn,.-.LSTART_sigreturn + + .balign 32 + .globl __kernel_rt_sigreturn + .type __kernel_rt_sigreturn,@function +__kernel_rt_sigreturn: +.LSTART_rt_sigreturn: + movl $__NR_ia32_rt_sigreturn, %eax + syscall +.LEND_rt_sigreturn: + .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE +.LSTARTCIE: + .long 0 /* CIE ID */ + .byte 1 /* Version number */ + .string "zR" /* NUL-terminated augmentation string */ + .uleb128 1 /* Code alignment factor */ + .sleb128 -4 /* Data alignment factor */ + .byte 8 /* Return address register column */ + .uleb128 1 /* Augmentation value length */ + .byte 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */ + .byte 0x0c /* DW_CFA_def_cfa */ + .uleb128 4 + .uleb128 4 + .byte 0x88 /* DW_CFA_offset, column 0x8 */ + .uleb128 1 + .align 4 +.LENDCIE: + + .long .LENDFDE1-.LSTARTFDE1 /* Length FDE */ +.LSTARTFDE1: + .long .LSTARTFDE1-.LSTARTFRAME /* CIE pointer */ + .long .LSTART_vsyscall-. /* PC-relative start address */ + .long .LEND_vsyscall-.LSTART_vsyscall + .uleb128 0 /* Augmentation length */ + /* What follows are the instructions for the table generation. + We have to record all changes of the stack pointer. */ + .byte 0x40 + .Lpush_ebp-.LSTART_vsyscall /* DW_CFA_advance_loc */ + .byte 0x0e /* DW_CFA_def_cfa_offset */ + .uleb128 8 + .byte 0x85, 0x02 /* DW_CFA_offset %ebp -8 */ + .byte 0x40 + .Lpop_ebp-.Lpush_ebp /* DW_CFA_advance_loc */ + .byte 0xc5 /* DW_CFA_restore %ebp */ + .byte 0x0e /* DW_CFA_def_cfa_offset */ + .uleb128 4 + .align 4 +.LENDFDE1: + + .long .LENDFDE2-.LSTARTFDE2 /* Length FDE */ +.LSTARTFDE2: + .long .LSTARTFDE2-.LSTARTFRAME /* CIE pointer */ + /* HACK: The dwarf2 unwind routines will subtract 1 from the + return address to get an address in the middle of the + presumed call instruction. Since we didn't get here via + a call, we need to include the nop before the real start + to make up for it. */ + .long .LSTART_sigreturn-1-. /* PC-relative start address */ + .long .LEND_sigreturn-.LSTART_sigreturn+1 + .uleb128 0 /* Augmentation length */ + /* What follows are the instructions for the table generation. + We record the locations of each register saved. This is + complicated by the fact that the "CFA" is always assumed to + be the value of the stack pointer in the caller. This means + that we must define the CFA of this body of code to be the + saved value of the stack pointer in the sigcontext. Which + also means that there is no fixed relation to the other + saved registers, which means that we must use DW_CFA_expression + to compute their addresses. It also means that when we + adjust the stack with the popl, we have to do it all over again. */ + +#define do_cfa_expr(offset) \ + .byte 0x0f; /* DW_CFA_def_cfa_expression */ \ + .uleb128 1f-0f; /* length */ \ +0: .byte 0x74; /* DW_OP_breg4 */ \ + .sleb128 offset; /* offset */ \ + .byte 0x06; /* DW_OP_deref */ \ +1: + +#define do_expr(regno, offset) \ + .byte 0x10; /* DW_CFA_expression */ \ + .uleb128 regno; /* regno */ \ + .uleb128 1f-0f; /* length */ \ +0: .byte 0x74; /* DW_OP_breg4 */ \ + .sleb128 offset; /* offset */ \ +1: + + do_cfa_expr(IA32_SIGCONTEXT_esp+4) + do_expr(0, IA32_SIGCONTEXT_eax+4) + do_expr(1, IA32_SIGCONTEXT_ecx+4) + do_expr(2, IA32_SIGCONTEXT_edx+4) + do_expr(3, IA32_SIGCONTEXT_ebx+4) + do_expr(5, IA32_SIGCONTEXT_ebp+4) + do_expr(6, IA32_SIGCONTEXT_esi+4) + do_expr(7, IA32_SIGCONTEXT_edi+4) + do_expr(8, IA32_SIGCONTEXT_eip+4) + + .byte 0x42 /* DW_CFA_advance_loc 2 -- nop; popl eax. */ + + do_cfa_expr(IA32_SIGCONTEXT_esp) + do_expr(0, IA32_SIGCONTEXT_eax) + do_expr(1, IA32_SIGCONTEXT_ecx) + do_expr(2, IA32_SIGCONTEXT_edx) + do_expr(3, IA32_SIGCONTEXT_ebx) + do_expr(5, IA32_SIGCONTEXT_ebp) + do_expr(6, IA32_SIGCONTEXT_esi) + do_expr(7, IA32_SIGCONTEXT_edi) + do_expr(8, IA32_SIGCONTEXT_eip) + + .align 4 +.LENDFDE2: + + .long .LENDFDE3-.LSTARTFDE3 /* Length FDE */ +.LSTARTFDE3: + .long .LSTARTFDE3-.LSTARTFRAME /* CIE pointer */ + /* HACK: See above wrt unwind library assumptions. */ + .long .LSTART_rt_sigreturn-1-. /* PC-relative start address */ + .long .LEND_rt_sigreturn-.LSTART_rt_sigreturn+1 + .uleb128 0 /* Augmentation */ + /* What follows are the instructions for the table generation. + We record the locations of each register saved. This is + slightly less complicated than the above, since we don't + modify the stack pointer in the process. */ + + do_cfa_expr(IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_esp) + do_expr(0, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_eax) + do_expr(1, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ecx) + do_expr(2, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_edx) + do_expr(3, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ebx) + do_expr(5, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ebp) + do_expr(6, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_esi) + do_expr(7, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_edi) + do_expr(8, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_eip) + + .align 4 +.LENDFDE3: diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/warmreboot.S linux-2.5.69-bk17/arch/x86_64/kernel/warmreboot.S --- linux-2.5.69-bk16/arch/x86_64/kernel/warmreboot.S 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.69-bk17/arch/x86_64/kernel/warmreboot.S 2003-05-24 04:33:33.000000000 -0700 @@ -0,0 +1,83 @@ +/* + * Switch back to real mode and call the BIOS reboot vector. + * This is a trampoline copied around in process.c + * Written 2003 by Andi Kleen, SuSE Labs. + */ + +#include + +#define R(x) x-warm_reboot(%ebx) +#define R64(x) x-warm_reboot(%rbx) + + /* running in identity mapping and in the first 64k of memory + and in compatibility mode. This must be position independent */ + + /* Follows 14.7 "Leaving Long Mode" in the AMD x86-64 manual, volume 2 + and 8.9.2 "Switching Back to Real-Address Mode" in the Intel IA32 + manual, volume 2 */ + + /* ebx: self pointer to warm_reboot */ + + .globl warm_reboot +warm_reboot: + addl %ebx, R64(real_mode_desc) /* relocate tables */ + addl %ebx,2+R64(warm_gdt_desc) + + movq %cr0,%rax + btr $31,%rax + movq %rax,%cr0 /* disable paging */ + jmp 1f /* flush prefetch queue */ + + .code32 +1: movl $MSR_EFER,%ecx + rdmsr + andl $~((1<<_EFER_LME)|(1<<_EFER_SCE)|(1<<_EFER_NX)),%eax + wrmsr /* disable long mode in EFER */ + + xorl %eax,%eax + movl %eax,%cr3 /* flush tlb */ + + /* Running protected mode without paging now */ + + wbinvd /* flush caches. Needed? */ + + lidt R(warm_idt_desc) + lgdt R(warm_gdt_desc) + + movl $0x10,%ecx /* load segment registers with real mode settings */ + movl %ecx,%ds + movl %ecx,%es + movl %ecx,%fs + movl %ecx,%gs + movl %ecx,%ss + + lea R(real_mode_desc),%eax + ljmp *(%eax) + + .code16: +real_mode: + xorl %eax,%eax + movl %eax,%cr0 + + /* some people claim $0xf000,0xfff0 is better. Use what 32bit linux uses. */ + /* code as bytes because gas has problems with it */ + .byte 0xea,0xf0,0xff,0x00,0xf0 /* ljmp 0xf000:0xfff0 */ + +real_mode_desc: + .long real_mode - warm_reboot + .short 8 +warm_gdt_desc: + .short 8*3 + .long warm_gdt - warm_reboot +warm_gdt: + .quad 0 + .quad 0x00009a000000ffff /* 16-bit real-mode 64k code at 0x00000000 */ + .quad 0x000092000100ffff /* 16-bit real-mode 64k data at 0x00000100 */ + +warm_idt_desc: + .short 0x3ff + .long 0 + + .globl warm_reboot_end +warm_reboot_end: + diff -urN linux-2.5.69-bk16/arch/x86_64/kernel/x8664_ksyms.c linux-2.5.69-bk17/arch/x86_64/kernel/x8664_ksyms.c --- linux-2.5.69-bk16/arch/x86_64/kernel/x8664_ksyms.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/kernel/x8664_ksyms.c 2003-05-24 04:33:33.000000000 -0700 @@ -207,3 +207,12 @@ extern unsigned long __supported_pte_mask; EXPORT_SYMBOL(__supported_pte_mask); + +#ifdef CONFIG_DISCONTIGMEM +EXPORT_SYMBOL(memnode_shift); +EXPORT_SYMBOL(memnodemap); +EXPORT_SYMBOL(node_data); +EXPORT_SYMBOL(fake_node); +#endif + +EXPORT_SYMBOL(clear_page); diff -urN linux-2.5.69-bk16/arch/x86_64/lib/copy_user.S linux-2.5.69-bk17/arch/x86_64/lib/copy_user.S --- linux-2.5.69-bk16/arch/x86_64/lib/copy_user.S 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/lib/copy_user.S 2003-05-24 04:33:33.000000000 -0700 @@ -6,16 +6,13 @@ #define FIX_ALIGNMENT 1 -#define movnti movq /* write to cache for now */ -#define prefetch prefetcht2 - #include #include #include /* Standard copy_to_user with segment limit checking */ .globl copy_to_user - .p2align + .p2align 4 copy_to_user: GET_THREAD_INFO(%rax) movq %rdi,%rcx @@ -27,7 +24,7 @@ /* Standard copy_from_user with segment limit checking */ .globl copy_from_user - .p2align + .p2align 4 copy_from_user: GET_THREAD_INFO(%rax) movq %rsi,%rcx @@ -58,23 +55,23 @@ * rdx count * * Output: - * eax uncopied bytes or 0 if successful. + * eax uncopied bytes or 0 if successfull. */ .globl copy_user_generic + .p2align 4 copy_user_generic: /* Put the first cacheline into cache. This should handle the small movements in ioctls etc., but not penalize the bigger filesystem data copies too much. */ pushq %rbx - prefetch (%rsi) xorl %eax,%eax /*zero for the exception handler */ #ifdef FIX_ALIGNMENT /* check for bad alignment of destination */ movl %edi,%ecx andl $7,%ecx - jnz bad_alignment -after_bad_alignment: + jnz .Lbad_alignment +.Lafter_bad_alignment: #endif movq %rdx,%rcx @@ -82,133 +79,133 @@ movl $64,%ebx shrq $6,%rdx decq %rdx - js handle_tail - jz loop_no_prefetch - -loop: - prefetch 64(%rsi) + js .Lhandle_tail -loop_no_prefetch: -s1: movq (%rsi),%r11 -s2: movq 1*8(%rsi),%r8 -s3: movq 2*8(%rsi),%r9 -s4: movq 3*8(%rsi),%r10 -d1: movnti %r11,(%rdi) -d2: movnti %r8,1*8(%rdi) -d3: movnti %r9,2*8(%rdi) -d4: movnti %r10,3*8(%rdi) + .p2align 4 +.Lloop: +.Ls1: movq (%rsi),%r11 +.Ls2: movq 1*8(%rsi),%r8 +.Ls3: movq 2*8(%rsi),%r9 +.Ls4: movq 3*8(%rsi),%r10 +.Ld1: movq %r11,(%rdi) +.Ld2: movq %r8,1*8(%rdi) +.Ld3: movq %r9,2*8(%rdi) +.Ld4: movq %r10,3*8(%rdi) -s5: movq 4*8(%rsi),%r11 -s6: movq 5*8(%rsi),%r8 -s7: movq 6*8(%rsi),%r9 -s8: movq 7*8(%rsi),%r10 -d5: movnti %r11,4*8(%rdi) -d6: movnti %r8,5*8(%rdi) -d7: movnti %r9,6*8(%rdi) -d8: movnti %r10,7*8(%rdi) - - addq %rbx,%rsi - addq %rbx,%rdi +.Ls5: movq 4*8(%rsi),%r11 +.Ls6: movq 5*8(%rsi),%r8 +.Ls7: movq 6*8(%rsi),%r9 +.Ls8: movq 7*8(%rsi),%r10 +.Ld5: movq %r11,4*8(%rdi) +.Ld6: movq %r8,5*8(%rdi) +.Ld7: movq %r9,6*8(%rdi) +.Ld8: movq %r10,7*8(%rdi) decq %rdx - jz loop_no_prefetch - jns loop -handle_tail: + leaq 64(%rsi),%rsi + leaq 64(%rdi),%rdi + + jns .Lloop + + .p2align 4 +.Lhandle_tail: movl %ecx,%edx andl $63,%ecx shrl $3,%ecx - jz handle_7 + jz .Lhandle_7 movl $8,%ebx -loop_8: -s9: movq (%rsi),%r8 -d9: movq %r8,(%rdi) - addq %rbx,%rdi - addq %rbx,%rsi + .p2align 4 +.Lloop_8: +.Ls9: movq (%rsi),%r8 +.Ld9: movq %r8,(%rdi) decl %ecx - jnz loop_8 + leaq 8(%rdi),%rdi + leaq 8(%rsi),%rsi + jnz .Lloop_8 -handle_7: +.Lhandle_7: movl %edx,%ecx andl $7,%ecx - jz ende -loop_1: -s10: movb (%rsi),%bl -d10: movb %bl,(%rdi) + jz .Lende + .p2align 4 +.Lloop_1: +.Ls10: movb (%rsi),%bl +.Ld10: movb %bl,(%rdi) incq %rdi incq %rsi decl %ecx - jnz loop_1 + jnz .Lloop_1 -ende: - sfence +.Lende: popq %rbx ret #ifdef FIX_ALIGNMENT /* align destination */ -bad_alignment: + .p2align 4 +.Lbad_alignment: movl $8,%r9d subl %ecx,%r9d movl %r9d,%ecx subq %r9,%rdx - jz small_align - js small_align -align_1: -s11: movb (%rsi),%bl -d11: movb %bl,(%rdi) + jz .Lsmall_align + js .Lsmall_align +.Lalign_1: +.Ls11: movb (%rsi),%bl +.Ld11: movb %bl,(%rdi) incq %rsi incq %rdi decl %ecx - jnz align_1 - jmp after_bad_alignment -small_align: + jnz .Lalign_1 + jmp .Lafter_bad_alignment +.Lsmall_align: addq %r9,%rdx - jmp handle_7 + jmp .Lhandle_7 #endif /* table sorted by exception address */ .section __ex_table,"a" .align 8 - .quad s1,s1e - .quad s2,s2e - .quad s3,s3e - .quad s4,s4e - .quad d1,s1e - .quad d2,s2e - .quad d3,s3e - .quad d4,s4e - .quad s5,s5e - .quad s6,s6e - .quad s7,s7e - .quad s8,s8e - .quad d5,s5e - .quad d6,s6e - .quad d7,s7e - .quad d8,s8e - .quad s9,e_quad - .quad d9,e_quad - .quad s10,e_byte - .quad d10,e_byte + .quad .Ls1,.Ls1e + .quad .Ls2,.Ls2e + .quad .Ls3,.Ls3e + .quad .Ls4,.Ls4e + .quad .Ld1,.Ls1e + .quad .Ld2,.Ls2e + .quad .Ld3,.Ls3e + .quad .Ld4,.Ls4e + .quad .Ls5,.Ls5e + .quad .Ls6,.Ls6e + .quad .Ls7,.Ls7e + .quad .Ls8,.Ls8e + .quad .Ld5,.Ls5e + .quad .Ld6,.Ls6e + .quad .Ld7,.Ls7e + .quad .Ld8,.Ls8e + .quad .Ls9,.Le_quad + .quad .Ld9,.Le_quad + .quad .Ls10,.Le_byte + .quad .Ld10,.Le_byte #ifdef FIX_ALIGNMENT - .quad s11,e_byte - .quad d11,e_byte + .quad .Ls11,.Le_byte + .quad .Ld11,.Le_byte #endif - .quad e5,e_zero + .quad .Le5,.Le_zero .previous /* compute 64-offset for main loop. 8 bytes accuracy with error on the pessimistic side. this is gross. it would be better to fix the interface. */ /* eax: zero, ebx: 64 */ -s1e: addl $8,%eax -s2e: addl $8,%eax -s3e: addl $8,%eax -s4e: addl $8,%eax -s5e: addl $8,%eax -s6e: addl $8,%eax -s7e: addl $8,%eax -s8e: addl $8,%eax +.Ls1e: addl $8,%eax +.Ls2e: addl $8,%eax +.Ls3e: addl $8,%eax +.Ls4e: addl $8,%eax +.Ls5e: addl $8,%eax +.Ls6e: addl $8,%eax +.Ls7e: addl $8,%eax +.Ls8e: addl $8,%eax addq %rbx,%rdi /* +64 */ subq %rax,%rdi /* correct destination with computed offset */ @@ -216,22 +213,22 @@ addq %rax,%rdx /* add offset to loopcnt */ andl $63,%ecx /* remaining bytes */ addq %rcx,%rdx /* add them */ - jmp zero_rest + jmp .Lzero_rest /* exception on quad word loop in tail handling */ /* ecx: loopcnt/8, %edx: length, rdi: correct */ -e_quad: +.Le_quad: shll $3,%ecx andl $7,%edx addl %ecx,%edx /* edx: bytes to zero, rdi: dest, eax:zero */ -zero_rest: +.Lzero_rest: movq %rdx,%rcx -e_byte: +.Le_byte: xorl %eax,%eax -e5: rep +.Le5: rep stosb /* when there is another exception while zeroing the rest just return */ -e_zero: +.Le_zero: movq %rdx,%rax - jmp ende + jmp .Lende diff -urN linux-2.5.69-bk16/arch/x86_64/mm/fault.c linux-2.5.69-bk17/arch/x86_64/mm/fault.c --- linux-2.5.69-bk16/arch/x86_64/mm/fault.c 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/mm/fault.c 2003-05-24 04:33:33.000000000 -0700 @@ -226,17 +226,18 @@ bad_area_nosemaphore: - /* User mode accesses just cause a SIGSEGV */ - if (error_code & 4) { #ifdef CONFIG_IA32_EMULATION /* 32bit vsyscall. map on demand. */ if (test_thread_flag(TIF_IA32) && - address >= 0xffffe000 && address < 0xffffefff-7) { + address >= 0xffffe000 && address < 0xffffe000 + PAGE_SIZE) { if (map_syscall32(mm, address) < 0) goto out_of_memory2; return; } #endif + + /* User mode accesses just cause a SIGSEGV */ + if (error_code & 4) { printk(KERN_INFO "%s[%d] segfault at rip:%lx rsp:%lx adr:%lx err:%lx\n", tsk->comm, tsk->pid, regs->rip, regs->rsp, address, diff -urN linux-2.5.69-bk16/arch/x86_64/mm/init.c linux-2.5.69-bk17/arch/x86_64/mm/init.c --- linux-2.5.69-bk16/arch/x86_64/mm/init.c 2003-05-04 16:53:07.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/mm/init.c 2003-05-24 04:33:33.000000000 -0700 @@ -39,7 +39,7 @@ #include #include -#define Dprintk(x...) printk(x) +#define Dprintk(x...) struct mmu_gather mmu_gathers[NR_CPUS]; @@ -105,7 +105,7 @@ pml4_t *level4; pgd_t *pgd; pmd_t *pmd; - pte_t *pte; + pte_t *pte, new_pte; Dprintk("set_pte_phys %lx to %lx\n", vaddr, phys); @@ -132,11 +132,13 @@ return; } } + new_pte = pfn_pte(phys >> PAGE_SHIFT, prot); + pte = pte_offset_kernel(pmd, vaddr); - /* CHECKME: */ - if (pte_val(*pte)) + if (!pte_none(*pte) && + pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask)) pte_ERROR(*pte); - set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot)); + set_pte(pte, new_pte); /* * It's enough to flush this one mapping. @@ -340,6 +342,35 @@ } #endif +/* Unmap a kernel mapping if it exists. This is useful to avoid prefetches + from the CPU leading to inconsistent cache lines. address and size + must be aligned to 2MB boundaries. + Does nothing when the mapping doesn't exist. */ +void __init clear_kernel_mapping(unsigned long address, unsigned long size) +{ + unsigned long end = address + size; + + BUG_ON(address & ~LARGE_PAGE_MASK); + BUG_ON(size & ~LARGE_PAGE_MASK); + + for (; address < end; address += LARGE_PAGE_SIZE) { + pgd_t *pgd = pgd_offset_k(address); + if (!pgd || pgd_none(*pgd)) + continue; + pmd_t *pmd = pmd_offset(pgd, address); + if (!pmd || pmd_none(*pmd)) + continue; + if (0 == (pmd_val(*pmd) & _PAGE_PSE)) { + /* Could handle this, but it should not happen currently. */ + printk(KERN_ERR + "clear_kernel_mapping: mapping has been split. will leak memory\n"); + pmd_ERROR(*pmd); + } + set_pmd(pmd, __pmd(0)); + } + __flush_tlb_all(); +} + static inline int page_is_ram (unsigned long pagenr) { int i; diff -urN linux-2.5.69-bk16/arch/x86_64/mm/k8topology.c linux-2.5.69-bk17/arch/x86_64/mm/k8topology.c --- linux-2.5.69-bk16/arch/x86_64/mm/k8topology.c 2003-05-04 16:53:55.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/mm/k8topology.c 2003-05-24 04:33:33.000000000 -0700 @@ -87,10 +87,8 @@ if (limit > end_pfn_map << PAGE_SHIFT) limit = end_pfn_map << PAGE_SHIFT; - if (limit <= base) { - printk(KERN_INFO "Node %d beyond memory map\n", nodeid); + if (limit <= base) continue; - } base >>= 16; base <<= 24; diff -urN linux-2.5.69-bk16/arch/x86_64/mm/numa.c linux-2.5.69-bk17/arch/x86_64/mm/numa.c --- linux-2.5.69-bk16/arch/x86_64/mm/numa.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/mm/numa.c 2003-05-24 04:33:33.000000000 -0700 @@ -15,7 +15,7 @@ #include #include -#define Dprintk(x...) printk(x) +#define Dprintk(x...) struct pglist_data *node_data[MAXNODE]; bootmem_data_t plat_node_bdata[MAX_NUMNODES]; @@ -104,8 +104,11 @@ reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages< numnodes) + if (nodeid + 1 > numnodes) { numnodes = nodeid + 1; + printk(KERN_INFO + "setup_node_bootmem: enlarging numnodes to %d\n", numnodes); + } nodes_present |= (1UL << nodeid); } @@ -121,7 +124,7 @@ start_pfn = node_start_pfn(nodeid); end_pfn = node_end_pfn(nodeid); - printk("setting up node %d %lx-%lx\n", nodeid, start_pfn, end_pfn); + printk(KERN_INFO "setting up node %d %lx-%lx\n", nodeid, start_pfn, end_pfn); /* All nodes > 0 have a zero length zone DMA */ dma_end_pfn = __pa(MAX_DMA_ADDRESS) >> PAGE_SHIFT; diff -urN linux-2.5.69-bk16/arch/x86_64/mm/pageattr.c linux-2.5.69-bk17/arch/x86_64/mm/pageattr.c --- linux-2.5.69-bk16/arch/x86_64/mm/pageattr.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/mm/pageattr.c 2003-05-24 04:33:33.000000000 -0700 @@ -63,29 +63,53 @@ __flush_tlb_one(address); } + +static inline void flush_map(unsigned long address) +{ + on_each_cpu(flush_kernel_map, (void *)address, 1, 1); +} + +struct deferred_page { + struct deferred_page *next; + struct page *fpage; + unsigned long address; +}; +static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */ + +static inline void save_page(unsigned long address, struct page *fpage) +{ + struct deferred_page *df; + df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL); + if (!df) { + flush_map(address); + __free_page(fpage); + } else { + df->next = df_list; + df->fpage = fpage; + df->address = address; + df_list = df; + } +} + /* * No more special protections in this 2/4MB area - revert to a * large page again. */ -static inline void revert_page(struct page *kpte_page, unsigned long address) +static void revert_page(struct page *kpte_page, unsigned long address) { pgd_t *pgd; pmd_t *pmd; pte_t large_pte; pgd = pgd_offset_k(address); - if (!pgd) BUG(); pmd = pmd_offset(pgd, address); - if (!pmd) BUG(); - if ((pmd_val(*pmd) & _PAGE_GLOBAL) == 0) BUG(); - + BUG_ON(pmd_val(*pmd) & _PAGE_PSE); large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, PAGE_KERNEL_LARGE); set_pte((pte_t *)pmd, large_pte); } static int -__change_page_attr(unsigned long address, struct page *page, pgprot_t prot, - struct page **oldpage) +__change_page_attr(unsigned long address, struct page *page, pgprot_t prot) { pte_t *kpte; struct page *kpte_page; @@ -107,6 +131,7 @@ struct page *split = split_large_page(address, prot); if (!split) return -ENOMEM; + atomic_inc(&kpte_page->count); set_pte(kpte,mk_pte(split, PAGE_KERNEL)); } } else if ((kpte_flags & _PAGE_PSE) == 0) { @@ -115,39 +140,12 @@ } if (atomic_read(&kpte_page->count) == 1) { - *oldpage = kpte_page; + save_page(address, kpte_page); revert_page(kpte_page, address); } return 0; } -static inline void flush_map(unsigned long address) -{ - on_each_cpu(flush_kernel_map, (void *)address, 1, 1); -} - -struct deferred_page { - struct deferred_page *next; - struct page *fpage; - unsigned long address; -}; -static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */ - -static inline void save_page(unsigned long address, struct page *fpage) -{ - struct deferred_page *df; - df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL); - if (!df) { - flush_map(address); - __free_page(fpage); - } else { - df->next = df_list; - df->fpage = fpage; - df->address = address; - df_list = df; - } -} - /* * Change the page attributes of an page in the linear mapping. * @@ -164,24 +162,19 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot) { int err = 0; - struct page *fpage, *fpage2; int i; down_write(&init_mm.mmap_sem); - for (i = 0; i < numpages; i++, page++) { + for (i = 0; i < numpages; !err && i++, page++) { unsigned long address = (unsigned long)page_address(page); - fpage = NULL; - err = __change_page_attr(address, page, prot, &fpage); + err = __change_page_attr(address, page, prot); + if (err) + break; /* Handle kernel mapping too which aliases part of the lowmem */ - if (!err && page_to_phys(page) < KERNEL_TEXT_SIZE) { + if (page_to_phys(page) < KERNEL_TEXT_SIZE) { unsigned long addr2 = __START_KERNEL_map + page_to_phys(page); - fpage2 = NULL; - err = __change_page_attr(addr2, page, prot, &fpage2); - if (fpage2) - save_page(addr2, fpage2); + err = __change_page_attr(addr2, page, prot); } - if (fpage) - save_page(address, fpage); } up_write(&init_mm.mmap_sem); return err; diff -urN linux-2.5.69-bk16/arch/x86_64/pci/irq.c linux-2.5.69-bk17/arch/x86_64/pci/irq.c --- linux-2.5.69-bk16/arch/x86_64/pci/irq.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/pci/irq.c 2003-05-24 04:33:33.000000000 -0700 @@ -378,8 +378,9 @@ return NULL; } -static void pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { + return IRQ_NONE; } static int pcibios_lookup_irq(struct pci_dev *dev, int assign) diff -urN linux-2.5.69-bk16/arch/x86_64/vmlinux.lds.S linux-2.5.69-bk17/arch/x86_64/vmlinux.lds.S --- linux-2.5.69-bk16/arch/x86_64/vmlinux.lds.S 2003-05-04 16:53:00.000000000 -0700 +++ linux-2.5.69-bk17/arch/x86_64/vmlinux.lds.S 2003-05-24 04:33:33.000000000 -0700 @@ -127,7 +127,7 @@ /* Sections to be discarded */ /DISCARD/ : { *(.exit.data) - *(.exit.text) + /* *(.exit.text) */ *(.exitcall.exit) *(.eh_frame) } diff -urN linux-2.5.69-bk16/drivers/acpi/dispatcher/dsinit.c linux-2.5.69-bk17/drivers/acpi/dispatcher/dsinit.c --- linux-2.5.69-bk16/drivers/acpi/dispatcher/dsinit.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/dispatcher/dsinit.c 2003-05-24 04:33:33.000000000 -0700 @@ -222,8 +222,8 @@ } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, - "\nTable [%4.4s] - %hd Objects with %hd Devices %hd Methods %hd Regions\n", - table_desc->pointer->signature, info.object_count, + "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n", + table_desc->pointer->signature, table_desc->table_id, info.object_count, info.device_count, info.method_count, info.op_region_count)); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, diff -urN linux-2.5.69-bk16/drivers/acpi/dispatcher/dsmethod.c linux-2.5.69-bk17/drivers/acpi/dispatcher/dsmethod.c --- linux-2.5.69-bk16/drivers/acpi/dispatcher/dsmethod.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/dispatcher/dsmethod.c 2003-05-24 04:33:33.000000000 -0700 @@ -290,6 +290,8 @@ return_ACPI_STATUS (AE_NULL_OBJECT); } + obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); + /* Init for new method, wait on concurrency semaphore */ status = acpi_ds_begin_method_execution (method_node, obj_desc, diff -urN linux-2.5.69-bk16/drivers/acpi/dispatcher/dsobject.c linux-2.5.69-bk17/drivers/acpi/dispatcher/dsobject.c --- linux-2.5.69-bk16/drivers/acpi/dispatcher/dsobject.c 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/dispatcher/dsobject.c 2003-05-24 04:33:33.000000000 -0700 @@ -204,7 +204,8 @@ if (obj_desc->buffer.length == 0) { obj_desc->buffer.pointer = NULL; - ACPI_REPORT_WARNING (("Buffer created with zero length in AML\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Buffer defined with zero length in AML, creating\n")); } else { obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE ( diff -urN linux-2.5.69-bk16/drivers/acpi/dispatcher/dsopcode.c linux-2.5.69-bk17/drivers/acpi/dispatcher/dsopcode.c --- linux-2.5.69-bk16/drivers/acpi/dispatcher/dsopcode.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/dispatcher/dsopcode.c 2003-05-24 04:33:33.000000000 -0700 @@ -82,7 +82,7 @@ union acpi_parse_object *arg; - ACPI_FUNCTION_TRACE ("acpi_ds_execute_arguments"); + ACPI_FUNCTION_TRACE ("ds_execute_arguments"); /* @@ -99,7 +99,7 @@ /* Create and initialize a new parser state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } @@ -139,7 +139,7 @@ /* Create and initialize a new parser state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } diff -urN linux-2.5.69-bk16/drivers/acpi/dispatcher/dswexec.c linux-2.5.69-bk17/drivers/acpi/dispatcher/dswexec.c --- linux-2.5.69-bk16/drivers/acpi/dispatcher/dswexec.c 2003-05-04 16:53:55.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/dispatcher/dswexec.c 2003-05-24 04:33:33.000000000 -0700 @@ -50,6 +50,7 @@ #include #include #include +#include #define _COMPONENT ACPI_DISPATCHER @@ -657,6 +658,16 @@ /* Always clear the object stack */ walk_state->num_operands = 0; + +#ifdef ACPI_DISASSEMBLER + + /* On error, display method locals/args */ + + if (ACPI_FAILURE (status)) { + acpi_dm_dump_method_info (status, walk_state, op); + } +#endif + return_ACPI_STATUS (status); } diff -urN linux-2.5.69-bk16/drivers/acpi/ec.c linux-2.5.69-bk17/drivers/acpi/ec.c --- linux-2.5.69-bk16/drivers/acpi/ec.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/ec.c 2003-05-24 04:33:33.000000000 -0700 @@ -113,7 +113,7 @@ switch (event) { case ACPI_EC_EVENT_OBF: do { - acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr, 0); + acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr); if (acpi_ec_status & ACPI_EC_FLAG_OBF) return 0; udelay(ACPI_EC_UDELAY); @@ -121,7 +121,7 @@ break; case ACPI_EC_EVENT_IBE: do { - acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr, 0); + acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr); if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) return 0; udelay(ACPI_EC_UDELAY); @@ -161,18 +161,18 @@ spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr, 0); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; - acpi_hw_low_level_write(8, address, &ec->data_addr, 0); + acpi_hw_low_level_write(8, address, &ec->data_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (result) goto end; - acpi_hw_low_level_read(8, data, &ec->data_addr, 0); + acpi_hw_low_level_read(8, data, &ec->data_addr); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", *data, address)); @@ -211,17 +211,17 @@ spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr, 0); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; - acpi_hw_low_level_write(8, address, &ec->data_addr, 0); + acpi_hw_low_level_write(8, address, &ec->data_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; - acpi_hw_low_level_write(8, data, &ec->data_addr, 0); + acpi_hw_low_level_write(8, data, &ec->data_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; @@ -310,12 +310,12 @@ */ spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr, 0); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (result) goto end; - acpi_hw_low_level_read(8, data, &ec->data_addr, 0); + acpi_hw_low_level_read(8, data, &ec->data_addr); if (!*data) result = -ENODATA; @@ -355,7 +355,7 @@ goto end; spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_read(8, &value, &ec->command_addr, 0); + acpi_hw_low_level_read(8, &value, &ec->command_addr); spin_unlock_irqrestore(&ec->lock, flags); /* TBD: Implement asynch events! diff -urN linux-2.5.69-bk16/drivers/acpi/events/evgpe.c linux-2.5.69-bk17/drivers/acpi/events/evgpe.c --- linux-2.5.69-bk16/drivers/acpi/events/evgpe.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/events/evgpe.c 2003-05-24 04:33:33.000000000 -0700 @@ -170,7 +170,7 @@ /* Read the Status Register */ status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value, - &gpe_register_info->status_address, 0); + &gpe_register_info->status_address); gpe_register_info->status = (u8) in_value; if (ACPI_FAILURE (status)) { goto unlock_and_exit; @@ -179,7 +179,7 @@ /* Read the Enable Register */ status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value, - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); gpe_register_info->enable = (u8) in_value; if (ACPI_FAILURE (status)) { goto unlock_and_exit; diff -urN linux-2.5.69-bk16/drivers/acpi/events/evgpeblk.c linux-2.5.69-bk17/drivers/acpi/events/evgpeblk.c --- linux-2.5.69-bk16/drivers/acpi/events/evgpeblk.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/events/evgpeblk.c 2003-05-24 04:33:33.000000000 -0700 @@ -634,13 +634,13 @@ * by writing a '0'. */ status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0x00, - &this_register->enable_address, 0); + &this_register->enable_address); if (ACPI_FAILURE (status)) { goto error_exit; } status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0xFF, - &this_register->status_address, 0); + &this_register->status_address); if (ACPI_FAILURE (status)) { goto error_exit; } @@ -732,18 +732,16 @@ /* Dump info about this GPE block */ - ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block: [%4.4s] %X registers at %8.8X%8.8X on interrupt %d\n", + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n", + gpe_block->block_base_number, + (u32) (gpe_block->block_base_number + + ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)), gpe_device->name.ascii, gpe_block->register_count, ACPI_HIDWORD (gpe_block->block_address.address), ACPI_LODWORD (gpe_block->block_address.address), interrupt_level)); - ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block defined as GPE 0x%.2X to GPE 0x%.2X\n", - gpe_block->block_base_number, - (u32) (gpe_block->block_base_number + - ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)))); - /* Find all GPE methods (_Lxx, _Exx) for this block */ status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device, diff -urN linux-2.5.69-bk16/drivers/acpi/events/evmisc.c linux-2.5.69-bk17/drivers/acpi/events/evmisc.c --- linux-2.5.69-bk16/drivers/acpi/events/evmisc.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/events/evmisc.c 2003-05-24 04:33:33.000000000 -0700 @@ -156,10 +156,10 @@ case ACPI_TYPE_POWER: if (notify_value <= ACPI_MAX_SYS_NOTIFY) { - handler_obj = obj_desc->common_notify.sys_handler; + handler_obj = obj_desc->common_notify.system_notify; } else { - handler_obj = obj_desc->common_notify.drv_handler; + handler_obj = obj_desc->common_notify.device_notify; } break; @@ -171,8 +171,8 @@ /* If there is any handler to run, schedule the dispatcher */ - if ((acpi_gbl_sys_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) || - (acpi_gbl_drv_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) || + if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) || + (acpi_gbl_device_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { notify_info = acpi_ut_create_generic_state (); if (!notify_info) { @@ -235,17 +235,17 @@ if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { /* Global system notification handler */ - if (acpi_gbl_sys_notify.handler) { - global_handler = acpi_gbl_sys_notify.handler; - global_context = acpi_gbl_sys_notify.context; + if (acpi_gbl_system_notify.handler) { + global_handler = acpi_gbl_system_notify.handler; + global_context = acpi_gbl_system_notify.context; } } else { /* Global driver notification handler */ - if (acpi_gbl_drv_notify.handler) { - global_handler = acpi_gbl_drv_notify.handler; - global_context = acpi_gbl_drv_notify.context; + if (acpi_gbl_device_notify.handler) { + global_handler = acpi_gbl_device_notify.handler; + global_context = acpi_gbl_device_notify.context; } } @@ -259,8 +259,8 @@ handler_obj = notify_info->notify.handler_obj; if (handler_obj) { - handler_obj->notify_handler.handler (notify_info->notify.node, notify_info->notify.value, - handler_obj->notify_handler.context); + handler_obj->notify.handler (notify_info->notify.node, notify_info->notify.value, + handler_obj->notify.context); } /* All done with the info object */ diff -urN linux-2.5.69-bk16/drivers/acpi/events/evregion.c linux-2.5.69-bk17/drivers/acpi/events/evregion.c --- linux-2.5.69-bk16/drivers/acpi/events/evregion.c 2003-05-04 16:53:34.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/events/evregion.c 2003-05-24 04:33:33.000000000 -0700 @@ -50,24 +50,32 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evregion") +#define ACPI_NUM_DEFAULT_SPACES 4 + +u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_DATA_TABLE}; + /******************************************************************************* * * FUNCTION: acpi_ev_init_address_spaces * - * PARAMETERS: + * PARAMETERS: None * * RETURN: Status * - * DESCRIPTION: Installs the core subsystem address space handlers. + * DESCRIPTION: Installs the core subsystem default address space handlers. * ******************************************************************************/ acpi_status acpi_ev_init_address_spaces ( - void) -{ + void) { acpi_status status; + acpi_native_uint i; ACPI_FUNCTION_TRACE ("ev_init_address_spaces"); @@ -75,9 +83,11 @@ /* * All address spaces (PCI Config, EC, SMBus) are scope dependent - * and registration must occur for a specific device. In the case - * system memory and IO address spaces there is currently no device - * associated with the address space. For these we use the root. + * and registration must occur for a specific device. + * + * In the case of the system memory and IO address spaces there is currently + * no device associated with the address space. For these we use the root. + * * We install the default PCI config space handler at the root so * that this space is immediately available even though the we have * not enumerated all the PCI Root Buses yet. This is to conform @@ -86,39 +96,27 @@ * near ready to find the PCI root buses at this point. * * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler - * has already been installed (via acpi_install_address_space_handler) + * has already been installed (via acpi_install_address_space_handler). + * Similar for AE_SAME_HANDLER. */ - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_SYSTEM_MEMORY, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); - } - - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_SYSTEM_IO, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); - } - - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_PCI_CONFIG, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); - } - - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_DATA_TABLE, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, + acpi_gbl_default_address_spaces[i], + ACPI_DEFAULT_HANDLER, NULL, NULL); + switch (status) { + case AE_OK: + case AE_SAME_HANDLER: + case AE_ALREADY_EXISTS: + + /* These exceptions are all OK */ + + break; + + default: + + return_ACPI_STATUS (status); + } } return_ACPI_STATUS (AE_OK); @@ -161,10 +159,10 @@ } /* - * _REG method has two arguments - * Arg0: Integer: Operation region space ID + * _REG method has two arguments + * Arg0: Integer: Operation region space ID * Same value as region_obj->Region.space_id - * Arg1: Integer: connection status + * Arg1: Integer: connection status * 1 for connecting the handler, * 0 for disconnecting the handler * Passed as a parameter @@ -180,16 +178,14 @@ goto cleanup; } - /* - * Set up the parameter objects - */ + /* Set up the parameter objects */ + params[0]->integer.value = region_obj->region.space_id; params[1]->integer.value = function; params[2] = NULL; - /* - * Execute the method, no return value - */ + /* Execute the method, no return value */ + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, region_obj2->extra.method_REG, NULL)); status = acpi_ns_evaluate_by_handle (region_obj2->extra.method_REG, params, NULL); @@ -245,10 +241,9 @@ return_ACPI_STATUS (AE_NOT_EXIST); } - /* - * Ensure that there is a handler associated with this region - */ - handler_desc = region_obj->region.addr_handler; + /* Ensure that there is a handler associated with this region */ + + handler_desc = region_obj->region.address_space; if (!handler_desc) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "no handler for region(%p) [%s]\n", region_obj, acpi_ut_get_region_name (region_obj->region.space_id))); @@ -264,24 +259,23 @@ /* * This region has not been initialized yet, do it */ - region_setup = handler_desc->addr_handler.setup; + region_setup = handler_desc->address_space.setup; if (!region_setup) { - /* - * Bad news, no init routine and not init'd - */ + /* No initialization routine, exit with error */ + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n", region_obj, acpi_ut_get_region_name (region_obj->region.space_id))); - return_ACPI_STATUS (AE_UNKNOWN_STATUS); + return_ACPI_STATUS (AE_NOT_EXIST); } /* * We must exit the interpreter because the region setup will potentially - * execute control methods + * execute control methods (e.g., _REG method for this region) */ acpi_ex_exit_interpreter (); status = region_setup (region_obj, ACPI_REGION_ACTIVATE, - handler_desc->addr_handler.context, ®ion_context); + handler_desc->address_space.context, ®ion_context); /* Re-enter the interpreter */ @@ -290,9 +284,8 @@ return_ACPI_STATUS (status2); } - /* - * Init routine may fail - */ + /* Check for failure of the Region Setup */ + if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n", acpi_format_exception (status), @@ -300,40 +293,50 @@ return_ACPI_STATUS (status); } - region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; - /* - * Save the returned context for use in all accesses to - * this particular region. + * Region initialization may have been completed by region_setup */ - region_obj2->extra.region_context = region_context; + if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { + region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; + + if (region_obj2->extra.region_context) { + /* The handler for this region was already installed */ + + ACPI_MEM_FREE (region_context); + } + else { + /* + * Save the returned context for use in all accesses to + * this particular region + */ + region_obj2->extra.region_context = region_context; + } + } } - /* - * We have everything we need, begin the process - */ - handler = handler_desc->addr_handler.handler; + /* We have everything we need, we can invoke the address space handler */ + + handler = handler_desc->address_space.handler; ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", - ®ion_obj->region.addr_handler->addr_handler, handler, + ®ion_obj->region.address_space->address_space, handler, ACPI_HIDWORD (address), ACPI_LODWORD (address), acpi_ut_get_region_name (region_obj->region.space_id))); - if (!(handler_desc->addr_handler.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* - * For handlers other than the default (supplied) handlers, we must - * exit the interpreter because the handler *might* block -- we don't - * know what it will do, so we can't hold the lock on the intepreter. + * For handlers other than the default (supplied) handlers, we must + * exit the interpreter because the handler *might* block -- we don't + * know what it will do, so we can't hold the lock on the intepreter. */ acpi_ex_exit_interpreter(); } - /* - * Invoke the handler. - */ + /* Call the handler */ + status = handler (function, address, bit_width, value, - handler_desc->addr_handler.context, + handler_desc->address_space.context, region_obj2->extra.region_context); if (ACPI_FAILURE (status)) { @@ -342,7 +345,7 @@ acpi_format_exception (status))); } - if (!(handler_desc->addr_handler.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * We just returned from a non-default handler, we must re-enter the * interpreter @@ -393,35 +396,30 @@ } region_context = region_obj2->extra.region_context; - /* - * Get the address handler from the region object - */ - handler_obj = region_obj->region.addr_handler; + /* Get the address handler from the region object */ + + handler_obj = region_obj->region.address_space; if (!handler_obj) { - /* - * This region has no handler, all done - */ + /* This region has no handler, all done */ + return_VOID; } + /* Find this region in the handler's list */ - /* - * Find this region in the handler's list - */ - obj_desc = handler_obj->addr_handler.region_list; - last_obj_ptr = &handler_obj->addr_handler.region_list; + obj_desc = handler_obj->address_space.region_list; + last_obj_ptr = &handler_obj->address_space.region_list; while (obj_desc) { - /* - * See if this is the one - */ + /* Is this the correct Region? */ + if (obj_desc == region_obj) { ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Removing Region %p from address handler %p\n", region_obj, handler_obj)); - /* - * This is it, remove it from the handler's list - */ + + /* This is it, remove it from the handler's list */ + *last_obj_ptr = obj_desc->region.next; obj_desc->region.next = NULL; /* Must clear field */ @@ -432,9 +430,8 @@ } } - /* - * Now stop region accesses by executing the _REG method - */ + /* Now stop region accesses by executing the _REG method */ + status = acpi_ev_execute_reg_method (region_obj, 0); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n", @@ -449,16 +446,14 @@ } } - /* - * Call the setup handler with the deactivate notification - */ - region_setup = handler_obj->addr_handler.setup; + /* Call the setup handler with the deactivate notification */ + + region_setup = handler_obj->address_space.setup; status = region_setup (region_obj, ACPI_REGION_DEACTIVATE, - handler_obj->addr_handler.context, ®ion_context); + handler_obj->address_space.context, ®ion_context); + + /* Init routine may fail, Just ignore errors */ - /* - * Init routine may fail, Just ignore errors - */ if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n", acpi_format_exception (status), @@ -468,31 +463,29 @@ region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE); /* - * Remove handler reference in the region + * Remove handler reference in the region * - * NOTE: this doesn't mean that the region goes away - * The region is just inaccessible as indicated to - * the _REG method + * NOTE: this doesn't mean that the region goes away + * The region is just inaccessible as indicated to + * the _REG method * - * If the region is on the handler's list - * this better be the region's handler + * If the region is on the handler's list + * this better be the region's handler */ - region_obj->region.addr_handler = NULL; + region_obj->region.address_space = NULL; + acpi_ut_remove_reference (handler_obj); return_VOID; + } - } /* found the right handler */ + /* Walk the linked list of handlers */ - /* - * Move through the linked list of handlers - */ last_obj_ptr = &obj_desc->region.next; obj_desc = obj_desc->region.next; } - /* - * If we get here, the region was not in the handler's region list - */ + /* If we get here, the region was not in the handler's region list */ + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Cannot remove region %p from address handler %p\n", region_obj, handler_obj)); @@ -534,16 +527,19 @@ region_obj, handler_obj, acpi_ut_get_region_name (region_obj->region.space_id))); - /* - * Link this region to the front of the handler's list - */ - region_obj->region.next = handler_obj->addr_handler.region_list; - handler_obj->addr_handler.region_list = region_obj; + /* Link this region to the front of the handler's list */ - /* - * Set the region's handler - */ - region_obj->region.addr_handler = handler_obj; + region_obj->region.next = handler_obj->address_space.region_list; + handler_obj->address_space.region_list = region_obj; + + /* Install the region's handler */ + + if (region_obj->region.address_space) { + return_ACPI_STATUS (AE_ALREADY_EXISTS); + } + + region_obj->region.address_space = handler_obj; + acpi_ut_add_reference (handler_obj); /* * Tell all users that this region is usable by running the _REG @@ -571,14 +567,14 @@ /******************************************************************************* * - * FUNCTION: acpi_ev_addr_handler_helper + * FUNCTION: acpi_ev_install_handler * * PARAMETERS: Handle - Node to be dumped * Level - Nesting level of the handle * Context - Passed into acpi_ns_walk_namespace * * DESCRIPTION: This routine installs an address handler into objects that are - * of type Region. + * of type Region or Device. * * If the Object is a Device, and the device has a handler of * the same type then the search is terminated in that branch. @@ -589,20 +585,20 @@ ******************************************************************************/ acpi_status -acpi_ev_addr_handler_helper ( +acpi_ev_install_handler ( acpi_handle obj_handle, u32 level, void *context, void **return_value) { union acpi_operand_object *handler_obj; - union acpi_operand_object *tmp_obj; + union acpi_operand_object *next_handler_obj; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_NAME ("ev_addr_handler_helper"); + ACPI_FUNCTION_NAME ("ev_install_handler"); handler_obj = (union acpi_operand_object *) context; @@ -621,8 +617,8 @@ } /* - * We only care about regions.and objects - * that can have address handlers + * We only care about regions.and objects + * that are allowed to have address space handlers */ if ((node->type != ACPI_TYPE_DEVICE) && (node->type != ACPI_TYPE_REGION) && @@ -634,81 +630,70 @@ obj_desc = acpi_ns_get_attached_object (node); if (!obj_desc) { - /* - * The object DNE, we don't care about it - */ + /* No object, just exit */ + return (AE_OK); } - /* - * Devices are handled different than regions - */ + /* Devices are handled different than regions */ + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_DEVICE) { - /* - * See if this guy has any handlers - */ - tmp_obj = obj_desc->device.addr_handler; - while (tmp_obj) { - /* - * Now let's see if it's for the same address space. - */ - if (tmp_obj->addr_handler.space_id == handler_obj->addr_handler.space_id) { - /* - * It's for the same address space - */ + /* Check if this Device already has a handler for this address space */ + + next_handler_obj = obj_desc->device.address_space; + while (next_handler_obj) { + /* Found a handler, is it for the same address space? */ + + if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) { ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler for region [%s] in device %p(%p) handler %p\n", - acpi_ut_get_region_name (handler_obj->addr_handler.space_id), - obj_desc, tmp_obj, handler_obj)); + acpi_ut_get_region_name (handler_obj->address_space.space_id), + obj_desc, next_handler_obj, handler_obj)); /* - * Since the object we found it on was a device, then it - * means that someone has already installed a handler for - * the branch of the namespace from this device on. Just - * bail out telling the walk routine to not traverse this - * branch. This preserves the scoping rule for handlers. + * Since the object we found it on was a device, then it + * means that someone has already installed a handler for + * the branch of the namespace from this device on. Just + * bail out telling the walk routine to not traverse this + * branch. This preserves the scoping rule for handlers. */ return (AE_CTRL_DEPTH); } - /* - * Move through the linked list of handlers - */ - tmp_obj = tmp_obj->addr_handler.next; + /* Walk the linked list of handlers attached to this device */ + + next_handler_obj = next_handler_obj->address_space.next; } /* - * As long as the device didn't have a handler for this - * space we don't care about it. We just ignore it and - * proceed. + * As long as the device didn't have a handler for this + * space we don't care about it. We just ignore it and + * proceed. */ return (AE_OK); } - /* - * Only here if it was a region - */ - if (obj_desc->region.space_id != handler_obj->addr_handler.space_id) { + /* Object is a Region */ + + if (obj_desc->region.space_id != handler_obj->address_space.space_id) { /* - * This region is for a different address space - * ignore it + * This region is for a different address space + * -- just ignore it */ return (AE_OK); } /* - * Now we have a region and it is for the handler's address - * space type. + * Now we have a region and it is for the handler's address + * space type. * - * First disconnect region for any previous handler (if any) + * First disconnect region for any previous handler (if any) */ acpi_ev_detach_region (obj_desc, FALSE); - /* - * Then connect the region to the new handler - */ - status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE); + /* Connect the region to the new handler */ + status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE); return (status); } diff -urN linux-2.5.69-bk16/drivers/acpi/events/evrgnini.c linux-2.5.69-bk17/drivers/acpi/events/evrgnini.c --- linux-2.5.69-bk16/drivers/acpi/events/evrgnini.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/events/evrgnini.c 2003-05-24 04:33:33.000000000 -0700 @@ -165,10 +165,11 @@ void **region_context) { acpi_status status = AE_OK; - acpi_integer temp; + acpi_integer pci_value; struct acpi_pci_id *pci_id = *region_context; union acpi_operand_object *handler_obj; - struct acpi_namespace_node *node; + struct acpi_namespace_node *parent_node; + struct acpi_namespace_node *pci_root_node; union acpi_operand_object *region_obj = (union acpi_operand_object *) handle; struct acpi_device_id object_hID; @@ -176,7 +177,7 @@ ACPI_FUNCTION_TRACE ("ev_pci_config_region_setup"); - handler_obj = region_obj->region.addr_handler; + handler_obj = region_obj->region.address_space; if (!handler_obj) { /* * No installed handler. This shouldn't happen because the dispatch @@ -187,45 +188,15 @@ return_ACPI_STATUS (AE_NOT_EXIST); } + *region_context = NULL; if (function == ACPI_REGION_DEACTIVATE) { if (pci_id) { ACPI_MEM_FREE (pci_id); - *region_context = NULL; } - return_ACPI_STATUS (status); } - /* Create a new context */ - - pci_id = ACPI_MEM_CALLOCATE (sizeof (struct acpi_pci_id)); - if (!pci_id) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* - * For PCI Config space access, we have to pass the segment, bus, - * device and function numbers. This routine must acquire those. - */ - - /* - * First get device and function numbers from the _ADR object - * in the parent's scope. - */ - node = acpi_ns_get_parent_node (region_obj->region.node); - - /* Evaluate the _ADR object */ - - status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp); - - /* - * The default is zero, and since the allocation above zeroed - * the data, just do nothing on failure. - */ - if (ACPI_SUCCESS (status)) { - pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp)); - pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp)); - } + parent_node = acpi_ns_get_parent_node (region_obj->region.node); /* * Get the _SEG and _BBN values from the device upon which the handler @@ -236,61 +207,106 @@ */ /* - * If the addr_handler.Node is still pointing to the root, we need + * If the address_space.Node is still pointing to the root, we need * to scan upward for a PCI Root bridge and re-associate the op_region * handlers with that device. */ - if (handler_obj->addr_handler.node == acpi_gbl_root_node) { - /* - * Node is currently the parent object - */ - while (node != acpi_gbl_root_node) { - status = acpi_ut_execute_HID (node, &object_hID); + if (handler_obj->address_space.node == acpi_gbl_root_node) { + /* Start search from the parent object */ + + pci_root_node = parent_node; + while (pci_root_node != acpi_gbl_root_node) { + status = acpi_ut_execute_HID (pci_root_node, &object_hID); if (ACPI_SUCCESS (status)) { /* Got a valid _HID, check if this is a PCI root */ - if (!(ACPI_STRNCMP (object_hID.buffer, PCI_ROOT_HID_STRING, + if (!(ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING, sizeof (PCI_ROOT_HID_STRING)))) { /* Install a handler for this PCI root bridge */ - status = acpi_install_address_space_handler ((acpi_handle) node, + status = acpi_install_address_space_handler ((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Could not install pci_config handler for %4.4s, %s\n", - node->name.ascii, acpi_format_exception (status))); + if (status == AE_SAME_HANDLER) { + /* + * It is OK if the handler is already installed on the root + * bridge. Still need to return a context object for the + * new PCI_Config operation region, however. + */ + status = AE_OK; + } + else { + ACPI_REPORT_ERROR (( + "Could not install pci_config handler for Root Bridge %4.4s, %s\n", + pci_root_node->name.ascii, acpi_format_exception (status))); + } } break; } } - node = acpi_ns_get_parent_node (node); + pci_root_node = acpi_ns_get_parent_node (pci_root_node); } + + /* PCI root bridge not found, use namespace root node */ } else { - node = handler_obj->addr_handler.node; + pci_root_node = handler_obj->address_space.node; } /* - * The PCI segment number comes from the _SEG method + * If this region is now initialized, we are done. + * (install_address_space_handler could have initialized it) */ - status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, node, &temp); - if (ACPI_SUCCESS (status)) { - pci_id->segment = ACPI_LOWORD (temp); + if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { + return_ACPI_STATUS (AE_OK); + } + + /* Region is still not initialized. Create a new context */ + + pci_id = ACPI_MEM_CALLOCATE (sizeof (struct acpi_pci_id)); + if (!pci_id) { + return_ACPI_STATUS (AE_NO_MEMORY); } /* - * The PCI bus number comes from the _BBN method + * For PCI_Config space access, we need the segment, bus, + * device and function numbers. Acquire them here. */ - status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, node, &temp); - if (ACPI_SUCCESS (status)) { - pci_id->bus = ACPI_LOWORD (temp); - } /* - * Complete this device's pci_id + * Get the PCI device and function numbers from the _ADR object + * contained in the parent's scope. + */ + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, parent_node, &pci_value); + + /* + * The default is zero, and since the allocation above zeroed + * the data, just do nothing on failure. */ - acpi_os_derive_pci_id (node, region_obj->region.node, &pci_id); + if (ACPI_SUCCESS (status)) { + pci_id->device = ACPI_HIWORD (ACPI_LODWORD (pci_value)); + pci_id->function = ACPI_LOWORD (ACPI_LODWORD (pci_value)); + } + + /* The PCI segment number comes from the _SEG method */ + + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, pci_root_node, &pci_value); + if (ACPI_SUCCESS (status)) { + pci_id->segment = ACPI_LOWORD (pci_value); + } + + /* The PCI bus number comes from the _BBN method */ + + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, pci_root_node, &pci_value); + if (ACPI_SUCCESS (status)) { + pci_id->bus = ACPI_LOWORD (pci_value); + } + + /* Complete this device's pci_id */ + + acpi_os_derive_pci_id (pci_root_node, region_obj->region.node, &pci_id); *region_context = pci_id; return_ACPI_STATUS (AE_OK); @@ -451,14 +467,15 @@ node = acpi_ns_get_parent_node (region_obj->region.node); space_id = region_obj->region.space_id; - region_obj->region.addr_handler = NULL; + /* Setup defaults */ + + region_obj->region.address_space = NULL; region_obj2->extra.method_REG = NULL; region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE); region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; - /* - * Find any "_REG" method associated with this region definition - */ + /* Find any "_REG" method associated with this region definition */ + status = acpi_ns_search_node (*reg_name_ptr, node, ACPI_TYPE_METHOD, &method_node); if (ACPI_SUCCESS (status)) { @@ -475,29 +492,27 @@ * ie: acpi_gbl_root_node->parent_entry being set to NULL */ while (node) { - /* - * Check to see if a handler exists - */ + /* Check to see if a handler exists */ + handler_obj = NULL; obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { - /* - * Can only be a handler if the object exists - */ + /* Can only be a handler if the object exists */ + switch (node->type) { case ACPI_TYPE_DEVICE: - handler_obj = obj_desc->device.addr_handler; + handler_obj = obj_desc->device.address_space; break; case ACPI_TYPE_PROCESSOR: - handler_obj = obj_desc->processor.addr_handler; + handler_obj = obj_desc->processor.address_space; break; case ACPI_TYPE_THERMAL: - handler_obj = obj_desc->thermal_zone.addr_handler; + handler_obj = obj_desc->thermal_zone.address_space; break; default: @@ -508,7 +523,7 @@ while (handler_obj) { /* Is this handler of the correct type? */ - if (handler_obj->addr_handler.space_id == space_id) { + if (handler_obj->address_space.space_id == space_id) { /* Found correct handler */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, @@ -523,7 +538,7 @@ /* Try next handler in the list */ - handler_obj = handler_obj->addr_handler.next; + handler_obj = handler_obj->address_space.next; } } @@ -534,9 +549,8 @@ node = acpi_ns_get_parent_node (node); } - /* - * If we get here, there is no handler for this region - */ + /* If we get here, there is no handler for this region */ + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "No handler for region_type %s(%X) (region_obj %p)\n", acpi_ut_get_region_name (space_id), space_id, region_obj)); diff -urN linux-2.5.69-bk16/drivers/acpi/events/evxface.c linux-2.5.69-bk17/drivers/acpi/events/evxface.c --- linux-2.5.69-bk16/drivers/acpi/events/evxface.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/events/evxface.c 2003-05-24 04:33:33.000000000 -0700 @@ -244,22 +244,22 @@ /* Make sure the handler is not already installed */ if (((handler_type == ACPI_SYSTEM_NOTIFY) && - acpi_gbl_sys_notify.handler) || + acpi_gbl_system_notify.handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && - acpi_gbl_drv_notify.handler)) { + acpi_gbl_device_notify.handler)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } if (handler_type == ACPI_SYSTEM_NOTIFY) { - acpi_gbl_sys_notify.node = node; - acpi_gbl_sys_notify.handler = handler; - acpi_gbl_sys_notify.context = context; + acpi_gbl_system_notify.node = node; + acpi_gbl_system_notify.handler = handler; + acpi_gbl_system_notify.context = context; } else /* ACPI_DEVICE_NOTIFY */ { - acpi_gbl_drv_notify.node = node; - acpi_gbl_drv_notify.handler = handler; - acpi_gbl_drv_notify.context = context; + acpi_gbl_device_notify.node = node; + acpi_gbl_device_notify.handler = handler; + acpi_gbl_device_notify.context = context; } /* Global notify handler installed */ @@ -282,13 +282,12 @@ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { - /* Object exists - make sure there's no handler */ if (((handler_type == ACPI_SYSTEM_NOTIFY) && - obj_desc->common_notify.sys_handler) || + obj_desc->common_notify.system_notify) || ((handler_type == ACPI_DEVICE_NOTIFY) && - obj_desc->common_notify.drv_handler)) { + obj_desc->common_notify.device_notify)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } @@ -305,6 +304,11 @@ /* Attach new object to the Node */ status = acpi_ns_attach_object (device, obj_desc, node->type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference (obj_desc); + if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -318,15 +322,15 @@ goto unlock_and_exit; } - notify_obj->notify_handler.node = node; - notify_obj->notify_handler.handler = handler; - notify_obj->notify_handler.context = context; + notify_obj->notify.node = node; + notify_obj->notify.handler = handler; + notify_obj->notify.context = context; if (handler_type == ACPI_SYSTEM_NOTIFY) { - obj_desc->common_notify.sys_handler = notify_obj; + obj_desc->common_notify.system_notify = notify_obj; } else /* ACPI_DEVICE_NOTIFY */ { - obj_desc->common_notify.drv_handler = notify_obj; + obj_desc->common_notify.device_notify = notify_obj; } } @@ -395,22 +399,22 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing notify handler for ROOT object.\n")); if (((handler_type == ACPI_SYSTEM_NOTIFY) && - !acpi_gbl_sys_notify.handler) || + !acpi_gbl_system_notify.handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && - !acpi_gbl_drv_notify.handler)) { + !acpi_gbl_device_notify.handler)) { status = AE_NOT_EXIST; goto unlock_and_exit; } if (handler_type == ACPI_SYSTEM_NOTIFY) { - acpi_gbl_sys_notify.node = NULL; - acpi_gbl_sys_notify.handler = NULL; - acpi_gbl_sys_notify.context = NULL; + acpi_gbl_system_notify.node = NULL; + acpi_gbl_system_notify.handler = NULL; + acpi_gbl_system_notify.context = NULL; } else { - acpi_gbl_drv_notify.node = NULL; - acpi_gbl_drv_notify.handler = NULL; - acpi_gbl_drv_notify.context = NULL; + acpi_gbl_device_notify.node = NULL; + acpi_gbl_device_notify.handler = NULL; + acpi_gbl_device_notify.context = NULL; } } @@ -436,14 +440,14 @@ /* Object exists - make sure there's an existing handler */ if (handler_type == ACPI_SYSTEM_NOTIFY) { - notify_obj = obj_desc->common_notify.sys_handler; + notify_obj = obj_desc->common_notify.system_notify; } else { - notify_obj = obj_desc->common_notify.drv_handler; + notify_obj = obj_desc->common_notify.device_notify; } if ((!notify_obj) || - (notify_obj->notify_handler.handler != handler)) { + (notify_obj->notify.handler != handler)) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } @@ -451,10 +455,10 @@ /* Remove the handler */ if (handler_type == ACPI_SYSTEM_NOTIFY) { - obj_desc->common_notify.sys_handler = NULL; + obj_desc->common_notify.system_notify = NULL; } else { - obj_desc->common_notify.drv_handler = NULL; + obj_desc->common_notify.device_notify = NULL; } acpi_ut_remove_reference (notify_obj); diff -urN linux-2.5.69-bk16/drivers/acpi/events/evxfevnt.c linux-2.5.69-bk17/drivers/acpi/events/evxfevnt.c --- linux-2.5.69-bk16/drivers/acpi/events/evxfevnt.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/events/evxfevnt.c 2003-05-24 04:33:33.000000000 -0700 @@ -654,7 +654,11 @@ } status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_DEVICE); + + /* Remove local reference to the object */ + acpi_ut_remove_reference (obj_desc); + if (ACPI_FAILURE (status)) { goto unlock_and_exit; } diff -urN linux-2.5.69-bk16/drivers/acpi/events/evxfregn.c linux-2.5.69-bk17/drivers/acpi/events/evxfregn.c --- linux-2.5.69-bk16/drivers/acpi/events/evxfregn.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/events/evxfregn.c 2003-05-24 04:33:33.000000000 -0700 @@ -154,7 +154,7 @@ break; default: - status = AE_NOT_EXIST; + status = AE_BAD_PARAMETER; goto unlock_and_exit; } } @@ -170,26 +170,36 @@ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { /* - * The object exists. + * The attached device object already exists. * Make sure the handler is not already installed. */ + handler_obj = obj_desc->device.address_space; - /* check the address handler the user requested */ + /* Walk the handler list for this device */ - handler_obj = obj_desc->device.addr_handler; while (handler_obj) { - /* - * Found an Address handler, see if user requested this - * address space. - */ - if(handler_obj->addr_handler.space_id == space_id) { - status = AE_ALREADY_EXISTS; + /* Same space_id indicates a handler already installed */ + + if(handler_obj->address_space.space_id == space_id) { + if (handler_obj->address_space.handler == handler) { + /* + * It is (relatively) OK to attempt to install the SAME + * handler twice. This can easily happen with PCI_Config space. + */ + status = AE_SAME_HANDLER; + goto unlock_and_exit; + } + else { + /* A handler is already installed */ + + status = AE_ALREADY_EXISTS; + } goto unlock_and_exit; } /* Walk the linked list of handlers */ - handler_obj = handler_obj->addr_handler.next; + handler_obj = handler_obj->address_space.next; } } else { @@ -218,8 +228,12 @@ /* Attach the new object to the Node */ status = acpi_ns_attach_object (node, obj_desc, type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference (obj_desc); + if (ACPI_FAILURE (status)) { - acpi_ut_remove_reference (obj_desc); goto unlock_and_exit; } } @@ -241,14 +255,25 @@ goto unlock_and_exit; } - handler_obj->addr_handler.space_id = (u8) space_id; - handler_obj->addr_handler.hflags = flags; - handler_obj->addr_handler.next = obj_desc->device.addr_handler; - handler_obj->addr_handler.region_list = NULL; - handler_obj->addr_handler.node = node; - handler_obj->addr_handler.handler = handler; - handler_obj->addr_handler.context = context; - handler_obj->addr_handler.setup = setup; + /* Init handler obj */ + + handler_obj->address_space.space_id = (u8) space_id; + handler_obj->address_space.hflags = flags; + handler_obj->address_space.region_list = NULL; + handler_obj->address_space.node = node; + handler_obj->address_space.handler = handler; + handler_obj->address_space.context = context; + handler_obj->address_space.setup = setup; + + /* Install at head of Device.address_space list */ + + handler_obj->address_space.next = obj_desc->device.address_space; + + /* + * The Device object is the first reference on the handler_obj. + * Each region that uses the handler adds a reference. + */ + obj_desc->device.address_space = handler_obj; /* * Walk the namespace finding all of the regions this @@ -262,18 +287,9 @@ * In either case, back up and search down the remainder * of the branch */ - status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, - ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, - acpi_ev_addr_handler_helper, - handler_obj, NULL); - - /* Place this handler 1st on the list */ - - handler_obj->common.reference_count = - (u16) (handler_obj->common.reference_count + - obj_desc->common.reference_count - 1); - obj_desc->device.addr_handler = handler_obj; - + status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler, + handler_obj, NULL); unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); @@ -341,12 +357,12 @@ /* Find the address handler the user requested */ - handler_obj = obj_desc->device.addr_handler; - last_obj_ptr = &obj_desc->device.addr_handler; + handler_obj = obj_desc->device.address_space; + last_obj_ptr = &obj_desc->device.address_space; while (handler_obj) { /* We have a handler, see if user requested this one */ - if (handler_obj->addr_handler.space_id == space_id) { + if (handler_obj->address_space.space_id == space_id) { /* Matched space_id, first dereference this in the Regions */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, @@ -354,7 +370,7 @@ handler_obj, handler, acpi_ut_get_region_name (space_id), node, obj_desc)); - region_obj = handler_obj->addr_handler.region_list; + region_obj = handler_obj->address_space.region_list; /* Walk the handler's region list */ @@ -372,13 +388,13 @@ * Walk the list: Just grab the head because the * detach_region removed the previous head. */ - region_obj = handler_obj->addr_handler.region_list; + region_obj = handler_obj->address_space.region_list; } /* Remove this Handler object from the list */ - *last_obj_ptr = handler_obj->addr_handler.next; + *last_obj_ptr = handler_obj->address_space.next; /* Now we can delete the handler object */ @@ -388,8 +404,8 @@ /* Walk the linked list of handlers */ - last_obj_ptr = &handler_obj->addr_handler.next; - handler_obj = handler_obj->addr_handler.next; + last_obj_ptr = &handler_obj->address_space.next; + handler_obj = handler_obj->address_space.next; } /* The handler does not exist */ diff -urN linux-2.5.69-bk16/drivers/acpi/executer/exconfig.c linux-2.5.69-bk17/drivers/acpi/executer/exconfig.c --- linux-2.5.69-bk16/drivers/acpi/executer/exconfig.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/executer/exconfig.c 2003-05-24 04:33:33.000000000 -0700 @@ -360,11 +360,11 @@ /* The table must be either an SSDT or a PSDT */ if ((!ACPI_STRNCMP (table_ptr->signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].sig_length)) && + acpi_gbl_table_data[ACPI_TABLE_PSDT].signature, + acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) && (!ACPI_STRNCMP (table_ptr->signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].sig_length))) { + acpi_gbl_table_data[ACPI_TABLE_SSDT].signature, + acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Table has invalid signature [%4.4s], must be SSDT or PSDT\n", table_ptr->signature)); diff -urN linux-2.5.69-bk16/drivers/acpi/executer/exdump.c linux-2.5.69-bk17/drivers/acpi/executer/exdump.c --- linux-2.5.69-bk16/drivers/acpi/executer/exdump.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/executer/exdump.c 2003-05-24 04:33:33.000000000 -0700 @@ -635,9 +635,9 @@ case ACPI_TYPE_DEVICE: - acpi_ex_out_pointer ("addr_handler", obj_desc->device.addr_handler); - acpi_ex_out_pointer ("sys_handler", obj_desc->device.sys_handler); - acpi_ex_out_pointer ("drv_handler", obj_desc->device.drv_handler); + acpi_ex_out_pointer ("address_space", obj_desc->device.address_space); + acpi_ex_out_pointer ("system_notify", obj_desc->device.system_notify); + acpi_ex_out_pointer ("device_notify", obj_desc->device.device_notify); break; @@ -673,7 +673,7 @@ acpi_ex_out_integer ("Flags", obj_desc->region.flags); acpi_ex_out_address ("Address", obj_desc->region.address); acpi_ex_out_integer ("Length", obj_desc->region.length); - acpi_ex_out_pointer ("addr_handler", obj_desc->region.addr_handler); + acpi_ex_out_pointer ("address_space", obj_desc->region.address_space); acpi_ex_out_pointer ("Next", obj_desc->region.next); break; @@ -682,8 +682,8 @@ acpi_ex_out_integer ("system_level", obj_desc->power_resource.system_level); acpi_ex_out_integer ("resource_order", obj_desc->power_resource.resource_order); - acpi_ex_out_pointer ("sys_handler", obj_desc->power_resource.sys_handler); - acpi_ex_out_pointer ("drv_handler", obj_desc->power_resource.drv_handler); + acpi_ex_out_pointer ("system_notify", obj_desc->power_resource.system_notify); + acpi_ex_out_pointer ("device_notify", obj_desc->power_resource.device_notify); break; @@ -692,17 +692,17 @@ acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id); acpi_ex_out_integer ("Length", obj_desc->processor.length); acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address); - acpi_ex_out_pointer ("sys_handler", obj_desc->processor.sys_handler); - acpi_ex_out_pointer ("drv_handler", obj_desc->processor.drv_handler); - acpi_ex_out_pointer ("addr_handler", obj_desc->processor.addr_handler); + acpi_ex_out_pointer ("system_notify", obj_desc->processor.system_notify); + acpi_ex_out_pointer ("device_notify", obj_desc->processor.device_notify); + acpi_ex_out_pointer ("address_space", obj_desc->processor.address_space); break; case ACPI_TYPE_THERMAL: - acpi_ex_out_pointer ("sys_handler", obj_desc->thermal_zone.sys_handler); - acpi_ex_out_pointer ("drv_handler", obj_desc->thermal_zone.drv_handler); - acpi_ex_out_pointer ("addr_handler", obj_desc->thermal_zone.addr_handler); + acpi_ex_out_pointer ("system_notify", obj_desc->thermal_zone.system_notify); + acpi_ex_out_pointer ("device_notify", obj_desc->thermal_zone.device_notify); + acpi_ex_out_pointer ("address_space", obj_desc->thermal_zone.address_space); break; @@ -762,18 +762,18 @@ case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: - acpi_ex_out_integer ("space_id", obj_desc->addr_handler.space_id); - acpi_ex_out_pointer ("Next", obj_desc->addr_handler.next); - acpi_ex_out_pointer ("region_list", obj_desc->addr_handler.region_list); - acpi_ex_out_pointer ("Node", obj_desc->addr_handler.node); - acpi_ex_out_pointer ("Context", obj_desc->addr_handler.context); + acpi_ex_out_integer ("space_id", obj_desc->address_space.space_id); + acpi_ex_out_pointer ("Next", obj_desc->address_space.next); + acpi_ex_out_pointer ("region_list", obj_desc->address_space.region_list); + acpi_ex_out_pointer ("Node", obj_desc->address_space.node); + acpi_ex_out_pointer ("Context", obj_desc->address_space.context); break; case ACPI_TYPE_LOCAL_NOTIFY: - acpi_ex_out_pointer ("Node", obj_desc->notify_handler.node); - acpi_ex_out_pointer ("Context", obj_desc->notify_handler.context); + acpi_ex_out_pointer ("Node", obj_desc->notify.node); + acpi_ex_out_pointer ("Context", obj_desc->notify.context); break; diff -urN linux-2.5.69-bk16/drivers/acpi/hardware/hwgpe.c linux-2.5.69-bk17/drivers/acpi/hardware/hwgpe.c --- linux-2.5.69-bk16/drivers/acpi/hardware/hwgpe.c 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/hardware/hwgpe.c 2003-05-24 04:33:33.000000000 -0700 @@ -77,7 +77,7 @@ * to enable the GPE, and write out the new register. */ status = acpi_hw_low_level_read (8, &in_byte, - &gpe_event_info->register_info->enable_address, 0); + &gpe_event_info->register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -85,7 +85,7 @@ /* Write with the new GPE bit enabled */ status = acpi_hw_low_level_write (8, (in_byte | gpe_event_info->bit_mask), - &gpe_event_info->register_info->enable_address, 0); + &gpe_event_info->register_info->enable_address); return (status); } @@ -164,7 +164,7 @@ * and write out the new register value to disable the GPE. */ status = acpi_hw_low_level_read (8, &in_byte, - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -172,7 +172,7 @@ /* Write the byte with this GPE bit cleared */ status = acpi_hw_low_level_write (8, (in_byte & ~(gpe_event_info->bit_mask)), - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -246,7 +246,7 @@ * clear this GPE. */ status = acpi_hw_low_level_write (8, gpe_event_info->bit_mask, - &gpe_event_info->register_info->status_address, 0); + &gpe_event_info->register_info->status_address); return (status); } @@ -293,7 +293,7 @@ /* GPE Enabled? */ - status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address, 0); + status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -310,7 +310,7 @@ /* GPE active (set)? */ - status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address, 0); + status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -360,7 +360,7 @@ for (i = 0; i < gpe_block->register_count; i++) { status = acpi_hw_low_level_write (8, 0x00, - &gpe_block->register_info[i].enable_address, (u32) i); + &gpe_block->register_info[i].enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -401,7 +401,7 @@ for (i = 0; i < gpe_block->register_count; i++) { status = acpi_hw_low_level_write (8, 0xFF, - &gpe_block->register_info[i].status_address, (u32) i); + &gpe_block->register_info[i].status_address); if (ACPI_FAILURE (status)) { return (status); } @@ -447,7 +447,7 @@ * will be using it to restore all the GPEs later. */ status = acpi_hw_low_level_read (8, &in_value, - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -458,7 +458,7 @@ * Disable all GPEs except wakeup GPEs. */ status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable, - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -539,7 +539,7 @@ * Blast them back in. */ status = acpi_hw_low_level_write (8, gpe_register_info->enable, - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } diff -urN linux-2.5.69-bk16/drivers/acpi/hardware/hwregs.c linux-2.5.69-bk17/drivers/acpi/hardware/hwregs.c --- linux-2.5.69-bk16/drivers/acpi/hardware/hwregs.c 2003-05-04 16:53:40.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/hardware/hwregs.c 2003-05-24 04:33:33.000000000 -0700 @@ -93,7 +93,7 @@ if (acpi_gbl_FADT->xpm1b_evt_blk.address) { status = acpi_hw_low_level_write (16, ACPI_BITMASK_ALL_FIXED_STATUS, - &acpi_gbl_FADT->xpm1b_evt_blk, 0); + &acpi_gbl_FADT->xpm1b_evt_blk); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -470,7 +470,6 @@ { u32 value1 = 0; u32 value2 = 0; - u32 bank_offset; acpi_status status; @@ -487,50 +486,53 @@ switch (register_id) { case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_evt_blk, 0); + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_evt_blk); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_evt_blk, 0); + /* PM1B is optional */ + + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_evt_blk); value1 |= value2; break; - case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/ + case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ - bank_offset = ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len); - status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_evt_blk, bank_offset); + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_xpm1a_enable); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_evt_blk, bank_offset); + /* PM1B is optional */ + + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_xpm1b_enable); value1 |= value2; break; case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ - status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_cnt_blk, 0); + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_cnt_blk); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_cnt_blk); value1 |= value2; break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - status = acpi_hw_low_level_read (8, &value1, &acpi_gbl_FADT->xpm2_cnt_blk, 0); + status = acpi_hw_low_level_read (8, &value1, &acpi_gbl_FADT->xpm2_cnt_blk); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - status = acpi_hw_low_level_read (32, &value1, &acpi_gbl_FADT->xpm_tmr_blk, 0); + status = acpi_hw_low_level_read (32, &value1, &acpi_gbl_FADT->xpm_tmr_blk); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ @@ -577,7 +579,6 @@ u32 register_id, u32 value) { - u32 bank_offset; acpi_status status; @@ -594,59 +595,62 @@ switch (register_id) { case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_evt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_evt_blk); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_evt_blk, 0); + /* PM1B is optional */ + + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_evt_blk); break; case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/ - bank_offset = ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len); - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_evt_blk, bank_offset); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1a_enable); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_evt_blk, bank_offset); + /* PM1B is optional */ + + status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1b_enable); break; case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk); break; case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk); break; case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk); break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - status = acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->xpm2_cnt_blk, 0); + status = acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->xpm2_cnt_blk); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - status = acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->xpm_tmr_blk, 0); + status = acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->xpm_tmr_blk); break; @@ -676,11 +680,11 @@ * * FUNCTION: acpi_hw_low_level_read * - * PARAMETERS: Register - GAS register structure - * Offset - Offset from the base address in the GAS - * Width - 8, 16, or 32 + * PARAMETERS: Width - 8, 16, or 32 + * Value - Where the value is returned + * Register - GAS register structure * - * RETURN: Value read + * RETURN: Status * * DESCRIPTION: Read from either memory, IO, or PCI config space. * @@ -690,11 +694,8 @@ acpi_hw_low_level_read ( u32 width, u32 *value, - struct acpi_generic_address *reg, - u32 offset) + struct acpi_generic_address *reg) { - acpi_physical_address mem_address; - acpi_io_address io_address; struct acpi_pci_id pci_id; u16 pci_register; acpi_status status; @@ -721,19 +722,16 @@ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: - mem_address = (reg->address - + (acpi_physical_address) offset); - - status = acpi_os_read_memory (mem_address, value, width); + status = acpi_os_read_memory ( + (acpi_physical_address) reg->address, + value, width); break; case ACPI_ADR_SPACE_SYSTEM_IO: - io_address = (acpi_io_address) (reg->address - + (acpi_physical_address) offset); - - status = acpi_os_read_port (io_address, value, width); + status = acpi_os_read_port ((acpi_io_address) reg->address, + value, width); break; @@ -743,15 +741,16 @@ pci_id.bus = 0; pci_id.device = ACPI_PCI_DEVICE (reg->address); pci_id.function = ACPI_PCI_FUNCTION (reg->address); - pci_register = (u16) (ACPI_PCI_REGISTER (reg->address) - + offset); + pci_register = (u16) ACPI_PCI_REGISTER (reg->address); - status = acpi_os_read_pci_configuration (&pci_id, pci_register, value, width); + status = acpi_os_read_pci_configuration (&pci_id, pci_register, + value, width); break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Unsupported address space: %X\n", reg->address_space_id)); status = AE_BAD_PARAMETER; break; } @@ -767,12 +766,10 @@ * PARAMETERS: Width - 8, 16, or 32 * Value - To be written * Register - GAS register structure - * Offset - Offset from the base address in the GAS - * * - * RETURN: Value read + * RETURN: Status * - * DESCRIPTION: Read from either memory, IO, or PCI config space. + * DESCRIPTION: Write to either memory, IO, or PCI config space. * ******************************************************************************/ @@ -780,11 +777,8 @@ acpi_hw_low_level_write ( u32 width, u32 value, - struct acpi_generic_address *reg, - u32 offset) + struct acpi_generic_address *reg) { - acpi_physical_address mem_address; - acpi_io_address io_address; struct acpi_pci_id pci_id; u16 pci_register; acpi_status status; @@ -809,19 +803,16 @@ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: - mem_address = (reg->address - + (acpi_physical_address) offset); - - status = acpi_os_write_memory (mem_address, value, width); + status = acpi_os_write_memory ( + (acpi_physical_address) reg->address, + value, width); break; case ACPI_ADR_SPACE_SYSTEM_IO: - io_address = (acpi_io_address) (reg->address - + (acpi_physical_address) offset); - - status = acpi_os_write_port (io_address, value, width); + status = acpi_os_write_port ((acpi_io_address) reg->address, + value, width); break; @@ -831,15 +822,16 @@ pci_id.bus = 0; pci_id.device = ACPI_PCI_DEVICE (reg->address); pci_id.function = ACPI_PCI_FUNCTION (reg->address); - pci_register = (u16) (ACPI_PCI_REGISTER (reg->address) - + offset); + pci_register = (u16) ACPI_PCI_REGISTER (reg->address); - status = acpi_os_write_pci_configuration (&pci_id, pci_register, (acpi_integer) value, width); + status = acpi_os_write_pci_configuration (&pci_id, pci_register, + (acpi_integer) value, width); break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Unsupported address space: %X\n", reg->address_space_id)); status = AE_BAD_PARAMETER; break; } diff -urN linux-2.5.69-bk16/drivers/acpi/hardware/hwtimer.c linux-2.5.69-bk17/drivers/acpi/hardware/hwtimer.c --- linux-2.5.69-bk16/drivers/acpi/hardware/hwtimer.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/hardware/hwtimer.c 2003-05-24 04:33:33.000000000 -0700 @@ -108,7 +108,7 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } - status = acpi_hw_low_level_read (32, ticks, &acpi_gbl_FADT->xpm_tmr_blk, 0); + status = acpi_hw_low_level_read (32, ticks, &acpi_gbl_FADT->xpm_tmr_blk); return_ACPI_STATUS (status); } diff -urN linux-2.5.69-bk16/drivers/acpi/namespace/nsalloc.c linux-2.5.69-bk17/drivers/acpi/namespace/nsalloc.c --- linux-2.5.69-bk16/drivers/acpi/namespace/nsalloc.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/namespace/nsalloc.c 2003-05-24 04:33:33.000000000 -0700 @@ -116,19 +116,33 @@ prev_node = NULL; next_node = parent_node->child; + /* Find the node that is the previous peer in the parent's child list */ + while (next_node != node) { prev_node = next_node; next_node = prev_node->peer; } if (prev_node) { + /* Node is not first child, unlink it */ + prev_node->peer = next_node->peer; if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { prev_node->flags |= ANOBJ_END_OF_PEER_LIST; } } else { - parent_node->child = next_node->peer; + /* Node is first child (has no previous peer) */ + + if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + /* No peers at all */ + + parent_node->child = NULL; + } + else { /* Link peer list to parent */ + + parent_node->child = next_node->peer; + } } @@ -222,7 +236,7 @@ struct acpi_namespace_node *node, /* New Child*/ acpi_object_type type) { - u16 owner_id = TABLE_ID_DSDT; + u16 owner_id = 0; struct acpi_namespace_node *child_node; #ifdef ACPI_ALPHABETIC_NAMESPACE @@ -355,6 +369,7 @@ { struct acpi_namespace_node *child_node; struct acpi_namespace_node *next_node; + struct acpi_namespace_node *node; u8 flags; @@ -399,6 +414,25 @@ * Detach an object if there is one, then free the child node */ acpi_ns_detach_object (child_node); + + /* + * Decrement the reference count(s) of all parents up to + * the root! (counts were incremented when the node was created) + */ + node = child_node; + while ((node = acpi_ns_get_parent_node (node)) != NULL) { + node->reference_count--; + } + + /* There should be only one reference remaining on this node */ + + if (child_node->reference_count != 1) { + ACPI_REPORT_WARNING (("Existing references (%d) on node being deleted (%p)\n", + child_node->reference_count, child_node)); + } + + /* Now we can delete the node */ + ACPI_MEM_FREE (child_node); /* And move on to the next child in the list */ @@ -512,7 +546,7 @@ * ******************************************************************************/ -static void +void acpi_ns_remove_reference ( struct acpi_namespace_node *node) { diff -urN linux-2.5.69-bk16/drivers/acpi/namespace/nsdumpdv.c linux-2.5.69-bk17/drivers/acpi/namespace/nsdumpdv.c --- linux-2.5.69-bk16/drivers/acpi/namespace/nsdumpdv.c 2003-05-04 16:52:48.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/namespace/nsdumpdv.c 2003-05-24 04:33:33.000000000 -0700 @@ -72,7 +72,8 @@ void *context, void **return_value) { - struct acpi_device_info info; + struct acpi_buffer buffer; + struct acpi_device_info *info; acpi_status status; u32 i; @@ -82,16 +83,19 @@ status = acpi_ns_dump_one_object (obj_handle, level, context, return_value); - status = acpi_get_object_info (obj_handle, &info); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info (obj_handle, &buffer); if (ACPI_SUCCESS (status)) { + info = buffer.pointer; for (i = 0; i < level; i++) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " ")); } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", - info.hardware_id, - ACPI_HIDWORD (info.address), ACPI_LODWORD (info.address), - info.current_status)); + info->hardware_id.value, + ACPI_HIDWORD (info->address), ACPI_LODWORD (info->address), + info->current_status)); + ACPI_MEM_FREE (info); } return (status); diff -urN linux-2.5.69-bk16/drivers/acpi/namespace/nsload.c linux-2.5.69-bk17/drivers/acpi/namespace/nsload.c --- linux-2.5.69-bk16/drivers/acpi/namespace/nsload.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/namespace/nsload.c 2003-05-24 04:33:33.000000000 -0700 @@ -79,7 +79,7 @@ /* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */ - if (!(acpi_gbl_acpi_table_data[table_desc->type].flags & ACPI_TABLE_EXECUTABLE)) { + if (!(acpi_gbl_table_data[table_desc->type].flags & ACPI_TABLE_EXECUTABLE)) { /* Just ignore this table */ return_ACPI_STATUS (AE_OK); @@ -182,7 +182,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDT\n")); - table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_DSDT]; + table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next; /* If table already loaded into namespace, just return */ @@ -190,8 +190,6 @@ goto unlock_and_exit; } - table_desc->table_id = TABLE_ID_DSDT; - /* Now load the single DSDT */ status = acpi_ns_load_table (table_desc, acpi_gbl_root_node); @@ -205,13 +203,13 @@ case ACPI_TABLE_SSDT: ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTs\n", - acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count)); + acpi_gbl_table_lists[ACPI_TABLE_SSDT].count)); /* * Traverse list of SSDT tables */ - table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT]; - for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) { + table_desc = acpi_gbl_table_lists[ACPI_TABLE_SSDT].next; + for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_SSDT].count; i++) { /* * Only attempt to load table if it is not * already loaded! @@ -233,14 +231,14 @@ case ACPI_TABLE_PSDT: ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTs\n", - acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count)); + acpi_gbl_table_lists[ACPI_TABLE_PSDT].count)); /* * Traverse list of PSDT tables */ - table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT]; + table_desc = acpi_gbl_table_lists[ACPI_TABLE_PSDT].next; - for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) { + for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_PSDT].count; i++) { /* Only attempt to load table if it is not already loaded! */ if (!table_desc->loaded_into_namespace) { diff -urN linux-2.5.69-bk16/drivers/acpi/namespace/nsparse.c linux-2.5.69-bk17/drivers/acpi/namespace/nsparse.c --- linux-2.5.69-bk16/drivers/acpi/namespace/nsparse.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/namespace/nsparse.c 2003-05-24 04:33:33.000000000 -0700 @@ -85,10 +85,9 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - /* Create and initialize a new walk state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, + walk_state = acpi_ds_create_walk_state (table_desc->table_id, NULL, NULL, NULL); if (!walk_state) { acpi_ps_free_op (parse_root); diff -urN linux-2.5.69-bk16/drivers/acpi/namespace/nssearch.c linux-2.5.69-bk17/drivers/acpi/namespace/nssearch.c --- linux-2.5.69-bk16/drivers/acpi/namespace/nssearch.c 2003-05-04 16:53:42.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/namespace/nssearch.c 2003-05-24 04:33:33.000000000 -0700 @@ -117,8 +117,9 @@ * Found matching entry. */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, - "Name %4.4s Type [%s] found at %p\n", - (char *) &target_name, acpi_ut_get_type_name (next_node->type), next_node)); + "Name %4.4s Type [%s] found in scope [%4.4s] %p\n", + (char *) &target_name, acpi_ut_get_type_name (next_node->type), + next_node->name.ascii, next_node)); *return_node = next_node; return_ACPI_STATUS (AE_OK); @@ -141,8 +142,10 @@ /* Searched entire namespace level, not found */ - ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name %4.4s Type [%s] not found at %p\n", - (char *) &target_name, acpi_ut_get_type_name (type), next_node)); + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Name %4.4s Type [%s] not found in search in scope [%4.4s] %p first child %p\n", + (char *) &target_name, acpi_ut_get_type_name (type), + node->name.ascii, node, node->child)); return_ACPI_STATUS (AE_NOT_FOUND); } diff -urN linux-2.5.69-bk16/drivers/acpi/namespace/nsutils.c linux-2.5.69-bk17/drivers/acpi/namespace/nsutils.c --- linux-2.5.69-bk16/drivers/acpi/namespace/nsutils.c 2003-05-04 16:53:28.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/namespace/nsutils.c 2003-05-24 04:33:33.000000000 -0700 @@ -181,7 +181,11 @@ status = acpi_ns_handle_to_pathname (node, &buffer); if (ACPI_SUCCESS (status)) { - acpi_os_printf ("%s [%s] (Node %p)", msg, (char *) buffer.pointer, node); + if (msg) { + acpi_os_printf ("%s ", msg); + } + + acpi_os_printf ("[%s] (Node %p)", (char *) buffer.pointer, node); ACPI_MEM_FREE (buffer.pointer); } } @@ -799,38 +803,31 @@ acpi_ns_terminate (void) { union acpi_operand_object *obj_desc; - struct acpi_namespace_node *this_node; ACPI_FUNCTION_TRACE ("ns_terminate"); - this_node = acpi_gbl_root_node; - /* - * 1) Free the entire namespace -- all objects, tables, and stacks + * 1) Free the entire namespace -- all nodes and objects * - * Delete all objects linked to the root - * (additional table descriptors) + * Delete all object descriptors attached to namepsace nodes */ - acpi_ns_delete_namespace_subtree (this_node); + acpi_ns_delete_namespace_subtree (acpi_gbl_root_node); - /* Detach any object(s) attached to the root */ + /* Detach any objects attached to the root */ - obj_desc = acpi_ns_get_attached_object (this_node); + obj_desc = acpi_ns_get_attached_object (acpi_gbl_root_node); if (obj_desc) { - acpi_ns_detach_object (this_node); - acpi_ut_remove_reference (obj_desc); + acpi_ns_detach_object (acpi_gbl_root_node); } - acpi_ns_delete_children (this_node); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); - /* * 2) Now we can delete the ACPI tables */ - acpi_tb_delete_acpi_tables (); + acpi_tb_delete_all_tables (); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n")); return_VOID; diff -urN linux-2.5.69-bk16/drivers/acpi/namespace/nsxfeval.c linux-2.5.69-bk17/drivers/acpi/namespace/nsxfeval.c --- linux-2.5.69-bk16/drivers/acpi/namespace/nsxfeval.c 2003-05-04 16:53:56.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/namespace/nsxfeval.c 2003-05-24 04:33:33.000000000 -0700 @@ -437,16 +437,15 @@ void *context, void **return_value) { + struct acpi_get_devices_info *info = context; acpi_status status; struct acpi_namespace_node *node; u32 flags; struct acpi_device_id hid; - struct acpi_device_id cid; - struct acpi_get_devices_info *info; + struct acpi_compatible_id_list *cid; + acpi_native_uint i; - info = context; - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return (status); @@ -462,9 +461,8 @@ return (AE_BAD_PARAMETER); } - /* - * Run _STA to determine if device is present - */ + /* Run _STA to determine if device is present */ + status = acpi_ut_execute_STA (node, &flags); if (ACPI_FAILURE (status)) { return (AE_CTRL_DEPTH); @@ -472,12 +470,12 @@ if (!(flags & 0x01)) { /* Don't return at the device or children of the device if not there */ + return (AE_CTRL_DEPTH); } - /* - * Filter based on device HID & CID - */ + /* Filter based on device HID & CID */ + if (info->hid != NULL) { status = acpi_ut_execute_HID (node, &hid); if (status == AE_NOT_FOUND) { @@ -487,7 +485,9 @@ return (AE_CTRL_DEPTH); } - if (ACPI_STRNCMP (hid.buffer, info->hid, sizeof (hid.buffer)) != 0) { + if (ACPI_STRNCMP (hid.value, info->hid, sizeof (hid.value)) != 0) { + /* Get the list of Compatible IDs */ + status = acpi_ut_execute_CID (node, &cid); if (status == AE_NOT_FOUND) { return (AE_OK); @@ -496,11 +496,16 @@ return (AE_CTRL_DEPTH); } - /* TBD: Handle CID packages */ + /* Walk the CID list */ - if (ACPI_STRNCMP (cid.buffer, info->hid, sizeof (cid.buffer)) != 0) { - return (AE_OK); + for (i = 0; i < cid->count; i++) { + if (ACPI_STRNCMP (cid->id[i].value, info->hid, + sizeof (struct acpi_compatible_id)) != 0) { + ACPI_MEM_FREE (cid); + return (AE_OK); + } } + ACPI_MEM_FREE (cid); } } diff -urN linux-2.5.69-bk16/drivers/acpi/namespace/nsxfname.c linux-2.5.69-bk17/drivers/acpi/namespace/nsxfname.c --- linux-2.5.69-bk16/drivers/acpi/namespace/nsxfname.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/namespace/nsxfname.c 2003-05-24 04:33:33.000000000 -0700 @@ -51,7 +51,7 @@ ACPI_MODULE_NAME ("nsxfname") -/**************************************************************************** +/****************************************************************************** * * FUNCTION: acpi_get_handle * @@ -119,7 +119,8 @@ /* * Find the Node and convert to a handle */ - status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH, &node); + status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH, + &node); *ret_handle = NULL; if (ACPI_SUCCESS (status)) { @@ -130,7 +131,7 @@ } -/**************************************************************************** +/****************************************************************************** * * FUNCTION: acpi_get_name * @@ -211,7 +212,7 @@ } -/**************************************************************************** +/****************************************************************************** * * FUNCTION: acpi_get_object_info * @@ -229,22 +230,27 @@ acpi_status acpi_get_object_info ( acpi_handle handle, - struct acpi_device_info *info) + struct acpi_buffer *buffer) { - struct acpi_device_id hid; - struct acpi_device_id uid; acpi_status status; - u32 device_status = 0; - acpi_integer address = 0; struct acpi_namespace_node *node; + struct acpi_device_info info; + struct acpi_device_info *return_info; + struct acpi_compatible_id_list *cid_list = NULL; + acpi_size size; /* Parameter validation */ - if (!handle || !info) { + if (!handle || !buffer) { return (AE_BAD_PARAMETER); } + status = acpi_ut_validate_buffer (buffer); + if (ACPI_FAILURE (status)) { + return (status); + } + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return (status); @@ -256,69 +262,94 @@ return (AE_BAD_PARAMETER); } - info->type = node->type; - info->name = node->name.integer; + /* Init return structure */ + + size = sizeof (struct acpi_device_info); + ACPI_MEMSET (&info, 0, size); + + info.type = node->type; + info.name = node->name.integer; + info.valid = 0; status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return (status); } - /* - * If not a device, we are all done. - */ - if (info->type != ACPI_TYPE_DEVICE) { - return (AE_OK); - } + /* If not a device, we are all done */ + if (info.type == ACPI_TYPE_DEVICE) { + /* + * Get extra info for ACPI Devices objects only: + * Run the Device _HID, _UID, _CID, _STA, and _ADR methods. + * + * Note: none of these methods are required, so they may or may + * not be present for this device. The Info.Valid bitfield is used + * to indicate which methods were found and ran successfully. + */ + + /* Execute the Device._HID method */ + + status = acpi_ut_execute_HID (node, &info.hardware_id); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_HID; + } - /* - * Get extra info for ACPI devices only. Run the - * _HID, _UID, _STA, and _ADR methods. Note: none - * of these methods are required, so they may or may - * not be present. The Info->Valid bits are used - * to indicate which methods ran successfully. - */ - info->valid = 0; + /* Execute the Device._UID method */ - /* Execute the _HID method and save the result */ + status = acpi_ut_execute_UID (node, &info.unique_id); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_UID; + } - status = acpi_ut_execute_HID (node, &hid); - if (ACPI_SUCCESS (status)) { - ACPI_STRNCPY (info->hardware_id, hid.buffer, sizeof(info->hardware_id)); - info->valid |= ACPI_VALID_HID; - } + /* Execute the Device._CID method */ - /* Execute the _UID method and save the result */ + status = acpi_ut_execute_CID (node, &cid_list); + if (ACPI_SUCCESS (status)) { + size += ((acpi_size) cid_list->count - 1) * + sizeof (struct acpi_compatible_id); + info.valid |= ACPI_VALID_CID; + } - status = acpi_ut_execute_UID (node, &uid); - if (ACPI_SUCCESS (status)) { - ACPI_STRCPY (info->unique_id, uid.buffer); - info->valid |= ACPI_VALID_UID; + /* Execute the Device._STA method */ + + status = acpi_ut_execute_STA (node, &info.current_status); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_STA; + } + + /* Execute the Device._ADR method */ + + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node, + &info.address); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_ADR; + } + + status = AE_OK; } - /* - * Execute the _STA method and save the result - * _STA is not always present - */ - status = acpi_ut_execute_STA (node, &device_status); - if (ACPI_SUCCESS (status)) { - info->current_status = device_status; - info->valid |= ACPI_VALID_STA; + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer (buffer, size); + if (ACPI_FAILURE (status)) { + goto cleanup; } - /* - * Execute the _ADR method and save result if successful - * _ADR is not always present - */ - status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, - node, &address); + /* Populate the return buffer */ - if (ACPI_SUCCESS (status)) { - info->address = address; - info->valid |= ACPI_VALID_ADR; + return_info = buffer->pointer; + ACPI_MEMCPY (return_info, &info, sizeof (struct acpi_device_info)); + + if (cid_list) { + ACPI_MEMCPY (&return_info->compatibility_id, cid_list, cid_list->size); } - return (AE_OK); + +cleanup: + if (cid_list) { + ACPI_MEM_FREE (cid_list); + } + return (status); } diff -urN linux-2.5.69-bk16/drivers/acpi/osl.c linux-2.5.69-bk17/drivers/acpi/osl.c --- linux-2.5.69-bk16/drivers/acpi/osl.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/osl.c 2003-05-24 04:33:33.000000000 -0700 @@ -237,7 +237,7 @@ static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs) { - return (*acpi_irq_handler)(acpi_irq_context); + return (*acpi_irq_handler)(acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; } acpi_status @@ -1006,7 +1006,7 @@ return 0; for (; count-- && str && *str; str++) { - if (isalnum(*str) || *str == ' ') + if (isalnum(*str) || *str == ' ' || *str == ':') *p++ = *str; else if (*str == '\'' || *str == '"') continue; diff -urN linux-2.5.69-bk16/drivers/acpi/parser/psargs.c linux-2.5.69-bk17/drivers/acpi/parser/psargs.c --- linux-2.5.69-bk16/drivers/acpi/parser/psargs.c 2003-05-04 16:53:09.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/parser/psargs.c 2003-05-24 04:33:33.000000000 -0700 @@ -350,6 +350,11 @@ (status != AE_NOT_FOUND)) { ACPI_REPORT_NSERROR (path, status); + + acpi_os_printf ("search_node %p start_node %p return_node %p\n", + scope_info.scope.node, parser_state->start_node, node); + + } else { /* diff -urN linux-2.5.69-bk16/drivers/acpi/parser/pswalk.c linux-2.5.69-bk17/drivers/acpi/parser/pswalk.c --- linux-2.5.69-bk16/drivers/acpi/parser/pswalk.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/parser/pswalk.c 2003-05-24 04:33:33.000000000 -0700 @@ -270,7 +270,7 @@ return_VOID; } - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, thread); + walk_state = acpi_ds_create_walk_state (0, NULL, NULL, thread); if (!walk_state) { return_VOID; } diff -urN linux-2.5.69-bk16/drivers/acpi/parser/psxface.c linux-2.5.69-bk17/drivers/acpi/parser/psxface.c --- linux-2.5.69-bk16/drivers/acpi/parser/psxface.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/parser/psxface.c 2003-05-24 04:33:33.000000000 -0700 @@ -178,7 +178,7 @@ /* Create and initialize a new walk state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } diff -urN linux-2.5.69-bk16/drivers/acpi/resources/rsxface.c linux-2.5.69-bk17/drivers/acpi/resources/rsxface.c --- linux-2.5.69-bk16/drivers/acpi/resources/rsxface.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/resources/rsxface.c 2003-05-24 04:33:33.000000000 -0700 @@ -379,25 +379,31 @@ { struct acpi_resource_address16 *address16; struct acpi_resource_address32 *address32; - struct acpi_resource_address64 *address64; switch (resource->id) { case ACPI_RSTYPE_ADDRESS16: + address16 = (struct acpi_resource_address16 *) &resource->data; ACPI_COPY_ADDRESS(out, address16); break; + case ACPI_RSTYPE_ADDRESS32: + address32 = (struct acpi_resource_address32 *) &resource->data; ACPI_COPY_ADDRESS(out, address32); break; + case ACPI_RSTYPE_ADDRESS64: - address64 = (struct acpi_resource_address64 *) &resource->data; - ACPI_COPY_ADDRESS(out, address64); + + /* Simple copy for 64 bit source */ + + ACPI_MEMCPY (out, &resource->data, sizeof (struct acpi_resource_address64)); break; + default: return (AE_BAD_PARAMETER); } diff -urN linux-2.5.69-bk16/drivers/acpi/scan.c linux-2.5.69-bk17/drivers/acpi/scan.c --- linux-2.5.69-bk16/drivers/acpi/scan.c 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/scan.c 2003-05-24 04:33:33.000000000 -0700 @@ -28,6 +28,8 @@ static void acpi_device_release(struct kobject * kobj) { struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj); + if (dev->pnp.cid_list) + kfree(dev->pnp.cid_list); kfree(dev); } @@ -69,7 +71,7 @@ device->kobj.parent = &parent->kobj; device->kobj.ktype = &ktype_acpi_ns; device->kobj.kset = &acpi_namespace_kset; - kobject_register(&device->kobj); + kobject_add(&device->kobj); } static int @@ -201,32 +203,15 @@ goto Done; if (device->flags.compatible_ids) { - acpi_status status = AE_OK; - union acpi_object *object = NULL; - char cid[256] = {}; - - status = acpi_evaluate_object(device->handle, "_CID", NULL, - &buffer); - if (ACPI_FAILURE(status) || !buffer.pointer) - return -ENOENT; - - object = (union acpi_object *) buffer.pointer; - - switch (object->type) { - case ACPI_TYPE_INTEGER: - acpi_ex_eisa_id_to_string((u32) object->integer.value, - cid); - break; - case ACPI_TYPE_STRING: - strncpy(cid, object->string.pointer, sizeof(cid) - 1); - break; - case ACPI_TYPE_PACKAGE: - /* TBD: Support CID packages */ - break; - } + struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; + int i; - if (strlen(cid) && strstr(driver->ids,cid)) - goto Done; + /* compare multiple _CID entries against driver ids */ + for (i = 0; i < cid_list->count; i++) + { + if (strstr(driver->ids, cid_list->id[i].value)) + goto Done; + } } error = -ENOENT; @@ -523,27 +508,30 @@ static void acpi_device_set_id(struct acpi_device * device, struct acpi_device * parent, acpi_handle handle, int type) { - struct acpi_device_info info; + struct acpi_device_info *info; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; char *hid = NULL; char *uid = NULL; + struct acpi_compatible_id_list *cid_list = NULL; acpi_status status; switch (type) { case ACPI_BUS_TYPE_DEVICE: - status = acpi_get_object_info(handle, &info); + status = acpi_get_object_info(handle, &buffer); if (ACPI_FAILURE(status)) { printk("%s: Error reading device info\n",__FUNCTION__); return; } - /* Clean up info strings (not NULL terminated) */ - info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; - info.unique_id[sizeof(info.unique_id)-1] = '\0'; - if (info.valid & ACPI_VALID_HID) - hid = info.hardware_id; - if (info.valid & ACPI_VALID_UID) - uid = info.unique_id; - if (info.valid & ACPI_VALID_ADR) { - device->pnp.bus_address = info.address; + + info = buffer.pointer; + if (info->valid & ACPI_VALID_HID) + hid = info->hardware_id.value; + if (info->valid & ACPI_VALID_UID) + uid = info->unique_id.value; + if (info->valid & ACPI_VALID_CID) + cid_list = &info->compatibility_id; + if (info->valid & ACPI_VALID_ADR) { + device->pnp.bus_address = info->address; device->flags.bus_address = 1; } break; @@ -586,6 +574,15 @@ sprintf(device->pnp.unique_id, "%s", uid); device->flags.unique_id = 1; } + if (cid_list) { + device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL); + if (device->pnp.cid_list) + memcpy(device->pnp.cid_list, cid_list, cid_list->size); + else + printk(KERN_ERR "Memory allocation error\n"); + } + + acpi_os_free(buffer.pointer); } int acpi_device_set_context(struct acpi_device * device, int type) @@ -781,8 +778,12 @@ end: if (!result) *child = device; - else + else { + if (device->pnp.cid_list) + kfree(device->pnp.cid_list); kfree(device); + } + return_VALUE(result); } diff -urN linux-2.5.69-bk16/drivers/acpi/tables/tbconvrt.c linux-2.5.69-bk17/drivers/acpi/tables/tbconvrt.c --- linux-2.5.69-bk16/drivers/acpi/tables/tbconvrt.c 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/tables/tbconvrt.c 2003-05-24 04:33:33.000000000 -0700 @@ -164,6 +164,36 @@ } +/****************************************************************************** + * + * FUNCTION: acpi_tb_init_generic_address + * + * PARAMETERS: new_gas_struct - GAS struct to be initialized + * register_bit_width - Width of this register + * Address - Address of the register + * + * RETURN: None + * + * DESCRIPTION: Initialize a GAS structure. + * + ******************************************************************************/ + +static void +acpi_tb_init_generic_address ( + struct acpi_generic_address *new_gas_struct, + u8 register_bit_width, + acpi_physical_address address) +{ + + ACPI_STORE_ADDRESS (new_gas_struct->address, address); + + new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; + new_gas_struct->register_bit_width = register_bit_width; + new_gas_struct->register_bit_offset = 0; + new_gas_struct->reserved = 0; +} + + /******************************************************************************* * * FUNCTION: acpi_tb_convert_fadt1 @@ -233,14 +263,34 @@ /* * Convert the V1.0 block addresses to V2.0 GAS structures */ - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1a_evt_blk, local_fadt->pm1_evt_len, local_fadt->V1_pm1a_evt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1b_evt_blk, local_fadt->pm1_evt_len, local_fadt->V1_pm1b_evt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1a_cnt_blk, local_fadt->pm1_cnt_len, local_fadt->V1_pm1a_cnt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1b_cnt_blk, local_fadt->pm1_cnt_len, local_fadt->V1_pm1b_cnt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm2_cnt_blk, local_fadt->pm2_cnt_len, local_fadt->V1_pm2_cnt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm_tmr_blk, local_fadt->pm_tm_len, local_fadt->V1_pm_tmr_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xgpe0_blk, 0, local_fadt->V1_gpe0_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xgpe1_blk, 0, local_fadt->V1_gpe1_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, local_fadt->pm1_evt_len, + (acpi_physical_address) local_fadt->V1_pm1a_evt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, local_fadt->pm1_evt_len, + (acpi_physical_address) local_fadt->V1_pm1b_evt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, local_fadt->pm1_cnt_len, + (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, local_fadt->pm1_cnt_len, + (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, local_fadt->pm2_cnt_len, + (acpi_physical_address) local_fadt->V1_pm2_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, local_fadt->pm_tm_len, + (acpi_physical_address) local_fadt->V1_pm_tmr_blk); + acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, 0, + (acpi_physical_address) local_fadt->V1_gpe0_blk); + acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, 0, + (acpi_physical_address) local_fadt->V1_gpe1_blk); + + /* Create separate GAS structs for the PM1 Enable registers */ + + acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable, + (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), + (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address + + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); + + acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable, + (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), + (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address + + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); } @@ -282,44 +332,58 @@ } if (!(local_fadt->xpm1a_evt_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1a_evt_blk, - local_fadt->pm1_evt_len, local_fadt->V1_pm1a_evt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, + local_fadt->pm1_evt_len, (acpi_physical_address) local_fadt->V1_pm1a_evt_blk); } if (!(local_fadt->xpm1b_evt_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1b_evt_blk, - local_fadt->pm1_evt_len, local_fadt->V1_pm1b_evt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, + local_fadt->pm1_evt_len, (acpi_physical_address) local_fadt->V1_pm1b_evt_blk); } if (!(local_fadt->xpm1a_cnt_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1a_cnt_blk, - local_fadt->pm1_cnt_len, local_fadt->V1_pm1a_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, + local_fadt->pm1_cnt_len, (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk); } if (!(local_fadt->xpm1b_cnt_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1b_cnt_blk, - local_fadt->pm1_cnt_len, local_fadt->V1_pm1b_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, + local_fadt->pm1_cnt_len, (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk); } if (!(local_fadt->xpm2_cnt_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm2_cnt_blk, - local_fadt->pm2_cnt_len, local_fadt->V1_pm2_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, + local_fadt->pm2_cnt_len, (acpi_physical_address) local_fadt->V1_pm2_cnt_blk); } if (!(local_fadt->xpm_tmr_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm_tmr_blk, - local_fadt->pm_tm_len, local_fadt->V1_pm_tmr_blk); + acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, + local_fadt->pm_tm_len, (acpi_physical_address) local_fadt->V1_pm_tmr_blk); } if (!(local_fadt->xgpe0_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xgpe0_blk, - 0, local_fadt->V1_gpe0_blk); + acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, + 0, (acpi_physical_address) local_fadt->V1_gpe0_blk); } if (!(local_fadt->xgpe1_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xgpe1_blk, - 0, local_fadt->V1_gpe1_blk); + acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, + 0, (acpi_physical_address) local_fadt->V1_gpe1_blk); } + + /* Create separate GAS structs for the PM1 Enable registers */ + + acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable, + (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), + (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address + + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); + acpi_gbl_xpm1a_enable.address_space_id = local_fadt->xpm1a_evt_blk.address_space_id; + + acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable, + (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), + (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address + + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); + acpi_gbl_xpm1b_enable.address_space_id = local_fadt->xpm1b_evt_blk.address_space_id; } @@ -396,7 +460,7 @@ /* Free the original table */ - table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_FADT]; + table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next; acpi_tb_delete_single_table (table_desc); /* Install the new table */ diff -urN linux-2.5.69-bk16/drivers/acpi/tables/tbget.c linux-2.5.69-bk17/drivers/acpi/tables/tbget.c --- linux-2.5.69-bk16/drivers/acpi/tables/tbget.c 2003-05-04 16:53:33.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/tables/tbget.c 2003-05-24 04:33:33.000000000 -0700 @@ -456,18 +456,18 @@ * instance is always in the list head. */ if (instance == 1) { - /* - * Just pluck the pointer out of the global table! - * Will be null if no table is present - */ - *table_ptr_loc = acpi_gbl_acpi_tables[table_type].pointer; + /* Get the first */ + + if (acpi_gbl_table_lists[table_type].next) { + *table_ptr_loc = acpi_gbl_table_lists[table_type].next->pointer; + } return_ACPI_STATUS (AE_OK); } /* * Check for instance out of range */ - if (instance > acpi_gbl_acpi_tables[table_type].count) { + if (instance > acpi_gbl_table_lists[table_type].count) { return_ACPI_STATUS (AE_NOT_EXIST); } @@ -478,7 +478,7 @@ * need to walk from the 2nd table until we reach the Instance * that the user is looking for and return its table pointer. */ - table_desc = acpi_gbl_acpi_tables[table_type].next; + table_desc = acpi_gbl_table_lists[table_type].next; for (i = 2; i < instance; i++) { table_desc = table_desc->next; } diff -urN linux-2.5.69-bk16/drivers/acpi/tables/tbgetall.c linux-2.5.69-bk17/drivers/acpi/tables/tbgetall.c --- linux-2.5.69-bk16/drivers/acpi/tables/tbgetall.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/tables/tbgetall.c 2003-05-24 04:33:33.000000000 -0700 @@ -307,7 +307,7 @@ /* Always delete the RSDP mapping, we are done with it */ - acpi_tb_delete_acpi_table (ACPI_TABLE_RSDP); + acpi_tb_delete_tables_by_type (ACPI_TABLE_RSDP); return_ACPI_STATUS (status); } diff -urN linux-2.5.69-bk16/drivers/acpi/tables/tbinstal.c linux-2.5.69-bk17/drivers/acpi/tables/tbinstal.c --- linux-2.5.69-bk16/drivers/acpi/tables/tbinstal.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/tables/tbinstal.c 2003-05-24 04:33:33.000000000 -0700 @@ -79,13 +79,13 @@ /* * Search for a signature match among the known table types */ - for (i = 0; i < NUM_ACPI_TABLES; i++) { - if (!(acpi_gbl_acpi_table_data[i].flags & search_type)) { + for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { + if (!(acpi_gbl_table_data[i].flags & search_type)) { continue; } - if (!ACPI_STRNCMP (signature, acpi_gbl_acpi_table_data[i].signature, - acpi_gbl_acpi_table_data[i].sig_length)) { + if (!ACPI_STRNCMP (signature, acpi_gbl_table_data[i].signature, + acpi_gbl_table_data[i].sig_length)) { /* Found a signature match, return index if requested */ if (table_info) { @@ -94,7 +94,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Table [%4.4s] is an ACPI table consumed by the core subsystem\n", - (char *) acpi_gbl_acpi_table_data[i].signature)); + (char *) acpi_gbl_table_data[i].signature)); return_ACPI_STATUS (AE_OK); } @@ -149,7 +149,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s located at %p\n", - acpi_gbl_acpi_table_data[table_info->type].name, table_info->pointer)); + acpi_gbl_table_data[table_info->type].name, table_info->pointer)); (void) acpi_ut_release_mutex (ACPI_MTX_TABLES); return_ACPI_STATUS (status); @@ -239,70 +239,58 @@ acpi_table_type table_type, struct acpi_table_desc *table_info) { - struct acpi_table_desc *list_head; + struct acpi_table_list *list_head; struct acpi_table_desc *table_desc; ACPI_FUNCTION_TRACE_U32 ("tb_init_table_descriptor", table_type); + + /* Allocate a descriptor for this table */ + + table_desc = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc)); + if (!table_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + /* * Install the table into the global data structure */ - list_head = &acpi_gbl_acpi_tables[table_type]; - table_desc = list_head; + list_head = &acpi_gbl_table_lists[table_type]; /* * Two major types of tables: 1) Only one instance is allowed. This * includes most ACPI tables such as the DSDT. 2) Multiple instances of * the table are allowed. This includes SSDT and PSDTs. */ - if (ACPI_IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags)) { + if (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags)) { /* * Only one table allowed, and a table has alread been installed * at this location, so return an error. */ - if (list_head->pointer) { + if (list_head->next) { return_ACPI_STATUS (AE_ALREADY_EXISTS); } - - table_desc->count = 1; - table_desc->prev = NULL; - table_desc->next = NULL; } - else { - /* - * Multiple tables allowed for this table type, we must link - * the new table in to the list of tables of this type. - */ - if (list_head->pointer) { - table_desc = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc)); - if (!table_desc) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - list_head->count++; - - /* Update the original previous */ - - list_head->prev->next = table_desc; - - /* Update new entry */ - table_desc->prev = list_head->prev; - table_desc->next = list_head; - - /* Update list head */ + /* + * Link the new table in to the list of tables of this type. + * Just insert at the start of the list, order unimportant. + * + * table_desc->Prev is already NULL from calloc() + */ + table_desc->next = list_head->next; + list_head->next = table_desc; - list_head->prev = table_desc; - } - else { - table_desc->count = 1; - } + if (table_desc->next) { + table_desc->next->prev = table_desc; } - /* Common initialization of the table descriptor */ + list_head->count++; - table_desc->type = table_info->type; + /* Finish initialization of the table descriptor */ + + table_desc->type = (u8) table_type; table_desc->pointer = table_info->pointer; table_desc->length = table_info->length; table_desc->allocation = table_info->allocation; @@ -316,8 +304,8 @@ * Set the appropriate global pointer (if there is one) to point to the * newly installed table */ - if (acpi_gbl_acpi_table_data[table_type].global_ptr) { - *(acpi_gbl_acpi_table_data[table_type].global_ptr) = table_info->pointer; + if (acpi_gbl_table_data[table_type].global_ptr) { + *(acpi_gbl_table_data[table_type].global_ptr) = table_info->pointer; } /* Return Data */ @@ -331,7 +319,7 @@ /******************************************************************************* * - * FUNCTION: acpi_tb_delete_acpi_tables + * FUNCTION: acpi_tb_delete_all_tables * * PARAMETERS: None. * @@ -342,7 +330,7 @@ ******************************************************************************/ void -acpi_tb_delete_acpi_tables (void) +acpi_tb_delete_all_tables (void) { acpi_table_type type; @@ -351,15 +339,15 @@ * Free memory allocated for ACPI tables * Memory can either be mapped or allocated */ - for (type = 0; type < NUM_ACPI_TABLES; type++) { - acpi_tb_delete_acpi_table (type); + for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) { + acpi_tb_delete_tables_by_type (type); } } /******************************************************************************* * - * FUNCTION: acpi_tb_delete_acpi_table + * FUNCTION: acpi_tb_delete_tables_by_type * * PARAMETERS: Type - The table type to be deleted * @@ -371,11 +359,15 @@ ******************************************************************************/ void -acpi_tb_delete_acpi_table ( +acpi_tb_delete_tables_by_type ( acpi_table_type type) { + struct acpi_table_desc *table_desc; + u32 count; + u32 i; - ACPI_FUNCTION_TRACE_U32 ("tb_delete_acpi_table", type); + + ACPI_FUNCTION_TRACE_U32 ("tb_delete_tables_by_type", type); if (type > ACPI_TABLE_MAX) { @@ -416,43 +408,10 @@ } /* Free the table */ - - acpi_tb_free_acpi_tables_of_type (&acpi_gbl_acpi_tables[type]); - - (void) acpi_ut_release_mutex (ACPI_MTX_TABLES); - return_VOID; -} - - -/******************************************************************************* - * - * FUNCTION: acpi_tb_free_acpi_tables_of_type - * - * PARAMETERS: table_info - A table info struct - * - * RETURN: None. - * - * DESCRIPTION: Free the memory associated with an internal ACPI table - * Table mutex should be locked. - * - ******************************************************************************/ - -void -acpi_tb_free_acpi_tables_of_type ( - struct acpi_table_desc *list_head) -{ - struct acpi_table_desc *table_desc; - u32 count; - u32 i; - - - ACPI_FUNCTION_TRACE_PTR ("tb_free_acpi_tables_of_type", list_head); - - /* Get the head of the list */ - table_desc = list_head; - count = list_head->count; + table_desc = acpi_gbl_table_lists[type].next; + count = acpi_gbl_table_lists[type].count; /* * Walk the entire list, deleting both the allocated tables @@ -462,6 +421,7 @@ table_desc = acpi_tb_uninstall_table (table_desc); } + (void) acpi_ut_release_mutex (ACPI_MTX_TABLES); return_VOID; } @@ -484,30 +444,31 @@ struct acpi_table_desc *table_desc) { - if (!table_desc) { + /* Must have a valid table descriptor and pointer */ + + if ((!table_desc) || + (!table_desc->pointer)) { return; } - if (table_desc->pointer) { - /* Valid table, determine type of memory allocation */ + /* Valid table, determine type of memory allocation */ - switch (table_desc->allocation) { - case ACPI_MEM_NOT_ALLOCATED: - break; + switch (table_desc->allocation) { + case ACPI_MEM_NOT_ALLOCATED: + break; - case ACPI_MEM_ALLOCATED: + case ACPI_MEM_ALLOCATED: - ACPI_MEM_FREE (table_desc->pointer); - break; + ACPI_MEM_FREE (table_desc->pointer); + break; - case ACPI_MEM_MAPPED: + case ACPI_MEM_MAPPED: - acpi_os_unmap_memory (table_desc->pointer, table_desc->length); - break; + acpi_os_unmap_memory (table_desc->pointer, table_desc->length); + break; - default: - break; - } + default: + break; } } @@ -533,18 +494,23 @@ struct acpi_table_desc *next_desc; - ACPI_FUNCTION_TRACE_PTR ("acpi_tb_uninstall_table", table_desc); + ACPI_FUNCTION_TRACE_PTR ("tb_uninstall_table", table_desc); if (!table_desc) { return_PTR (NULL); } - /* Unlink the descriptor */ + /* Unlink the descriptor from the doubly linked list */ if (table_desc->prev) { table_desc->prev->next = table_desc->next; } + else { + /* Is first on list, update list head */ + + acpi_gbl_table_lists[table_desc->type].next = table_desc->next; + } if (table_desc->next) { table_desc->next->prev = table_desc->prev; @@ -554,23 +520,12 @@ acpi_tb_delete_single_table (table_desc); - /* Free the table descriptor (Don't delete the list head, tho) */ - - if ((table_desc->prev) == (table_desc->next)) { - next_desc = NULL; + /* Free the table descriptor */ - /* Clear the list head */ + next_desc = table_desc->next; + ACPI_MEM_FREE (table_desc); - table_desc->pointer = NULL; - table_desc->length = 0; - table_desc->count = 0; - } - else { - /* Free the table descriptor */ - - next_desc = table_desc->next; - ACPI_MEM_FREE (table_desc); - } + /* Return pointer to the next descriptor */ return_PTR (next_desc); } diff -urN linux-2.5.69-bk16/drivers/acpi/tables/tbutils.c linux-2.5.69-bk17/drivers/acpi/tables/tbutils.c --- linux-2.5.69-bk16/drivers/acpi/tables/tbutils.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/tables/tbutils.c 2003-05-24 04:33:33.000000000 -0700 @@ -66,26 +66,25 @@ acpi_status acpi_tb_handle_to_object ( u16 table_id, - struct acpi_table_desc **table_desc) + struct acpi_table_desc **return_table_desc) { u32 i; - struct acpi_table_desc *list_head; + struct acpi_table_desc *table_desc; ACPI_FUNCTION_NAME ("tb_handle_to_object"); for (i = 0; i < ACPI_TABLE_MAX; i++) { - list_head = &acpi_gbl_acpi_tables[i]; - do { - if (list_head->table_id == table_id) { - *table_desc = list_head; + table_desc = acpi_gbl_table_lists[i].next; + while (table_desc) { + if (table_desc->table_id == table_id) { + *return_table_desc = table_desc; return (AE_OK); } - list_head = list_head->next; - - } while (list_head != &acpi_gbl_acpi_tables[i]); + table_desc = table_desc->next; + } } ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "table_id=%X does not exist\n", table_id)); diff -urN linux-2.5.69-bk16/drivers/acpi/tables/tbxface.c linux-2.5.69-bk17/drivers/acpi/tables/tbxface.c --- linux-2.5.69-bk16/drivers/acpi/tables/tbxface.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/tables/tbxface.c 2003-05-24 04:33:33.000000000 -0700 @@ -235,7 +235,7 @@ acpi_unload_table ( acpi_table_type table_type) { - struct acpi_table_desc *list_head; + struct acpi_table_desc *table_desc; ACPI_FUNCTION_TRACE ("acpi_unload_table"); @@ -250,22 +250,22 @@ /* Find all tables of the requested type */ - list_head = &acpi_gbl_acpi_tables[table_type]; - do { + table_desc = acpi_gbl_table_lists[table_type].next; + while (table_desc); { /* * Delete all namespace entries owned by this table. Note that these * entries can appear anywhere in the namespace by virtue of the AML * "Scope" operator. Thus, we need to track ownership by an ID, not * simply a position within the hierarchy */ - acpi_ns_delete_namespace_by_owner (list_head->table_id); + acpi_ns_delete_namespace_by_owner (table_desc->table_id); - /* Delete (or unmap) the actual table */ - - acpi_tb_delete_acpi_table (table_type); + table_desc = table_desc->next; + } - } while (list_head != &acpi_gbl_acpi_tables[table_type]); + /* Delete (or unmap) all tables of this type */ + acpi_tb_delete_tables_by_type (table_type); return_ACPI_STATUS (AE_OK); } @@ -313,7 +313,7 @@ /* Check the table type and instance */ if ((table_type > ACPI_TABLE_MAX) || - (ACPI_IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags) && + (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) && instance > 1)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } @@ -394,7 +394,7 @@ /* Check the table type and instance */ if ((table_type > ACPI_TABLE_MAX) || - (ACPI_IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags) && + (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) && instance > 1)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } diff -urN linux-2.5.69-bk16/drivers/acpi/toshiba_acpi.c linux-2.5.69-bk17/drivers/acpi/toshiba_acpi.c --- linux-2.5.69-bk16/drivers/acpi/toshiba_acpi.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/toshiba_acpi.c 2003-05-24 04:33:33.000000000 -0700 @@ -33,7 +33,7 @@ * */ -#define TOSHIBA_ACPI_VERSION "0.14" +#define TOSHIBA_ACPI_VERSION "0.15" #define PROC_INTERFACE_VERSION 1 #include @@ -172,9 +172,7 @@ for (i = 0; i < HCI_WORDS; ++i) { in_objs[i].type = ACPI_TYPE_INTEGER; in_objs[i].integer.value = in[i]; - /*printk("%04x ", in[i]);*/ } - /*printk("\n");*/ results.length = sizeof(out_objs); results.pointer = out_objs; @@ -184,9 +182,7 @@ if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) { for (i = 0; i < out_objs->package.count; ++i) { out[i] = out_objs->package.elements[i].integer.value; - /*printk("%04x ", out[i]);*/ } - /*printk("\n");*/ } return status; @@ -226,7 +222,7 @@ typedef struct _ProcItem { - char* name; + const char* name; char* (*read_func)(char*); unsigned long (*write_func)(const char*, unsigned long); } ProcItem; @@ -284,10 +280,8 @@ write_lcd(const char* buffer, unsigned long count) { int value; - /*int byte_count;*/ u32 hci_result; - /* ISSUE: %i doesn't work with hex values as advertised */ if (snscanf(buffer, count, " brightness : %i", &value) == 1 && value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { value = value << HCI_LCD_BRIGHTNESS_SHIFT; @@ -414,6 +408,11 @@ last_key_event = value; } else if (hci_result == HCI_EMPTY) { /* better luck next time */ + } else if (hci_result == HCI_NOT_SUPPORTED) { + /* This is a workaround for an unresolved issue on + * some machines where system events sporadically + * become disabled. */ + hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); } else { p += sprintf(p, "ERROR\n"); goto end; diff -urN linux-2.5.69-bk16/drivers/acpi/utilities/utcopy.c linux-2.5.69-bk17/drivers/acpi/utilities/utcopy.c --- linux-2.5.69-bk16/drivers/acpi/utilities/utcopy.c 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/utilities/utcopy.c 2003-05-24 04:33:33.000000000 -0700 @@ -651,13 +651,21 @@ */ if ((source_desc->buffer.pointer) && (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) { - dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length); - if (!dest_desc->buffer.pointer) { - return (AE_NO_MEMORY); - } + dest_desc->buffer.pointer = NULL; + + /* Create an actual buffer only if length > 0 */ - ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer, - source_desc->buffer.length); + if (source_desc->buffer.length) { + dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length); + if (!dest_desc->buffer.pointer) { + return (AE_NO_MEMORY); + } + + /* Copy the actual buffer data */ + + ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer, + source_desc->buffer.length); + } } break; diff -urN linux-2.5.69-bk16/drivers/acpi/utilities/utdelete.c linux-2.5.69-bk17/drivers/acpi/utilities/utdelete.c --- linux-2.5.69-bk16/drivers/acpi/utilities/utdelete.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/utilities/utdelete.c 2003-05-24 04:33:33.000000000 -0700 @@ -71,6 +71,7 @@ void *obj_pointer = NULL; union acpi_operand_object *handler_desc; union acpi_operand_object *second_desc; + union acpi_operand_object *next_desc; ACPI_FUNCTION_TRACE_PTR ("ut_delete_internal_obj", object); @@ -136,6 +137,15 @@ if (object->device.gpe_block) { (void) acpi_ev_delete_gpe_block (object->device.gpe_block); } + + /* Walk the handler list for this device */ + + handler_desc = object->device.address_space; + while (handler_desc) { + next_desc = handler_desc->address_space.next; + acpi_ut_remove_reference (handler_desc); + handler_desc = next_desc; + } break; @@ -183,10 +193,13 @@ * default handlers -- and therefore, we created the context object * locally, it was not created by an external caller. */ - handler_desc = object->region.addr_handler; - if ((handler_desc) && - (handler_desc->addr_handler.hflags == ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { - obj_pointer = second_desc->extra.region_context; + handler_desc = object->region.address_space; + if (handler_desc) { + if (handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { + obj_pointer = second_desc->extra.region_context; + } + + acpi_ut_remove_reference (handler_desc); } /* Now we can free the Extra object */ @@ -211,7 +224,6 @@ break; } - /* Free any allocated memory (pointer within the object) found above */ if (obj_pointer) { @@ -299,7 +311,7 @@ new_count = count; /* - * Reference count action (increment, decrement, or force delete) + * Perform the reference count action (increment, decrement, or force delete) */ switch (action) { @@ -402,8 +414,6 @@ { acpi_status status; u32 i; - union acpi_operand_object *next; - union acpi_operand_object *new; union acpi_generic_state *state_list = NULL; union acpi_generic_state *state; @@ -417,9 +427,8 @@ return_ACPI_STATUS (AE_OK); } - /* - * Make sure that this isn't a namespace handle - */ + /* Make sure that this isn't a namespace handle */ + if (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", object)); return_ACPI_STATUS (AE_OK); @@ -439,28 +448,8 @@ switch (ACPI_GET_OBJECT_TYPE (object)) { case ACPI_TYPE_DEVICE: - status = acpi_ut_create_update_state_and_push (object->device.addr_handler, - action, &state_list); - if (ACPI_FAILURE (status)) { - goto error_exit; - } - - acpi_ut_update_ref_count (object->device.sys_handler, action); - acpi_ut_update_ref_count (object->device.drv_handler, action); - break; - - - case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: - - /* Must walk list of address handlers */ - - next = object->addr_handler.next; - while (next) { - new = next->addr_handler.next; - acpi_ut_update_ref_count (next, action); - - next = new; - } + acpi_ut_update_ref_count (object->device.system_notify, action); + acpi_ut_update_ref_count (object->device.device_notify, action); break; @@ -590,16 +579,14 @@ ACPI_FUNCTION_TRACE_PTR ("ut_add_reference", object); - /* - * Ensure that we have a valid object - */ + /* Ensure that we have a valid object */ + if (!acpi_ut_valid_internal_object (object)) { return_VOID; } - /* - * We have a valid ACPI internal object, now increment the reference count - */ + /* Increment the reference count */ + (void) acpi_ut_update_object_reference (object, REF_INCREMENT); return_VOID; } @@ -624,6 +611,7 @@ ACPI_FUNCTION_TRACE_PTR ("ut_remove_reference", object); + /* * Allow a NULL pointer to be passed in, just ignore it. This saves * each caller from having to check. Also, ignore NS nodes. @@ -634,9 +622,8 @@ return_VOID; } - /* - * Ensure that we have a valid object - */ + /* Ensure that we have a valid object */ + if (!acpi_ut_valid_internal_object (object)) { return_VOID; } diff -urN linux-2.5.69-bk16/drivers/acpi/utilities/uteval.c linux-2.5.69-bk17/drivers/acpi/utilities/uteval.c --- linux-2.5.69-bk16/drivers/acpi/utilities/uteval.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/utilities/uteval.c 2003-05-24 04:33:33.000000000 -0700 @@ -210,6 +210,46 @@ /******************************************************************************* * + * FUNCTION: acpi_ut_copy_id_string + * + * PARAMETERS: Destination - Where to copy the string + * Source - Source string + * max_length - Length of the destination buffer + * + * RETURN: None + * + * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods. + * Performs removal of a leading asterisk if present -- workaround + * for a known issue on a bunch of machines. + * + ******************************************************************************/ + +static void +acpi_ut_copy_id_string ( + char *destination, + char *source, + acpi_size max_length) +{ + + + /* + * Workaround for ID strings that have a leading asterisk. This construct + * is not allowed by the ACPI specification (ID strings must be + * alphanumeric), but enough existing machines have this embedded in their + * ID strings that the following code is useful. + */ + if (*source == '*') { + source++; + } + + /* Do the actual copy */ + + ACPI_STRNCPY (destination, source, max_length); +} + + +/******************************************************************************* + * * FUNCTION: acpi_ut_execute_HID * * PARAMETERS: device_node - Node for the device @@ -245,12 +285,13 @@ if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { /* Convert the Numeric HID to string */ - acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->buffer); + acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->value); } else { /* Copy the String HID from the returned object */ - ACPI_STRNCPY (hid->buffer, obj_desc->string.pointer, sizeof(hid->buffer)); + acpi_ut_copy_id_string (hid->value, obj_desc->string.pointer, + sizeof (hid->value)); } /* On exit, we must delete the return object */ @@ -262,6 +303,57 @@ /******************************************************************************* * + * FUNCTION: acpi_ut_translate_one_cid + * + * PARAMETERS: obj_desc - _CID object, must be integer or string + * one_cid - Where the CID string is returned + * + * RETURN: Status + * + * DESCRIPTION: Return a numeric or string _CID value as a string. + * (Compatible ID) + * + * NOTE: Assumes a maximum _CID string length of + * ACPI_MAX_CID_LENGTH. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_translate_one_cid ( + union acpi_operand_object *obj_desc, + struct acpi_compatible_id *one_cid) +{ + + + switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { + case ACPI_TYPE_INTEGER: + + /* Convert the Numeric CID to string */ + + acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, one_cid->value); + return (AE_OK); + + case ACPI_TYPE_STRING: + + if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) { + return (AE_AML_STRING_LIMIT); + } + + /* Copy the String CID from the returned object */ + + acpi_ut_copy_id_string (one_cid->value, obj_desc->string.pointer, + ACPI_MAX_CID_LENGTH); + return (AE_OK); + + default: + + return (AE_TYPE); + } +} + + +/******************************************************************************* + * * FUNCTION: acpi_ut_execute_CID * * PARAMETERS: device_node - Node for the device @@ -279,55 +371,86 @@ acpi_status acpi_ut_execute_CID ( struct acpi_namespace_node *device_node, - struct acpi_device_id *cid) + struct acpi_compatible_id_list **return_cid_list) { union acpi_operand_object *obj_desc; acpi_status status; + u32 count; + u32 size; + struct acpi_compatible_id_list *cid_list; + acpi_native_uint i; ACPI_FUNCTION_TRACE ("ut_execute_CID"); + /* Evaluate the _CID method for this device */ + status = acpi_ut_evaluate_object (device_node, METHOD_NAME__CID, - ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE, &obj_desc); + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE, + &obj_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - /* - * A _CID can return either a single compatible ID or a package of compatible - * IDs. Each compatible ID can be a Number (32 bit compressed EISA ID) or - * string (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss"). - */ - switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { - case ACPI_TYPE_INTEGER: + /* Get the number of _CIDs returned */ - /* Convert the Numeric CID to string */ + count = 1; + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) { + count = obj_desc->package.count; + } - acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, cid->buffer); - break; + /* Allocate a worst-case buffer for the _CIDs */ - case ACPI_TYPE_STRING: + size = (((count - 1) * sizeof (struct acpi_compatible_id)) + + sizeof (struct acpi_compatible_id_list)); - /* Copy the String CID from the returned object */ + cid_list = ACPI_MEM_CALLOCATE ((acpi_size) size); + if (!cid_list) { + return_ACPI_STATUS (AE_NO_MEMORY); + } - ACPI_STRNCPY (cid->buffer, obj_desc->string.pointer, sizeof (cid->buffer)); - break; + /* Init CID list */ - case ACPI_TYPE_PACKAGE: + cid_list->count = count; + cid_list->size = size; - /* TBD: Parse package elements; need different return struct, etc. */ + /* + * A _CID can return either a single compatible ID or a package of compatible + * IDs. Each compatible ID can be one of the following: + * -- Number (32 bit compressed EISA ID) or + * -- String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss"). + */ - status = AE_SUPPORT; - break; + /* The _CID object can be either a single CID or a package (list) of CIDs */ - default: + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) { + /* Translate each package element */ - status = AE_TYPE; - break; + for (i = 0; i < count; i++) { + status = acpi_ut_translate_one_cid (obj_desc->package.elements[i], + &cid_list->id[i]); + if (ACPI_FAILURE (status)) { + break; + } + } } + else { + /* Only one CID, translate to a string */ - /* On exit, we must delete the return object */ + status = acpi_ut_translate_one_cid (obj_desc, cid_list->id); + } + + /* Cleanup on error */ + + if (ACPI_FAILURE (status)) { + ACPI_MEM_FREE (cid_list); + } + else { + *return_cid_list = cid_list; + } + + /* On exit, we must delete the _CID return object */ acpi_ut_remove_reference (obj_desc); return_ACPI_STATUS (status); @@ -371,12 +494,13 @@ if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { /* Convert the Numeric UID to string */ - acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->buffer); + acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->value); } else { /* Copy the String UID from the returned object */ - ACPI_STRNCPY (uid->buffer, obj_desc->string.pointer, sizeof (uid->buffer)); + acpi_ut_copy_id_string (uid->value, obj_desc->string.pointer, + sizeof (uid->value)); } /* On exit, we must delete the return object */ diff -urN linux-2.5.69-bk16/drivers/acpi/utilities/utglobal.c linux-2.5.69-bk17/drivers/acpi/utilities/utglobal.c --- linux-2.5.69-bk16/drivers/acpi/utilities/utglobal.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/utilities/utglobal.c 2003-05-24 04:33:33.000000000 -0700 @@ -299,10 +299,10 @@ ******************************************************************************/ -struct acpi_table_desc acpi_gbl_acpi_tables[NUM_ACPI_TABLES]; +struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES]; -struct acpi_table_support acpi_gbl_acpi_table_data[NUM_ACPI_TABLES] = +struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] = { /*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */ @@ -535,12 +535,10 @@ #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) - /* * Strings and procedures used for debug only */ - /***************************************************************************** * * FUNCTION: acpi_ut_get_mutex_name @@ -558,7 +556,7 @@ u32 mutex_id) { - if (mutex_id > MAX_MTX) + if (mutex_id > MAX_MUTEX) { return ("Invalid Mutex ID"); } @@ -566,7 +564,6 @@ return (acpi_gbl_mutex_names[mutex_id]); } - #endif @@ -630,9 +627,12 @@ owner_id = acpi_gbl_next_table_owner_id; acpi_gbl_next_table_owner_id++; + /* Check for wraparound */ + if (acpi_gbl_next_table_owner_id == ACPI_FIRST_METHOD_ID) { acpi_gbl_next_table_owner_id = ACPI_FIRST_TABLE_ID; + ACPI_REPORT_WARNING (("Table owner ID wraparound\n")); } break; @@ -644,6 +644,8 @@ if (acpi_gbl_next_method_owner_id == ACPI_FIRST_TABLE_ID) { + /* Check for wraparound */ + acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID; } break; @@ -710,23 +712,19 @@ /* ACPI table structure */ - for (i = 0; i < NUM_ACPI_TABLES; i++) + for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { - acpi_gbl_acpi_tables[i].prev = &acpi_gbl_acpi_tables[i]; - acpi_gbl_acpi_tables[i].next = &acpi_gbl_acpi_tables[i]; - acpi_gbl_acpi_tables[i].pointer = NULL; - acpi_gbl_acpi_tables[i].length = 0; - acpi_gbl_acpi_tables[i].allocation = ACPI_MEM_NOT_ALLOCATED; - acpi_gbl_acpi_tables[i].count = 0; + acpi_gbl_table_lists[i].next = NULL; + acpi_gbl_table_lists[i].count = 0; } /* Mutex locked flags */ - for (i = 0; i < NUM_MTX; i++) + for (i = 0; i < NUM_MUTEX; i++) { - acpi_gbl_acpi_mutex_info[i].mutex = NULL; - acpi_gbl_acpi_mutex_info[i].owner_id = ACPI_MUTEX_NOT_ACQUIRED; - acpi_gbl_acpi_mutex_info[i].use_count = 0; + acpi_gbl_mutex_info[i].mutex = NULL; + acpi_gbl_mutex_info[i].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[i].use_count = 0; } /* GPE support */ @@ -737,8 +735,8 @@ /* Global notify handlers */ - acpi_gbl_sys_notify.handler = NULL; - acpi_gbl_drv_notify.handler = NULL; + acpi_gbl_system_notify.handler = NULL; + acpi_gbl_device_notify.handler = NULL; acpi_gbl_init_handler = NULL; /* Global "typed" ACPI table pointers */ diff -urN linux-2.5.69-bk16/drivers/acpi/utilities/utmisc.c linux-2.5.69-bk17/drivers/acpi/utilities/utmisc.c --- linux-2.5.69-bk16/drivers/acpi/utilities/utmisc.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/utilities/utmisc.c 2003-05-24 04:33:33.000000000 -0700 @@ -549,7 +549,7 @@ /* * Create each of the predefined mutex objects */ - for (i = 0; i < NUM_MTX; i++) { + for (i = 0; i < NUM_MUTEX; i++) { status = acpi_ut_create_mutex (i); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -588,7 +588,7 @@ /* * Delete each predefined mutex object */ - for (i = 0; i < NUM_MTX; i++) { + for (i = 0; i < NUM_MUTEX; i++) { (void) acpi_ut_delete_mutex (i); } @@ -619,15 +619,15 @@ ACPI_FUNCTION_TRACE_U32 ("ut_create_mutex", mutex_id); - if (mutex_id > MAX_MTX) { + if (mutex_id > MAX_MUTEX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - if (!acpi_gbl_acpi_mutex_info[mutex_id].mutex) { + if (!acpi_gbl_mutex_info[mutex_id].mutex) { status = acpi_os_create_semaphore (1, 1, - &acpi_gbl_acpi_mutex_info[mutex_id].mutex); - acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; - acpi_gbl_acpi_mutex_info[mutex_id].use_count = 0; + &acpi_gbl_mutex_info[mutex_id].mutex); + acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[mutex_id].use_count = 0; } return_ACPI_STATUS (status); @@ -656,14 +656,14 @@ ACPI_FUNCTION_TRACE_U32 ("ut_delete_mutex", mutex_id); - if (mutex_id > MAX_MTX) { + if (mutex_id > MAX_MUTEX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - status = acpi_os_delete_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex); + status = acpi_os_delete_semaphore (acpi_gbl_mutex_info[mutex_id].mutex); - acpi_gbl_acpi_mutex_info[mutex_id].mutex = NULL; - acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[mutex_id].mutex = NULL; + acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; return_ACPI_STATUS (status); } @@ -693,7 +693,7 @@ ACPI_FUNCTION_NAME ("ut_acquire_mutex"); - if (mutex_id > MAX_MTX) { + if (mutex_id > MAX_MUTEX) { return (AE_BAD_PARAMETER); } @@ -705,8 +705,8 @@ * the mutex ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ - for (i = mutex_id; i < MAX_MTX; i++) { - if (acpi_gbl_acpi_mutex_info[i].owner_id == this_thread_id) { + for (i = mutex_id; i < MAX_MUTEX; i++) { + if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { if (i == mutex_id) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Mutex [%s] already acquired by this thread [%X]\n", @@ -728,14 +728,14 @@ "Thread %X attempting to acquire Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); - status = acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, + status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1, ACPI_WAIT_FOREVER); if (ACPI_SUCCESS (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); - acpi_gbl_acpi_mutex_info[mutex_id].use_count++; - acpi_gbl_acpi_mutex_info[mutex_id].owner_id = this_thread_id; + acpi_gbl_mutex_info[mutex_id].use_count++; + acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id; } else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not acquire Mutex [%s] %s\n", @@ -776,14 +776,14 @@ "Thread %X releasing Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); - if (mutex_id > MAX_MTX) { + if (mutex_id > MAX_MUTEX) { return (AE_BAD_PARAMETER); } /* * Mutex must be acquired in order to release it! */ - if (acpi_gbl_acpi_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) { + if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Mutex [%s] is not acquired, cannot release\n", acpi_ut_get_mutex_name (mutex_id))); @@ -797,8 +797,8 @@ * ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ - for (i = mutex_id; i < MAX_MTX; i++) { - if (acpi_gbl_acpi_mutex_info[i].owner_id == this_thread_id) { + for (i = mutex_id; i < MAX_MUTEX; i++) { + if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { if (i == mutex_id) { continue; } @@ -813,9 +813,9 @@ /* Mark unlocked FIRST */ - acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; - status = acpi_os_signal_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, 1); + status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not release Mutex [%s] %s\n", diff -urN linux-2.5.69-bk16/drivers/acpi/utilities/utobject.c linux-2.5.69-bk17/drivers/acpi/utilities/utobject.c --- linux-2.5.69-bk16/drivers/acpi/utilities/utobject.c 2003-05-04 16:53:33.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/utilities/utobject.c 2003-05-24 04:33:33.000000000 -0700 @@ -149,7 +149,7 @@ acpi_size buffer_size) { union acpi_operand_object *buffer_desc; - u8 *buffer; + u8 *buffer = NULL; ACPI_FUNCTION_TRACE_U32 ("ut_create_buffer_object", buffer_size); @@ -163,14 +163,18 @@ return_PTR (NULL); } - /* Allocate the actual buffer */ + /* Create an actual buffer only if size > 0 */ - buffer = ACPI_MEM_CALLOCATE (buffer_size); - if (!buffer) { - ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n", - (u32) buffer_size)); - acpi_ut_remove_reference (buffer_desc); - return_PTR (NULL); + if (buffer_size > 0) { + /* Allocate the actual buffer */ + + buffer = ACPI_MEM_CALLOCATE (buffer_size); + if (!buffer) { + ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n", + (u32) buffer_size)); + acpi_ut_remove_reference (buffer_desc); + return_PTR (NULL); + } } /* Complete buffer object initialization */ diff -urN linux-2.5.69-bk16/drivers/acpi/utilities/utxface.c linux-2.5.69-bk17/drivers/acpi/utilities/utxface.c --- linux-2.5.69-bk16/drivers/acpi/utilities/utxface.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/drivers/acpi/utilities/utxface.c 2003-05-24 04:33:33.000000000 -0700 @@ -145,22 +145,8 @@ /* - * Install the default op_region handlers. These are installed unless - * other handlers have already been installed via the - * install_address_space_handler interface - */ - if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n")); - - status = acpi_ev_init_address_spaces (); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - } - - /* * We must initialize the hardware before we can enable ACPI. - * FADT values are validated here. + * The values from the FADT are validated here. */ if (!(flags & ACPI_NO_HARDWARE_INIT)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI hardware\n")); @@ -172,7 +158,7 @@ } /* - * Enable ACPI on this platform + * Enable ACPI mode */ if (!(flags & ACPI_NO_ACPI_ENABLE)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n")); @@ -187,8 +173,9 @@ } /* - * Note: - * We must have the hardware AND events initialized before we can execute + * Initialize ACPI Event handling + * + * NOTE: We must have the hardware AND events initialized before we can execute * ANY control methods SAFELY. Any control method can require ACPI hardware * support, so the hardware MUST be initialized before execution! */ @@ -201,7 +188,7 @@ } } - /* Install SCI handler, Global Lock handler, GPE handlers */ + /* Install the SCI handler, Global Lock handler, and GPE handlers */ if (!(flags & ACPI_NO_HANDLER_INIT)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL/GPE handlers\n")); @@ -237,14 +224,20 @@ ACPI_FUNCTION_TRACE ("acpi_initialize_objects"); + /* - * Initialize all device objects in the namespace - * This runs the _STA and _INI methods. + * Install the default op_region handlers. These are installed unless + * other handlers have already been installed via the + * install_address_space_handler interface. + * + * NOTE: This will cause _REG methods to be run. Any objects accessed + * by the _REG methods will be automatically initialized, even if they + * contain executable AML (see call to acpi_ns_initialize_objects below). */ - if (!(flags & ACPI_NO_DEVICE_INIT)) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Devices\n")); + if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n")); - status = acpi_ns_initialize_devices (); + status = acpi_ev_init_address_spaces (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -252,8 +245,8 @@ /* * Initialize the objects that remain uninitialized. This - * runs the executable AML that is part of the declaration of op_regions - * and Fields. + * runs the executable AML that may be part of the declaration of these + * objects: operation_regions, buffer_fields, Buffers, and Packages. */ if (!(flags & ACPI_NO_OBJECT_INIT)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Objects\n")); @@ -265,6 +258,19 @@ } /* + * Initialize all device objects in the namespace + * This runs the _STA and _INI methods. + */ + if (!(flags & ACPI_NO_DEVICE_INIT)) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Devices\n")); + + status = acpi_ns_initialize_devices (); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + + /* * Empty the caches (delete the cached objects) on the assumption that * the table load filled them up more than they will be at runtime -- * thus wasting non-paged memory. @@ -431,9 +437,9 @@ /* Current status of the ACPI tables, per table type */ - info_ptr->num_table_types = NUM_ACPI_TABLES; - for (i = 0; i < NUM_ACPI_TABLES; i++) { - info_ptr->table_info[i].count = acpi_gbl_acpi_tables[i].count; + info_ptr->num_table_types = NUM_ACPI_TABLE_TYPES; + for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { + info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count; } return_ACPI_STATUS (AE_OK); diff -urN linux-2.5.69-bk16/drivers/ide/ide-disk.c linux-2.5.69-bk17/drivers/ide/ide-disk.c --- linux-2.5.69-bk16/drivers/ide/ide-disk.c 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/ide-disk.c 2003-05-24 04:33:33.000000000 -0700 @@ -247,7 +247,7 @@ * * Returns 0 on success. * - * Note that we may be called from two contexts - the do_rw_disk context + * Note that we may be called from two contexts - __ide_do_rw_disk() context * and IRQ context. The IRQ can happen any time after we've output the * full "mcount" number of sectors, so we must make sure we update the * state _before_ we output the final part of the data! @@ -351,11 +351,11 @@ } /* - * do_rw_disk() issues READ and WRITE commands to a disk, + * __ide_do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. * It also takes care of issuing special DRIVE_CMDs. */ -static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) +ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) { ide_hwif_t *hwif = HWIF(drive); u8 lba48 = (drive->addressing == 1) ? 1 : 0; @@ -367,11 +367,6 @@ if (driver_blocked) panic("Request while ide driver is blocked?"); -#if defined(CONFIG_BLK_DEV_PDC4030) || defined(CONFIG_BLK_DEV_PDC4030_MODULE) - if (IS_PDC4030_DRIVE) - return promise_rw_disk(drive, rq, block); -#endif /* CONFIG_BLK_DEV_PDC4030 */ - if (drive->using_tcq && idedisk_start_tag(drive, rq)) { if (!ata_pending_commands(drive)) BUG(); @@ -550,10 +545,11 @@ } return ide_started; } - blk_dump_rq_flags(rq, "do_rw_disk - bad command"); + blk_dump_rq_flags(rq, "__ide_do_rw_disk - bad command"); ide_end_request(drive, 0, 0); return ide_stopped; } +EXPORT_SYMBOL_GPL(__ide_do_rw_disk); #else /* CONFIG_IDE_TASKFILE_IO */ @@ -562,15 +558,15 @@ static ide_startstop_t lba_48_rw_disk(ide_drive_t *, struct request *, unsigned long long); /* - * do_rw_disk() issues READ and WRITE commands to a disk, + * __ide_do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. * It also takes care of issuing special DRIVE_CMDs. */ -static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) +ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) { BUG_ON(drive->blocked); if (!blk_fs_request(rq)) { - blk_dump_rq_flags(rq, "do_rw_disk - bad command"); + blk_dump_rq_flags(rq, "__ide_do_rw_disk - bad command"); ide_end_request(drive, 0, 0); return ide_stopped; } @@ -581,11 +577,6 @@ * need to add split taskfile operations based on 28bit threshold. */ -#if defined(CONFIG_BLK_DEV_PDC4030) || defined(CONFIG_BLK_DEV_PDC4030_MODULE) - if (IS_PDC4030_DRIVE) - return promise_rw_disk(drive, rq, block); -#endif /* CONFIG_BLK_DEV_PDC4030 */ - if (drive->using_tcq && idedisk_start_tag(drive, rq)) { if (!ata_pending_commands(drive)) BUG(); @@ -601,6 +592,7 @@ /* 28-bit CHS : DIE DIE DIE piece of legacy crap!!! */ return chs_rw_disk(drive, rq, (unsigned long) block); } +EXPORT_SYMBOL_GPL(__ide_do_rw_disk); static task_ioreg_t get_command (ide_drive_t *drive, int cmd) { @@ -760,6 +752,16 @@ #endif /* CONFIG_IDE_TASKFILE_IO */ +static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) +{ + ide_hwif_t *hwif = HWIF(drive); + + if (hwif->rw_disk) + return hwif->rw_disk(drive, rq, block); + else + return __ide_do_rw_disk(drive, rq, block); +} + static int do_idedisk_flushcache(ide_drive_t *drive); static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat) @@ -1541,11 +1543,6 @@ struct hd_driveid *id = drive->id; unsigned long capacity; -#if 0 - if (IS_PDC4030_DRIVE) - DRIVER(drive)->do_request = promise_rw_disk; -#endif - idedisk_add_settings(drive); if (drive->id_read == 0) @@ -1674,7 +1671,7 @@ .supports_dsc_overlap = 0, .cleanup = idedisk_cleanup, .flushcache = do_idedisk_flushcache, - .do_request = do_rw_disk, + .do_request = ide_do_rw_disk, .sense = idedisk_dump_status, .error = idedisk_error, .abort = idedisk_abort, diff -urN linux-2.5.69-bk16/drivers/ide/ide.c linux-2.5.69-bk17/drivers/ide/ide.c --- linux-2.5.69-bk16/drivers/ide/ide.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/ide.c 2003-05-24 04:33:33.000000000 -0700 @@ -913,6 +913,8 @@ } for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; + if (hwif->hold) + continue; if ((!hwif->present && !hwif->mate && !initializing) || (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing)) goto found; @@ -924,6 +926,8 @@ found: if (hwif->present) ide_unregister(index); + else if (!hwif->hold) + init_hwif_data(index); if (hwif->present) return -1; memcpy(&hwif->hw, hw, sizeof(*hw)); diff -urN linux-2.5.69-bk16/drivers/ide/legacy/ali14xx.c linux-2.5.69-bk17/drivers/ide/legacy/ali14xx.c --- linux-2.5.69-bk16/drivers/ide/legacy/ali14xx.c 2003-05-04 16:53:06.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/legacy/ali14xx.c 2003-05-24 04:33:33.000000000 -0700 @@ -54,13 +54,7 @@ #include -#ifdef CONFIG_BLK_DEV_ALI14XX_MODULE -# define _IDE_C -# include "ide_modes.h" -# undef _IDE_C -#else -# include "ide_modes.h" -#endif /* CONFIG_BLK_DEV_ALI14XX_MODULE */ +#include "ide_modes.h" /* port addresses for auto-detection */ #define ALI_NUM_PORTS 4 diff -urN linux-2.5.69-bk16/drivers/ide/legacy/dtc2278.c linux-2.5.69-bk17/drivers/ide/legacy/dtc2278.c --- linux-2.5.69-bk16/drivers/ide/legacy/dtc2278.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/legacy/dtc2278.c 2003-05-24 04:33:33.000000000 -0700 @@ -21,13 +21,7 @@ #include -#ifdef CONFIG_BLK_DEV_DTC2278_MODULE -# define _IDE_C -# include "ide_modes.h" -# undef _IDE_C -#else -# include "ide_modes.h" -#endif /* CONFIG_BLK_DEV_DTC2278_MODULE */ +#include "ide_modes.h" /* * Changing this #undef to #define may solve start up problems in some systems. diff -urN linux-2.5.69-bk16/drivers/ide/legacy/ht6560b.c linux-2.5.69-bk17/drivers/ide/legacy/ht6560b.c --- linux-2.5.69-bk16/drivers/ide/legacy/ht6560b.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/legacy/ht6560b.c 2003-05-24 04:33:33.000000000 -0700 @@ -53,13 +53,7 @@ #include -#ifdef CONFIG_BLK_DEV_HT6560B_MODULE -# define _IDE_C -# include "ide_modes.h" -# undef _IDE_C -#else -# include "ide_modes.h" -#endif /* CONFIG_BLK_DEV_HT6560B_MODULE */ +#include "ide_modes.h" /* #define DEBUG */ /* remove comments for DEBUG messages */ diff -urN linux-2.5.69-bk16/drivers/ide/legacy/pdc4030.c linux-2.5.69-bk17/drivers/ide/legacy/pdc4030.c --- linux-2.5.69-bk16/drivers/ide/legacy/pdc4030.c 2003-05-04 16:53:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/legacy/pdc4030.c 2003-05-24 04:33:33.000000000 -0700 @@ -94,6 +94,8 @@ #include "pdc4030.h" +static ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block); + /* * promise_selectproc() is invoked by ide.c * in preparation for access to the specified drive. @@ -231,6 +233,10 @@ /* DC4030 hosted drives need their own identify... */ hwif->identify = hwif2->identify = &pdc4030_identify; + /* Override the normal ide disk read/write. */ + hwif->rw_disk = promise_rw_disk; + hwif2->rw_disk = promise_rw_disk; + /* Shift the remaining interfaces up by one */ for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) { ide_hwif_t *h = &ide_hwifs[i]; @@ -803,7 +809,7 @@ } } -ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) +static ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { /* The four drives on the two logical (one physical) interfaces are distinguished by writing the drive number (0-3) to the diff -urN linux-2.5.69-bk16/drivers/ide/legacy/qd65xx.c linux-2.5.69-bk17/drivers/ide/legacy/qd65xx.c --- linux-2.5.69-bk16/drivers/ide/legacy/qd65xx.c 2003-05-04 16:53:03.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/legacy/qd65xx.c 2003-05-24 04:33:33.000000000 -0700 @@ -42,14 +42,7 @@ #include #include -#ifdef CONFIG_BLK_DEV_QD65XX_MODULE -# define _IDE_C -# include "ide_modes.h" -# undef _IDE_C -#else -# include "ide_modes.h" -#endif /* CONFIG_BLK_DEV_QD65XX_MODULE */ - +#include "ide_modes.h" #include "qd65xx.h" /* diff -urN linux-2.5.69-bk16/drivers/ide/legacy/umc8672.c linux-2.5.69-bk17/drivers/ide/legacy/umc8672.c --- linux-2.5.69-bk16/drivers/ide/legacy/umc8672.c 2003-05-04 16:53:03.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/legacy/umc8672.c 2003-05-24 04:33:33.000000000 -0700 @@ -54,13 +54,7 @@ #include -#ifdef CONFIG_BLK_DEV_UMC8672_MODULE -# define _IDE_C -# include "ide_modes.h" -# undef _IDE_C -#else -# include "ide_modes.h" -#endif /* CONFIG_BLK_DEV_UMC8672_MODULE */ +#include "ide_modes.h" /* * Default speeds. These can be changed with "auto-tune" and/or hdparm. diff -urN linux-2.5.69-bk16/drivers/ide/pci/amd74xx.c linux-2.5.69-bk17/drivers/ide/pci/amd74xx.c --- linux-2.5.69-bk16/drivers/ide/pci/amd74xx.c 2003-05-04 16:53:57.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/pci/amd74xx.c 2003-05-24 04:33:33.000000000 -0700 @@ -313,7 +313,8 @@ case AMD_UDMA_100: pci_read_config_byte(dev, AMD_CABLE_DETECT, &t); - amd_80w = ((u & 0x3) ? 1 : 0) | ((u & 0xc) ? 2 : 0); + pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); + amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0); for (i = 24; i >= 0; i -= 8) if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) { printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits correctly. Enabling workaround.\n"); @@ -383,11 +384,6 @@ return 0; } -static unsigned int __init ata66_amd74xx(ide_hwif_t *hwif) -{ - return ((amd_enabled & amd_80w) >> hwif->channel) & 1; -} - static void __init init_hwif_amd74xx(ide_hwif_t *hwif) { int i; diff -urN linux-2.5.69-bk16/drivers/ide/pci/amd74xx.h linux-2.5.69-bk17/drivers/ide/pci/amd74xx.h --- linux-2.5.69-bk16/drivers/ide/pci/amd74xx.h 2003-05-04 16:53:00.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/pci/amd74xx.h 2003-05-24 04:33:33.000000000 -0700 @@ -40,7 +40,7 @@ .init_dma = init_dma_amd74xx, .channels = 2, .autodma = AUTODMA, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, .bootable = ON_BOARD, .extra = 0 },{ /* 1 */ @@ -53,7 +53,7 @@ .init_dma = init_dma_amd74xx, .channels = 2, .autodma = AUTODMA, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, .bootable = ON_BOARD, .extra = 0 },{ /* 2 */ @@ -66,7 +66,7 @@ .init_dma = init_dma_amd74xx, .channels = 2, .autodma = AUTODMA, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, .bootable = ON_BOARD, .extra = 0 },{ /* 3 */ @@ -79,7 +79,7 @@ .init_dma = init_dma_amd74xx, .channels = 2, .autodma = AUTODMA, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, .bootable = ON_BOARD, .extra = 0 },{ /* 4 */ @@ -92,7 +92,7 @@ .init_dma = init_dma_amd74xx, .autodma = AUTODMA, .channels = 2, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, .bootable = ON_BOARD, .extra = 0 }, @@ -106,7 +106,7 @@ .init_dma = init_dma_amd74xx, .channels = 2, .autodma = AUTODMA, - .enablebits = {{0x50,0x01,0x01}, {0x50,0x02,0x02}}, + .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, .bootable = ON_BOARD, .extra = 0, }, @@ -120,7 +120,7 @@ .init_dma = init_dma_amd74xx, .channels = 2, .autodma = AUTODMA, - .enablebits = {{0x50,0x01,0x01}, {0x50,0x02,0x02}}, + .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, .bootable = ON_BOARD, .extra = 0, }, diff -urN linux-2.5.69-bk16/drivers/ide/pci/piix.c linux-2.5.69-bk17/drivers/ide/pci/piix.c --- linux-2.5.69-bk16/drivers/ide/pci/piix.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/pci/piix.c 2003-05-24 04:33:33.000000000 -0700 @@ -142,6 +142,9 @@ p += sprintf(p, "\nController: %d\n", i); p += sprintf(p, "\n Intel "); switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801EB_1: + p += sprintf(p, "PIIX4 SATA 150 "); + break; case PCI_DEVICE_ID_INTEL_82801BA_8: case PCI_DEVICE_ID_INTEL_82801BA_9: case PCI_DEVICE_ID_INTEL_82801CA_10: @@ -275,6 +278,9 @@ u8 mode; switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801EB_1: + mode = 3; + break; /* UDMA 100 capable */ case PCI_DEVICE_ID_INTEL_82801BA_8: case PCI_DEVICE_ID_INTEL_82801BA_9: @@ -325,6 +331,7 @@ static u8 piix_dma_2_pio (u8 xfer_rate) { switch(xfer_rate) { + case XFER_UDMA_6: case XFER_UDMA_5: case XFER_UDMA_4: case XFER_UDMA_3: @@ -603,6 +610,7 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name) { switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801EB_1: case PCI_DEVICE_ID_INTEL_82801AA_1: case PCI_DEVICE_ID_INTEL_82801AB_1: case PCI_DEVICE_ID_INTEL_82801BA_8: @@ -803,6 +811,7 @@ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18}, { 0, }, }; diff -urN linux-2.5.69-bk16/drivers/ide/pci/piix.h linux-2.5.69-bk17/drivers/ide/pci/piix.h --- linux-2.5.69-bk16/drivers/ide/pci/piix.h 2003-05-04 16:53:07.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/pci/piix.h 2003-05-24 04:33:33.000000000 -0700 @@ -291,10 +291,10 @@ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, .bootable = ON_BOARD, .extra = 0, - },{ /* 17 */ + },{ /* 18 */ .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801DB_10, - .name = "ICH4", + .device = PCI_DEVICE_ID_INTEL_82801EB_1, + .name = "ICH5-SATA", .init_setup = init_setup_piix, .init_chipset = init_chipset_piix, .init_iops = NULL, diff -urN linux-2.5.69-bk16/drivers/ide/pci/serverworks.c linux-2.5.69-bk17/drivers/ide/pci/serverworks.c --- linux-2.5.69-bk16/drivers/ide/pci/serverworks.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/pci/serverworks.c 2003-05-24 04:33:33.000000000 -0700 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/serverworks.c Version 0.7 10 Sept 2002 + * linux/drivers/ide/pci/serverworks.c Version 0.8 25 Ebr 2003 * * Copyright (C) 1998-2000 Michel Aubry * Copyright (C) 1998-2000 Andrzej Krzysztofowicz @@ -203,11 +203,22 @@ } #endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + while (*list) + if (!strcmp(*list++, drive->id->model)) + return 1; + return 0; +} + static u8 svwks_ratemask (ide_drive_t *drive) { struct pci_dev *dev = HWIF(drive)->pci_dev; u8 mode; + if (!svwks_revision) + pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); + if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { u32 reg = 0; if (isa_dev) @@ -225,9 +236,13 @@ } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) { u8 btr = 0; pci_read_config_byte(dev, 0x5A, &btr); - mode = btr; + mode = btr & 0x3; if (!eighty_ninty_three(drive)) mode = min(mode, (u8)1); + /* If someone decides to do UDMA133 on CSB5 the same + issue will bite so be inclusive */ + if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100)) + mode = 2; } if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && @@ -419,13 +434,10 @@ static void svwks_tune_drive (ide_drive_t *drive, u8 pio) { - /* Tune to desired value or to "best". We must not adjust - "best" when we adjust from pio numbers to rate values! */ - - if(pio != 255) - (void) svwks_tune_chipset(drive, (XFER_PIO_0 + pio)); - else + if(pio == 255) (void) svwks_tune_chipset(drive, 255); + else + (void) svwks_tune_chipset(drive, (XFER_PIO_0 + pio)); } static int config_chipset_for_dma (ide_drive_t *drive) @@ -446,7 +458,7 @@ drive->init_speed = 0; - if (id && (id->capability & 1) && drive->autodma) { + if ((id->capability & 1) && drive->autodma) { /* Consult the list of known "bad" drives */ if (hwif->ide_dma_bad_drive(drive)) goto fast_ata_pio; @@ -483,28 +495,10 @@ return hwif->ide_dma_on(drive); } +/* This can go soon */ + static int svwks_ide_dma_end (ide_drive_t *drive) { - /* - * We never place the OSB4 into a UDMA mode with a disk - * medium, that means the UDMA "all my data is 4 byte shifted" - * problem cannot occur. - */ -#if 0 - ide_hwif_t *hwif = HWIF(drive); - u8 dma_stat = hwif->INB(hwif->dma_status); - - if ((dma_stat & 1) && drive->media == ide_disk) - { - printk(KERN_CRIT "Serverworks OSB4 in impossible state.\n"); - printk(KERN_CRIT "Disable UDMA or if you are using Seagate then try switching disk types\n"); - printk(KERN_CRIT "on this controller. Please report this event to osb4-bug@ide.cabal.tm\n"); - /* Panic might sys_sync -> death by corrupt disk */ - printk(KERN_CRIT "OSB4: continuing might cause disk corruption.\n"); - while(1) - cpu_relax(); - } -#endif return __ide_dma_end(drive); } @@ -630,8 +624,6 @@ static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif) { -// struct pci_dev *dev = hwif->pci_dev; -// return 0; return 1; } diff -urN linux-2.5.69-bk16/drivers/ide/pci/serverworks.h linux-2.5.69-bk17/drivers/ide/pci/serverworks.h --- linux-2.5.69-bk16/drivers/ide/pci/serverworks.h 2003-05-04 16:53:12.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/pci/serverworks.h 2003-05-24 04:33:33.000000000 -0700 @@ -11,6 +11,16 @@ #define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ #define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ +/* Seagate Barracuda ATA IV Family drives in UDMA mode 5 + * can overrun their FIFOs when used with the CSB5 */ +const char *svwks_bad_ata100[] = { + "ST320011A", + "ST340016A", + "ST360021A", + "ST380021A", + NULL +}; + #define DISPLAY_SVWKS_TIMINGS 1 #if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) diff -urN linux-2.5.69-bk16/drivers/ide/pci/sis5513.c linux-2.5.69-bk17/drivers/ide/pci/sis5513.c --- linux-2.5.69-bk16/drivers/ide/pci/sis5513.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/pci/sis5513.c 2003-05-24 04:33:33.000000000 -0700 @@ -161,9 +161,10 @@ { "SiS748", PCI_DEVICE_ID_SI_748, ATA_133, 0 }, { "SiS746", PCI_DEVICE_ID_SI_746, ATA_133, 0 }, { "SiS745", PCI_DEVICE_ID_SI_745, ATA_133, 0 }, - { "SiS740", PCI_DEVICE_ID_SI_740, ATA_100, 0 }, + { "SiS740", PCI_DEVICE_ID_SI_740, ATA_133, 0 }, { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100, SIS5513_LATENCY }, { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a, SIS5513_LATENCY }, + { "SiS655", PCI_DEVICE_ID_SI_655, ATA_133, 0 }, { "SiS652", PCI_DEVICE_ID_SI_652, ATA_133, 0 }, { "SiS651", PCI_DEVICE_ID_SI_651, ATA_133, 0 }, { "SiS650", PCI_DEVICE_ID_SI_650, ATA_133, 0 }, @@ -257,8 +258,8 @@ static char* chipset_capability[] = { "ATA", "ATA 16", "ATA 33", "ATA 66", - "ATA 100", "ATA 100", - "ATA 133", "ATA 133" + "ATA 100 (1st gen)", "ATA 100 (2nd gen)", + "ATA 133 (1st gen)", "ATA 133 (2nd gen)" }; #if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) @@ -331,8 +332,8 @@ // Configuration space remapped to 0x70 drive_pci = 0x70; } - pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+8*pos, ®dw0); - pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+8*pos+4, ®dw1); + pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+4*pos, ®dw0); + pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+4*pos+8, ®dw1); p += sprintf(p, "Drive %d:\n", pos); } @@ -357,8 +358,7 @@ case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; case ATA_100: case ATA_133a: p += sprintf(p, cycle_time[reg01 & 0x0F]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; + default: p += sprintf(p, "?"); break; } p += sprintf(p, " \t UDMA Cycle Time "); switch(chipset_family) { @@ -367,42 +367,39 @@ case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; case ATA_100: case ATA_133a: p += sprintf(p, cycle_time[reg11 & 0x0F]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; + default: p += sprintf(p, "?"); break; } p += sprintf(p, "\n"); } + if (chipset_family < ATA_133) { /* else case TODO */ /* Data Active */ - p += sprintf(p, " Data Active Time "); - switch(chipset_family) { - case ATA_00: - case ATA_16: /* confirmed */ - case ATA_33: - case ATA_66: - case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break; - case ATA_100: - case ATA_133a: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; - } - p += sprintf(p, " \t Data Active Time "); - switch(chipset_family) { - case ATA_00: - case ATA_16: - case ATA_33: - case ATA_66: - case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break; - case ATA_100: - case ATA_133a: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; - } - p += sprintf(p, "\n"); + p += sprintf(p, " Data Active Time "); + switch(chipset_family) { + case ATA_00: + case ATA_16: /* confirmed */ + case ATA_33: + case ATA_66: + case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break; + default: p += sprintf(p, "?"); break; + } + p += sprintf(p, " \t Data Active Time "); + switch(chipset_family) { + case ATA_00: + case ATA_16: + case ATA_33: + case ATA_66: + case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break; + default: p += sprintf(p, "?"); break; + } + p += sprintf(p, "\n"); /* Data Recovery */ /* warning: may need (reg&0x07) for pre ATA66 chips */ - if (chipset_family < ATA_133) { p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]); } @@ -430,7 +427,6 @@ p += sprintf(p, "\nSiS 5513 "); switch(chipset_family) { - case ATA_00: p += sprintf(p, "Unknown???"); break; case ATA_16: p += sprintf(p, "DMA 16"); break; case ATA_33: p += sprintf(p, "Ultra 33"); break; case ATA_66: p += sprintf(p, "Ultra 66"); break; @@ -867,6 +863,19 @@ return sis5513_config_drive_xfer_rate(drive); } +/* Helper function used at init time + * returns a PCI device revision ID + * (used to detect different IDE controller versions) + */ +static u8 __init devfn_rev(int device, int function) +{ + u8 revision; + /* Find device */ + struct pci_dev* dev = pci_find_slot(0,PCI_DEVFN(device,function)); + pci_read_config_byte(dev, PCI_REVISION_ID, &revision); + return revision; +} + /* Chip detection and general config */ static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char *name) { @@ -887,26 +896,24 @@ /* check 100/133 chipset family */ if (chipset_family == ATA_133) { u32 reg54h; - u16 reg02h; + u16 devid; pci_read_config_dword(dev, 0x54, ®54h); + /* SiS962 and above report 0x5518 dev id if high bit is cleared */ pci_write_config_dword(dev, 0x54, (reg54h & 0x7fffffff)); - pci_read_config_word(dev, 0x02, ®02h); + pci_read_config_word(dev, 0x02, &devid); + /* restore register 0x54 */ pci_write_config_dword(dev, 0x54, reg54h); + /* devid 5518 here means SiS962 or later - which supports ATA133 */ - if (reg02h != 0x5518) { + which supports ATA133. + These are refered by chipset_family = ATA133 + */ + if (devid != 0x5518) { u8 reg49h; - unsigned long sbrev; /* SiS961 family */ - - /* - * FIXME !!! GAK!!!!!!!!!! PCI DIRECT POKING - */ - outl(0x80001008, 0x0cf8); - sbrev = inl(0x0cfc); - pci_read_config_byte(dev, 0x49, ®49h); - if (((sbrev & 0xff) == 0x10) && (reg49h & 0x80)) + /* check isa bridge device rev id */ + if (((devfn_rev(2,0) & 0xff) == 0x10) && (reg49h & 0x80)) chipset_family = ATA_133a; else chipset_family = ATA_100; @@ -924,6 +931,14 @@ u8 latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */ pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); } + + /* Special case for SiS630 : 630S/ET is ATA_100a */ + if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) { + /* check host device rev id */ + if (devfn_rev(0,0) >= 0x30) { + chipset_family = ATA_100a; + } + } } /* Make general config ops here diff -urN linux-2.5.69-bk16/drivers/ide/pci/via82cxxx.c linux-2.5.69-bk17/drivers/ide/pci/via82cxxx.c --- linux-2.5.69-bk16/drivers/ide/pci/via82cxxx.c 2003-05-04 16:52:48.000000000 -0700 +++ linux-2.5.69-bk17/drivers/ide/pci/via82cxxx.c 2003-05-24 04:33:33.000000000 -0700 @@ -1,12 +1,12 @@ /* * - * Version 3.36 + * Version 3.37 * * VIA IDE driver for Linux. Supported southbridges: * * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, - * vt8235 + * vt8235, vt8237 * * Copyright (c) 2000-2002 Vojtech Pavlik * @@ -74,9 +74,7 @@ u8 rev_max; u16 flags; } via_isa_bridges[] = { -#ifdef FUTURE_BRIDGES - { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 }, -#endif + { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, @@ -148,7 +146,7 @@ via_print("----------VIA BusMastering IDE Configuration" "----------------"); - via_print("Driver Version: 3.36"); + via_print("Driver Version: 3.37"); via_print("South Bridge: VIA %s", via_config->name); diff -urN linux-2.5.69-bk16/drivers/pci/quirks.c linux-2.5.69-bk17/drivers/pci/quirks.c --- linux-2.5.69-bk16/drivers/pci/quirks.c 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/pci/quirks.c 2003-05-24 04:33:34.000000000 -0700 @@ -635,7 +635,22 @@ if(pdev->devfn == 0) interrupt_line_quirk = 1; } - + +/* + * Serverworks CSB5 IDE does not fully support native mode + */ +static void __init quirk_svwks_csb5ide(struct pci_dev *pdev) +{ + u8 prog; + pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog); + if (prog & 5) { + prog &= ~5; + pdev->class &= ~5; + pci_write_config_byte(pdev, PCI_CLASS_PROG, prog); + /* need to re-assign BARs for compat mode */ + quirk_ide_bases(pdev); + } +} /* This was originally an Alpha specific thing, but it really fits here. * The i82375 PCI/EISA bridge appears as non-classified. Fix that. @@ -812,7 +827,9 @@ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master }, - + + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge }, /* diff -urN linux-2.5.69-bk16/drivers/usb/core/message.c linux-2.5.69-bk17/drivers/usb/core/message.c --- linux-2.5.69-bk16/drivers/usb/core/message.c 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/usb/core/message.c 2003-05-24 04:33:34.000000000 -0700 @@ -672,6 +672,7 @@ { int i, b; + /* NOTE: affects all endpoints _except_ ep0 */ for (i=0; iactconfig->desc.bNumInterfaces; i++) { struct usb_interface *ifp = dev->actconfig->interface + i; struct usb_host_interface *as = ifp->altsetting + ifp->act_altsetting; @@ -862,6 +863,7 @@ usb_settoggle (dev, ep, out, 0); (out ? dev->epmaxpacketout : dev->epmaxpacketin) [ep] = iface_as->endpoint [i].desc.wMaxPacketSize; + usb_endpoint_running (dev, ep, out); } return 0; @@ -916,7 +918,7 @@ /* if it's already configured, clear out old state first. */ if (dev->state != USB_STATE_ADDRESS && disable) { - for (i = 0; i < 15; i++) { + for (i = 1 /* skip ep0 */; i < 15; i++) { disable (dev, i); disable (dev, USB_DIR_IN | i); } diff -urN linux-2.5.69-bk16/drivers/usb/gadget/ether.c linux-2.5.69-bk17/drivers/usb/gadget/ether.c --- linux-2.5.69-bk16/drivers/usb/gadget/ether.c 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/usb/gadget/ether.c 2003-05-24 04:33:34.000000000 -0700 @@ -1107,7 +1107,7 @@ } /* respond with data transfer before status phase? */ - if (value > 0) { + if (value >= 0) { req->length = value; value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); if (value < 0) { diff -urN linux-2.5.69-bk16/drivers/usb/gadget/net2280.c linux-2.5.69-bk17/drivers/usb/gadget/net2280.c --- linux-2.5.69-bk16/drivers/usb/gadget/net2280.c 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/usb/gadget/net2280.c 2003-05-24 04:33:34.000000000 -0700 @@ -393,7 +393,7 @@ struct net2280_request *req; ep = container_of (_ep, struct net2280_ep, ep); - if (!ep || !_req) + if (!_ep || !_req) return; req = container_of (_req, struct net2280_request, req); @@ -442,7 +442,7 @@ struct net2280_ep *ep; ep = container_of (_ep, struct net2280_ep, ep); - if (!ep || (!ep->desc && ep->num != 0)) + if (!_ep || (!ep->desc && ep->num != 0)) return 0; *dma = DMA_ADDR_INVALID; @@ -561,16 +561,12 @@ writel ((1 << FIFO_FLUSH), statp); mb (); tmp = readl (statp); - if (tmp & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)) { + if (tmp & (1 << DATA_OUT_PING_TOKEN_INTERRUPT) + /* high speed did bulk NYET; fifo isn't filling */ + && ep->dev->gadget.speed == USB_SPEED_FULL) { unsigned usec; - if (ep->dev->gadget.speed == USB_SPEED_HIGH) { - if (ep->ep.maxpacket <= 512) - usec = 10; /* 512 byte bulk */ - else - usec = 21; /* 1024 byte interrupt */ - } else - usec = 50; /* 64 byte bulk/interrupt */ + usec = 50; /* 64 byte bulk/interrupt */ handshake (statp, (1 << USB_OUT_PING_NAK_SENT), (1 << USB_OUT_PING_NAK_SENT), usec); /* NAK done; now CLEAR_NAK_OUT_PACKETS is safe */ @@ -614,15 +610,13 @@ count = readl (®s->ep_avail); tmp = req->req.length - req->req.actual; if (count > tmp) { - unsigned over = tmp % ep->ep.maxpacket; - - /* FIXME handle this consistently between PIO and DMA */ - if (over) { + /* as with DMA, data overflow gets flushed */ + if ((tmp % ep->ep.maxpacket) != 0) { ERROR (ep->dev, - "%s out fifo %d bytes, over %d extra %d\n", - ep->ep.name, count, over, count - tmp); + "%s out fifo %d bytes, expected %d\n", + ep->ep.name, count, tmp); req->req.status = -EOVERFLOW; - tmp -= over; + cleanup = 1; } count = tmp; } @@ -670,10 +664,12 @@ /* don't let DMA continue after a short OUT packet, * so overruns can't affect the next transfer. + * in case of overruns on max-size packets, we can't + * stop the fifo from filling but we can flush it. */ if (ep->is_in) dmacount |= (1 << DMA_DIRECTION); - else if ((dmacount % ep->ep.maxpacket) != 0) + else dmacount |= (1 << END_OF_CHAIN); req->valid = valid; @@ -897,8 +893,12 @@ start_dma (ep, req); else { /* maybe there's no control data, just status ack */ - if (ep->num == 0 && _req->length == 0) + if (ep->num == 0 && _req->length == 0) { + allow_status (ep); + done (ep, req, 0); + VDEBUG (dev, "%s status ack\n", ep->ep.name); goto done; + } /* PIO ... stuff the fifo, or unblock it. */ if (ep->is_in) @@ -948,10 +948,9 @@ } /* else the irq handler advances the queue. */ - if (req) { -done: + if (req) list_add_tail (&req->queue, &ep->queue); - } +done: spin_unlock_irqrestore (&dev->lock, flags); /* pci writes may still be posted */ @@ -992,6 +991,8 @@ /* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short" * packets, including overruns, even when the transfer was * exactly the length requested (dmacount now zero). + * FIXME there's an overrun case here too, where we expect + * a short packet but receive a max length one (won't NAK). */ if (!ep->is_in && (req->req.length % ep->ep.maxpacket) != 0) { req->dma_done = 1; @@ -1186,7 +1187,8 @@ return -EINVAL; if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - if ((ep->desc->bmAttributes & 0x03) == USB_ENDPOINT_XFER_ISOC) + if (ep->desc /* not ep0 */ && (ep->desc->bmAttributes & 0x03) + == USB_ENDPOINT_XFER_ISOC) return -EINVAL; VDEBUG (ep->dev, "%s %s halt\n", _ep->name, value ? "set" : "clear"); @@ -1712,7 +1714,7 @@ static void ep0_start (struct net2280 *dev) { - writel ( (1 << SET_EP_HIDE_STATUS_PHASE) + writel ( (1 << CLEAR_EP_HIDE_STATUS_PHASE) | (1 << CLEAR_NAK_OUT_PACKETS) | (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) , &dev->epregs [0].ep_rsp); @@ -1916,22 +1918,27 @@ if (ep->is_in) { /* status; stop NAKing */ if (t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)) { - if (ep->dev->protocol_stall) + if (ep->dev->protocol_stall) { + ep->stopped = 1; set_halt (ep); + } mode = 2; - /* reply to extra IN tokens with a zlp */ + /* reply to extra IN data tokens with a zlp */ } else if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) { if (ep->dev->protocol_stall) { + ep->stopped = 1; set_halt (ep); mode = 2; - } else if (!req) + } else if (!req && ep->stopped) write_fifo (ep, 0); } } else { /* status; stop NAKing */ if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) { - if (ep->dev->protocol_stall) + if (ep->dev->protocol_stall) { + ep->stopped = 1; set_halt (ep); + } mode = 2; /* an extra OUT token is an error */ } else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)) @@ -2031,6 +2038,10 @@ /* maybe advance queue to next request */ if (ep->num == 0) { + /* FIXME need mechanism (request flag?) so control OUT + * can decide to stall ep0 after that done() returns, + * from non-irq context + */ allow_status (ep); req = 0; } else { @@ -2171,6 +2182,7 @@ struct net2280_ep *e; u16 status; + /* hw handles device and interface status */ if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT)) goto delegate; if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0 @@ -2188,12 +2200,14 @@ set_fifo_bytecount (ep, u.r.wLength); writel (status, &dev->epregs [0].ep_data); allow_status (ep); + VDEBUG (dev, "%s stat %02x\n", ep->ep.name, status); goto next_endpoints; } break; case USB_REQ_CLEAR_FEATURE: { struct net2280_ep *e; + /* hw handles device features */ if (u.r.bRequestType != USB_RECIP_ENDPOINT) goto delegate; if (u.r.wIndex != 0 /* HALT feature */ @@ -2202,11 +2216,15 @@ if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0) goto do_stall; clear_halt (e); + allow_status (ep); + VDEBUG (dev, "%s clear halt\n", ep->ep.name); + goto next_endpoints; } break; case USB_REQ_SET_FEATURE: { struct net2280_ep *e; + /* hw handles device features */ if (u.r.bRequestType != USB_RECIP_ENDPOINT) goto delegate; if (u.r.wIndex != 0 /* HALT feature */ @@ -2215,6 +2233,9 @@ if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0) goto do_stall; set_halt (e); + allow_status (ep); + VDEBUG (dev, "%s set halt\n", ep->ep.name); + goto next_endpoints; } break; default: @@ -2235,23 +2256,12 @@ VDEBUG (dev, "req %02x.%02x protocol STALL; stat %d\n", u.r.bRequestType, u.r.bRequest, tmp); dev->protocol_stall = 1; - - /* when there's no data, queueing a response is optional */ - } else if (list_empty (&ep->queue)) { - if (u.r.wLength == 0) { - /* done() not possible/requested */ - allow_status (ep); - } else { - DEBUG (dev, "req %02x.%02x v%04x " - "gadget error, len %d, stat %d\n", - u.r.bRequestType, u.r.bRequest, - le16_to_cpu (u.r.wValue), - u.r.wLength, tmp); - dev->protocol_stall = 1; - } } - /* some in/out token irq should follow; maybe stall then. */ + /* some in/out token irq should follow; maybe stall then. + * driver must queue a request (even zlp) or halt ep0 + * before the host times out. + */ } next_endpoints: diff -urN linux-2.5.69-bk16/drivers/usb/gadget/net2280.h linux-2.5.69-bk17/drivers/usb/gadget/net2280.h --- linux-2.5.69-bk16/drivers/usb/gadget/net2280.h 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/usb/gadget/net2280.h 2003-05-24 04:33:34.000000000 -0700 @@ -437,6 +437,8 @@ /*-------------------------------------------------------------------------*/ +#ifdef __KERNEL__ + /* indexed registers [11.10] are accessed indirectly * caller must own the device lock. */ @@ -457,6 +459,9 @@ /* posted, may not be visible yet */ } +#endif /* __KERNEL__ */ + + #define REG_DIAG 0x0 #define RETRY_COUNTER 16 #define FORCE_PCI_SERR 11 @@ -471,6 +476,8 @@ #define REG_CHIPREV 0x03 /* in bcd */ #define REG_HS_NAK_RATE 0x0a /* NAK per N uframes */ +#ifdef __KERNEL__ + /* ep a-f highspeed and fullspeed maxpacket, addresses * computed from ep->num */ @@ -519,6 +526,7 @@ writel ( (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) | (1 << CLEAR_NAK_OUT_PACKETS_MODE) , &ep->regs->ep_rsp); + ep->stopped = 1; } static inline void set_halt (struct net2280_ep *ep) @@ -707,3 +715,4 @@ writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp); } +#endif /* __KERNEL__ */ diff -urN linux-2.5.69-bk16/drivers/usb/gadget/zero.c linux-2.5.69-bk17/drivers/usb/gadget/zero.c --- linux-2.5.69-bk16/drivers/usb/gadget/zero.c 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/usb/gadget/zero.c 2003-05-24 04:33:34.000000000 -0700 @@ -653,7 +653,7 @@ /* this endpoint is normally active while we're configured */ case -ECONNRESET: /* request dequeued */ case -ESHUTDOWN: /* disconnect from host */ - DEBUG (dev, "%s gone (%d), %d/%d\n", ep->name, status, + VDEBUG (dev, "%s gone (%d), %d/%d\n", ep->name, status, req->actual, req->length); free_ep_req (ep, req); return; @@ -1035,9 +1035,6 @@ if (ctrl->bRequestType != 0) break; spin_lock (&dev->lock); - /* change hardware configuration! - * no response queued, just zero status == success - */ value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC); spin_unlock (&dev->lock); break; @@ -1092,7 +1089,7 @@ } /* respond with data transfer before status phase? */ - if (value > 0) { + if (value >= 0) { req->length = value; value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); if (value < 0) { diff -urN linux-2.5.69-bk16/drivers/usb/host/uhci-hcd.c linux-2.5.69-bk17/drivers/usb/host/uhci-hcd.c --- linux-2.5.69-bk16/drivers/usb/host/uhci-hcd.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/drivers/usb/host/uhci-hcd.c 2003-05-24 04:33:34.000000000 -0700 @@ -61,7 +61,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v2.0" +#define DRIVER_VERSION "v2.1" #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber" #define DRIVER_DESC "USB Universal Host Controller Interface driver" @@ -91,9 +91,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb); -static int ports_active(struct uhci_hcd *uhci); -static void suspend_hc(struct uhci_hcd *uhci); -static void wakeup_hc(struct uhci_hcd *uhci); +static void hc_state_transitions(struct uhci_hcd *uhci); /* If a transfer is still active after this much time, turn off FSBR */ #define IDLE_TIMEOUT (HZ / 20) /* 50 ms */ @@ -1757,9 +1755,8 @@ uhci->skel_term_qh->link = UHCI_PTR_TERM; } - /* enter global suspend if nothing connected */ - if (!uhci->is_suspended && !ports_active(uhci)) - suspend_hc(uhci); + /* Poll for and perform state transitions */ + hc_state_transitions(uhci); init_stall_timer(hcd); } @@ -1884,14 +1881,14 @@ err("%x: host system error, PCI problems?", io_addr); if (status & USBSTS_HCPE) err("%x: host controller process error. something bad happened", io_addr); - if ((status & USBSTS_HCH) && !uhci->is_suspended) { + if ((status & USBSTS_HCH) && uhci->state > 0) { err("%x: host controller halted. very bad", io_addr); /* FIXME: Reset the controller, fix the offending TD */ } } if (status & USBSTS_RD) - wakeup_hc(uhci); + uhci->resume_detect = 1; uhci_free_pending_qhs(uhci); @@ -1922,10 +1919,18 @@ unsigned int io_addr = uhci->io_addr; /* Global reset for 50ms */ + uhci->state = UHCI_RESET; outw(USBCMD_GRESET, io_addr + USBCMD); - wait_ms(50); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((HZ*50+999) / 1000); + set_current_state(TASK_RUNNING); outw(0, io_addr + USBCMD); - wait_ms(10); + + /* Another 10ms delay */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((HZ*10+999) / 1000); + set_current_state(TASK_RUNNING); + uhci->resume_detect = 0; } static void suspend_hc(struct uhci_hcd *uhci) @@ -1933,34 +1938,49 @@ unsigned int io_addr = uhci->io_addr; dbg("%x: suspend_hc", io_addr); - - uhci->is_suspended = 1; - smp_wmb(); - + uhci->state = UHCI_SUSPENDED; + uhci->resume_detect = 0; outw(USBCMD_EGSM, io_addr + USBCMD); } static void wakeup_hc(struct uhci_hcd *uhci) { unsigned int io_addr = uhci->io_addr; - unsigned int status; - dbg("%x: wakeup_hc", io_addr); + switch (uhci->state) { + case UHCI_SUSPENDED: /* Start the resume */ + dbg("%x: wakeup_hc", io_addr); + + /* Global resume for >= 20ms */ + outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD); + uhci->state = UHCI_RESUMING_1; + uhci->state_end = jiffies + (20*HZ+999) / 1000; + break; - /* Global resume for 20ms */ - outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD); - wait_ms(20); - outw(0, io_addr + USBCMD); - - /* wait for EOP to be sent */ - status = inw(io_addr + USBCMD); - while (status & USBCMD_FGR) - status = inw(io_addr + USBCMD); + case UHCI_RESUMING_1: /* End global resume */ + uhci->state = UHCI_RESUMING_2; + outw(0, io_addr + USBCMD); + /* Falls through */ - uhci->is_suspended = 0; + case UHCI_RESUMING_2: /* Wait for EOP to be sent */ + if (inw(io_addr + USBCMD) & USBCMD_FGR) + break; - /* Run and mark it configured with a 64-byte max packet */ - outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); + /* Run for at least 1 second, and + * mark it configured with a 64-byte max packet */ + uhci->state = UHCI_RUNNING_GRACE; + uhci->state_end = jiffies + HZ; + outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, + io_addr + USBCMD); + break; + + case UHCI_RUNNING_GRACE: /* Now allowed to suspend */ + uhci->state = UHCI_RUNNING; + break; + + default: + break; + } } static int ports_active(struct uhci_hcd *uhci) @@ -1975,6 +1995,73 @@ return connection; } +static int suspend_allowed(struct uhci_hcd *uhci) +{ + unsigned int io_addr = uhci->io_addr; + int i; + + if (!uhci->hcd.pdev || + uhci->hcd.pdev->vendor != PCI_VENDOR_ID_INTEL || + uhci->hcd.pdev->device != PCI_DEVICE_ID_INTEL_82371AB_2) + return 1; + + /* This is a 82371AB/EB/MB USB controller which has a bug that + * causes false resume indications if any port has an + * over current condition. To prevent problems, we will not + * allow a global suspend if any ports are OC. + * + * Some motherboards using the 82371AB/EB/MB (but not the USB portion) + * appear to hardwire the over current inputs active to disable + * the USB ports. + */ + + /* check for over current condition on any port */ + for (i = 0; i < uhci->rh_numports; i++) { + if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC) + return 0; + } + + return 1; +} + +static void hc_state_transitions(struct uhci_hcd *uhci) +{ + switch (uhci->state) { + case UHCI_RUNNING: + + /* global suspend if nothing connected for 1 second */ + if (!ports_active(uhci) && suspend_allowed(uhci)) { + uhci->state = UHCI_SUSPENDING_GRACE; + uhci->state_end = jiffies + HZ; + } + break; + + case UHCI_SUSPENDING_GRACE: + if (ports_active(uhci)) + uhci->state = UHCI_RUNNING; + else if (time_after_eq(jiffies, uhci->state_end)) + suspend_hc(uhci); + break; + + case UHCI_SUSPENDED: + + /* wakeup if requested by a device */ + if (uhci->resume_detect) + wakeup_hc(uhci); + break; + + case UHCI_RESUMING_1: + case UHCI_RESUMING_2: + case UHCI_RUNNING_GRACE: + if (time_after_eq(jiffies, uhci->state_end)) + wakeup_hc(uhci); + break; + + default: + break; + } +} + static void start_hc(struct uhci_hcd *uhci) { unsigned int io_addr = uhci->io_addr; @@ -2003,6 +2090,8 @@ outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD); /* Run and mark it configured with a 64-byte max packet */ + uhci->state = UHCI_RUNNING_GRACE; + uhci->state_end = jiffies + HZ; outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); uhci->hcd.state = USB_STATE_READY; @@ -2101,8 +2190,6 @@ uhci->fsbr = 0; uhci->fsbrtimeout = 0; - uhci->is_suspended = 0; - spin_lock_init(&uhci->qh_remove_list_lock); INIT_LIST_HEAD(&uhci->qh_remove_list); @@ -2335,7 +2422,11 @@ { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - suspend_hc(uhci); + /* Don't try to suspend broken motherboards, reset instead */ + if (suspend_allowed(uhci)) + suspend_hc(uhci); + else + reset_hc(uhci); return 0; } @@ -2345,8 +2436,13 @@ pci_set_master(uhci->hcd.pdev); - reset_hc(uhci); - start_hc(uhci); + if (uhci->state == UHCI_SUSPENDED) + uhci->resume_detect = 1; + else { + reset_hc(uhci); + start_hc(uhci); + } + uhci->hcd.state = USB_STATE_READY; return 0; } #endif diff -urN linux-2.5.69-bk16/drivers/usb/host/uhci-hcd.h linux-2.5.69-bk17/drivers/usb/host/uhci-hcd.h --- linux-2.5.69-bk16/drivers/usb/host/uhci-hcd.h 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk17/drivers/usb/host/uhci-hcd.h 2003-05-24 04:33:34.000000000 -0700 @@ -53,6 +53,7 @@ #define USBPORTSC_RD 0x0040 /* Resume Detect */ #define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ #define USBPORTSC_PR 0x0200 /* Port Reset */ +#define USBPORTSC_OC 0x0400 /* Over Current condition */ #define USBPORTSC_SUSP 0x1000 /* Suspend */ /* Legacy support register */ @@ -282,6 +283,29 @@ return 0; /* int128 for 128-255 ms (Max.) */ } +/* + * Device states for the host controller. + * + * To prevent "bouncing" in the presence of electrical noise, + * we insist on a 1-second "grace" period, before switching to + * the RUNNING or SUSPENDED states, during which the state is + * not allowed to change. + * + * The resume process is divided into substates in order to avoid + * potentially length delays during the timer handler. + * + * States in which the host controller is halted must have values <= 0. + */ +enum uhci_state { + UHCI_RESET, + UHCI_RUNNING_GRACE, /* Before RUNNING */ + UHCI_RUNNING, /* The normal state */ + UHCI_SUSPENDING_GRACE, /* Before SUSPENDED */ + UHCI_SUSPENDED = -10, /* When no devices are attached */ + UHCI_RESUMING_1, + UHCI_RESUMING_2 +}; + #define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd) /* @@ -313,7 +337,10 @@ struct uhci_frame_list *fl; /* P: uhci->frame_list_lock */ int fsbr; /* Full speed bandwidth reclamation */ unsigned long fsbrtimeout; /* FSBR delay */ - int is_suspended; + + enum uhci_state state; /* FIXME: needs a spinlock */ + unsigned long state_end; /* Time of next transition */ + int resume_detect; /* Need a Global Resume */ /* Main list of URB's currently controlled by this HC */ spinlock_t urb_list_lock; diff -urN linux-2.5.69-bk16/drivers/usb/misc/speedtch.c linux-2.5.69-bk17/drivers/usb/misc/speedtch.c --- linux-2.5.69-bk16/drivers/usb/misc/speedtch.c 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/usb/misc/speedtch.c 2003-05-24 04:33:34.000000000 -0700 @@ -1,7 +1,8 @@ /****************************************************************************** - * speedtouch.c -- Alcatel SpeedTouch USB xDSL modem driver. + * speedtouch.c - Alcatel SpeedTouch USB xDSL modem driver * * Copyright (C) 2001, Alcatel + * Copyright (C) 2003, Duncan Sands * * 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 @@ -40,7 +41,6 @@ * udsl_usb_send_data_context->urb to a pointer and adding code * to alloc and free it * - remove_wait_queue() added to udsl_atm_processqueue_thread() - * - Duncan Sands (duncan.sands@wanadoo.fr) is the new maintainer * * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL. * (reported by stephen.robinson@zen.co.uk) @@ -97,48 +97,65 @@ #define DRIVER_DESC "Alcatel SpeedTouch USB driver" #define DRIVER_VERSION "1.6" +static const char udsl_driver_name [] = "speedtch"; + #define SPEEDTOUCH_VENDORID 0x06b9 #define SPEEDTOUCH_PRODUCTID 0x4061 -#define UDSL_NUMBER_RCV_URBS 1 -#define UDSL_NUMBER_SND_URBS 1 -#define UDSL_NUMBER_SND_BUFS (2*UDSL_NUMBER_SND_URBS) -#define UDSL_RCV_BUFFER_SIZE (1*64) /* ATM cells */ -#define UDSL_SND_BUFFER_SIZE (1*64) /* ATM cells */ -/* max should be (1500 IP mtu + 2 ppp bytes + 32 * 5 cellheader overhead) for - * PPPoA and (1500 + 14 + 32*5 cellheader overhead) for PPPoE */ -#define UDSL_MAX_AAL5_MRU 2048 - -#define UDSL_IOCTL_START 1 -#define UDSL_IOCTL_STOP 2 +#define UDSL_NUM_RCV_URBS 1 +#define UDSL_NUM_SND_URBS 1 +#define UDSL_NUM_RCV_BUFS (2*UDSL_NUM_RCV_URBS) +#define UDSL_NUM_SND_BUFS (2*UDSL_NUM_SND_URBS) +#define UDSL_RCV_BUF_SIZE 32 /* ATM cells */ +#define UDSL_SND_BUF_SIZE 64 /* ATM cells */ -/* endpoint declarations */ +#define UDSL_IOCTL_LINE_UP 1 +#define UDSL_IOCTL_LINE_DOWN 2 #define UDSL_ENDPOINT_DATA_OUT 0x07 #define UDSL_ENDPOINT_DATA_IN 0x87 #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) +#define UDSL_NUM_CELLS(x) (((x) + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD) -#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) ) - -/* usb_device_id struct */ +#define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) ) static struct usb_device_id udsl_usb_ids [] = { { USB_DEVICE (SPEEDTOUCH_VENDORID, SPEEDTOUCH_PRODUCTID) }, - { } /* Terminating entry */ + { } }; MODULE_DEVICE_TABLE (usb, udsl_usb_ids); -/* context declarations */ +/* receive */ + +struct udsl_receive_buffer { + struct list_head list; + unsigned char *base; + unsigned int filled_cells; +}; struct udsl_receiver { struct list_head list; - struct sk_buff *skb; + struct udsl_receive_buffer *buffer; struct urb *urb; struct udsl_instance_data *instance; }; +struct udsl_vcc_data { + /* vpi/vci lookup */ + struct list_head list; + short vpi; + int vci; + struct atm_vcc *vcc; + + /* raw cell reassembly */ + struct sk_buff *skb; + unsigned int max_pdu; +}; + +/* send */ + struct udsl_send_buffer { struct list_head list; unsigned char *base; @@ -157,73 +174,55 @@ struct atm_skb_data atm_data; unsigned int num_cells; unsigned int num_entire; - unsigned char cell_header [ATM_CELL_HEADER]; unsigned int pdu_padding; + unsigned char cell_header [ATM_CELL_HEADER]; unsigned char aal5_trailer [ATM_AAL5_TRAILER]; }; #define UDSL_SKB(x) ((struct udsl_control *)(x)->cb) -struct udsl_vcc_data { - /* vpi/vci lookup */ - struct list_head list; - short vpi; - int vci; - struct atm_vcc *vcc; - - /* raw cell reassembly */ - unsigned short mtu; - struct sk_buff *reasBuffer; -}; - -/* - * UDSL main driver data - */ +/* main driver data */ struct udsl_instance_data { struct semaphore serialize; - /* usb device part */ + /* USB device part */ struct usb_device *usb_dev; char description [64]; int firmware_loaded; - /* atm device part */ + /* ATM device part */ struct atm_dev *atm_dev; struct list_head vcc_list; - /* receiving */ - struct udsl_receiver all_receivers [UDSL_NUMBER_RCV_URBS]; + /* receive */ + struct udsl_receiver receivers [UDSL_NUM_RCV_URBS]; + struct udsl_receive_buffer receive_buffers [UDSL_NUM_RCV_BUFS]; - spinlock_t spare_receivers_lock; + spinlock_t receive_lock; struct list_head spare_receivers; - - spinlock_t completed_receivers_lock; - struct list_head completed_receivers; + struct list_head filled_receive_buffers; struct tasklet_struct receive_tasklet; + struct list_head spare_receive_buffers; - /* sending */ - struct udsl_sender all_senders [UDSL_NUMBER_SND_URBS]; - struct udsl_send_buffer all_buffers [UDSL_NUMBER_SND_BUFS]; + /* send */ + struct udsl_sender senders [UDSL_NUM_SND_URBS]; + struct udsl_send_buffer send_buffers [UDSL_NUM_SND_BUFS]; struct sk_buff_head sndqueue; spinlock_t send_lock; struct list_head spare_senders; - struct list_head spare_buffers; + struct list_head spare_send_buffers; struct tasklet_struct send_tasklet; struct sk_buff *current_skb; /* being emptied */ struct udsl_send_buffer *current_buffer; /* being filled */ - struct list_head filled_buffers; + struct list_head filled_send_buffers; }; -static const char udsl_driver_name [] = "speedtch"; - -/* - * atm driver prototypes and structures - */ +/* ATM */ static void udsl_atm_dev_close (struct atm_dev *dev); static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci); @@ -239,17 +238,17 @@ .ioctl = udsl_atm_ioctl, .send = udsl_atm_send, .proc_read = udsl_atm_proc_read, + .owner = THIS_MODULE, }; -/* - * usb driver prototypes and structures - */ -static int udsl_usb_probe (struct usb_interface *intf, - const struct usb_device_id *id); +/* USB */ + +static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_id *id); static void udsl_usb_disconnect (struct usb_interface *intf); static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *user_data); static struct usb_driver udsl_usb_driver = { + .owner = THIS_MODULE, .name = udsl_driver_name, .probe = udsl_usb_probe, .disconnect = udsl_usb_disconnect, @@ -272,133 +271,110 @@ return NULL; } -static struct sk_buff *udsl_decode_rawcell (struct udsl_instance_data *instance, struct sk_buff *skb, struct udsl_vcc_data **ctx) +static void udsl_extract_cells (struct udsl_instance_data *instance, unsigned char *source, unsigned int howmany) { - if (!instance || !skb || !ctx) - return NULL; - if (!skb->data || !skb->tail) - return NULL; - - while (skb->len) { - unsigned char *cell = skb->data; - unsigned char *cell_payload; - struct udsl_vcc_data *vcc; - short vpi; - int vci; - - vpi = ((cell[0] & 0x0f) << 4) | (cell[1] >> 4); - vci = ((cell[1] & 0x0f) << 12) | (cell[2] << 4) | (cell[3] >> 4); - - vdbg ("udsl_decode_rawcell (0x%p, 0x%p, 0x%p) called", instance, skb, ctx); - vdbg ("udsl_decode_rawcell skb->data %p, skb->tail %p", skb->data, skb->tail); - - /* here should the header CRC check be... */ - - if (!(vcc = udsl_find_vcc (instance, vpi, vci))) { - dbg ("udsl_decode_rawcell: no vcc found for packet on vpi %d, vci %d", vpi, vci); - __skb_pull (skb, min (skb->len, (unsigned) 53)); + struct udsl_vcc_data *cached_vcc = NULL; + struct atm_vcc *vcc; + struct sk_buff *skb; + struct udsl_vcc_data *vcc_data; + int cached_vci = 0; + unsigned int i; + unsigned int length; + unsigned int pdu_length; + int pti; + int vci; + short cached_vpi = 0; + short vpi; + + for (i = 0; i < howmany; i++, source += ATM_CELL_SIZE) { + vpi = ((source [0] & 0x0f) << 4) | (source [1] >> 4); + vci = ((source [1] & 0x0f) << 12) | (source [2] << 4) | (source [3] >> 4); + pti = (source [3] & 0x2) != 0; + + vdbg ("udsl_extract_cells: vpi %hd, vci %d, pti %d", vpi, vci, pti); + + if (cached_vcc && (vci == cached_vci) && (vpi == cached_vpi)) + vcc_data = cached_vcc; + else if ((vcc_data = udsl_find_vcc (instance, vpi, vci))) { + cached_vcc = vcc_data; + cached_vpi = vpi; + cached_vci = vci; } else { - vdbg ("udsl_decode_rawcell found vcc %p for packet on vpi %d, vci %d", vcc, vpi, vci); + dbg ("udsl_extract_cells: unknown vpi/vci (%hd/%d)!", vpi, vci); + continue; + } - if (skb->len >= 53) { - cell_payload = cell + 5; + vcc = vcc_data->vcc; - if (!vcc->reasBuffer) - vcc->reasBuffer = dev_alloc_skb (vcc->mtu); + if (!vcc_data->skb && !(vcc_data->skb = dev_alloc_skb (vcc_data->max_pdu))) { + dbg ("udsl_extract_cells: no memory for skb (vcc: 0x%p)!", vcc); + if (pti) + atomic_inc (&vcc->stats->rx_err); + continue; + } - /* if alloc fails, we just drop the cell. it is possible that we can still - * receive cells on other vcc's - */ - if (vcc->reasBuffer) { - /* if (buffer overrun) discard received cells until now */ - if ((vcc->reasBuffer->len) > (vcc->mtu - 48)) - skb_trim (vcc->reasBuffer, 0); - - /* copy data */ - memcpy (vcc->reasBuffer->tail, cell_payload, 48); - skb_put (vcc->reasBuffer, 48); - - /* check for end of buffer */ - if (cell[3] & 0x2) { - struct sk_buff *tmp; - - /* the aal5 buffer ends here, cut the buffer. */ - /* buffer will always have at least one whole cell, so */ - /* don't need to check return from skb_pull */ - skb_pull (skb, 53); - *ctx = vcc; - tmp = vcc->reasBuffer; - vcc->reasBuffer = NULL; - - vdbg ("udsl_decode_rawcell returns ATM_AAL5 pdu 0x%p with length %d", tmp, tmp->len); - return tmp; - } - } - /* flush the cell */ - /* buffer will always contain at least one whole cell, so don't */ - /* need to check return value from skb_pull */ - skb_pull (skb, 53); - } else { - /* If data is corrupt and skb doesn't hold a whole cell, flush the lot */ - __skb_pull (skb, skb->len); - return NULL; - } + skb = vcc_data->skb; + + if (skb->len + ATM_CELL_PAYLOAD > vcc_data->max_pdu) { + dbg ("udsl_extract_cells: buffer overrun (max_pdu: %u, skb->len %u, vcc: 0x%p)", vcc_data->max_pdu, skb->len, vcc); + /* discard cells already received */ + skb_trim (skb, 0); + BUG_ON (vcc_data->max_pdu < ATM_CELL_PAYLOAD); } - } - return NULL; -} + memcpy (skb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); + __skb_put (skb, ATM_CELL_PAYLOAD); -static struct sk_buff *udsl_decode_aal5 (struct udsl_vcc_data *ctx, struct sk_buff *skb) -{ - uint crc = 0xffffffff; - uint length, pdu_crc, pdu_length; + if (pti) { + length = (source [ATM_CELL_SIZE - 6] << 8) + source [ATM_CELL_SIZE - 5]; - vdbg ("udsl_decode_aal5 (0x%p, 0x%p) called", ctx, skb); + /* guard against overflow */ + if (length > ATM_MAX_AAL5_PDU) { + dbg ("udsl_extract_cells: bogus length %u (vcc: 0x%p)", length, vcc); + goto drop; + } - if (skb->len && (skb->len % 48)) - return NULL; + pdu_length = UDSL_NUM_CELLS (length) * ATM_CELL_PAYLOAD; - length = (skb->tail[-6] << 8) + skb->tail[-5]; - pdu_crc = - (skb->tail[-4] << 24) + (skb->tail[-3] << 16) + (skb->tail[-2] << 8) + skb->tail[-1]; - pdu_length = ((length + 47 + 8) / 48) * 48; + if (skb->len < pdu_length) { + dbg ("udsl_extract_cells: bogus pdu_length %u (skb->len: %u, vcc: 0x%p)", pdu_length, skb->len, vcc); + goto drop; + } - vdbg ("udsl_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d", skb->len, length, pdu_crc, pdu_length); + if (crc32_be (~0, skb->tail - pdu_length, pdu_length) != 0xc704dd7b) { + dbg ("udsl_extract_cells: packet failed crc check (vcc: 0x%p)", vcc); + goto drop; + } - /* is skb long enough ? */ - if (skb->len < pdu_length) { - atomic_inc (&ctx->vcc->stats->rx_err); - return NULL; - } + if (!atm_charge (vcc, skb->truesize)) { + dbg ("udsl_extract_cells: failed atm_charge (skb->truesize: %u)", skb->truesize); + goto drop_no_stats; /* atm_charge increments rx_drop */ + } - /* is skb too long ? */ - if (skb->len > pdu_length) { - dbg ("udsl_decode_aal5: Warning: readjusting illegal size %d -> %d", skb->len, pdu_length); - /* buffer is too long. we can try to recover - * if we discard the first part of the skb. - * the crc will decide whether this was ok - */ - skb_pull (skb, skb->len - pdu_length); - } + /* now that we are sure to send the skb, it is ok to change skb->data */ + if (skb->len > pdu_length) + skb_pull (skb, skb->len - pdu_length); /* discard initial junk */ - crc = ~crc32_be (crc, skb->data, pdu_length - 4); + skb_trim (skb, length); /* drop zero padding and trailer */ - /* check crc */ - if (pdu_crc != crc) { - dbg ("udsl_decode_aal5: crc check failed!"); - atomic_inc (&ctx->vcc->stats->rx_err); - return NULL; - } + atomic_inc (&vcc->stats->rx); - /* pdu is ok */ - skb_trim (skb, length); + PACKETDEBUG (skb->data, skb->len); + + vdbg ("udsl_extract_cells: sending skb 0x%p, skb->len %u, skb->truesize %u", skb, skb->len, skb->truesize); + + vcc->push (vcc, skb); - /* update stats */ - atomic_inc (&ctx->vcc->stats->rx); + vcc_data->skb = NULL; - vdbg ("udsl_decode_aal5 returns pdu 0x%p with length %d", skb, skb->len); - return skb; + continue; + +drop: + atomic_inc (&vcc->stats->rx_err); +drop_no_stats: + skb_trim (skb, 0); + } + } } @@ -406,7 +382,7 @@ ** encode ** *************/ -static const unsigned char zeros[ATM_CELL_PAYLOAD]; +static const unsigned char zeros [ATM_CELL_PAYLOAD]; static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) { @@ -421,7 +397,7 @@ ctrl->cell_header [3] = vcc->vci << 4; ctrl->cell_header [4] = 0xec; - ctrl->num_cells = (skb->len + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD; + ctrl->num_cells = UDSL_NUM_CELLS (skb->len); ctrl->num_entire = skb->len / ATM_CELL_PAYLOAD; zero_padding = ctrl->num_cells * ATM_CELL_PAYLOAD - skb->len - ATM_AAL5_TRAILER; @@ -490,8 +466,7 @@ memset (target, 0, ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); target += ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; - if (--ctrl->num_cells) - BUG(); + BUG_ON (--ctrl->num_cells); } memcpy (target, ctrl->aal5_trailer, ATM_AAL5_TRAILER); @@ -511,145 +486,89 @@ static void udsl_complete_receive (struct urb *urb, struct pt_regs *regs) { + struct udsl_receive_buffer *buf; struct udsl_instance_data *instance; struct udsl_receiver *rcv; unsigned long flags; - if (!urb || !(rcv = urb->context) || !(instance = rcv->instance)) { + if (!urb || !(rcv = urb->context)) { dbg ("udsl_complete_receive: bad urb!"); return; } - vdbg ("udsl_complete_receive entered (urb 0x%p, status %d)", urb, urb->status); + instance = rcv->instance; + buf = rcv->buffer; + + buf->filled_cells = urb->actual_length / ATM_CELL_SIZE; + + vdbg ("udsl_complete_receive: urb 0x%p, status %d, actual_length %d, filled_cells %u, rcv 0x%p, buf 0x%p", urb, urb->status, urb->actual_length, buf->filled_cells, rcv, buf); + + BUG_ON (buf->filled_cells > UDSL_RCV_BUF_SIZE); /* may not be in_interrupt() */ - spin_lock_irqsave (&instance->completed_receivers_lock, flags); - list_add_tail (&rcv->list, &instance->completed_receivers); - tasklet_schedule (&instance->receive_tasklet); - spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); + spin_lock_irqsave (&instance->receive_lock, flags); + list_add (&rcv->list, &instance->spare_receivers); + list_add_tail (&buf->list, &instance->filled_receive_buffers); + if (likely (!urb->status)) + tasklet_schedule (&instance->receive_tasklet); + spin_unlock_irqrestore (&instance->receive_lock, flags); } static void udsl_process_receive (unsigned long data) { + struct udsl_receive_buffer *buf; struct udsl_instance_data *instance = (struct udsl_instance_data *) data; struct udsl_receiver *rcv; - unsigned char *data_start; - struct sk_buff *skb; - struct urb *urb; - struct udsl_vcc_data *atmsar_vcc = NULL; - struct sk_buff *new = NULL, *tmp = NULL; int err; - vdbg ("udsl_process_receive entered"); - - spin_lock_irq (&instance->completed_receivers_lock); - while (!list_empty (&instance->completed_receivers)) { - rcv = list_entry (instance->completed_receivers.next, struct udsl_receiver, list); - list_del (&rcv->list); - spin_unlock_irq (&instance->completed_receivers_lock); - - urb = rcv->urb; - vdbg ("udsl_process_receive: got packet %p with length %d and status %d", urb, urb->actual_length, urb->status); - - switch (urb->status) { - case 0: - vdbg ("udsl_process_receive: processing urb with rcv %p, urb %p, skb %p", rcv, urb, rcv->skb); - - /* update the skb structure */ - skb = rcv->skb; - skb_trim (skb, 0); - skb_put (skb, urb->actual_length); - data_start = skb->data; - - vdbg ("skb->len = %d", skb->len); - PACKETDEBUG (skb->data, skb->len); - - while ((new = udsl_decode_rawcell (instance, skb, &atmsar_vcc))) { - vdbg ("(after cell processing)skb->len = %d", new->len); - - tmp = new; - new = udsl_decode_aal5 (atmsar_vcc, new); - - /* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */ - if (new) { - vdbg ("(after aal5 decap) skb->len = %d", new->len); - if (new->len && atm_charge (atmsar_vcc->vcc, new->truesize)) { - PACKETDEBUG (new->data, new->len); - atmsar_vcc->vcc->push (atmsar_vcc->vcc, new); - } else { - dbg - ("dropping incoming packet : vcc->sk->rcvbuf = %d, skb->true_size = %d", - atmsar_vcc->vcc->sk->rcvbuf, new->truesize); - dev_kfree_skb (new); - } - } else { - dbg ("udsl_decode_aal5 returned NULL!"); - dev_kfree_skb (tmp); - } - } - - /* restore skb */ - skb_push (skb, skb->data - data_start); - - usb_fill_bulk_urb (urb, - instance->usb_dev, - usb_rcvbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_IN), - (unsigned char *) rcv->skb->data, - UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE, - udsl_complete_receive, - rcv); - if (!(err = usb_submit_urb (urb, GFP_ATOMIC))) - break; - dbg ("udsl_process_receive: submission failed (%d)", err); - /* fall through */ - default: /* error or urb unlinked */ - vdbg ("udsl_process_receive: adding to spare_receivers"); - spin_lock_irq (&instance->spare_receivers_lock); - list_add (&rcv->list, &instance->spare_receivers); - spin_unlock_irq (&instance->spare_receivers_lock); +made_progress: + while (!list_empty (&instance->spare_receive_buffers)) { + spin_lock_irq (&instance->receive_lock); + if (list_empty (&instance->spare_receivers)) { + spin_unlock_irq (&instance->receive_lock); break; - } /* switch */ - - spin_lock_irq (&instance->completed_receivers_lock); - } /* while */ - spin_unlock_irq (&instance->completed_receivers_lock); - vdbg ("udsl_process_receive successful"); -} - -static void udsl_fire_receivers (struct udsl_instance_data *instance) -{ - struct list_head receivers, *pos, *n; - - INIT_LIST_HEAD (&receivers); - - down (&instance->serialize); - - spin_lock_irq (&instance->spare_receivers_lock); - list_splice_init (&instance->spare_receivers, &receivers); - spin_unlock_irq (&instance->spare_receivers_lock); + } + rcv = list_entry (instance->spare_receivers.next, struct udsl_receiver, list); + list_del (&rcv->list); + spin_unlock_irq (&instance->receive_lock); - list_for_each_safe (pos, n, &receivers) { - struct udsl_receiver *rcv = list_entry (pos, struct udsl_receiver, list); + buf = list_entry (instance->spare_receive_buffers.next, struct udsl_receive_buffer, list); + list_del (&buf->list); - dbg ("udsl_fire_receivers: firing urb %p", rcv->urb); + rcv->buffer = buf; usb_fill_bulk_urb (rcv->urb, instance->usb_dev, usb_rcvbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_IN), - (unsigned char *) rcv->skb->data, - UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE, + buf->base, + UDSL_RCV_BUF_SIZE * ATM_CELL_SIZE, udsl_complete_receive, rcv); - if (usb_submit_urb (rcv->urb, GFP_KERNEL) < 0) { - dbg ("udsl_fire_receivers: submit failed!"); - spin_lock_irq (&instance->spare_receivers_lock); - list_move (pos, &instance->spare_receivers); - spin_unlock_irq (&instance->spare_receivers_lock); + vdbg ("udsl_process_receive: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf); + + if ((err = usb_submit_urb(rcv->urb, GFP_ATOMIC)) < 0) { + dbg ("udsl_process_receive: urb submission failed (%d)!", err); + list_add (&buf->list, &instance->spare_receive_buffers); + spin_lock_irq (&instance->receive_lock); + list_add (&rcv->list, &instance->spare_receivers); + spin_unlock_irq (&instance->receive_lock); + break; } } - up (&instance->serialize); + spin_lock_irq (&instance->receive_lock); + if (list_empty (&instance->filled_receive_buffers)) { + spin_unlock_irq (&instance->receive_lock); + return; /* done - no more buffers */ + } + buf = list_entry (instance->filled_receive_buffers.next, struct udsl_receive_buffer, list); + list_del (&buf->list); + spin_unlock_irq (&instance->receive_lock); + vdbg ("udsl_process_receive: processing buf 0x%p", buf); + udsl_extract_cells (instance, buf->base, buf->filled_cells); + list_add (&buf->list, &instance->spare_receive_buffers); + goto made_progress; } @@ -673,7 +592,7 @@ /* may not be in_interrupt() */ spin_lock_irqsave (&instance->send_lock, flags); list_add (&snd->list, &instance->spare_senders); - list_add (&snd->buffer->list, &instance->spare_buffers); + list_add (&snd->buffer->list, &instance->spare_send_buffers); tasklet_schedule (&instance->send_tasklet); spin_unlock_irqrestore (&instance->send_lock, flags); } @@ -681,17 +600,17 @@ static void udsl_process_send (unsigned long data) { struct udsl_send_buffer *buf; - int err; struct udsl_instance_data *instance = (struct udsl_instance_data *) data; - unsigned int num_written; struct sk_buff *skb; struct udsl_sender *snd; + int err; + unsigned int num_written; made_progress: spin_lock_irq (&instance->send_lock); while (!list_empty (&instance->spare_senders)) { - if (!list_empty (&instance->filled_buffers)) { - buf = list_entry (instance->filled_buffers.next, struct udsl_send_buffer, list); + if (!list_empty (&instance->filled_send_buffers)) { + buf = list_entry (instance->filled_send_buffers.next, struct udsl_send_buffer, list); list_del (&buf->list); } else if ((buf = instance->current_buffer)) { instance->current_buffer = NULL; @@ -707,7 +626,7 @@ instance->usb_dev, usb_sndbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_OUT), buf->base, - (UDSL_SND_BUFFER_SIZE - buf->free_cells) * ATM_CELL_SIZE, + (UDSL_SND_BUF_SIZE - buf->free_cells) * ATM_CELL_SIZE, udsl_complete_send, snd); @@ -718,33 +637,32 @@ spin_lock_irq (&instance->send_lock); list_add (&snd->list, &instance->spare_senders); spin_unlock_irq (&instance->send_lock); - list_add (&buf->list, &instance->filled_buffers); - return; + list_add (&buf->list, &instance->filled_send_buffers); + return; /* bail out */ } spin_lock_irq (&instance->send_lock); } /* while */ spin_unlock_irq (&instance->send_lock); - if (!instance->current_skb && !(instance->current_skb = skb_dequeue (&instance->sndqueue))) { + if (!instance->current_skb && !(instance->current_skb = skb_dequeue (&instance->sndqueue))) return; /* done - no more skbs */ - } skb = instance->current_skb; if (!(buf = instance->current_buffer)) { spin_lock_irq (&instance->send_lock); - if (list_empty (&instance->spare_buffers)) { + if (list_empty (&instance->spare_send_buffers)) { instance->current_buffer = NULL; spin_unlock_irq (&instance->send_lock); return; /* done - no more buffers */ } - buf = list_entry (instance->spare_buffers.next, struct udsl_send_buffer, list); + buf = list_entry (instance->spare_send_buffers.next, struct udsl_send_buffer, list); list_del (&buf->list); spin_unlock_irq (&instance->send_lock); buf->free_start = buf->base; - buf->free_cells = UDSL_SND_BUFFER_SIZE; + buf->free_cells = UDSL_SND_BUF_SIZE; instance->current_buffer = buf; } @@ -754,7 +672,7 @@ vdbg ("udsl_process_send: wrote %u cells from skb 0x%p to buffer 0x%p", num_written, skb, buf); if (!(buf->free_cells -= num_written)) { - list_add_tail (&buf->list, &instance->filled_buffers); + list_add_tail (&buf->list, &instance->filled_send_buffers); instance->current_buffer = NULL; } @@ -766,7 +684,7 @@ if (vcc->pop) vcc->pop (vcc, skb); else - kfree_skb (skb); + dev_kfree_skb (skb); instance->current_skb = NULL; atomic_inc (&vcc->stats->tx); @@ -788,7 +706,7 @@ if (vcc->pop) vcc->pop (vcc, skb); else - kfree_skb (skb); + dev_kfree_skb (skb); } spin_unlock_irq (&instance->sndqueue.lock); @@ -799,7 +717,7 @@ if (vcc->pop) vcc->pop (vcc, skb); else - kfree_skb (skb); + dev_kfree_skb (skb); } tasklet_enable (&instance->send_tasklet); dbg ("udsl_cancel_send done"); @@ -851,6 +769,7 @@ dbg ("udsl_atm_dev_close: queue has %u elements", instance->sndqueue.qlen); + tasklet_kill (&instance->receive_tasklet); tasklet_kill (&instance->send_tasklet); kfree (instance); dev->dev_data = NULL; @@ -871,8 +790,8 @@ if (!left--) return sprintf (page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - atm_dev->esi[0], atm_dev->esi[1], atm_dev->esi[2], - atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]); + atm_dev->esi [0], atm_dev->esi [1], atm_dev->esi [2], + atm_dev->esi [3], atm_dev->esi [4], atm_dev->esi [5]); if (!left--) return sprintf (page, "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n", @@ -925,7 +844,7 @@ return -EINVAL; /* only support AAL5 */ - if (vcc->qos.aal != ATM_AAL5) + if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0) || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) return -EINVAL; if (!instance->firmware_loaded) { @@ -949,7 +868,7 @@ new->vcc = vcc; new->vpi = vpi; new->vci = vci; - new->mtu = UDSL_MAX_AAL5_MRU; + new->max_pdu = max (1, UDSL_NUM_CELLS (vcc->qos.rxtp.max_sdu)) * ATM_CELL_PAYLOAD; vcc->dev_data = new; vcc->vpi = vpi; @@ -965,7 +884,7 @@ up (&instance->serialize); - udsl_fire_receivers (instance); + tasklet_schedule (&instance->receive_tasklet); dbg ("udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)", new, new->max_pdu); @@ -994,9 +913,9 @@ list_del (&vcc_data->list); tasklet_enable (&instance->receive_tasklet); - if (vcc_data->reasBuffer) - kfree_skb (vcc_data->reasBuffer); - vcc_data->reasBuffer = NULL; + if (vcc_data->skb) + dev_kfree_skb (vcc_data->skb); + vcc_data->skb = NULL; kfree (vcc_data); vcc->dev_data = NULL; @@ -1041,7 +960,9 @@ instance->firmware_loaded = 1; } up (&instance->serialize); - udsl_fire_receivers (instance); + + tasklet_schedule (&instance->receive_tasklet); + return 0; } @@ -1057,10 +978,10 @@ } switch (code) { - case UDSL_IOCTL_START: + case UDSL_IOCTL_LINE_UP: instance->atm_dev->signal = ATM_PHY_SIG_FOUND; return udsl_set_alternate (instance); - case UDSL_IOCTL_STOP: + case UDSL_IOCTL_LINE_DOWN: instance->atm_dev->signal = ATM_PHY_SIG_LOST; return 0; default: @@ -1101,31 +1022,25 @@ INIT_LIST_HEAD (&instance->vcc_list); - spin_lock_init (&instance->spare_receivers_lock); + spin_lock_init (&instance->receive_lock); INIT_LIST_HEAD (&instance->spare_receivers); - - spin_lock_init (&instance->completed_receivers_lock); - INIT_LIST_HEAD (&instance->completed_receivers); + INIT_LIST_HEAD (&instance->filled_receive_buffers); tasklet_init (&instance->receive_tasklet, udsl_process_receive, (unsigned long) instance); + INIT_LIST_HEAD (&instance->spare_receive_buffers); skb_queue_head_init (&instance->sndqueue); spin_lock_init (&instance->send_lock); INIT_LIST_HEAD (&instance->spare_senders); - INIT_LIST_HEAD (&instance->spare_buffers); + INIT_LIST_HEAD (&instance->spare_send_buffers); tasklet_init (&instance->send_tasklet, udsl_process_send, (unsigned long) instance); - INIT_LIST_HEAD (&instance->filled_buffers); + INIT_LIST_HEAD (&instance->filled_send_buffers); /* receive init */ - for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { - struct udsl_receiver *rcv = &(instance->all_receivers[i]); - - if (!(rcv->skb = dev_alloc_skb (UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE))) { - dbg ("udsl_usb_probe: no memory for skb %d!", i); - goto fail; - } + for (i = 0; i < UDSL_NUM_RCV_URBS; i++) { + struct udsl_receiver *rcv = &(instance->receivers [i]); if (!(rcv->urb = usb_alloc_urb (0, GFP_KERNEL))) { dbg ("udsl_usb_probe: no memory for receive urb %d!", i); @@ -1135,13 +1050,22 @@ rcv->instance = instance; list_add (&rcv->list, &instance->spare_receivers); + } + + for (i = 0; i < UDSL_NUM_RCV_BUFS; i++) { + struct udsl_receive_buffer *buf = &(instance->receive_buffers [i]); + + if (!(buf->base = kmalloc (UDSL_RCV_BUF_SIZE * ATM_CELL_SIZE, GFP_KERNEL))) { + dbg ("udsl_usb_probe: no memory for receive buffer %d!", i); + goto fail; + } - dbg ("udsl_usb_probe: skb->truesize = %d (asked for %d)", rcv->skb->truesize, UDSL_RCV_BUF_SIZE * ATM_CELL_SIZE); + list_add (&buf->list, &instance->spare_receive_buffers); } /* send init */ - for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) { - struct udsl_sender *snd = &(instance->all_senders[i]); + for (i = 0; i < UDSL_NUM_SND_URBS; i++) { + struct udsl_sender *snd = &(instance->senders [i]); if (!(snd->urb = usb_alloc_urb (0, GFP_KERNEL))) { dbg ("udsl_usb_probe: no memory for send urb %d!", i); @@ -1153,18 +1077,18 @@ list_add (&snd->list, &instance->spare_senders); } - for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) { - struct udsl_send_buffer *buf = &(instance->all_buffers[i]); + for (i = 0; i < UDSL_NUM_SND_BUFS; i++) { + struct udsl_send_buffer *buf = &(instance->send_buffers [i]); - if (!(buf->base = kmalloc (UDSL_SND_BUFFER_SIZE * ATM_CELL_SIZE, GFP_KERNEL))) { + if (!(buf->base = kmalloc (UDSL_SND_BUF_SIZE * ATM_CELL_SIZE, GFP_KERNEL))) { dbg ("udsl_usb_probe: no memory for send buffer %d!", i); goto fail; } - list_add (&buf->list, &instance->spare_buffers); + list_add (&buf->list, &instance->spare_send_buffers); } - /* atm init */ + /* ATM init */ if (!(instance->atm_dev = atm_dev_register (udsl_driver_name, &udsl_atm_devops, -1, 0))) { dbg ("udsl_usb_probe: failed to register ATM device!"); goto fail; @@ -1174,14 +1098,14 @@ instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX; instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN; - /* tmp init atm device, set to 128kbit */ + /* temp init ATM device, set to 128kbit */ instance->atm_dev->link_rate = 128 * 1000 / 424; /* set MAC address, it is stored in the serial number */ memset (instance->atm_dev->esi, 0, sizeof (instance->atm_dev->esi)); if (usb_string (dev, dev->descriptor.iSerialNumber, mac_str, sizeof (mac_str)) == 12) for (i = 0; i < 6; i++) - instance->atm_dev->esi[i] = (hex2int (mac_str[i * 2]) * 16) + (hex2int (mac_str[i * 2 + 1])); + instance->atm_dev->esi [i] = (hex2int (mac_str [i * 2]) * 16) + (hex2int (mac_str [i * 2 + 1])); /* device description */ buf = instance->description; @@ -1215,20 +1139,17 @@ return 0; fail: - for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) - kfree (instance->all_buffers[i].base); + for (i = 0; i < UDSL_NUM_SND_BUFS; i++) + kfree (instance->send_buffers [i].base); - for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) - usb_free_urb (instance->all_senders[i].urb); + for (i = 0; i < UDSL_NUM_SND_URBS; i++) + usb_free_urb (instance->senders [i].urb); - for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { - struct udsl_receiver *rcv = &(instance->all_receivers[i]); + for (i = 0; i < UDSL_NUM_RCV_BUFS; i++) + kfree (instance->receive_buffers [i].base); - usb_free_urb (rcv->urb); - - if (rcv->skb) - kfree_skb (rcv->skb); - } + for (i = 0; i < UDSL_NUM_RCV_URBS; i++) + usb_free_urb (instance->receivers [i].urb); kfree (instance); @@ -1239,7 +1160,7 @@ { struct udsl_instance_data *instance = usb_get_intfdata (intf); struct list_head *pos; - unsigned int count = 0; + unsigned int count; int result, i; dbg ("udsl_usb_disconnect entered"); @@ -1251,38 +1172,25 @@ return; } - tasklet_disable (&instance->receive_tasklet); - /* receive finalize */ - down (&instance->serialize); /* vs udsl_fire_receivers */ - /* no need to take the spinlock */ - list_for_each (pos, &instance->spare_receivers) - if (++count > UDSL_NUMBER_RCV_URBS) - panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); - INIT_LIST_HEAD (&instance->spare_receivers); - up (&instance->serialize); - - dbg ("udsl_usb_disconnect: flushed %u spare receivers", count); - - count = UDSL_NUMBER_RCV_URBS - count; + tasklet_disable (&instance->receive_tasklet); - for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) - if ((result = usb_unlink_urb (instance->all_receivers[i].urb)) < 0) + for (i = 0; i < UDSL_NUM_RCV_URBS; i++) + if ((result = usb_unlink_urb (instance->receivers [i].urb)) < 0) dbg ("udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d", i, result); /* wait for completion handlers to finish */ do { - unsigned int completed = 0; - - spin_lock_irq (&instance->completed_receivers_lock); - list_for_each (pos, &instance->completed_receivers) - if (++completed > count) + count = 0; + spin_lock_irq (&instance->receive_lock); + list_for_each (pos, &instance->spare_receivers) + if (++count > UDSL_NUM_RCV_URBS) panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); - spin_unlock_irq (&instance->completed_receivers_lock); + spin_unlock_irq (&instance->receive_lock); - dbg ("udsl_usb_disconnect: found %u completed receivers", completed); + dbg ("udsl_usb_disconnect: found %u spare receivers", count); - if (completed == count) + if (count == UDSL_NUM_RCV_URBS) break; set_current_state (TASK_RUNNING); @@ -1290,37 +1198,36 @@ } while (1); /* no need to take the spinlock */ - INIT_LIST_HEAD (&instance->completed_receivers); + INIT_LIST_HEAD (&instance->filled_receive_buffers); + INIT_LIST_HEAD (&instance->spare_receive_buffers); tasklet_enable (&instance->receive_tasklet); - tasklet_kill (&instance->receive_tasklet); - for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { - struct udsl_receiver *rcv = &(instance->all_receivers[i]); + for (i = 0; i < UDSL_NUM_RCV_URBS; i++) + usb_free_urb (instance->receivers [i].urb); - usb_free_urb (rcv->urb); - kfree_skb (rcv->skb); - } + for (i = 0; i < UDSL_NUM_RCV_BUFS; i++) + kfree (instance->receive_buffers [i].base); /* send finalize */ tasklet_disable (&instance->send_tasklet); - for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) - if ((result = usb_unlink_urb (instance->all_senders[i].urb)) < 0) + for (i = 0; i < UDSL_NUM_SND_URBS; i++) + if ((result = usb_unlink_urb (instance->senders [i].urb)) < 0) dbg ("udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d", i, result); /* wait for completion handlers to finish */ do { count = 0; - spin_lock (&instance->send_lock); + spin_lock_irq (&instance->send_lock); list_for_each (pos, &instance->spare_senders) - if (++count > UDSL_NUMBER_SND_URBS) + if (++count > UDSL_NUM_SND_URBS) panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); - spin_unlock (&instance->send_lock); + spin_unlock_irq (&instance->send_lock); dbg ("udsl_usb_disconnect: found %u spare senders", count); - if (count == UDSL_NUMBER_SND_URBS) + if (count == UDSL_NUM_SND_URBS) break; set_current_state (TASK_RUNNING); @@ -1329,22 +1236,22 @@ /* no need to take the spinlock */ INIT_LIST_HEAD (&instance->spare_senders); - INIT_LIST_HEAD (&instance->spare_buffers); + INIT_LIST_HEAD (&instance->spare_send_buffers); instance->current_buffer = NULL; tasklet_enable (&instance->send_tasklet); - for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) - usb_free_urb (instance->all_senders[i].urb); + for (i = 0; i < UDSL_NUM_SND_URBS; i++) + usb_free_urb (instance->senders [i].urb); - for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) - kfree (instance->all_buffers[i].base); + for (i = 0; i < UDSL_NUM_SND_BUFS; i++) + kfree (instance->send_buffers [i].base); wmb (); instance->usb_dev = NULL; - /* atm finalize */ - shutdown_atm_dev (instance->atm_dev); /* frees instance */ + /* ATM finalize */ + shutdown_atm_dev (instance->atm_dev); /* frees instance, kills tasklets */ } @@ -1392,10 +1299,10 @@ int i = 0, j = 0; for (i = 0; i < len;) { - buffer[0] = '\0'; + buffer [0] = '\0'; sprintf (buffer, "%.3d :", i); for (j = 0; (j < 16) && (i < len); j++, i++) { - sprintf (buffer, "%s %2.2x", buffer, data[i]); + sprintf (buffer, "%s %2.2x", buffer, data [i]); } dbg ("%s", buffer); } diff -urN linux-2.5.69-bk16/drivers/usb/storage/transport.c linux-2.5.69-bk17/drivers/usb/storage/transport.c --- linux-2.5.69-bk16/drivers/usb/storage/transport.c 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/usb/storage/transport.c 2003-05-24 04:33:34.000000000 -0700 @@ -988,7 +988,7 @@ US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n", le32_to_cpu(bcs.Signature), bcs.Tag, bcs.Residue, bcs.Status); - if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) || + if ((bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) && bcs.Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) || bcs.Tag != bcb.Tag || bcs.Status > US_BULK_STAT_PHASE) { US_DEBUGP("Bulk logical error\n"); diff -urN linux-2.5.69-bk16/drivers/usb/storage/transport.h linux-2.5.69-bk17/drivers/usb/storage/transport.h --- linux-2.5.69-bk16/drivers/usb/storage/transport.h 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/drivers/usb/storage/transport.h 2003-05-24 04:33:34.000000000 -0700 @@ -105,6 +105,8 @@ #define US_BULK_CS_WRAP_LEN 13 #define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ +/* This is for Olympus Camedia digital cameras */ +#define US_BULK_CS_OLYMPUS_SIGN 0x55425355 /* spells out 'USBU' */ #define US_BULK_STAT_OK 0 #define US_BULK_STAT_FAIL 1 #define US_BULK_STAT_PHASE 2 diff -urN linux-2.5.69-bk16/include/acpi/acconfig.h linux-2.5.69-bk17/include/acpi/acconfig.h --- linux-2.5.69-bk16/include/acpi/acconfig.h 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acconfig.h 2003-05-24 04:33:34.000000000 -0700 @@ -64,7 +64,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20030418 +#define ACPI_CA_VERSION 0x20030522 /* Maximum objects in the various object caches */ @@ -133,6 +133,11 @@ #define ACPI_MAX_STRING_CONVERSION 200 +/* Length of _HID, _UID, and _CID values */ + +#define ACPI_DEVICE_ID_LENGTH 0x09 +#define ACPI_MAX_CID_LENGTH 48 + /* * Operand Stack (in WALK_STATE), Must be large enough to contain METHOD_MAX_ARG */ diff -urN linux-2.5.69-bk16/include/acpi/acdebug.h linux-2.5.69-bk17/include/acpi/acdebug.h --- linux-2.5.69-bk16/include/acpi/acdebug.h 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acdebug.h 2003-05-24 04:33:34.000000000 -0700 @@ -230,10 +230,6 @@ char *output_type); void -acpi_db_decode_node ( - struct acpi_namespace_node *node); - -void acpi_db_display_result_object ( union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state); @@ -243,11 +239,6 @@ char *display_count_arg); void -acpi_db_display_internal_object ( - union acpi_operand_object *obj_desc, - struct acpi_walk_state *walk_state); - -void acpi_db_display_arguments ( void); @@ -264,6 +255,10 @@ void); void +acpi_db_display_object_type ( + char *object_arg); + +void acpi_db_display_argument_object ( union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state); @@ -276,10 +271,6 @@ acpi_db_get_pointer ( void *target); -void -acpi_db_decode_internal_object ( - union acpi_operand_object *obj_desc); - /* * dbexec - debugger control method execution diff -urN linux-2.5.69-bk16/include/acpi/acdisasm.h linux-2.5.69-bk17/include/acpi/acdisasm.h --- linux-2.5.69-bk16/include/acpi/acdisasm.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.69-bk17/include/acpi/acdisasm.h 2003-05-24 04:33:34.000000000 -0700 @@ -0,0 +1,406 @@ +/****************************************************************************** + * + * Name: acdisasm.h - AML disassembler + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2003, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACDISASM_H__ +#define __ACDISASM_H__ + +#include "amlresrc.h" + + +#define BLOCK_NONE 0 +#define BLOCK_PAREN 1 +#define BLOCK_BRACE 2 +#define BLOCK_COMMA_LIST 4 + +extern const char *acpi_gbl_io_decode[2]; +extern const char *acpi_gbl_word_decode[4]; +extern const char *acpi_gbl_consume_decode[2]; +extern const char *acpi_gbl_min_decode[2]; +extern const char *acpi_gbl_max_decode[2]; +extern const char *acpi_gbl_DECdecode[2]; +extern const char *acpi_gbl_RNGdecode[4]; +extern const char *acpi_gbl_MEMdecode[4]; +extern const char *acpi_gbl_RWdecode[2]; +extern const char *acpi_gbl_irq_decode[2]; +extern const char *acpi_gbl_HEdecode[2]; +extern const char *acpi_gbl_LLdecode[2]; +extern const char *acpi_gbl_SHRdecode[2]; +extern const char *acpi_gbl_TYPdecode[4]; +extern const char *acpi_gbl_BMdecode[2]; +extern const char *acpi_gbl_SIZdecode[4]; +extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES]; +extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES]; +extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES]; +extern const char *acpi_gbl_match_ops[ACPI_NUM_MATCH_OPS]; + + +struct acpi_op_walk_info +{ + u32 level; + u32 bit_offset; +}; + +typedef +acpi_status (*asl_walk_callback) ( + union acpi_parse_object *op, + u32 level, + void *context); + + +/* + * dmwalk + */ + +void +acpi_dm_walk_parse_tree ( + union acpi_parse_object *op, + asl_walk_callback descending_callback, + asl_walk_callback ascending_callback, + void *context); + +acpi_status +acpi_dm_descending_op ( + union acpi_parse_object *op, + u32 level, + void *context); + +acpi_status +acpi_dm_ascending_op ( + union acpi_parse_object *op, + u32 level, + void *context); + + +/* + * dmopcode + */ + +void +acpi_dm_validate_name ( + char *name, + union acpi_parse_object *op); + +u32 +acpi_dm_dump_name ( + char *name); + +void +acpi_dm_unicode ( + union acpi_parse_object *op); + +void +acpi_dm_disassemble ( + struct acpi_walk_state *walk_state, + union acpi_parse_object *origin, + u32 num_opcodes); + +void +acpi_dm_namestring ( + char *name); + +void +acpi_dm_display_path ( + union acpi_parse_object *op); + +void +acpi_dm_disassemble_one_op ( + struct acpi_walk_state *walk_state, + struct acpi_op_walk_info *info, + union acpi_parse_object *op); + +void +acpi_dm_decode_internal_object ( + union acpi_operand_object *obj_desc); + +void +acpi_dm_decode_node ( + struct acpi_namespace_node *node); + +u32 +acpi_dm_block_type ( + union acpi_parse_object *op); + +u32 +acpi_dm_list_type ( + union acpi_parse_object *op); + +acpi_status +acpi_ps_display_object_pathname ( + struct acpi_walk_state *walk_state, + union acpi_parse_object *op); + +void +acpi_dm_method_flags ( + union acpi_parse_object *op); + +void +acpi_dm_field_flags ( + union acpi_parse_object *op); + +void +acpi_dm_address_space ( + u8 space_id); + +void +acpi_dm_region_flags ( + union acpi_parse_object *op); + +void +acpi_dm_match_op ( + union acpi_parse_object *op); + +void +acpi_dm_match_keyword ( + union acpi_parse_object *op); + +u8 +acpi_dm_comma_if_list_member ( + union acpi_parse_object *op); + +void +acpi_dm_comma_if_field_member ( + union acpi_parse_object *op); + + +/* + * dmobject + */ + +void +acpi_dm_decode_node ( + struct acpi_namespace_node *node); + +void +acpi_dm_display_internal_object ( + union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state); + +void +acpi_dm_display_arguments ( + struct acpi_walk_state *walk_state); + +void +acpi_dm_display_locals ( + struct acpi_walk_state *walk_state); + +void +acpi_dm_dump_method_info ( + acpi_status status, + struct acpi_walk_state *walk_state, + union acpi_parse_object *op); + + +/* + * dmbuffer + */ + +void +acpi_is_eisa_id ( + union acpi_parse_object *op); + +void +acpi_dm_eisa_id ( + u32 encoded_id); + +u8 +acpi_dm_is_unicode_buffer ( + union acpi_parse_object *op); + +u8 +acpi_dm_is_string_buffer ( + union acpi_parse_object *op); + + +/* + * dmresrc + */ + +void +acpi_dm_disasm_byte_list ( + u32 level, + u8 *byte_data, + u32 byte_count); + +void +acpi_dm_byte_list ( + struct acpi_op_walk_info *info, + union acpi_parse_object *op); + +void +acpi_dm_resource_descriptor ( + struct acpi_op_walk_info *info, + u8 *byte_data, + u32 byte_count); + +u8 +acpi_dm_is_resource_descriptor ( + union acpi_parse_object *op); + +void +acpi_dm_indent ( + u32 level); + +void +acpi_dm_bit_list ( + u16 mask); + +void +acpi_dm_decode_attribute ( + u8 attribute); + +/* + * dmresrcl + */ + +void +acpi_dm_io_flags ( + u8 flags); + +void +acpi_dm_memory_flags ( + u8 flags, + u8 specific_flags); + +void +acpi_dm_word_descriptor ( + struct asl_word_address_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_dword_descriptor ( + struct asl_dword_address_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_qword_descriptor ( + struct asl_qword_address_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_memory24_descriptor ( + struct asl_memory_24_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_memory32_descriptor ( + struct asl_memory_32_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_fixed_mem32_descriptor ( + struct asl_fixed_memory_32_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_generic_register_descriptor ( + struct asl_general_register_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_interrupt_descriptor ( + struct asl_extended_xrupt_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_vendor_large_descriptor ( + struct asl_large_vendor_desc *resource, + u32 length, + u32 level); + + +/* + * dmresrcs + */ + +void +acpi_dm_irq_descriptor ( + struct asl_irq_format_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_dma_descriptor ( + struct asl_dma_format_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_io_descriptor ( + struct asl_io_port_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_fixed_io_descriptor ( + struct asl_fixed_io_port_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_start_dependent_descriptor ( + struct asl_start_dependent_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_end_dependent_descriptor ( + struct asl_start_dependent_desc *resource, + u32 length, + u32 level); + +void +acpi_dm_vendor_small_descriptor ( + struct asl_small_vendor_desc *resource, + u32 length, + u32 level); + + +#endif /* __ACDISASM_H__ */ diff -urN linux-2.5.69-bk16/include/acpi/acevents.h linux-2.5.69-bk17/include/acpi/acevents.h --- linux-2.5.69-bk16/include/acpi/acevents.h 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acevents.h 2003-05-24 04:33:34.000000000 -0700 @@ -165,7 +165,7 @@ void *value); acpi_status -acpi_ev_addr_handler_helper ( +acpi_ev_install_handler ( acpi_handle obj_handle, u32 level, void *context, diff -urN linux-2.5.69-bk16/include/acpi/acexcep.h linux-2.5.69-bk17/include/acpi/acexcep.h --- linux-2.5.69-bk16/include/acpi/acexcep.h 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acexcep.h 2003-05-24 04:33:34.000000000 -0700 @@ -94,8 +94,9 @@ #define AE_NO_GLOBAL_LOCK (acpi_status) (0x001A | AE_CODE_ENVIRONMENTAL) #define AE_LOGICAL_ADDRESS (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL) #define AE_ABORT_METHOD (acpi_status) (0x001C | AE_CODE_ENVIRONMENTAL) +#define AE_SAME_HANDLER (acpi_status) (0x001D | AE_CODE_ENVIRONMENTAL) -#define AE_CODE_ENV_MAX 0x001C +#define AE_CODE_ENV_MAX 0x001D /* * Programmer exceptions @@ -219,7 +220,8 @@ "AE_NO_HARDWARE_RESPONSE", "AE_NO_GLOBAL_LOCK", "AE_LOGICAL_ADDRESS", - "AE_ABORT_METHOD" + "AE_ABORT_METHOD", + "AE_SAME_HANDLER" }; char const *acpi_gbl_exception_names_pgm[] = diff -urN linux-2.5.69-bk16/include/acpi/acglobal.h linux-2.5.69-bk17/include/acpi/acglobal.h --- linux-2.5.69-bk16/include/acpi/acglobal.h 2003-05-04 16:52:48.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acglobal.h 2003-05-24 04:33:34.000000000 -0700 @@ -105,6 +105,8 @@ */ ACPI_EXTERN u8 acpi_gbl_integer_bit_width; ACPI_EXTERN u8 acpi_gbl_integer_byte_width; +ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; +ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; /* * Since there may be multiple SSDTs and PSDTS, a single pointer is not @@ -115,15 +117,15 @@ /* * ACPI Table info arrays */ -extern struct acpi_table_desc acpi_gbl_acpi_tables[NUM_ACPI_TABLES]; -extern struct acpi_table_support acpi_gbl_acpi_table_data[NUM_ACPI_TABLES]; +extern struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES]; +extern struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES]; /* * Predefined mutex objects. This array contains the * actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs. * (The table maps local handles to the real OS handles) */ -ACPI_EXTERN struct acpi_mutex_info acpi_gbl_acpi_mutex_info [NUM_MTX]; +ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[NUM_MUTEX]; /***************************************************************************** @@ -134,8 +136,8 @@ ACPI_EXTERN struct acpi_memory_list acpi_gbl_memory_lists[ACPI_NUM_MEM_LISTS]; -ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_drv_notify; -ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_sys_notify; +ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify; +ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify; ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; ACPI_EXTERN acpi_handle acpi_gbl_global_lock_semaphore; @@ -200,7 +202,7 @@ ****************************************************************************/ -ACPI_EXTERN struct acpi_thread_state *acpi_gbl_current_walk_list; +ACPI_EXTERN struct acpi_thread_state *acpi_gbl_current_walk_list; /* Control method single step flag */ @@ -213,7 +215,7 @@ * ****************************************************************************/ -ACPI_EXTERN union acpi_parse_object *acpi_gbl_parsed_namespace_root; +ACPI_EXTERN union acpi_parse_object *acpi_gbl_parsed_namespace_root; /***************************************************************************** * @@ -234,8 +236,8 @@ extern struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS]; ACPI_EXTERN struct acpi_fixed_event_handler acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; -ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; -ACPI_EXTERN struct acpi_gpe_block_info *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; +ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; +ACPI_EXTERN struct acpi_gpe_block_info *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; ACPI_EXTERN acpi_handle acpi_gbl_gpe_lock; diff -urN linux-2.5.69-bk16/include/acpi/achware.h linux-2.5.69-bk17/include/acpi/achware.h --- linux-2.5.69-bk16/include/acpi/achware.h 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/achware.h 2003-05-24 04:33:34.000000000 -0700 @@ -98,15 +98,13 @@ acpi_hw_low_level_read ( u32 width, u32 *value, - struct acpi_generic_address *reg, - u32 offset); + struct acpi_generic_address *reg); acpi_status acpi_hw_low_level_write ( u32 width, u32 value, - struct acpi_generic_address *reg, - u32 offset); + struct acpi_generic_address *reg); acpi_status acpi_hw_clear_acpi_status ( diff -urN linux-2.5.69-bk16/include/acpi/aclocal.h linux-2.5.69-bk17/include/acpi/aclocal.h --- linux-2.5.69-bk16/include/acpi/aclocal.h 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/aclocal.h 2003-05-24 04:33:34.000000000 -0700 @@ -87,8 +87,8 @@ #define ACPI_MTX_DEBUG_CMD_COMPLETE 11 #define ACPI_MTX_DEBUG_CMD_READY 12 -#define MAX_MTX 12 -#define NUM_MTX MAX_MTX+1 +#define MAX_MUTEX 12 +#define NUM_MUTEX MAX_MUTEX+1 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) @@ -140,12 +140,8 @@ typedef u16 acpi_owner_id; #define ACPI_OWNER_TYPE_TABLE 0x0 #define ACPI_OWNER_TYPE_METHOD 0x1 -#define ACPI_FIRST_METHOD_ID 0x0000 -#define ACPI_FIRST_TABLE_ID 0x8000 - -/* TBD: [Restructure] get rid of the need for this! */ - -#define TABLE_ID_DSDT (acpi_owner_id) 0x8000 +#define ACPI_FIRST_METHOD_ID 0x0001 +#define ACPI_FIRST_TABLE_ID 0xF000 /* Field access granularities */ @@ -232,13 +228,18 @@ u64 physical_address; u32 aml_length; acpi_size length; - u32 count; acpi_owner_id table_id; u8 type; u8 allocation; u8 loaded_into_namespace; }; +struct acpi_table_list +{ + struct acpi_table_desc *next; + u32 count; +}; + struct acpi_find_context { @@ -855,16 +856,6 @@ #define ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE 0x8A -/* String version of device HIDs and UIDs */ - -#define ACPI_DEVICE_ID_LENGTH 0x09 - -struct acpi_device_id -{ - char buffer[ACPI_DEVICE_ID_LENGTH]; -}; - - /***************************************************************************** * * Miscellaneous diff -urN linux-2.5.69-bk16/include/acpi/acmacros.h linux-2.5.69-bk17/include/acpi/acmacros.h --- linux-2.5.69-bk16/include/acpi/acmacros.h 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acmacros.h 2003-05-24 04:33:34.000000000 -0700 @@ -441,26 +441,6 @@ /* - * Build a GAS structure from earlier ACPI table entries (V1.0 and 0.71 extensions) - * - * 1) Address space - * 2) Length in bytes -- convert to length in bits - * 3) Bit offset is zero - * 4) Reserved field is zero - * 5) Expand address to 64 bits - */ -#define ASL_BUILD_GAS_FROM_ENTRY(a,b,c,d) do {a.address_space_id = (u8) d;\ - a.register_bit_width = (u8) ACPI_MUL_8 (b);\ - a.register_bit_offset = 0;\ - a.reserved = 0;\ - ACPI_STORE_ADDRESS (a.address,(acpi_physical_address) c);} while (0) - -/* ACPI V1.0 entries -- address space is always I/O */ - -#define ASL_BUILD_GAS_FROM_V1_ENTRY(a,b,c) ASL_BUILD_GAS_FROM_ENTRY(a,b,c,ACPI_ADR_SPACE_SYSTEM_IO) - - -/* * Reporting macros that are never compiled out */ diff -urN linux-2.5.69-bk16/include/acpi/acnamesp.h linux-2.5.69-bk17/include/acpi/acnamesp.h --- linux-2.5.69-bk16/include/acpi/acnamesp.h 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acnamesp.h 2003-05-24 04:33:34.000000000 -0700 @@ -201,6 +201,11 @@ char *name1, char *name2); +void +acpi_ns_remove_reference ( + struct acpi_namespace_node *node); + + /* * Namespace modification - nsmodify */ diff -urN linux-2.5.69-bk16/include/acpi/acobject.h linux-2.5.69-bk17/include/acpi/acobject.h --- linux-2.5.69-bk16/include/acpi/acobject.h 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acobject.h 2003-05-24 04:33:34.000000000 -0700 @@ -112,9 +112,9 @@ * Common fields for objects that support ASL notifications */ #define ACPI_COMMON_NOTIFY_INFO \ - union acpi_operand_object *sys_handler; /* Handler for system notifies */\ - union acpi_operand_object *drv_handler; /* Handler for driver notifies */\ - union acpi_operand_object *addr_handler; /* Handler for Address space */ + union acpi_operand_object *system_notify; /* Handler for system notifies */\ + union acpi_operand_object *device_notify; /* Handler for driver notifies */\ + union acpi_operand_object *address_space; /* Handler for Address space */ /****************************************************************************** @@ -214,7 +214,7 @@ ACPI_OBJECT_COMMON_HEADER u8 space_id; - union acpi_operand_object *addr_handler; /* Handler for system notifies */ + union acpi_operand_object *address_space; /* Handler for region access */ struct acpi_namespace_node *node; /* containing object */ union acpi_operand_object *next; u32 length; @@ -446,8 +446,8 @@ struct acpi_object_buffer_field buffer_field; struct acpi_object_bank_field bank_field; struct acpi_object_index_field index_field; - struct acpi_object_notify_handler notify_handler; - struct acpi_object_addr_handler addr_handler; + struct acpi_object_notify_handler notify; + struct acpi_object_addr_handler address_space; struct acpi_object_reference reference; struct acpi_object_extra extra; struct acpi_object_data data; diff -urN linux-2.5.69-bk16/include/acpi/acpi_bus.h linux-2.5.69-bk17/include/acpi/acpi_bus.h --- linux-2.5.69-bk16/include/acpi/acpi_bus.h 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acpi_bus.h 2003-05-24 04:33:34.000000000 -0700 @@ -186,6 +186,7 @@ acpi_bus_id bus_id; /* Object name */ acpi_bus_address bus_address; /* _ADR */ acpi_hardware_id hardware_id; /* _HID */ + struct acpi_compatible_id_list *cid_list; /* _CIDs */ acpi_unique_id unique_id; /* _UID */ acpi_device_name device_name; /* Driver-determined */ acpi_device_class device_class; /* " */ diff -urN linux-2.5.69-bk16/include/acpi/acpiosxf.h linux-2.5.69-bk17/include/acpi/acpiosxf.h --- linux-2.5.69-bk16/include/acpi/acpiosxf.h 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acpiosxf.h 2003-05-24 04:33:34.000000000 -0700 @@ -290,12 +290,12 @@ u8 acpi_os_readable ( void *pointer, - u32 length); + acpi_size length); u8 acpi_os_writable ( void *pointer, - u32 length); + acpi_size length); u32 acpi_os_get_timer ( diff -urN linux-2.5.69-bk16/include/acpi/acpixf.h linux-2.5.69-bk17/include/acpi/acpixf.h --- linux-2.5.69-bk16/include/acpi/acpixf.h 2003-05-04 16:52:48.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acpixf.h 2003-05-24 04:33:34.000000000 -0700 @@ -228,8 +228,8 @@ acpi_status acpi_get_object_info ( - acpi_handle device, - struct acpi_device_info *info); + acpi_handle handle, + struct acpi_buffer *return_buffer); acpi_status acpi_get_next_object ( diff -urN linux-2.5.69-bk16/include/acpi/actables.h linux-2.5.69-bk17/include/acpi/actables.h --- linux-2.5.69-bk16/include/acpi/actables.h 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/actables.h 2003-05-24 04:33:34.000000000 -0700 @@ -157,7 +157,7 @@ acpi_status acpi_tb_recognize_table ( struct acpi_table_desc *table_info, - u8 search_type); + u8 search_type); acpi_status acpi_tb_init_table_descriptor ( @@ -170,11 +170,11 @@ */ void -acpi_tb_delete_acpi_tables ( +acpi_tb_delete_all_tables ( void); void -acpi_tb_delete_acpi_table ( +acpi_tb_delete_tables_by_type ( acpi_table_type type); void @@ -185,10 +185,6 @@ acpi_tb_uninstall_table ( struct acpi_table_desc *table_desc); -void -acpi_tb_free_acpi_tables_of_type ( - struct acpi_table_desc *table_info); - /* * tbrsd - RSDP, RSDT utilities diff -urN linux-2.5.69-bk16/include/acpi/actypes.h linux-2.5.69-bk17/include/acpi/actypes.h --- linux-2.5.69-bk16/include/acpi/actypes.h 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/actypes.h 2003-05-24 04:33:34.000000000 -0700 @@ -407,7 +407,7 @@ #define ACPI_TABLE_SSDT (acpi_table_type) 5 #define ACPI_TABLE_XSDT (acpi_table_type) 6 #define ACPI_TABLE_MAX 6 -#define NUM_ACPI_TABLES (ACPI_TABLE_MAX+1) +#define NUM_ACPI_TABLE_TYPES (ACPI_TABLE_MAX+1) /* @@ -747,7 +747,7 @@ u32 debug_level; u32 debug_layer; u32 num_table_types; - struct acpi_table_info table_info [NUM_ACPI_TABLES]; + struct acpi_table_info table_info [NUM_ACPI_TABLE_TYPES]; }; @@ -832,12 +832,35 @@ #define ACPI_INTERRUPT_HANDLED 0x01 -/* Structure and flags for acpi_get_device_info */ +/* Common string version of device HIDs and UIDs */ -#define ACPI_VALID_HID 0x1 -#define ACPI_VALID_UID 0x2 -#define ACPI_VALID_ADR 0x4 -#define ACPI_VALID_STA 0x8 +struct acpi_device_id +{ + char value[ACPI_DEVICE_ID_LENGTH]; +}; + +/* Common string version of device CIDs */ + +struct acpi_compatible_id +{ + char value[ACPI_MAX_CID_LENGTH]; +}; + +struct acpi_compatible_id_list +{ + u32 count; + u32 size; + struct acpi_compatible_id id[1]; +}; + + +/* Structure and flags for acpi_get_object_info */ + +#define ACPI_VALID_STA 0x0001 +#define ACPI_VALID_ADR 0x0002 +#define ACPI_VALID_HID 0x0004 +#define ACPI_VALID_UID 0x0008 +#define ACPI_VALID_CID 0x0010 #define ACPI_COMMON_OBJ_INFO \ @@ -851,15 +874,18 @@ }; +/* Structure returned from Get Object Info */ + struct acpi_device_info { ACPI_COMMON_OBJ_INFO; - u32 valid; /* Are the next bits legit? */ - char hardware_id[9]; /* _HID value if any */ - char unique_id[9]; /* _UID value if any */ - acpi_integer address; /* _ADR value if any */ - u32 current_status; /* _STA value */ + u32 valid; /* Indicates which fields are valid */ + u32 current_status; /* _STA value */ + acpi_integer address; /* _ADR value if any */ + struct acpi_device_id hardware_id; /* _HID value if any */ + struct acpi_device_id unique_id; /* _UID value if any */ + struct acpi_compatible_id_list compatibility_id; /* List of _CIDs if any */ }; diff -urN linux-2.5.69-bk16/include/acpi/acutils.h linux-2.5.69-bk17/include/acpi/acutils.h --- linux-2.5.69-bk16/include/acpi/acutils.h 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk17/include/acpi/acutils.h 2003-05-24 04:33:34.000000000 -0700 @@ -488,7 +488,7 @@ acpi_status acpi_ut_execute_CID ( struct acpi_namespace_node *device_node, - struct acpi_device_id *cid); + struct acpi_compatible_id_list **return_cid_list); acpi_status acpi_ut_execute_STA ( diff -urN linux-2.5.69-bk16/include/acpi/amlresrc.h linux-2.5.69-bk17/include/acpi/amlresrc.h --- linux-2.5.69-bk16/include/acpi/amlresrc.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.69-bk17/include/acpi/amlresrc.h 2003-05-24 04:33:34.000000000 -0700 @@ -0,0 +1,329 @@ + +/****************************************************************************** + * + * Module Name: amlresrc.h - AML resource descriptors + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2003, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#ifndef __AMLRESRC_H +#define __AMLRESRC_H + + +#define ASL_RESNAME_ADDRESS "_ADR" +#define ASL_RESNAME_ALIGNMENT "_ALN" +#define ASL_RESNAME_ADDRESSSPACE "_ASI" +#define ASL_RESNAME_BASEADDRESS "_BAS" +#define ASL_RESNAME_BUSMASTER "_BM_" /* Master(1), Slave(0) */ +#define ASL_RESNAME_DECODE "_DEC" +#define ASL_RESNAME_DMA "_DMA" +#define ASL_RESNAME_DMATYPE "_TYP" /* Compatible(0), A(1), B(2), F(3) */ +#define ASL_RESNAME_GRANULARITY "_GRA" +#define ASL_RESNAME_INTERRUPT "_INT" +#define ASL_RESNAME_INTERRUPTLEVEL "_LL_" /* active_lo(1), active_hi(0) */ +#define ASL_RESNAME_INTERRUPTSHARE "_SHR" /* Shareable(1), no_share(0) */ +#define ASL_RESNAME_INTERRUPTTYPE "_HE_" /* Edge(1), Level(0) */ +#define ASL_RESNAME_LENGTH "_LEN" +#define ASL_RESNAME_MEMATTRIBUTES "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */ +#define ASL_RESNAME_MEMTYPE "_MEM" /* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */ +#define ASL_RESNAME_MAXADDR "_MAX" +#define ASL_RESNAME_MINADDR "_MIN" +#define ASL_RESNAME_MAXTYPE "_MAF" +#define ASL_RESNAME_MINTYPE "_MIF" +#define ASL_RESNAME_REGISTERBITOFFSET "_RBO" +#define ASL_RESNAME_REGISTERBITWIDTH "_RBW" +#define ASL_RESNAME_RANGETYPE "_RNG" +#define ASL_RESNAME_READWRITETYPE "_RW_" /* read_only(0), Writeable (1) */ +#define ASL_RESNAME_TRANSLATION "_TRA" +#define ASL_RESNAME_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */ +#define ASL_RESNAME_TYPE "_TTP" /* Translation(1), Static (0) */ +#define ASL_RESNAME_XFERTYPE "_SIz" /* 8(0), 8_and16(1), 16(2) */ + + +/* Default sizes for "small" resource descriptors */ + +#define ASL_RDESC_IRQ_SIZE 0x02 +#define ASL_RDESC_DMA_SIZE 0x02 +#define ASL_RDESC_ST_DEPEND_SIZE 0x00 +#define ASL_RDESC_END_DEPEND_SIZE 0x00 +#define ASL_RDESC_IO_SIZE 0x07 +#define ASL_RDESC_FIXED_IO_SIZE 0x03 +#define ASL_RDESC_END_TAG_SIZE 0x01 + + +struct asl_resource_node +{ + u32 buffer_length; + void *buffer; + struct asl_resource_node *next; +}; + + +/* + * Resource descriptors defined in the ACPI specification. + * + * Alignment must be BYTE because these descriptors + * are used to overlay the AML byte stream. + */ +#pragma pack(1) + +struct asl_irq_format_desc +{ + u8 descriptor_type; + u16 irq_mask; + u8 flags; +}; + + +struct asl_irq_noflags_desc +{ + u8 descriptor_type; + u16 irq_mask; +}; + + +struct asl_dma_format_desc +{ + u8 descriptor_type; + u8 dma_channel_mask; + u8 flags; +}; + + +struct asl_start_dependent_desc +{ + u8 descriptor_type; + u8 flags; +}; + + +struct asl_start_dependent_noprio_desc +{ + u8 descriptor_type; +}; + + +struct asl_end_dependent_desc +{ + u8 descriptor_type; +}; + + +struct asl_io_port_desc +{ + u8 descriptor_type; + u8 information; + u16 address_min; + u16 address_max; + u8 alignment; + u8 length; +}; + + +struct asl_fixed_io_port_desc +{ + u8 descriptor_type; + u16 base_address; + u8 length; +}; + + +struct asl_small_vendor_desc +{ + u8 descriptor_type; + u8 vendor_defined[7]; +}; + + +struct asl_end_tag_desc +{ + u8 descriptor_type; + u8 checksum; +}; + + +/* LARGE descriptors */ + +struct asl_memory_24_desc +{ + u8 descriptor_type; + u16 length; + u8 information; + u16 address_min; + u16 address_max; + u16 alignment; + u16 range_length; +}; + + +struct asl_large_vendor_desc +{ + u8 descriptor_type; + u16 length; + u8 vendor_defined[1]; +}; + + +struct asl_memory_32_desc +{ + u8 descriptor_type; + u16 length; + u8 information; + u32 address_min; + u32 address_max; + u32 alignment; + u32 range_length; +}; + + +struct asl_fixed_memory_32_desc +{ + u8 descriptor_type; + u16 length; + u8 information; + u32 base_address; + u32 range_length; +}; + + +struct asl_qword_address_desc +{ + u8 descriptor_type; + u16 length; + u8 resource_type; + u8 flags; + u8 specific_flags; + u64 granularity; + u64 address_min; + u64 address_max; + u64 translation_offset; + u64 address_length; + u8 optional_fields[2]; +}; + + +struct asl_dword_address_desc +{ + u8 descriptor_type; + u16 length; + u8 resource_type; + u8 flags; + u8 specific_flags; + u32 granularity; + u32 address_min; + u32 address_max; + u32 translation_offset; + u32 address_length; + u8 optional_fields[2]; +}; + + +struct asl_word_address_desc +{ + u8 descriptor_type; + u16 length; + u8 resource_type; + u8 flags; + u8 specific_flags; + u16 granularity; + u16 address_min; + u16 address_max; + u16 translation_offset; + u16 address_length; + u8 optional_fields[2]; +}; + + +struct asl_extended_xrupt_desc +{ + u8 descriptor_type; + u16 length; + u8 flags; + u8 table_length; + u32 interrupt_number[1]; + /* res_source_index, res_source optional fields follow */ +}; + + +struct asl_general_register_desc +{ + u8 descriptor_type; + u16 length; + u8 address_space_id; + u8 bit_width; + u8 bit_offset; + u8 reserved; + u64 address; +}; + +/* restore default alignment */ + +#pragma pack() + +/* Union of all resource descriptors, sow we can allocate the worst case */ + +union asl_resource_desc +{ + struct asl_irq_format_desc irq; + struct asl_dma_format_desc dma; + struct asl_start_dependent_desc std; + struct asl_end_dependent_desc end; + struct asl_io_port_desc iop; + struct asl_fixed_io_port_desc fio; + struct asl_small_vendor_desc smv; + struct asl_end_tag_desc et; + + struct asl_memory_24_desc M24; + struct asl_large_vendor_desc lgv; + struct asl_memory_32_desc M32; + struct asl_fixed_memory_32_desc F32; + struct asl_qword_address_desc qas; + struct asl_dword_address_desc das; + struct asl_word_address_desc was; + struct asl_extended_xrupt_desc exx; + struct asl_general_register_desc grg; + u32 u32_item; + u16 u16_item; + u8 U8item; +}; + + +#endif + diff -urN linux-2.5.69-bk16/include/asm-x86_64/apic.h linux-2.5.69-bk17/include/asm-x86_64/apic.h --- linux-2.5.69-bk16/include/asm-x86_64/apic.h 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/apic.h 2003-05-24 04:33:34.000000000 -0700 @@ -9,7 +9,7 @@ #ifdef CONFIG_X86_LOCAL_APIC -#define APIC_DEBUG 1 +#define APIC_DEBUG 0 #if APIC_DEBUG #define Dprintk(x...) printk(x) diff -urN linux-2.5.69-bk16/include/asm-x86_64/calling.h linux-2.5.69-bk17/include/asm-x86_64/calling.h --- linux-2.5.69-bk16/include/asm-x86_64/calling.h 2003-05-04 16:53:33.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/calling.h 2003-05-24 04:33:34.000000000 -0700 @@ -84,8 +84,9 @@ movq \offset+72(%rsp),%rax .endm +#define REST_SKIP 6*8 .macro SAVE_REST - subq $6*8,%rsp + subq $REST_SKIP,%rsp movq %rbx,5*8(%rsp) movq %rbp,4*8(%rsp) movq %r12,3*8(%rsp) @@ -94,7 +95,6 @@ movq %r15,(%rsp) .endm -#define REST_SKIP 6*8 .macro RESTORE_REST movq (%rsp),%r15 movq 1*8(%rsp),%r14 diff -urN linux-2.5.69-bk16/include/asm-x86_64/compat.h linux-2.5.69-bk17/include/asm-x86_64/compat.h --- linux-2.5.69-bk16/include/asm-x86_64/compat.h 2003-05-24 04:33:29.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/compat.h 2003-05-24 04:33:34.000000000 -0700 @@ -1,9 +1,11 @@ #ifndef _ASM_X86_64_COMPAT_H #define _ASM_X86_64_COMPAT_H + /* * Architecture specific compatibility types */ #include +#include #define COMPAT_USER_HZ 100 diff -urN linux-2.5.69-bk16/include/asm-x86_64/debugreg.h linux-2.5.69-bk17/include/asm-x86_64/debugreg.h --- linux-2.5.69-bk16/include/asm-x86_64/debugreg.h 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/debugreg.h 2003-05-24 04:33:34.000000000 -0700 @@ -58,7 +58,7 @@ We can slow the instruction pipeline for instructions coming via the gdt or the ldt if we want to. I am not sure why this is an advantage */ -#define DR_CONTROL_RESERVED (0xFFFFFFFFFC00) /* Reserved by Intel */ +#define DR_CONTROL_RESERVED (0xFFFFFFFF0000FC00UL) /* Reserved */ #define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ #define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ diff -urN linux-2.5.69-bk16/include/asm-x86_64/e820.h linux-2.5.69-bk17/include/asm-x86_64/e820.h --- linux-2.5.69-bk16/include/asm-x86_64/e820.h 2003-05-04 16:53:34.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/e820.h 2003-05-24 04:33:34.000000000 -0700 @@ -50,7 +50,7 @@ extern unsigned long e820_end_of_ram(void); extern void e820_reserve_resources(void); extern void e820_print_map(char *who); -extern int e820_mapped(unsigned long start, unsigned long end, int type); +extern int e820_mapped(unsigned long start, unsigned long end, unsigned type); extern void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end); diff -urN linux-2.5.69-bk16/include/asm-x86_64/floppy.h linux-2.5.69-bk17/include/asm-x86_64/floppy.h --- linux-2.5.69-bk16/include/asm-x86_64/floppy.h 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/floppy.h 2003-05-24 04:33:34.000000000 -0700 @@ -64,7 +64,7 @@ #endif if(!doing_pdma) { floppy_interrupt(irq, dev_id, regs); - return; + return IRQ_HANDLED; } #ifdef TRACE_FLPY_INT @@ -96,7 +96,7 @@ calls++; #endif if(st == 0x20) - return; + return IRQ_HANDLED; if(!(st & 0x20)) { virtual_dma_residue += virtual_dma_count; virtual_dma_count=0; diff -urN linux-2.5.69-bk16/include/asm-x86_64/i387.h linux-2.5.69-bk17/include/asm-x86_64/i387.h --- linux-2.5.69-bk16/include/asm-x86_64/i387.h 2003-05-04 16:53:29.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/i387.h 2003-05-24 04:33:34.000000000 -0700 @@ -17,6 +17,7 @@ #include #include #include +#include extern void fpu_init(void); extern void init_fpu(struct task_struct *child); @@ -91,6 +92,8 @@ ".previous" : [err] "=r" (err) : [fx] "r" (fx), "0" (0)); + if (unlikely(err)) + init_fpu(current); return err; } @@ -109,6 +112,8 @@ ".previous" : [err] "=r" (err) : [fx] "r" (fx), "0" (0)); + if (unlikely(err)) + __clear_user(fx, sizeof(struct i387_fxsave_struct)); return err; } diff -urN linux-2.5.69-bk16/include/asm-x86_64/ia32.h linux-2.5.69-bk17/include/asm-x86_64/ia32.h --- linux-2.5.69-bk16/include/asm-x86_64/ia32.h 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/ia32.h 2003-05-24 04:33:34.000000000 -0700 @@ -133,6 +133,25 @@ } _sifields; } siginfo_t32; +struct sigframe32 +{ + u32 pretcode; + int sig; + struct sigcontext_ia32 sc; + struct _fpstate_ia32 fpstate; + unsigned int extramask[_COMPAT_NSIG_WORDS-1]; +}; + +struct rt_sigframe32 +{ + u32 pretcode; + int sig; + u32 pinfo; + u32 puc; + struct siginfo32 info; + struct ucontext_ia32 uc; + struct _fpstate_ia32 fpstate; +}; struct ustat32 { __u32 f_tfree; diff -urN linux-2.5.69-bk16/include/asm-x86_64/io.h linux-2.5.69-bk17/include/asm-x86_64/io.h --- linux-2.5.69-bk16/include/asm-x86_64/io.h 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/io.h 2003-05-24 04:33:34.000000000 -0700 @@ -120,6 +120,7 @@ #define __io_virt(x) ((void *)(x)) #endif +#ifndef __i386__ /* * Change virtual addresses to physical addresses and vv. * These are pretty trivial @@ -133,6 +134,7 @@ { return __va(address); } +#endif /* * Change "struct page" to physical address. @@ -259,6 +261,7 @@ return retval; } +#ifndef __i386__ /** * isa_check_signature - find BIOS signatures * @io_addr: mmio address to check @@ -288,6 +291,7 @@ out: return retval; } +#endif /* Nothing to do */ diff -urN linux-2.5.69-bk16/include/asm-x86_64/irq.h linux-2.5.69-bk17/include/asm-x86_64/irq.h --- linux-2.5.69-bk16/include/asm-x86_64/irq.h 2003-05-04 16:52:48.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/irq.h 2003-05-24 04:33:34.000000000 -0700 @@ -32,4 +32,8 @@ extern void disable_irq_nosync(unsigned int); extern void enable_irq(unsigned int); +#ifdef CONFIG_X86_LOCAL_APIC +#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ +#endif + #endif /* _ASM_IRQ_H */ diff -urN linux-2.5.69-bk16/include/asm-x86_64/page.h linux-2.5.69-bk17/include/asm-x86_64/page.h --- linux-2.5.69-bk16/include/asm-x86_64/page.h 2003-05-04 16:53:00.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/page.h 2003-05-24 04:33:34.000000000 -0700 @@ -58,9 +58,13 @@ #define __pte(x) ((pte_t) { (x) } ) #define __pmd(x) ((pmd_t) { (x) } ) #define __pgd(x) ((pgd_t) { (x) } ) -#define __level4(x) ((level4_t) { (x) } ) +#define __pml4(x) ((pml4_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } ) +extern unsigned long vm_stack_flags, vm_stack_flags32; +extern unsigned long vm_data_default_flags, vm_data_default_flags32; +extern unsigned long vm_force_exec32; + #endif /* !__ASSEMBLY__ */ /* to align the pointer to the (next) page boundary */ @@ -119,9 +123,19 @@ #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) -#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ +#define __VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#define __VM_STACK_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#define VM_DATA_DEFAULT_FLAGS \ + (test_thread_flag(TIF_IA32) ? vm_data_default_flags32 : \ + vm_data_default_flags) + +#define VM_STACK_DEFAULT_FLAGS \ + (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags) + + #endif /* __KERNEL__ */ #endif /* _X86_64_PAGE_H */ diff -urN linux-2.5.69-bk16/include/asm-x86_64/pci.h linux-2.5.69-bk17/include/asm-x86_64/pci.h --- linux-2.5.69-bk16/include/asm-x86_64/pci.h 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/pci.h 2003-05-24 04:33:34.000000000 -0700 @@ -76,8 +76,8 @@ * Once the device is given the dma address, the device owns this memory * until either pci_unmap_single or pci_dma_sync_single is performed. */ -extern dma_addr_t __pci_map_single(struct pci_dev *hwdev, void *ptr, - size_t size, int direction, int flush); +extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, + int direction); void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t addr, @@ -126,8 +126,8 @@ #else -static inline dma_addr_t __pci_map_single(struct pci_dev *hwdev, void *ptr, - size_t size, int direction, int flush) +static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, + size_t size, int direction) { dma_addr_t addr; @@ -214,12 +214,6 @@ extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction); -static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, - size_t size, int direction) -{ - return __pci_map_single(hwdev,ptr,size,direction,1); -} - #define pci_unmap_page pci_unmap_single /* Return whether the given PCI device DMA address mask can diff -urN linux-2.5.69-bk16/include/asm-x86_64/pda.h linux-2.5.69-bk17/include/asm-x86_64/pda.h --- linux-2.5.69-bk16/include/asm-x86_64/pda.h 2003-05-04 16:53:12.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/pda.h 2003-05-24 04:33:34.000000000 -0700 @@ -46,11 +46,11 @@ #define pda_to_op(op,field,val) do { \ switch (sizeof_field(struct x8664_pda, field)) { \ case 2: \ -asm volatile(op "w %0,%%gs:%c1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \ +asm volatile(op "w %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \ case 4: \ -asm volatile(op "l %0,%%gs:%c1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \ +asm volatile(op "l %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \ case 8: \ -asm volatile(op "q %0,%%gs:%c1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \ +asm volatile(op "q %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \ default: __bad_pda_field(); \ } \ } while (0) @@ -63,11 +63,11 @@ typedef typeof_field(struct x8664_pda, field) T__; T__ ret__; \ switch (sizeof_field(struct x8664_pda, field)) { \ case 2: \ -asm volatile(op "w %%gs:%c1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\ +asm volatile(op "w %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\ case 4: \ -asm volatile(op "l %%gs:%c1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\ +asm volatile(op "l %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\ case 8: \ -asm volatile(op "q %%gs:%c1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\ +asm volatile(op "q %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\ default: __bad_pda_field(); \ } \ ret__; }) diff -urN linux-2.5.69-bk16/include/asm-x86_64/pgtable.h linux-2.5.69-bk17/include/asm-x86_64/pgtable.h --- linux-2.5.69-bk16/include/asm-x86_64/pgtable.h 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/pgtable.h 2003-05-24 04:33:34.000000000 -0700 @@ -28,6 +28,7 @@ #define swapper_pg_dir NULL extern void paging_init(void); +extern void clear_kernel_mapping(unsigned long addr, unsigned long size); extern unsigned long pgkern_mask; @@ -165,11 +166,11 @@ #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX) #define PAGE_SHARED_EXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) -#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX) +#define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX) +#define PAGE_COPY PAGE_COPY_NOEXEC #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX) #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) - #define __PAGE_KERNEL \ (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX) #define __PAGE_KERNEL_EXECUTABLE \ @@ -181,7 +182,7 @@ #define __PAGE_KERNEL_VSYSCALL \ (_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) #define __PAGE_KERNEL_LARGE \ - (_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_PSE | _PAGE_NX) + (__PAGE_KERNEL | _PAGE_PSE) #define MAKE_GLOBAL(x) __pgprot((x) | _PAGE_GLOBAL) @@ -241,6 +242,7 @@ * The following only work if pte_present() is true. * Undefined behaviour if not.. */ +static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; } extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } diff -urN linux-2.5.69-bk16/include/asm-x86_64/processor.h linux-2.5.69-bk17/include/asm-x86_64/processor.h --- linux-2.5.69-bk16/include/asm-x86_64/processor.h 2003-05-04 16:53:55.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/processor.h 2003-05-24 04:33:34.000000000 -0700 @@ -218,14 +218,18 @@ struct thread_struct { unsigned long rsp0; - unsigned long rip; unsigned long rsp; unsigned long userrsp; /* Copy from PDA */ unsigned long fs; unsigned long gs; unsigned short es, ds, fsindex, gsindex; /* Hardware debugging registers */ - unsigned long debugreg[8]; /* %%db0-7 debug registers */ + unsigned long debugreg0; + unsigned long debugreg1; + unsigned long debugreg2; + unsigned long debugreg3; + unsigned long debugreg6; + unsigned long debugreg7; /* fault info */ unsigned long cr2, trap_no, error_code; /* floating point info */ @@ -304,17 +308,30 @@ #define cpu_has_fpu 1 -#if 0 -/* disabled for now to work around opteron errata #91. Also gcc 3.2 - doesn't like this in some cases. */ +/* Some early Opteron versions incorrectly fault on prefetch (errata #91). + If this happens just jump back. */ #define ARCH_HAS_PREFETCH -#define prefetch(x) __builtin_prefetch((x),0,1) -#endif +static inline void prefetch(void *x) +{ + asm volatile("2: prefetchnta %0\n1:\t" + ".section __ex_table,\"a\"\n\t" + " .align 8\n\t" + " .quad 2b,1b\n\t" + ".previous" :: "m" (*(unsigned long *)x)); +} #define ARCH_HAS_PREFETCHW +static inline void prefetchw(void *x) +{ + asm volatile("2: prefetchw %0\n1:\t" + ".section __ex_table,\"a\"\n\t" + " .align 8\n\t" + " .quad 2b,1b\n\t" + ".previous" :: "m" (*(unsigned long *)x)); +} + #define ARCH_HAS_SPINLOCK_PREFETCH -#define prefetchw(x) __builtin_prefetch((x),1,1) #define spin_lock_prefetch(x) prefetchw(x) #define cpu_relax() rep_nop() diff -urN linux-2.5.69-bk16/include/asm-x86_64/segment.h linux-2.5.69-bk17/include/asm-x86_64/segment.h --- linux-2.5.69-bk16/include/asm-x86_64/segment.h 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/segment.h 2003-05-24 04:33:34.000000000 -0700 @@ -18,6 +18,7 @@ #define __USER_CS 0x33 /* 6*8+3 */ #define __USER32_DS __USER_DS #define __KERNEL16_CS (GDT_ENTRY_KERNELCS16 * 8) +#define __KERNEL_COMPAT32_CS 0x8 #define GDT_ENTRY_TLS 1 #define GDT_ENTRY_TSS 8 /* needs two entries */ diff -urN linux-2.5.69-bk16/include/asm-x86_64/suspend.h linux-2.5.69-bk17/include/asm-x86_64/suspend.h --- linux-2.5.69-bk16/include/asm-x86_64/suspend.h 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/suspend.h 2003-05-24 04:33:34.000000000 -0700 @@ -54,13 +54,6 @@ extern unsigned long saved_esi; extern unsigned long saved_edi; -static inline void acpi_save_register_state(unsigned long return_point) -{ - /* FIXME: This is probably no longer correct: we need to save all caller-saved registers */ -} - -#define acpi_restore_register_state() do {} while (0) - /* routines for saving/restoring kernel state */ extern int acpi_save_state_mem(void); extern int acpi_save_state_disk(void); diff -urN linux-2.5.69-bk16/include/asm-x86_64/system.h linux-2.5.69-bk17/include/asm-x86_64/system.h --- linux-2.5.69-bk16/include/asm-x86_64/system.h 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/system.h 2003-05-24 04:33:34.000000000 -0700 @@ -16,9 +16,14 @@ #define __STR(x) #x #define STR(x) __STR(x) -#define __PUSH(x) "pushq %%" __STR(x) "\n\t" -#define __POP(x) "popq %%" __STR(x) "\n\t" +#define __SAVE(reg,offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t" +#define __RESTORE(reg,offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t" +#ifdef CONFIG_X86_REMOTE_DEBUG + +/* full frame for the debug stub */ +/* Should be replaced with a dwarf2 cie/fde description, then gdb could + figure it out all by itself. */ struct save_context_frame { unsigned long rbp; unsigned long rbx; @@ -34,46 +39,64 @@ unsigned long r12; unsigned long rdi; unsigned long rsi; + unsigned long flags; }; -/* frame pointer must be last for get_wchan */ -/* It would be more efficient to let the compiler clobber most of these registers. - Clobbering all is not possible because that lets reload freak out. Even just - clobbering six generates wrong code with gcc 3.1 for me so do it this way for now. - rbp needs to be always explicitly saved because gcc cannot clobber the - frame pointer and the scheduler is compiled with frame pointers. -AK */ #define SAVE_CONTEXT \ - __PUSH(rsi) __PUSH(rdi) \ - __PUSH(r12) __PUSH(r13) __PUSH(r14) __PUSH(r15) \ - __PUSH(rdx) __PUSH(rcx) __PUSH(r8) __PUSH(r9) __PUSH(r10) __PUSH(r11) \ - __PUSH(rbx) __PUSH(rbp) + "pushfq\n\t" \ + "subq $14*8,%%rsp\n\t" \ + __SAVE(rbx, 12) __SAVE(rdi, 1) \ + __SAVE(rdx, 6) __SAVE(rcx, 7) \ + __SAVE(r8, 8) __SAVE(r9, 9) \ + __SAVE(r12, 2) __SAVE(r13, 3) \ + __SAVE(r14, 4) __SAVE(r15, 5) \ + __SAVE(r10, 10) __SAVE(r11, 11) \ + __SAVE(rsi, 0) __SAVE(rbp, 13) \ + + #define RESTORE_CONTEXT \ - __POP(rbp) __POP(rbx) \ - __POP(r11) __POP(r10) __POP(r9) __POP(r8) __POP(rcx) __POP(rdx) \ - __POP(r15) __POP(r14) __POP(r13) __POP(r12) \ - __POP(rdi) __POP(rsi) + __RESTORE(rbx, 12) __RESTORE(rdi, 1) \ + __RESTORE(rdx, 6) __RESTORE(rcx, 7) \ + __RESTORE(r12, 2) __RESTORE(r13, 3) \ + __RESTORE(r14, 4) __RESTORE(r15, 5) \ + __RESTORE(r10, 10) __RESTORE(r11, 11) \ + __RESTORE(r8, 8) __RESTORE(r9, 9) \ + __RESTORE(rbp, 13) __RESTORE(rsi, 0) \ + "addq $14*8,%%rsp\n\t" \ + "popfq\n\t" + +#define __EXTRA_CLOBBER -/* RED-PEN: pipeline stall on ret because it is not predicted */ -/* RED-PEN: the register saving could be optimized */ +#else /* frame pointer must be last for get_wchan */ +#define SAVE_CONTEXT "pushfq ; pushq %%rbp ; movq %%rsi,%%rbp\n\t" +#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popfq\n\t" + +#define __EXTRA_CLOBBER \ + ,"rcx","rbx","rdx","r8","r9","r10","r11","r12","r13","r14","r15" +#endif #define switch_to(prev,next,last) \ asm volatile(SAVE_CONTEXT \ - "movq %%rsp,%[prevrsp]\n\t" \ - "movq %[nextrsp],%%rsp\n\t" \ - "movq $thread_return,%[prevrip]\n\t" \ - "pushq %[nextrip]\n\t" \ - "jmp __switch_to\n\t" \ + "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \ + "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \ + "call __switch_to\n\t" \ ".globl thread_return\n" \ "thread_return:\n\t" \ + "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" \ + "movq %P[thread_info](%%rsi),%%r8\n\t" \ + "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ + "movq %%rax,%%rdi\n\t" \ + "jc ret_from_fork\n\t" \ RESTORE_CONTEXT \ - :[prevrsp] "=m" (prev->thread.rsp), \ - [prevrip] "=m" (prev->thread.rip), \ - "=a" (last) \ - :[nextrsp] "m" (next->thread.rsp), \ - [nextrip] "m" (next->thread.rip), \ - [next] "S" (next), [prev] "D" (prev) \ - :"memory") + : "=a" (last) \ + : [next] "S" (next), [prev] "D" (prev), \ + [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), \ + [ti_flags] "i" (offsetof(struct thread_info, flags)),\ + [tif_fork] "i" (TIF_FORK), \ + [thread_info] "i" (offsetof(struct task_struct, thread_info)), \ + [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)) \ + : "memory", "cc" __EXTRA_CLOBBER) extern void load_gs_index(unsigned); @@ -88,14 +111,14 @@ "2:\n" \ ".section .fixup,\"ax\"\n" \ "3:\t" \ - "pushq $0 ; popq %% " #seg "\n\t" \ + "movl %1,%%" #seg "\n\t" \ "jmp 2b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n\t" \ ".align 8\n\t" \ ".quad 1b,3b\n" \ ".previous" \ - : :"r" (value)) + : :"r" (value), "r" (0)) #define set_debug(value,register) \ __asm__("movq %0,%%db" #register \ @@ -298,4 +321,7 @@ void disable_hlt(void); void enable_hlt(void); +#define HAVE_EAT_KEY +void eat_key(void); + #endif diff -urN linux-2.5.69-bk16/include/asm-x86_64/thread_info.h linux-2.5.69-bk17/include/asm-x86_64/thread_info.h --- linux-2.5.69-bk16/include/asm-x86_64/thread_info.h 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk17/include/asm-x86_64/thread_info.h 2003-05-24 04:33:34.000000000 -0700 @@ -68,7 +68,7 @@ static inline struct thread_info *stack_thread_info(void) { struct thread_info *ti; - __asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (~8191UL)); + __asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1))); return ti; } @@ -104,6 +104,7 @@ #define TIF_IRET 5 /* force IRET */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_IA32 17 /* 32bit process */ +#define TIF_FORK 18 /* ret_from_fork */ #define _TIF_SYSCALL_TRACE (1<