diff --git a/debian/changelog b/debian/changelog index 845c7007f..238999025 100644 --- a/debian/changelog +++ b/debian/changelog @@ -192,6 +192,45 @@ linux-2.6 (2.6.20-1~experimental.1) UNRELEASED; urgency=low - nfs: nfs_getattr() can't call nfs_sync_mapping_range() for non-regular files - dio: invalidate clean pages before dio write - initialise pi_lock if CONFIG_RT_MUTEXES=N + * Add stable release 2.6.20.5: + - FRA_{DST,SRC} are le16 for decnet + - CIFS: reset mode when client notices that ATTR_READONLY is no longer set + - ide: clear bmdma status in ide_intr() for ICHx controllers (revised #4) + - ide: remove clearing bmdma status from cdrom_decode_status() (rev #4) + - NET: Fix sock_attach_fd() failure in sys_accept() + - DCCP: Fix exploitable hole in DCCP socket options + - ide: revert "ide: fix drive side 80c cable check, take 2" for now + - generic_serial: fix decoding of baud rate + - IPV6: Fix ipv6 round-robin locking. + - VIDEO: Fix FFB DAC revision probing + - PPP: Fix PPP skb leak + - V4L: msp_attach must return 0 if no msp3400 was found. + - CRYPTO: api: scatterwalk_copychunks() fails to advance through scatterlist + - APPLETALK: Fix a remotely triggerable crash + - UML - fix epoll + - UML - host VDSO fix + - UML - Fix static linking + - UML - use correct register file size everywhere + - libata: sata_mv: don't touch reserved bits in EDMA config register + - libata: sata_mv: Fix 50xx irq mask + - libata bugfix: HDIO_DRIVE_TASK + - V4L: Fix SECAM handling on saa7115 + - DVB: fix nxt200x rf input switching + - SPARC: Fix sparc builds with gcc-4.2.x + - V4L: saa7146: Fix allocation of clipping memory + - uml: fix unreasonably long udelay + - NET: Fix packet classidier NULL pointer OOPS + - NET_SCHED: Fix ingress qdisc locking. + - sata_nv: delay on switching between NCQ and non-NCQ commands + - dvb-core: fix several locking related problems + - ieee1394: dv1394: fix CardBus card ejection + - CIFS: Allow reset of file to ATTR_NORMAL when archive bit not set + - jmicron: make ide jmicron driver play nice with libata ones + - libata: clear TF before IDENTIFYing + - NET: Fix FIB rules compatability + - DVB: isl6421: don't reference freed memory + - V4L: radio: Fix error in Kbuild file + - i2o: block IO errors on i2o disk [ Gordon Farquharson ] * Disable broken config options on ARM. @@ -207,7 +246,7 @@ linux-2.6 (2.6.20-1~experimental.1) UNRELEASED; urgency=low * Allow '.' and '+' in the target dist field of the changelog. dpkg has supported this since 1.13.20, see #361171. - -- dann frazier Tue, 03 Apr 2007 15:10:04 -0600 + -- maximilian attems Fri, 6 Apr 2007 21:17:20 +0200 linux-2.6 (2.6.18.dfsg.1-10) unstable; urgency=low diff --git a/debian/patches/bugfix/2.6.20.5 b/debian/patches/bugfix/2.6.20.5 new file mode 100644 index 000000000..a584f9f83 --- /dev/null +++ b/debian/patches/bugfix/2.6.20.5 @@ -0,0 +1,1838 @@ +diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h +index 66cb400..62403bd 100644 +--- a/arch/um/include/sysdep-x86_64/ptrace.h ++++ b/arch/um/include/sysdep-x86_64/ptrace.h +@@ -104,10 +104,6 @@ union uml_pt_regs { + #endif + #ifdef UML_CONFIG_MODE_SKAS + struct skas_regs { +- /* x86_64 ptrace uses sizeof(user_regs_struct) as its register +- * file size, while i386 uses FRAME_SIZE. Therefore, we need +- * to use UM_FRAME_SIZE here instead of HOST_FRAME_SIZE. +- */ + unsigned long regs[MAX_REG_NR]; + unsigned long fp[HOST_FP_SIZE]; + struct faultinfo faultinfo; +diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c +index 5a99dd3..13c6cb5 100644 +--- a/arch/um/os-Linux/elf_aux.c ++++ b/arch/um/os-Linux/elf_aux.c +@@ -40,6 +40,9 @@ __init void scan_elf_aux( char **envp) + switch ( auxv->a_type ) { + case AT_SYSINFO: + __kernel_vsyscall = auxv->a_un.a_val; ++ /* See if the page is under TASK_SIZE */ ++ if (__kernel_vsyscall < (unsigned long) envp) ++ __kernel_vsyscall = 0; + break; + case AT_SYSINFO_EHDR: + vsyscall_ehdr = auxv->a_un.a_val; +diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c +index b3c11cf..9383e87 100644 +--- a/arch/um/os-Linux/skas/mem.c ++++ b/arch/um/os-Linux/skas/mem.c +@@ -48,7 +48,7 @@ int multi_op_count = 0; + static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) + { + unsigned long regs[MAX_REG_NR]; +- int n; ++ int n, i; + long ret, offset; + unsigned long * data; + unsigned long * syscall; +@@ -66,9 +66,13 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) + (unsigned long) &__syscall_stub_start); + + n = ptrace_setregs(pid, regs); +- if(n < 0) ++ if(n < 0){ ++ printk("Registers - \n"); ++ for(i = 0; i < MAX_REG_NR; i++) ++ printk("\t%d\t0x%lx\n", i, regs[i]); + panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", +- n); ++ -n); ++ } + + wait_stub_done(pid, 0, "do_syscall_stub"); + +diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c +index 9b34fe6..c4998cf 100644 +--- a/arch/um/os-Linux/skas/process.c ++++ b/arch/um/os-Linux/skas/process.c +@@ -67,7 +67,7 @@ void wait_stub_done(int pid, int sig, char * fname) + + if((n < 0) || !WIFSTOPPED(status) || + (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ +- unsigned long regs[HOST_FRAME_SIZE]; ++ unsigned long regs[MAX_REG_NR]; + + if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + printk("Failed to get registers from stub, " +@@ -76,7 +76,7 @@ void wait_stub_done(int pid, int sig, char * fname) + int i; + + printk("Stub registers -\n"); +- for(i = 0; i < HOST_FRAME_SIZE; i++) ++ for(i = 0; i < ARRAY_SIZE(regs); i++) + printk("\t%d - %lx\n", i, regs[i]); + } + panic("%s : failed to wait for SIGUSR1/SIGTRAP, " +@@ -328,7 +328,7 @@ void userspace(union uml_pt_regs *regs) + int copy_context_skas0(unsigned long new_stack, int pid) + { + int err; +- unsigned long regs[HOST_FRAME_SIZE]; ++ unsigned long regs[MAX_REG_NR]; + unsigned long fp_regs[HOST_FP_SIZE]; + unsigned long current_stack = current_stub_stack(); + struct stub_data *data = (struct stub_data *) current_stack; +diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c +index 7cd0369..ecd21e0 100644 +--- a/arch/um/os-Linux/sys-i386/registers.c ++++ b/arch/um/os-Linux/sys-i386/registers.c +@@ -15,7 +15,7 @@ + + /* These are set once at boot time and not changed thereafter */ + +-static unsigned long exec_regs[HOST_FRAME_SIZE]; ++static unsigned long exec_regs[MAX_REG_NR]; + static unsigned long exec_fp_regs[HOST_FP_SIZE]; + static unsigned long exec_fpx_regs[HOST_XFP_SIZE]; + static int have_fpx_regs = 1; +@@ -101,6 +101,7 @@ void init_registers(int pid) + { + int err; + ++ memset(exec_regs, 0, sizeof(exec_regs)); + err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); + if(err) + panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", +@@ -124,7 +125,7 @@ void init_registers(int pid) + + void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) + { +- memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); ++ memcpy(regs, exec_regs, sizeof(exec_regs)); + if(fp_regs != NULL) + memcpy(fp_regs, exec_fp_regs, + HOST_FP_SIZE * sizeof(unsigned long)); +diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c +index cb8e8a2..019f6c4 100644 +--- a/arch/um/os-Linux/sys-x86_64/registers.c ++++ b/arch/um/os-Linux/sys-x86_64/registers.c +@@ -14,7 +14,7 @@ + + /* These are set once at boot time and not changed thereafter */ + +-static unsigned long exec_regs[HOST_FRAME_SIZE]; ++static unsigned long exec_regs[MAX_REG_NR]; + static unsigned long exec_fp_regs[HOST_FP_SIZE]; + + void init_thread_registers(union uml_pt_regs *to) +@@ -72,7 +72,7 @@ void init_registers(int pid) + + void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) + { +- memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); ++ memcpy(regs, exec_regs, sizeof(exec_regs)); + if(fp_regs != NULL) + memcpy(fp_regs, exec_fp_regs, + HOST_FP_SIZE * sizeof(unsigned long)); +diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c +index 2c11b97..d623e07 100644 +--- a/arch/um/sys-i386/delay.c ++++ b/arch/um/sys-i386/delay.c +@@ -27,14 +27,3 @@ void __udelay(unsigned long usecs) + } + + EXPORT_SYMBOL(__udelay); +- +-void __const_udelay(unsigned long usecs) +-{ +- int i, n; +- +- n = (loops_per_jiffy * HZ * usecs) / MILLION; +- for(i=0;iap->private_data; + void __iomem *mmio = nv_adma_ctl_block(qc->ap); ++ int curr_ncq = (qc->tf.protocol == ATA_PROT_NCQ); + + VPRINTK("ENTER\n"); + +@@ -1166,6 +1168,14 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) + /* write append register, command tag in lower 8 bits + and (number of cpbs to append -1) in top 8 bits */ + wmb(); ++ ++ if(curr_ncq != pp->last_issue_ncq) { ++ /* Seems to need some delay before switching between NCQ and non-NCQ ++ commands, else we get command timeouts and such. */ ++ udelay(20); ++ pp->last_issue_ncq = curr_ncq; ++ } ++ + writew(qc->tag, mmio + NV_ADMA_APPEND); + + DPRINTK("Issued tag %u\n",qc->tag); +diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c +index e769811..e2a0b6f 100644 +--- a/drivers/char/generic_serial.c ++++ b/drivers/char/generic_serial.c +@@ -711,12 +711,6 @@ void gs_close(struct tty_struct * tty, struct file * filp) + } + + +-static unsigned int gs_baudrates[] = { +- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, +- 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 +-}; +- +- + void gs_set_termios (struct tty_struct * tty, + struct ktermios * old_termios) + { +@@ -772,7 +766,6 @@ void gs_set_termios (struct tty_struct * tty, + + baudrate = tty_get_baud_rate(tty); + +- baudrate = gs_baudrates[baudrate]; + if ((tiosp->c_cflag & CBAUD) == B38400) { + if ( (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + baudrate = 57600; +diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c +index 5969cec..a2bde80 100644 +--- a/drivers/ide/ide-cd.c ++++ b/drivers/ide/ide-cd.c +@@ -687,15 +687,8 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 sta + static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) + { + struct request *rq = HWGROUP(drive)->rq; +- ide_hwif_t *hwif = HWIF(drive); + int stat, err, sense_key; + +- /* We may have bogus DMA interrupts in PIO state here */ +- if (HWIF(drive)->dma_status && hwif->atapi_irq_bogon) { +- stat = hwif->INB(hwif->dma_status); +- /* Should we force the bit as well ? */ +- hwif->OUTB(stat, hwif->dma_status); +- } + /* Check for errors. */ + stat = HWIF(drive)->INB(IDE_STATUS_REG); + if (stat_ret) +@@ -930,6 +923,10 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, + HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); + + if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { ++ /* waiting for CDB interrupt, not DMA yet. */ ++ if (info->dma) ++ drive->waiting_for_dma = 0; ++ + /* packet command */ + ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry); + return ide_started; +@@ -972,6 +969,10 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, + /* Check for errors. */ + if (cdrom_decode_status(drive, DRQ_STAT, NULL)) + return ide_stopped; ++ ++ /* Ok, next interrupt will be DMA interrupt. */ ++ if (info->dma) ++ drive->waiting_for_dma = 1; + } else { + /* Otherwise, we must wait for DRQ to get set. */ + if (ide_wait_stat(&startstop, drive, DRQ_STAT, +diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c +index 2614f41..99d1c43 100644 +--- a/drivers/ide/ide-io.c ++++ b/drivers/ide/ide-io.c +@@ -1646,6 +1646,17 @@ irqreturn_t ide_intr (int irq, void *dev_id) + del_timer(&hwgroup->timer); + spin_unlock(&ide_lock); + ++ /* Some controllers might set DMA INTR no matter DMA or PIO; ++ * bmdma status might need to be cleared even for ++ * PIO interrupts to prevent spurious/lost irq. ++ */ ++ if (hwif->ide_dma_clear_irq && !(drive->waiting_for_dma)) ++ /* ide_dma_end() needs bmdma status for error checking. ++ * So, skip clearing bmdma status here and leave it ++ * to ide_dma_end() if this is dma interrupt. ++ */ ++ hwif->ide_dma_clear_irq(drive); ++ + if (drive->unmask) + local_irq_enable_in_hardirq(); + /* service this interrupt, may set handler for next interrupt */ +diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c +index 6558055..59b10a0 100644 +--- a/drivers/ide/ide-iops.c ++++ b/drivers/ide/ide-iops.c +@@ -598,6 +598,9 @@ u8 eighty_ninty_three (ide_drive_t *drive) + if(HWIF(drive)->udma_four == 0) + return 0; + ++ printk(KERN_INFO "%s: hw_config=%04x\n", ++ drive->name, drive->id->hw_config); ++ + /* Check for SATA but only if we are ATA5 or higher */ + if (drive->id->hw_config == 0 && (drive->id->major_rev_num & 0x7FE0)) + return 1; +@@ -607,8 +610,14 @@ u8 eighty_ninty_three (ide_drive_t *drive) + if(!(drive->id->hw_config & 0x4000)) + return 0; + #endif /* CONFIG_IDEDMA_IVB */ ++/* ++ * FIXME: enable this after fixing master/slave IDENTIFY order, ++ * also ignore the result if the slave device is pre-ATA3 one ++ */ ++#if 0 + if (!(drive->id->hw_config & 0x2000)) + return 0; ++#endif + return 1; + } + +diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c +index 6c9bd51..8e73fe5 100644 +--- a/drivers/ide/ide.c ++++ b/drivers/ide/ide.c +@@ -503,6 +503,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) + hwif->ide_dma_on = tmp_hwif->ide_dma_on; + hwif->ide_dma_off_quietly = tmp_hwif->ide_dma_off_quietly; + hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq; ++ hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq; + hwif->ide_dma_host_on = tmp_hwif->ide_dma_host_on; + hwif->ide_dma_host_off = tmp_hwif->ide_dma_host_off; + hwif->ide_dma_lostirq = tmp_hwif->ide_dma_lostirq; +diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c +index f07bbbe..84fb87b 100644 +--- a/drivers/ide/pci/jmicron.c ++++ b/drivers/ide/pci/jmicron.c +@@ -240,12 +240,31 @@ static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_devi + return 0; + } + ++/* If libata is configured, jmicron PCI quirk will configure it such ++ * that the SATA ports are in AHCI function while the PATA ports are ++ * in a separate IDE function. In such cases, match device class and ++ * attach only to IDE. If libata isn't configured, keep the old ++ * behavior for backward compatibility. ++ */ ++#if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE) ++#define JMB_CLASS PCI_CLASS_STORAGE_IDE << 8 ++#define JMB_CLASS_MASK 0xffff00 ++#else ++#define JMB_CLASS 0 ++#define JMB_CLASS_MASK 0 ++#endif ++ + static struct pci_device_id jmicron_pci_tbl[] = { +- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, +- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, +- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, +- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, ++ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, ++ PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 0}, ++ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, ++ PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 1}, ++ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, ++ PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 2}, ++ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, ++ PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 3}, ++ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, ++ PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 4}, + { 0, }, + }; + +diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c +index edb37f3..c5ec6f1 100644 +--- a/drivers/ide/pci/piix.c ++++ b/drivers/ide/pci/piix.c +@@ -411,17 +411,14 @@ fast_ata_pio: + } + + /** +- * init_chipset_piix - set up the PIIX chipset +- * @dev: PCI device to set up +- * @name: Name of the device ++ * piix_is_ichx - check if ICHx ++ * @dev: PCI device to check + * +- * Initialize the PCI device as required. For the PIIX this turns +- * out to be nice and simple ++ * returns 1 if ICHx, 0 otherwise. + */ +- +-static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name) ++static int piix_is_ichx(struct pci_dev *dev) + { +- switch(dev->device) { ++ switch (dev->device) { + case PCI_DEVICE_ID_INTEL_82801EB_1: + case PCI_DEVICE_ID_INTEL_82801AA_1: + case PCI_DEVICE_ID_INTEL_82801AB_1: +@@ -439,19 +436,51 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char + case PCI_DEVICE_ID_INTEL_ICH7_21: + case PCI_DEVICE_ID_INTEL_ESB2_18: + case PCI_DEVICE_ID_INTEL_ICH8_6: +- { +- unsigned int extra = 0; +- pci_read_config_dword(dev, 0x54, &extra); +- pci_write_config_dword(dev, 0x54, extra|0x400); +- } +- default: +- break; ++ return 1; + } + + return 0; + } + + /** ++ * init_chipset_piix - set up the PIIX chipset ++ * @dev: PCI device to set up ++ * @name: Name of the device ++ * ++ * Initialize the PCI device as required. For the PIIX this turns ++ * out to be nice and simple ++ */ ++ ++static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name) ++{ ++ if (piix_is_ichx(dev)) { ++ unsigned int extra = 0; ++ pci_read_config_dword(dev, 0x54, &extra); ++ pci_write_config_dword(dev, 0x54, extra|0x400); ++ } ++ ++ return 0; ++} ++ ++/** ++ * piix_dma_clear_irq - clear BMDMA status ++ * @drive: IDE drive to clear ++ * ++ * Called from ide_intr() for PIO interrupts ++ * to clear BMDMA status as needed by ICHx ++ */ ++static void piix_dma_clear_irq(ide_drive_t *drive) ++{ ++ ide_hwif_t *hwif = HWIF(drive); ++ u8 dma_stat; ++ ++ /* clear the INTR & ERROR bits */ ++ dma_stat = hwif->INB(hwif->dma_status); ++ /* Should we force the bit as well ? */ ++ hwif->OUTB(dma_stat, hwif->dma_status); ++} ++ ++/** + * init_hwif_piix - fill in the hwif for the PIIX + * @hwif: IDE interface + * +@@ -473,10 +502,6 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) + /* This is a painful system best to let it self tune for now */ + return; + } +- /* ESB2 appears to generate spurious DMA interrupts in PIO mode +- when in native mode */ +- if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18) +- hwif->atapi_irq_bogon = 1; + + hwif->autodma = 0; + hwif->tuneproc = &piix_tune_drive; +@@ -487,6 +512,10 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) + if (!hwif->dma_base) + return; + ++ /* ICHx need to clear the bmdma status for all interrupts */ ++ if (piix_is_ichx(hwif->pci_dev)) ++ hwif->ide_dma_clear_irq = &piix_dma_clear_irq; ++ + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x3f; + hwif->mwdma_mask = 0x06; +diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c +index 1084da4..59e383c 100644 +--- a/drivers/ieee1394/dv1394.c ++++ b/drivers/ieee1394/dv1394.c +@@ -2267,11 +2267,7 @@ static void dv1394_remove_host (struct hpsb_host *host) + { + struct video_card *video; + unsigned long flags; +- int id = host->id; +- +- /* We only work with the OHCI-1394 driver */ +- if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) +- return; ++ int id = host->id, found_ohci_card = 0; + + /* find the corresponding video_cards */ + do { +@@ -2284,6 +2280,7 @@ static void dv1394_remove_host (struct hpsb_host *host) + if ((tmp_vid->id >> 2) == id) { + list_del(&tmp_vid->list); + video = tmp_vid; ++ found_ohci_card = 1; + break; + } + } +@@ -2293,8 +2290,9 @@ static void dv1394_remove_host (struct hpsb_host *host) + dv1394_un_init(video); + } while (video != NULL); + +- class_device_destroy(hpsb_protocol_class, +- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2))); ++ if (found_ohci_card) ++ class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR, ++ IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id << 2))); + } + + static void dv1394_add_host (struct hpsb_host *host) +diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c +index 988499d..ec473eb 100644 +--- a/drivers/media/dvb/dvb-core/dmxdev.c ++++ b/drivers/media/dvb/dvb-core/dmxdev.c +@@ -181,8 +181,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) + struct dvb_device *dvbdev = file->private_data; + struct dmxdev *dmxdev = dvbdev->priv; + +- if (mutex_lock_interruptible(&dmxdev->mutex)) +- return -ERESTARTSYS; ++ mutex_lock(&dmxdev->mutex); + + if ((file->f_flags & O_ACCMODE) == O_WRONLY) { + dmxdev->demux->disconnect_frontend(dmxdev->demux); +@@ -674,13 +673,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file) + static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, + struct dmxdev_filter *dmxdevfilter) + { +- if (mutex_lock_interruptible(&dmxdev->mutex)) +- return -ERESTARTSYS; +- +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { +- mutex_unlock(&dmxdev->mutex); +- return -ERESTARTSYS; +- } ++ mutex_lock(&dmxdev->mutex); ++ mutex_lock(&dmxdevfilter->mutex); + + dvb_dmxdev_filter_stop(dmxdevfilter); + dvb_dmxdev_filter_reset(dmxdevfilter); +diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c +index fcff5ea..6d8d1c3 100644 +--- a/drivers/media/dvb/dvb-core/dvb_demux.c ++++ b/drivers/media/dvb/dvb-core/dvb_demux.c +@@ -673,8 +673,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) + struct dvb_demux *demux = feed->demux; + int ret; + +- if (mutex_lock_interruptible(&demux->mutex)) +- return -ERESTARTSYS; ++ mutex_lock(&demux->mutex); + + if (feed->state < DMX_STATE_GO) { + mutex_unlock(&demux->mutex); +@@ -748,8 +747,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, + struct dvb_demux *demux = (struct dvb_demux *)dmx; + struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; + +- if (mutex_lock_interruptible(&demux->mutex)) +- return -ERESTARTSYS; ++ mutex_lock(&demux->mutex); + + if (feed->state == DMX_STATE_FREE) { + mutex_unlock(&demux->mutex); +@@ -916,8 +914,7 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + int ret; + +- if (mutex_lock_interruptible(&dvbdmx->mutex)) +- return -ERESTARTSYS; ++ mutex_lock(&dvbdmx->mutex); + + if (!dvbdmx->stop_feed) { + mutex_unlock(&dvbdmx->mutex); +@@ -942,8 +939,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, + struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + +- if (mutex_lock_interruptible(&dvbdmx->mutex)) +- return -ERESTARTSYS; ++ mutex_lock(&dvbdmx->mutex); + + if (dvbdmxfilter->feed != dvbdmxfeed) { + mutex_unlock(&dvbdmx->mutex); +@@ -1016,8 +1012,7 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux, + struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; + struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; + +- if (mutex_lock_interruptible(&dvbdmx->mutex)) +- return -ERESTARTSYS; ++ mutex_lock(&dvbdmx->mutex); + + if (dvbdmxfeed->state == DMX_STATE_FREE) { + mutex_unlock(&dvbdmx->mutex); +@@ -1126,8 +1121,7 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux, + if (demux->frontend) + return -EINVAL; + +- if (mutex_lock_interruptible(&dvbdemux->mutex)) +- return -ERESTARTSYS; ++ mutex_lock(&dvbdemux->mutex); + + demux->frontend = frontend; + mutex_unlock(&dvbdemux->mutex); +@@ -1138,8 +1132,7 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux) + { + struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; + +- if (mutex_lock_interruptible(&dvbdemux->mutex)) +- return -ERESTARTSYS; ++ mutex_lock(&dvbdemux->mutex); + + demux->frontend = NULL; + mutex_unlock(&dvbdemux->mutex); +diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c +index af35f30..b3a8cbb 100644 +--- a/drivers/media/dvb/dvb-core/dvbdev.c ++++ b/drivers/media/dvb/dvb-core/dvbdev.c +@@ -204,8 +204,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + + int id; + +- if (mutex_lock_interruptible(&dvbdev_register_lock)) +- return -ERESTARTSYS; ++ mutex_lock(&dvbdev_register_lock); + + if ((id = dvbdev_get_free_id (adap, type)) < 0) { + mutex_unlock(&dvbdev_register_lock); +@@ -295,8 +294,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu + { + int num; + +- if (mutex_lock_interruptible(&dvbdev_register_lock)) +- return -ERESTARTSYS; ++ mutex_lock(&dvbdev_register_lock); + + if ((num = dvbdev_get_free_adapter_num ()) < 0) { + mutex_unlock(&dvbdev_register_lock); +@@ -324,8 +322,7 @@ EXPORT_SYMBOL(dvb_register_adapter); + + int dvb_unregister_adapter(struct dvb_adapter *adap) + { +- if (mutex_lock_interruptible(&dvbdev_register_lock)) +- return -ERESTARTSYS; ++ mutex_lock(&dvbdev_register_lock); + list_del (&adap->list_head); + mutex_unlock(&dvbdev_register_lock); + return 0; +diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c +index ef31936..c967148 100644 +--- a/drivers/media/dvb/frontends/isl6421.c ++++ b/drivers/media/dvb/frontends/isl6421.c +@@ -122,6 +122,7 @@ struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter + /* detect if it is present or not */ + if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) { + kfree(isl6421); ++ fe->sec_priv = NULL; + return NULL; + } + +diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c +index 87c286e..b809f83 100644 +--- a/drivers/media/dvb/frontends/nxt200x.c ++++ b/drivers/media/dvb/frontends/nxt200x.c +@@ -562,7 +562,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, + + /* set input */ + if (state->config->set_pll_input) +- state->config->set_pll_input(buf, 1); ++ state->config->set_pll_input(buf+1, 1); + break; + case VSB_8: + /* Set non-punctured clock for VSB */ +@@ -571,7 +571,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, + + /* set input */ + if (state->config->set_pll_input) +- state->config->set_pll_input(buf, 0); ++ state->config->set_pll_input(buf+1, 0); + break; + default: + return -EINVAL; +diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig +index 920b63f..af66a5d 100644 +--- a/drivers/media/radio/Kconfig ++++ b/drivers/media/radio/Kconfig +@@ -3,7 +3,7 @@ + # + + menu "Radio Adapters" +- depends on VIDEO_DEV!=n ++ depends on VIDEO_DEV + + config RADIO_CADET + tristate "ADS Cadet AM/FM Tuner" +diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c +index 2fb9fe6..91078c0 100644 +--- a/drivers/media/video/msp3400-driver.c ++++ b/drivers/media/video/msp3400-driver.c +@@ -825,7 +825,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) + if (msp_reset(client) == -1) { + v4l_dbg(1, msp_debug, client, "msp3400 not found\n"); + kfree(client); +- return -1; ++ return 0; + } + + state = kmalloc(sizeof(*state), GFP_KERNEL); +@@ -859,7 +859,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) + v4l_dbg(1, msp_debug, client, "not an msp3400 (cannot read chip version)\n"); + kfree(state); + kfree(client); +- return -1; ++ return 0; + } + + msp_set_audio(client); +diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c +index c2374ed..7e494c5 100644 +--- a/drivers/media/video/saa7115.c ++++ b/drivers/media/video/saa7115.c +@@ -960,7 +960,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) + reg |= 0x10; + } else if (std == V4L2_STD_NTSC_M_JP) { + reg |= 0x40; +- } else if (std == V4L2_STD_SECAM) { ++ } else if (std & V4L2_STD_SECAM) { + reg |= 0x50; + } + saa711x_write(client, R_0E_CHROMA_CNTL_1, reg); +diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c +index da9859f..b17c4b2 100644 +--- a/drivers/message/i2o/i2o_block.c ++++ b/drivers/message/i2o/i2o_block.c +@@ -390,13 +390,6 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) + return BLKPREP_KILL; + } + +- /* request is already processed by us, so return */ +- if (blk_special_request(req)) { +- osm_debug("REQ_SPECIAL already set!\n"); +- req->cmd_flags |= REQ_DONTPREP; +- return BLKPREP_OK; +- } +- + /* connect the i2o_block_request to the request */ + if (!req->special) { + ireq = i2o_block_request_alloc(); +@@ -408,11 +401,8 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) + ireq->i2o_blk_dev = i2o_blk_dev; + req->special = ireq; + ireq->req = req; +- } else +- ireq = req->special; +- ++ } + /* do not come back here */ +- req->cmd_type = REQ_TYPE_SPECIAL; + req->cmd_flags |= REQ_DONTPREP; + + return BLKPREP_OK; +diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c +index c6de566..ddf94ea 100644 +--- a/drivers/net/ppp_generic.c ++++ b/drivers/net/ppp_generic.c +@@ -2544,6 +2544,9 @@ static void ppp_destroy_interface(struct ppp *ppp) + ppp->active_filter = NULL; + #endif /* CONFIG_PPP_FILTER */ + ++ if (ppp->xmit_pending) ++ kfree_skb(ppp->xmit_pending); ++ + kfree(ppp); + } + +diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c +index 15854ae..1d4e835 100644 +--- a/drivers/video/ffb.c ++++ b/drivers/video/ffb.c +@@ -336,14 +336,30 @@ struct ffb_dac { + u32 value2; + }; + ++#define FFB_DAC_UCTRL 0x1001 /* User Control */ ++#define FFB_DAC_UCTRL_MANREV 0x00000f00 /* 4-bit Manufacturing Revision */ ++#define FFB_DAC_UCTRL_MANREV_SHIFT 8 ++#define FFB_DAC_TGEN 0x6000 /* Timing Generator */ ++#define FFB_DAC_TGEN_VIDE 0x00000001 /* Video Enable */ ++#define FFB_DAC_DID 0x8000 /* Device Identification */ ++#define FFB_DAC_DID_PNUM 0x0ffff000 /* Device Part Number */ ++#define FFB_DAC_DID_PNUM_SHIFT 12 ++#define FFB_DAC_DID_REV 0xf0000000 /* Device Revision */ ++#define FFB_DAC_DID_REV_SHIFT 28 ++ ++#define FFB_DAC_CUR_CTRL 0x100 ++#define FFB_DAC_CUR_CTRL_P0 0x00000001 ++#define FFB_DAC_CUR_CTRL_P1 0x00000002 ++ + struct ffb_par { + spinlock_t lock; + struct ffb_fbc __iomem *fbc; + struct ffb_dac __iomem *dac; + + u32 flags; +-#define FFB_FLAG_AFB 0x00000001 +-#define FFB_FLAG_BLANKED 0x00000002 ++#define FFB_FLAG_AFB 0x00000001 /* AFB m3 or m6 */ ++#define FFB_FLAG_BLANKED 0x00000002 /* screen is blanked */ ++#define FFB_FLAG_INVCURSOR 0x00000004 /* DAC has inverted cursor logic */ + + u32 fg_cache __attribute__((aligned (8))); + u32 bg_cache; +@@ -354,7 +370,6 @@ struct ffb_par { + unsigned long physbase; + unsigned long fbsize; + +- int dac_rev; + int board_type; + }; + +@@ -426,11 +441,12 @@ static void ffb_switch_from_graph(struct ffb_par *par) + FFBWait(par); + + /* Disable cursor. */ +- upa_writel(0x100, &dac->type2); +- if (par->dac_rev <= 2) ++ upa_writel(FFB_DAC_CUR_CTRL, &dac->type2); ++ if (par->flags & FFB_FLAG_INVCURSOR) + upa_writel(0, &dac->value2); + else +- upa_writel(3, &dac->value2); ++ upa_writel((FFB_DAC_CUR_CTRL_P0 | ++ FFB_DAC_CUR_CTRL_P1), &dac->value2); + + spin_unlock_irqrestore(&par->lock, flags); + } +@@ -664,18 +680,18 @@ ffb_blank(int blank, struct fb_info *info) + struct ffb_par *par = (struct ffb_par *) info->par; + struct ffb_dac __iomem *dac = par->dac; + unsigned long flags; +- u32 tmp; ++ u32 val; ++ int i; + + spin_lock_irqsave(&par->lock, flags); + + FFBWait(par); + ++ upa_writel(FFB_DAC_TGEN, &dac->type); ++ val = upa_readl(&dac->value); + switch (blank) { + case FB_BLANK_UNBLANK: /* Unblanking */ +- upa_writel(0x6000, &dac->type); +- tmp = (upa_readl(&dac->value) | 0x1); +- upa_writel(0x6000, &dac->type); +- upa_writel(tmp, &dac->value); ++ val |= FFB_DAC_TGEN_VIDE; + par->flags &= ~FFB_FLAG_BLANKED; + break; + +@@ -683,13 +699,16 @@ ffb_blank(int blank, struct fb_info *info) + case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */ + case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */ + case FB_BLANK_POWERDOWN: /* Poweroff */ +- upa_writel(0x6000, &dac->type); +- tmp = (upa_readl(&dac->value) & ~0x1); +- upa_writel(0x6000, &dac->type); +- upa_writel(tmp, &dac->value); ++ val &= ~FFB_DAC_TGEN_VIDE; + par->flags |= FFB_FLAG_BLANKED; + break; + } ++ upa_writel(FFB_DAC_TGEN, &dac->type); ++ upa_writel(val, &dac->value); ++ for (i = 0; i < 10; i++) { ++ upa_writel(FFB_DAC_TGEN, &dac->type); ++ upa_readl(&dac->value); ++ } + + spin_unlock_irqrestore(&par->lock, flags); + +@@ -894,6 +913,7 @@ static int ffb_init_one(struct of_device *op) + struct ffb_dac __iomem *dac; + struct all_info *all; + int err; ++ u32 dac_pnum, dac_rev, dac_mrev; + + all = kzalloc(sizeof(*all), GFP_KERNEL); + if (!all) +@@ -948,17 +968,31 @@ static int ffb_init_one(struct of_device *op) + if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) + upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr); + +- ffb_switch_from_graph(&all->par); +- + dac = all->par.dac; +- upa_writel(0x8000, &dac->type); +- all->par.dac_rev = upa_readl(&dac->value) >> 0x1c; ++ upa_writel(FFB_DAC_DID, &dac->type); ++ dac_pnum = upa_readl(&dac->value); ++ dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT; ++ dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT; ++ ++ upa_writel(FFB_DAC_UCTRL, &dac->type); ++ dac_mrev = upa_readl(&dac->value); ++ dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >> ++ FFB_DAC_UCTRL_MANREV_SHIFT; + + /* Elite3D has different DAC revision numbering, and no DAC revisions +- * have the reversed meaning of cursor enable. ++ * have the reversed meaning of cursor enable. Otherwise, Pacifica 1 ++ * ramdacs with manufacturing revision less than 3 have inverted ++ * cursor logic. We identify Pacifica 1 as not Pacifica 2, the ++ * latter having a part number value of 0x236e. + */ +- if (all->par.flags & FFB_FLAG_AFB) +- all->par.dac_rev = 10; ++ if ((all->par.flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) { ++ all->par.flags &= ~FFB_FLAG_INVCURSOR; ++ } else { ++ if (dac_mrev < 3) ++ all->par.flags |= FFB_FLAG_INVCURSOR; ++ } ++ ++ ffb_switch_from_graph(&all->par); + + /* Unblank it just to be sure. When there are multiple + * FFB/AFB cards in the system, or it is not the OBP +@@ -993,10 +1027,12 @@ static int ffb_init_one(struct of_device *op) + + dev_set_drvdata(&op->dev, all); + +- printk("%s: %s at %016lx, type %d, DAC revision %d\n", ++ printk("%s: %s at %016lx, type %d, " ++ "DAC pnum[%x] rev[%d] manuf_rev[%d]\n", + dp->full_name, + ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"), +- all->par.physbase, all->par.board_type, all->par.dac_rev); ++ all->par.physbase, all->par.board_type, ++ dac_pnum, dac_rev, dac_mrev); + + return 0; + } +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index c4fa91b..a894e6d 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -488,6 +488,12 @@ int cifs_get_inode_info(struct inode **pinode, + mode e.g. 555 */ + if (cifsInfo->cifsAttrs & ATTR_READONLY) + inode->i_mode &= ~(S_IWUGO); ++ else if ((inode->i_mode & S_IWUGO) == 0) ++ /* the ATTR_READONLY flag may have been */ ++ /* changed on server -- set any w bits */ ++ /* allowed by mnt_file_mode */ ++ inode->i_mode |= (S_IWUGO & ++ cifs_sb->mnt_file_mode); + /* BB add code here - + validate if device or weird share or device type? */ + } +@@ -1133,6 +1139,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) + struct cifsFileInfo *open_file = NULL; + FILE_BASIC_INFO time_buf; + int set_time = FALSE; ++ int set_dosattr = FALSE; + __u64 mode = 0xFFFFFFFFFFFFFFFFULL; + __u64 uid = 0xFFFFFFFFFFFFFFFFULL; + __u64 gid = 0xFFFFFFFFFFFFFFFFULL; +@@ -1269,15 +1276,23 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) + else if (attrs->ia_valid & ATTR_MODE) { + rc = 0; + if ((mode & S_IWUGO) == 0) /* not writeable */ { +- if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) ++ if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { ++ set_dosattr = TRUE; + time_buf.Attributes = + cpu_to_le32(cifsInode->cifsAttrs | + ATTR_READONLY); ++ } + } else if ((mode & S_IWUGO) == S_IWUGO) { +- if (cifsInode->cifsAttrs & ATTR_READONLY) ++ if (cifsInode->cifsAttrs & ATTR_READONLY) { ++ set_dosattr = TRUE; + time_buf.Attributes = + cpu_to_le32(cifsInode->cifsAttrs & + (~ATTR_READONLY)); ++ /* Windows ignores set to zero */ ++ if(time_buf.Attributes == 0) ++ time_buf.Attributes |= ++ cpu_to_le32(ATTR_NORMAL); ++ } + } + /* BB to be implemented - + via Windows security descriptors or streams */ +@@ -1315,7 +1330,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) + } else + time_buf.ChangeTime = 0; + +- if (set_time || time_buf.Attributes) { ++ if (set_time || set_dosattr) { + time_buf.CreationTime = 0; /* do not change */ + /* In the future we should experiment - try setting timestamps + via Handle (SetFileInfo) instead of by path */ +diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c +index 99dfb53..d1d79fe 100644 +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -215,6 +215,10 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, + tmp_inode->i_mode |= S_IFREG; + if (attr & ATTR_READONLY) + tmp_inode->i_mode &= ~(S_IWUGO); ++ else if ((tmp_inode->i_mode & S_IWUGO) == 0) ++ /* the ATTR_READONLY flag may have been changed on */ ++ /* server -- set any w bits allowed by mnt_file_mode */ ++ tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); + } /* could add code here - to validate if device or weird share type? */ + + /* can not fill in nlink here as in qpathinfo version and Unx search */ +diff --git a/include/asm-sparc/mostek.h b/include/asm-sparc/mostek.h +index bd92a78..958d051 100644 +--- a/include/asm-sparc/mostek.h ++++ b/include/asm-sparc/mostek.h +@@ -87,7 +87,7 @@ extern void __iomem *mstk48t02_regs; + #define MSTK_DOW_MASK 0x07 + #define MSTK_DOM_MASK 0x3f + #define MSTK_MONTH_MASK 0x1f +-#define MSTK_YEAR_MASK 0xff ++#define MSTK_YEAR_MASK 0xffU + + /* Binary coded decimal conversion macros. */ + #define MSTK_REGVAL_TO_DECIMAL(x) (((x) & 0x0F) + 0x0A * ((x) >> 0x04)) +diff --git a/include/asm-sparc64/mostek.h b/include/asm-sparc64/mostek.h +index 09b5aba..d14dd89 100644 +--- a/include/asm-sparc64/mostek.h ++++ b/include/asm-sparc64/mostek.h +@@ -89,7 +89,7 @@ extern void __iomem *mstk48t02_regs; + #define MSTK_DOW_MASK 0x07 + #define MSTK_DOM_MASK 0x3f + #define MSTK_MONTH_MASK 0x1f +-#define MSTK_YEAR_MASK 0xff ++#define MSTK_YEAR_MASK 0xffU + + /* Binary coded decimal conversion macros. */ + #define MSTK_REGVAL_TO_DECIMAL(x) (((x) & 0x0F) + 0x0A * ((x) >> 0x04)) +diff --git a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S +index f045451..b16222b 100644 +--- a/include/asm-um/common.lds.S ++++ b/include/asm-um/common.lds.S +@@ -15,6 +15,7 @@ + PROVIDE (_unprotected_end = .); + + . = ALIGN(4096); ++ .note : { *(note.*) } + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; +diff --git a/include/asm-um/delay.h b/include/asm-um/delay.h +index 0985bda..c71e32b 100644 +--- a/include/asm-um/delay.h ++++ b/include/asm-um/delay.h +@@ -1,9 +1,20 @@ + #ifndef __UM_DELAY_H + #define __UM_DELAY_H + +-#include "asm/arch/delay.h" +-#include "asm/archparam.h" +- + #define MILLION 1000000 + ++/* Undefined on purpose */ ++extern void __bad_udelay(void); ++ ++extern void __udelay(unsigned long usecs); ++extern void __delay(unsigned long loops); ++ ++#define udelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \ ++ __bad_udelay() : __udelay(n)) ++ ++/* It appears that ndelay is not used at all for UML, and has never been ++ * implemented. */ ++extern void __unimplemented_ndelay(void); ++#define ndelay(n) __unimplemented_ndelay() ++ + #endif +diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h +index 84cfa8b..d2a96cb 100644 +--- a/include/linux/eventpoll.h ++++ b/include/linux/eventpoll.h +@@ -31,12 +31,19 @@ + /* + * On x86-64 make the 64bit structure have the same alignment as the + * 32bit structure. This makes 32bit emulation easier. ++ * ++ * UML/x86_64 needs the same packing as x86_64 - UML + UML_X86 + ++ * 64_BIT adds up to UML/x86_64. + */ + #ifdef __x86_64__ + #define EPOLL_PACKED __attribute__((packed)) + #else ++#if defined(CONFIG_UML) && defined(CONFIG_UML_X86) && defined(CONFIG_64BIT) ++#define EPOLL_PACKED __attribute__((packed)) ++#else + #define EPOLL_PACKED + #endif ++#endif + + struct epoll_event { + __u32 events; +diff --git a/include/linux/ide.h b/include/linux/ide.h +index e26a039..3808698 100644 +--- a/include/linux/ide.h ++++ b/include/linux/ide.h +@@ -727,6 +727,7 @@ typedef struct hwif_s { + int (*ide_dma_on)(ide_drive_t *drive); + int (*ide_dma_off_quietly)(ide_drive_t *drive); + int (*ide_dma_test_irq)(ide_drive_t *drive); ++ void (*ide_dma_clear_irq)(ide_drive_t *drive); + int (*ide_dma_host_on)(ide_drive_t *drive); + int (*ide_dma_host_off)(ide_drive_t *drive); + int (*ide_dma_lostirq)(ide_drive_t *drive); +@@ -796,7 +797,6 @@ typedef struct hwif_s { + unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */ + unsigned no_io_32bit : 1; /* 1 = can not do 32-bit IO ops */ + unsigned err_stops_fifo : 1; /* 1=data FIFO is cleared by an error */ +- unsigned atapi_irq_bogon : 1; /* Generates spurious DMA interrupts in PIO mode */ + + struct device gendev; + struct completion gendev_rel_comp; /* To deal with device release() */ +diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h +index 83fe2e3..50e33b0 100644 +--- a/include/media/saa7146_vv.h ++++ b/include/media/saa7146_vv.h +@@ -239,7 +239,8 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits); + #define SAA7146_HPS_SYNC_PORT_B 0x01 + + /* some memory sizes */ +-#define SAA7146_CLIPPING_MEM (14*PAGE_SIZE) ++/* max. 16 clipping rectangles */ ++#define SAA7146_CLIPPING_MEM (16 * 4 * sizeof(u32)) + + /* some defines for the various clipping-modes */ + #define SAA7146_CLIPPING_RECT 0x4 +diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h +index bc3c264..d585ea9 100644 +--- a/include/net/fib_rules.h ++++ b/include/net/fib_rules.h +@@ -34,6 +34,7 @@ struct fib_rules_ops + int family; + struct list_head list; + int rule_size; ++ int addr_size; + + int (*action)(struct fib_rule *, + struct flowi *, int, +diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h +index 7be4f4e..1d2037c 100644 +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -58,6 +58,7 @@ struct fib6_node + __u16 fn_bit; /* bit key */ + __u16 fn_flags; + __u32 fn_sernum; ++ struct rt6_info *rr_ptr; + }; + + #ifndef CONFIG_IPV6_SUBTREES +diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c +index 3a70522..7c69506 100644 +--- a/net/appletalk/ddp.c ++++ b/net/appletalk/ddp.c +@@ -1417,10 +1417,13 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, + /* + * Size check to see if ddp->deh_len was crap + * (Otherwise we'll detonate most spectacularly +- * in the middle of recvmsg()). ++ * in the middle of atalk_checksum() or recvmsg()). + */ +- if (skb->len < sizeof(*ddp)) ++ if (skb->len < sizeof(*ddp) || skb->len < (len_hops & 1023)) { ++ pr_debug("AppleTalk: dropping corrupted frame (deh_len=%u, " ++ "skb->len=%u)\n", len_hops & 1023, skb->len); + goto freeit; ++ } + + /* + * Any checksums. Note we don't do htons() on this == is assumed to be +diff --git a/net/core/dev.c b/net/core/dev.c +index e660cb5..295f8f9 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1750,10 +1750,10 @@ static int ing_filter(struct sk_buff *skb) + + skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); + +- spin_lock(&dev->ingress_lock); ++ spin_lock(&dev->queue_lock); + if ((q = dev->qdisc_ingress) != NULL) + result = q->enqueue(skb, q); +- spin_unlock(&dev->ingress_lock); ++ spin_unlock(&dev->queue_lock); + + } + +diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c +index 1df6cd4..bdbb479 100644 +--- a/net/core/fib_rules.c ++++ b/net/core/fib_rules.c +@@ -152,6 +152,28 @@ out: + + EXPORT_SYMBOL_GPL(fib_rules_lookup); + ++static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, ++ struct fib_rules_ops *ops) ++{ ++ int err = -EINVAL; ++ ++ if (frh->src_len) ++ if (tb[FRA_SRC] == NULL || ++ frh->src_len > (ops->addr_size * 8) || ++ nla_len(tb[FRA_SRC]) != ops->addr_size) ++ goto errout; ++ ++ if (frh->dst_len) ++ if (tb[FRA_DST] == NULL || ++ frh->dst_len > (ops->addr_size * 8) || ++ nla_len(tb[FRA_DST]) != ops->addr_size) ++ goto errout; ++ ++ err = 0; ++errout: ++ return err; ++} ++ + int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) + { + struct fib_rule_hdr *frh = nlmsg_data(nlh); +@@ -173,6 +195,10 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) + if (err < 0) + goto errout; + ++ err = validate_rulemsg(frh, tb, ops); ++ if (err < 0) ++ goto errout; ++ + rule = kzalloc(ops->rule_size, GFP_KERNEL); + if (rule == NULL) { + err = -ENOMEM; +@@ -260,6 +286,10 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) + if (err < 0) + goto errout; + ++ err = validate_rulemsg(frh, tb, ops); ++ if (err < 0) ++ goto errout; ++ + list_for_each_entry(rule, ops->rules_list, list) { + if (frh->action && (frh->action != rule->action)) + continue; +diff --git a/net/dccp/proto.c b/net/dccp/proto.c +index 63b3fa2..88ed359 100644 +--- a/net/dccp/proto.c ++++ b/net/dccp/proto.c +@@ -575,7 +575,7 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname, + if (get_user(len, optlen)) + return -EFAULT; + +- if (len < sizeof(int)) ++ if (len < (int)sizeof(int)) + return -EINVAL; + + dp = dccp_sk(sk); +@@ -589,9 +589,11 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname, + (__be32 __user *)optval, optlen); + case DCCP_SOCKOPT_SEND_CSCOV: + val = dp->dccps_pcslen; ++ len = sizeof(val); + break; + case DCCP_SOCKOPT_RECV_CSCOV: + val = dp->dccps_pcrlen; ++ len = sizeof(val); + break; + case 128 ... 191: + return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, +diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c +index e32d0c3..5e86dd5 100644 +--- a/net/decnet/dn_rules.c ++++ b/net/decnet/dn_rules.c +@@ -109,8 +109,6 @@ errout: + + static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = { + FRA_GENERIC_POLICY, +- [FRA_SRC] = { .type = NLA_U16 }, +- [FRA_DST] = { .type = NLA_U16 }, + }; + + static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) +@@ -133,7 +131,7 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + int err = -EINVAL; + struct dn_fib_rule *r = (struct dn_fib_rule *)rule; + +- if (frh->src_len > 16 || frh->dst_len > 16 || frh->tos) ++ if (frh->tos) + goto errout; + + if (rule->table == RT_TABLE_UNSPEC) { +@@ -150,11 +148,11 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + } + } + +- if (tb[FRA_SRC]) +- r->src = nla_get_u16(tb[FRA_SRC]); ++ if (frh->src_len) ++ r->src = nla_get_le16(tb[FRA_SRC]); + +- if (tb[FRA_DST]) +- r->dst = nla_get_u16(tb[FRA_DST]); ++ if (frh->dst_len) ++ r->dst = nla_get_le16(tb[FRA_DST]); + + r->src_len = frh->src_len; + r->srcmask = dnet_make_mask(r->src_len); +@@ -176,10 +174,10 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, + if (frh->dst_len && (r->dst_len != frh->dst_len)) + return 0; + +- if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC]))) ++ if (frh->src_len && (r->src != nla_get_le16(tb[FRA_SRC]))) + return 0; + +- if (tb[FRA_DST] && (r->dst != nla_get_u16(tb[FRA_DST]))) ++ if (frh->dst_len && (r->dst != nla_get_le16(tb[FRA_DST]))) + return 0; + + return 1; +@@ -214,9 +212,9 @@ static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb, + frh->tos = 0; + + if (r->dst_len) +- NLA_PUT_U16(skb, FRA_DST, r->dst); ++ NLA_PUT_LE16(skb, FRA_DST, r->dst); + if (r->src_len) +- NLA_PUT_U16(skb, FRA_SRC, r->src); ++ NLA_PUT_LE16(skb, FRA_SRC, r->src); + + return 0; + +@@ -249,6 +247,7 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) + static struct fib_rules_ops dn_fib_rules_ops = { + .family = AF_DECnet, + .rule_size = sizeof(struct dn_fib_rule), ++ .addr_size = sizeof(u16), + .action = dn_fib_rule_action, + .match = dn_fib_rule_match, + .configure = dn_fib_rule_configure, +diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c +index b837c33..c660c07 100644 +--- a/net/ipv4/fib_rules.c ++++ b/net/ipv4/fib_rules.c +@@ -171,8 +171,6 @@ static struct fib_table *fib_empty_table(void) + + static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = { + FRA_GENERIC_POLICY, +- [FRA_SRC] = { .type = NLA_U32 }, +- [FRA_DST] = { .type = NLA_U32 }, + [FRA_FLOW] = { .type = NLA_U32 }, + }; + +@@ -183,8 +181,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + int err = -EINVAL; + struct fib4_rule *rule4 = (struct fib4_rule *) rule; + +- if (frh->src_len > 32 || frh->dst_len > 32 || +- (frh->tos & ~IPTOS_TOS_MASK)) ++ if (frh->tos & ~IPTOS_TOS_MASK) + goto errout; + + if (rule->table == RT_TABLE_UNSPEC) { +@@ -201,10 +198,10 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + } + } + +- if (tb[FRA_SRC]) ++ if (frh->src_len) + rule4->src = nla_get_be32(tb[FRA_SRC]); + +- if (tb[FRA_DST]) ++ if (frh->dst_len) + rule4->dst = nla_get_be32(tb[FRA_DST]); + + #ifdef CONFIG_NET_CLS_ROUTE +@@ -242,10 +239,10 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, + return 0; + #endif + +- if (tb[FRA_SRC] && (rule4->src != nla_get_be32(tb[FRA_SRC]))) ++ if (frh->src_len && (rule4->src != nla_get_be32(tb[FRA_SRC]))) + return 0; + +- if (tb[FRA_DST] && (rule4->dst != nla_get_be32(tb[FRA_DST]))) ++ if (frh->dst_len && (rule4->dst != nla_get_be32(tb[FRA_DST]))) + return 0; + + return 1; +@@ -309,6 +306,7 @@ static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule) + static struct fib_rules_ops fib4_rules_ops = { + .family = AF_INET, + .rule_size = sizeof(struct fib4_rule), ++ .addr_size = sizeof(u32), + .action = fib4_rule_action, + .match = fib4_rule_match, + .configure = fib4_rule_configure, +diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c +index 0862809..ea3035b 100644 +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -131,8 +131,6 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) + + static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = { + FRA_GENERIC_POLICY, +- [FRA_SRC] = { .len = sizeof(struct in6_addr) }, +- [FRA_DST] = { .len = sizeof(struct in6_addr) }, + }; + + static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, +@@ -142,9 +140,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + int err = -EINVAL; + struct fib6_rule *rule6 = (struct fib6_rule *) rule; + +- if (frh->src_len > 128 || frh->dst_len > 128) +- goto errout; +- + if (rule->action == FR_ACT_TO_TBL) { + if (rule->table == RT6_TABLE_UNSPEC) + goto errout; +@@ -155,11 +150,11 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + } + } + +- if (tb[FRA_SRC]) ++ if (frh->src_len) + nla_memcpy(&rule6->src.addr, tb[FRA_SRC], + sizeof(struct in6_addr)); + +- if (tb[FRA_DST]) ++ if (frh->dst_len) + nla_memcpy(&rule6->dst.addr, tb[FRA_DST], + sizeof(struct in6_addr)); + +@@ -186,11 +181,11 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, + if (frh->tos && (rule6->tclass != frh->tos)) + return 0; + +- if (tb[FRA_SRC] && ++ if (frh->src_len && + nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr))) + return 0; + +- if (tb[FRA_DST] && ++ if (frh->dst_len && + nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) + return 0; + +@@ -240,6 +235,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) + static struct fib_rules_ops fib6_rules_ops = { + .family = AF_INET6, + .rule_size = sizeof(struct fib6_rule), ++ .addr_size = sizeof(struct in6_addr), + .action = fib6_rule_action, + .match = fib6_rule_match, + .configure = fib6_rule_configure, +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index 96d8310..2d9c425 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -659,6 +659,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + ins = &iter->u.next; + } + ++ /* Reset round-robin state, if necessary */ ++ if (ins == &fn->leaf) ++ fn->rr_ptr = NULL; ++ + /* + * insert node + */ +@@ -1110,6 +1114,10 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, + rt6_stats.fib_rt_entries--; + rt6_stats.fib_discarded_routes++; + ++ /* Reset round-robin state, if necessary */ ++ if (fn->rr_ptr == rt) ++ fn->rr_ptr = NULL; ++ + /* Adjust walkers */ + read_lock(&fib6_walker_lock); + FOR_WALKERS(w) { +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 5f0043c..01bcf4a 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -354,55 +354,76 @@ static int rt6_score_route(struct rt6_info *rt, int oif, + return m; + } + +-static struct rt6_info *rt6_select(struct rt6_info **head, int oif, +- int strict) ++static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict, ++ int *mpri, struct rt6_info *match) + { +- struct rt6_info *match = NULL, *last = NULL; +- struct rt6_info *rt, *rt0 = *head; +- u32 metric; ++ int m; ++ ++ if (rt6_check_expired(rt)) ++ goto out; ++ ++ m = rt6_score_route(rt, oif, strict); ++ if (m < 0) ++ goto out; ++ ++ if (m > *mpri) { ++ if (strict & RT6_LOOKUP_F_REACHABLE) ++ rt6_probe(match); ++ *mpri = m; ++ match = rt; ++ } else if (strict & RT6_LOOKUP_F_REACHABLE) { ++ rt6_probe(rt); ++ } ++ ++out: ++ return match; ++} ++ ++static struct rt6_info *find_rr_leaf(struct fib6_node *fn, ++ struct rt6_info *rr_head, ++ u32 metric, int oif, int strict) ++{ ++ struct rt6_info *rt, *match; + int mpri = -1; + +- RT6_TRACE("%s(head=%p(*head=%p), oif=%d)\n", +- __FUNCTION__, head, head ? *head : NULL, oif); ++ match = NULL; ++ for (rt = rr_head; rt && rt->rt6i_metric == metric; ++ rt = rt->u.next) ++ match = find_match(rt, oif, strict, &mpri, match); ++ for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric; ++ rt = rt->u.next) ++ match = find_match(rt, oif, strict, &mpri, match); + +- for (rt = rt0, metric = rt0->rt6i_metric; +- rt && rt->rt6i_metric == metric && (!last || rt != rt0); +- rt = rt->u.next) { +- int m; ++ return match; ++} + +- if (rt6_check_expired(rt)) +- continue; ++static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) ++{ ++ struct rt6_info *match, *rt0; + +- last = rt; ++ RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", ++ __FUNCTION__, fn->leaf, oif); + +- m = rt6_score_route(rt, oif, strict); +- if (m < 0) +- continue; ++ rt0 = fn->rr_ptr; ++ if (!rt0) ++ fn->rr_ptr = rt0 = fn->leaf; + +- if (m > mpri) { +- if (strict & RT6_LOOKUP_F_REACHABLE) +- rt6_probe(match); +- match = rt; +- mpri = m; +- } else if (strict & RT6_LOOKUP_F_REACHABLE) { +- rt6_probe(rt); +- } +- } ++ match = find_rr_leaf(fn, rt0, rt0->rt6i_metric, oif, strict); + + if (!match && +- (strict & RT6_LOOKUP_F_REACHABLE) && +- last && last != rt0) { ++ (strict & RT6_LOOKUP_F_REACHABLE)) { ++ struct rt6_info *next = rt0->u.next; ++ + /* no entries matched; do round-robin */ +- static DEFINE_SPINLOCK(lock); +- spin_lock(&lock); +- *head = rt0->u.next; +- rt0->u.next = last->u.next; +- last->u.next = rt0; +- spin_unlock(&lock); ++ if (!next || next->rt6i_metric != rt0->rt6i_metric) ++ next = fn->leaf; ++ ++ if (next != rt0) ++ fn->rr_ptr = next; + } + +- RT6_TRACE("%s() => %p, score=%d\n", +- __FUNCTION__, match, mpri); ++ RT6_TRACE("%s() => %p\n", ++ __FUNCTION__, match); + + return (match ? match : &ip6_null_entry); + } +@@ -648,7 +669,7 @@ restart_2: + fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); + + restart: +- rt = rt6_select(&fn->leaf, fl->iif, strict | reachable); ++ rt = rt6_select(fn, fl->iif, strict | reachable); + BACKTRACK(&fl->fl6_src); + if (rt == &ip6_null_entry || + rt->rt6i_flags & RTF_CACHE) +@@ -743,7 +764,7 @@ restart_2: + fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); + + restart: +- rt = rt6_select(&fn->leaf, fl->oif, strict | reachable); ++ rt = rt6_select(fn, fl->oif, strict | reachable); + BACKTRACK(&fl->fl6_src); + if (rt == &ip6_null_entry || + rt->rt6i_flags & RTF_CACHE) +diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c +index 09fda68..23e4459 100644 +--- a/net/sched/cls_basic.c ++++ b/net/sched/cls_basic.c +@@ -82,6 +82,13 @@ static void basic_put(struct tcf_proto *tp, unsigned long f) + + static int basic_init(struct tcf_proto *tp) + { ++ struct basic_head *head; ++ ++ head = kzalloc(sizeof(*head), GFP_KERNEL); ++ if (head == NULL) ++ return -ENOBUFS; ++ INIT_LIST_HEAD(&head->flist); ++ tp->root = head; + return 0; + } + +@@ -177,15 +184,6 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle, + } + + err = -ENOBUFS; +- if (head == NULL) { +- head = kzalloc(sizeof(*head), GFP_KERNEL); +- if (head == NULL) +- goto errout; +- +- INIT_LIST_HEAD(&head->flist); +- tp->root = head; +- } +- + f = kzalloc(sizeof(*f), GFP_KERNEL); + if (f == NULL) + goto errout; +diff --git a/net/socket.c b/net/socket.c +index 4e39631..afb6085 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -1368,7 +1368,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, + + err = sock_attach_fd(newsock, newfile); + if (err < 0) +- goto out_fd; ++ goto out_fd_simple; + + err = security_socket_accept(sock, newsock); + if (err) +@@ -1401,6 +1401,11 @@ out_put: + fput_light(sock->file, fput_needed); + out: + return err; ++out_fd_simple: ++ sock_release(newsock); ++ put_filp(newfile); ++ put_unused_fd(newfd); ++ goto out_put; + out_fd: + fput(newfile); + put_unused_fd(newfd); diff --git a/debian/patches/series/1~experimental.1 b/debian/patches/series/1~experimental.1 index 205b27db0..78fa3a197 100644 --- a/debian/patches/series/1~experimental.1 +++ b/debian/patches/series/1~experimental.1 @@ -40,3 +40,4 @@ + bugfix/2.6.20.3 + bugfix/ia64/hardcode-arch-script-output.patch + bugfix/2.6.20.4 ++ bugfix/2.6.20.5