1839 lines
59 KiB
Groff
1839 lines
59 KiB
Groff
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;i<n;i++)
|
|
- cpu_relax();
|
|
-}
|
|
-
|
|
-EXPORT_SYMBOL(__const_udelay);
|
|
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
|
|
index 137f444..dee5be6 100644
|
|
--- a/arch/um/sys-x86_64/delay.c
|
|
+++ b/arch/um/sys-x86_64/delay.c
|
|
@@ -28,14 +28,3 @@ void __udelay(unsigned long usecs)
|
|
}
|
|
|
|
EXPORT_SYMBOL(__udelay);
|
|
-
|
|
-void __const_udelay(unsigned long usecs)
|
|
-{
|
|
- unsigned long i, n;
|
|
-
|
|
- n = (loops_per_jiffy * HZ * usecs) / MILLION;
|
|
- for(i=0;i<n;i++)
|
|
- cpu_relax();
|
|
-}
|
|
-
|
|
-EXPORT_SYMBOL(__const_udelay);
|
|
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
|
|
index 35172d3..a664231 100644
|
|
--- a/crypto/scatterwalk.c
|
|
+++ b/crypto/scatterwalk.c
|
|
@@ -91,6 +91,8 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
|
|
memcpy_dir(buf, vaddr, len_this_page, out);
|
|
scatterwalk_unmap(vaddr, out);
|
|
|
|
+ scatterwalk_advance(walk, nbytes);
|
|
+
|
|
if (nbytes == len_this_page)
|
|
break;
|
|
|
|
@@ -99,7 +101,5 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
|
|
|
|
scatterwalk_pagedone(walk, out, 1);
|
|
}
|
|
-
|
|
- scatterwalk_advance(walk, nbytes);
|
|
}
|
|
EXPORT_SYMBOL_GPL(scatterwalk_copychunks);
|
|
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
|
|
index 667acd2..d6fcf0a 100644
|
|
--- a/drivers/ata/libata-core.c
|
|
+++ b/drivers/ata/libata-core.c
|
|
@@ -1478,7 +1478,16 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
|
|
}
|
|
|
|
tf.protocol = ATA_PROT_PIO;
|
|
- tf.flags |= ATA_TFLAG_POLLING; /* for polling presence detection */
|
|
+
|
|
+ /* Some devices choke if TF registers contain garbage. Make
|
|
+ * sure those are properly initialized.
|
|
+ */
|
|
+ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
|
|
+
|
|
+ /* Device presence detection is unreliable on some
|
|
+ * controllers. Always poll IDENTIFY if available.
|
|
+ */
|
|
+ tf.flags |= ATA_TFLAG_POLLING;
|
|
|
|
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
|
|
id, sizeof(id[0]) * ATA_ID_WORDS);
|
|
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
|
|
index 73902d3..1790542 100644
|
|
--- a/drivers/ata/libata-scsi.c
|
|
+++ b/drivers/ata/libata-scsi.c
|
|
@@ -295,6 +295,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
|
|
scsi_cmd[8] = args[3];
|
|
scsi_cmd[10] = args[4];
|
|
scsi_cmd[12] = args[5];
|
|
+ scsi_cmd[13] = args[6] & 0x0f;
|
|
scsi_cmd[14] = args[0];
|
|
|
|
/* Good values for timeout and retries? Values below
|
|
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
|
|
index aae0b52..4054cdb 100644
|
|
--- a/drivers/ata/sata_mv.c
|
|
+++ b/drivers/ata/sata_mv.c
|
|
@@ -139,14 +139,19 @@ enum {
|
|
PCI_ERR = (1 << 18),
|
|
TRAN_LO_DONE = (1 << 19), /* 6xxx: IRQ coalescing */
|
|
TRAN_HI_DONE = (1 << 20), /* 6xxx: IRQ coalescing */
|
|
+ PORTS_0_3_COAL_DONE = (1 << 8),
|
|
+ PORTS_4_7_COAL_DONE = (1 << 17),
|
|
PORTS_0_7_COAL_DONE = (1 << 21), /* 6xxx: IRQ coalescing */
|
|
GPIO_INT = (1 << 22),
|
|
SELF_INT = (1 << 23),
|
|
TWSI_INT = (1 << 24),
|
|
HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */
|
|
+ HC_MAIN_RSVD_5 = (0x1fff << 19), /* bits 31-19 */
|
|
HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE |
|
|
PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
|
|
HC_MAIN_RSVD),
|
|
+ HC_MAIN_MASKED_IRQS_5 = (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
|
|
+ HC_MAIN_RSVD_5),
|
|
|
|
/* SATAHC registers */
|
|
HC_CFG_OFS = 0,
|
|
@@ -843,23 +848,27 @@ static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
|
|
u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
|
|
|
|
/* set up non-NCQ EDMA configuration */
|
|
- cfg &= ~0x1f; /* clear queue depth */
|
|
- cfg &= ~EDMA_CFG_NCQ; /* clear NCQ mode */
|
|
cfg &= ~(1 << 9); /* disable equeue */
|
|
|
|
- if (IS_GEN_I(hpriv))
|
|
+ if (IS_GEN_I(hpriv)) {
|
|
+ cfg &= ~0x1f; /* clear queue depth */
|
|
cfg |= (1 << 8); /* enab config burst size mask */
|
|
+ }
|
|
|
|
- else if (IS_GEN_II(hpriv))
|
|
+ else if (IS_GEN_II(hpriv)) {
|
|
+ cfg &= ~0x1f; /* clear queue depth */
|
|
cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
|
|
+ cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
|
|
+ }
|
|
|
|
else if (IS_GEN_IIE(hpriv)) {
|
|
- cfg |= (1 << 23); /* dis RX PM port mask */
|
|
- cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */
|
|
+ cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */
|
|
+ cfg |= (1 << 22); /* enab 4-entry host queue cache */
|
|
cfg &= ~(1 << 19); /* dis 128-entry queue (for now?) */
|
|
cfg |= (1 << 18); /* enab early completion */
|
|
- cfg |= (1 << 17); /* enab host q cache */
|
|
- cfg |= (1 << 22); /* enab cutthrough */
|
|
+ cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */
|
|
+ cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */
|
|
+ cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
|
|
}
|
|
|
|
writelfl(cfg, port_mmio + EDMA_CFG_OFS);
|
|
@@ -2283,7 +2292,11 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
|
|
|
|
/* and unmask interrupt generation for host regs */
|
|
writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
|
|
- writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
|
|
+
|
|
+ if (IS_50XX(hpriv))
|
|
+ writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
|
|
+ else
|
|
+ writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
|
|
|
|
VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
|
|
"PCI int cause/mask=0x%08x/0x%08x\n",
|
|
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
|
|
index f7a963e..91f24b1 100644
|
|
--- a/drivers/ata/sata_nv.c
|
|
+++ b/drivers/ata/sata_nv.c
|
|
@@ -214,6 +214,7 @@ struct nv_adma_port_priv {
|
|
struct nv_adma_prd *aprd;
|
|
dma_addr_t aprd_dma;
|
|
u8 flags;
|
|
+ int last_issue_ncq;
|
|
};
|
|
|
|
#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT)))))
|
|
@@ -1151,6 +1152,7 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
|
|
{
|
|
struct nv_adma_port_priv *pp = qc->ap->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);
|