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);