diff -urN linux-2.4.31/Documentation/Configure.help linux-2.4.32/Documentation/Configure.help --- linux-2.4.31/Documentation/Configure.help 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/Documentation/Configure.help 2005-11-16 11:12:54.562075817 -0800 @@ -9978,9 +9978,7 @@ CONFIG_PPPOE Support for PPP over Ethernet. - This driver requires the current pppd from the "ppp" CVS repository - on cvs.samba.org. The required support will be present in the next - ppp release (2.4.2). + This driver requires a ppp release >= 2.4.2. Wireless LAN (non-hamradio) CONFIG_NET_RADIO @@ -28990,6 +28988,9 @@ the TEA algorithm to address a potential key weakness in the TEA algorithm. + Xtendend Encryption Tiny Algorithm is a mis-implementation + of the XTEA algorithm for compatibility purposes. + CONFIG_CRYPTO_ARC4 ARC4 cipher algorithm. diff -urN linux-2.4.31/Documentation/cciss.txt linux-2.4.32/Documentation/cciss.txt --- linux-2.4.31/Documentation/cciss.txt 2004-08-07 16:26:04.000000000 -0700 +++ linux-2.4.32/Documentation/cciss.txt 2005-11-16 11:12:54.563075862 -0800 @@ -15,7 +15,11 @@ * SA 6400 U320 Expansion Module * SA 6i * SA 6422 - * SA V100 + * SA P600 + * SA P400 + * SA P400i + * SA E200 + * SA E200i If nodes are not already created in the /dev/cciss directory diff -urN linux-2.4.31/Documentation/crypto/api-intro.txt linux-2.4.32/Documentation/crypto/api-intro.txt --- linux-2.4.31/Documentation/crypto/api-intro.txt 2004-11-17 03:54:20.000000000 -0800 +++ linux-2.4.32/Documentation/crypto/api-intro.txt 2005-11-16 11:12:54.563075862 -0800 @@ -221,6 +221,7 @@ TEA/XTEA algorithm contributors: Aaron Grothe + Michael Ringe Khazad algorithm contributors: Aaron Grothe diff -urN linux-2.4.31/Documentation/networking/vortex.txt linux-2.4.32/Documentation/networking/vortex.txt --- linux-2.4.31/Documentation/networking/vortex.txt 2002-08-02 17:39:42.000000000 -0700 +++ linux-2.4.32/Documentation/networking/vortex.txt 2005-11-16 11:12:54.563075862 -0800 @@ -12,7 +12,7 @@ Please report problems to one or more of: Andrew Morton - Netdev mailing list + Netdev mailing list Linux kernel mailing list Please note the 'Reporting and Diagnosing Problems' section at the end diff -urN linux-2.4.31/MAINTAINERS linux-2.4.32/MAINTAINERS --- linux-2.4.31/MAINTAINERS 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/MAINTAINERS 2005-11-16 11:12:54.564075907 -0800 @@ -116,7 +116,7 @@ 8169 10/100/1000 GIGABIT ETHERNET DRIVER P: Francois Romieu M: romieu@fr.zoreil.com -L: netdev@oss.sgi.com +L: netdev@vger.kernel.org S: Maintained 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER @@ -820,7 +820,7 @@ I2C SUBSYSTEM P: Jean Delvare M: khali@linux-fr.org -L: sensors@stimpy.netroedge.com +L: lm-sensors@lm-sensors.org W: http://www.lm-sensors.nu/ S: Maintained @@ -993,9 +993,11 @@ IPVS P: Wensong Zhang M: wensong@linux-vs.org +P: Simon Horman +M: horms@verge.net.au P: Julian Anastasov M: ja@ssi.bg -L: lvs-users@linuxvirtualserver.org +L: netdev@vger.kernel.org S: Maintained IPX NETWORK LAYER @@ -1186,7 +1188,7 @@ P: Manish Lachwani M: Manish_Lachwani@pmc-sierra.com L: linux-mips@linux-mips.org -L: netdev@oss.sgi.com +L: netdev@vger.kernel.org S: Supported MARVELL YUKON / SYSKONNECT DRIVER @@ -1315,7 +1317,7 @@ NETWORKING [GENERAL] P: Networking Team -M: netdev@oss.sgi.com +M: netdev@vger.kernel.org L: linux-net@vger.kernel.org S: Maintained @@ -1332,7 +1334,7 @@ M: yoshfuji@linux-ipv6.org P: Patrick McHardy M: kaber@coreworks.de -L: netdev@oss.sgi.com +L: netdev@vger.kernel.org S: Maintained NFS CLIENT @@ -1529,7 +1531,7 @@ PRISM54 WIRELESS DRIVER P: Prism54 Development Team M: prism54-private@prism54.org -L: netdev@oss.sgi.com +L: netdev@vger.kernel.org W: http://prism54.org S: Maintained diff -urN linux-2.4.31/Makefile linux-2.4.32/Makefile --- linux-2.4.31/Makefile 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/Makefile 2005-11-16 11:12:54.685081300 -0800 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 4 -SUBLEVEL = 31 +SUBLEVEL = 32 EXTRAVERSION = KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -urN linux-2.4.31/arch/alpha/kernel/Makefile linux-2.4.32/arch/alpha/kernel/Makefile --- linux-2.4.31/arch/alpha/kernel/Makefile 2003-11-28 10:26:19.000000000 -0800 +++ linux-2.4.32/arch/alpha/kernel/Makefile 2005-11-16 11:12:54.565075951 -0800 @@ -76,7 +76,7 @@ obj-y += sys_alcor.o endif ifneq ($(CONFIG_ALPHA_CABRIOLET)$(CONFIG_ALPHA_EB164)$(CONFIG_ALPHA_EB66P)$(CONFIG_ALPHA_LX164)$(CONFIG_ALPHA_PC164),) -obj-y += sys_cabriolet.o +obj-y += sys_cabriolet.o ns87312.o endif obj-$(CONFIG_ALPHA_DP264) += sys_dp264.o diff -urN linux-2.4.31/arch/i386/kernel/apm.c linux-2.4.32/arch/i386/kernel/apm.c --- linux-2.4.31/arch/i386/kernel/apm.c 2003-08-25 04:44:39.000000000 -0700 +++ linux-2.4.32/arch/i386/kernel/apm.c 2005-11-16 11:12:54.566075996 -0800 @@ -327,7 +327,7 @@ * Save a segment register away */ #define savesegment(seg, where) \ - __asm__ __volatile__("movl %%" #seg ",%0" : "=m" (where)) + __asm__ __volatile__("mov %%" #seg ",%0" : "=m" (where)) /* * Maximum number of events stored @@ -553,7 +553,7 @@ #ifdef APM_ZERO_SEGS # define APM_DECL_SEGS \ - unsigned int saved_fs; unsigned int saved_gs; + unsigned short saved_fs; unsigned short saved_gs; # define APM_DO_SAVE_SEGS \ savesegment(fs, saved_fs); savesegment(gs, saved_gs) # define APM_DO_ZERO_SEGS \ diff -urN linux-2.4.31/arch/i386/kernel/pci-irq.c linux-2.4.32/arch/i386/kernel/pci-irq.c --- linux-2.4.31/arch/i386/kernel/pci-irq.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/arch/i386/kernel/pci-irq.c 2005-11-16 11:12:54.567076040 -0800 @@ -664,6 +664,30 @@ static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { /* FIXME: We should move some of the quirk fixup stuff here */ + + /* + * work arounds for some buggy BIOSes + */ + if (device == PCI_DEVICE_ID_VIA_82C586_0) { + switch(router->device) + { + case PCI_DEVICE_ID_VIA_82C686: + /* + * Asus k7m bios wrongly reports 82C686A + * as 586-compatible + */ + device = PCI_DEVICE_ID_VIA_82C686; + break; + case PCI_DEVICE_ID_VIA_8235: + /** + * Asus a7v-x bios wrongly reports 8235 + * as 586-compatible + */ + device = PCI_DEVICE_ID_VIA_8235; + break; + } + } + switch(device) { case PCI_DEVICE_ID_VIA_82C586_0: @@ -674,6 +698,7 @@ case PCI_DEVICE_ID_VIA_82C596: case PCI_DEVICE_ID_VIA_82C686: case PCI_DEVICE_ID_VIA_8231: + case PCI_DEVICE_ID_VIA_8235: /* FIXME: add new ones for 8233/5 */ r->name = "VIA"; r->get = pirq_via_get; diff -urN linux-2.4.31/arch/i386/kernel/process.c linux-2.4.32/arch/i386/kernel/process.c --- linux-2.4.31/arch/i386/kernel/process.c 2004-11-17 03:54:21.000000000 -0800 +++ linux-2.4.32/arch/i386/kernel/process.c 2005-11-16 11:12:54.567076040 -0800 @@ -544,7 +544,7 @@ * Save a segment. */ #define savesegment(seg,value) \ - asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value))) + asm volatile("mov %%" #seg ",%0":"=m" (value)) int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, unsigned long unused, @@ -661,8 +661,8 @@ * Save away %fs and %gs. No need to save %es and %ds, as * those are always kernel segments while inside the kernel. */ - asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs)); - asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs)); + asm volatile("mov %%fs,%0":"=m" (prev->fs)); + asm volatile("mov %%gs,%0":"=m" (prev->gs)); /* * Restore %fs and %gs. diff -urN linux-2.4.31/arch/i386/kernel/traps.c linux-2.4.32/arch/i386/kernel/traps.c --- linux-2.4.31/arch/i386/kernel/traps.c 2002-11-28 15:53:09.000000000 -0800 +++ linux-2.4.32/arch/i386/kernel/traps.c 2005-11-16 11:12:54.568076085 -0800 @@ -631,15 +631,14 @@ */ cwd = get_fpu_cwd(task); swd = get_fpu_swd(task); - switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) { + switch (swd & ~cwd & 0x3f) { case 0x000: default: break; case 0x001: /* Invalid Op */ - case 0x041: /* Stack Fault */ - case 0x241: /* Stack Fault | Direction */ + /* swd & 0x240 == 0x040: Stack Fault */ + /* swd & 0x240 == 0x240: Stack Fault | Direction */ info.si_code = FPE_FLTINV; - /* Should we clear the SF or let user space do it ???? */ break; case 0x002: /* Denormalize */ case 0x010: /* Underflow */ diff -urN linux-2.4.31/arch/ia64/ia32/sys_ia32.c linux-2.4.32/arch/ia64/ia32/sys_ia32.c --- linux-2.4.31/arch/ia64/ia32/sys_ia32.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/arch/ia64/ia32/sys_ia32.c 2005-11-16 11:12:54.570076174 -0800 @@ -94,7 +94,7 @@ static DECLARE_MUTEX(ia32_mmap_sem); static int -nargs (unsigned int arg, char **ap) +nargs (unsigned int arg, char **ap, int max) { unsigned int addr; int n, err; @@ -107,6 +107,8 @@ err = get_user(addr, (unsigned int *)A(arg)); if (err) return err; + if (n > max) + return -E2BIG; if (ap) *ap++ = (char *) A(addr); arg += sizeof(unsigned int); @@ -128,10 +130,11 @@ int na, ne, len; long r; - na = nargs(argv, NULL); + /* Allocates upto 2x MAX_ARG_PAGES */ + na = nargs(argv, NULL, (MAX_ARG_PAGES*PAGE_SIZE) / sizeof(char *) - 1); if (na < 0) return na; - ne = nargs(envp, NULL); + ne = nargs(envp, NULL, (MAX_ARG_PAGES*PAGE_SIZE) / sizeof(char *) - 1 ); if (ne < 0) return ne; len = (na + ne + 2) * sizeof(*av); @@ -143,10 +146,10 @@ av[na] = NULL; ae[ne] = NULL; - r = nargs(argv, av); + r = nargs(argv, av, na); if (r < 0) goto out; - r = nargs(envp, ae); + r = nargs(envp, ae, ne); if (r < 0) goto out; diff -urN linux-2.4.31/arch/ia64/mm/fault.c linux-2.4.32/arch/ia64/mm/fault.c --- linux-2.4.31/arch/ia64/mm/fault.c 2003-08-25 04:44:39.000000000 -0700 +++ linux-2.4.32/arch/ia64/mm/fault.c 2005-11-16 11:12:54.571076219 -0800 @@ -206,9 +206,6 @@ return; } - if (done_with_exception(regs)) - return; - /* * Since we have no vma's for region 5, we might get here even if the address is * valid, due to the VHPT walker inserting a non present translation that becomes @@ -219,6 +216,9 @@ if (REGION_NUMBER(address) == 5 && mapped_kernel_page_is_present(address)) return; + if (done_with_exception(regs)) + return; + /* * Oops. The kernel tried to access some bad page. We'll have to terminate things * with extreme prejudice. diff -urN linux-2.4.31/arch/mips/.gdbinit linux-2.4.32/arch/mips/.gdbinit --- linux-2.4.31/arch/mips/.gdbinit 1997-12-10 10:31:09.000000000 -0800 +++ linux-2.4.32/arch/mips/.gdbinit 1969-12-31 16:00:00.000000000 -0800 @@ -1,7 +0,0 @@ -echo Setting up the environment for debugging vmlinux...\n -echo set remotedebug 0 \n -set remotedebug 0 -echo cd arch/mips/kernel \n -cd arch/mips/kernel -echo target remote /dev/ttyS0 \n -target remote /dev/ttyS0 diff -urN linux-2.4.31/arch/ppc/boot/lib/zlib.c linux-2.4.32/arch/ppc/boot/lib/zlib.c --- linux-2.4.31/arch/ppc/boot/lib/zlib.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.32/arch/ppc/boot/lib/zlib.c 2005-11-16 11:12:54.573076308 -0800 @@ -1278,7 +1278,7 @@ { *t = (inflate_huft *)Z_NULL; *m = 0; - return Z_OK; + return Z_DATA_ERROR; } @@ -1322,6 +1322,7 @@ if ((j = *p++) != 0) v[x[j]++] = i; } while (++i < n); + n = x[g]; /* set n to length of v */ /* Generate the Huffman codes and for each, make the table entries */ diff -urN linux-2.4.31/arch/ppc/kernel/time.c linux-2.4.32/arch/ppc/kernel/time.c --- linux-2.4.31/arch/ppc/kernel/time.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/arch/ppc/kernel/time.c 2005-11-16 11:12:54.573076308 -0800 @@ -84,7 +84,7 @@ extern unsigned long wall_jiffies; -static long time_offset; +static long timezone_offset; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; @@ -187,7 +187,7 @@ xtime.tv_sec - last_rtc_update >= 659 && abs(xtime.tv_usec - (1000000-1000000/HZ)) < 500000/HZ && jiffies - wall_jiffies == 1) { - if (ppc_md.set_rtc_time(xtime.tv_sec+1 + time_offset) == 0) + if (ppc_md.set_rtc_time(xtime.tv_sec+1 + timezone_offset) == 0) last_rtc_update = xtime.tv_sec+1; else /* Try again one minute later */ @@ -297,7 +297,7 @@ unsigned old_stamp, stamp, elapsed; if (ppc_md.time_init != NULL) - time_offset = ppc_md.time_init(); + timezone_offset = ppc_md.time_init(); if (__USE_RTC()) { /* 601 processor: dec counts down by 128 every 128ns */ @@ -344,9 +344,9 @@ /* If platform provided a timezone (pmac), we correct the time * using do_sys_settimeofday() which in turn calls warp_clock() */ - if (time_offset) { + if (timezone_offset) { struct timezone tz; - tz.tz_minuteswest = -time_offset / 60; + tz.tz_minuteswest = -timezone_offset / 60; tz.tz_dsttime = 0; do_sys_settimeofday(NULL, &tz); } diff -urN linux-2.4.31/arch/ppc64/boot/zlib.c linux-2.4.32/arch/ppc64/boot/zlib.c --- linux-2.4.31/arch/ppc64/boot/zlib.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.32/arch/ppc64/boot/zlib.c 2005-11-16 11:12:54.575076397 -0800 @@ -1338,6 +1338,7 @@ if ((j = *p++) != 0) v[x[j]++] = i; } while (++i < n); + n = x[g]; /* set n to length of v */ /* Generate the Huffman codes and for each, make the table entries */ diff -urN linux-2.4.31/arch/ppc64/kernel/ioctl32.c linux-2.4.32/arch/ppc64/kernel/ioctl32.c --- linux-2.4.31/arch/ppc64/kernel/ioctl32.c 2005-01-19 06:09:36.000000000 -0800 +++ linux-2.4.32/arch/ppc64/kernel/ioctl32.c 2005-11-16 11:12:54.577076486 -0800 @@ -876,13 +876,15 @@ r = (void *) &r4; } - if (ret) - return -EFAULT; + if (ret) { + ret = -EFAULT; + goto out; + } set_fs (KERNEL_DS); ret = sys_ioctl (fd, cmd, (long) r); set_fs (old_fs); - +out: if (mysock) sockfd_put(mysock); diff -urN linux-2.4.31/arch/sparc64/kernel/ioctl32.c linux-2.4.32/arch/sparc64/kernel/ioctl32.c --- linux-2.4.31/arch/sparc64/kernel/ioctl32.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/arch/sparc64/kernel/ioctl32.c 2005-11-16 11:12:54.581076664 -0800 @@ -809,13 +809,15 @@ r = (void *) &r4; } - if (ret) - return -EFAULT; + if (ret) { + ret = -EFAULT; + goto out; + } set_fs (KERNEL_DS); ret = sys_ioctl (fd, cmd, (long) r); set_fs (old_fs); - +out: if (mysock) sockfd_put(mysock); diff -urN linux-2.4.31/arch/sparc64/kernel/sparc64_ksyms.c linux-2.4.32/arch/sparc64/kernel/sparc64_ksyms.c --- linux-2.4.31/arch/sparc64/kernel/sparc64_ksyms.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/arch/sparc64/kernel/sparc64_ksyms.c 2005-11-16 11:12:54.581076664 -0800 @@ -63,7 +63,6 @@ extern void die_if_kernel(char *str, struct pt_regs *regs); void _sigpause_common (unsigned int set, struct pt_regs *); extern void *__bzero(void *, size_t); -extern void *__bzero_noasi(void *, size_t); extern void *__memscan_zero(void *, size_t); extern void *__memscan_generic(void *, int, size_t); extern int __memcmp(const void *, const void *, __kernel_size_t); diff -urN linux-2.4.31/arch/sparc64/kernel/sys_sparc32.c linux-2.4.32/arch/sparc64/kernel/sys_sparc32.c --- linux-2.4.31/arch/sparc64/kernel/sys_sparc32.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/arch/sparc64/kernel/sys_sparc32.c 2005-11-16 11:12:54.583076754 -0800 @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -2919,12 +2920,12 @@ if (optlen != kreplsize) return -ENOPROTOOPT; - krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL); + krepl = (struct ipt_replace *)vmalloc(kreplsize); if (krepl == NULL) return -ENOMEM; if (copy_from_user(krepl, optval, kreplsize)) { - kfree(krepl); + vfree(krepl); return -EFAULT; } @@ -2932,10 +2933,9 @@ ((struct ipt_replace32 *)krepl)->counters); kcountersize = krepl->num_counters * sizeof(struct ipt_counters); - krepl->counters = (struct ipt_counters *)kmalloc( - kcountersize, GFP_KERNEL); + krepl->counters = (struct ipt_counters *)vmalloc(kcountersize); if (krepl->counters == NULL) { - kfree(krepl); + vfree(krepl); return -ENOMEM; } @@ -2949,8 +2949,8 @@ copy_to_user(counters32, krepl->counters, kcountersize)) ret = -EFAULT; - kfree(krepl->counters); - kfree(krepl); + vfree(krepl->counters); + vfree(krepl); return ret; } @@ -4205,7 +4205,7 @@ old_fs = get_fs(); set_fs(KERNEL_DS); - ret = sys_utimes(kfilename, &ktvs[0]); + ret = sys_utimes(kfilename, (tvs ? &ktvs[0] : NULL)); set_fs(old_fs); putname(kfilename); diff -urN linux-2.4.31/arch/sparc64/solaris/socket.c linux-2.4.32/arch/sparc64/solaris/socket.c --- linux-2.4.31/arch/sparc64/solaris/socket.c 2001-02-18 19:49:54.000000000 -0800 +++ linux-2.4.32/arch/sparc64/solaris/socket.c 2005-11-16 11:12:54.584076798 -0800 @@ -410,8 +410,10 @@ unsigned long *kcmsg; __kernel_size_t32 cmlen; - if(kern_msg.msg_controllen > sizeof(ctl) && - kern_msg.msg_controllen <= 256) { + if (kern_msg.msg_controllen <= sizeof(__kernel_size_t32)) + return -EINVAL; + + if(kern_msg.msg_controllen > sizeof(ctl)) { err = -ENOBUFS; ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL); if(!ctl_buf) diff -urN linux-2.4.31/arch/x86_64/ia32/ia32_ioctl.c linux-2.4.32/arch/x86_64/ia32/ia32_ioctl.c --- linux-2.4.31/arch/x86_64/ia32/ia32_ioctl.c 2005-01-19 06:09:39.000000000 -0800 +++ linux-2.4.32/arch/x86_64/ia32/ia32_ioctl.c 2005-11-16 11:12:54.587076932 -0800 @@ -816,6 +816,11 @@ extern struct socket *sockfd_lookup(int fd, int *err); +extern __inline__ void sockfd_put(struct socket *sock) +{ + fput(sock->file); +} + static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { int ret; @@ -857,12 +862,17 @@ r = (void *) &r4; } - if (ret) - return -EFAULT; + if (ret) { + ret = -EFAULT; + goto out; + } set_fs (KERNEL_DS); ret = sys_ioctl (fd, cmd, (long) r); set_fs (old_fs); +out: + if (mysock) + sockfd_put(mysock); return ret; } @@ -2766,17 +2776,24 @@ static int tiocgdev(unsigned fd, unsigned cmd, unsigned int *ptr) { - struct file *file = fget(fd); + struct file *file; struct tty_struct *real_tty; + int ret; + file = fget(fd); if (!file) return -EBADF; + ret = -EINVAL; if (file->f_op->ioctl != tty_ioctl) - return -EINVAL; + goto out; real_tty = (struct tty_struct *)file->private_data; if (!real_tty) - return -EINVAL; - return put_user(kdev_t_to_nr(real_tty->device), ptr); + goto out; + ret = put_user(kdev_t_to_nr(real_tty->device), ptr); +out: + fput(file); + + return ret; } diff -urN linux-2.4.31/arch/x86_64/ia32/sys_ia32.c linux-2.4.32/arch/x86_64/ia32/sys_ia32.c --- linux-2.4.31/arch/x86_64/ia32/sys_ia32.c 2005-01-19 06:09:39.000000000 -0800 +++ linux-2.4.32/arch/x86_64/ia32/sys_ia32.c 2005-11-16 11:12:54.588076976 -0800 @@ -2200,7 +2200,7 @@ return ret; } -static int nargs(u32 src, char **dst) +static int nargs(u32 src, char **dst, int max) { int cnt; u32 val; @@ -2210,13 +2210,13 @@ int ret = get_user(val, (__u32 *)(u64)src); if (ret) return ret; + if (cnt > max) + return -E2BIG; if (dst) dst[cnt] = (char *)(u64)val; cnt++; src += 4; - if (cnt >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) - return -E2BIG; - } while(val); + } while(val); if (dst) dst[cnt-1] = 0; return cnt; @@ -2230,13 +2230,14 @@ int ret; unsigned sz = 0; + /* Can actually allocate 2*MAX_ARG_PAGES */ if (argv) { - na = nargs(argv, NULL); + na = nargs(argv, NULL, (MAX_ARG_PAGES * PAGE_SIZE)/sizeof(char*) - 1); if (na < 0) return -EFAULT; } if (envp) { - ne = nargs(envp, NULL); + ne = nargs(envp, NULL, (MAX_ARG_PAGES * PAGE_SIZE)/sizeof(char*) - 1); if (ne < 0) return -EFAULT; } @@ -2252,13 +2253,13 @@ } if (argv) { - ret = nargs(argv, buf); + ret = nargs(argv, buf, na); if (ret < 0) goto free; } if (envp) { - ret = nargs(envp, buf + na); + ret = nargs(envp, buf + na, ne); if (ret < 0) goto free; } diff -urN linux-2.4.31/arch/x86_64/kernel/io_apic.c linux-2.4.32/arch/x86_64/kernel/io_apic.c --- linux-2.4.31/arch/x86_64/kernel/io_apic.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/arch/x86_64/kernel/io_apic.c 2005-11-16 11:12:54.590077066 -0800 @@ -222,7 +222,6 @@ __setup("apic", ioapic_setup); -#ifndef CONFIG_SMP #include #include #include @@ -279,7 +278,6 @@ } } } -#endif static int __init ioapic_pirq_setup(char *str) { diff -urN linux-2.4.31/arch/x86_64/kernel/pci-gart.c linux-2.4.32/arch/x86_64/kernel/pci-gart.c --- linux-2.4.31/arch/x86_64/kernel/pci-gart.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/arch/x86_64/kernel/pci-gart.c 2005-11-16 11:12:54.590077066 -0800 @@ -47,6 +47,10 @@ extern int fallback_aper_order; extern int fallback_aper_force; +#ifdef CONFIG_SWIOTLB +extern char *io_tlb_start, *io_tlb_end; +#endif + /* Allocation bitmap for the remapping area */ static spinlock_t iommu_bitmap_lock = SPIN_LOCK_UNLOCKED; static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */ @@ -234,10 +238,10 @@ void *vaddr, dma_addr_t bus) { unsigned long iommu_page; - extern char *io_tlb_start, *io_tlb_end; - + size = round_up(size, PAGE_SIZE); #ifdef CONFIG_SWIOTLB + /* Overlap should not happen */ if (swiotlb && vaddr >= (void *)io_tlb_start && vaddr < (void *)io_tlb_end) { swiotlb_unmap_single (hwdev, bus, size, PCI_DMA_TODEVICE); diff -urN linux-2.4.31/arch/x86_64/kernel/process.c linux-2.4.32/arch/x86_64/kernel/process.c --- linux-2.4.31/arch/x86_64/kernel/process.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/arch/x86_64/kernel/process.c 2005-11-16 11:12:54.591077110 -0800 @@ -526,10 +526,10 @@ p->thread.fs = me->thread.fs; p->thread.gs = me->thread.gs; - asm("movl %%gs,%0" : "=m" (p->thread.gsindex)); - asm("movl %%fs,%0" : "=m" (p->thread.fsindex)); - asm("movl %%es,%0" : "=m" (p->thread.es)); - asm("movl %%ds,%0" : "=m" (p->thread.ds)); + asm("mov %%gs,%0" : "=m" (p->thread.gsindex)); + asm("mov %%fs,%0" : "=m" (p->thread.fsindex)); + asm("mov %%es,%0" : "=m" (p->thread.es)); + asm("mov %%ds,%0" : "=m" (p->thread.ds)); unlazy_fpu(current); p->thread.i387 = current->thread.i387; @@ -574,11 +574,11 @@ /* * Switch DS and ES. */ - asm volatile("movl %%es,%0" : "=m" (prev->es)); + asm volatile("mov %%es,%0" : "=m" (prev->es)); if (unlikely(next->es | prev->es)) loadsegment(es, next->es); - asm volatile ("movl %%ds,%0" : "=m" (prev->ds)); + asm volatile ("mov %%ds,%0" : "=m" (prev->ds)); if (unlikely(next->ds | prev->ds)) loadsegment(ds, next->ds); @@ -587,7 +587,7 @@ */ { unsigned fsindex; - asm volatile("movl %%fs,%0" : "=g" (fsindex)); + asm volatile("movl %%fs,%0" : "=r" (fsindex)); /* segment register != 0 always requires a reload. also reload when it has changed. when prev process used 64bit base always reload @@ -608,7 +608,7 @@ } { unsigned gsindex; - asm volatile("movl %%gs,%0" : "=g" (gsindex)); + asm volatile("movl %%gs,%0" : "=r" (gsindex)); if (unlikely((gsindex | next->gsindex) || prev->gs)) { load_gs_index(next->gsindex); if (gsindex) diff -urN linux-2.4.31/arch/x86_64/kernel/ptrace.c linux-2.4.32/arch/x86_64/kernel/ptrace.c --- linux-2.4.31/arch/x86_64/kernel/ptrace.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.32/arch/x86_64/kernel/ptrace.c 2005-11-16 11:12:54.591077110 -0800 @@ -114,13 +114,13 @@ child->thread.es = value & 0xffff; return 0; case offsetof(struct user_regs_struct,fs_base): - if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) - return -EIO; + if (value >= TASK_SIZE) + return -EIO; child->thread.fs = value; return 0; case offsetof(struct user_regs_struct,gs_base): - if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) - return -EIO; + if (value >= TASK_SIZE) + return -EIO; child->thread.gs = value; return 0; case offsetof(struct user_regs_struct, eflags): @@ -139,6 +139,11 @@ return -EIO; value &= 0xffff; break; + case offsetof(struct user_regs_struct, rip): + /* Check if the new RIP address is canonical */ + if (value >= TASK_SIZE) + return -EIO; + break; } put_stack_long(child, regno - sizeof(struct pt_regs), value); return 0; diff -urN linux-2.4.31/arch/x86_64/kernel/setup.c linux-2.4.32/arch/x86_64/kernel/setup.c --- linux-2.4.31/arch/x86_64/kernel/setup.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/arch/x86_64/kernel/setup.c 2005-11-16 11:12:54.592077155 -0800 @@ -304,7 +304,7 @@ #endif paging_init(); -#if !defined(CONFIG_SMP) && defined(CONFIG_X86_IO_APIC) +#if defined(CONFIG_X86_IO_APIC) extern void check_ioapic(void); check_ioapic(); #endif diff -urN linux-2.4.31/arch/x86_64/kernel/traps.c linux-2.4.32/arch/x86_64/kernel/traps.c --- linux-2.4.31/arch/x86_64/kernel/traps.c 2004-04-14 06:05:28.000000000 -0700 +++ linux-2.4.32/arch/x86_64/kernel/traps.c 2005-11-16 11:12:54.592077155 -0800 @@ -857,7 +857,7 @@ set_intr_gate(9,&coprocessor_segment_overrun); set_intr_gate(10,&invalid_TSS); set_intr_gate(11,&segment_not_present); - set_intr_gate_ist(12,&stack_segment,STACKFAULT_STACK); + set_intr_gate(12,&stack_segment); set_intr_gate(13,&general_protection); set_intr_gate(14,&page_fault); set_intr_gate(15,&spurious_interrupt_bug); diff -urN linux-2.4.31/crypto/tcrypt.c linux-2.4.32/crypto/tcrypt.c --- linux-2.4.31/crypto/tcrypt.c 2004-11-17 03:54:21.000000000 -0800 +++ linux-2.4.32/crypto/tcrypt.c 2005-11-16 11:12:54.593077199 -0800 @@ -64,7 +64,7 @@ "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", "arc4", "michael_mic", "deflate", "tea", "xtea", "khazad", - "wp512", "wp384", "wp256", "tnepres", "anubis", NULL + "wp512", "wp384", "wp256", "tnepres", "anubis", "xeta", NULL }; static void @@ -590,6 +590,10 @@ test_cipher ("anubis", MODE_CBC, ENCRYPT, anubis_cbc_enc_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); + //XETA + test_cipher ("xeta", MODE_ECB, ENCRYPT, xeta_enc_tv_template, XETA_ENC_TEST_VECTORS); + test_cipher ("xeta", MODE_ECB, DECRYPT, xeta_dec_tv_template, XETA_DEC_TEST_VECTORS); + test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS); @@ -725,6 +729,11 @@ test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); break; + case 30: + test_cipher ("xeta", MODE_ECB, ENCRYPT, xeta_enc_tv_template, XETA_ENC_TEST_VECTORS); + test_cipher ("xeta", MODE_ECB, DECRYPT, xeta_dec_tv_template, XETA_DEC_TEST_VECTORS); + break; + #ifdef CONFIG_CRYPTO_HMAC case 100: test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); diff -urN linux-2.4.31/crypto/tcrypt.h linux-2.4.32/crypto/tcrypt.h --- linux-2.4.31/crypto/tcrypt.h 2004-11-17 03:54:21.000000000 -0800 +++ linux-2.4.32/crypto/tcrypt.h 2005-11-16 11:12:54.594077244 -0800 @@ -2085,7 +2085,7 @@ .klen = 16, .input = { [0 ... 8] = 0x00 }, .ilen = 8, - .result = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 }, + .result = { 0xd8, 0xd4, 0xe9, 0xde, 0xd9, 0x1e, 0x13, 0xf7 }, .rlen = 8, }, { .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76, @@ -2093,13 +2093,13 @@ .klen = 16, .input = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e }, .ilen = 8, - .result = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 }, + .result = { 0x94, 0xeb, 0xc8, 0x96, 0x84, 0x6a, 0x49, 0xa8 }, .rlen = 8, }, { .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25, 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e }, .klen = 16, - .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, + .input = { 0x3e, 0xce, 0xae, 0x22, 0x60, 0x56, 0xa8, 0x9d, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 }, .ilen = 16, .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, @@ -2114,10 +2114,10 @@ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 }, .ilen = 32, - .result = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, - 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, - 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, - 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 }, + .result = { 0x99, 0x81, 0x9f, 0x5d, 0x6f, 0x4b, 0x31, 0x3a, + 0x86, 0xff, 0x6f, 0xd0, 0xe3, 0x87, 0x70, 0x07, + 0x4d, 0xb8, 0xcf, 0xf3, 0x99, 0x50, 0xb3, 0xd4, + 0x73, 0xa2, 0xfa, 0xc9, 0x16, 0x59, 0x5d, 0x81 }, .rlen = 32, } }; @@ -2127,7 +2127,7 @@ { .key = { [0 ... 15] = 0x00 }, .klen = 16, - .input = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 }, + .input = { 0xd8, 0xd4, 0xe9, 0xde, 0xd9, 0x1e, 0x13, 0xf7 }, .ilen = 8, .result = { [0 ... 8] = 0x00 }, .rlen = 8, @@ -2135,7 +2135,7 @@ .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76, 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 }, .klen = 16, - .input = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 }, + .input = { 0x94, 0xeb, 0xc8, 0x96, 0x84, 0x6a, 0x49, 0xa8 }, .ilen = 8, .result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e }, .rlen = 8, @@ -2143,8 +2143,8 @@ .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25, 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e }, .klen = 16, - .input = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, - 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c }, + .input = { 0x3e, 0xce, 0xae, 0x22, 0x60, 0x56, 0xa8, 0x9d, + 0x77, 0x4d, 0xd4, 0xb4, 0x87, 0x24, 0xe3, 0x9a }, .ilen = 16, .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 }, @@ -2153,10 +2153,10 @@ .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c, 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f }, .klen = 16, - .input = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, - 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, - 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, - 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 }, + .input = { 0x99, 0x81, 0x9f, 0x5d, 0x6f, 0x4b, 0x31, 0x3a, + 0x86, 0xff, 0x6f, 0xd0, 0xe3, 0x87, 0x70, 0x07, + 0x4d, 0xb8, 0xcf, 0xf3, 0x99, 0x50, 0xb3, 0xd4, + 0x73, 0xa2, 0xfa, 0xc9, 0x16, 0x59, 0x5d, 0x81 }, .ilen = 32, .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, @@ -2469,6 +2469,100 @@ }, }; +/* + * XETA test vectors + */ +#define XETA_ENC_TEST_VECTORS 4 +#define XETA_DEC_TEST_VECTORS 4 + +struct cipher_testvec xeta_enc_tv_template[] = +{ + { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .input = { [0 ... 8] = 0x00 }, + .ilen = 8, + .result = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 }, + .rlen = 8, + }, { + .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76, + 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 }, + .klen = 16, + .input = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e }, + .ilen = 8, + .result = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 }, + .rlen = 8, + }, { + .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25, + 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e }, + .klen = 16, + .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, + 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 }, + .ilen = 16, + .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, + 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c }, + .rlen = 16, + }, { + .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c, + 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f }, + .klen = 16, + .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, + 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, + 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 }, + .ilen = 32, + .result = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, + 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, + 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, + 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 }, + .rlen = 32, + } +}; + +struct cipher_testvec xeta_dec_tv_template[] = +{ + { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .input = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 }, + .ilen = 8, + .result = { [0 ... 8] = 0x00 }, + .rlen = 8, + }, { + .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76, + 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 }, + .klen = 16, + .input = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 }, + .ilen = 8, + .result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e }, + .rlen = 8, + }, { + .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25, + 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e }, + .klen = 16, + .input = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, + 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c }, + .ilen = 16, + .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, + 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 }, + .rlen = 16, + }, { + .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c, + 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f }, + .klen = 16, + .input = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, + 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, + 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, + 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 }, + .ilen = 32, + .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, + 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, + 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 }, + .rlen = 32, + } +}; + /* * Compression stuff. */ diff -urN linux-2.4.31/crypto/tea.c linux-2.4.32/crypto/tea.c --- linux-2.4.31/crypto/tea.c 2004-11-17 03:54:21.000000000 -0800 +++ linux-2.4.32/crypto/tea.c 2005-11-16 11:12:54.595077288 -0800 @@ -1,11 +1,15 @@ /* * Cryptographic API. * - * TEA and Xtended TEA Algorithms + * TEA, XTEA, and XETA crypto alogrithms * * The TEA and Xtended TEA algorithms were developed by David Wheeler * and Roger Needham at the Computer Laboratory of Cambridge University. * + * Due to the order of evaluation in XTEA many people have incorrectly + * implemented it. XETA (XTEA in the wrong order), exists for + * compatibility with these implementations. + * * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.com * * This program is free software; you can redistribute it and/or modify @@ -153,9 +157,9 @@ z = u32_in (src + 4); while (sum != limit) { - y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; + y += ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum&3]); sum += XTEA_DELTA; - z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; + z += ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 &3]); } u32_out (dst, y); @@ -175,6 +179,51 @@ sum = XTEA_DELTA * XTEA_ROUNDS; while (sum) { + z -= ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 & 3]); + sum -= XTEA_DELTA; + y -= ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum & 3]); + } + + u32_out (dst, y); + u32_out (dst + 4, z); + +} + +static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src) +{ + + u32 y, z, sum = 0; + u32 limit = XTEA_DELTA * XTEA_ROUNDS; + + struct xtea_ctx *ctx = ctx_arg; + + y = u32_in (src); + z = u32_in (src + 4); + + while (sum != limit) { + y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; + sum += XTEA_DELTA; + z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; + + } + + u32_out (dst, y); + u32_out (dst + 4, z); + +} + +static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src) +{ + + u32 y, z, sum; + struct tea_ctx *ctx = ctx_arg; + + y = u32_in (src); + z = u32_in (src + 4); + + sum = XTEA_DELTA * XTEA_ROUNDS; + + while (sum) { z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3]; sum -= XTEA_DELTA; y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3]; @@ -215,6 +264,22 @@ .cia_decrypt = xtea_decrypt } } }; + +static struct crypto_alg xeta_alg = { + .cra_name = "xeta", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = XTEA_BLOCK_SIZE, + .cra_ctxsize = sizeof (struct xtea_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(xtea_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = XTEA_KEY_SIZE, + .cia_max_keysize = XTEA_KEY_SIZE, + .cia_setkey = xtea_setkey, + .cia_encrypt = xeta_encrypt, + .cia_decrypt = xeta_decrypt } } +}; + static int __init init(void) { int ret = 0; @@ -229,6 +294,13 @@ goto out; } + ret = crypto_register_alg(&xeta_alg); + if (ret < 0) { + crypto_unregister_alg(&tea_alg); + crypto_unregister_alg(&xtea_alg); + goto out; + } + out: return ret; } @@ -237,10 +309,11 @@ { crypto_unregister_alg(&tea_alg); crypto_unregister_alg(&xtea_alg); + crypto_unregister_alg(&xeta_alg); } module_init(init); module_exit(fini); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("TEA & XTEA Cryptographic Algorithms"); +MODULE_DESCRIPTION("TEA, XTEA & XETA Cryptographic Algorithms"); diff -urN linux-2.4.31/drivers/block/cciss.c linux-2.4.32/drivers/block/cciss.c --- linux-2.4.31/drivers/block/cciss.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/drivers/block/cciss.c 2005-11-16 11:12:54.597077378 -0800 @@ -1,6 +1,6 @@ /* * Disk Array driver for HP SA 5xxx and 6xxx Controllers - * Copyright 2000, 2002 Hewlett-Packard Development Company, L.P. + * Copyright 2000, 2005 Hewlett-Packard Development Company, L.P. * * 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 @@ -45,13 +45,13 @@ #include #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 2.4.52)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,52) +#define DRIVER_NAME "HP CISS Driver (v 2.4.60)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,60) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); MODULE_DESCRIPTION("Driver for HP SA5xxx SA6xxx Controllers version 2.4.52"); -MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400 6i SA6422 V100"); +MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400 6i SA6422 P600 P400 P400i E200i E200"); MODULE_LICENSE("GPL"); #include "cciss_cmd.h" @@ -80,8 +80,24 @@ 0x0E11, 0x4091, 0, 0, 0}, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409E, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISS, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA, + 0x103C, 0x3225, 0, 0, 0}, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, + 0x103C, 0x3234, 0, 0, 0}, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, + 0x103C, 0x3235, 0, 0, 0}, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3211, 0, 0, 0}, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, + 0x103C, 0x3212, 0, 0, 0}, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, + 0x103C, 0x3213, 0, 0, 0}, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, + 0x103C, 0x3214, 0, 0, 0}, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, + 0x103C, 0x3215, 0, 0, 0}, + { PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, {0,} }; MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); @@ -103,7 +119,14 @@ { 0x409D0E11, "Smart Array 6400 EM", &SA5_access}, { 0x40910E11, "Smart Array 6i", &SA5_access}, { 0x409E0E11, "Smart Array 6422", &SA5_access}, - { 0x3211103C, "Smart Array V100", &SA5_access}, + { 0x3234103c, "Smart Array P400", &SA5_access}, + { 0x3235103c, "Smart Array P400i", &SA5_access}, + { 0x3211103c, "Smart Array E200i", &SA5_access}, + { 0x3212103c, "Smart Array E200", &SA5_access}, + { 0x3213103c, "Smart Array E200i", &SA5_access}, + { 0x3214103c, "Smart Array E200i", &SA5_access}, + { 0x3215103c, "Smart Array E200i", &SA5_access}, + { 0xFFFF103C, "Unknown Smart Array", &SA5_access}, }; /* How long to wait (in millesconds) for board to go into simple mode */ @@ -2805,12 +2828,6 @@ break; } } - if (i == NR_PRODUCTS) { - printk(KERN_WARNING "cciss: Sorry, I don't know how" - " to access the Smart Array controller %08lx\n", - (unsigned long)board_id); - return -1; - } if ( (readb(&c->cfgtable->Signature[0]) != 'C') || (readb(&c->cfgtable->Signature[1]) != 'I') || (readb(&c->cfgtable->Signature[2]) != 'S') || @@ -2818,6 +2835,25 @@ printk("Does not appear to be a valid CISS config table\n"); return -1; } + /* We didn't find the controller in our list. We know the + * signature is valid. If it's an HP device let's try to + * bind to the device and fire it up. Otherwise we bail. + */ + if (i == NR_PRODUCTS) { + if (subsystem_vendor_id == PCI_VENDOR_ID_HP) { + c->product_name = products[NR_PRODUCTS-1].product_name; + c->access = *(products[NR_PRODUCTS-1].access); + printk(KERN_WARNING "cciss: This is an unknown " + "Smart Array controller.\n" + "cciss: Please update to the latest driver " + "available from www.hp.com.\n"); + } else { + printk(KERN_WARNING "cciss: Sorry, I don't know how" + " to access the Smart Array controller %08lx\n" + , (unsigned long)board_id); + return -1; + } + } #ifdef CONFIG_X86 { diff -urN linux-2.4.31/drivers/bluetooth/bfusb.c linux-2.4.32/drivers/bluetooth/bfusb.c --- linux-2.4.31/drivers/bluetooth/bfusb.c 2004-08-07 16:26:04.000000000 -0700 +++ linux-2.4.32/drivers/bluetooth/bfusb.c 2005-11-16 11:12:54.598077422 -0800 @@ -470,12 +470,11 @@ return 0; write_lock_irqsave(&bfusb->lock, flags); + write_unlock_irqrestore(&bfusb->lock, flags); bfusb_unlink_urbs(bfusb); bfusb_flush(hdev); - write_unlock_irqrestore(&bfusb->lock, flags); - MOD_DEC_USE_COUNT; return 0; diff -urN linux-2.4.31/drivers/bluetooth/hci_usb.c linux-2.4.32/drivers/bluetooth/hci_usb.c --- linux-2.4.31/drivers/bluetooth/hci_usb.c 2004-08-07 16:26:04.000000000 -0700 +++ linux-2.4.32/drivers/bluetooth/hci_usb.c 2005-11-16 11:12:54.598077422 -0800 @@ -398,13 +398,13 @@ BT_DBG("%s", hdev->name); + /* Synchronize with completion handlers */ write_lock_irqsave(&husb->completion_lock, flags); - + write_unlock_irqrestore(&husb->completion_lock, flags); + hci_usb_unlink_urbs(husb); hci_usb_flush(hdev); - write_unlock_irqrestore(&husb->completion_lock, flags); - MOD_DEC_USE_COUNT; return 0; } diff -urN linux-2.4.31/drivers/char/cyclades.c linux-2.4.32/drivers/char/cyclades.c --- linux-2.4.31/drivers/char/cyclades.c 2005-01-19 06:09:44.000000000 -0800 +++ linux-2.4.32/drivers/char/cyclades.c 2005-11-16 11:12:54.602077600 -0800 @@ -2960,10 +2960,15 @@ cy_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info; unsigned long flags; int c, ret = 0; + if (!tty) + return 0; + + info = (struct cyclades_port *)tty->driver_data; + #ifdef CY_DEBUG_IO printk("cyc:cy_write ttyC%d\n", info->line); /* */ #endif @@ -2972,7 +2977,7 @@ return 0; } - if (!tty || !info->xmit_buf || !tmp_buf){ + if (!info->xmit_buf || !tmp_buf){ return 0; } @@ -3047,9 +3052,14 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info; unsigned long flags; + if (!tty) + return; + + info = (struct cyclades_port *)tty->driver_data; + #ifdef CY_DEBUG_IO printk("cyc:cy_put_char ttyC%d\n", info->line); #endif @@ -3057,7 +3067,7 @@ if (serial_paranoia_check(info, tty->device, "cy_put_char")) return; - if (!tty || !info->xmit_buf) + if (!info->xmit_buf) return; CY_LOCK(info, flags); diff -urN linux-2.4.31/drivers/char/esp.c linux-2.4.32/drivers/char/esp.c --- linux-2.4.31/drivers/char/esp.c 2005-01-19 06:09:45.000000000 -0800 +++ linux-2.4.32/drivers/char/esp.c 2005-11-16 11:12:54.604077690 -0800 @@ -1251,13 +1251,18 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch) { - struct esp_struct *info = (struct esp_struct *)tty->driver_data; + struct esp_struct *info; unsigned long flags; + if (!tty) + return; + + info = (struct esp_struct *)tty->driver_data; + if (serial_paranoia_check(info, tty->device, "rs_put_char")) return; - if (!tty || !info->xmit_buf) + if (!info->xmit_buf) return; save_flags(flags); cli(); @@ -1296,13 +1301,19 @@ const unsigned char *buf, int count) { int c, t, ret = 0; - struct esp_struct *info = (struct esp_struct *)tty->driver_data; + struct esp_struct *info; unsigned long flags; + + if (!tty) + return 0; + + info = (struct esp_struct *)tty->driver_data; + if (serial_paranoia_check(info, tty->device, "rs_write")) return 0; - if (!tty || !info->xmit_buf || !tmp_buf) + if (!info->xmit_buf || !tmp_buf) return 0; if (from_user) diff -urN linux-2.4.31/drivers/char/isicom.c linux-2.4.32/drivers/char/isicom.c --- linux-2.4.31/drivers/char/isicom.c 2005-01-19 06:09:46.000000000 -0800 +++ linux-2.4.32/drivers/char/isicom.c 2005-11-16 11:12:54.605077734 -0800 @@ -1223,9 +1223,15 @@ static int isicom_write(struct tty_struct * tty, int from_user, const unsigned char * buf, int count) { - struct isi_port * port = (struct isi_port *) tty->driver_data; + struct isi_port * port; unsigned long flags; int cnt, total = 0; + + if (!tty) + return 0; + + port = (struct isi_port *) tty->driver_data; + #ifdef ISICOM_DEBUG printk(KERN_DEBUG "ISICOM: isicom_write for port%d: %d bytes.\n", port->channel+1, count); @@ -1233,7 +1239,7 @@ if (isicom_paranoia_check(port, tty->device, "isicom_write")) return 0; - if (!tty || !port->xmit_buf || !tmp_buf) + if (!port->xmit_buf || !tmp_buf) return 0; if (from_user) down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */ @@ -1281,13 +1287,18 @@ /* put_char et all */ static void isicom_put_char(struct tty_struct * tty, unsigned char ch) { - struct isi_port * port = (struct isi_port *) tty->driver_data; + struct isi_port * port; unsigned long flags; + + if (!tty) + return; + + port = (struct isi_port *) tty->driver_data; if (isicom_paranoia_check(port, tty->device, "isicom_put_char")) return; - if (!tty || !port->xmit_buf) + if (!port->xmit_buf) return; #ifdef ISICOM_DEBUG printk(KERN_DEBUG "ISICOM: put_char, port %d, char %c.\n", port->channel+1, ch); diff -urN linux-2.4.31/drivers/char/mxser.c linux-2.4.32/drivers/char/mxser.c --- linux-2.4.31/drivers/char/mxser.c 2005-01-19 06:09:47.000000000 -0800 +++ linux-2.4.32/drivers/char/mxser.c 2005-11-16 11:12:54.607077823 -0800 @@ -911,10 +911,15 @@ const unsigned char *buf, int count) { int c, total = 0; - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info; unsigned long flags; - if (!tty || !info->xmit_buf || !mxvar_tmp_buf) + if (!tty) + return (0); + + info = (struct mxser_struct *) tty->driver_data; + + if (!info->xmit_buf || !mxvar_tmp_buf) return (0); save_flags(flags); @@ -979,10 +984,15 @@ static void mxser_put_char(struct tty_struct *tty, unsigned char ch) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info; unsigned long flags; - if (!tty || !info->xmit_buf) + if (!tty) + return; + + info = (struct mxser_struct *) tty->driver_data; + + if (!info->xmit_buf) return; save_flags(flags); diff -urN linux-2.4.31/drivers/char/riscom8.c linux-2.4.32/drivers/char/riscom8.c --- linux-2.4.31/drivers/char/riscom8.c 2005-01-19 06:09:49.000000000 -0800 +++ linux-2.4.32/drivers/char/riscom8.c 2005-11-16 11:12:54.608077868 -0800 @@ -1220,17 +1220,22 @@ static int rc_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { - struct riscom_port *port = (struct riscom_port *)tty->driver_data; + struct riscom_port *port; struct riscom_board *bp; int c, total = 0; unsigned long flags; + + if (!tty) + return 0; + + port = (struct riscom_port *)tty->driver_data; if (rc_paranoia_check(port, tty->device, "rc_write")) return 0; bp = port_Board(port); - if (!tty || !port->xmit_buf || !tmp_buf) + if (!port->xmit_buf || !tmp_buf) return 0; save_flags(flags); @@ -1298,13 +1303,18 @@ static void rc_put_char(struct tty_struct * tty, unsigned char ch) { - struct riscom_port *port = (struct riscom_port *)tty->driver_data; + struct riscom_port *port; unsigned long flags; + if (!tty) + return; + + port = (struct riscom_port *)tty->driver_data; + if (rc_paranoia_check(port, tty->device, "rc_put_char")) return; - if (!tty || !port->xmit_buf) + if (!port->xmit_buf) return; save_flags(flags); cli(); diff -urN linux-2.4.31/drivers/char/serial.c linux-2.4.32/drivers/char/serial.c --- linux-2.4.31/drivers/char/serial.c 2005-01-19 06:09:50.000000000 -0800 +++ linux-2.4.32/drivers/char/serial.c 2005-11-16 11:12:54.612078046 -0800 @@ -1827,13 +1827,18 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch) { - struct async_struct *info = (struct async_struct *)tty->driver_data; + struct async_struct *info; unsigned long flags; + if (!tty) + return; + + info = (struct async_struct *)tty->driver_data; + if (serial_paranoia_check(info, tty->device, "rs_put_char")) return; - if (!tty || !info->xmit.buf) + if (!info->xmit.buf) return; save_flags(flags); cli(); @@ -1873,13 +1878,18 @@ const unsigned char *buf, int count) { int c, ret = 0; - struct async_struct *info = (struct async_struct *)tty->driver_data; + struct async_struct *info; unsigned long flags; + if (!tty) + return 0; + + info = (struct async_struct *)tty->driver_data; + if (serial_paranoia_check(info, tty->device, "rs_write")) return 0; - if (!tty || !info->xmit.buf || !tmp_buf) + if (!info->xmit.buf || !tmp_buf) return 0; save_flags(flags); diff -urN linux-2.4.31/drivers/char/specialix.c linux-2.4.32/drivers/char/specialix.c --- linux-2.4.31/drivers/char/specialix.c 2005-01-19 06:09:51.000000000 -0800 +++ linux-2.4.32/drivers/char/specialix.c 2005-11-16 11:12:54.613078091 -0800 @@ -1600,17 +1600,22 @@ static int sx_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port; struct specialix_board *bp; int c, total = 0; unsigned long flags; + + if (!tty) + return 0; + + port = (struct specialix_port *)tty->driver_data; if (sx_paranoia_check(port, tty->device, "sx_write")) return 0; bp = port_Board(port); - if (!tty || !port->xmit_buf || !tmp_buf) + if (!port->xmit_buf || !tmp_buf) return 0; save_flags(flags); @@ -1676,13 +1681,18 @@ static void sx_put_char(struct tty_struct * tty, unsigned char ch) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port; unsigned long flags; + if (!tty) + return; + + port = (struct specialix_port *)tty->driver_data; + if (sx_paranoia_check(port, tty->device, "sx_put_char")) return; - if (!tty || !port->xmit_buf) + if (!port->xmit_buf) return; save_flags(flags); cli(); diff -urN linux-2.4.31/drivers/char/vt.c linux-2.4.32/drivers/char/vt.c --- linux-2.4.31/drivers/char/vt.c 2005-01-19 06:09:53.000000000 -0800 +++ linux-2.4.32/drivers/char/vt.c 2005-11-16 11:12:54.614078135 -0800 @@ -166,6 +166,9 @@ if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS) return -EINVAL; + if (!capable(CAP_SYS_TTY_CONFIG)) + perm = 0; + switch (cmd) { case KDGKBENT: key_map = key_maps[s]; @@ -276,6 +279,9 @@ char *first_free, *fj, *fnw; int i, j, k; + if (!capable(CAP_SYS_TTY_CONFIG)) + perm = 0; + /* we mostly copy too much here (512bytes), but who cares ;) */ if (copy_from_user(&tmp, user_kdgkb, sizeof(struct kbsentry))) return -EFAULT; diff -urN linux-2.4.31/drivers/md/md.c linux-2.4.32/drivers/md/md.c --- linux-2.4.31/drivers/md/md.c 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.32/drivers/md/md.c 2005-11-16 11:12:54.616078224 -0800 @@ -1271,148 +1271,164 @@ memcpy (sb, freshest->sb, sizeof(*sb)); /* - * at this point we have picked the 'best' superblock - * from all available superblocks. - * now we validate this superblock and kick out possibly - * failed disks. + * For multipathing, lots of things are different from "true" + * RAIDs. + * All rdev's could be read, so they are no longer faulty. + * As there is just one sb, trying to find changed devices via the + * this_disk pointer is useless too. + * + * lmb@suse.de, 2002-09-12 */ - ITERATE_RDEV(mddev,rdev,tmp) { - /* - * Kick all non-fresh devices - */ - __u64 ev1, ev2; - ev1 = md_event(rdev->sb); - ev2 = md_event(sb); - ++ev1; - if (ev1 < ev2) { - printk(KERN_WARNING "md: kicking non-fresh %s from array!\n", - partition_name(rdev->dev)); - kick_rdev_from_array(rdev); - continue; - } - } - /* - * Fix up changed device names ... but only if this disk has a - * recent update time. Use faulty checksum ones too. - */ - if (mddev->sb->level != -4) - ITERATE_RDEV(mddev,rdev,tmp) { - __u64 ev1, ev2, ev3; - if (rdev->faulty || rdev->alias_device) { - MD_BUG(); - goto abort; - } - ev1 = md_event(rdev->sb); - ev2 = md_event(sb); - ev3 = ev2; - --ev3; - if ((rdev->dev != rdev->old_dev) && - ((ev1 == ev2) || (ev1 == ev3))) { + if (sb->level == -4) { + int desc_nr = 0; + + /* ... and initialize from the current rdevs instead */ + ITERATE_RDEV(mddev,rdev,tmp) { mdp_disk_t *desc; - printk(KERN_WARNING "md: device name has changed from %s to %s since last import!\n", - partition_name(rdev->old_dev), partition_name(rdev->dev)); - if (rdev->desc_nr == -1) { - MD_BUG(); - goto abort; - } + rdev->desc_nr=desc_nr; + desc = &sb->disks[rdev->desc_nr]; - if (rdev->old_dev != MKDEV(desc->major, desc->minor)) { - MD_BUG(); - goto abort; - } - desc->major = MAJOR(rdev->dev); - desc->minor = MINOR(rdev->dev); - desc = &rdev->sb->this_disk; + + desc->number = desc_nr; desc->major = MAJOR(rdev->dev); desc->minor = MINOR(rdev->dev); - } - } + desc->raid_disk = desc_nr; - /* - * Remove unavailable and faulty devices ... - * - * note that if an array becomes completely unrunnable due to - * missing devices, we do not write the superblock back, so the - * administrator has a chance to fix things up. The removal thus - * only happens if it's nonfatal to the contents of the array. - */ - for (i = 0; i < MD_SB_DISKS; i++) { - int found; - mdp_disk_t *desc; - kdev_t dev; + /* We could read from it, so it isn't faulty + * any longer */ + if (disk_faulty(desc)) + mark_disk_spare(desc); - desc = sb->disks + i; - dev = MKDEV(desc->major, desc->minor); + memcpy(&rdev->sb->this_disk,desc,sizeof(*desc)); + + desc_nr++; + } + /* Kick out all old info about disks we used to have, + * if any */ + for (i = desc_nr; i < MD_SB_DISKS; i++) + memset(&(sb->disks[i]),0,sizeof(mdp_disk_t)); + } else { /* - * We kick faulty devices/descriptors immediately. - * - * Note: multipath devices are a special case. Since we - * were able to read the superblock on the path, we don't - * care if it was previously marked as faulty, it's up now - * so enable it. + * at this point we have picked the 'best' superblock + * from all available superblocks. + * now we validate this superblock and kick out possibly + * failed disks. */ - if (disk_faulty(desc) && mddev->sb->level != -4) { - found = 0; - ITERATE_RDEV(mddev,rdev,tmp) { - if (rdev->desc_nr != desc->number) - continue; - printk(KERN_WARNING "md%d: kicking faulty %s!\n", - mdidx(mddev),partition_name(rdev->dev)); - kick_rdev_from_array(rdev); - found = 1; - break; - } - if (!found) { - if (dev == MKDEV(0,0)) - continue; - printk(KERN_WARNING "md%d: removing former faulty %s!\n", - mdidx(mddev), partition_name(dev)); - } - remove_descriptor(desc, sb); - continue; - } else if (disk_faulty(desc)) { + ITERATE_RDEV(mddev,rdev,tmp) { /* - * multipath entry marked as faulty, unfaulty it + * Kick all non-fresh devices */ - rdev = find_rdev(mddev, dev); - if(rdev) - mark_disk_spare(desc); - else - remove_descriptor(desc, sb); + __u64 ev1, ev2; + ev1 = md_event(rdev->sb); + ev2 = md_event(sb); + ++ev1; + if (ev1 < ev2) { + printk(KERN_WARNING "md: kicking non-fresh %s from array!\n", + partition_name(rdev->dev)); + kick_rdev_from_array(rdev); + continue; + } } - if (dev == MKDEV(0,0)) - continue; /* - * Is this device present in the rdev ring? + * Fix up changed device names ... but only if this disk has a + * recent update time. Use faulty checksum ones too. */ - found = 0; ITERATE_RDEV(mddev,rdev,tmp) { + __u64 ev1, ev2, ev3; + if (rdev->faulty || rdev->alias_device) { + MD_BUG(); + goto abort; + } + ev1 = md_event(rdev->sb); + ev2 = md_event(sb); + ev3 = ev2; + --ev3; + if ((rdev->dev != rdev->old_dev) && + ((ev1 == ev2) || (ev1 == ev3))) { + mdp_disk_t *desc; + + printk(KERN_WARNING "md: device name has changed from %s to %s since last import!\n", + partition_name(rdev->old_dev), partition_name(rdev->dev)); + if (rdev->desc_nr == -1) { + MD_BUG(); + goto abort; + } + desc = &sb->disks[rdev->desc_nr]; + if (rdev->old_dev != MKDEV(desc->major, desc->minor)) { + MD_BUG(); + goto abort; + } + desc->major = MAJOR(rdev->dev); + desc->minor = MINOR(rdev->dev); + desc = &rdev->sb->this_disk; + desc->major = MAJOR(rdev->dev); + desc->minor = MINOR(rdev->dev); + } + } + + /* + * Remove unavailable and faulty devices ... + * + * note that if an array becomes completely unrunnable due to + * missing devices, we do not write the superblock back, so the + * administrator has a chance to fix things up. The removal thus + * only happens if it's nonfatal to the contents of the array. + */ + for (i = 0; i < MD_SB_DISKS; i++) { + int found; + mdp_disk_t *desc; + kdev_t dev; + + desc = sb->disks + i; + dev = MKDEV(desc->major, desc->minor); + /* - * Multi-path IO special-case: since we have no - * this_disk descriptor at auto-detect time, - * we cannot check rdev->number. - * We can check the device though. + * We kick faulty devices/descriptors immediately. */ - if ((sb->level == -4) && (rdev->dev == - MKDEV(desc->major,desc->minor))) { - found = 1; - break; + if (disk_faulty(desc)) { + found = 0; + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->desc_nr != desc->number) + continue; + printk(KERN_WARNING "md%d: kicking faulty %s!\n", + mdidx(mddev),partition_name(rdev->dev)); + kick_rdev_from_array(rdev); + found = 1; + break; + } + if (!found) { + if (dev == MKDEV(0,0)) + continue; + printk(KERN_WARNING "md%d: removing former faulty %s!\n", + mdidx(mddev), partition_name(dev)); + } + remove_descriptor(desc, sb); + continue; } - if (rdev->desc_nr == desc->number) { - found = 1; - break; + + if (dev == MKDEV(0,0)) + continue; + /* + * Is this device present in the rdev ring? + */ + found = 0; + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->desc_nr == desc->number) { + found = 1; + break; + } } - } - if (found) - continue; + if (found) + continue; - printk(KERN_WARNING "md%d: former device %s is unavailable, removing from array!\n", - mdidx(mddev), partition_name(dev)); - remove_descriptor(desc, sb); + printk(KERN_WARNING "md%d: former device %s is unavailable, removing from array!\n", + mdidx(mddev), partition_name(dev)); + remove_descriptor(desc, sb); + } } /* diff -urN linux-2.4.31/drivers/scsi/ahci.c linux-2.4.32/drivers/scsi/ahci.c --- linux-2.4.31/drivers/scsi/ahci.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/drivers/scsi/ahci.c 2005-11-16 11:12:54.617078269 -0800 @@ -38,7 +38,8 @@ #include #define DRV_NAME "ahci" -#define DRV_VERSION "1.00" +#define DRV_VERSION "1.01" + enum { AHCI_PCI_BAR = 5, @@ -48,6 +49,7 @@ AHCI_CMD_SLOT_SZ = 32 * 32, AHCI_RX_FIS_SZ = 256, AHCI_CMD_TBL_HDR = 0x80, + AHCI_CMD_TBL_CDB = 0x40, AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16), AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ + AHCI_RX_FIS_SZ, @@ -132,6 +134,9 @@ PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */ PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */ PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */ + + /* hpriv->flags bits */ + AHCI_FLAG_MSI = (1 << 0), }; struct ahci_cmd_hdr { @@ -181,13 +186,14 @@ static u8 ahci_check_status(struct ata_port *ap); static u8 ahci_check_err(struct ata_port *ap); static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); +static void ahci_remove_one (struct pci_dev *pdev); static Scsi_Host_Template ahci_sht = { .module = THIS_MODULE, .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, .detect = ata_scsi_detect, .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -256,6 +262,12 @@ board_ahci }, /* ICH7R */ { PCI_VENDOR_ID_AL, 0x5288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ULi M5288 */ + { PCI_VENDOR_ID_INTEL, 0x2681, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* ESB2 */ + { PCI_VENDOR_ID_INTEL, 0x2682, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* ESB2 */ + { PCI_VENDOR_ID_INTEL, 0x2683, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* ESB2 */ { } /* terminate list */ }; @@ -264,7 +276,7 @@ .name = DRV_NAME, .id_table = ahci_pci_tbl, .probe = ahci_init_one, - .remove = ata_pci_remove_one, + .remove = ahci_remove_one, }; @@ -282,6 +294,8 @@ { struct ahci_host_priv *hpriv = host_set->private_data; kfree(hpriv); + + ata_host_stop(host_set); } static int ahci_port_start(struct ata_port *ap) @@ -289,26 +303,19 @@ struct device *dev = ap->host_set->dev; struct ahci_host_priv *hpriv = ap->host_set->private_data; struct ahci_port_priv *pp; - int rc; void *mem, *mmio = ap->host_set->mmio_base; void *port_mmio = ahci_port_base(mmio, ap->port_no); dma_addr_t mem_dma; - rc = ata_port_start(ap); - if (rc) - return rc; - pp = kmalloc(sizeof(*pp), GFP_KERNEL); - if (!pp) { - rc = -ENOMEM; - goto err_out; - } + if (!pp) + return -ENOMEM; memset(pp, 0, sizeof(*pp)); mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); if (!mem) { - rc = -ENOMEM; - goto err_out_kfree; + kfree(pp); + return -ENOMEM; } memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ); @@ -358,12 +365,6 @@ readl(port_mmio + PORT_CMD); /* flush */ return 0; - -err_out_kfree: - kfree(pp); -err_out: - ata_port_stop(ap); - return rc; } @@ -389,7 +390,6 @@ dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, pp->cmd_slot, pp->cmd_slot_dma); kfree(pp); - ata_port_stop(ap); } static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in) @@ -496,7 +496,8 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) { - struct ahci_port_priv *pp = qc->ap->private_data; + struct ata_port *ap = qc->ap; + struct ahci_port_priv *pp = ap->private_data; u32 opts; const u32 cmd_fis_len = 5; /* five dwords */ @@ -508,18 +509,8 @@ opts = (qc->n_elem << 16) | cmd_fis_len; if (qc->tf.flags & ATA_TFLAG_WRITE) opts |= AHCI_CMD_WRITE; - - switch (qc->tf.protocol) { - case ATA_PROT_ATAPI: - case ATA_PROT_ATAPI_NODATA: - case ATA_PROT_ATAPI_DMA: + if (is_atapi_taskfile(&qc->tf)) opts |= AHCI_CMD_ATAPI; - break; - - default: - /* do nothing */ - break; - } pp->cmd_slot[0].opts = cpu_to_le32(opts); pp->cmd_slot[0].status = 0; @@ -531,6 +522,10 @@ * a SATA Register - Host to Device command FIS. */ ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0); + if (opts & AHCI_CMD_ATAPI) { + memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); + memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len); + } if (!(qc->flags & ATA_QCFLAG_DMAMAP)) return; @@ -853,15 +848,19 @@ } /* move to PCI layer, integrate w/ MSI stuff */ -static void pci_enable_intx(struct pci_dev *pdev) +static void pci_intx(struct pci_dev *pdev, int enable) { - u16 pci_command; + u16 pci_command, new; pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - if (pci_command & PCI_COMMAND_INTX_DISABLE) { - pci_command &= ~PCI_COMMAND_INTX_DISABLE; + + if (enable) + new = pci_command & ~PCI_COMMAND_INTX_DISABLE; + else + new = pci_command | PCI_COMMAND_INTX_DISABLE; + + if (new != pci_command) pci_write_config_word(pdev, PCI_COMMAND, pci_command); - } } static void ahci_print_info(struct ata_probe_ent *probe_ent) @@ -943,7 +942,7 @@ unsigned long base; void *mmio_base; unsigned int board_idx = (unsigned int) ent->driver_data; - int pci_dev_busy = 0; + int have_msi, pci_dev_busy = 0; int rc; VPRINTK("ENTER\n"); @@ -961,12 +960,17 @@ goto err_out; } - pci_enable_intx(pdev); + if (pci_enable_msi(pdev) == 0) + have_msi = 1; + else { + pci_intx(pdev, 1); + have_msi = 0; + } probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); if (probe_ent == NULL) { rc = -ENOMEM; - goto err_out_regions; + goto err_out_msi; } memset(probe_ent, 0, sizeof(*probe_ent)); @@ -999,6 +1003,9 @@ probe_ent->mmio_base = mmio_base; probe_ent->private_data = hpriv; + if (have_msi) + hpriv->flags |= AHCI_FLAG_MSI; + /* initialize adapter */ rc = ahci_host_init(probe_ent); if (rc) @@ -1016,7 +1023,11 @@ iounmap(mmio_base); err_out_free_ent: kfree(probe_ent); -err_out_regions: +err_out_msi: + if (have_msi) + pci_disable_msi(pdev); + else + pci_intx(pdev, 0); pci_release_regions(pdev); err_out: if (!pci_dev_busy) @@ -1024,6 +1035,38 @@ return rc; } +static void ahci_remove_one (struct pci_dev *pdev) +{ + struct device *dev = pci_dev_to_dev(pdev); + struct ata_host_set *host_set = dev_get_drvdata(dev); + struct ahci_host_priv *hpriv = host_set->private_data; + struct ata_port *ap; + Scsi_Host_Template *sht; + int have_msi, rc; + + /* FIXME: this unregisters all ports attached to the + * Scsi_Host_Template given. We _might_ have multiple + * templates (though we don't ATM), so this is ok... for now. + */ + ap = host_set->ports[0]; + sht = ap->host->hostt; + rc = scsi_unregister_module(MODULE_SCSI_HA, sht); + /* FIXME: handle 'rc' failure? */ + + have_msi = hpriv->flags & AHCI_FLAG_MSI; + free_irq(host_set->irq, host_set); + + host_set->ops->host_stop(host_set); + kfree(host_set); + + if (have_msi) + pci_disable_msi(pdev); + else + pci_intx(pdev, 0); + pci_release_regions(pdev); + pci_disable_device(pdev); + dev_set_drvdata(dev, NULL); +} static int __init ahci_init(void) { diff -urN linux-2.4.31/drivers/scsi/ata_piix.c linux-2.4.32/drivers/scsi/ata_piix.c --- linux-2.4.31/drivers/scsi/ata_piix.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/ata_piix.c 2005-11-16 11:12:54.618078314 -0800 @@ -61,6 +61,7 @@ ich6_sata = 3, ich6_sata_rm = 4, ich7_sata = 5, + esb2_sata = 6, }; static int piix_init_one (struct pci_dev *pdev, @@ -93,6 +94,7 @@ { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm }, { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata }, { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata }, + { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb2_sata }, { } /* terminate list */ }; @@ -151,6 +153,7 @@ .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_operations piix_sata_ops = { @@ -178,6 +181,7 @@ .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info piix_port_info[] = { @@ -256,6 +260,18 @@ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, + + /* esb2_sata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | + PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR | + ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &piix_sata_ops, + }, }; static struct pci_bits piix_enable_bits[] = { @@ -650,15 +666,6 @@ return ata_pci_init_one(pdev, port_info, n_ports); } -/** - * piix_init - - * - * LOCKING: - * - * RETURNS: - * - */ - static int __init piix_init(void) { int rc; @@ -685,13 +692,6 @@ return rc; } -/** - * piix_exit - - * - * LOCKING: - * - */ - static void __exit piix_exit(void) { scsi_unregister_module(MODULE_SCSI_HA, &piix_sht); diff -urN linux-2.4.31/drivers/scsi/libata-core.c linux-2.4.32/drivers/scsi/libata-core.c --- linux-2.4.31/drivers/scsi/libata-core.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/libata-core.c 2005-11-16 11:12:54.622078492 -0800 @@ -185,6 +185,28 @@ ata_wait_idle(ap); } + +/** + * ata_tf_load - send taskfile registers to host controller + * @ap: Port to which output is sent + * @tf: ATA taskfile register set + * + * Outputs ATA taskfile to standard ATA host controller using MMIO + * or PIO as indicated by the ATA_FLAG_MMIO flag. + * Writes the control, feature, nsect, lbal, lbam, and lbah registers. + * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect, + * hob_lbal, hob_lbam, and hob_lbah. + * + * This function waits for idle (!BUSY and !DRQ) after writing + * registers. If the control register has a new value, this + * function also waits for idle after writing control and before + * writing the remaining registers. + * + * May be used as the tf_load() entry in ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf) { if (ap->flags & ATA_FLAG_MMIO) @@ -194,11 +216,11 @@ } /** - * ata_exec_command - issue ATA command to host controller + * ata_exec_command_pio - issue ATA command to host controller * @ap: port to which command is being issued * @tf: ATA taskfile register set * - * Issues PIO/MMIO write to ATA command register, with proper + * Issues PIO write to ATA command register, with proper * synchronization with interrupt handler / other threads. * * LOCKING: @@ -234,6 +256,18 @@ ata_pause(ap); } + +/** + * ata_exec_command - issue ATA command to host controller + * @ap: port to which command is being issued + * @tf: ATA taskfile register set + * + * Issues PIO/MMIO write to ATA command register, with proper + * synchronization with interrupt handler / other threads. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf) { if (ap->flags & ATA_FLAG_MMIO) @@ -304,7 +338,7 @@ } /** - * ata_tf_read - input device's ATA taskfile shadow registers + * ata_tf_read_pio - input device's ATA taskfile shadow registers * @ap: Port from which input is read * @tf: ATA taskfile register set for storing input * @@ -367,6 +401,23 @@ } } + +/** + * ata_tf_read - input device's ATA taskfile shadow registers + * @ap: Port from which input is read + * @tf: ATA taskfile register set for storing input + * + * Reads ATA taskfile registers for currently-selected device + * into @tf. + * + * Reads nsect, lbal, lbam, lbah, and device. If ATA_TFLAG_LBA48 + * is set, also reads the hob registers. + * + * May be used as the tf_read() entry in ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { if (ap->flags & ATA_FLAG_MMIO) @@ -380,7 +431,7 @@ * @ap: port where the device is * * Reads ATA taskfile status register for currently-selected device - * and return it's value. This also clears pending interrupts + * and return its value. This also clears pending interrupts * from this device * * LOCKING: @@ -396,7 +447,7 @@ * @ap: port where the device is * * Reads ATA taskfile status register for currently-selected device - * via MMIO and return it's value. This also clears pending interrupts + * via MMIO and return its value. This also clears pending interrupts * from this device * * LOCKING: @@ -407,6 +458,20 @@ return readb((void __iomem *) ap->ioaddr.status_addr); } + +/** + * ata_check_status - Read device status reg & clear interrupt + * @ap: port where the device is + * + * Reads ATA taskfile status register for currently-selected device + * and return its value. This also clears pending interrupts + * from this device + * + * May be used as the check_status() entry in ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ u8 ata_check_status(struct ata_port *ap) { if (ap->flags & ATA_FLAG_MMIO) @@ -414,6 +479,20 @@ return ata_check_status_pio(ap); } + +/** + * ata_altstatus - Read device alternate status reg + * @ap: port where the device is + * + * Reads ATA taskfile alternate status register for + * currently-selected device and return its value. + * + * Note: may NOT be used as the check_altstatus() entry in + * ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ u8 ata_altstatus(struct ata_port *ap) { if (ap->ops->check_altstatus) @@ -424,6 +503,20 @@ return inb(ap->ioaddr.altstatus_addr); } + +/** + * ata_chk_err - Read device error reg + * @ap: port where the device is + * + * Reads ATA taskfile error register for + * currently-selected device and return its value. + * + * Note: may NOT be used as the check_err() entry in + * ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ u8 ata_chk_err(struct ata_port *ap) { if (ap->ops->check_err) @@ -872,10 +965,24 @@ } } + +/** + * ata_noop_dev_select - Select device 0/1 on ATA bus + * @ap: ATA channel to manipulate + * @device: ATA device (numbered from zero) to select + * + * This function performs no actual function. + * + * May be used as the dev_select() entry in ata_port_operations. + * + * LOCKING: + * caller. + */ void ata_noop_dev_select (struct ata_port *ap, unsigned int device) { } + /** * ata_std_dev_select - Select device 0/1 on ATA bus * @ap: ATA channel to manipulate @@ -883,7 +990,9 @@ * * Use the method defined in the ATA specification to * make either device 0, or device 1, active on the - * ATA channel. + * ATA channel. Works with both PIO and MMIO. + * + * May be used as the dev_select() entry in ata_port_operations. * * LOCKING: * caller. @@ -1185,11 +1294,47 @@ DPRINTK("EXIT, err\n"); } + +static inline u8 ata_dev_knobble(struct ata_port *ap) +{ + return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id))); +} + +/** + * ata_dev_config - Run device specific handlers and check for + * SATA->PATA bridges + * @ap: Bus + * @i: Device + * + * LOCKING: + */ + +void ata_dev_config(struct ata_port *ap, unsigned int i) +{ + /* limit bridge transfers to udma5, 200 sectors */ + if (ata_dev_knobble(ap)) { + printk(KERN_INFO "ata%u(%u): applying bridge limits\n", + ap->id, ap->device->devno); + ap->udma_mask &= ATA_UDMA5; + ap->host->max_sectors = ATA_MAX_SECTORS; + ap->host->hostt->max_sectors = ATA_MAX_SECTORS; + ap->device->flags |= ATA_DFLAG_LOCK_SECTORS; + } + + if (ap->ops->dev_config) + ap->ops->dev_config(ap, &ap->device[i]); +} + /** * ata_bus_probe - Reset and probe ATA bus * @ap: Bus to probe * + * Master ATA bus probing function. Initiates a hardware-dependent + * bus reset, then attempts to identify any devices found on + * the bus. + * * LOCKING: + * PCI/etc. bus probe sem. * * RETURNS: * Zero on success, non-zero on error. @@ -1207,8 +1352,7 @@ ata_dev_identify(ap, i); if (ata_dev_present(&ap->device[i])) { found = 1; - if (ap->ops->dev_config) - ap->ops->dev_config(ap, &ap->device[i]); + ata_dev_config(ap,i); } } @@ -1228,10 +1372,14 @@ } /** - * ata_port_probe - - * @ap: + * ata_port_probe - Mark port as enabled + * @ap: Port for which we indicate enablement * - * LOCKING: + * Modify @ap data structure such that the system + * thinks that the entire port is enabled. + * + * LOCKING: host_set lock, or some other form of + * serialization. */ void ata_port_probe(struct ata_port *ap) @@ -1240,10 +1388,15 @@ } /** - * __sata_phy_reset - - * @ap: + * __sata_phy_reset - Wake/reset a low-level SATA PHY + * @ap: SATA port associated with target SATA PHY. + * + * This function issues commands to standard SATA Sxxx + * PHY registers, to wake up the phy (and device), and + * clear any reset condition. * * LOCKING: + * PCI/etc. bus probe sem. * */ void __sata_phy_reset(struct ata_port *ap) @@ -1252,11 +1405,13 @@ unsigned long timeout = jiffies + (HZ * 5); if (ap->flags & ATA_FLAG_SATA_RESET) { - scr_write(ap, SCR_CONTROL, 0x301); /* issue phy wake/reset */ - scr_read(ap, SCR_STATUS); /* dummy read; flush */ - udelay(400); /* FIXME: a guess */ + /* issue phy wake/reset */ + scr_write_flush(ap, SCR_CONTROL, 0x301); + /* Couldn't find anything in SATA I/II specs, but + * AHCI-1.1 10.4.2 says at least 1 ms. */ + mdelay(1); } - scr_write(ap, SCR_CONTROL, 0x300); /* issue phy wake/clear reset */ + scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */ /* wait for phy to become ready, if necessary */ do { @@ -1288,10 +1443,14 @@ } /** - * __sata_phy_reset - - * @ap: + * sata_phy_reset - Reset SATA bus. + * @ap: SATA port associated with target SATA PHY. + * + * This function resets the SATA bus, and then probes + * the bus for devices. * * LOCKING: + * PCI/etc. bus probe sem. * */ void sata_phy_reset(struct ata_port *ap) @@ -1303,10 +1462,16 @@ } /** - * ata_port_disable - - * @ap: + * ata_port_disable - Disable port. + * @ap: Port to be disabled. * - * LOCKING: + * Modify @ap data structure such that the system + * thinks that the entire port is disabled, and should + * never attempt to probe or communicate with devices + * on this port. + * + * LOCKING: host_set lock, or some other form of + * serialization. */ void ata_port_disable(struct ata_port *ap) @@ -1415,7 +1580,10 @@ * ata_set_mode - Program timings and issue SET FEATURES - XFER * @ap: port on which timings will be programmed * + * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). + * * LOCKING: + * PCI/etc. bus probe sem. * */ static void ata_set_mode(struct ata_port *ap) @@ -1466,7 +1634,10 @@ * @tmout_pat: impatience timeout * @tmout: overall timeout * - * LOCKING: + * Sleep until ATA Status register bit BSY clears, + * or a timeout occurs. + * + * LOCKING: None. * */ @@ -1552,10 +1723,14 @@ } /** - * ata_bus_edd - - * @ap: + * ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command. + * @ap: Port to reset and probe + * + * Use the EXECUTE DEVICE DIAGNOSTIC command to reset and + * probe the bus. Not often used these days. * * LOCKING: + * PCI/etc. bus probe sem. * */ @@ -1632,8 +1807,8 @@ * the device is ATA or ATAPI. * * LOCKING: - * Inherited from caller. Some functions called by this function - * obtain the host_set lock. + * PCI/etc. bus probe sem. + * Obtains host_set lock. * * SIDE EFFECTS: * Sets ATA_FLAG_PORT_DISABLED if bus reset fails. @@ -1746,6 +1921,7 @@ "HITACHI CDR-8335", "HITACHI CDR-8435", "Toshiba CD-ROM XM-6202B", + "TOSHIBA CD-ROM XM-1702BC", "CD-532E-A", "E-IDE CD-ROM CR-840", "CD-ROM Drive/F5A", @@ -1753,7 +1929,6 @@ "SAMSUNG CD-ROM SC-148C", "SAMSUNG CD-ROM SC", "SanDisk SDP3B-64", - "SAMSUNG CD-ROM SN-124", "ATAPI CD-ROM DRIVE 40X MAXIMUM", "_NEC DV5800A", }; @@ -1875,7 +2050,11 @@ * @xfer_mode_out: (output) SET FEATURES - XFER MODE code * @xfer_shift_out: (output) bit shift that selects this mode * + * Based on host and device capabilities, determine the + * maximum transfer mode that is amenable to all. + * * LOCKING: + * PCI/etc. bus probe sem. * * RETURNS: * Zero on success, negative on error. @@ -1908,7 +2087,11 @@ * @ap: Port associated with device @dev * @dev: Device to which command will be sent * + * Issue SET FEATURES - XFER MODE command to device @dev + * on port @ap. + * * LOCKING: + * PCI/etc. bus probe sem. */ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) @@ -1946,10 +2129,13 @@ } /** - * ata_sg_clean - - * @qc: + * ata_sg_clean - Unmap DMA memory associated with command + * @qc: Command containing DMA memory to be released + * + * Unmap all mapped DMA memory associated with this command. * * LOCKING: + * spin_lock_irqsave(host_set lock) */ static void ata_sg_clean(struct ata_queued_cmd *qc) @@ -1980,7 +2166,11 @@ * ata_fill_sg - Fill PCI IDE PRD table * @qc: Metadata associated with taskfile to be transferred * + * Fill PCI IDE PRD (scatter-gather) table with segments + * associated with the current disk command. + * * LOCKING: + * spin_lock_irqsave(host_set lock) * */ static void ata_fill_sg(struct ata_queued_cmd *qc) @@ -2027,7 +2217,13 @@ * ata_check_atapi_dma - Check whether ATAPI DMA can be supported * @qc: Metadata associated with taskfile to check * + * Allow low-level driver to filter ATA PACKET commands, returning + * a status indicating whether or not it is OK to use DMA for the + * supplied PACKET command. + * * LOCKING: + * spin_lock_irqsave(host_set lock) + * * RETURNS: 0 when ATAPI DMA can be used * nonzero otherwise */ @@ -2045,6 +2241,8 @@ * ata_qc_prep - Prepare taskfile for submission * @qc: Metadata associated with taskfile to be prepared * + * Prepare ATA taskfile for submission. + * * LOCKING: * spin_lock_irqsave(host_set lock) */ @@ -2056,6 +2254,32 @@ ata_fill_sg(qc); } +/** + * ata_sg_init_one - Associate command with memory buffer + * @qc: Command to be associated + * @buf: Memory buffer + * @buflen: Length of memory buffer, in bytes. + * + * Initialize the data-related elements of queued_cmd @qc + * to point to a single memory buffer, @buf of byte length @buflen. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + + + +/** + * ata_sg_init_one - Prepare a one-entry scatter-gather list. + * @qc: Queued command + * @buf: transfer buffer + * @buflen: length of buf + * + * Builds a single-entry scatter-gather list to initiate a + * transfer utilizing the specified buffer. + * + * LOCKING: + */ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) { struct scatterlist *sg; @@ -2070,9 +2294,35 @@ sg = qc->sg; sg->page = virt_to_page(buf); sg->offset = (unsigned long) buf & ~PAGE_MASK; - sg_dma_len(sg) = buflen; + sg->length = buflen; } +/** + * ata_sg_init - Associate command with scatter-gather table. + * @qc: Command to be associated + * @sg: Scatter-gather table. + * @n_elem: Number of elements in s/g table. + * + * Initialize the data-related elements of queued_cmd @qc + * to point to a scatter-gather table @sg, containing @n_elem + * elements. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + + +/** + * ata_sg_init - Assign a scatter gather list to a queued command + * @qc: Queued command + * @sg: Scatter-gather list + * @n_elem: length of sg list + * + * Attaches a scatter-gather list to a queued command. + * + * LOCKING: + */ + void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, unsigned int n_elem) { @@ -2082,14 +2332,16 @@ } /** - * ata_sg_setup_one - - * @qc: + * ata_sg_setup_one - DMA-map the memory buffer associated with a command. + * @qc: Command with memory buffer to be mapped. + * + * DMA-map the memory buffer associated with queued_cmd @qc. * * LOCKING: * spin_lock_irqsave(host_set lock) * * RETURNS: - * + * Zero on success, negative on error. */ static int ata_sg_setup_one(struct ata_queued_cmd *qc) @@ -2100,11 +2352,12 @@ dma_addr_t dma_address; dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt, - sg_dma_len(sg), dir); + sg->length, dir); if (dma_mapping_error(dma_address)) return -1; sg_dma_address(sg) = dma_address; + sg_dma_len(sg) = sg->length; DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg), qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); @@ -2113,13 +2366,16 @@ } /** - * ata_sg_setup - - * @qc: + * ata_sg_setup - DMA-map the scatter-gather table associated with a command. + * @qc: Command with scatter-gather table to be mapped. + * + * DMA-map the scatter-gather table associated with queued_cmd @qc. * * LOCKING: * spin_lock_irqsave(host_set lock) * * RETURNS: + * Zero on success, negative on error. * */ @@ -2149,6 +2405,7 @@ * @ap: * * LOCKING: + * None. (executing in kernel thread context) * * RETURNS: * @@ -2196,6 +2453,7 @@ * @ap: * * LOCKING: + * None. (executing in kernel thread context) */ static void ata_pio_complete (struct ata_port *ap) @@ -2238,6 +2496,18 @@ ata_qc_complete(qc, drv_stat); } + +/** + * swap_buf_le16 - + * @buf: Buffer to swap + * @buf_words: Number of 16-bit words in buffer. + * + * Swap halves of 16-bit words if needed to convert from + * little-endian byte order to native cpu byte order, or + * vice-versa. + * + * LOCKING: + */ void swap_buf_le16(u16 *buf, unsigned int buf_words) { #ifdef __BIG_ENDIAN @@ -2309,7 +2579,7 @@ qc->cursect++; qc->cursg_ofs++; - if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) { + if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) { qc->cursg++; qc->cursg_ofs = 0; } @@ -2338,7 +2608,6 @@ next_sg: sg = &qc->sg[qc->cursg]; -next_page: page = sg->page; offset = sg->offset + qc->cursg_ofs; @@ -2346,7 +2615,8 @@ page = nth_page(page, (offset >> PAGE_SHIFT)); offset %= PAGE_SIZE; - count = min(sg_dma_len(sg) - qc->cursg_ofs, bytes); + /* don't overrun current sg */ + count = min(sg->length - qc->cursg_ofs, bytes); /* don't cross page boundaries */ count = min(count, (unsigned int)PAGE_SIZE - offset); @@ -2357,7 +2627,7 @@ qc->curbytes += count; qc->cursg_ofs += count; - if (qc->cursg_ofs == sg_dma_len(sg)) { + if (qc->cursg_ofs == sg->length) { qc->cursg++; qc->cursg_ofs = 0; } @@ -2370,8 +2640,6 @@ kunmap(page); if (bytes) { - if (qc->cursg_ofs < sg_dma_len(sg)) - goto next_page; goto next_sg; } } @@ -2413,6 +2681,7 @@ * @ap: * * LOCKING: + * None. (executing in kernel thread context) */ static void ata_pio_block(struct ata_port *ap) @@ -2539,7 +2808,7 @@ ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer)); qc->dma_dir = DMA_FROM_DEVICE; - memset(&qc->cdb, 0, sizeof(ap->cdb_len)); + memset(&qc->cdb, 0, ap->cdb_len); qc->cdb[0] = REQUEST_SENSE; qc->cdb[4] = SCSI_SENSE_BUFFERSIZE; @@ -2582,6 +2851,7 @@ * transaction completed successfully. * * LOCKING: + * Inherited from SCSI layer (none, can sleep) */ static void ata_qc_timeout(struct ata_queued_cmd *qc) @@ -2691,6 +2961,7 @@ * @dev: Device from whom we request an available command structure * * LOCKING: + * None. */ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) @@ -2716,6 +2987,7 @@ * @dev: Device from whom we request an available command structure * * LOCKING: + * None. */ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, @@ -2780,6 +3052,7 @@ * in case something prevents using it. * * LOCKING: + * spin_lock_irqsave(host_set lock) * */ void ata_qc_free(struct ata_queued_cmd *qc) @@ -2793,9 +3066,13 @@ /** * ata_qc_complete - Complete an active ATA command * @qc: Command to complete - * @drv_stat: ATA status register contents + * @drv_stat: ATA Status register contents + * + * Indicate to the mid and upper layers that an ATA + * command has completed, with either an ok or not-ok status. * * LOCKING: + * spin_lock_irqsave(host_set lock) * */ @@ -2811,6 +3088,7 @@ /* call completion callback */ rc = qc->complete_fn(qc, drv_stat); + qc->flags &= ~ATA_QCFLAG_ACTIVE; /* if callback indicates not to complete command (non-zero), * return immediately @@ -2839,7 +3117,7 @@ return 1; /* fall through */ - + default: return 0; } @@ -2890,6 +3168,7 @@ return -1; } + /** * ata_qc_issue_prot - issue taskfile to device in proto-dependent manner * @qc: command to issue to device @@ -2899,6 +3178,8 @@ * classes called "protocols", and issuing each type of protocol * is slightly different. * + * May be used as the qc_issue() entry in ata_port_operations. + * * LOCKING: * spin_lock_irqsave(host_set lock) * @@ -2956,7 +3237,7 @@ } /** - * ata_bmdma_setup - Set up PCI IDE BMDMA transaction + * ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction * @qc: Info associated with this ATA transaction. * * LOCKING: @@ -3063,6 +3344,18 @@ ap->ioaddr.bmdma_addr + ATA_DMA_CMD); } + +/** + * ata_bmdma_start - Start a PCI IDE BMDMA transaction + * @qc: Info associated with this ATA transaction. + * + * Writes the ATA_DMA_START flag to the DMA command register. + * + * May be used as the bmdma_start() entry in ata_port_operations. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ void ata_bmdma_start(struct ata_queued_cmd *qc) { if (qc->ap->flags & ATA_FLAG_MMIO) @@ -3071,6 +3364,20 @@ ata_bmdma_start_pio(qc); } + +/** + * ata_bmdma_setup - Set up PCI IDE BMDMA transaction + * @qc: Info associated with this ATA transaction. + * + * Writes address of PRD table to device's PRD Table Address + * register, sets the DMA control register, and calls + * ops->exec_command() to start the transfer. + * + * May be used as the bmdma_setup() entry in ata_port_operations. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ void ata_bmdma_setup(struct ata_queued_cmd *qc) { if (qc->ap->flags & ATA_FLAG_MMIO) @@ -3079,6 +3386,19 @@ ata_bmdma_setup_pio(qc); } + +/** + * ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt. + * @ap: Port associated with this ATA transaction. + * + * Clear interrupt and error flags in DMA status register. + * + * May be used as the irq_clear() entry in ata_port_operations. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + void ata_bmdma_irq_clear(struct ata_port *ap) { if (ap->flags & ATA_FLAG_MMIO) { @@ -3091,6 +3411,19 @@ } + +/** + * ata_bmdma_status - Read PCI IDE BMDMA status + * @ap: Port associated with this ATA transaction. + * + * Read and return BMDMA status register. + * + * May be used as the bmdma_status() entry in ata_port_operations. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + u8 ata_bmdma_status(struct ata_port *ap) { u8 host_stat; @@ -3102,6 +3435,19 @@ return host_stat; } + +/** + * ata_bmdma_stop - Stop PCI IDE BMDMA transfer + * @ap: Port associated with this ATA transaction. + * + * Clears the ATA_DMA_START flag in the dma control register + * + * May be used as the bmdma_stop() entry in ata_port_operations. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + void ata_bmdma_stop(struct ata_port *ap) { if (ap->flags & ATA_FLAG_MMIO) { @@ -3201,13 +3547,18 @@ /** * ata_interrupt - Default ATA host interrupt handler - * @irq: irq line - * @dev_instance: pointer to our host information structure + * @irq: irq line (unused) + * @dev_instance: pointer to our ata_host_set information structure * @regs: unused * + * Default interrupt handler for PCI IDE devices. Calls + * ata_host_intr() for each port that is not disabled. + * * LOCKING: + * Obtains host_set lock during operation. * * RETURNS: + * IRQ_NONE or IRQ_HANDLED. * */ @@ -3229,7 +3580,8 @@ struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.ctl & ATA_NIEN)) && + (qc->flags & ATA_QCFLAG_ACTIVE)) handled |= ata_host_intr(ap, qc); } } @@ -3299,6 +3651,19 @@ ata_qc_complete(qc, ATA_ERR); } + +/** + * ata_port_start - Set port up for dma. + * @ap: Port to initialize + * + * Called just after data structures for each port are + * initialized. Allocates space for PRD table. + * + * May be used as the port_start() entry in ata_port_operations. + * + * LOCKING: + */ + int ata_port_start (struct ata_port *ap) { struct device *dev = ap->host_set->dev; @@ -3312,6 +3677,18 @@ return 0; } + +/** + * ata_port_stop - Undo ata_port_start() + * @ap: Port to shut down + * + * Frees the PRD table. + * + * May be used as the port_stop() entry in ata_port_operations. + * + * LOCKING: + */ + void ata_port_stop (struct ata_port *ap) { struct device *dev = ap->host_set->dev; @@ -3319,6 +3696,13 @@ dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); } +void ata_host_stop (struct ata_host_set *host_set) +{ + if (host_set->mmio_base) + iounmap(host_set->mmio_base); +} + + /** * ata_host_remove - Unregister SCSI host structure with upper layers * @ap: Port to unregister @@ -3347,7 +3731,11 @@ * @ent: Probe information provided by low-level driver * @port_no: Port number associated with this ata_port * + * Initialize a new ata_port structure, and its associated + * scsi_host. + * * LOCKING: + * Inherited from caller. * */ @@ -3401,9 +3789,13 @@ * @host_set: Collections of ports to which we add * @port_no: Port number associated with this host * + * Attach low-level ATA driver to system. + * * LOCKING: + * PCI/etc. bus probe sem. * * RETURNS: + * New ata_port on success, for NULL on error. * */ @@ -3436,12 +3828,22 @@ } /** - * ata_device_add - - * @ent: + * ata_device_add - Register hardware device with ATA and SCSI layers + * @ent: Probe information describing hardware device to be registered + * + * This function processes the information provided in the probe + * information struct @ent, allocates the necessary ATA and SCSI + * host information structures, initializes them, and registers + * everything with requisite kernel subsystems. + * + * This function requests irqs, probes the ATA bus, and probes + * the SCSI bus. * * LOCKING: + * PCI/etc. bus probe sem. * * RETURNS: + * Number of ports registered. Zero on error (no ports registered). * */ @@ -3612,7 +4014,15 @@ /** * ata_std_ports - initialize ioaddr with standard port offsets. * @ioaddr: IO address structure to be initialized + * + * Utility function which initializes data_addr, error_addr, + * feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr, + * device_addr, status_addr, and command_addr to standard offsets + * relative to cmd_addr. + * + * Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr. */ + void ata_std_ports(struct ata_ioports *ioaddr) { ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA; @@ -3654,6 +4064,20 @@ return probe_ent; } + + +/** + * ata_pci_init_native_mode - Initialize native-mode driver + * @pdev: pci device to be initialized + * @port: array[2] of pointers to port info structures. + * + * Utility function which allocates and initializes an + * ata_probe_ent structure for a standard dual-port + * PIO-based IDE controller. The returned ata_probe_ent + * structure can be passed to ata_device_add(). The returned + * ata_probe_ent structure should then be freed with kfree(). + */ + #ifdef CONFIG_PCI struct ata_probe_ent * ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port) @@ -3735,10 +4159,19 @@ * @port_info: Information from low-level host driver * @n_ports: Number of ports attached to host controller * + * This is a helper function which can be called from a driver's + * xxx_init_one() probe function if the hardware uses traditional + * IDE taskfile registers. + * + * This function calls pci_enable_device(), reserves its register + * regions, sets the dma mask, enables bus master mode, and calls + * ata_device_add() + * * LOCKING: * Inherited from PCI layer (may sleep). * * RETURNS: + * Zero on success, negative on errno-based value on error. * */ @@ -3882,10 +4315,6 @@ /* FIXME: handle 'rc' failure? */ free_irq(host_set->irq, host_set); - if (host_set->ops->host_stop) - host_set->ops->host_stop(host_set); - if (host_set->mmio_base) - iounmap(host_set->mmio_base); for (i = 0; i < host_set->n_ports; i++) { ap = host_set->ports[i]; @@ -3900,6 +4329,9 @@ } } + if (host_set->ops->host_stop) + host_set->ops->host_stop(host_set); + kfree(host_set); pci_release_regions(pdev); @@ -3958,15 +4390,6 @@ #endif /* CONFIG_PCI */ -/** - * ata_init - - * - * LOCKING: - * - * RETURNS: - * - */ - static int __init ata_init(void) { printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n"); @@ -4007,6 +4430,7 @@ EXPORT_SYMBOL_GPL(ata_exec_command); EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); +EXPORT_SYMBOL_GPL(ata_host_stop); EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); @@ -4029,6 +4453,7 @@ EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_id_string); +EXPORT_SYMBOL_GPL(ata_dev_config); EXPORT_SYMBOL_GPL(ata_scsi_simulate); #ifdef CONFIG_PCI diff -urN linux-2.4.31/drivers/scsi/libata-scsi.c linux-2.4.32/drivers/scsi/libata-scsi.c --- linux-2.4.31/drivers/scsi/libata-scsi.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/drivers/scsi/libata-scsi.c 2005-11-16 11:12:54.623078536 -0800 @@ -906,7 +906,7 @@ } /** - * ata_scsiop_noop - + * ata_scsiop_noop - Command handler that simply returns success. * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. @@ -1135,8 +1135,12 @@ n_sectors = ata_id_u32(args->id, 60); n_sectors--; /* ATA TotalUserSectors - 1 */ - tmp = n_sectors; /* note: truncates, if lba48 */ if (args->cmd->cmnd[0] == READ_CAPACITY) { + if( n_sectors >= 0xffffffffULL ) + tmp = 0xffffffff ; /* Return max count on overflow */ + else + tmp = n_sectors ; + /* sector count, 32-bit */ rbuf[0] = tmp >> (8 * 3); rbuf[1] = tmp >> (8 * 2); @@ -1150,10 +1154,12 @@ } else { /* sector count, 64-bit */ - rbuf[2] = n_sectors >> (8 * 7); - rbuf[3] = n_sectors >> (8 * 6); - rbuf[4] = n_sectors >> (8 * 5); - rbuf[5] = n_sectors >> (8 * 4); + tmp = n_sectors >> (8 * 4); + rbuf[2] = tmp >> (8 * 3); + rbuf[3] = tmp >> (8 * 2); + rbuf[4] = tmp >> (8 * 1); + rbuf[5] = tmp; + tmp = n_sectors; rbuf[6] = tmp >> (8 * 3); rbuf[7] = tmp >> (8 * 2); rbuf[8] = tmp >> (8 * 1); diff -urN linux-2.4.31/drivers/scsi/libata.h linux-2.4.32/drivers/scsi/libata.h --- linux-2.4.31/drivers/scsi/libata.h 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/libata.h 2005-11-16 11:12:54.623078536 -0800 @@ -26,7 +26,7 @@ #define __LIBATA_H__ #define DRV_NAME "libata" -#define DRV_VERSION "1.10" /* must be exactly four chars */ +#define DRV_VERSION "1.11" /* must be exactly four chars */ struct ata_scsi_args { u16 *id; diff -urN linux-2.4.31/drivers/scsi/megaraid2.c linux-2.4.32/drivers/scsi/megaraid2.c --- linux-2.4.31/drivers/scsi/megaraid2.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/megaraid2.c 2005-11-16 11:12:54.627078715 -0800 @@ -14,7 +14,7 @@ * - speed-ups (list handling fixes, issued_list, optimizations.) * - lots of cleanups. * - * Version : v2.10.8.2 (July 26, 2004) + * Version : v2.10.10.1 (January 27, 2005) * * Authors: Atul Mukker * Sreenivas Bagalkote @@ -46,7 +46,7 @@ #include "megaraid2.h" -#if defined(__x86_64__) +#ifdef LSI_CONFIG_COMPAT #include #endif @@ -181,7 +181,7 @@ /* * Scan PCI bus for our all devices. */ - for( i = 0; i < sizeof(dev_sw_table)/sizeof(u16); i += 2 ) { + for( i = 0; i < ((int) (sizeof(dev_sw_table)/sizeof(u16))); i += 2 ) { mega_find_card(host_template, dev_sw_table[i], dev_sw_table[i+1]); @@ -233,7 +233,7 @@ "MegaRAID Shutdown routine not registered!!\n"); } -#if defined(__x86_64__) +#ifdef LSI_CONFIG_COMPAT /* * Register the 32-bit ioctl conversion */ @@ -341,6 +341,7 @@ (subsysvid != INTEL_SUBSYS_VID) && (subsysvid != FSC_SUBSYS_VID) && (subsysvid != ACER_SUBSYS_VID) && + (subsysvid != NEC_SUBSYS_VID) && (subsysvid != LSI_SUBSYS_VID) ) continue; @@ -821,6 +822,78 @@ } +/** + * issue_scb() + * @adapter - pointer to our soft state + * @scb - scsi control block + * + * Post a command to the card if the mailbox is available, otherwise return + * busy. We also take the scb from the pending list if the mailbox is + * available. + */ +static inline int +issue_scb(adapter_t *adapter, scb_t *scb) +{ + volatile mbox64_t *mbox64 = adapter->mbox64; + volatile mbox_t *mbox = adapter->mbox; + unsigned int i = 0; + + if(unlikely(mbox->busy)) { + do { + udelay(1); + i++; + } while( mbox->busy && (i < max_mbox_busy_wait) ); + + if(mbox->busy) return -1; + } + + /* Copy mailbox data into host structure */ + memcpy((char *)mbox, (char *)scb->raw_mbox, 16); + + mbox->cmdid = scb->idx; /* Set cmdid */ + mbox->busy = 1; /* Set busy */ + + + /* + * Increment the pending queue counter + */ + atomic_inc(&adapter->pend_cmds); + + switch (mbox->cmd) { + case MEGA_MBOXCMD_EXTPTHRU: + if( !adapter->has_64bit_addr ) break; + // else fall through + case MEGA_MBOXCMD_LREAD64: + case MEGA_MBOXCMD_LWRITE64: + case MEGA_MBOXCMD_PASSTHRU64: + mbox64->xfer_segment_lo = mbox->xferaddr; + mbox64->xfer_segment_hi = 0; + mbox->xferaddr = 0xFFFFFFFF; + break; + default: + mbox64->xfer_segment_lo = 0; + mbox64->xfer_segment_hi = 0; + } + + /* + * post the command + */ + scb->state |= SCB_ISSUED; + + if( likely(adapter->flag & BOARD_MEMMAP) ) { + mbox->poll = 0; + mbox->ack = 0; + WRINDOOR(adapter, adapter->mbox_dma | 0x1); + } + else { + irq_enable(adapter); + issue_command(adapter); + } + + return 0; +} + + /* * mega_query_adapter() * @adapter - pointer to our soft state @@ -990,78 +1063,6 @@ /** - * issue_scb() - * @adapter - pointer to our soft state - * @scb - scsi control block - * - * Post a command to the card if the mailbox is available, otherwise return - * busy. We also take the scb from the pending list if the mailbox is - * available. - */ -static inline int -issue_scb(adapter_t *adapter, scb_t *scb) -{ - volatile mbox64_t *mbox64 = adapter->mbox64; - volatile mbox_t *mbox = adapter->mbox; - unsigned int i = 0; - - if(unlikely(mbox->busy)) { - do { - udelay(1); - i++; - } while( mbox->busy && (i < max_mbox_busy_wait) ); - - if(mbox->busy) return -1; - } - - /* Copy mailbox data into host structure */ - memcpy((char *)mbox, (char *)scb->raw_mbox, 16); - - mbox->cmdid = scb->idx; /* Set cmdid */ - mbox->busy = 1; /* Set busy */ - - - /* - * Increment the pending queue counter - */ - atomic_inc(&adapter->pend_cmds); - - switch (mbox->cmd) { - case MEGA_MBOXCMD_EXTPTHRU: - if( !adapter->has_64bit_addr ) break; - // else fall through - case MEGA_MBOXCMD_LREAD64: - case MEGA_MBOXCMD_LWRITE64: - case MEGA_MBOXCMD_PASSTHRU64: - mbox64->xfer_segment_lo = mbox->xferaddr; - mbox64->xfer_segment_hi = 0; - mbox->xferaddr = 0xFFFFFFFF; - break; - default: - mbox64->xfer_segment_lo = 0; - mbox64->xfer_segment_hi = 0; - } - - /* - * post the command - */ - scb->state |= SCB_ISSUED; - - if( likely(adapter->flag & BOARD_MEMMAP) ) { - mbox->poll = 0; - mbox->ack = 0; - WRINDOOR(adapter, adapter->mbox_dma | 0x1); - } - else { - irq_enable(adapter); - issue_command(adapter); - } - - return 0; -} - - -/** * mega_runpendq() * @adapter - pointer to our soft state * @@ -1074,7 +1075,6 @@ __mega_runpendq(adapter); } - static void __mega_runpendq(adapter_t *adapter) { @@ -1176,80 +1176,6 @@ return ldrv_num; } -/* - * Wait until the controller's mailbox is available - */ -static inline int -mega_busywait_mbox (adapter_t *adapter) -{ - if (adapter->mbox->busy) - return __mega_busywait_mbox(adapter); - return 0; -} - - -/** - * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs - * @adapter - controller's soft state - * - * Interrupt ackrowledgement sequence for IO mapped HBAs - */ -static inline void -megaraid_iombox_ack_sequence(adapter_t *adapter) -{ - u8 status; - u8 nstatus; - u8 completed[MAX_FIRMWARE_STATUS]; - u8 byte; - int i; - - - /* - * loop till F/W has more commands for us to complete. - */ - do { - /* Check if a valid interrupt is pending */ - byte = irq_state(adapter); - if( (byte & VALID_INTR_BYTE) == 0 ) { - return; - } - set_irq_state(adapter, byte); - - while ((nstatus = adapter->mbox->numstatus) == 0xFF) { - cpu_relax(); - } - adapter->mbox->numstatus = 0xFF; - - for (i = 0; i < nstatus; i++) { - while ((completed[i] = adapter->mbox->completed[i]) - == 0xFF) { - cpu_relax(); - } - - adapter->mbox->completed[i] = 0xFF; - } - - // we must read the valid status now - if ((status = adapter->mbox->status) == 0xFF) { - printk(KERN_WARNING - "megaraid critical: status 0xFF from firmware.\n"); - } - adapter->mbox->status = 0xFF; - - /* - * decrement the pending queue counter - */ - atomic_sub(nstatus, &adapter->pend_cmds); - - /* Acknowledge interrupt */ - irq_ack(adapter); - - mega_cmd_done(adapter, completed, nstatus, status); - - } while(1); -} - - /* * megaraid_queue() @@ -1755,8 +1681,8 @@ pthru = scb->pthru; memset(pthru, 0, sizeof (mega_passthru)); - /* 0=6sec/1=60sec/2=10min/3=3hrs */ - pthru->timeout = 2; + /* 0=6sec/1=60sec/2=10min/3=3hrs/4=NO timeout */ + pthru->timeout = 4; pthru->ars = 1; pthru->reqsenselen = 14; @@ -1819,8 +1745,8 @@ epthru = scb->epthru; memset(epthru, 0, sizeof(mega_ext_passthru)); - /* 0=6sec/1=60sec/2=10min/3=3hrs */ - epthru->timeout = 2; + /* 0=6sec/1=60sec/2=10min/3=3hrs/4=NO timeout */ + epthru->timeout = 4; epthru->ars = 1; epthru->reqsenselen = 14; @@ -1862,6 +1788,32 @@ } +/* + * Wait until the controller's mailbox is available + */ +static inline int +mega_busywait_mbox (adapter_t *adapter) +{ + if (adapter->mbox->busy) + return __mega_busywait_mbox(adapter); + return 0; +} + +static int +__mega_busywait_mbox (adapter_t *adapter) +{ + volatile mbox_t *mbox = adapter->mbox; + long counter; + + for (counter = 0; counter < 10000; counter++) { + if (!mbox->busy) + return 0; + udelay(100); yield(); + } + return -1; /* give up after 1 second */ +} + + /** * issue_scb_block() * @adapter - pointer to our soft state @@ -1962,137 +1914,7 @@ return -1; } - -/** - * megaraid_isr_iomapped() - * @irq - irq - * @devp - pointer to our soft state - * @regs - unused - * - * Interrupt service routine for io-mapped controllers. - * Find out if our device is interrupting. If yes, acknowledge the interrupt - * and service the completed commands. - */ -static void -megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs) -{ - adapter_t *adapter = devp; - unsigned long flags; - - - spin_lock_irqsave(adapter->host_lock, flags); - - megaraid_iombox_ack_sequence(adapter); - - /* Loop through any pending requests */ - if( atomic_read(&adapter->quiescent ) == 0) { - mega_runpendq(adapter); - } - - spin_unlock_irqrestore(adapter->host_lock, flags); - - return; -} - - -/** - * megaraid_memmbox_ack_sequence - interrupt ack sequence for memory mapped HBAs - * @adapter - controller's soft state - * - * Interrupt ackrowledgement sequence for memory mapped HBAs - */ -static inline void -megaraid_memmbox_ack_sequence(adapter_t *adapter) -{ - u8 status; - u32 dword = 0; - u8 nstatus; - u8 completed[MAX_FIRMWARE_STATUS]; - int i; - - - /* - * loop till F/W has more commands for us to complete. - */ - do { - /* Check if a valid interrupt is pending */ - dword = RDOUTDOOR(adapter); - if( dword != 0x10001234 ) { - /* - * No more pending commands - */ - return; - } - WROUTDOOR(adapter, 0x10001234); - - while ((nstatus = adapter->mbox->numstatus) == 0xFF) { - cpu_relax(); - } - adapter->mbox->numstatus = 0xFF; - - for (i = 0; i < nstatus; i++ ) { - while ((completed[i] = adapter->mbox->completed[i]) - == 0xFF) { - cpu_relax(); - } - - adapter->mbox->completed[i] = 0xFF; - } - - // we must read the valid status now - if ((status = adapter->mbox->status) == 0xFF) { - printk(KERN_WARNING - "megaraid critical: status 0xFF from firmware.\n"); - } - adapter->mbox->status = 0xFF; - - /* - * decrement the pending queue counter - */ - atomic_sub(nstatus, &adapter->pend_cmds); - - /* Acknowledge interrupt */ - WRINDOOR(adapter, 0x2); - - while( RDINDOOR(adapter) & 0x02 ) cpu_relax(); - - mega_cmd_done(adapter, completed, nstatus, status); - - } while(1); -} - - -/** - * megaraid_isr_memmapped() - * @irq - irq - * @devp - pointer to our soft state - * @regs - unused - * - * Interrupt service routine for memory-mapped controllers. - * Find out if our device is interrupting. If yes, acknowledge the interrupt - * and service the completed commands. - */ -static void -megaraid_isr_memmapped(int irq, void *devp, struct pt_regs *regs) -{ - adapter_t *adapter = devp; - unsigned long flags; - - - spin_lock_irqsave(adapter->host_lock, flags); - - megaraid_memmbox_ack_sequence(adapter); - - /* Loop through any pending requests */ - if(atomic_read(&adapter->quiescent) == 0) { - mega_runpendq(adapter); - } - - spin_unlock_irqrestore(adapter->host_lock, flags); - - return; -} - + /** * mega_cmd_done() * @adapter - pointer to our soft state @@ -2102,7 +1924,7 @@ * * Complete the comamnds and call the scsi mid-layer callback hooks. */ -static void +static inline void mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status) { mega_ext_passthru *epthru = NULL; @@ -2351,6 +2173,197 @@ } +/** + * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs + * @adapter - controller's soft state + * + * Interrupt ackrowledgement sequence for IO mapped HBAs + */ +static inline void +megaraid_iombox_ack_sequence(adapter_t *adapter) +{ + u8 status; + int nstatus; + u8 completed[MAX_FIRMWARE_STATUS]; + u8 byte; + int i; + + + /* + * loop till F/W has more commands for us to complete. + */ + do { + /* Check if a valid interrupt is pending */ + byte = irq_state(adapter); + if( (byte & VALID_INTR_BYTE) == 0 ) { + return; + } + set_irq_state(adapter, byte); + + while ((nstatus = adapter->mbox->numstatus) == 0xFF) { + cpu_relax(); + } + adapter->mbox->numstatus = 0xFF; + + for (i = 0; i < nstatus; i++) { + while ((completed[i] = adapter->mbox->completed[i]) + == 0xFF) { + cpu_relax(); + } + + adapter->mbox->completed[i] = 0xFF; + } + + // we must read the valid status now + if ((status = adapter->mbox->status) == 0xFF) { + printk(KERN_WARNING + "megaraid critical: status 0xFF from firmware.\n"); + } + adapter->mbox->status = 0xFF; + + /* + * decrement the pending queue counter + */ + atomic_sub(nstatus, &adapter->pend_cmds); + + /* Acknowledge interrupt */ + irq_ack(adapter); + + mega_cmd_done(adapter, completed, nstatus, status); + + } while(1); +} + + +/** + * megaraid_isr_iomapped() + * @irq - irq + * @devp - pointer to our soft state + * @regs - unused + * + * Interrupt service routine for io-mapped controllers. + * Find out if our device is interrupting. If yes, acknowledge the interrupt + * and service the completed commands. + */ +static void +megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs) +{ + adapter_t *adapter = devp; + unsigned long flags; + + spin_lock_irqsave(adapter->host_lock, flags); + + megaraid_iombox_ack_sequence(adapter); + + /* Loop through any pending requests */ + if( atomic_read(&adapter->quiescent ) == 0) { + mega_runpendq(adapter); + } + + spin_unlock_irqrestore(adapter->host_lock, flags); + + return; +} + + +/** + * megaraid_memmbox_ack_sequence - interrupt ack sequence for memory mapped HBAs + * @adapter - controller's soft state + * + * Interrupt ackrowledgement sequence for memory mapped HBAs + */ +static inline void +megaraid_memmbox_ack_sequence(adapter_t *adapter) +{ + u8 status; + u32 dword = 0; + int nstatus; + u8 completed[MAX_FIRMWARE_STATUS]; + int i; + + + /* + * loop till F/W has more commands for us to complete. + */ + do { + /* Check if a valid interrupt is pending */ + dword = RDOUTDOOR(adapter); + if( dword != 0x10001234 ) { + /* + * No more pending commands + */ + return; + } + WROUTDOOR(adapter, 0x10001234); + + while ((nstatus = adapter->mbox->numstatus) == 0xFF) { + cpu_relax(); + } + adapter->mbox->numstatus = 0xFF; + + for (i = 0; i < nstatus; i++ ) { + while ((completed[i] = adapter->mbox->completed[i]) + == 0xFF) { + cpu_relax(); + } + + adapter->mbox->completed[i] = 0xFF; + } + + // we must read the valid status now + if ((status = adapter->mbox->status) == 0xFF) { + printk(KERN_WARNING + "megaraid critical: status 0xFF from firmware.\n"); + } + adapter->mbox->status = 0xFF; + + /* + * decrement the pending queue counter + */ + atomic_sub(nstatus, &adapter->pend_cmds); + + /* Acknowledge interrupt */ + WRINDOOR(adapter, 0x2); + + while( RDINDOOR(adapter) & 0x02 ) cpu_relax(); + + mega_cmd_done(adapter, completed, nstatus, status); + + } while(1); +} + + +/** + * megaraid_isr_memmapped() + * @irq - irq + * @devp - pointer to our soft state + * @regs - unused + * + * Interrupt service routine for memory-mapped controllers. + * Find out if our device is interrupting. If yes, acknowledge the interrupt + * and service the completed commands. + */ +static void +megaraid_isr_memmapped(int irq, void *devp, struct pt_regs *regs) +{ + adapter_t *adapter = devp; + unsigned long flags; + + spin_lock_irqsave(adapter->host_lock, flags); + + megaraid_memmbox_ack_sequence(adapter); + + /* Loop through any pending requests */ + if(atomic_read(&adapter->quiescent) == 0) { + mega_runpendq(adapter); + } + + spin_unlock_irqrestore(adapter->host_lock, flags); + + return; +} + + /* * Free a SCB structure * Note: We assume the scsi commands associated with this scb is not free yet. @@ -2404,19 +2417,6 @@ list_add(&scb->list, &adapter->free_list); } -static int -__mega_busywait_mbox (adapter_t *adapter) -{ - volatile mbox_t *mbox = adapter->mbox; - long counter; - - for (counter = 0; counter < 10000; counter++) { - if (!mbox->busy) - return 0; - udelay(100); yield(); - } - return -1; /* give up after 1 second */ -} /* * Copies data to SGLIST @@ -2434,7 +2434,7 @@ cmd = scb->cmd; - /* return 0 elements if no data transfer */ + // return 0 elements if no data transfer if (!cmd->request_buffer || !cmd->request_bufflen) return 0; @@ -2561,6 +2561,7 @@ enquiry3->pdrv_state[i] = inquiry->pdrv_info.pdrv_state[i]; } + static inline void mega_free_sgl(adapter_t *adapter) { @@ -2726,7 +2727,7 @@ */ scsi_unregister(host); -#if defined(__x86_64__) +#ifdef LSI_CONFIG_COMPAT unregister_ioctl32_conversion(MEGAIOCCMD); #endif @@ -2835,7 +2836,6 @@ return SUCCESS; } - static int megaraid_reset(Scsi_Cmnd *cmd) { @@ -2903,12 +2903,10 @@ /* * Perform the ack sequence, since interrupts are unavailable */ - if( adapter->flag & BOARD_MEMMAP ) { + if (adapter->flag & BOARD_MEMMAP) megaraid_memmbox_ack_sequence(adapter); - } - else { + else megaraid_iombox_ack_sequence(adapter); - } spin_unlock(adapter->host_lock); @@ -2941,7 +2939,6 @@ return rval; } - #ifdef CONFIG_PROC_FS /* Following code handles /proc fs */ @@ -3200,6 +3197,7 @@ return len; } + /** * mega_allocate_inquiry() * @dma_handle - handle returned for dma address @@ -3582,7 +3580,7 @@ * Check for overflow. We print less than 240 * characters for inquiry */ - if( (len + 240) >= PAGE_SIZE ) break; + if( (len + 240) >= ((int) PAGE_SIZE) ) break; len += sprintf(page+len, "%s.\n", str); @@ -3886,7 +3884,7 @@ * Check for overflow. We print less than 240 characters for * information about each logical drive. */ - if( (len + 240) >= PAGE_SIZE ) break; + if( (len + 240) >= ((int) PAGE_SIZE) ) break; len += sprintf(page+len, "Logical drive:%2d:, ", i); @@ -4172,7 +4170,7 @@ } -#if defined(__x86_64__) +#ifdef LSI_CONFIG_COMPAT static int megadev_compat_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filep) @@ -4221,7 +4219,7 @@ megacmd_t mc; megastat_t *ustats; int num_ldrv; - u32 uxferaddr = 0; + caddr_t uxferaddr=NULL; struct pci_dev *pdev; ustats = NULL; /* avoid compilation warnings */ @@ -4251,13 +4249,13 @@ switch( uioc.opcode ) { case GET_DRIVER_VER: - if( put_user(driver_ver, (u32 *)uioc.uioc_uaddr) ) + if( put_user(driver_ver, (u32 *)uioc.u_dataaddr) ) return (-EFAULT); break; case GET_N_ADAP: - if( put_user(hba_count, (u32 *)uioc.uioc_uaddr) ) + if( put_user(hba_count, (u32 *)uioc.u_dataaddr) ) return (-EFAULT); /* @@ -4275,7 +4273,7 @@ if( (adapno = GETADAP(uioc.adapno)) >= hba_count ) return (-ENODEV); - if( copy_to_user(uioc.uioc_uaddr, mcontroller+adapno, + if( copy_to_user(uioc.u_dataaddr, mcontroller+adapno, sizeof(struct mcontroller)) ) return (-EFAULT); break; @@ -4291,7 +4289,7 @@ adapter = hba_soft_state[adapno]; - ustats = (megastat_t *)uioc.uioc_uaddr; + ustats = (megastat_t *)uioc.u_dataaddr; if( copy_from_user(&num_ldrv, &ustats->num_ldrv, sizeof(int)) ) return (-EFAULT); @@ -4333,7 +4331,7 @@ /* * Which adapter */ - if( (adapno = GETADAP(uioc.adapno)) >= hba_count ) + if( (adapno = GETADAP(uioc.adapno)) >= hba_count ) return (-ENODEV); adapter = hba_soft_state[adapno]; @@ -4342,37 +4340,37 @@ * Deletion of logical drive is a special case. The adapter * should be quiescent before this command is issued. */ - if( uioc.uioc_rmbox[0] == FC_DEL_LOGDRV && - uioc.uioc_rmbox[2] == OP_DEL_LOGDRV ) { + if( RMBOX(uioc)[0] == FC_DEL_LOGDRV ) { + if ( RMBOX(uioc)[2] == OP_DEL_LOGDRV ) { + /* + * Do we support this feature + */ + if( !adapter->support_random_del ) { + printk(KERN_WARNING "megaraid: logdrv "); + printk("delete on non-supporting F/W.\n"); - /* - * Do we support this feature - */ - if( !adapter->support_random_del ) { - printk(KERN_WARNING "megaraid: logdrv "); - printk("delete on non-supporting F/W.\n"); + return (-EINVAL); + } - return (-EINVAL); - } + rval = mega_del_logdrv( adapter, RMBOX(uioc)[3] ); - rval = mega_del_logdrv( adapter, uioc.uioc_rmbox[3] ); + if( rval == 0 ) { + memset(&mc, 0, sizeof(megacmd_t)); - if( rval == 0 ) { - memset(&mc, 0, sizeof(megacmd_t)); + mc.status = rval; - mc.status = rval; + rval = mega_n_to_m((void *)arg, &mc); + } - rval = mega_n_to_m((void *)arg, &mc); + return rval; } - - return rval; } /* * This interface only support the regular passthru commands. * Reject extended passthru and 64-bit passthru */ - if( uioc.uioc_rmbox[0] == MEGA_MBOXCMD_PASSTHRU64 || - uioc.uioc_rmbox[0] == MEGA_MBOXCMD_EXTPTHRU ) { + if( RMBOX(uioc)[0] == MEGA_MBOXCMD_PASSTHRU64 || + RMBOX(uioc)[0] == MEGA_MBOXCMD_EXTPTHRU ) { printk(KERN_WARNING "megaraid: rejected passthru.\n"); @@ -4386,7 +4384,7 @@ pdev = adapter->dev; /* Is it a passthru command or a DCMD */ - if( uioc.uioc_rmbox[0] == MEGA_MBOXCMD_PASSTHRU ) { + if( RMBOX(uioc)[0] == MEGA_MBOXCMD_PASSTHRU ) { /* Passthru commands */ pthru = adapter->int_pthru; @@ -4394,20 +4392,12 @@ /* * The user passthru structure */ - upthru = (mega_passthru *) - ((ulong)(MBOX(uioc)->xferaddr)); - /* - * Copy in the user passthru here. - */ - if( copy_from_user(pthru, (char *)upthru, - sizeof(mega_passthru)) ) { - return (-EFAULT); - } - + upthru = &uioc.pthru; + memcpy(pthru, (char *)upthru,sizeof(mega_passthru)); /* * Is there a data transfer; If the data transfer - * length is <= INT_MEMBLK_SZ, usr the buffer - * allocated at the load time. Otherwise, allocate it + * length is <= INT_MEMBLK_SZ, usr the buffer + * allocated at the load time. Otherwise, allocate it * here. */ if (pthru->dataxferlen) { @@ -4417,8 +4407,9 @@ pthru->dataxferlen, &data_dma_hndl ); - if (data == NULL) + if (data == NULL) { return (-ENOMEM); + } } else { data = adapter->int_data; @@ -4428,11 +4419,11 @@ * Save the user address and point the kernel * address at just allocated memory */ - uxferaddr = pthru->dataxferaddr; + uxferaddr = (caddr_t) uioc.u_dataaddr; if (data_dma_hndl) pthru->dataxferaddr = data_dma_hndl; else - pthru->dataxferaddr = + pthru->dataxferaddr = adapter->int_data_dma_hndl; } @@ -4440,12 +4431,12 @@ /* * Is data coming down-stream */ - if( pthru->dataxferlen && (uioc.flags & UIOC_WR) ) { + if(pthru->dataxferlen && (uioc.flags & UIOC_WR) ) { /* * Get the user data */ if( copy_from_user(data, - (char *)((ulong)uxferaddr), + (char *)uxferaddr, pthru->dataxferlen) ) { rval = (-EFAULT); goto freedata_and_return; @@ -4471,7 +4462,7 @@ * Is data going up-stream */ if( pthru->dataxferlen && (uioc.flags & UIOC_RD) ) { - if( copy_to_user((char *)((ulong)uxferaddr), + if( copy_to_user((char *)uxferaddr, data, pthru->dataxferlen) ) { rval = (-EFAULT); } @@ -4511,7 +4502,7 @@ else { data = adapter->int_data; } - uxferaddr = MBOX(uioc)->xferaddr; + uxferaddr = uioc.u_dataaddr; } /* @@ -4559,7 +4550,7 @@ * Is data going up-stream */ if( uioc.xferlen && (uioc.flags & UIOC_RD) ) { - if( copy_to_user((char *)((ulong)uxferaddr), + if( copy_to_user((char *)uxferaddr, data, uioc.xferlen) ) { rval = (-EFAULT); @@ -4648,18 +4639,18 @@ case MEGAIOC_QDRVRVER: /* Query driver version */ uioc->opcode = GET_DRIVER_VER; - uioc->uioc_uaddr = uioc_mimd.data; + uioc->u_dataaddr = uioc_mimd.data; break; case MEGAIOC_QNADAP: /* Get # of adapters */ uioc->opcode = GET_N_ADAP; - uioc->uioc_uaddr = uioc_mimd.data; + uioc->u_dataaddr = uioc_mimd.data; break; case MEGAIOC_QADAPINFO: /* Get adapter information */ uioc->opcode = GET_ADAP_INFO; uioc->adapno = uioc_mimd.ui.fcs.adapno; - uioc->uioc_uaddr = uioc_mimd.data; + uioc->u_dataaddr = uioc_mimd.data; break; default: @@ -4674,9 +4665,16 @@ uioc->opcode = MBOX_CMD; uioc->adapno = uioc_mimd.ui.fcs.adapno; - memcpy(uioc->uioc_rmbox, uioc_mimd.mbox, 18); + memcpy(&uioc->u_mbox, uioc_mimd.mbox, 18); uioc->xferlen = uioc_mimd.ui.fcs.length; + uioc->u_dataaddr = uioc_mimd.ui.fcs.buffer; + + if (uioc_mimd.mbox[0] == MEGA_MBOXCMD_PASSTHRU ) { + memcpy(&uioc->pthru,&uioc_mimd.pthru, + sizeof(mega_passthru)); + + } if( uioc_mimd.outlen ) uioc->flags = UIOC_RD; if( uioc_mimd.inlen ) uioc->flags |= UIOC_WR; @@ -4688,13 +4686,20 @@ uioc->opcode = MBOX_CMD; uioc->adapno = uioc_mimd.ui.fcs.adapno; - memcpy(uioc->uioc_rmbox, uioc_mimd.mbox, 18); + memcpy(&uioc->u_mbox, uioc_mimd.mbox, 18); /* * Choose the xferlen bigger of input and output data */ uioc->xferlen = uioc_mimd.outlen > uioc_mimd.inlen ? uioc_mimd.outlen : uioc_mimd.inlen; + uioc->u_dataaddr = uioc_mimd.data; + + if (uioc_mimd.mbox[0] == MEGA_MBOXCMD_PASSTHRU ) { + memcpy(&uioc->pthru,&uioc_mimd.pthru, + sizeof(mega_passthru)); + + } if( uioc_mimd.outlen ) uioc->flags = UIOC_RD; if( uioc_mimd.inlen ) uioc->flags |= UIOC_WR; @@ -4720,7 +4725,6 @@ static int mega_n_to_m(void *arg, megacmd_t *mc) { - nitioctl_t *uiocp; megacmd_t *umc; megacmd_t kmc; mega_passthru *upthru; @@ -4735,20 +4739,14 @@ if( memcmp(signature, "MEGANIT", 7) == 0 ) { - uiocp = (nitioctl_t *)arg; - - if( put_user(mc->status, (u8 *)&MBOX_P(uiocp)->status) ) - return (-EFAULT); - - if( mc->cmd == MEGA_MBOXCMD_PASSTHRU ) { - - umc = MBOX_P(uiocp); - upthru = (mega_passthru *)((ulong)(umc->xferaddr)); - - if( put_user(mc->status, (u8 *)&upthru->scsistatus) ) - return (-EFAULT); - } + /* + * NOTE: The nit ioctl is still under flux because of + * change of mailbox definition, in HPE. No applications yet + * use this interface and let's not have applications use this + * interface till the new specifitions are in place. + */ + return -EINVAL; } else { uioc_mimd = (struct uioctl_t *)arg; @@ -4763,8 +4761,7 @@ if (copy_from_user(&kmc, umc, sizeof(megacmd_t))) { return -EFAULT; } - - upthru = (mega_passthru *)((ulong)kmc.xferaddr); + upthru = (mega_passthru *)((ulong)&uioc_mimd->pthru); if( put_user(mc->status, (u8 *)&upthru->scsistatus) ){ return (-EFAULT); @@ -5179,6 +5176,7 @@ } + /** * mega_reorder_hosts() * @@ -5393,7 +5391,6 @@ } - /** mega_internal_dev_inquiry() * @adapter - pointer to our soft state * @ch - channel for this device diff -urN linux-2.4.31/drivers/scsi/megaraid2.h linux-2.4.32/drivers/scsi/megaraid2.h --- linux-2.4.31/drivers/scsi/megaraid2.h 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/megaraid2.h 2005-11-16 11:12:54.628078759 -0800 @@ -6,7 +6,7 @@ #define MEGARAID_VERSION \ - "v2.10.8.2 (Release Date: Mon Jul 26 12:15:51 EDT 2004)\n" + "v2.10.10.1 (Release Date: Thu Jan 27 16:19:44 EDT 2005)\n" /* * Driver features - change the values to enable or disable features in the @@ -83,6 +83,7 @@ #define INTEL_SUBSYS_VID 0x8086 #define FSC_SUBSYS_VID 0x1734 #define ACER_SUBSYS_VID 0x1025 +#define NEC_SUBSYS_VID 0x1033 #define HBA_SIGNATURE 0x3344 #define HBA_SIGNATURE_471 0xCCCC @@ -707,15 +708,15 @@ char signature[8]; /* Must contain "MEGANIT" */ u32 opcode; /* opcode for the command */ u32 adapno; /* adapter number */ - union { - u8 __raw_mbox[18]; - caddr_t __uaddr; /* xferaddr for non-mbox cmds */ - }__ua; - -#define uioc_rmbox __ua.__raw_mbox -#define MBOX(uioc) ((megacmd_t *)&((uioc).__ua.__raw_mbox[0])) -#define MBOX_P(uioc) ((megacmd_t *)&((uioc)->__ua.__raw_mbox[0])) -#define uioc_uaddr __ua.__uaddr + mbox_t u_mbox; /* user mailbox */ + caddr_t u_dataaddr; /* xferaddr for DCMD and non-mbox + commands */ + mega_passthru pthru; + +#define RMBOX(uioc) ((u8 *)&(uioc).u_mbox) +#define MBOX(uioc) ((megacmd_t *)&(uioc).u_mbox) +#define MBOX_P(uioc) ((megacmd_t *)&(uioc)->u_mbox) + u32 xferlen; /* xferlen for DCMD and non-mbox commands */ @@ -1128,7 +1129,7 @@ u32 *buffer, u32 *length); static inline int mega_busywait_mbox (adapter_t *); static int __mega_busywait_mbox (adapter_t *); -static void mega_cmd_done(adapter_t *, u8 [], int, int); +static inline void mega_cmd_done(adapter_t *, u8 [], int, int); static inline void mega_free_sgl (adapter_t *adapter); static void mega_8_to_40ld (mraid_inquiry *inquiry, mega_inquiry3 *enquiry3, mega_product_info *); @@ -1137,7 +1138,14 @@ unsigned long, void *); static int megadev_open (struct inode *, struct file *); -#if defined(__x86_64__) +#if defined( __x86_64__) || defined(IA32_EMULATION) +#ifndef __ia64__ +#define LSI_CONFIG_COMPAT +#endif +#endif + + +#ifdef LSI_CONFIG_COMPAT static int megadev_compat_ioctl(unsigned int, unsigned int, unsigned long, struct file *); #endif diff -urN linux-2.4.31/drivers/scsi/sata_nv.c linux-2.4.32/drivers/scsi/sata_nv.c --- linux-2.4.31/drivers/scsi/sata_nv.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sata_nv.c 2005-11-16 11:12:54.629078804 -0800 @@ -329,6 +329,8 @@ host->host_desc->disable_hotplug(host_set); kfree(host); + + ata_host_stop(host_set); } static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) diff -urN linux-2.4.31/drivers/scsi/sata_promise.c linux-2.4.32/drivers/scsi/sata_promise.c --- linux-2.4.31/drivers/scsi/sata_promise.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sata_promise.c 2005-11-16 11:12:54.630078849 -0800 @@ -42,6 +42,7 @@ #define DRV_NAME "sata_promise" #define DRV_VERSION "1.01" + enum { PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ @@ -58,6 +59,7 @@ board_2037x = 0, /* FastTrak S150 TX2plus */ board_20319 = 1, /* FastTrak S150 TX4 */ + board_20619 = 2, /* FastTrak TX4000 */ PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */ @@ -121,6 +123,7 @@ .scr_write = pdc_sata_scr_write, .port_start = pdc_port_start, .port_stop = pdc_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info pdc_port_info[] = { @@ -145,11 +148,24 @@ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_ata_ops, }, + + /* board_20619 */ + { + .sht = &pdc_ata_sht, + .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | + ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_ata_ops, + }, }; static struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0, @@ -168,6 +184,9 @@ { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, + { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_20619 }, + { } /* terminate list */ }; @@ -629,6 +648,15 @@ case board_2037x: probe_ent->n_ports = 2; break; + case board_20619: + probe_ent->n_ports = 4; + + pdc_ata_setup_port(&probe_ent->port[2], base + 0x300); + pdc_ata_setup_port(&probe_ent->port[3], base + 0x380); + + probe_ent->port[2].scr_addr = base + 0x600; + probe_ent->port[3].scr_addr = base + 0x700; + break; default: BUG(); break; @@ -684,7 +712,7 @@ MODULE_AUTHOR("Jeff Garzik"); -MODULE_DESCRIPTION("Promise SATA TX2/TX4 low-level driver"); +MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl); MODULE_VERSION(DRV_VERSION); diff -urN linux-2.4.31/drivers/scsi/sata_qstor.c linux-2.4.32/drivers/scsi/sata_qstor.c --- linux-2.4.31/drivers/scsi/sata_qstor.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sata_qstor.c 2005-11-16 11:12:54.630078849 -0800 @@ -537,6 +537,8 @@ writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */ + + ata_host_stop(host_set); } static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe) diff -urN linux-2.4.31/drivers/scsi/sata_sil.c linux-2.4.32/drivers/scsi/sata_sil.c --- linux-2.4.31/drivers/scsi/sata_sil.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sata_sil.c 2005-11-16 11:12:54.631078893 -0800 @@ -82,6 +82,7 @@ { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 }, { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, { } /* terminate list */ }; @@ -160,6 +161,7 @@ .scr_write = sil_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info sil_port_info[] = { @@ -427,7 +429,13 @@ writeb(cls, mmio_base + SIL_FIFO_R0); writeb(cls, mmio_base + SIL_FIFO_W0); writeb(cls, mmio_base + SIL_FIFO_R1); - writeb(cls, mmio_base + SIL_FIFO_W2); + writeb(cls, mmio_base + SIL_FIFO_W1); + if (ent->driver_data == sil_3114) { + writeb(cls, mmio_base + SIL_FIFO_R2); + writeb(cls, mmio_base + SIL_FIFO_W2); + writeb(cls, mmio_base + SIL_FIFO_R3); + writeb(cls, mmio_base + SIL_FIFO_W3); + } } else printk(KERN_WARNING DRV_NAME "(%s): cache line size not set. Driver may not function\n", pci_name(pdev)); diff -urN linux-2.4.31/drivers/scsi/sata_sis.c linux-2.4.32/drivers/scsi/sata_sis.c --- linux-2.4.31/drivers/scsi/sata_sis.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sata_sis.c 2005-11-16 11:12:54.631078893 -0800 @@ -114,6 +114,7 @@ .scr_write = sis_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info sis_port_info = { diff -urN linux-2.4.31/drivers/scsi/sata_svw.c linux-2.4.32/drivers/scsi/sata_svw.c --- linux-2.4.31/drivers/scsi/sata_svw.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sata_svw.c 2005-11-16 11:12:54.631078893 -0800 @@ -49,7 +49,7 @@ #endif /* CONFIG_PPC_OF */ #define DRV_NAME "sata_svw" -#define DRV_VERSION "1.05" +#define DRV_VERSION "1.06" /* Taskfile registers offsets */ #define K2_SATA_TF_CMD_OFFSET 0x00 @@ -313,6 +313,7 @@ .scr_write = k2_sata_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base) @@ -343,6 +344,7 @@ void *mmio_base; int pci_dev_busy = 0; int rc; + int i; if (!printed_version++) printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); @@ -417,11 +419,11 @@ probe_ent->mwdma_mask = 0x7; probe_ent->udma_mask = 0x7f; - /* We have 4 ports per PCI function */ - k2_sata_setup_port(&probe_ent->port[0], base + 0 * K2_SATA_PORT_OFFSET); - k2_sata_setup_port(&probe_ent->port[1], base + 1 * K2_SATA_PORT_OFFSET); - k2_sata_setup_port(&probe_ent->port[2], base + 2 * K2_SATA_PORT_OFFSET); - k2_sata_setup_port(&probe_ent->port[3], base + 3 * K2_SATA_PORT_OFFSET); + /* different controllers have different number of ports - currently 4 or 8 */ + /* All ports are on the same function. Multi-function device is no + * longer available. This should not be seen in any system. */ + for (i = 0; i < ent->driver_data; i++) + k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET); pci_set_master(pdev); @@ -439,11 +441,17 @@ return rc; } - +/* 0x240 is device ID for Apple K2 device + * 0x241 is device ID for Serverworks Frodo4 + * 0x242 is device ID for Serverworks Frodo8 + * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA + * controller + * */ static struct pci_device_id k2_sata_pci_tbl[] = { - { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, + { 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, + { 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, + { 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, { } }; diff -urN linux-2.4.31/drivers/scsi/sata_sx4.c linux-2.4.32/drivers/scsi/sata_sx4.c --- linux-2.4.31/drivers/scsi/sata_sx4.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sata_sx4.c 2005-11-16 11:12:54.632078938 -0800 @@ -245,6 +245,8 @@ iounmap(dimm_mmio); kfree(hpriv); + + ata_host_stop(host_set); } static int pdc_port_start(struct ata_port *ap) diff -urN linux-2.4.31/drivers/scsi/sata_uli.c linux-2.4.32/drivers/scsi/sata_uli.c --- linux-2.4.31/drivers/scsi/sata_uli.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sata_uli.c 2005-11-16 11:12:54.632078938 -0800 @@ -113,6 +113,7 @@ .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info uli_port_info = { diff -urN linux-2.4.31/drivers/scsi/sata_via.c linux-2.4.32/drivers/scsi/sata_via.c --- linux-2.4.31/drivers/scsi/sata_via.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sata_via.c 2005-11-16 11:12:54.633078982 -0800 @@ -134,6 +134,7 @@ .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info svia_port_info = { diff -urN linux-2.4.31/drivers/scsi/sata_vsc.c linux-2.4.32/drivers/scsi/sata_vsc.c --- linux-2.4.31/drivers/scsi/sata_vsc.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sata_vsc.c 2005-11-16 11:12:54.633078982 -0800 @@ -230,6 +230,7 @@ .scr_write = vsc_sata_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base) diff -urN linux-2.4.31/drivers/scsi/sd.c linux-2.4.32/drivers/scsi/sd.c --- linux-2.4.31/drivers/scsi/sd.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/scsi/sd.c 2005-11-16 11:12:54.634079027 -0800 @@ -1472,6 +1472,7 @@ kfree(sd_sizes); kfree(sd_blocksizes); kfree(sd_hardsizes); + kfree(sd_max_sectors); for (i = 0; i < N_USED_SD_MAJORS; i++) { kfree(sd_gendisks[i].de_arr); kfree(sd_gendisks[i].flags); @@ -1482,6 +1483,7 @@ del_gendisk(&sd_gendisks[i]); blksize_size[SD_MAJOR(i)] = NULL; hardsect_size[SD_MAJOR(i)] = NULL; + max_sectors[SD_MAJOR(i)] = NULL; read_ahead[SD_MAJOR(i)] = 0; } sd_template.dev_max = 0; diff -urN linux-2.4.31/drivers/sound/.indent.pro linux-2.4.32/drivers/sound/.indent.pro --- linux-2.4.31/drivers/sound/.indent.pro 1997-09-30 08:46:46.000000000 -0700 +++ linux-2.4.32/drivers/sound/.indent.pro 1969-12-31 16:00:00.000000000 -0800 @@ -1,8 +0,0 @@ --bad --bap --nfca --bl --psl --di16 --lp --ip5 diff -urN linux-2.4.31/drivers/sound/.version linux-2.4.32/drivers/sound/.version --- linux-2.4.31/drivers/sound/.version 1997-11-09 23:01:54.000000000 -0800 +++ linux-2.4.32/drivers/sound/.version 1969-12-31 16:00:00.000000000 -0800 @@ -1,2 +0,0 @@ -3.8s -0x030804 diff -urN linux-2.4.31/drivers/sound/i810_audio.c linux-2.4.32/drivers/sound/i810_audio.c --- linux-2.4.31/drivers/sound/i810_audio.c 2004-11-17 03:54:21.000000000 -0800 +++ linux-2.4.32/drivers/sound/i810_audio.c 2005-11-16 11:12:54.639079250 -0800 @@ -458,12 +458,38 @@ /* extract register offset from codec struct */ #define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id]) -#define GET_CIV(port) MODULOP2(inb((port) + OFF_CIV), SG_LEN) -#define GET_LVI(port) MODULOP2(inb((port) + OFF_LVI), SG_LEN) +#define I810_IOREAD(size, type, card, off) \ +({ \ + type val; \ + if (card->use_mmio) \ + val=read##size(card->iobase_mmio+off); \ + else \ + val=in##size(card->iobase+off); \ + val; \ +}) + +#define I810_IOREADL(card, off) I810_IOREAD(l, u32, card, off) +#define I810_IOREADW(card, off) I810_IOREAD(w, u16, card, off) +#define I810_IOREADB(card, off) I810_IOREAD(b, u8, card, off) + +#define I810_IOWRITE(size, val, card, off) \ +({ \ + if (card->use_mmio) \ + write##size(val, card->iobase_mmio+off); \ + else \ + out##size(val, card->iobase+off); \ +}) + +#define I810_IOWRITEL(val, card, off) I810_IOWRITE(l, val, card, off) +#define I810_IOWRITEW(val, card, off) I810_IOWRITE(w, val, card, off) +#define I810_IOWRITEB(val, card, off) I810_IOWRITE(b, val, card, off) + +#define GET_CIV(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_CIV), SG_LEN) +#define GET_LVI(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_LVI), SG_LEN) /* set LVI from CIV */ -#define CIV_TO_LVI(port, off) \ - outb(MODULOP2(GET_CIV((port)) + (off), SG_LEN), (port) + OFF_LVI) +#define CIV_TO_LVI(card, port, off) \ + I810_IOWRITEB(MODULOP2(GET_CIV((card), (port)) + (off), SG_LEN), (card), (port) + OFF_LVI) static struct i810_card *devs = NULL; @@ -722,9 +748,9 @@ return 0; if (rec) - port = state->card->iobase + dmabuf->read_channel->port; + port = dmabuf->read_channel->port; else - port = state->card->iobase + dmabuf->write_channel->port; + port = dmabuf->write_channel->port; if(state->card->pci_id == PCI_DEVICE_ID_SI_7012) { port_picb = port + OFF_SR; @@ -733,8 +759,8 @@ port_picb = port + OFF_PICB; do { - civ = GET_CIV(port); - offset = inw(port_picb); + civ = GET_CIV(state->card, port); + offset = I810_IOREADW(state->card, port_picb); /* Must have a delay here! */ if(offset == 0) udelay(1); @@ -753,7 +779,7 @@ * that we won't have to worry about the chip still being * out of sync with reality ;-) */ - } while (civ != GET_CIV(port) || offset != inw(port_picb)); + } while (civ != GET_CIV(state->card, port) || offset != I810_IOREADW(state->card, port_picb)); return (((civ + 1) * dmabuf->fragsize - (bytes * offset)) % dmabuf->dmasize); @@ -766,15 +792,15 @@ struct i810_card *card = state->card; dmabuf->enable &= ~ADC_RUNNING; - outb(0, card->iobase + PI_CR); + I810_IOWRITEB(0, card, PI_CR); // wait for the card to acknowledge shutdown - while( inb(card->iobase + PI_CR) != 0 ) ; + while( I810_IOREADB(card, PI_CR) != 0 ) ; // now clear any latent interrupt bits (like the halt bit) if(card->pci_id == PCI_DEVICE_ID_SI_7012) - outb( inb(card->iobase + PI_PICB), card->iobase + PI_PICB ); + I810_IOWRITEB( I810_IOREADB(card, PI_PICB), card, PI_PICB ); else - outb( inb(card->iobase + PI_SR), card->iobase + PI_SR ); - outl( inl(card->iobase + GLOB_STA) & INT_PI, card->iobase + GLOB_STA); + I810_IOWRITEB( I810_IOREADB(card, PI_SR), card, PI_SR ); + I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PI, card, GLOB_STA); } static void stop_adc(struct i810_state *state) @@ -795,7 +821,7 @@ (dmabuf->trigger & PCM_ENABLE_INPUT)) { dmabuf->enable |= ADC_RUNNING; // Interrupt enable, LVI enable, DMA enable - outb(0x10 | 0x04 | 0x01, state->card->iobase + PI_CR); + I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PI_CR); } } @@ -816,15 +842,15 @@ struct i810_card *card = state->card; dmabuf->enable &= ~DAC_RUNNING; - outb(0, card->iobase + PO_CR); + I810_IOWRITEB(0, card, PO_CR); // wait for the card to acknowledge shutdown - while( inb(card->iobase + PO_CR) != 0 ) ; + while( I810_IOREADB(card, PO_CR) != 0 ) ; // now clear any latent interrupt bits (like the halt bit) if(card->pci_id == PCI_DEVICE_ID_SI_7012) - outb( inb(card->iobase + PO_PICB), card->iobase + PO_PICB ); + I810_IOWRITEB( I810_IOREADB(card, PO_PICB), card, PO_PICB ); else - outb( inb(card->iobase + PO_SR), card->iobase + PO_SR ); - outl( inl(card->iobase + GLOB_STA) & INT_PO, card->iobase + GLOB_STA); + I810_IOWRITEB( I810_IOREADB(card, PO_SR), card, PO_SR ); + I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PO, card, GLOB_STA); } static void stop_dac(struct i810_state *state) @@ -845,7 +871,7 @@ (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { dmabuf->enable |= DAC_RUNNING; // Interrupt enable, LVI enable, DMA enable - outb(0x10 | 0x04 | 0x01, state->card->iobase + PO_CR); + I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PO_CR); } } static void start_dac(struct i810_state *state) @@ -1008,12 +1034,12 @@ sg++; } spin_lock_irqsave(&state->card->lock, flags); - outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */ - while( inb(state->card->iobase+c->port+OFF_CR) & 0x02 ) ; - outl((u32)state->card->chandma + + I810_IOWRITEB(2, state->card, c->port+OFF_CR); /* reset DMA machine */ + while( I810_IOREADB(state->card, c->port+OFF_CR) & 0x02 ) ; + I810_IOWRITEL((u32)state->card->chandma + c->num*sizeof(struct i810_channel), - state->card->iobase+c->port+OFF_BDBAR); - CIV_TO_LVI(state->card->iobase+c->port, 0); + state->card, c->port+OFF_BDBAR); + CIV_TO_LVI(state->card, c->port, 0); spin_unlock_irqrestore(&state->card->lock, flags); @@ -1045,14 +1071,13 @@ void (*start)(struct i810_state *); count = dmabuf->count; - port = state->card->iobase; if (rec) { - port += dmabuf->read_channel->port; + port = dmabuf->read_channel->port; trigger = PCM_ENABLE_INPUT; start = __start_adc; count = dmabuf->dmasize - count; } else { - port += dmabuf->write_channel->port; + port = dmabuf->write_channel->port; trigger = PCM_ENABLE_OUTPUT; start = __start_dac; } @@ -1062,19 +1087,32 @@ if (count < fragsize) return; + /* if we are currently stopped, then our CIV is actually set to our + * *last* sg segment and we are ready to wrap to the next. However, + * if we set our LVI to the last sg segment, then it won't wrap to + * the next sg segment, it won't even get a start. So, instead, when + * we are stopped, we set both the LVI value and also we increment + * the CIV value to the next sg segment to be played so that when + * we call start, things will operate properly. Since the CIV can't + * be written to directly for this purpose, we set the LVI to CIV + 1 + * temporarily. Once the engine has started we set the LVI to its + * final value. + */ if (!dmabuf->enable && dmabuf->ready) { if (!(dmabuf->trigger & trigger)) return; + CIV_TO_LVI(state->card, port, 1); + start(state); - while (!(inb(port + OFF_CR) & ((1<<4) | (1<<2)))) + while (!(I810_IOREADB(state->card, port + OFF_CR) & ((1<<4) | (1<<2)))) ; } /* MASKP2(swptr, fragsize) - 1 is the tail of our transfer */ x = MODULOP2(MASKP2(dmabuf->swptr, fragsize) - 1, dmabuf->dmasize); x >>= dmabuf->fragshift; - outb(x, port + OFF_LVI); + I810_IOWRITEB(x, state->card, port + OFF_LVI); } static void i810_update_lvi(struct i810_state *state, int rec) @@ -1116,8 +1154,8 @@ /* this is normal for the end of a read */ /* only give an error if we went past the */ /* last valid sg entry */ - if (GET_CIV(state->card->iobase + PI_BASE) != - GET_LVI(state->card->iobase + PI_BASE)) { + if (GET_CIV(state->card, PI_BASE) != + GET_LVI(state->card, PI_BASE)) { printk(KERN_WARNING "i810_audio: DMA overrun on read\n"); dmabuf->error++; } @@ -1141,13 +1179,13 @@ /* this is normal for the end of a write */ /* only give an error if we went past the */ /* last valid sg entry */ - if (GET_CIV(state->card->iobase + PO_BASE) != - GET_LVI(state->card->iobase + PO_BASE)) { + if (GET_CIV(state->card, PO_BASE) != + GET_LVI(state->card, PO_BASE)) { printk(KERN_WARNING "i810_audio: DMA overrun on write\n"); printk("i810_audio: CIV %d, LVI %d, hwptr %x, " "count %d\n", - GET_CIV(state->card->iobase + PO_BASE), - GET_LVI(state->card->iobase + PO_BASE), + GET_CIV(state->card, PO_BASE), + GET_LVI(state->card, PO_BASE), dmabuf->hwptr, dmabuf->count); dmabuf->error++; } @@ -1295,7 +1333,7 @@ struct i810_state *state = card->states[i]; struct i810_channel *c; struct dmabuf *dmabuf; - unsigned long port = card->iobase; + unsigned long port; u16 status; if(!state) @@ -1310,12 +1348,12 @@ } else /* This can occur going from R/W to close */ continue; - port+=c->port; + port = c->port; if(card->pci_id == PCI_DEVICE_ID_SI_7012) - status = inw(port + OFF_PICB); + status = I810_IOREADW(card, port + OFF_PICB); else - status = inw(port + OFF_SR); + status = I810_IOREADW(card, port + OFF_SR); #ifdef DEBUG_INTERRUPTS printk("NUM %d PORT %X IRQ ( ST%d ", c->num, c->port, status); @@ -1348,7 +1386,7 @@ if(dmabuf->enable & ADC_RUNNING) count = dmabuf->dmasize - count; if (count >= (int)dmabuf->fragsize) { - outb(inb(port+OFF_CR) | 1, port+OFF_CR); + I810_IOWRITEB(I810_IOREADB(card, port+OFF_CR) | 1, card, port+OFF_CR); #ifdef DEBUG_INTERRUPTS printk(" CONTINUE "); #endif @@ -1364,9 +1402,9 @@ } } if(card->pci_id == PCI_DEVICE_ID_SI_7012) - outw(status & DMA_INT_MASK, port + OFF_PICB); + I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_PICB); else - outw(status & DMA_INT_MASK, port + OFF_SR); + I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_SR); } #ifdef DEBUG_INTERRUPTS printk(")\n"); @@ -1380,7 +1418,7 @@ spin_lock(&card->lock); - status = inl(card->iobase + GLOB_STA); + status = I810_IOREADL(card, GLOB_STA); if(!(status & INT_MASK)) { @@ -1392,7 +1430,7 @@ i810_channel_interrupt(card); /* clear 'em */ - outl(status & INT_MASK, card->iobase + GLOB_STA); + I810_IOWRITEL(status & INT_MASK, card, GLOB_STA); spin_unlock(&card->lock); return IRQ_HANDLED; } @@ -1790,13 +1828,13 @@ __stop_adc(state); } if (c != NULL) { - outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */ - while ( inb(state->card->iobase+c->port+OFF_CR) & 2 ) + I810_IOWRITEB(2, state->card, c->port+OFF_CR); /* reset DMA machine */ + while ( I810_IOREADB(state->card, c->port+OFF_CR) & 2 ) cpu_relax(); - outl((u32)state->card->chandma + + I810_IOWRITEL((u32)state->card->chandma + c->num*sizeof(struct i810_channel), - state->card->iobase+c->port+OFF_BDBAR); - CIV_TO_LVI(state->card->iobase+c->port, 0); + state->card, c->port+OFF_BDBAR); + CIV_TO_LVI(state->card, c->port, 0); } spin_unlock_irqrestore(&state->card->lock, flags); @@ -1926,7 +1964,7 @@ /* Global Status and Global Control register are now */ /* used to indicate this. */ - i_glob_cnt = inl(state->card->iobase + GLOB_CNT); + i_glob_cnt = I810_IOREADL(state->card, GLOB_CNT); /* Current # of channels enabled */ if ( i_glob_cnt & 0x0100000 ) @@ -1938,14 +1976,14 @@ switch ( val ) { case 2: /* 2 channels is always supported */ - outl(i_glob_cnt & 0xffcfffff, - state->card->iobase + GLOB_CNT); + I810_IOWRITEL(i_glob_cnt & 0xffcfffff, + state->card, GLOB_CNT); /* Do we need to change mixer settings???? */ break; case 4: /* Supported on some chipsets, better check first */ if ( state->card->channels >= 4 ) { - outl((i_glob_cnt & 0xffcfffff) | 0x100000, - state->card->iobase + GLOB_CNT); + I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x100000, + state->card, GLOB_CNT); /* Do we need to change mixer settings??? */ } else { val = ret; @@ -1953,8 +1991,8 @@ break; case 6: /* Supported on some chipsets, better check first */ if ( state->card->channels >= 6 ) { - outl((i_glob_cnt & 0xffcfffff) | 0x200000, - state->card->iobase + GLOB_CNT); + I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x200000, + state->card, GLOB_CNT); /* Do we need to change mixer settings??? */ } else { val = ret; @@ -2483,8 +2521,8 @@ } else { i810_set_dac_rate(state, 8000); /* Put the ACLink in 2 channel mode by default */ - i = inl(card->iobase + GLOB_CNT); - outl(i & 0xffcfffff, card->iobase + GLOB_CNT); + i = I810_IOREADL(card, GLOB_CNT); + I810_IOWRITEL(i & 0xffcfffff, card, GLOB_CNT); } } @@ -2575,7 +2613,7 @@ int count = 100; u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f); - while(count-- && (inb(card->iobase + CAS) & 1)) + while(count-- && (I810_IOREADB(card, CAS) & 1)) udelay(1); return inw(card->ac97base + reg_set); @@ -2603,7 +2641,7 @@ int count = 100; u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f); - while(count-- && (inb(card->iobase + CAS) & 1)) + while(count-- && (I810_IOREADB(card, CAS) & 1)) udelay(1); outw(data, card->ac97base + reg_set); @@ -2692,7 +2730,7 @@ static inline int i810_ac97_exists(struct i810_card *card, int ac97_number) { - u32 reg = inl(card->iobase + GLOB_STA); + u32 reg = I810_IOREADL(card, GLOB_STA); switch (ac97_number) { case 0: return reg & (1<<8); @@ -2763,7 +2801,7 @@ static int i810_ac97_power_up_bus(struct i810_card *card) { - u32 reg = inl(card->iobase + GLOB_CNT); + u32 reg = I810_IOREADL(card, GLOB_CNT); int i; int primary_codec_id = 0; @@ -2775,14 +2813,14 @@ reg&=~8; /* ACLink on */ /* At this point we deassert AC_RESET # */ - outl(reg , card->iobase + GLOB_CNT); + I810_IOWRITEL(reg , card, GLOB_CNT); /* We must now allow time for the Codec initialisation. 600mS is the specified time */ for(i=0;i<10;i++) { - if((inl(card->iobase+GLOB_CNT)&4)==0) + if((I810_IOREADL(card, GLOB_CNT)&4)==0) break; set_current_state(TASK_UNINTERRUPTIBLE); @@ -2801,8 +2839,11 @@ * See if the primary codec comes ready. This must happen * before we start doing DMA stuff */ - /* see i810_ac97_init for the next 7 lines (jsaw) */ - inw(card->ac97base); + /* see i810_ac97_init for the next 10 lines (jsaw) */ + if (card->use_mmio) + readw(card->ac97base_mmio); + else + inw(card->ac97base); if (ich_use_mmio(card)) { primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3; printk(KERN_INFO "i810_audio: Primary codec has ID %d\n", @@ -2820,7 +2861,10 @@ else printk("no response.\n"); } - inw(card->ac97base); + if (card->use_mmio) + readw(card->ac97base_mmio); + else + inw(card->ac97base); return 1; } @@ -2845,15 +2889,15 @@ /* to check.... */ card->channels = 2; - reg = inl(card->iobase + GLOB_STA); + reg = I810_IOREADL(card, GLOB_STA); if ( reg & 0x0200000 ) card->channels = 6; else if ( reg & 0x0100000 ) card->channels = 4; printk(KERN_INFO "i810_audio: Audio Controller supports %d channels.\n", card->channels); printk(KERN_INFO "i810_audio: Defaulting to base 2 channel mode.\n"); - reg = inl(card->iobase + GLOB_CNT); - outl(reg & 0xffcfffff, card->iobase + GLOB_CNT); + reg = I810_IOREADL(card, GLOB_CNT); + I810_IOWRITEL(reg & 0xffcfffff, card, GLOB_CNT); for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) card->ac97_codec[num_ac97] = NULL; @@ -2864,8 +2908,10 @@ for (num_ac97 = 0; num_ac97 < nr_ac97_max; num_ac97++) { /* codec reset */ printk(KERN_INFO "i810_audio: Resetting connection %d\n", num_ac97); - if (card->use_mmio) readw(card->ac97base_mmio + 0x80*num_ac97); - else inw(card->ac97base + 0x80*num_ac97); + if (card->use_mmio) + readw(card->ac97base_mmio + 0x80*num_ac97); + else + inw(card->ac97base + 0x80*num_ac97); /* If we have the SDATA_IN Map Register, as on ICH4, we do not loop thru all possible codec IDs but thru all @@ -3068,7 +3114,7 @@ goto config_out; } dmabuf->count = dmabuf->dmasize; - CIV_TO_LVI(card->iobase+dmabuf->write_channel->port, -1); + CIV_TO_LVI(card, dmabuf->write_channel->port, -1); local_irq_save(flags); start_dac(state); offset = i810_get_dma_addr(state, 0); @@ -3112,13 +3158,6 @@ return -ENODEV; } - if( pci_resource_start(pci_dev, 1) == 0) - { - /* MMIO only ICH5 .. here be dragons .. */ - printk(KERN_ERR "i810_audio: Pure MMIO interfaces not yet supported.\n"); - return -ENODEV; - } - if ((card = kmalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) { printk(KERN_ERR "i810_audio: out of memory\n"); return -ENOMEM; @@ -3131,6 +3170,11 @@ card->ac97base = pci_resource_start (pci_dev, 0); card->iobase = pci_resource_start (pci_dev, 1); + if (!(card->ac97base) || !(card->iobase)) { + card->ac97base = 0; + card->iobase = 0; + } + /* if chipset could have mmio capability, check it */ if (card_cap[pci_id->driver_data].flags & CAP_MMIO) { card->ac97base_mmio_phys = pci_resource_start (pci_dev, 2); @@ -3145,6 +3189,11 @@ } } + if (!(card->use_mmio) && (!(card->iobase) || !(card->ac97base))) { + printk(KERN_ERR "i810_audio: No I/O resources available.\n"); + goto out_mem; + } + card->irq = pci_dev->irq; card->next = devs; card->magic = I810_CARD_MAGIC; @@ -3190,8 +3239,14 @@ } /* claim our iospace and irq */ - request_region(card->iobase, 64, card_names[pci_id->driver_data]); - request_region(card->ac97base, 256, card_names[pci_id->driver_data]); + if (!request_region(card->iobase, 64, card_names[pci_id->driver_data])) { + printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->iobase); + goto out_region1; + } + if (!request_region(card->ac97base, 256, card_names[pci_id->driver_data])) { + printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->ac97base); + goto out_region2; + } if (request_irq(card->irq, &i810_interrupt, SA_SHIRQ, card_names[pci_id->driver_data], card)) { @@ -3264,8 +3319,10 @@ release_mem_region(card->iobase_mmio_phys, 256); } out_pio: - release_region(card->iobase, 64); release_region(card->ac97base, 256); +out_region2: + release_region(card->iobase, 64); +out_region1: pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH, card->channel, card->chandma); out_mem: diff -urN linux-2.4.31/drivers/usb/gadget/file_storage.c linux-2.4.32/drivers/usb/gadget/file_storage.c --- linux-2.4.31/drivers/usb/gadget/file_storage.c 2004-08-07 16:26:05.000000000 -0700 +++ linux-2.4.32/drivers/usb/gadget/file_storage.c 2005-11-16 11:12:54.641079339 -0800 @@ -1454,6 +1454,7 @@ /* Respond with data/status or defer until later? */ if (rc >= 0 && rc != DELAYED_STATUS) { fsg->ep0req->length = rc; + fsg->ep0req->zero = (rc < ctrl->wLength); fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? "ep0-in" : "ep0-out"); rc = ep0_queue(fsg); diff -urN linux-2.4.31/drivers/usb/host/usb-ohci.c linux-2.4.32/drivers/usb/host/usb-ohci.c --- linux-2.4.31/drivers/usb/host/usb-ohci.c 2005-01-19 06:10:07.000000000 -0800 +++ linux-2.4.32/drivers/usb/host/usb-ohci.c 2005-11-16 11:12:54.643079428 -0800 @@ -677,7 +677,6 @@ return -ENOMEM; } memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *)); - init_waitqueue_head (&urb_priv->wait); /* fill the private part of the URB */ urb_priv->length = size; @@ -824,10 +823,12 @@ urb_priv->ed->state |= ED_URB_DEL; if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) { + DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); DECLARE_WAITQUEUE (wait, current); int timeout = OHCI_UNLINK_TIMEOUT; - add_wait_queue(&urb_priv->wait, &wait); + add_wait_queue (&unlink_wakeup, &wait); + urb_priv->wait = &unlink_wakeup; spin_unlock_irqrestore(&ohci->ohci_lock, flags); /* wait until all TDs are deleted */ @@ -840,12 +841,10 @@ /* * A waitqueue head is self-locked, but we try - * to interlock with the dl_del_urb() which may - * be doing wake_up() right now, least - * urb->complete poisons over the urb->wait. + * to interlock with the dl_del_urb(). */ spin_lock_irqsave(&ohci->ohci_lock, flags); - remove_wait_queue(&urb_priv->wait, &wait); + remove_wait_queue(&unlink_wakeup, &wait); spin_unlock_irqrestore(&ohci->ohci_lock, flags); if (urb->status == USB_ST_URB_PENDING) { err ("unlink URB timeout"); @@ -1566,7 +1565,7 @@ static void dl_del_urb (ohci_t *ohci, struct urb * urb) { - urb_priv_t * urb_priv = urb->hcpriv; + wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait; urb_rm_priv_locked (urb); @@ -1577,7 +1576,8 @@ urb->status = -ENOENT; /* unblock sohci_unlink_urb */ - wake_up(&urb_priv->wait); + if (wait_head) + wake_up (wait_head); } } diff -urN linux-2.4.31/drivers/usb/host/usb-ohci.h linux-2.4.32/drivers/usb/host/usb-ohci.h --- linux-2.4.31/drivers/usb/host/usb-ohci.h 2005-01-19 06:10:07.000000000 -0800 +++ linux-2.4.32/drivers/usb/host/usb-ohci.h 2005-11-16 11:12:54.644079473 -0800 @@ -336,7 +336,7 @@ __u16 length; // number of tds associated with this request __u16 td_cnt; // number of tds already serviced int state; - wait_queue_head_t wait; + wait_queue_head_t * wait; td_t * td[0]; // list pointer to all corresponding TDs associated with this request } urb_priv_t; diff -urN linux-2.4.31/drivers/usb/printer.c linux-2.4.32/drivers/usb/printer.c --- linux-2.4.31/drivers/usb/printer.c 2004-08-07 16:26:05.000000000 -0700 +++ linux-2.4.32/drivers/usb/printer.c 2005-11-16 11:12:54.644079473 -0800 @@ -740,6 +740,7 @@ schedule(); } else { set_current_state(TASK_RUNNING); + down (&usblp->sem); break; } down (&usblp->sem); diff -urN linux-2.4.31/drivers/usb/serial/ftdi_sio.c linux-2.4.32/drivers/usb/serial/ftdi_sio.c --- linux-2.4.31/drivers/usb/serial/ftdi_sio.c 2005-04-03 18:42:19.000000000 -0700 +++ linux-2.4.32/drivers/usb/serial/ftdi_sio.c 2005-11-16 11:12:54.646079562 -0800 @@ -350,6 +350,17 @@ { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0, 0x3ff) }, + { USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_RM_CANVIEW_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0, 0x3ff) }, { } /* Terminating entry */ }; @@ -378,6 +389,7 @@ { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_PIEGROUP_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0x400, 0xffff) }, @@ -430,9 +442,41 @@ { USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E808_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E809_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80A_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80B_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80C_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80D_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80E_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80F_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E888_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E889_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88A_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88B_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88C_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88D_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_2_PID, 0x400, 0xffff) }, { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, + { USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0x400, 0xffff) }, + { USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_RM_CANVIEW_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0x400, 0xffff) }, { } /* Terminating entry */ }; @@ -482,6 +526,7 @@ { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID, 0x400, 0xffff) }, + { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, @@ -536,9 +581,41 @@ { USB_DEVICE(FTDI_VID, PROTEGO_R2X0) }, { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) }, { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E808_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E809_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80A_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80B_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80C_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80D_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80E_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80F_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E888_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E889_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88A_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88B_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88C_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88D_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) }, + { USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_2_PID, 0x400, 0xffff) }, { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, + { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, + { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, + { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, + { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, + { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, { } /* Terminating entry */ }; @@ -1012,7 +1089,7 @@ goto check_and_exit; } - if ((new_serial.baud_base != priv->baud_base) || + if ((new_serial.baud_base != priv->baud_base) && (new_serial.baud_base < 9600)) return -EINVAL; @@ -1238,25 +1315,23 @@ } /* ftdi_HE_TIRA1_startup */ -/* Startup for the 8U232AM chip */ +/* Startup for user specified 8U232AM (or 232BM) device */ static int ftdi_userdev_startup (struct usb_serial *serial) { struct ftdi_private *priv; + int err; - priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); - if (!priv){ - err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private)); - return -ENOMEM; + + dbg("%s",__FUNCTION__); + /* XXX Assume it's a FT8U232AM. An FT232BM device can be used, but + * it will behave like a FT8U232AM. -- IJA */ + err = ftdi_8U232AM_startup(serial); + if (err){ + return (err); } - priv->chip_type = FT8U232AM; /* XXX: Hmm. Keep this.... -- REW */ + priv = serial->port->private; priv->baud_base = baud_base; - priv->custom_divisor = 0; - priv->write_offset = 0; - init_waitqueue_head(&priv->delta_msr_wait); - /* This will push the characters through immediately rather - than queue a task to deliver them */ - priv->flags = ASYNC_LOW_LATENCY; return (0); } @@ -1451,7 +1526,7 @@ dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count); if (count == 0) { - err("write request of 0 bytes"); + dbg("write request of 0 bytes"); goto exit; } @@ -1585,17 +1660,18 @@ int i; unsigned long flags; - spin_lock_irqsave (&priv->write_urb_pool_lock, flags); - for (i = 0; i < NUM_URBS && priv->write_urb_pool[i]; i++) { - if (priv->write_urb_pool[i]->status != -EINPROGRESS) { - room += URB_TRANSFER_BUFFER_SIZE - priv->write_offset; - } + if (priv->write_urb_pool[i]->status != -EINPROGRESS) + room++; } - spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); + /* Harmless lies for the sake of line disciplines */ + if ((room -= 2) < 0) + room = 0; + + room *= URB_TRANSFER_BUFFER_SIZE - priv->write_offset; dbg("%s - returns %d", __FUNCTION__, room); return(room); } /* ftdi_write_room */ @@ -1913,6 +1989,13 @@ if (change_speed(port)) { err("%s urb failed to set baurdrate", __FUNCTION__); } + /* Ensure RTS and DTR are raised */ + else if (set_dtr(port, HIGH) < 0){ + err("%s Error from DTR HIGH urb", __FUNCTION__); + } + else if (set_rts(port, HIGH) < 0){ + err("%s Error from RTS HIGH urb", __FUNCTION__); + } } /* Set flow control */ @@ -2209,6 +2292,8 @@ dbg("%s", __FUNCTION__); + if (vendor != -1) + usb_serial_deregister (&ftdi_userdev_device); usb_serial_deregister (&ftdi_HE_TIRA1_device); usb_serial_deregister (&ftdi_USB_UIRT_device); usb_serial_deregister (&ftdi_FT232BM_device); diff -urN linux-2.4.31/drivers/usb/serial/ftdi_sio.h linux-2.4.32/drivers/usb/serial/ftdi_sio.h --- linux-2.4.31/drivers/usb/serial/ftdi_sio.h 2004-08-07 16:26:05.000000000 -0700 +++ linux-2.4.32/drivers/usb/serial/ftdi_sio.h 2005-11-16 11:12:54.647079606 -0800 @@ -143,6 +143,8 @@ /* ELV USB Module UO100 (PID sent by Stefan Frings) */ #define FTDI_ELV_UO100_PID 0xFB58 /* Product Id */ +/* ELV USB Module UM100 (PID sent by Arnim Laeuger) */ +#define FTDI_ELV_UM100_PID 0xFB5A /* Product Id */ /* * Definitions for ID TECH (www.idt-net.com) devices @@ -155,8 +157,13 @@ */ #define OCT_VID 0x0B39 /* OCT vendor ID */ /* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */ +/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */ +/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */ #define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ +/* an infrared receiver for user access control with IR tags */ +#define FTDI_PIEGROUP_PID 0xF208 /* Product Id */ + /* * Protego product ids */ @@ -165,11 +172,81 @@ #define PROTEGO_SPECIAL_3 0xFC72 /* special/unknown device */ #define PROTEGO_SPECIAL_4 0xFC73 /* special/unknown device */ +/* + * Gude Analog- und Digitalsysteme GmbH + */ +#define FTDI_GUDEADS_E808_PID 0xE808 +#define FTDI_GUDEADS_E809_PID 0xE809 +#define FTDI_GUDEADS_E80A_PID 0xE80A +#define FTDI_GUDEADS_E80B_PID 0xE80B +#define FTDI_GUDEADS_E80C_PID 0xE80C +#define FTDI_GUDEADS_E80D_PID 0xE80D +#define FTDI_GUDEADS_E80E_PID 0xE80E +#define FTDI_GUDEADS_E80F_PID 0xE80F +#define FTDI_GUDEADS_E888_PID 0xE888 /* Expert ISDN Control USB */ +#define FTDI_GUDEADS_E889_PID 0xE889 /* USB RS-232 OptoBridge */ +#define FTDI_GUDEADS_E88A_PID 0xE88A +#define FTDI_GUDEADS_E88B_PID 0xE88B +#define FTDI_GUDEADS_E88C_PID 0xE88C +#define FTDI_GUDEADS_E88D_PID 0xE88D +#define FTDI_GUDEADS_E88E_PID 0xE88E +#define FTDI_GUDEADS_E88F_PID 0xE88F + +/* + * Linx Technologies product ids + */ +#define LINX_SDMUSBQSS_PID 0xF448 /* Linx SDM-USB-QS-S */ +#define LINX_MASTERDEVEL2_PID 0xF449 /* Linx Master Development 2.0 */ +#define LINX_FUTURE_0_PID 0xF44A /* Linx future device */ +#define LINX_FUTURE_1_PID 0xF44B /* Linx future device */ +#define LINX_FUTURE_2_PID 0xF44C /* Linx future device */ + /* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */ /* unit for PIC16's/PIC18's */ #define FTDI_CCSICDU20_0_PID 0xF9D0 #define FTDI_CCSICDU40_1_PID 0xF9D1 +/* Inside Accesso contactless reader (http://www.insidefr.com) */ +#define INSIDE_ACCESSO 0xFAD0 + +/* + * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI + */ +#define INTREPID_VID 0x093C +#define INTREPID_VALUECAN_PID 0x0601 +#define INTREPID_NEOVI_PID 0x0701 + +/* + * Falcom Wireless Communications GmbH + */ +#define FALCOM_VID 0x0F94 /* Vendor Id */ +#define FALCOM_TWIST_PID 0x0001 /* Falcom Twist USB GPRS modem */ + +/* + * SUUNTO product ids + */ +#define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ + +/* + * Definitions for B&B Electronics products. + */ +#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ +#define BANDB_USOTL4_PID 0xAC01 /* USOTL4 Isolated RS-485 Converter */ +#define BANDB_USTL4_PID 0xAC02 /* USTL4 RS-485 Converter */ +#define BANDB_USO9ML2_PID 0xAC03 /* USO9ML2 Isolated RS-232 Converter */ + +/* + * RM Michaelides CANview USB (http://www.rmcan.com) + * CAN fieldbus interface adapter, added by port GmbH www.port.de). + * Ian Abbott changed the macro names for consistency. + */ +#define FTDI_RM_CANVIEW_PID 0xfd60 /* Product Id */ + +/* + * EVER Eco Pro UPS (http://www.ever.com.pl/) + */ +#define EVER_ECO_PRO_CDS 0xe520 /* RS-232 converter */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ diff -urN linux-2.4.31/fs/buffer.c linux-2.4.32/fs/buffer.c --- linux-2.4.31/fs/buffer.c 2004-11-17 03:54:21.000000000 -0800 +++ linux-2.4.32/fs/buffer.c 2005-11-16 11:12:54.649079695 -0800 @@ -584,7 +584,7 @@ (*bhp)->b_prev_free->b_next_free = bh; (*bhp)->b_prev_free = bh; nr_buffers_type[blist]++; - size_buffers_type[blist] += bh->b_size; + size_buffers_type[blist] += bh->b_size >> 9; } static void __remove_from_lru_list(struct buffer_head * bh) @@ -604,7 +604,7 @@ bh->b_next_free = NULL; bh->b_prev_free = NULL; nr_buffers_type[blist]--; - size_buffers_type[blist] -= bh->b_size; + size_buffers_type[blist] -= bh->b_size >> 9; } } @@ -1033,7 +1033,7 @@ { unsigned long dirty, tot, hard_dirty_limit, soft_dirty_limit; - dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT; + dirty = size_buffers_type[BUF_DIRTY] >> (PAGE_SHIFT - 9); tot = nr_free_buffer_pages(); dirty *= 100; @@ -1054,7 +1054,7 @@ { unsigned long dirty, tot, dirty_limit; - dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT; + dirty = size_buffers_type[BUF_DIRTY] >> (PAGE_SHIFT - 9); tot = nr_free_buffer_pages(); dirty *= 100; @@ -2839,7 +2839,7 @@ } printk("%9s: %d buffers, %lu kbyte, %d used (last=%d), " "%d locked, %d dirty, %d delay\n", - buf_types[nlist], found, size_buffers_type[nlist]>>10, + buf_types[nlist], found, size_buffers_type[nlist]>>(10-9), used, lastused, locked, dirty, delalloc); } spin_unlock(&lru_list_lock); diff -urN linux-2.4.31/fs/inode.c linux-2.4.32/fs/inode.c --- linux-2.4.31/fs/inode.c 2004-04-14 06:05:40.000000000 -0700 +++ linux-2.4.32/fs/inode.c 2005-11-16 11:12:54.650079740 -0800 @@ -297,7 +297,7 @@ { struct list_head *to; - if (inode->i_state & I_FREEING) + if (inode->i_state & (I_FREEING|I_CLEAR)) return; if (list_empty(&inode->i_hash)) return; @@ -634,7 +634,9 @@ cdput(inode->i_cdev); inode->i_cdev = NULL; } + spin_lock(&inode_lock); inode->i_state = I_CLEAR; + spin_unlock(&inode_lock); } /* diff -urN linux-2.4.31/fs/isofs/compress.c linux-2.4.32/fs/isofs/compress.c --- linux-2.4.31/fs/isofs/compress.c 2002-11-28 15:53:15.000000000 -0800 +++ linux-2.4.32/fs/isofs/compress.c 2005-11-16 11:12:54.650079740 -0800 @@ -147,8 +147,14 @@ cend = le32_to_cpu(*(u32 *)(bh->b_data + (blockendptr & bufmask))); brelse(bh); + if (cstart > cend) + goto eio; + csize = cend-cstart; + if (csize > deflateBound(1UL << zisofs_block_shift)) + goto eio; + /* Now page[] contains an array of pages, any of which can be NULL, and the locks on which we hold. We should now read the data and release the pages. If the pages are NULL the decompressed data diff -urN linux-2.4.31/fs/isofs/inode.c linux-2.4.32/fs/isofs/inode.c --- linux-2.4.31/fs/isofs/inode.c 2005-04-03 18:42:20.000000000 -0700 +++ linux-2.4.32/fs/isofs/inode.c 2005-11-16 11:12:54.651079785 -0800 @@ -335,16 +335,16 @@ else if (!strcmp(value,"acorn")) popt->map = 'a'; else return 0; } - if (!strcmp(this_char,"session") && value) { + else if (!strcmp(this_char,"session") && value) { char * vpnt = value; unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0); - if(ivalue < 0 || ivalue >99) return 0; + if (ivalue > 99) return 0; popt->session=ivalue+1; } - if (!strcmp(this_char,"sbsector") && value) { + else if (!strcmp(this_char,"sbsector") && value) { char * vpnt = value; unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0); - if(ivalue < 0 || ivalue >660*512) return 0; + if (ivalue > 660*512) return 0; popt->sbsector=ivalue; } else if (!strcmp(this_char,"check") && value) { diff -urN linux-2.4.31/fs/nfs/nfs2xdr.c linux-2.4.32/fs/nfs/nfs2xdr.c --- linux-2.4.31/fs/nfs/nfs2xdr.c 2002-11-28 15:53:15.000000000 -0800 +++ linux-2.4.32/fs/nfs/nfs2xdr.c 2005-11-16 11:12:54.652079829 -0800 @@ -571,8 +571,11 @@ strlen = (u32*)kmap(rcvbuf->pages[0]); /* Convert length of symlink */ len = ntohl(*strlen); - if (len > rcvbuf->page_len) - len = rcvbuf->page_len; + if (len >= rcvbuf->page_len - sizeof(u32) || len > NFS2_MAXPATHLEN) { + dprintk("NFS: server returned giant symlink!\n"); + kunmap(rcvbuf->pages[0]); + return -ENAMETOOLONG; + } *strlen = len; /* NULL terminate the string we got */ string = (char *)(strlen + 1); diff -urN linux-2.4.31/fs/nfs/nfs3xdr.c linux-2.4.32/fs/nfs/nfs3xdr.c --- linux-2.4.31/fs/nfs/nfs3xdr.c 2003-11-28 10:26:21.000000000 -0800 +++ linux-2.4.32/fs/nfs/nfs3xdr.c 2005-11-16 11:12:54.652079829 -0800 @@ -759,8 +759,11 @@ strlen = (u32*)kmap(rcvbuf->pages[0]); /* Convert length of symlink */ len = ntohl(*strlen); - if (len > rcvbuf->page_len) - len = rcvbuf->page_len; + if (len >= rcvbuf->page_len - sizeof(u32)) { + dprintk("NFS: server returned giant symlink!\n"); + kunmap(rcvbuf->pages[0]); + return -ENAMETOOLONG; + } *strlen = len; /* NULL terminate the string we got */ string = (char *)(strlen + 1); diff -urN linux-2.4.31/fs/nfsd/vfs.c linux-2.4.32/fs/nfsd/vfs.c --- linux-2.4.31/fs/nfsd/vfs.c 2005-04-03 18:42:20.000000000 -0700 +++ linux-2.4.32/fs/nfsd/vfs.c 2005-11-16 11:12:54.653079874 -0800 @@ -280,13 +280,17 @@ } /* Revoke setuid/setgid bit on chown/chgrp */ - if ((iap->ia_valid & ATTR_UID) && (imode & S_ISUID) - && iap->ia_uid != inode->i_uid) { + if ((iap->ia_valid & ATTR_UID) + && (imode & S_ISUID) + && !S_ISDIR(imode) + && iap->ia_uid != inode->i_uid) { iap->ia_valid |= ATTR_MODE; iap->ia_mode = imode &= ~S_ISUID; } - if ((iap->ia_valid & ATTR_GID) && (imode & S_ISGID) - && iap->ia_gid != inode->i_gid) { + if ((iap->ia_valid & ATTR_GID) + && (imode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) + && !S_ISDIR(imode) + && iap->ia_gid != inode->i_gid) { iap->ia_valid |= ATTR_MODE; iap->ia_mode = imode &= ~S_ISGID; } @@ -297,6 +301,7 @@ iap->ia_valid |= ATTR_CTIME; if (iap->ia_valid & ATTR_SIZE) { + down_write(&inode->i_alloc_sem); fh_lock(fhp); size_change = 1; } @@ -307,6 +312,7 @@ } if (size_change) { fh_unlock(fhp); + up_write(&inode->i_alloc_sem); put_write_access(inode); } if (!err) diff -urN linux-2.4.31/include/asm-i386/system.h linux-2.4.32/include/asm-i386/system.h --- linux-2.4.31/include/asm-i386/system.h 2004-04-14 06:05:40.000000000 -0700 +++ linux-2.4.32/include/asm-i386/system.h 2005-11-16 11:12:54.654079918 -0800 @@ -84,7 +84,7 @@ #define loadsegment(seg,value) \ asm volatile("\n" \ "1:\t" \ - "movl %0,%%" #seg "\n" \ + "mov %0,%%" #seg "\n" \ "2:\n" \ ".section .fixup,\"ax\"\n" \ "3:\t" \ @@ -96,7 +96,7 @@ ".align 4\n\t" \ ".long 1b,3b\n" \ ".previous" \ - : :"m" (*(unsigned int *)&(value))) + : :"m" (value)) /* * Clear and set 'TS' bit respectively diff -urN linux-2.4.31/include/asm-sparc64/uaccess.h linux-2.4.32/include/asm-sparc64/uaccess.h --- linux-2.4.31/include/asm-sparc64/uaccess.h 2004-11-17 03:54:22.000000000 -0800 +++ linux-2.4.32/include/asm-sparc64/uaccess.h 2005-11-16 11:12:54.654079918 -0800 @@ -294,10 +294,10 @@ } #define __copy_in_user copy_in_user +extern __kernel_size_t __bzero_noasi(void *addr, __kernel_size_t size); + extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size) { - extern __kernel_size_t __bzero_noasi(void *addr, __kernel_size_t size); - return __bzero_noasi(addr, size); } diff -urN linux-2.4.31/include/asm-x86_64/desc.h linux-2.4.32/include/asm-x86_64/desc.h --- linux-2.4.31/include/asm-x86_64/desc.h 2004-08-07 16:26:06.000000000 -0700 +++ linux-2.4.32/include/asm-x86_64/desc.h 2005-11-16 11:12:54.654079918 -0800 @@ -128,7 +128,7 @@ static inline void set_tss_desc(unsigned n, void *addr) { - set_tssldt_descriptor((void *)&gdt_table + __CPU_DESC_INDEX(n,tss), (unsigned long)addr, DESC_TSS, sizeof(struct tss_struct)); + set_tssldt_descriptor((void *)&gdt_table + __CPU_DESC_INDEX(n,tss), (unsigned long)addr, DESC_TSS, IO_BITMAP_OFFSET + IO_BITMAP_BYTES + 7); } static inline void set_ldt_desc(unsigned n, void *addr, int size) diff -urN linux-2.4.31/include/asm-x86_64/pci.h linux-2.4.32/include/asm-x86_64/pci.h --- linux-2.4.31/include/asm-x86_64/pci.h 2004-04-14 06:05:40.000000000 -0700 +++ linux-2.4.32/include/asm-x86_64/pci.h 2005-11-16 11:12:54.655079963 -0800 @@ -65,8 +65,9 @@ extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle); -#ifdef CONFIG_SWIOTLB extern int swiotlb; + +#ifdef CONFIG_SWIOTLB extern dma_addr_t swiotlb_map_single (struct pci_dev *hwdev, void *ptr, size_t size, int dir); extern void swiotlb_unmap_single (struct pci_dev *hwdev, dma_addr_t dev_addr, diff -urN linux-2.4.31/include/asm-x86_64/processor.h linux-2.4.32/include/asm-x86_64/processor.h --- linux-2.4.31/include/asm-x86_64/processor.h 2004-04-14 06:05:40.000000000 -0700 +++ linux-2.4.32/include/asm-x86_64/processor.h 2005-11-16 11:12:54.655079963 -0800 @@ -260,6 +260,7 @@ * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. */ #define IO_BITMAP_SIZE 32 +#define IO_BITMAP_BYTES (IO_BITMAP_SIZE * sizeof(u32)) #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap) #define INVALID_IO_BITMAP_OFFSET 0x8000 @@ -325,10 +326,9 @@ #define INIT_MMAP \ { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL } -#define STACKFAULT_STACK 1 -#define DOUBLEFAULT_STACK 2 -#define NMI_STACK 3 -#define N_EXCEPTION_STACKS 3 /* hw limit: 7 */ +#define DOUBLEFAULT_STACK 1 +#define NMI_STACK 2 +#define N_EXCEPTION_STACKS 2 /* hw limit: 7 */ #define EXCEPTION_STKSZ PAGE_SIZE #define EXCEPTION_STK_ORDER 0 diff -urN linux-2.4.31/include/linux/ata.h linux-2.4.32/include/linux/ata.h --- linux-2.4.31/include/linux/ata.h 2005-04-03 18:42:20.000000000 -0700 +++ linux-2.4.32/include/linux/ata.h 2005-11-16 11:12:54.655079963 -0800 @@ -224,6 +224,7 @@ }; #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) +#define ata_id_is_sata(id) ((id)[93] == 0) #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) #define ata_id_has_flush(id) ((id)[83] & (1 << 12)) diff -urN linux-2.4.31/include/linux/delay.h linux-2.4.32/include/linux/delay.h --- linux-2.4.31/include/linux/delay.h 2005-01-19 06:10:12.000000000 -0800 +++ linux-2.4.32/include/linux/delay.h 2005-11-16 11:12:54.656080007 -0800 @@ -14,6 +14,24 @@ #include /* + * We define MAX_MSEC_OFFSET as the maximal value that can be accepted by + * msecs_to_jiffies() without risking a multiply overflow. This function + * returns MAX_JIFFY_OFFSET for arguments above those values. + */ + +#if HZ <= 1000 && !(1000 % HZ) +# define MAX_MSEC_OFFSET \ + (ULONG_MAX - (1000 / HZ) + 1) +#elif HZ > 1000 && !(HZ % 1000) +# define MAX_MSEC_OFFSET \ + (ULONG_MAX / (HZ / 1000)) +#else +# define MAX_MSEC_OFFSET \ + ((ULONG_MAX - 999) / HZ) +#endif + + +/* * Convert jiffies to milliseconds and back. * * Avoid unnecessary multiplications/divisions in the @@ -43,14 +61,14 @@ static inline unsigned long msecs_to_jiffies(const unsigned int m) { - if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET)) + if (MAX_MSEC_OFFSET < UINT_MAX && m > (unsigned int)MAX_MSEC_OFFSET) return MAX_JIFFY_OFFSET; #if HZ <= 1000 && !(1000 % HZ) - return (m + (1000 / HZ) - 1) / (1000 / HZ); + return ((unsigned long)m + (1000 / HZ) - 1) / (1000 / HZ); #elif HZ > 1000 && !(HZ % 1000) - return m * (HZ / 1000); + return (unsigned long)m * (HZ / 1000); #else - return (m * HZ + 999) / 1000; + return ((unsigned long)m * HZ + 999) / 1000; #endif } diff -urN linux-2.4.31/include/linux/libata-compat.h linux-2.4.32/include/linux/libata-compat.h --- linux-2.4.31/include/linux/libata-compat.h 2005-04-03 18:42:20.000000000 -0700 +++ linux-2.4.32/include/linux/libata-compat.h 2005-11-16 11:12:54.656080007 -0800 @@ -23,6 +23,9 @@ return (struct pci_dev *) dev; } +static inline int pci_enable_msi(struct pci_dev *dev) { return -1; } +static inline void pci_disable_msi(struct pci_dev *dev) {} + #define pci_set_consistent_dma_mask(pdev,mask) (0) #define DMA_FROM_DEVICE PCI_DMA_FROMDEVICE diff -urN linux-2.4.31/include/linux/libata.h linux-2.4.32/include/linux/libata.h --- linux-2.4.31/include/linux/libata.h 2005-04-03 18:42:20.000000000 -0700 +++ linux-2.4.32/include/linux/libata.h 2005-11-16 11:12:54.657080052 -0800 @@ -411,6 +411,7 @@ extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf); extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); +extern void ata_host_stop (struct ata_host_set *host_set); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); extern void ata_qc_prep(struct ata_queued_cmd *qc); extern int ata_qc_issue_prot(struct ata_queued_cmd *qc); @@ -421,6 +422,7 @@ extern unsigned int ata_dev_classify(struct ata_taskfile *tf); extern void ata_dev_id_string(u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); +extern void ata_dev_config(struct ata_port *ap, unsigned int i); extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_port *ap); @@ -465,12 +467,34 @@ return ap->ops->check_status(ap); } + +/** + * ata_pause - Flush writes and pause 400 nanoseconds. + * @ap: Port to wait for. + * + * LOCKING: + * Inherited from caller. + */ + static inline void ata_pause(struct ata_port *ap) { ata_altstatus(ap); ndelay(400); } + +/** + * ata_busy_wait - Wait for a port status register + * @ap: Port to wait for. + * + * Waits up to max*10 microseconds for the selected bits in the port's + * status register to be cleared. + * Returns final value of status register. + * + * LOCKING: + * Inherited from caller. + */ + static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits, unsigned int max) { @@ -485,6 +509,18 @@ return status; } + +/** + * ata_wait_idle - Wait for a port to be idle. + * @ap: Port to wait for. + * + * Waits up to 10ms for port's BUSY and DRQ signals to clear. + * Returns final value of status register. + * + * LOCKING: + * Inherited from caller. + */ + static inline u8 ata_wait_idle(struct ata_port *ap) { u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); @@ -523,6 +559,18 @@ tf->device = ATA_DEVICE_OBS | ATA_DEV1; } + +/** + * ata_irq_on - Enable interrupts on a port. + * @ap: Port on which interrupts are enabled. + * + * Enable interrupts on a legacy IDE device using MMIO or PIO, + * wait for idle, clear any pending interrupts. + * + * LOCKING: + * Inherited from caller. + */ + static inline u8 ata_irq_on(struct ata_port *ap) { struct ata_ioports *ioaddr = &ap->ioaddr; @@ -542,6 +590,18 @@ return tmp; } + +/** + * ata_irq_ack - Acknowledge a device interrupt. + * @ap: Port on which interrupts are enabled. + * + * Wait up to 10 ms for legacy IDE device to become idle (BUSY + * or BUSY+DRQ clear). Obtain dma status and port status from + * device. Clear the interrupt. Return port status. + * + * LOCKING: + */ + static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) { unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY; @@ -583,6 +643,13 @@ ap->ops->scr_write(ap, reg, val); } +static inline void scr_write_flush(struct ata_port *ap, unsigned int reg, + u32 val) +{ + ap->ops->scr_write(ap, reg, val); + (void) ap->ops->scr_read(ap, reg); +} + static inline unsigned int sata_dev_present(struct ata_port *ap) { return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0; diff -urN linux-2.4.31/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h --- linux-2.4.31/include/linux/netfilter_ipv4/ip_conntrack.h 2005-04-03 18:42:20.000000000 -0700 +++ linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h 2005-11-16 11:12:54.657080052 -0800 @@ -229,7 +229,7 @@ ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo); /* decrement reference count on a conntrack */ -extern inline void ip_conntrack_put(struct ip_conntrack *ct); +extern void ip_conntrack_put(struct ip_conntrack *ct); /* find unconfirmed expectation based on tuple */ struct ip_conntrack_expect * diff -urN linux-2.4.31/include/linux/netfilter_ipv4/ip_nat_rule.h linux-2.4.32/include/linux/netfilter_ipv4/ip_nat_rule.h --- linux-2.4.31/include/linux/netfilter_ipv4/ip_nat_rule.h 2003-11-28 10:26:21.000000000 -0800 +++ linux-2.4.32/include/linux/netfilter_ipv4/ip_nat_rule.h 2005-11-16 11:12:54.657080052 -0800 @@ -19,5 +19,10 @@ alloc_null_binding(struct ip_conntrack *conntrack, struct ip_nat_info *info, unsigned int hooknum); + +extern unsigned int +alloc_null_binding_confirmed(struct ip_conntrack *conntrack, + struct ip_nat_info *info, + unsigned int hooknum); #endif #endif /* _IP_NAT_RULE_H */ diff -urN linux-2.4.31/include/linux/netfilter_ipv4/ip_tables.h linux-2.4.32/include/linux/netfilter_ipv4/ip_tables.h --- linux-2.4.31/include/linux/netfilter_ipv4/ip_tables.h 2005-04-03 18:42:20.000000000 -0700 +++ linux-2.4.32/include/linux/netfilter_ipv4/ip_tables.h 2005-11-16 11:12:54.657080052 -0800 @@ -283,8 +283,6 @@ struct ipt_entry entrytable[0]; }; -extern struct semaphore ipt_mutex; - /* Standard return verdict, or do jump. */ #define IPT_STANDARD_TARGET "" /* Error verdict. */ diff -urN linux-2.4.31/include/linux/pci_ids.h linux-2.4.32/include/linux/pci_ids.h --- linux-2.4.31/include/linux/pci_ids.h 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/include/linux/pci_ids.h 2005-11-16 11:12:54.659080141 -0800 @@ -608,6 +608,10 @@ #define PCI_DEVICE_ID_HP_PCIX_LBA 0x122e #define PCI_DEVICE_ID_HP_SX1000_IOC 0x127c #define PCI_DEVICE_ID_HP_CISS 0x3210 +#define PCI_DEVICE_ID_HP_CISSA 0x3220 +#define PCI_DEVICE_ID_HP_CISSB 0x3222 +#define PCI_DEVICE_ID_HP_CISSC 0x3230 +#define PCI_DEVICE_ID_HP_CISSD 0x3238 #define PCI_VENDOR_ID_PCTECH 0x1042 #define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 diff -urN linux-2.4.31/include/linux/zlib.h linux-2.4.32/include/linux/zlib.h --- linux-2.4.31/include/linux/zlib.h 2002-11-28 15:53:15.000000000 -0800 +++ linux-2.4.32/include/linux/zlib.h 2005-11-16 11:12:54.660080186 -0800 @@ -516,6 +516,11 @@ stream state was inconsistent (such as zalloc or state being NULL). */ +static inline unsigned long deflateBound(unsigned long s) +{ + return s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11; +} + ZEXTERN int ZEXPORT zlib_deflateParams OF((z_streamp strm, int level, int strategy)); diff -urN linux-2.4.31/include/net/ax25.h linux-2.4.32/include/net/ax25.h --- linux-2.4.31/include/net/ax25.h 2001-11-22 11:47:11.000000000 -0800 +++ linux-2.4.32/include/net/ax25.h 2005-11-16 11:12:54.660080186 -0800 @@ -142,7 +142,7 @@ ax25_address calls[AX25_MAX_DIGIS]; unsigned char repeated[AX25_MAX_DIGIS]; unsigned char ndigi; - char lastrepeat; + signed char lastrepeat; } ax25_digi; typedef struct ax25_route { diff -urN linux-2.4.31/include/net/ip6_fib.h linux-2.4.32/include/net/ip6_fib.h --- linux-2.4.31/include/net/ip6_fib.h 2004-11-17 03:54:22.000000000 -0800 +++ linux-2.4.32/include/net/ip6_fib.h 2005-11-16 11:12:54.661080230 -0800 @@ -171,13 +171,16 @@ extern int fib6_add(struct fib6_node *root, struct rt6_info *rt, - struct nlmsghdr *nlh); + struct nlmsghdr *nlh, + struct netlink_skb_parms *req); extern int fib6_del(struct rt6_info *rt, - struct nlmsghdr *nlh); + struct nlmsghdr *nlh, + struct netlink_skb_parms *req); extern void inet6_rt_notify(int event, struct rt6_info *rt, - struct nlmsghdr *nlh); + struct nlmsghdr *nlh, + struct netlink_skb_parms *req); extern void fib6_run_gc(unsigned long dummy); diff -urN linux-2.4.31/include/net/ip6_route.h linux-2.4.32/include/net/ip6_route.h --- linux-2.4.31/include/net/ip6_route.h 2003-06-13 07:51:39.000000000 -0700 +++ linux-2.4.32/include/net/ip6_route.h 2005-11-16 11:12:54.661080230 -0800 @@ -39,9 +39,11 @@ extern int ipv6_route_ioctl(unsigned int cmd, void *arg); extern int ip6_route_add(struct in6_rtmsg *rtmsg, - struct nlmsghdr *); + struct nlmsghdr *, + struct netlink_skb_parms *req); extern int ip6_del_rt(struct rt6_info *, - struct nlmsghdr *); + struct nlmsghdr *, + struct netlink_skb_parms *req); extern int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev); diff -urN linux-2.4.31/include/net/ip_vs.h linux-2.4.32/include/net/ip_vs.h --- linux-2.4.31/include/net/ip_vs.h 2005-01-19 06:10:13.000000000 -0800 +++ linux-2.4.32/include/net/ip_vs.h 2005-11-16 11:12:54.661080230 -0800 @@ -82,6 +82,7 @@ #define IP_VS_CONN_F_IN_SEQ 0x0400 /* must do input seq adjust */ #define IP_VS_CONN_F_SEQ_MASK 0x0600 /* in/out sequence mask */ #define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */ +#define IP_VS_CONN_F_TEMPLATE 0x1000 /* template, not connection */ /* Move it to better place one day, for now keep it unique */ #define NFC_IPVS_PROPERTY 0x10000 @@ -592,6 +593,8 @@ extern struct ip_vs_conn *ip_vs_conn_in_get (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); +extern struct ip_vs_conn *ip_vs_ct_in_get +(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); extern struct ip_vs_conn *ip_vs_conn_out_get (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); diff -urN linux-2.4.31/lib/inflate.c linux-2.4.32/lib/inflate.c --- linux-2.4.31/lib/inflate.c 2002-11-28 15:53:15.000000000 -0800 +++ linux-2.4.32/lib/inflate.c 2005-11-16 11:12:54.662080275 -0800 @@ -320,7 +320,7 @@ { *t = (struct huft *)NULL; *m = 0; - return 0; + return 2; } DEBG("huft2 "); @@ -368,6 +368,7 @@ if ((j = *p++) != 0) v[x[j]++] = i; } while (++i < n); + n = x[g]; /* set n to length of v */ DEBG("h6 "); @@ -404,12 +405,13 @@ DEBG1("2 "); f -= a + 1; /* deduct codes from patterns left */ xp = c + k; - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } } DEBG1("3 "); z = 1 << j; /* table entries for j-bit table */ diff -urN linux-2.4.31/lib/rbtree.c linux-2.4.32/lib/rbtree.c --- linux-2.4.31/lib/rbtree.c 2004-11-17 03:54:22.000000000 -0800 +++ linux-2.4.32/lib/rbtree.c 2005-11-16 11:12:54.663080319 -0800 @@ -332,6 +332,7 @@ node = node->rb_right; while (node->rb_left) node = node->rb_left; + return node; } /* No right-hand children. Everything down and left is @@ -355,6 +356,7 @@ node = node->rb_left; while (node->rb_right) node = node->rb_right; + return node; } /* No left-hand children. Go up till we find an ancestor which diff -urN linux-2.4.31/mm/vmscan.c linux-2.4.32/mm/vmscan.c --- linux-2.4.31/mm/vmscan.c 2005-01-19 06:10:13.000000000 -0800 +++ linux-2.4.32/mm/vmscan.c 2005-11-16 11:12:54.663080319 -0800 @@ -556,6 +556,7 @@ continue; } + smp_rmb(); if (PageDirty(page)) { spin_unlock(&pagecache_lock); UnlockPage(page); diff -urN linux-2.4.31/net/ipv4/igmp.c linux-2.4.32/net/ipv4/igmp.c --- linux-2.4.31/net/ipv4/igmp.c 2005-01-19 06:10:13.000000000 -0800 +++ linux-2.4.32/net/ipv4/igmp.c 2005-11-16 11:12:54.664080364 -0800 @@ -1582,7 +1582,7 @@ } pmc->sources = 0; pmc->sfmode = MCAST_EXCLUDE; - pmc->sfcount[MCAST_EXCLUDE] = 0; + pmc->sfcount[MCAST_INCLUDE] = 0; pmc->sfcount[MCAST_EXCLUDE] = 1; } diff -urN linux-2.4.31/net/ipv4/inetpeer.c linux-2.4.32/net/ipv4/inetpeer.c --- linux-2.4.31/net/ipv4/inetpeer.c 2001-10-01 09:19:56.000000000 -0700 +++ linux-2.4.32/net/ipv4/inetpeer.c 2005-11-16 11:12:54.665080409 -0800 @@ -445,9 +445,12 @@ /* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime * interval depending on the total number of entries (more entries, * less interval). */ - peer_periodic_timer.expires = jiffies - + inet_peer_gc_maxtime - - (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ * - peer_total / inet_peer_threshold * HZ; + if (peer_total >= inet_peer_threshold) + peer_periodic_timer.expires = jiffies + inet_peer_gc_mintime; + else + peer_periodic_timer.expires = jiffies + + inet_peer_gc_maxtime + - (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ * + peer_total / inet_peer_threshold * HZ; add_timer(&peer_periodic_timer); } diff -urN linux-2.4.31/net/ipv4/ipvs/ip_vs_conn.c linux-2.4.32/net/ipv4/ipvs/ip_vs_conn.c --- linux-2.4.31/net/ipv4/ipvs/ip_vs_conn.c 2005-01-19 06:10:13.000000000 -0800 +++ linux-2.4.32/net/ipv4/ipvs/ip_vs_conn.c 2005-11-16 11:12:54.666080453 -0800 @@ -210,6 +210,7 @@ cp = list_entry(e, struct ip_vs_conn, c_list); if (s_addr==cp->caddr && s_port==cp->cport && d_port==cp->vport && d_addr==cp->vaddr && + ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) && protocol==cp->protocol) { /* HIT */ atomic_inc(&cp->refcnt); @@ -241,6 +242,40 @@ return cp; } +/* Get reference to connection template */ +struct ip_vs_conn *ip_vs_ct_in_get +(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port) +{ + unsigned hash; + struct ip_vs_conn *cp; + + hash = ip_vs_conn_hashkey(protocol, s_addr, s_port); + + ct_read_lock(hash); + + list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { + if (s_addr==cp->caddr && s_port==cp->cport && + d_port==cp->vport && d_addr==cp->vaddr && + cp->flags & IP_VS_CONN_F_TEMPLATE && + protocol==cp->protocol) { + /* HIT */ + atomic_inc(&cp->refcnt); + goto out; + } + } + cp = NULL; + + out: + ct_read_unlock(hash); + + IP_VS_DBG(7, "template lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n", + ip_vs_proto_name(protocol), + NIPQUAD(s_addr), ntohs(s_port), + NIPQUAD(d_addr), ntohs(d_port), + cp?"hit":"not hit"); + + return cp; +} /* * Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab. @@ -1087,7 +1122,7 @@ IP_VS_DBG(9, "Unbind-dest %s c:%u.%u.%u.%u:%d " "v:%u.%u.%u.%u:%d d:%u.%u.%u.%u:%d fwd:%c " - "s:%s flg:%X cnt:%d destcnt:%d", + "s:%s flg:%X cnt:%d destcnt:%d\n", ip_vs_proto_name(cp->protocol), NIPQUAD(cp->caddr), ntohs(cp->cport), NIPQUAD(cp->vaddr), ntohs(cp->vport), @@ -1098,10 +1133,9 @@ /* * Decrease the inactconns or activeconns counter - * if it is not a connection template ((cp->cport!=0) - * || (cp->flags & IP_VS_CONN_F_NO_CPORT)). + * if it is not a connection template */ - if (cp->cport || (cp->flags & IP_VS_CONN_F_NO_CPORT)) { + if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) { if (cp->flags & IP_VS_CONN_F_INACTIVE) { atomic_dec(&dest->inactconns); } else { @@ -1145,7 +1179,7 @@ /* * Invalidate the connection template */ - if (ct->cport) { + if (ct->vport != 65535) { if (ip_vs_conn_unhash(ct)) { ct->dport = 65535; ct->vport = 65535; @@ -1248,7 +1282,6 @@ { cp->timeout = 0; mod_timer(&cp->timer, jiffies); - __ip_vs_conn_put(cp); } /* @@ -1414,7 +1447,6 @@ int idx; struct ip_vs_conn *cp; struct list_head *l,*e; - struct ip_vs_conn *ct; /* * Randomly scan 1/32 of the whole table every second @@ -1430,7 +1462,7 @@ l = &ip_vs_conn_tab[hash]; for (e=l->next; e!=l; e=e->next) { cp = list_entry(e, struct ip_vs_conn, c_list); - if (!cp->cport && !(cp->flags & IP_VS_CONN_F_NO_CPORT)) + if (cp->flags & IP_VS_CONN_F_TEMPLATE) /* connection template */ continue; switch(cp->state) { @@ -1448,21 +1480,12 @@ continue; } - /* - * Drop the entry, and drop its ct if not referenced - */ - atomic_inc(&cp->refcnt); - ct_write_unlock(hash); - - if ((ct = cp->control)) - atomic_inc(&ct->refcnt); IP_VS_DBG(4, "del connection\n"); ip_vs_conn_expire_now(cp); - if (ct) { + if (cp->control) { IP_VS_DBG(4, "del conn template\n"); - ip_vs_conn_expire_now(ct); + ip_vs_conn_expire_now(cp->control); } - ct_write_lock(hash); } ct_write_unlock(hash); } @@ -1477,7 +1500,6 @@ int idx; struct ip_vs_conn *cp; struct list_head *l,*e; - struct ip_vs_conn *ct; flush_again: for (idx=0; idxnext; e!=l; e=e->next) { cp = list_entry(e, struct ip_vs_conn, c_list); - atomic_inc(&cp->refcnt); - ct_write_unlock(idx); - if ((ct = cp->control)) - atomic_inc(&ct->refcnt); IP_VS_DBG(4, "del connection\n"); ip_vs_conn_expire_now(cp); - if (ct) { + if (cp->control) { IP_VS_DBG(4, "del conn template\n"); - ip_vs_conn_expire_now(ct); + ip_vs_conn_expire_now(cp->control); } - ct_write_lock(idx); } ct_write_unlock_bh(idx); } diff -urN linux-2.4.31/net/ipv4/ipvs/ip_vs_core.c linux-2.4.32/net/ipv4/ipvs/ip_vs_core.c --- linux-2.4.31/net/ipv4/ipvs/ip_vs_core.c 2005-04-03 18:42:20.000000000 -0700 +++ linux-2.4.32/net/ipv4/ipvs/ip_vs_core.c 2005-11-16 11:12:54.667080498 -0800 @@ -188,10 +188,10 @@ if (portp[1] == svc->port) { /* Check if a template already exists */ if (svc->port != FTPPORT) - ct = ip_vs_conn_in_get(iph->protocol, snet, 0, + ct = ip_vs_ct_in_get(iph->protocol, snet, 0, iph->daddr, portp[1]); else - ct = ip_vs_conn_in_get(iph->protocol, snet, 0, + ct = ip_vs_ct_in_get(iph->protocol, snet, 0, iph->daddr, 0); if (!ct || !ip_vs_check_template(ct)) { @@ -216,14 +216,14 @@ snet, 0, iph->daddr, portp[1], dest->addr, dest->port, - 0, + IP_VS_CONN_F_TEMPLATE, dest); else ct = ip_vs_conn_new(iph->protocol, snet, 0, iph->daddr, 0, dest->addr, 0, - 0, + IP_VS_CONN_F_TEMPLATE, dest); if (ct == NULL) return NULL; @@ -242,10 +242,10 @@ * port zero template: */ if (svc->fwmark) - ct = ip_vs_conn_in_get(IPPROTO_IP, snet, 0, + ct = ip_vs_ct_in_get(IPPROTO_IP, snet, 0, htonl(svc->fwmark), 0); else - ct = ip_vs_conn_in_get(iph->protocol, snet, 0, + ct = ip_vs_ct_in_get(iph->protocol, snet, 0, iph->daddr, 0); if (!ct || !ip_vs_check_template(ct)) { @@ -270,14 +270,14 @@ snet, 0, htonl(svc->fwmark), 0, dest->addr, 0, - 0, + IP_VS_CONN_F_TEMPLATE, dest); else ct = ip_vs_conn_new(iph->protocol, snet, 0, iph->daddr, 0, dest->addr, 0, - 0, + IP_VS_CONN_F_TEMPLATE, dest); if (ct == NULL) return NULL; @@ -1111,11 +1111,10 @@ if (sysctl_ip_vs_expire_nodest_conn) { /* try to expire the connection immediately */ ip_vs_conn_expire_now(cp); - } else { - /* don't restart its timer, and silently - drop the packet. */ - __ip_vs_conn_put(cp); } + /* don't restart its timer, and silently + drop the packet. */ + __ip_vs_conn_put(cp); return NF_DROP; } diff -urN linux-2.4.31/net/ipv4/ipvs/ip_vs_sync.c linux-2.4.32/net/ipv4/ipvs/ip_vs_sync.c --- linux-2.4.31/net/ipv4/ipvs/ip_vs_sync.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/net/ipv4/ipvs/ip_vs_sync.c 2005-11-16 11:12:54.668080542 -0800 @@ -295,16 +295,24 @@ p = (char *)buffer + sizeof(struct ip_vs_sync_mesg); for (i=0; inr_conns; i++) { + unsigned flags; + s = (struct ip_vs_sync_conn *)p; - cp = ip_vs_conn_in_get(s->protocol, - s->caddr, s->cport, - s->vaddr, s->vport); + flags = ntohs(s->flags); + if (!(flags & IP_VS_CONN_F_TEMPLATE)) + cp = ip_vs_conn_in_get(s->protocol, + s->caddr, s->cport, + s->vaddr, s->vport); + else + cp = ip_vs_ct_in_get(s->protocol, + s->caddr, s->cport, + s->vaddr, s->vport); if (!cp) { cp = ip_vs_conn_new(s->protocol, s->caddr, s->cport, s->vaddr, s->vport, s->daddr, s->dport, - ntohs(s->flags), NULL); + flags, NULL); if (!cp) { IP_VS_ERR("ip_vs_conn_new failed\n"); return; @@ -313,11 +321,11 @@ } else if (!cp->dest) { /* it is an entry created by the synchronization */ cp->state = ntohs(s->state); - cp->flags = ntohs(s->flags) | IP_VS_CONN_F_HASHED; + cp->flags = flags | IP_VS_CONN_F_HASHED; } /* Note that we don't touch its state and flags if it is a normal entry. */ - if (ntohs(s->flags) & IP_VS_CONN_F_SEQ_MASK) { + if (flags & IP_VS_CONN_F_SEQ_MASK) { opt = (struct ip_vs_sync_conn_options *)&s[1]; memcpy(&cp->in_seq, opt, sizeof(*opt)); p += FULL_CONN_SIZE; diff -urN linux-2.4.31/net/ipv4/netfilter/ip_nat_proto_icmp.c linux-2.4.32/net/ipv4/netfilter/ip_nat_proto_icmp.c --- linux-2.4.31/net/ipv4/netfilter/ip_nat_proto_icmp.c 2000-03-17 10:56:20.000000000 -0800 +++ linux-2.4.32/net/ipv4/netfilter/ip_nat_proto_icmp.c 2005-11-16 11:12:54.668080542 -0800 @@ -26,16 +26,17 @@ const struct ip_conntrack *conntrack) { static u_int16_t id = 0; - unsigned int range_size - = (unsigned int)range->max.icmp.id - range->min.icmp.id + 1; + unsigned int range_size; unsigned int i; + range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1; /* If no range specified... */ if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) range_size = 0xFFFF; for (i = 0; i < range_size; i++, id++) { - tuple->src.u.icmp.id = range->min.icmp.id + (id % range_size); + tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) + + (id % range_size)); if (!ip_nat_used_tuple(tuple, conntrack)) return 1; } diff -urN linux-2.4.31/net/ipv4/netfilter/ip_nat_proto_tcp.c linux-2.4.32/net/ipv4/netfilter/ip_nat_proto_tcp.c --- linux-2.4.31/net/ipv4/netfilter/ip_nat_proto_tcp.c 2002-11-28 15:53:15.000000000 -0800 +++ linux-2.4.32/net/ipv4/netfilter/ip_nat_proto_tcp.c 2005-11-16 11:12:54.668080542 -0800 @@ -31,7 +31,8 @@ enum ip_nat_manip_type maniptype, const struct ip_conntrack *conntrack) { - static u_int16_t port = 0, *portptr; + static u_int16_t port = 0; + u_int16_t *portptr; unsigned int range_size, min, i; if (maniptype == IP_NAT_MANIP_SRC) diff -urN linux-2.4.31/net/ipv4/netfilter/ip_nat_proto_udp.c linux-2.4.32/net/ipv4/netfilter/ip_nat_proto_udp.c --- linux-2.4.31/net/ipv4/netfilter/ip_nat_proto_udp.c 2000-08-04 13:07:24.000000000 -0700 +++ linux-2.4.32/net/ipv4/netfilter/ip_nat_proto_udp.c 2005-11-16 11:12:54.669080587 -0800 @@ -32,7 +32,8 @@ enum ip_nat_manip_type maniptype, const struct ip_conntrack *conntrack) { - static u_int16_t port = 0, *portptr; + static u_int16_t port = 0; + u_int16_t *portptr; unsigned int range_size, min, i; if (maniptype == IP_NAT_MANIP_SRC) diff -urN linux-2.4.31/net/ipv4/netfilter/ip_nat_rule.c linux-2.4.32/net/ipv4/netfilter/ip_nat_rule.c --- linux-2.4.31/net/ipv4/netfilter/ip_nat_rule.c 2005-01-19 06:10:13.000000000 -0800 +++ linux-2.4.32/net/ipv4/netfilter/ip_nat_rule.c 2005-11-16 11:12:54.669080587 -0800 @@ -241,6 +241,27 @@ return ip_nat_setup_info(conntrack, &mr, hooknum); } +unsigned int +alloc_null_binding_confirmed(struct ip_conntrack *conntrack, + struct ip_nat_info *info, + unsigned int hooknum) +{ + u_int32_t ip + = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC + ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip + : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip); + u_int16_t all + = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC + ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all + : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all); + struct ip_nat_multi_range mr + = { 1, { { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } } } }; + + DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n", + conntrack, NIPQUAD(ip)); + return ip_nat_setup_info(conntrack, &mr, hooknum); +} + int ip_nat_rule_find(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, diff -urN linux-2.4.31/net/ipv4/netfilter/ip_nat_standalone.c linux-2.4.32/net/ipv4/netfilter/ip_nat_standalone.c --- linux-2.4.31/net/ipv4/netfilter/ip_nat_standalone.c 2005-04-03 18:42:20.000000000 -0700 +++ linux-2.4.32/net/ipv4/netfilter/ip_nat_standalone.c 2005-11-16 11:12:54.669080587 -0800 @@ -123,8 +123,12 @@ ret = call_expect(master_ct(ct), pskb, hooknum, ct, info); } else { - /* LOCAL_IN hook doesn't have a chain! */ - if (hooknum == NF_IP_LOCAL_IN) + if (unlikely(is_confirmed(ct))) + /* NAT module was loaded late */ + ret = alloc_null_binding_confirmed(ct, info, + hooknum); + else if (hooknum == NF_IP_LOCAL_IN) + /* LOCAL_IN hook doesn't have a chain */ ret = alloc_null_binding(ct, info, hooknum); else diff -urN linux-2.4.31/net/ipv4/netfilter/ip_queue.c linux-2.4.32/net/ipv4/netfilter/ip_queue.c --- linux-2.4.31/net/ipv4/netfilter/ip_queue.c 2004-02-18 05:36:32.000000000 -0800 +++ linux-2.4.32/net/ipv4/netfilter/ip_queue.c 2005-11-16 11:12:54.670080631 -0800 @@ -62,7 +62,9 @@ static void ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) { + local_bh_disable(); nf_reinject(entry->skb, entry->info, verdict); + local_bh_enable(); kfree(entry); } diff -urN linux-2.4.31/net/ipv4/netfilter/ipt_unclean.c linux-2.4.32/net/ipv4/netfilter/ipt_unclean.c --- linux-2.4.31/net/ipv4/netfilter/ipt_unclean.c 2004-08-07 16:26:06.000000000 -0700 +++ linux-2.4.32/net/ipv4/netfilter/ipt_unclean.c 2005-11-16 11:12:54.670080631 -0800 @@ -264,6 +264,7 @@ { [TH_SYN] = 1, [TH_SYN|TH_ACK] = 1, + [TH_SYN|TH_ACK|TH_PUSH] = 1, [TH_RST] = 1, [TH_RST|TH_ACK] = 1, [TH_RST|TH_ACK|TH_PUSH] = 1, diff -urN linux-2.4.31/net/ipv4/tcp_input.c linux-2.4.32/net/ipv4/tcp_input.c --- linux-2.4.31/net/ipv4/tcp_input.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/net/ipv4/tcp_input.c 2005-11-16 11:12:54.673080765 -0800 @@ -374,8 +374,6 @@ app_win -= tp->ack.rcv_mss; app_win = max(app_win, 2U*tp->advmss); - if (!ofo_win) - tp->window_clamp = min(tp->window_clamp, app_win); tp->rcv_ssthresh = min(tp->window_clamp, 2U*tp->advmss); } } @@ -2488,6 +2486,7 @@ /* Note, it is the only place, where * fast path is recovered for sending TCP. */ + tp->pred_flags = 0; tcp_fast_path_check(sk, tp); if (nwin > tp->max_window) { diff -urN linux-2.4.31/net/ipv6/addrconf.c linux-2.4.32/net/ipv6/addrconf.c --- linux-2.4.31/net/ipv6/addrconf.c 2004-11-17 03:54:22.000000000 -0800 +++ linux-2.4.32/net/ipv6/addrconf.c 2005-11-16 11:12:54.675080854 -0800 @@ -883,7 +883,7 @@ if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT)) rtmsg.rtmsg_flags |= RTF_NONEXTHOP; - ip6_route_add(&rtmsg, NULL); + ip6_route_add(&rtmsg, NULL, NULL); } /* Create "default" multicast route to the interface */ @@ -900,7 +900,7 @@ rtmsg.rtmsg_ifindex = dev->ifindex; rtmsg.rtmsg_flags = RTF_UP; rtmsg.rtmsg_type = RTMSG_NEWROUTE; - ip6_route_add(&rtmsg, NULL); + ip6_route_add(&rtmsg, NULL, NULL); } static void sit_route_add(struct net_device *dev) @@ -917,7 +917,7 @@ rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP; rtmsg.rtmsg_ifindex = dev->ifindex; - ip6_route_add(&rtmsg, NULL); + ip6_route_add(&rtmsg, NULL, NULL); } static void addrconf_add_lroute(struct net_device *dev) @@ -1009,7 +1009,7 @@ if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { if (rt->rt6i_flags&RTF_EXPIRES) { if (pinfo->onlink == 0 || valid_lft == 0) { - ip6_del_rt(rt, NULL); + ip6_del_rt(rt, NULL, NULL); rt = NULL; } else { rt->rt6i_expires = rt_expires; @@ -1592,7 +1592,7 @@ rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex; - ip6_route_add(&rtmsg, NULL); + ip6_route_add(&rtmsg, NULL, NULL); } out: diff -urN linux-2.4.31/net/ipv6/ip6_fib.c linux-2.4.32/net/ipv6/ip6_fib.c --- linux-2.4.31/net/ipv6/ip6_fib.c 2004-11-17 03:54:22.000000000 -0800 +++ linux-2.4.32/net/ipv6/ip6_fib.c 2005-11-16 11:12:54.676080899 -0800 @@ -424,7 +424,7 @@ */ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, - struct nlmsghdr *nlh) + struct nlmsghdr *nlh, struct netlink_skb_parms *req) { struct rt6_info *iter = NULL; struct rt6_info **ins; @@ -482,7 +482,7 @@ *ins = rt; rt->rt6i_node = fn; atomic_inc(&rt->rt6i_ref); - inet6_rt_notify(RTM_NEWROUTE, rt, nlh); + inet6_rt_notify(RTM_NEWROUTE, rt, nlh, req); rt6_stats.fib_rt_entries++; if ((fn->fn_flags & RTN_RTINFO) == 0) { @@ -506,7 +506,8 @@ * with source addr info in sub-trees */ -int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh) +int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh, + struct netlink_skb_parms *req) { struct fib6_node *fn; int err = -ENOMEM; @@ -579,7 +580,7 @@ } #endif - err = fib6_add_rt2node(fn, rt, nlh); + err = fib6_add_rt2node(fn, rt, nlh, req); if (err == 0) { fib6_start_gc(rt); @@ -888,7 +889,7 @@ } static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, - struct nlmsghdr *nlh) + struct nlmsghdr *nlh, struct netlink_skb_parms *req) { struct fib6_walker_t *w; struct rt6_info *rt = *rtp; @@ -943,11 +944,11 @@ if (atomic_read(&rt->rt6i_ref) != 1) BUG(); } - inet6_rt_notify(RTM_DELROUTE, rt, nlh); + inet6_rt_notify(RTM_DELROUTE, rt, nlh, req); rt6_release(rt); } -int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh) +int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, struct netlink_skb_parms *req) { struct fib6_node *fn = rt->rt6i_node; struct rt6_info **rtp; @@ -972,7 +973,7 @@ for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) { if (*rtp == rt) { - fib6_del_route(fn, rtp, nlh); + fib6_del_route(fn, rtp, nlh, req); return 0; } } @@ -1101,7 +1102,7 @@ res = c->func(rt, c->arg); if (res < 0) { w->leaf = rt; - res = fib6_del(rt, NULL); + res = fib6_del(rt, NULL, NULL); if (res) { #if RT6_DEBUG >= 2 printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res); diff -urN linux-2.4.31/net/ipv6/mcast.c linux-2.4.32/net/ipv6/mcast.c --- linux-2.4.31/net/ipv6/mcast.c 2005-01-19 06:10:14.000000000 -0800 +++ linux-2.4.32/net/ipv6/mcast.c 2005-11-16 11:12:54.677080944 -0800 @@ -1243,15 +1243,6 @@ return 0; skb_reserve(skb, (dev->hard_header_len + 15) & ~15); - if (dev->hard_header) { - unsigned char ha[MAX_ADDR_LEN]; - - ndisc_mc_map(&mld2_all_mcr, ha, dev, 1); - if (dev->hard_header(skb, dev, ETH_P_IPV6,ha,NULL,size) < 0) { - kfree_skb(skb); - return 0; - } - } if (ipv6_get_lladdr(dev, &addr_buf)) { /* : @@ -1275,6 +1266,30 @@ return skb; } +static inline int mld_dev_queue_xmit2(struct sk_buff *skb) +{ + struct net_device *dev = skb->dev; + + if (dev->hard_header) { + unsigned char ha[MAX_ADDR_LEN]; + int err; + + ndisc_mc_map(&skb->nh.ipv6h->daddr, ha, dev, 1); + err = dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len); + if (err < 0) { + kfree_skb(skb); + return err; + } + } + return dev_queue_xmit(skb); +} + +static inline int mld_dev_queue_xmit(struct sk_buff *skb) +{ + return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dev, + mld_dev_queue_xmit2); +} + static void mld_sendpack(struct sk_buff *skb) { struct ipv6hdr *pip6 = skb->nh.ipv6h; @@ -1289,7 +1304,7 @@ pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0)); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, - dev_queue_xmit); + mld_dev_queue_xmit); if (!err) ICMP6_INC_STATS(Icmp6OutMsgs); } @@ -1585,12 +1600,6 @@ return; skb_reserve(skb, (dev->hard_header_len + 15) & ~15); - if (dev->hard_header) { - unsigned char ha[MAX_ADDR_LEN]; - ndisc_mc_map(snd_addr, ha, dev, 1); - if (dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, full_len) < 0) - goto out; - } if (ipv6_get_lladdr(dev, &addr_buf)) { /* : @@ -1616,7 +1625,7 @@ csum_partial((__u8 *) hdr, len, 0)); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, - dev_queue_xmit); + mld_dev_queue_xmit); if (!err) { if (type == ICMPV6_MGM_REDUCTION) ICMP6_INC_STATS(Icmp6OutGroupMembReductions); @@ -1626,9 +1635,6 @@ } return; - -out: - kfree_skb(skb); } static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, @@ -1867,7 +1873,7 @@ } pmc->mca_sources = 0; pmc->mca_sfmode = MCAST_EXCLUDE; - pmc->mca_sfcount[MCAST_EXCLUDE] = 0; + pmc->mca_sfcount[MCAST_INCLUDE] = 0; pmc->mca_sfcount[MCAST_EXCLUDE] = 1; } diff -urN linux-2.4.31/net/ipv6/ndisc.c linux-2.4.32/net/ipv6/ndisc.c --- linux-2.4.31/net/ipv6/ndisc.c 2004-11-17 03:54:22.000000000 -0800 +++ linux-2.4.32/net/ipv6/ndisc.c 2005-11-16 11:12:54.678080988 -0800 @@ -876,7 +876,7 @@ /* It is safe only because we aer in BH */ dst_release(&rt->u.dst); - ip6_del_rt(rt, NULL); + ip6_del_rt(rt, NULL, NULL); } } } else { @@ -962,7 +962,7 @@ rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); if (rt && lifetime == 0) { - ip6_del_rt(rt, NULL); + ip6_del_rt(rt, NULL, NULL); rt = NULL; } diff -urN linux-2.4.31/net/ipv6/netfilter/ip6_queue.c linux-2.4.32/net/ipv6/netfilter/ip6_queue.c --- linux-2.4.31/net/ipv6/netfilter/ip6_queue.c 2004-02-18 05:36:32.000000000 -0800 +++ linux-2.4.32/net/ipv6/netfilter/ip6_queue.c 2005-11-16 11:12:54.678080988 -0800 @@ -68,7 +68,9 @@ static void ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) { + local_bh_disable(); nf_reinject(entry->skb, entry->info, verdict); + local_bh_enable(); kfree(entry); } diff -urN linux-2.4.31/net/ipv6/netfilter/ip6t_LOG.c linux-2.4.32/net/ipv6/netfilter/ip6t_LOG.c --- linux-2.4.31/net/ipv6/netfilter/ip6t_LOG.c 2005-01-19 06:10:14.000000000 -0800 +++ linux-2.4.32/net/ipv6/netfilter/ip6t_LOG.c 2005-11-16 11:12:54.679081033 -0800 @@ -363,7 +363,6 @@ const void *targinfo, void *userinfo) { - struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h; const struct ip6t_log_info *loginfo = targinfo; char level_string[4] = "< >"; @@ -375,41 +374,32 @@ in ? in->name : "", out ? out->name : ""); if (in && !out) { + unsigned int len; /* MAC logging for input chain only. */ printk("MAC="); - if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) { - if ((*pskb)->dev->type != ARPHRD_SIT){ - int i; - unsigned char *p = (*pskb)->mac.raw; - for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++) - printk("%02x%c", *p, - i==(*pskb)->dev->hard_header_len - 1 - ? ' ':':'); - } else { - int i; - unsigned char *p = (*pskb)->mac.raw; - if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){ - p -= (ETH_ALEN+2); - for (i = 0; i < (ETH_ALEN); i++,p++) - printk("%02x%s", *p, - i == ETH_ALEN-1 ? "->" : ":"); - p -= (ETH_ALEN*2); - for (i = 0; i < (ETH_ALEN); i++,p++) - printk("%02x%c", *p, - i == ETH_ALEN-1 ? ' ' : ':'); - } - - if (((*pskb)->dev->addr_len == 4) && - (*pskb)->dev->hard_header_len > 20){ - printk("TUNNEL="); - p = (*pskb)->mac.raw + 12; - for (i = 0; i < 4; i++,p++) - printk("%3d%s", *p, - i == 3 ? "->" : "."); - for (i = 0; i < 4; i++,p++) - printk("%3d%c", *p, - i == 3 ? ' ' : '.'); - } + if ((*pskb)->dev && (len = (*pskb)->dev->hard_header_len) && + (*pskb)->mac.raw != (*pskb)->nh.raw) { + unsigned char *p = (*pskb)->mac.raw; + int i; + + if ((*pskb)->dev->type == ARPHRD_SIT && + (p -= ETH_HLEN) < (*pskb)->head) + p = NULL; + + if (p != NULL) { + for (i = 0; i < len; i++) + printk("%02x%s", p[i], + i == len - 1 ? "" : ":"); + } + printk(" "); + + if ((*pskb)->dev->type == ARPHRD_SIT) { + struct iphdr *iph; + + iph = (struct iphdr *)(*pskb)->mac.raw; + printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ", + NIPQUAD(iph->saddr), + NIPQUAD(iph->daddr)); } } else printk(" "); diff -urN linux-2.4.31/net/ipv6/route.c linux-2.4.32/net/ipv6/route.c --- linux-2.4.31/net/ipv6/route.c 2004-11-17 03:54:22.000000000 -0800 +++ linux-2.4.32/net/ipv6/route.c 2005-11-16 11:12:54.681081122 -0800 @@ -325,12 +325,12 @@ be destroyed. */ -static int rt6_ins(struct rt6_info *rt, struct nlmsghdr *nlh) +static int rt6_ins(struct rt6_info *rt, struct nlmsghdr *nlh, struct netlink_skb_parms *req) { int err; write_lock_bh(&rt6_lock); - err = fib6_add(&ip6_routing_table, rt, nlh); + err = fib6_add(&ip6_routing_table, rt, nlh, req); write_unlock_bh(&rt6_lock); return err; @@ -341,7 +341,7 @@ */ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr, - struct in6_addr *saddr) + struct in6_addr *saddr, struct netlink_skb_parms *req) { int err; struct rt6_info *rt; @@ -373,7 +373,7 @@ dst_hold(&rt->u.dst); - err = rt6_ins(rt, NULL); + err = rt6_ins(rt, NULL, req); if (err == 0) return rt; @@ -479,7 +479,8 @@ read_unlock_bh(&rt6_lock); rt = rt6_cow(rt, &skb->nh.ipv6h->daddr, - &skb->nh.ipv6h->saddr); + &skb->nh.ipv6h->saddr, + &NETLINK_CB(skb)); if (rt->u.dst.error != -EEXIST || --attempts <= 0) goto out2; @@ -558,7 +559,7 @@ read_unlock_bh(&rt6_lock); rt = rt6_cow(rt, fl->nl_u.ip6_u.daddr, - fl->nl_u.ip6_u.saddr); + fl->nl_u.ip6_u.saddr, NULL); if (rt->u.dst.error != -EEXIST || --attempts <= 0) goto out2; @@ -619,7 +620,7 @@ if (rt) { if (rt->rt6i_flags & RTF_CACHE) - ip6_del_rt(rt, NULL); + ip6_del_rt(rt, NULL, NULL); else dst_release(dst); } @@ -712,7 +713,7 @@ * */ -int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh) +int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, struct netlink_skb_parms *req) { int err; struct rtmsg *r; @@ -865,7 +866,7 @@ if (rt->u.dst.advmss > 65535-20) rt->u.dst.advmss = 65535; rt->u.dst.dev = dev; - return rt6_ins(rt, nlh); + return rt6_ins(rt, nlh, req); out: if (dev) @@ -874,7 +875,7 @@ return err; } -int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh) +int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, struct netlink_skb_parms *req) { int err; @@ -886,13 +887,13 @@ dst_release(&rt->u.dst); - err = fib6_del(rt, nlh); + err = fib6_del(rt, nlh, req); write_unlock_bh(&rt6_lock); return err; } -int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh) +int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, struct netlink_skb_parms *req) { struct fib6_node *fn; struct rt6_info *rt; @@ -919,7 +920,7 @@ dst_hold(&rt->u.dst); read_unlock_bh(&rt6_lock); - return ip6_del_rt(rt, nlh); + return ip6_del_rt(rt, nlh, req); } } read_unlock_bh(&rt6_lock); @@ -1021,11 +1022,11 @@ rt->u.dst.advmss = 65535; nrt->rt6i_hoplimit = ipv6_get_hoplimit(neigh->dev); - if (rt6_ins(nrt, NULL)) + if (rt6_ins(nrt, NULL, NULL)) goto out; if (rt->rt6i_flags&RTF_CACHE) { - ip6_del_rt(rt, NULL); + ip6_del_rt(rt, NULL, NULL); return; } @@ -1087,7 +1088,7 @@ 2. It is gatewayed route or NONEXTHOP route. Action: clone it. */ if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { - nrt = rt6_cow(rt, daddr, saddr); + nrt = rt6_cow(rt, daddr, saddr, NULL); if (!nrt->u.dst.error) { nrt->u.dst.pmtu = pmtu; /* According to RFC 1981, detecting PMTU increase shouldn't be @@ -1111,7 +1112,7 @@ dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires); nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES; nrt->u.dst.pmtu = pmtu; - rt6_ins(nrt, NULL); + rt6_ins(nrt, NULL, NULL); } out: @@ -1184,7 +1185,7 @@ rtmsg.rtmsg_ifindex = dev->ifindex; - ip6_route_add(&rtmsg, NULL); + ip6_route_add(&rtmsg, NULL, NULL); return rt6_get_dflt_router(gwaddr, dev); } @@ -1210,7 +1211,7 @@ read_unlock_bh(&rt6_lock); - ip6_del_rt(rt, NULL); + ip6_del_rt(rt, NULL, NULL); goto restart; } @@ -1236,10 +1237,10 @@ rtnl_lock(); switch (cmd) { case SIOCADDRT: - err = ip6_route_add(&rtmsg, NULL); + err = ip6_route_add(&rtmsg, NULL, NULL); break; case SIOCDELRT: - err = ip6_route_del(&rtmsg, NULL); + err = ip6_route_del(&rtmsg, NULL, NULL); break; default: err = -EINVAL; @@ -1296,7 +1297,7 @@ ipv6_addr_copy(&rt->rt6i_dst.addr, addr); rt->rt6i_dst.plen = 128; - rt6_ins(rt, NULL); + rt6_ins(rt, NULL, NULL); return 0; } @@ -1313,7 +1314,7 @@ rt = rt6_lookup(addr, NULL, loopback_dev.ifindex, 1); if (rt) { if (rt->rt6i_dst.plen == 128) - err = ip6_del_rt(rt, NULL); + err = ip6_del_rt(rt, NULL, NULL); else dst_release(&rt->u.dst); } @@ -1429,7 +1430,7 @@ nrt->rt6i_flags |= RTF_CACHE; dst_hold(&nrt->u.dst); - err = rt6_ins(nrt, NULL); + err = rt6_ins(nrt, NULL, NULL); if (err) nrt->u.dst.error = err; return nrt; @@ -1556,7 +1557,7 @@ if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) return -EINVAL; - return ip6_route_del(&rtmsg, nlh); + return ip6_route_del(&rtmsg, nlh, &NETLINK_CB(skb)); } int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) @@ -1566,7 +1567,7 @@ if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) return -EINVAL; - return ip6_route_add(&rtmsg, nlh); + return ip6_route_add(&rtmsg, nlh, &NETLINK_CB(skb)); } struct rt6_rtnl_dump_arg @@ -1576,11 +1577,8 @@ }; static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, - struct in6_addr *dst, - struct in6_addr *src, - int iif, - int type, u32 pid, u32 seq, - struct nlmsghdr *in_nlh, int prefix) + struct in6_addr *dst, struct in6_addr *src, + int iif, int type, u32 pid, u32 seq, int prefix) { struct rtmsg *rtm; struct nlmsghdr *nlh; @@ -1593,9 +1591,6 @@ return 1; } } - if (!pid && in_nlh) { - pid = in_nlh->nlmsg_pid; - } nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*rtm)); rtm = NLMSG_DATA(nlh); @@ -1683,7 +1678,7 @@ return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, - NULL, prefix); + prefix); } static int fib6_dump_node(struct fib6_walker_t *w) @@ -1834,7 +1829,7 @@ fl.nl_u.ip6_u.saddr, iif, RTM_NEWROUTE, NETLINK_CB(in_skb).pid, - nlh->nlmsg_seq, nlh, 0); + nlh->nlmsg_seq, 0); if (err < 0) { err = -EMSGSIZE; goto out_free; @@ -1850,17 +1845,25 @@ goto out; } -void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh) +void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh, + struct netlink_skb_parms *req) { struct sk_buff *skb; int size = NLMSG_SPACE(sizeof(struct rtmsg)+256); + u32 pid = current->pid; + u32 seq = 0; + + if (req) + pid = req->pid; + if (nlh) + seq = nlh->nlmsg_seq; skb = alloc_skb(size, gfp_any()); if (!skb) { netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS); return; } - if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh, 0) < 0) { + if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0) < 0) { kfree_skb(skb); netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL); return; diff -urN linux-2.4.31/net/ipv6/udp.c linux-2.4.32/net/ipv6/udp.c --- linux-2.4.31/net/ipv6/udp.c 2004-11-17 03:54:22.000000000 -0800 +++ linux-2.4.32/net/ipv6/udp.c 2005-11-16 11:12:54.681081122 -0800 @@ -89,7 +89,7 @@ next:; } result = best; - for(;; result += UDP_HTABLE_SIZE) { + for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) { if (result > sysctl_local_port_range[1]) result = sysctl_local_port_range[0] + ((result - sysctl_local_port_range[0]) & @@ -97,6 +97,8 @@ if (!udp_lport_inuse(result)) break; } + if (i >= (1 << 16) / UDP_HTABLE_SIZE) + goto fail; gotit: udp_port_rover = snum = result; } else { diff -urN linux-2.4.31/net/netlink/af_netlink.c linux-2.4.32/net/netlink/af_netlink.c --- linux-2.4.31/net/netlink/af_netlink.c 2005-05-31 17:56:56.000000000 -0700 +++ linux-2.4.32/net/netlink/af_netlink.c 2005-11-16 11:12:54.682081166 -0800 @@ -330,9 +330,9 @@ u32 pid = nlk_sk(sk)->pid; netlink_table_grab(); - hash->entries--; for (skp = nl_pid_hashfn(hash, pid); *skp; skp = &((*skp)->next)) { if (*skp == sk) { + hash->entries--; *skp = sk->next; __sock_put(sk); break; @@ -450,7 +450,12 @@ err = netlink_insert(sk, pid); if (err == -EADDRINUSE) goto retry; - return 0; + + /* If 2 threads race to autobind, that is fine. */ + if (err == -EBUSY) + err = 0; + + return err; } static inline int netlink_capable(struct socket *sock, unsigned int flag)