From: Linus Torvalds Date: Fri, 23 Nov 2007 20:38:25 +0000 (-0500) Subject: - pre2 X-Git-Tag: 2.4.0-test8pre2 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=e6c596f32c9985778bafd67bc8a129fc76a2313d;p=history.git - pre2 - The TCP socket leak patch _really_ went in this time. - get rid of more suser() checks in networking.. It's "capable(CAP_NET_ADMIN)". - sparc updates - alpha updates. Fast alpha xor for raid. AP1000 updates. - Wonders never cease. digiboard driver updates. Christoph Lameter is BAAACK! - SiS frame buffer driver updates. Can be used without a BIOS. - nfsd interface cleanup. - fix potential buffer overruns in get_partition_list. Remove limitation of one page. - floppy driver capability cleanups. Use "request_region()". - handle dcache flushing when there are shared user mappings that may be dirty. - get rid of the "xxxx_ret()" user access macros. They are more complex than just doing the return directly and they hide what's going on. - fix up broken BIOSes that don't give unique ID's to different APICs - make more of the drm drivers compile on other platforms and know about the signal blocking issues. - net/atm/mpoa_proc.c: user-space access thinko - pcmcia: David Hinds: merge updates from 3.1.20 - pcmcia: non-ISA machines really shouldn't use ISA interrupts ;) - ext2: truncate races and error code return fixes - true shared signals for pthreads.. --- diff --git a/Documentation/digiboard.txt b/Documentation/digiboard.txt index b25fc158a51d..6a2da7fe673b 100644 --- a/Documentation/digiboard.txt +++ b/Documentation/digiboard.txt @@ -8,11 +8,6 @@ The Digiboard Driver for Linux supports the following boards: switches) You can use up to 4 cards with this driver and it should work on other architectures than intel also. -In case you have problems with this version (1.6.1) of this driver, please -email directly to me as I made the last update. It you have a report about -running it on other architectures than intel, email me, so I can document -it here. - A version of this driver has been taken by Digiboard to make a driver software package which supports also PC/Xem cards and newer PCI cards but it doesn't support the old PC/Xi cards and it isn't yet ported to @@ -154,22 +149,12 @@ Sources of Information ---------------------- Please contact digi directly digilnux@dgii.com. Forward any information of -general interest to me. +general interest to me so that I can include it on the webpage. -Web page (mainly of historical interest): http://lameter.com/digi +Web page: http://lameter.com/digi Christoph Lameter (christoph@lameter.com) Aug 14, 2000. -Supporting Tools ----------------- - -Some (old) tools and more detailed information can be found at -ftp://lameter.com/digi - -The "ditty" tool described in the Digiboard Manuals for other Unixes -is also available. - - Device file creation -------------------- diff --git a/MAINTAINERS b/MAINTAINERS index 65cf9b34bb22..1a4cc0d4a92b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -655,10 +655,12 @@ L: autofs@linux.kernel.org S: Maintained KERNEL NFSD -P: G. Allen Morris III -M: gam3@acm.org +P: Neil Brown +M: neilb@cse.unsw.edu.au L: nfs-devel@linux.kernel.org (Linux NFS) -W: http://csua.berkeley.edu/~gam3/knfsd +L: nfs@lists.sourceforge.net +W: http://nfs.sourceforge.net/ +W: http://www.cse.unsw.edu.au/~neilb/oss/knfsd/ S: Maintained LANMEDIA WAN CARD DRIVER @@ -894,7 +896,7 @@ PCMCIA SUBSYSTEM P: David Hinds M: dhinds@zen.stanford.edu L: linux-kernel@vger.kernel.org -W: http://pcmcia.sourceforge.org +W: http://pcmcia-cs.sourceforge.net S: Maintained PCNET32 NETWORK DRIVER diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index 3daa2c73cdd8..4f6c6b65cad8 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -23,6 +23,8 @@ have_mcpu_pca56 := $(shell if $(CC) -mcpu=pca56 -S -o /dev/null -xc /dev/null > have_mcpu_ev6 := $(shell if $(CC) -mcpu=ev6 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) +have_mcpu_ev67 := $(shell if $(CC) -mcpu=ev67 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) + # Turn on the proper cpu optimizations. ifeq ($(have_mcpu),y) # If GENERIC, make sure to turn off any instruction set extensions that diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c index 5aa00254b89e..c686fd29d573 100644 --- a/arch/alpha/kernel/core_cia.c +++ b/arch/alpha/kernel/core_cia.c @@ -754,6 +754,364 @@ cia_pci_clr_err(void) *(vip)CIA_IOC_CIA_ERR; /* re-read to force write. */ } +static void +cia_decode_pci_error(struct el_CIA_sysdata_mcheck *cia, const char *msg) +{ + static const char * const pci_cmd_desc[16] = { + "Interrupt Acknowledge", "Special Cycle", "I/O Read", + "I/O Write", "Reserved 0x4", "Reserved 0x5", "Memory Read", + "Memory Write", "Reserved 0x8", "Reserved 0x9", + "Configuration Read", "Configuration Write", + "Memory Read Multiple", "Dual Address Cycle", + "Memory Read Line", "Memory Write and Invalidate" + }; + + if (cia->cia_err & (CIA_ERR_COR_ERR + | CIA_ERR_UN_COR_ERR + | CIA_ERR_MEM_NEM + | CIA_ERR_PA_PTE_INV)) { + static const char * const window_desc[6] = { + "No window active", "Window 0 hit", "Window 1 hit", + "Window 2 hit", "Window 3 hit", "Monster window hit" + }; + + const char *window; + const char *cmd; + unsigned long addr, tmp; + int lock, dac; + + cmd = pci_cmd_desc[cia->pci_err0 & 0x7]; + lock = (cia->pci_err0 >> 4) & 1; + dac = (cia->pci_err0 >> 5) & 1; + + tmp = (cia->pci_err0 >> 8) & 0x1F; + tmp = ffs(tmp); + window = window_desc[tmp]; + + addr = cia->pci_err1; + if (dac) { + tmp = *(vip)CIA_IOC_PCI_W_DAC & 0xFFUL; + addr |= tmp << 32; + } + + printk(KERN_CRIT "CIA machine check: %s\n", msg); + printk(KERN_CRIT " DMA command: %s\n", cmd); + printk(KERN_CRIT " PCI address: %#010lx\n", addr); + printk(KERN_CRIT " %s, Lock: %d, DAC: %d\n", + window, lock, dac); + } else if (cia->cia_err & (CIA_ERR_PERR + | CIA_ERR_PCI_ADDR_PE + | CIA_ERR_RCVD_MAS_ABT + | CIA_ERR_RCVD_TAR_ABT + | CIA_ERR_IOA_TIMEOUT)) { + static const char * const master_st_desc[16] = { + "Idle", "Drive bus", "Address step cycle", + "Address cycle", "Data cycle", "Last read data cycle", + "Last write data cycle", "Read stop cycle", + "Write stop cycle", "Read turnaround cycle", + "Write turnaround cycle", "Reserved 0xB", + "Reserved 0xC", "Reserved 0xD", "Reserved 0xE", + "Unknown state" + }; + static const char * const target_st_desc[16] = { + "Idle", "Busy", "Read data cycle", "Write data cycle", + "Read stop cycle", "Write stop cycle", + "Read turnaround cycle", "Write turnaround cycle", + "Read wait cycle", "Write wait cycle", + "Reserved 0xA", "Reserved 0xB", "Reserved 0xC", + "Reserved 0xD", "Reserved 0xE", "Unknown state" + }; + + const char *cmd; + const char *master, *target; + unsigned long addr, tmp; + int dac; + + master = master_st_desc[(cia->pci_err0 >> 16) & 0xF]; + target = target_st_desc[(cia->pci_err0 >> 20) & 0xF]; + cmd = pci_cmd_desc[(cia->pci_err0 >> 24) & 0xF]; + dac = (cia->pci_err0 >> 28) & 1; + + addr = cia->pci_err2; + if (dac) { + tmp = *(volatile int *)CIA_IOC_PCI_W_DAC & 0xFFUL; + addr |= tmp << 32; + } + + printk(KERN_CRIT "CIA machine check: %s\n", msg); + printk(KERN_CRIT " PCI command: %s\n", cmd); + printk(KERN_CRIT " Master state: %s, Target state: %s\n", + master, target); + printk(KERN_CRIT " PCI address: %#010lx, DAC: %d\n", + addr, dac); + } else { + printk(KERN_CRIT "CIA machine check: %s\n", msg); + printk(KERN_CRIT " Unknown PCI error\n"); + printk(KERN_CRIT " PCI_ERR0 = %#08lx", cia->pci_err0); + printk(KERN_CRIT " PCI_ERR1 = %#08lx", cia->pci_err1); + printk(KERN_CRIT " PCI_ERR2 = %#08lx", cia->pci_err2); + } +} + +static void +cia_decode_mem_error(struct el_CIA_sysdata_mcheck *cia, const char *msg) +{ + unsigned long mem_port_addr; + unsigned long mem_port_mask; + const char *mem_port_cmd; + const char *seq_state; + const char *set_select; + unsigned long tmp; + + /* If this is a DMA command, also decode the PCI bits. */ + if ((cia->mem_err1 >> 20) & 1) + cia_decode_pci_error(cia, msg); + else + printk(KERN_CRIT "CIA machine check: %s\n", msg); + + mem_port_addr = cia->mem_err0 & 0xfffffff0; + mem_port_addr |= (cia->mem_err1 & 0x83UL) << 32; + + mem_port_mask = (cia->mem_err1 >> 12) & 0xF; + + tmp = (cia->mem_err1 >> 8) & 0xF; + tmp |= ((cia->mem_err1 >> 20) & 1) << 4; + if ((tmp & 0x1E) == 0x06) + mem_port_cmd = "WRITE BLOCK or WRITE BLOCK LOCK"; + else if ((tmp & 0x1C) == 0x08) + mem_port_cmd = "READ MISS or READ MISS MODIFY"; + else if (tmp == 0x1C) + mem_port_cmd = "BC VICTIM"; + else if ((tmp & 0x1E) == 0x0E) + mem_port_cmd = "READ MISS MODIFY"; + else if ((tmp & 0x1C) == 0x18) + mem_port_cmd = "DMA READ or DMA READ MODIFY"; + else if ((tmp & 0x1E) == 0x12) + mem_port_cmd = "DMA WRITE"; + else + mem_port_cmd = "Unknown"; + + tmp = (cia->mem_err1 >> 16) & 0xF; + switch (tmp) { + case 0x0: + seq_state = "Idle"; + break; + case 0x1: + seq_state = "DMA READ or DMA WRITE"; + break; + case 0x2: case 0x3: + seq_state = "READ MISS (or READ MISS MODIFY) with victim"; + break; + case 0x4: case 0x5: case 0x6: + seq_state = "READ MISS (or READ MISS MODIFY) with no victim"; + break; + case 0x8: case 0x9: case 0xB: + seq_state = "Refresh"; + break; + case 0xC: + seq_state = "Idle, waiting for DMA pending read"; + break; + case 0xE: case 0xF: + seq_state = "Idle, ras precharge"; + break; + default: + seq_state = "Unknown"; + break; + } + + tmp = (cia->mem_err1 >> 24) & 0x1F; + switch (tmp) { + case 0x00: set_select = "Set 0 selected"; break; + case 0x01: set_select = "Set 1 selected"; break; + case 0x02: set_select = "Set 2 selected"; break; + case 0x03: set_select = "Set 3 selected"; break; + case 0x04: set_select = "Set 4 selected"; break; + case 0x05: set_select = "Set 5 selected"; break; + case 0x06: set_select = "Set 6 selected"; break; + case 0x07: set_select = "Set 7 selected"; break; + case 0x08: set_select = "Set 8 selected"; break; + case 0x09: set_select = "Set 9 selected"; break; + case 0x0A: set_select = "Set A selected"; break; + case 0x0B: set_select = "Set B selected"; break; + case 0x0C: set_select = "Set C selected"; break; + case 0x0D: set_select = "Set D selected"; break; + case 0x0E: set_select = "Set E selected"; break; + case 0x0F: set_select = "Set F selected"; break; + case 0x10: set_select = "No set selected"; break; + case 0x1F: set_select = "Refresh cycle"; break; + default: set_select = "Unknown"; break; + } + + printk(KERN_CRIT " Memory port command: %s\n", mem_port_cmd); + printk(KERN_CRIT " Memory port address: %#010lx, mask: %#lx\n", + mem_port_addr, mem_port_mask); + printk(KERN_CRIT " Memory sequencer state: %s\n", seq_state); + printk(KERN_CRIT " Memory set: %s\n", set_select); +} + +static void +cia_decode_ecc_error(struct el_CIA_sysdata_mcheck *cia, const char *msg) +{ + long syn; + long i; + const char *fmt; + + cia_decode_mem_error(cia, msg); + + syn = cia->cia_syn & 0xff; + if (syn == (syn & -syn)) { + fmt = KERN_CRIT " ECC syndrome %#x -- check bit %d\n"; + i = ffs(syn) - 1; + } else { + static unsigned char const data_bit[64] = { + 0xCE, 0xCB, 0xD3, 0xD5, + 0xD6, 0xD9, 0xDA, 0xDC, + 0x23, 0x25, 0x26, 0x29, + 0x2A, 0x2C, 0x31, 0x34, + 0x0E, 0x0B, 0x13, 0x15, + 0x16, 0x19, 0x1A, 0x1C, + 0xE3, 0xE5, 0xE6, 0xE9, + 0xEA, 0xEC, 0xF1, 0xF4, + 0x4F, 0x4A, 0x52, 0x54, + 0x57, 0x58, 0x5B, 0x5D, + 0xA2, 0xA4, 0xA7, 0xA8, + 0xAB, 0xAD, 0xB0, 0xB5, + 0x8F, 0x8A, 0x92, 0x94, + 0x97, 0x98, 0x9B, 0x9D, + 0x62, 0x64, 0x67, 0x68, + 0x6B, 0x6D, 0x70, 0x75 + }; + + for (i = 0; i < 64; ++i) + if (data_bit[i] == syn) + break; + + if (i < 64) + fmt = KERN_CRIT " ECC syndrome %#x -- data bit %d\n"; + else + fmt = KERN_CRIT " ECC syndrome %#x -- unknown bit\n"; + } + + printk (fmt, syn, i); +} + +static void +cia_decode_parity_error(struct el_CIA_sysdata_mcheck *cia) +{ + static const char * const cmd_desc[16] = { + "NOP", "LOCK", "FETCH", "FETCH_M", "MEMORY BARRIER", + "SET DIRTY", "WRITE BLOCK", "WRITE BLOCK LOCK", + "READ MISS0", "READ MISS1", "READ MISS MOD0", + "READ MISS MOD1", "BCACHE VICTIM", "Spare", + "READ MISS MOD STC0", "READ MISS MOD STC1" + }; + + unsigned long addr; + unsigned long mask; + const char *cmd; + int par; + + addr = cia->cpu_err0 & 0xfffffff0; + addr |= (cia->cpu_err1 & 0x83UL) << 32; + cmd = cmd_desc[(cia->cpu_err1 >> 8) & 0xF]; + mask = (cia->cpu_err1 >> 12) & 0xF; + par = (cia->cpu_err1 >> 21) & 1; + + printk(KERN_CRIT "CIA machine check: System bus parity error\n"); + printk(KERN_CRIT " Command: %s, Parity bit: %d\n", cmd, par); + printk(KERN_CRIT " Address: %#010lx, Mask: %#lx\n", addr, mask); +} + +static int +cia_decode_mchk(unsigned long la_ptr) +{ + struct el_common *com; + struct el_CIA_sysdata_mcheck *cia; + int which; + + com = (void *)la_ptr; + cia = (void *)(la_ptr + com->sys_offset); + + if ((cia->cia_err & CIA_ERR_VALID) == 0) + return 0; + + which = cia->cia_err & 0xfff; + switch (ffs(which) - 1) { + case 0: /* CIA_ERR_COR_ERR */ + cia_decode_ecc_error(cia, "Corrected ECC error"); + break; + case 1: /* CIA_ERR_UN_COR_ERR */ + cia_decode_ecc_error(cia, "Uncorrected ECC error"); + break; + case 2: /* CIA_ERR_CPU_PE */ + cia_decode_parity_error(cia); + break; + case 3: /* CIA_ERR_MEM_NEM */ + cia_decode_mem_error(cia, "Access to nonexistent memory"); + break; + case 4: /* CIA_ERR_PCI_SERR */ + cia_decode_pci_error(cia, "PCI bus system error"); + break; + case 5: /* CIA_ERR_PERR */ + cia_decode_pci_error(cia, "PCI data parity error"); + break; + case 6: /* CIA_ERR_PCI_ADDR_PE */ + cia_decode_pci_error(cia, "PCI address parity error"); + break; + case 7: /* CIA_ERR_RCVD_MAS_ABT */ + cia_decode_pci_error(cia, "PCI master abort"); + break; + case 8: /* CIA_ERR_RCVD_TAR_ABT */ + cia_decode_pci_error(cia, "PCI target abort"); + break; + case 9: /* CIA_ERR_PA_PTE_INV */ + cia_decode_pci_error(cia, "PCI invalid PTE"); + break; + case 10: /* CIA_ERR_FROM_WRT_ERR */ + cia_decode_mem_error(cia, "Write to flash ROM attempted"); + break; + case 11: /* CIA_ERR_IOA_TIMEOUT */ + cia_decode_pci_error(cia, "I/O timeout"); + break; + } + + if (cia->cia_err & CIA_ERR_LOST_CORR_ERR) + printk(KERN_CRIT "CIA lost machine check: " + "Correctable ECC error\n"); + if (cia->cia_err & CIA_ERR_LOST_UN_CORR_ERR) + printk(KERN_CRIT "CIA lost machine check: " + "Uncorrectable ECC error\n"); + if (cia->cia_err & CIA_ERR_LOST_CPU_PE) + printk(KERN_CRIT "CIA lost machine check: " + "System bus parity error\n"); + if (cia->cia_err & CIA_ERR_LOST_MEM_NEM) + printk(KERN_CRIT "CIA lost machine check: " + "Access to nonexistent memory\n"); + if (cia->cia_err & CIA_ERR_LOST_PERR) + printk(KERN_CRIT "CIA lost machine check: " + "PCI data parity error\n"); + if (cia->cia_err & CIA_ERR_LOST_PCI_ADDR_PE) + printk(KERN_CRIT "CIA lost machine check: " + "PCI address parity error\n"); + if (cia->cia_err & CIA_ERR_LOST_RCVD_MAS_ABT) + printk(KERN_CRIT "CIA lost machine check: " + "PCI master abort\n"); + if (cia->cia_err & CIA_ERR_LOST_RCVD_TAR_ABT) + printk(KERN_CRIT "CIA lost machine check: " + "PCI target abort\n"); + if (cia->cia_err & CIA_ERR_LOST_PA_PTE_INV) + printk(KERN_CRIT "CIA lost machine check: " + "PCI invalid PTE\n"); + if (cia->cia_err & CIA_ERR_LOST_FROM_WRT_ERR) + printk(KERN_CRIT "CIA lost machine check: " + "Write to flash ROM attempted\n"); + if (cia->cia_err & CIA_ERR_LOST_IOA_TIMEOUT) + printk(KERN_CRIT "CIA lost machine check: " + "I/O timeout\n"); + + return 1; +} + void cia_machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs) @@ -769,30 +1127,7 @@ cia_machine_check(unsigned long vector, unsigned long la_ptr, mb(); expected = mcheck_expected(0); - if (!expected && vector == 0x660) { - struct el_common *com; - struct el_common_EV5_uncorrectable_mcheck *ev5; - struct el_CIA_sysdata_mcheck *cia; - - com = (void *)la_ptr; - ev5 = (void *)(la_ptr + com->proc_offset); - cia = (void *)(la_ptr + com->sys_offset); - - if (com->code == 0x202) { - printk(KERN_CRIT "CIA PCI machine check: code=%x\n" - " cpu_err0=%08x cpu_err1=%08x cia_err=%08x\n" - " cia_stat=%08x err_mask=%08x cia_syn=%08x\n" - " mem_err0=%08x mem_err1=%08x\n" - " pci_err0=%08x pci_err1=%08x pci_err2=%08x\n", - (int) com->code, - (int) cia->cpu_err0, (int) cia->cpu_err1, - (int) cia->cia_err, (int) cia->cia_stat, - (int) cia->err_mask, (int) cia->cia_syn, - (int) cia->mem_err0, (int) cia->mem_err1, - (int) cia->pci_err0, (int) cia->pci_err1, - (int) cia->pci_err2); - expected = 1; - } - } + if (!expected && vector == 0x660) + expected = cia_decode_mchk(la_ptr); process_mcheck_info(vector, la_ptr, regs, "CIA", expected); } diff --git a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c index 453766d2e229..03034874782f 100644 --- a/arch/alpha/kernel/core_irongate.c +++ b/arch/alpha/kernel/core_irongate.c @@ -28,12 +28,7 @@ #include "proto.h" #include "pci_impl.h" - -/* - * NOTE: Herein lie back-to-back mb instructions. They are magic. - * One plausible explanation is that the I/O controller does not properly - * handle the system transaction. Another involves timing. Ho hum. - */ +#undef DEBUG_IRONGATE /* define to enable verbose Irongate debug */ /* * BIOS32-style PCI interface: @@ -200,11 +195,12 @@ struct pci_ops irongate_pci_ops = write_dword: irongate_write_config_dword }; -#if 0 +#ifdef DEBUG_IRONGATE static void irongate_register_dump(const char *function_name) { printk("%s: Irongate registers:\n" + "\tFunction 0:\n" "\tdev_vendor\t0x%08x\n" "\tstat_cmd\t0x%08x\n" "\tclass\t\t0x%08x\n" @@ -249,7 +245,26 @@ irongate_register_dump(const char *function_name) "\tagpstat\t\t0x%08x\n" "\tagpcmd\t\t0x%08x\n" "\tagpva\t\t0x%08x\n" - "\tagpmode\t\t0x%08x\n", + "\tagpmode\t\t0x%08x\n" + + "\n\tFunction 1:\n" + "\tdev_vendor:\t0x%08x\n" + "\tcmd_status:\t0x%08x\n" + "\trevid_etc :\t0x%08x\n" + "\thtype_etc :\t0x%08x\n" + "\trsrvd0[0] :\t0x%08x\n" + "\trsrvd0[1] :\t0x%08x\n" + "\tbus_nmbers:\t0x%08x\n" + "\tio_baselim:\t0x%08x\n" + "\tmem_bselim:\t0x%08x\n" + "\tpf_baselib:\t0x%08x\n" + "\trsrvd1[0] :\t0x%08x\n" + "\trsrvd1[1] :\t0x%08x\n" + "\tio_baselim:\t0x%08x\n" + "\trsrvd2[0] :\t0x%08x\n" + "\trsrvd2[1] :\t0x%08x\n" + "\tinterrupt :\t0x%08x\n", + function_name, IRONGATE0->dev_vendor, IRONGATE0->stat_cmd, @@ -295,7 +310,23 @@ irongate_register_dump(const char *function_name) IRONGATE0->agpstat, IRONGATE0->agpcmd, IRONGATE0->agpva, - IRONGATE0->agpmode); + IRONGATE0->agpmode, + IRONGATE1->dev_vendor, + IRONGATE1->stat_cmd, + IRONGATE1->class, + IRONGATE1->htype, + IRONGATE1->rsrvd0[0], + IRONGATE1->rsrvd0[1], + IRONGATE1->busnos, + IRONGATE1->io_baselim_regs, + IRONGATE1->mem_baselim, + IRONGATE1->pfmem_baselim, + IRONGATE1->rsrvd1[0], + IRONGATE1->rsrvd1[1], + IRONGATE1->io_baselim, + IRONGATE1->rsrvd2[0], + IRONGATE1->rsrvd2[1], + IRONGATE1->interrupt ); } #else #define irongate_register_dump(x) diff --git a/arch/i386/defconfig b/arch/i386/defconfig index ce51570daee8..1a9a69b277b5 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -501,10 +501,6 @@ CONFIG_PCMCIA_SERIAL=y # # Multimedia devices # - -# -# Video For Linux -# # CONFIG_VIDEO_DEV is not set # diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c index b264c54a31a2..b71cf06f6146 100644 --- a/arch/i386/kernel/i387.c +++ b/arch/i386/kernel/i387.c @@ -279,7 +279,6 @@ static inline int save_i387_fsave( struct _fpstate *buf ) { struct task_struct *tsk = current; - unlazy_fpu( tsk ); tsk->thread.i387.fsave.status = tsk->thread.i387.fsave.swd; if ( __copy_to_user( buf, &tsk->thread.i387.fsave, sizeof(struct i387_fsave_struct) ) ) @@ -292,8 +291,6 @@ static inline int save_i387_fxsave( struct _fpstate *buf ) struct task_struct *tsk = current; int err = 0; - unlazy_fpu( tsk ); - if ( convert_fxsr_to_user( buf, &tsk->thread.i387.fxsave ) ) return -1; diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index e1b00a70253f..66e1bd9c21a5 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -982,7 +982,10 @@ void disable_IO_APIC(void) static void __init setup_ioapic_ids_from_mpc (void) { struct IO_APIC_reg_00 reg_00; + unsigned long phys_id_present_map = phys_cpu_present_map; int apic; + int i; + unsigned char old_id; /* * Set the IOAPIC ID to the value stored in the MPC table. @@ -992,6 +995,8 @@ static void __init setup_ioapic_ids_from_mpc (void) /* Read the register 0 value */ *(int *)®_00 = io_apic_read(apic, 0); + old_id = mp_ioapics[apic].mpc_apicid; + if (mp_ioapics[apic].mpc_apicid >= 0xf) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", apic, mp_ioapics[apic].mpc_apicid); @@ -1000,6 +1005,35 @@ static void __init setup_ioapic_ids_from_mpc (void) mp_ioapics[apic].mpc_apicid = reg_00.ID; } + /* + * Sanity check, is the ID really free? Every APIC in a + * system must have a unique ID or we get lots of nice + * 'stuck on smp_invalidate_needed IPI wait' messages. + */ + if (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid)) { + printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", + apic, mp_ioapics[apic].mpc_apicid); + for (i = 0; i < 0xf; i++) + if (!(phys_id_present_map & (1 << i))) + break; + if (i >= 0xf) + panic("Max APIC ID exceeded!\n"); + printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", + i); + phys_id_present_map |= 1 << i; + mp_ioapics[apic].mpc_apicid = i; + } + + /* + * We need to adjust the IRQ routing table + * if the ID changed. + */ + if (old_id != mp_ioapics[apic].mpc_apicid) + for (i = 0; i < mp_irq_entries; i++) + if (mp_irqs[i].mpc_dstapic == old_id) + mp_irqs[i].mpc_dstapic + = mp_ioapics[apic].mpc_apicid; + /* * Read the right value from the MPC table and * write it into the ID register. @@ -1007,15 +1041,6 @@ static void __init setup_ioapic_ids_from_mpc (void) printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", mp_ioapics[apic].mpc_apicid); - /* - * Sanity check, is the ID really free? Every APIC in the - * system must have a unique ID or we get lots of nice - * 'stuck on smp_invalidate_needed IPI wait' messages. - */ - if (phys_cpu_present_map & (1<signal, signr); + sigaddset(¤t->pending.signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index f2aa6cae4398..a08842491500 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.106 2000/08/05 10:48:40 davem Exp $ +/* $Id: irq.c,v 1.107 2000/08/26 02:42:28 anton Exp $ * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the * Sparc the IRQ's are basically 'cast in stone' * and you are supposed to probe the prom's device @@ -8,7 +8,7 @@ * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1995 Pete A. Zaitcev (zaitcev@metabyte.com) * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) - * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 1998-2000 Anton Blanchard (anton@linuxcare.com) */ #include @@ -196,41 +196,29 @@ void free_irq(unsigned int irq, void *dev_id) } #ifdef CONFIG_SMP -/* SMP interrupt locking on Sparc. */ /* Who has global_irq_lock. */ unsigned char global_irq_holder = NO_PROC_ID; -/* This protects IRQ's. */ -spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED; - -/* Global IRQ locking depth. */ -atomic_t global_irq_count = ATOMIC_INIT(0); - void smp_show_backtrace_all_cpus(void); void show_backtrace(void); -#define MAXCOUNT 100000000 #define VERBOSE_DEBUG_IRQLOCK +#define MAXCOUNT 100000000 static void show(char * str) { - int i; int cpu = smp_processor_id(); + int i; printk("\n%s, CPU %d:\n", str, cpu); - printk("irq: %d [ ", atomic_read(&global_irq_count)); - - for (i = 0; i < NR_CPUS; i++) { - printk("%d ", local_irq_count(i)); - } - printk("]\n"); - - printk("bh: %d [ ", (spin_is_locked(&global_bh_lock) ? 1 : 0)); - - for (i = 0; i < NR_CPUS; i++) { - printk("%d ", local_bh_count(cpu)); - } + printk("irq: %d [ ", irqs_running()); + for (i = 0; i < smp_num_cpus; i++) + printk("%u ", __brlock_array[i][BR_GLOBALIRQ_LOCK]); + printk("]\nbh: %d [ ", + (spin_is_locked(&global_bh_lock) ? 1 : 0)); + for (i = 0; i < smp_num_cpus; i++) + printk("%u ", local_bh_count(i)); printk("]\n"); #ifdef VERBOSE_DEBUG_IRQLOCK @@ -240,48 +228,11 @@ static void show(char * str) #endif } + /* * We have to allow irqs to arrive between __sti and __cli */ -#define SYNC_OTHER_CORES(x) udelay(x+1) - -static inline void wait_on_irq(int cpu) -{ - int count = MAXCOUNT; - - for (;;) { - /* - * Wait until all interrupts are gone. Wait - * for bottom half handlers unless we're - * already executing in one.. - */ - if (!atomic_read(&global_irq_count)) { - if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) - break; - } - - /* Duh, we have to loop. Release the lock to avoid deadlocks */ - spin_unlock(&global_irq_lock); - - for (;;) { - if (!--count) { - show("wait_on_irq"); - count = ~0; - } - __sti(); - SYNC_OTHER_CORES(cpu); - __cli(); - if (atomic_read(&global_irq_count)) - continue; - if (spin_is_locked (&global_irq_lock)) - continue; - if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) - continue; - if (spin_trylock(&global_irq_lock)) - break; - } - } -} +#define SYNC_OTHER_CORES(x) barrier() /* * This is called when we want to synchronize with @@ -292,8 +243,7 @@ static inline void wait_on_irq(int cpu) */ void synchronize_irq(void) { - if (atomic_read(&global_irq_count)) { - /* Stupid approach */ + if (irqs_running()) { cli(); sti(); } @@ -301,32 +251,37 @@ void synchronize_irq(void) static inline void get_irqlock(int cpu) { - int count = MAXCOUNT; + int count; - if (!spin_trylock(&global_irq_lock)) { - /* do we already hold the lock? */ - if ((unsigned char) cpu == global_irq_holder) - return; - /* Uhhuh.. Somebody else got it. Wait.. */ - do { - while (spin_is_locked(&global_irq_lock)) { - if (!--count) { - show("get_irqlock"); - count = ~0; - } - barrier(); + if ((unsigned char)cpu == global_irq_holder) + return; + + count = MAXCOUNT; +again: + br_write_lock(BR_GLOBALIRQ_LOCK); + for (;;) { + spinlock_t *lock; + + if (!irqs_running() && + (local_bh_count(smp_processor_id()) || !spin_is_locked(&global_bh_lock))) + break; + + br_write_unlock(BR_GLOBALIRQ_LOCK); + lock = &__br_write_locks[BR_GLOBALIRQ_LOCK].lock; + while (irqs_running() || + spin_is_locked(lock) || + (!local_bh_count(smp_processor_id()) && spin_is_locked(&global_bh_lock))) { + if (!--count) { + show("get_irqlock"); + count = (~0 >> 1); } - } while (!spin_trylock(&global_irq_lock)); + __sti(); + SYNC_OTHER_CORES(cpu); + __cli(); + } + goto again; } - /* - * We also to make sure that nobody else is running - * in an interrupt context. - */ - wait_on_irq(cpu); - /* - * Ok, finally.. - */ global_irq_holder = cpu; } @@ -344,7 +299,7 @@ static inline void get_irqlock(int cpu) */ void __global_cli(void) { - unsigned int flags; + unsigned long flags; __save_flags(flags); @@ -374,9 +329,7 @@ void __global_sti(void) */ unsigned long __global_save_flags(void) { - int retval; - int local_enabled = 0; - unsigned long flags; + unsigned long flags, local_enabled, retval; __save_flags(flags); diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index e05b20f4e731..a1742c21d3f2 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -1,4 +1,4 @@ -/* $Id: sparc_ksyms.c,v 1.102 2000/08/05 10:48:40 davem Exp $ +/* $Id: sparc_ksyms.c,v 1.103 2000/08/26 02:42:28 anton Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -111,13 +111,6 @@ EXPORT_SYMBOL_PRIVATE(_rw_read_enter); EXPORT_SYMBOL_PRIVATE(_rw_read_exit); EXPORT_SYMBOL_PRIVATE(_rw_write_enter); #endif -#ifdef CONFIG_SMP -EXPORT_SYMBOL(__global_save_flags); -EXPORT_SYMBOL(__global_restore_flags); -EXPORT_SYMBOL(__global_sti); -EXPORT_SYMBOL(__global_cli); -#endif - /* rw semaphores */ EXPORT_SYMBOL_NOVERS(___down_read); EXPORT_SYMBOL_NOVERS(___down_write); @@ -137,14 +130,17 @@ EXPORT_SYMBOL_PRIVATE(_change_bit); EXPORT_SYMBOL_PRIVATE(_set_le_bit); EXPORT_SYMBOL_PRIVATE(_clear_le_bit); -/* IRQ implementation. */ #ifdef CONFIG_SMP +/* Kernel wide locking */ EXPORT_SYMBOL(kernel_flag); + +/* IRQ implementation. */ EXPORT_SYMBOL(global_irq_holder); -EXPORT_SYMBOL(global_irq_lock); -EXPORT_SYMBOL(global_bh_lock); -EXPORT_SYMBOL(global_irq_count); EXPORT_SYMBOL(synchronize_irq); +EXPORT_SYMBOL(__global_cli); +EXPORT_SYMBOL(__global_sti); +EXPORT_SYMBOL(__global_save_flags); +EXPORT_SYMBOL(__global_restore_flags); #endif EXPORT_SYMBOL(udelay); diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 4f5bd16c5b31..408d59cbf981 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.221 2000/08/14 00:46:13 anton Exp $ +/* $Id: srmmu.c,v 1.222 2000/08/29 08:59:23 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -1323,8 +1323,8 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma, mapping = file->f_dentry->d_inode->i_mapping; offset = (address & PAGE_MASK) - vma->vm_start; spin_lock(&mapping->i_shared_lock); - vmaring = mapping->i_mmap; - do { + vmaring = mapping->i_mmap_shared; + if (vmaring != NULL) do { /* Do not mistake ourselves as another mapping. */ if(vmaring == vma) continue; diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 66bc3af7b811..a99ce736e55c 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.198 2000/08/14 00:46:13 anton Exp $ +/* $Id: sun4c.c,v 1.199 2000/08/29 08:59:23 davem Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -2404,8 +2404,8 @@ static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long addr mapping = vma->vm_file->f_dentry->d_inode->i_mapping; spin_lock(&mapping->i_shared_lock); - vmaring = mapping->i_mmap; - do { + vmaring = mapping->i_mmap_shared; + if (vmaring != NULL) do { unsigned long vaddr = vmaring->vm_start + offset; unsigned long start; diff --git a/arch/sparc/prom/console.c b/arch/sparc/prom/console.c index c2b857459c52..bf61ff1a7a81 100644 --- a/arch/sparc/prom/console.c +++ b/arch/sparc/prom/console.c @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.22 2000/02/08 20:24:23 davem Exp $ +/* $Id: console.c,v 1.23 2000/08/26 02:38:03 anton Exp $ * console.c: Routines that deal with sending and receiving IO * to/from the current console device using the PROM. * @@ -30,7 +30,7 @@ prom_nbgetchar(void) int i = -1; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: case PROM_SUN4: @@ -49,7 +49,7 @@ prom_nbgetchar(void) break; }; restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return i; /* Ugh, we could spin forever on unsupported proms ;( */ } @@ -63,7 +63,7 @@ prom_nbputchar(char c) unsigned long flags; int i = -1; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: case PROM_SUN4: @@ -82,7 +82,7 @@ prom_nbputchar(char c) break; }; restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return i; /* Ugh, we could spin forever on unsupported proms ;( */ } @@ -125,10 +125,10 @@ prom_query_input_device() return PROMDEV_I_UNK; }; case PROM_V3: - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); if(prom_node_has_property(st_p, "keyboard")) return PROMDEV_IKBD; if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) { @@ -174,10 +174,10 @@ prom_query_output_device() break; case PROM_V2: case PROM_V3: - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb)); if (propl >= 0 && propl == sizeof("display") && strncmp("display", propb, sizeof("display")) == 0) diff --git a/arch/sparc/prom/devmap.c b/arch/sparc/prom/devmap.c index 463b07527acc..eb12073578ad 100644 --- a/arch/sparc/prom/devmap.c +++ b/arch/sparc/prom/devmap.c @@ -1,4 +1,4 @@ -/* $Id: devmap.c,v 1.6 1998/03/09 14:04:23 jj Exp $ +/* $Id: devmap.c,v 1.7 2000/08/26 02:38:03 anton Exp $ * promdevmap.c: Map device/IO areas to virtual addresses. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -29,13 +29,13 @@ prom_mapio(char *vhint, int ios, unsigned int paddr, unsigned int num_bytes) unsigned long flags; char *ret; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); if((num_bytes == 0) || (paddr == 0)) ret = (char *) 0x0; else ret = (*(romvec->pv_v2devops.v2_dumb_mmap))(vhint, ios, paddr, num_bytes); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return ret; } @@ -46,9 +46,9 @@ prom_unmapio(char *vaddr, unsigned int num_bytes) unsigned long flags; if(num_bytes == 0x0) return; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return; } diff --git a/arch/sparc/prom/devops.c b/arch/sparc/prom/devops.c index 5a58efa0bb27..61919b54f6cc 100644 --- a/arch/sparc/prom/devops.c +++ b/arch/sparc/prom/devops.c @@ -1,4 +1,4 @@ -/* $Id: devops.c,v 1.12 2000/01/29 01:09:12 anton Exp $ +/* $Id: devops.c,v 1.13 2000/08/26 02:38:03 anton Exp $ * devops.c: Device operations using the PROM. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -21,7 +21,7 @@ prom_devopen(char *dstr) { int handle; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: handle = (*(romvec->pv_v0devops.v0_devopen))(dstr); @@ -36,7 +36,7 @@ prom_devopen(char *dstr) break; }; restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return handle; } @@ -46,7 +46,7 @@ int prom_devclose(int dhandle) { unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: (*(romvec->pv_v0devops.v0_devclose))(dhandle); @@ -59,7 +59,7 @@ prom_devclose(int dhandle) break; }; restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return 0; } @@ -70,7 +70,7 @@ void prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) { unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: (*(romvec->pv_v0devops.v0_seekdev))(dhandle, seekhi, seeklo); @@ -83,7 +83,7 @@ prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) break; }; restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return; } diff --git a/arch/sparc/prom/misc.c b/arch/sparc/prom/misc.c index 3c2f2434df33..86ce39910198 100644 --- a/arch/sparc/prom/misc.c +++ b/arch/sparc/prom/misc.c @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.17 1998/07/21 10:36:22 jj Exp $ +/* $Id: misc.c,v 1.18 2000/08/26 02:38:03 anton Exp $ * misc.c: Miscellaneous prom functions that don't belong * anywhere else. * @@ -15,16 +15,18 @@ extern void restore_current(void); +spinlock_t prom_lock = SPIN_LOCK_UNLOCKED; + /* Reset and reboot the machine with the command 'bcommand'. */ void prom_reboot(char *bcommand) { unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_reboot))(bcommand); /* Never get here. */ restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); } /* Forth evaluate the expression contained in 'fstring'. */ @@ -34,13 +36,13 @@ prom_feval(char *fstring) unsigned long flags; if(!fstring || fstring[0] == 0) return; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); if(prom_vers == PROM_V0) (*(romvec->pv_fortheval.v0_eval))(strlen(fstring), fstring); else (*(romvec->pv_fortheval.v2_eval))(fstring); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); } /* We want to do this more nicely some day. */ @@ -66,10 +68,10 @@ prom_cmdline(void) prom_palette (1); #endif install_obp_ticker(); - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_abort))(); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); install_linux_ticker(); #ifdef CONFIG_SUN_AUXIO TURN_ON_LED; @@ -88,11 +90,11 @@ prom_halt(void) { unsigned long flags; again: - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_halt))(); /* Never get here. */ restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); goto again; /* PROM is out to get me -DaveM */ } diff --git a/arch/sparc/prom/mp.c b/arch/sparc/prom/mp.c index ba624673fe5a..92fe3739fdb8 100644 --- a/arch/sparc/prom/mp.c +++ b/arch/sparc/prom/mp.c @@ -1,4 +1,4 @@ -/* $Id: mp.c,v 1.11 2000/01/29 01:09:12 anton Exp $ +/* $Id: mp.c,v 1.12 2000/08/26 02:38:03 anton Exp $ * mp.c: OpenBoot Prom Multiprocessor support routines. Don't call * these on a UP or else you will halt and catch fire. ;) * @@ -25,7 +25,7 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha int ret; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: case PROM_V2: @@ -37,7 +37,7 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha break; }; restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return ret; } @@ -51,7 +51,7 @@ prom_stopcpu(int cpunode) int ret; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: case PROM_V2: @@ -63,7 +63,7 @@ prom_stopcpu(int cpunode) break; }; restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return ret; } @@ -77,7 +77,7 @@ prom_idlecpu(int cpunode) int ret; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: case PROM_V2: @@ -89,7 +89,7 @@ prom_idlecpu(int cpunode) break; }; restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return ret; } @@ -103,7 +103,7 @@ prom_restartcpu(int cpunode) int ret; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: case PROM_V2: @@ -115,7 +115,7 @@ prom_restartcpu(int cpunode) break; }; restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return ret; } diff --git a/arch/sparc/prom/segment.c b/arch/sparc/prom/segment.c index 62b3f85425ec..09d6460165ab 100644 --- a/arch/sparc/prom/segment.c +++ b/arch/sparc/prom/segment.c @@ -1,4 +1,4 @@ -/* $Id: segment.c,v 1.6 1998/03/09 14:04:27 jj Exp $ +/* $Id: segment.c,v 1.7 2000/08/26 02:38:03 anton Exp $ * segment.c: Prom routine to map segments in other contexts before * a standalone is completely mapped. This is for sun4 and * sun4c architectures only. @@ -21,9 +21,9 @@ void prom_putsegment(int ctx, unsigned long vaddr, int segment) { unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_setctxt))(ctx, (char *) vaddr, segment); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return; } diff --git a/arch/sparc/prom/tree.c b/arch/sparc/prom/tree.c index 2e79057d86f6..adfe6e75a721 100644 --- a/arch/sparc/prom/tree.c +++ b/arch/sparc/prom/tree.c @@ -1,4 +1,4 @@ -/* $Id: tree.c,v 1.25 1998/09/17 11:04:58 jj Exp $ +/* $Id: tree.c,v 1.26 2000/08/26 02:38:03 anton Exp $ * tree.c: Basic device tree traversal/scanning for the Linux * prom library. * @@ -26,10 +26,10 @@ int __prom_getchild(int node) unsigned long flags; int cnode; - save_and_cli(flags); + spin_lock_irqsave(&prom_lock, flags); cnode = prom_nodeops->no_child(node); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return cnode; } @@ -57,10 +57,10 @@ int __prom_getsibling(int node) unsigned long flags; int cnode; - save_and_cli(flags); + spin_lock_irqsave(&prom_lock, flags); cnode = prom_nodeops->no_nextnode(node); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return cnode; } @@ -93,10 +93,10 @@ int prom_getproplen(int node, char *prop) if((!node) || (!prop)) return -1; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); ret = prom_nodeops->no_proplen(node, prop); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return ret; } @@ -113,10 +113,10 @@ int prom_getproperty(int node, char *prop, char *buffer, int bufsize) if((plen > bufsize) || (plen == 0) || (plen == -1)) return -1; /* Ok, things seem all right. */ - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); ret = prom_nodeops->no_getprop(node, prop, buffer); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return ret; } @@ -226,10 +226,10 @@ char * __prom_nextprop(int node, char * oprop) unsigned long flags; char *prop; - save_and_cli(flags); + spin_lock_irqsave(&prom_lock, flags); prop = prom_nodeops->no_nextprop(node, oprop); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return prop; } @@ -325,10 +325,10 @@ int prom_setprop(int node, char *pname, char *value, int size) if(size == 0) return 0; if((pname == 0) || (value == 0)) return 0; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); ret = prom_nodeops->no_setprop(node, pname, value, size); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); return ret; } @@ -337,10 +337,10 @@ int prom_inst2pkg(int inst) int node; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&prom_lock, flags); node = (*romvec->pv_v2devops.v2_inst2pkg)(inst); restore_current(); - restore_flags(flags); + spin_unlock_irqrestore(&prom_lock, flags); if (node == -1) return 0; return node; } diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 7f2e21a512e6..9e1c652461a4 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.91 2000/08/05 10:48:40 davem Exp $ +/* $Id: irq.c,v 1.92 2000/08/26 02:42:28 anton Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -608,7 +608,7 @@ again: spin_is_locked(lock) || (!local_bh_count(smp_processor_id()) && spin_is_locked(&global_bh_lock))) { if (!--count) { - show("wait_on_irq"); + show("get_irqlock"); count = (~0 >> 1); } __sti(); diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index e869af4e62e3..235d3488931b 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.45 2000/07/30 23:12:24 davem Exp $ +/* $Id: sys_sparc.c,v 1.46 2000/08/29 07:01:54 davem Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -398,13 +398,18 @@ asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, return -EINVAL; if (new_p == (utrap_handler_t)(long)UTH_NOCHANGE) { if (old_p) { - if (!current->thread.utraps) - put_user_ret(NULL, old_p, -EFAULT); - else - put_user_ret((utrap_handler_t)(current->thread.utraps[type]), old_p, -EFAULT); + if (!current->thread.utraps) { + if (put_user(NULL, old_p)) + return -EFAULT; + } else { + if (put_user((utrap_handler_t)(current->thread.utraps[type]), old_p)) + return -EFAULT; + } + } + if (old_d) { + if (put_user(NULL, old_d)) + return -EFAULT; } - if (old_d) - put_user_ret(NULL, old_d, -EFAULT); return 0; } if (!current->thread.utraps) { @@ -431,11 +436,14 @@ asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, UT_TRAP_INSTRUCTION_31*sizeof(long)); } } - if (old_p) - put_user_ret((utrap_handler_t)(current->thread.utraps[type]), - old_p, -EFAULT); - if (old_d) - put_user_ret(NULL, old_d, -EFAULT); + if (old_p) { + if (put_user((utrap_handler_t)(current->thread.utraps[type]), old_p)) + return -EFAULT; + } + if (old_d) { + if (put_user(NULL, old_d)) + return -EFAULT; + } current->thread.utraps[type] = (long)new_p; return 0; diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index 3cf5b6883c0b..e80d6b13fac1 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -1,4 +1,4 @@ -/* $Id: fs.c,v 1.22 2000/07/28 12:15:02 davem Exp $ +/* $Id: fs.c,v 1.23 2000/08/29 07:01:54 davem Exp $ * fs.c: fs related syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -612,20 +612,25 @@ asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg) case SOL_F_SETLKW: cmd = F_SETLKW; break; } - get_user_ret (f.l_type, &((struct sol_flock *)A(arg))->l_type, -EFAULT); - __get_user_ret (f.l_whence, &((struct sol_flock *)A(arg))->l_whence, -EFAULT); - __get_user_ret (f.l_start, &((struct sol_flock *)A(arg))->l_start, -EFAULT); - __get_user_ret (f.l_len, &((struct sol_flock *)A(arg))->l_len, -EFAULT); - __get_user_ret (f.l_pid, &((struct sol_flock *)A(arg))->l_sysid, -EFAULT); + if (get_user (f.l_type, &((struct sol_flock *)A(arg))->l_type) || + __get_user (f.l_whence, &((struct sol_flock *)A(arg))->l_whence) || + __get_user (f.l_start, &((struct sol_flock *)A(arg))->l_start) || + __get_user (f.l_len, &((struct sol_flock *)A(arg))->l_len) || + __get_user (f.l_pid, &((struct sol_flock *)A(arg))->l_sysid)) + return -EFAULT; + set_fs(KERNEL_DS); ret = sys_fcntl(fd, cmd, (unsigned long)&f); set_fs(old_fs); - __put_user_ret (f.l_type, &((struct sol_flock *)A(arg))->l_type, -EFAULT); - __put_user_ret (f.l_whence, &((struct sol_flock *)A(arg))->l_whence, -EFAULT); - __put_user_ret (f.l_start, &((struct sol_flock *)A(arg))->l_start, -EFAULT); - __put_user_ret (f.l_len, &((struct sol_flock *)A(arg))->l_len, -EFAULT); - __put_user_ret (f.l_pid, &((struct sol_flock *)A(arg))->l_pid, -EFAULT); - __put_user_ret (0, &((struct sol_flock *)A(arg))->l_sysid, -EFAULT); + + if (__put_user (f.l_type, &((struct sol_flock *)A(arg))->l_type) || + __put_user (f.l_whence, &((struct sol_flock *)A(arg))->l_whence) || + __put_user (f.l_start, &((struct sol_flock *)A(arg))->l_start) || + __put_user (f.l_len, &((struct sol_flock *)A(arg))->l_len) || + __put_user (f.l_pid, &((struct sol_flock *)A(arg))->l_pid) || + __put_user (0, &((struct sol_flock *)A(arg))->l_sysid)) + return -EFAULT; + return ret; } case SOL_F_FREESP: @@ -634,7 +639,9 @@ asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg) int (*sys_newftruncate)(unsigned int, unsigned long)= (int (*)(unsigned int, unsigned long))SYS(ftruncate); - get_user_ret(length, &((struct sol_flock*)A(arg))->l_start, -EFAULT); + if (get_user(length, &((struct sol_flock*)A(arg))->l_start)) + return -EFAULT; + return sys_newftruncate(fd, length); } }; diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index a7edd1876c6d..ca8bf25f3915 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.29 2000/08/14 23:50:31 anton Exp $ +/* $Id: misc.c,v 1.30 2000/08/29 07:01:54 davem Exp $ * misc.c: Miscelaneous syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -139,12 +139,14 @@ asmlinkage int solaris_brk(u32 brk) int i, len = (countfrom) ? \ ((sizeof(to) > sizeof(from) ? \ sizeof(from) : sizeof(to))) : sizeof(to); \ - copy_to_user_ret(to, from, len, -EFAULT); \ + if (copy_to_user(to, from, len)) \ + return -EFAULT; \ if (dotchop) \ for (p=from,i=0; *p && *p != '.' && --len; p++,i++); \ else \ i = len - 1; \ - __put_user_ret('\0', (char *)(to+i), -EFAULT); \ + if (__put_user('\0', (char *)(to+i))) \ + return -EFAULT; \ } struct sol_uname { @@ -297,10 +299,13 @@ asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count) } len = strlen(r) + 1; if (count < len) { - copy_to_user_ret((char *)A(buf), r, count - 1, -EFAULT); - __put_user_ret(0, (char *)A(buf) + count - 1, -EFAULT); - } else - copy_to_user_ret((char *)A(buf), r, len, -EFAULT); + if (copy_to_user((char *)A(buf), r, count - 1) || + __put_user(0, (char *)A(buf) + count - 1)) + return -EFAULT; + } else { + if (copy_to_user((char *)A(buf), r, len)) + return -EFAULT; + } return len; } diff --git a/arch/sparc64/solaris/signal.c b/arch/sparc64/solaris/signal.c index 7105bc05ce2b..a399238f58ce 100644 --- a/arch/sparc64/solaris/signal.c +++ b/arch/sparc64/solaris/signal.c @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.5 1997/12/15 15:04:59 jj Exp $ +/* $Id: signal.c,v 1.6 2000/08/29 07:01:54 davem Exp $ * signal.c: Signal emulation for Solaris * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -368,9 +368,13 @@ asmlinkage int solaris_waitid(int idtype, s32 pid, u32 info, int options) if (info) { struct sol_siginfo *s = (struct sol_siginfo *)A(info); - if (get_user (status, (unsigned int *)A(info))) return -EFAULT; - __put_user_ret (SOLARIS_SIGCLD, &s->si_signo, -EFAULT); - __put_user_ret (ret, &s->_data._proc._pid, -EFAULT); + if (get_user (status, (unsigned int *)A(info))) + return -EFAULT; + + if (__put_user (SOLARIS_SIGCLD, &s->si_signo) || + __put_user (ret, &s->_data._proc._pid)) + return -EFAULT; + switch (status & 0xff) { case 0: ret = SOLARIS_CLD_EXITED; status = (status >> 8) & 0xff; @@ -390,8 +394,10 @@ asmlinkage int solaris_waitid(int idtype, s32 pid, u32 info, int options) status = linux_to_solaris_signals[status & 0x7f]; break; } - __put_user_ret (ret, &s->si_code, -EFAULT); - __put_user_ret (status, &s->_data._proc._pdata._cld._status, -EFAULT); + + if (__put_user (ret, &s->si_code) || + __put_user (status, &s->_data._proc._pdata._cld._status)) + return -EFAULT; } return 0; } diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index dcd9d1036eac..16221e3fe96f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -118,6 +118,12 @@ * being used to store jiffies, which are unsigned longs). */ +/* + * 2000/08/28 -- Arnaldo Carvalho de Melo + * - get rid of check_region + * - s/suser/capable/ + */ + #define FLOPPY_SANITY_CHECK #undef FLOPPY_SILENT_DCL_CLEAR @@ -3497,7 +3503,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, /* permission checks */ if (((cmd & 0x40) && !(filp->f_mode & 2)) || - ((cmd & 0x80) && !suser())) + ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) return -EPERM; /* copyin */ @@ -4299,23 +4305,14 @@ static int floppy_grab_irq_and_dma(void) for (fdc=0; fdc< N_FDC; fdc++){ if (FDCS->address != -1){ - if (check_region(FDCS->address, 6) < 0 || - check_region(FDCS->address+7, 1) < 0) { + if (!request_region(FDCS->address, 6, "floppy")) { DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address); - fd_free_irq(); - fd_free_dma(); - while(--fdc >= 0) { - release_region(FDCS->address, 6); - release_region(FDCS->address+7, 1); - } - MOD_DEC_USE_COUNT; - spin_lock_irqsave(&floppy_usage_lock, flags); - usage_count--; - spin_unlock_irqrestore(&floppy_usage_lock, flags); - return -1; + goto cleanup1; + } + if (!request_region(FDCS->address + 7, 1, "floppy DIR")) { + DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address + 7); + goto cleanup2; } - request_region(FDCS->address, 6, "floppy"); - request_region(FDCS->address+7, 1, "floppy DIR"); /* address + 6 is reserved, and may be taken by IDE. * Unfortunately, Adaptec doesn't know this :-(, */ } @@ -4339,6 +4336,20 @@ static int floppy_grab_irq_and_dma(void) fdc = 0; irqdma_allocated = 1; return 0; +cleanup2: + release_region(FDCS->address, 6); +cleanup1: + fd_free_irq(); + fd_free_dma(); + while(--fdc >= 0) { + release_region(FDCS->address, 6); + release_region(FDCS->address + 7, 1); + } + MOD_DEC_USE_COUNT; + spin_lock_irqsave(&floppy_usage_lock, flags); + usage_count--; + spin_unlock_irqrestore(&floppy_usage_lock, flags); + return -1; } static void floppy_release_irq_and_dma(void) diff --git a/drivers/block/xor.c b/drivers/block/xor.c index eb99582de095..4fe04fb89a37 100644 --- a/drivers/block/xor.c +++ b/drivers/block/xor.c @@ -1406,6 +1406,818 @@ XORBLOCK_TEMPLATE(SPARC) } #endif /* __sparc_v[78]__ */ +#ifdef __alpha__ +/* + * High speed xor_block operation for RAID4/5 pipelined for Alpha EV5. + * There is a second version using EV6 prefetch instructions. + * + * Copyright (C) 2000 Richard Henderson (rth@redhat.com) + */ + +XORBLOCK_TEMPLATE(alpha) +{ + long lines = bh_ptr[0]->b_size / sizeof (long) / 8; + long *d = (long *) bh_ptr[0]->b_data; + long *s1 = (long *) bh_ptr[1]->b_data; + long *s2, *s3, *s4; + + if (count == 2) goto two_blocks; + + s2 = (long *) bh_ptr[2]->b_data; + if (count == 3) goto three_blocks; + + s3 = (long *) bh_ptr[3]->b_data; + if (count == 4) goto four_blocks; + + s4 = (long *) bh_ptr[4]->b_data; + goto five_blocks; + +two_blocks: +asm volatile (" + .align 4 +2: + ldq $0,0(%0) + ldq $1,0(%1) + ldq $2,8(%0) + ldq $3,8(%1) + + ldq $4,16(%0) + ldq $5,16(%1) + ldq $6,24(%0) + ldq $7,24(%1) + + ldq $16,32(%0) + ldq $17,32(%1) + ldq $18,40(%0) + ldq $19,40(%1) + + ldq $20,48(%0) + ldq $21,48(%1) + ldq $22,56(%0) + xor $0,$1,$0 # 7 cycles from $1 load + + ldq $23,56(%1) + xor $2,$3,$2 + stq $0,0(%0) + xor $4,$5,$4 + + stq $2,8(%0) + xor $6,$7,$6 + stq $4,16(%0) + xor $16,$17,$16 + + stq $6,24(%0) + xor $18,$19,$18 + stq $16,32(%0) + xor $20,$21,$20 + + stq $18,40(%0) + xor $22,$23,$22 + stq $20,48(%0) + subq %2,1,%2 + + stq $22,56(%0) + addq %0,64,%0 + addq %1,64,%1 + bgt %2,2b" + : "=r"(d), "=r"(s1), "=r"(lines) + : "0"(d), "1"(s1), "2"(lines) + : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23"); + return; + +three_blocks: +asm volatile (" + .align 4 +3: + ldq $0,0(%0) + ldq $1,0(%1) + ldq $2,0(%2) + ldq $3,8(%0) + + ldq $4,8(%1) + ldq $6,16(%0) + ldq $7,16(%1) + ldq $17,24(%0) + + ldq $18,24(%1) + ldq $20,32(%0) + ldq $21,32(%1) + ldq $5,8(%2) + + ldq $16,16(%2) + ldq $19,24(%2) + ldq $22,32(%2) + nop + + xor $0,$1,$1 # 8 cycles from $0 load + xor $3,$4,$4 # 6 cycles from $4 load + xor $6,$7,$7 # 6 cycles from $7 load + xor $17,$18,$18 # 5 cycles from $18 load + + xor $1,$2,$2 # 9 cycles from $2 load + xor $20,$21,$21 # 5 cycles from $21 load + stq $2,0(%0) + xor $4,$5,$5 # 6 cycles from $5 load + + stq $5,8(%0) + xor $7,$16,$16 # 7 cycles from $16 load + stq $16,16(%0) + xor $18,$19,$19 # 7 cycles from $19 load + + stq $19,24(%0) + xor $21,$22,$22 # 7 cycles from $22 load + stq $22,32(%0) + nop + + ldq $0,40(%0) + ldq $1,40(%1) + ldq $3,48(%0) + ldq $4,48(%1) + + ldq $6,56(%0) + ldq $7,56(%1) + ldq $2,40(%2) + ldq $5,48(%2) + + ldq $16,56(%2) + xor $0,$1,$1 # 4 cycles from $1 load + xor $3,$4,$4 # 5 cycles from $4 load + xor $6,$7,$7 # 5 cycles from $7 load + + xor $1,$2,$2 # 4 cycles from $2 load + xor $4,$5,$5 # 5 cycles from $5 load + stq $2,40(%0) + xor $7,$16,$16 # 4 cycles from $16 load + + stq $5,48(%0) + subq %3,1,%3 + stq $16,56(%0) + addq %2,64,%2 + + addq %1,64,%1 + addq %0,64,%0 + bgt %3,3b" + : "=r"(d), "=r"(s1), "=r"(s2), "=r"(lines) + : "0"(d), "1"(s1), "2"(s2), "3"(lines) + : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + "$16", "$17", "$18", "$19", "$20", "$21", "$22"); + return; + +four_blocks: +asm volatile (" + .align 4 +4: + ldq $0,0(%0) + ldq $1,0(%1) + ldq $2,0(%2) + ldq $3,0(%3) + + ldq $4,8(%0) + ldq $5,8(%1) + ldq $6,8(%2) + ldq $7,8(%3) + + ldq $16,16(%0) + ldq $17,16(%1) + ldq $18,16(%2) + ldq $19,16(%3) + + ldq $20,24(%0) + xor $0,$1,$1 # 6 cycles from $1 load + ldq $21,24(%1) + xor $2,$3,$3 # 6 cycles from $3 load + + ldq $0,24(%2) + xor $1,$3,$3 + ldq $1,24(%3) + xor $4,$5,$5 # 7 cycles from $5 load + + stq $3,0(%0) + xor $6,$7,$7 + xor $16,$17,$17 # 7 cycles from $17 load + xor $5,$7,$7 + + stq $7,8(%0) + xor $18,$19,$19 # 7 cycles from $19 load + ldq $2,32(%0) + xor $17,$19,$19 + + ldq $3,32(%1) + ldq $4,32(%2) + ldq $5,32(%3) + xor $20,$21,$21 # 8 cycles from $21 load + + ldq $6,40(%0) + ldq $7,40(%1) + ldq $16,40(%2) + ldq $17,40(%3) + + stq $19,16(%0) + xor $0,$1,$1 # 9 cycles from $1 load + xor $2,$3,$3 # 5 cycles from $3 load + xor $21,$1,$1 + + ldq $18,48(%0) + xor $4,$5,$5 # 5 cycles from $5 load + ldq $19,48(%1) + xor $3,$5,$5 + + ldq $20,48(%2) + ldq $21,48(%3) + ldq $0,56(%0) + ldq $1,56(%1) + + ldq $2,56(%2) + xor $6,$7,$7 # 8 cycles from $6 load + ldq $3,56(%3) + xor $16,$17,$17 # 8 cycles from $17 load + + xor $7,$17,$17 + xor $18,$19,$19 # 5 cycles from $19 load + xor $20,$21,$21 # 5 cycles from $21 load + xor $19,$21,$21 + + stq $1,24(%0) + xor $0,$1,$1 # 5 cycles from $1 load + stq $5,32(%0) + xor $2,$3,$3 # 4 cycles from $3 load + + stq $17,40(%0) + xor $1,$3,$3 + stq $21,48(%0) + subq %4,1,%4 + + stq $3,56(%0) + addq %3,64,%3 + addq %2,64,%2 + addq %1,64,%1 + + addq %0,64,%0 + bgt %4,4b" + : "=r"(d), "=r"(s1), "=r"(s2), "=r"(s3), "=r"(lines) + : "0"(d), "1"(s1), "2"(s2), "3"(s3), "4"(lines) + : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + "$16", "$17", "$18", "$19", "$20", "$21"); + return; + +five_blocks: +asm volatile (" + ldq %0,0(%6) + ldq %1,8(%6) + ldq %2,16(%6) + ldq %3,24(%6) + ldq %4,32(%6) + ldq %0,%7(%0) + ldq %1,%7(%1) + ldq %2,%7(%2) + ldq %3,%7(%3) + ldq %4,%7(%4) + .align 4 +5: + ldq $0,0(%0) + ldq $1,0(%1) + ldq $2,0(%2) + ldq $3,0(%3) + + ldq $4,0(%4) + ldq $5,8(%0) + ldq $6,8(%1) + ldq $7,8(%2) + + ldq $16,8(%3) + ldq $17,8(%4) + ldq $18,16(%0) + ldq $19,16(%1) + + ldq $20,16(%2) + xor $0,$1,$1 # 6 cycles from $1 load + ldq $21,16(%3) + xor $2,$3,$3 # 6 cycles from $3 load + + ldq $0,16(%4) + xor $1,$3,$3 + ldq $1,24(%0) + xor $3,$4,$4 # 7 cycles from $4 load + + stq $4,0(%0) + xor $5,$6,$6 # 7 cycles from $6 load + xor $7,$16,$16 # 7 cycles from $16 load + xor $6,$17,$17 # 7 cycles from $17 load + + ldq $2,24(%1) + xor $16,$17,$17 + ldq $3,24(%2) + xor $18,$19,$19 # 8 cycles from $19 load + + stq $17,8(%0) + xor $19,$20,$20 # 8 cycles from $20 load + ldq $4,24(%3) + xor $21,$0,$0 # 7 cycles from $0 load + + ldq $5,24(%4) + xor $20,$0,$0 + ldq $6,32(%0) + ldq $7,32(%1) + + stq $0,16(%0) + xor $1,$2,$2 # 6 cycles from $2 load + ldq $16,32(%2) + xor $3,$4,$4 # 4 cycles from $4 load + + ldq $17,32(%3) + xor $2,$4,$4 + ldq $18,32(%4) + ldq $19,40(%0) + + ldq $20,40(%1) + ldq $21,40(%2) + ldq $0,40(%3) + xor $4,$5,$5 # 7 cycles from $5 load + + stq $5,24(%0) + xor $6,$7,$7 # 7 cycles from $7 load + ldq $1,40(%4) + ldq $2,48(%0) + + ldq $3,48(%1) + xor $7,$16,$16 # 7 cycles from $16 load + ldq $4,48(%2) + xor $17,$18,$18 # 6 cycles from $18 load + + ldq $5,48(%3) + xor $16,$18,$18 + ldq $6,48(%4) + xor $19,$20,$20 # 7 cycles from $20 load + + stq $18,32(%0) + xor $20,$21,$21 # 8 cycles from $21 load + ldq $7,56(%0) + xor $0,$1,$1 # 6 cycles from $1 load + + ldq $16,56(%1) + ldq $17,56(%2) + ldq $18,56(%3) + ldq $19,56(%4) + + xor $21,$1,$1 + xor $2,$3,$3 # 9 cycles from $3 load + xor $3,$4,$4 # 9 cycles from $4 load + xor $5,$6,$6 # 8 cycles from $6 load + + unop + xor $4,$6,$6 + xor $7,$16,$16 # 7 cycles from $16 load + xor $17,$18,$18 # 6 cycles from $18 load + + stq $6,48(%0) + xor $16,$18,$18 + subq %5,1,%5 + xor $18,$19,$19 # 8 cycles from $19 load + + stq $19,56(%0) + addq %4,64,%4 + addq %3,64,%3 + addq %2,64,%2 + + addq %1,64,%1 + addq %0,64,%0 + bgt %5,5b" + : "=&r"(d), "=&r"(s1), "=&r"(s2), "=&r"(s3), "=r"(s4), "=r"(lines) + /* ARG! We've run out of asm arguments! We've got to reload + all those pointers we just loaded. */ + : "r"(bh_ptr), "i" (&((struct buffer_head *)0)->b_data), "5"(lines) + : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + "$16", "$17", "$18", "$19", "$20", "$21"); + return; +} + +#define prefetch(base, ofs) \ + asm("ldq $31,%2(%0)" : "=r"(base) : "0"(base), "i"(ofs)) + +XORBLOCK_TEMPLATE(alpha_prefetch) +{ + long lines = bh_ptr[0]->b_size / sizeof (long) / 8; + long *d = (long *) bh_ptr[0]->b_data; + long *s1 = (long *) bh_ptr[1]->b_data; + long *s2, *s3, *s4; + long p; + + p = count == 2; + prefetch(d, 0); + prefetch(s1, 0); + prefetch(d, 64); + prefetch(s1, 64); + prefetch(d, 128); + prefetch(s1, 128); + prefetch(d, 192); + prefetch(s1, 192); + if (p) goto two_blocks; + + s2 = (long *) bh_ptr[2]->b_data; + p = count == 3; + prefetch(s2, 0); + prefetch(s2, 64); + prefetch(s2, 128); + prefetch(s2, 192); + if (p) goto three_blocks; + + s3 = (long *) bh_ptr[3]->b_data; + p = count == 4; + prefetch(s3, 0); + prefetch(s3, 64); + prefetch(s3, 128); + prefetch(s3, 192); + if (p) goto four_blocks; + + s4 = (long *) bh_ptr[4]->b_data; + prefetch(s4, 0); + prefetch(s4, 64); + prefetch(s4, 128); + prefetch(s4, 192); + goto five_blocks; + +two_blocks: +asm volatile (" + .align 4 +2: + ldq $0,0(%0) + ldq $1,0(%1) + ldq $2,8(%0) + ldq $3,8(%1) + + ldq $4,16(%0) + ldq $5,16(%1) + ldq $6,24(%0) + ldq $7,24(%1) + + ldq $16,32(%0) + ldq $17,32(%1) + ldq $18,40(%0) + ldq $19,40(%1) + + ldq $20,48(%0) + ldq $21,48(%1) + ldq $22,56(%0) + ldq $23,56(%1) + + ldq $31,256(%0) + xor $0,$1,$0 # 8 cycles from $1 load + ldq $31,256(%1) + xor $2,$3,$2 + + stq $0,0(%0) + xor $4,$5,$4 + stq $2,8(%0) + xor $6,$7,$6 + + stq $4,16(%0) + xor $16,$17,$16 + stq $6,24(%0) + xor $18,$19,$18 + + stq $16,32(%0) + xor $20,$21,$20 + stq $18,40(%0) + xor $22,$23,$22 + + stq $20,48(%0) + subq %2,1,%2 + stq $22,56(%0) + addq %0,64,%0 + + addq %1,64,%1 + bgt %2,2b" + : "=r"(d), "=r"(s1), "=r"(lines) + : "0"(d), "1"(s1), "2"(lines) + : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23"); + return; + +three_blocks: +asm volatile (" + .align 4 +3: + ldq $0,0(%0) + ldq $1,0(%1) + ldq $2,0(%2) + ldq $3,8(%0) + + ldq $4,8(%1) + ldq $6,16(%0) + ldq $7,16(%1) + ldq $17,24(%0) + + ldq $18,24(%1) + ldq $20,32(%0) + ldq $21,32(%1) + ldq $5,8(%2) + + ldq $16,16(%2) + ldq $19,24(%2) + ldq $22,32(%2) + nop + + xor $0,$1,$1 # 8 cycles from $0 load + xor $3,$4,$4 # 7 cycles from $4 load + xor $6,$7,$7 # 6 cycles from $7 load + xor $17,$18,$18 # 5 cycles from $18 load + + xor $1,$2,$2 # 9 cycles from $2 load + xor $20,$21,$21 # 5 cycles from $21 load + stq $2,0(%0) + xor $4,$5,$5 # 6 cycles from $5 load + + stq $5,8(%0) + xor $7,$16,$16 # 7 cycles from $16 load + stq $16,16(%0) + xor $18,$19,$19 # 7 cycles from $19 load + + stq $19,24(%0) + xor $21,$22,$22 # 7 cycles from $22 load + stq $22,32(%0) + nop + + ldq $0,40(%0) + ldq $1,40(%1) + ldq $3,48(%0) + ldq $4,48(%1) + + ldq $6,56(%0) + ldq $7,56(%1) + ldq $2,40(%2) + ldq $5,48(%2) + + ldq $16,56(%2) + ldq $31,256(%0) + ldq $31,256(%1) + ldq $31,256(%2) + + xor $0,$1,$1 # 6 cycles from $1 load + xor $3,$4,$4 # 5 cycles from $4 load + xor $6,$7,$7 # 5 cycles from $7 load + xor $1,$2,$2 # 4 cycles from $2 load + + xor $4,$5,$5 # 5 cycles from $5 load + xor $7,$16,$16 # 4 cycles from $16 load + stq $2,40(%0) + subq %3,1,%3 + + stq $5,48(%0) + addq %2,64,%2 + stq $16,56(%0) + addq %1,64,%1 + + addq %0,64,%0 + bgt %3,3b" + : "=r"(d), "=r"(s1), "=r"(s2), "=r"(lines) + : "0"(d), "1"(s1), "2"(s2), "3"(lines) + : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + "$16", "$17", "$18", "$19", "$20", "$21", "$22"); + return; + +four_blocks: +asm volatile (" + .align 4 +4: + ldq $0,0(%0) + ldq $1,0(%1) + ldq $2,0(%2) + ldq $3,0(%3) + + ldq $4,8(%0) + ldq $5,8(%1) + ldq $6,8(%2) + ldq $7,8(%3) + + ldq $16,16(%0) + ldq $17,16(%1) + ldq $18,16(%2) + ldq $19,16(%3) + + ldq $20,24(%0) + xor $0,$1,$1 # 6 cycles from $1 load + ldq $21,24(%1) + xor $2,$3,$3 # 6 cycles from $3 load + + ldq $0,24(%2) + xor $1,$3,$3 + ldq $1,24(%3) + xor $4,$5,$5 # 7 cycles from $5 load + + stq $3,0(%0) + xor $6,$7,$7 + xor $16,$17,$17 # 7 cycles from $17 load + xor $5,$7,$7 + + stq $7,8(%0) + xor $18,$19,$19 # 7 cycles from $19 load + ldq $2,32(%0) + xor $17,$19,$19 + + ldq $3,32(%1) + ldq $4,32(%2) + ldq $5,32(%3) + xor $20,$21,$21 # 8 cycles from $21 load + + ldq $6,40(%0) + ldq $7,40(%1) + ldq $16,40(%2) + ldq $17,40(%3) + + stq $19,16(%0) + xor $0,$1,$1 # 9 cycles from $1 load + xor $2,$3,$3 # 5 cycles from $3 load + xor $21,$1,$1 + + ldq $18,48(%0) + xor $4,$5,$5 # 5 cycles from $5 load + ldq $19,48(%1) + xor $3,$5,$5 + + ldq $20,48(%2) + ldq $21,48(%3) + ldq $0,56(%0) + ldq $1,56(%1) + + ldq $2,56(%2) + xor $6,$7,$7 # 8 cycles from $6 load + ldq $3,56(%3) + xor $16,$17,$17 # 8 cycles from $17 load + + ldq $31,256(%0) + xor $7,$17,$17 + ldq $31,256(%1) + xor $18,$19,$19 # 6 cycles from $19 load + + ldq $31,256(%2) + xor $20,$21,$21 # 6 cycles from $21 load + ldq $31,256(%3) + xor $19,$21,$21 + + stq $1,24(%0) + xor $0,$1,$1 # 7 cycles from $1 load + stq $5,32(%0) + xor $2,$3,$3 # 6 cycles from $3 load + + stq $17,40(%0) + xor $1,$3,$3 + stq $21,48(%0) + subq %4,1,%4 + + stq $3,56(%0) + addq %3,64,%3 + addq %2,64,%2 + addq %1,64,%1 + + addq %0,64,%0 + bgt %4,4b" + : "=r"(d), "=r"(s1), "=r"(s2), "=r"(s3), "=r"(lines) + : "0"(d), "1"(s1), "2"(s2), "3"(s3), "4"(lines) + : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + "$16", "$17", "$18", "$19", "$20", "$21"); + return; + +five_blocks: +asm volatile (" + ldq %0,0(%6) + ldq %1,8(%6) + ldq %2,16(%6) + ldq %3,24(%6) + ldq %4,32(%6) + ldq %0,%7(%0) + ldq %1,%7(%1) + ldq %2,%7(%2) + ldq %3,%7(%3) + ldq %4,%7(%4) + .align 4 +5: + ldq $0,0(%0) + ldq $1,0(%1) + ldq $2,0(%2) + ldq $3,0(%3) + + ldq $4,0(%4) + ldq $5,8(%0) + ldq $6,8(%1) + ldq $7,8(%2) + + ldq $16,8(%3) + ldq $17,8(%4) + ldq $18,16(%0) + ldq $19,16(%1) + + ldq $20,16(%2) + xor $0,$1,$1 # 6 cycles from $1 load + ldq $21,16(%3) + xor $2,$3,$3 # 6 cycles from $3 load + + ldq $0,16(%4) + xor $1,$3,$3 + ldq $1,24(%0) + xor $3,$4,$4 # 7 cycles from $4 load + + stq $4,0(%0) + xor $5,$6,$6 # 7 cycles from $6 load + xor $7,$16,$16 # 7 cycles from $16 load + xor $6,$17,$17 # 7 cycles from $17 load + + ldq $2,24(%1) + xor $16,$17,$17 + ldq $3,24(%2) + xor $18,$19,$19 # 8 cycles from $19 load + + stq $17,8(%0) + xor $19,$20,$20 # 8 cycles from $20 load + ldq $4,24(%3) + xor $21,$0,$0 # 7 cycles from $0 load + + ldq $5,24(%4) + xor $20,$0,$0 + ldq $6,32(%0) + ldq $7,32(%1) + + stq $0,16(%0) + xor $1,$2,$2 # 6 cycles from $2 load + ldq $16,32(%2) + xor $3,$4,$4 # 4 cycles from $4 load + + ldq $17,32(%3) + xor $2,$4,$4 + ldq $18,32(%4) + ldq $19,40(%0) + + ldq $20,40(%1) + ldq $21,40(%2) + ldq $0,40(%3) + xor $4,$5,$5 # 7 cycles from $5 load + + stq $5,24(%0) + xor $6,$7,$7 # 7 cycles from $7 load + ldq $1,40(%4) + ldq $2,48(%0) + + ldq $3,48(%1) + xor $7,$16,$16 # 7 cycles from $16 load + ldq $4,48(%2) + xor $17,$18,$18 # 6 cycles from $18 load + + ldq $5,48(%3) + xor $16,$18,$18 + ldq $6,48(%4) + xor $19,$20,$20 # 7 cycles from $20 load + + stq $18,32(%0) + xor $20,$21,$21 # 8 cycles from $21 load + ldq $7,56(%0) + xor $0,$1,$1 # 6 cycles from $1 load + + ldq $16,56(%1) + ldq $17,56(%2) + ldq $18,56(%3) + ldq $19,56(%4) + + ldq $31,256(%0) + xor $21,$1,$1 + ldq $31,256(%1) + xor $2,$3,$3 # 9 cycles from $3 load + + ldq $31,256(%2) + xor $3,$4,$4 # 9 cycles from $4 load + ldq $31,256(%3) + xor $5,$6,$6 # 8 cycles from $6 load + + ldq $31,256(%4) + xor $4,$6,$6 + xor $7,$16,$16 # 7 cycles from $16 load + xor $17,$18,$18 # 6 cycles from $18 load + + stq $6,48(%0) + xor $16,$18,$18 + subq %5,1,%5 + xor $18,$19,$19 # 8 cycles from $19 load + + stq $19,56(%0) + addq %4,64,%4 + addq %3,64,%3 + addq %2,64,%2 + + addq %1,64,%1 + addq %0,64,%0 + bgt %5,5b" + : "=&r"(d), "=&r"(s1), "=&r"(s2), "=&r"(s3), "=r"(s4), "=r"(lines) + /* ARG! We've run out of asm arguments! We've got to reload + all those pointers we just loaded. */ + : "r"(bh_ptr), "i" (&((struct buffer_head *)0)->b_data), "5"(lines) + : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + "$16", "$17", "$18", "$19", "$20", "$21"); + return; +} + +#undef prefetch + +#endif /* __alpha__ */ + #ifndef __sparc_v9__ /* @@ -1815,8 +2627,21 @@ static inline void pick_fastest_function(void) } #ifdef CONFIG_X86_XMM if (cpu_has_xmm) { + /* we force the use of the KNI xor block because it + can write around l2. we may also be able + to load into the l1 only depending on how + the cpu deals with a load to a line that is + being prefetched. + */ fastest = &t_xor_block_pIII_kni; } +#endif +#ifdef __alpha__ + if (implver() == IMPLVER_EV6) { + /* Force the use of alpha_prefetch if EV6, as it + is significantly faster in the cold cache case. */ + fastest = &t_xor_block_alpha_prefetch; + } #endif xor_block = fastest->xor_block; printk( "using fastest function: %s (%d.%03d MB/sec)\n", fastest->name, @@ -1854,27 +2679,23 @@ void calibrate_xor_block(void) if (cpu_has_xmm) { printk(KERN_INFO "raid5: KNI detected, trying cache-avoiding KNI checksum routine\n"); - /* we force the use of the KNI xor block because it - can write around l2. we may also be able - to load into the l1 only depending on how - the cpu deals with a load to a line that is - being prefetched. - */ xor_speed(&t_xor_block_pIII_kni,&b1,&b2); } #endif /* CONFIG_X86_XMM */ #ifdef __i386__ - if (md_cpu_has_mmx()) { printk(KERN_INFO "raid5: MMX detected, trying high-speed MMX checksum routines\n"); xor_speed(&t_xor_block_pII_mmx,&b1,&b2); xor_speed(&t_xor_block_p5_mmx,&b1,&b2); } - #endif /* __i386__ */ - + +#ifdef __alpha__ + xor_speed(&t_xor_block_alpha,&b1,&b2); + xor_speed(&t_xor_block_alpha_prefetch,&b1,&b2); +#endif xor_speed(&t_xor_block_8regs,&b1,&b2); xor_speed(&t_xor_block_32regs,&b1,&b2); diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 4503bbfed82a..f032a310a989 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -292,10 +292,10 @@ MODULE_PARM(check_media_type, "i"); /* These are used to simplify getting data in from and back to user land */ #define IOCTL_IN(arg, type, in) \ - copy_from_user_ret(&in, (type *) arg, sizeof in, -EFAULT) + copy_from_user(&in, (type *) arg, sizeof in) #define IOCTL_OUT(arg, type, out) \ - copy_to_user_ret((type *) arg, &out, sizeof out, -EFAULT) + copy_to_user((type *) arg, &out, sizeof out) /* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in a lot of places. This macro makes the code more clear. */ @@ -1463,7 +1463,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); if (!(cdo->capability & CDC_MULTI_SESSION)) return -ENOSYS; - IOCTL_IN(arg, struct cdrom_multisession, ms_info); + if (IOCTL_IN(arg, struct cdrom_multisession, ms_info)) + return -EFAULT; requested_format = ms_info.addr_format; if (!((requested_format == CDROM_MSF) || (requested_format == CDROM_LBA))) @@ -1473,7 +1474,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return ret; sanitize_format(&ms_info.addr, &ms_info.addr_format, requested_format); - IOCTL_OUT(arg, struct cdrom_multisession, ms_info); + if (IOCTL_OUT(arg, struct cdrom_multisession, ms_info)) + return -EFAULT; cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n"); return 0; } @@ -1632,7 +1634,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return -ENOSYS; if ((ret=cdo->get_mcn(cdi, &mcn))) return ret; - IOCTL_OUT(arg, struct cdrom_mcn, mcn); + if (IOCTL_OUT(arg, struct cdrom_mcn, mcn)) + return -EFAULT; cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n"); return 0; } @@ -1717,7 +1720,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ - IOCTL_IN(arg, struct cdrom_subchnl, q); + if (IOCTL_IN(arg, struct cdrom_subchnl, q)) + return -EFAULT; requested = q.cdsc_format; if (!((requested == CDROM_MSF) || (requested == CDROM_LBA))) @@ -1728,7 +1732,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, back = q.cdsc_format; /* local copy */ sanitize_format(&q.cdsc_absaddr, &back, requested); sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - IOCTL_OUT(arg, struct cdrom_subchnl, q); + if (IOCTL_OUT(arg, struct cdrom_subchnl, q)) + return -EFAULT; /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ return 0; } @@ -1737,10 +1742,12 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ - IOCTL_IN(arg, struct cdrom_tochdr, header); + if (IOCTL_IN(arg, struct cdrom_tochdr, header)) + return -EFAULT; if ((ret=cdo->audio_ioctl(cdi, cmd, &header))) return ret; - IOCTL_OUT(arg, struct cdrom_tochdr, header); + if (IOCTL_OUT(arg, struct cdrom_tochdr, header)) + return -EFAULT; /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */ return 0; } @@ -1750,7 +1757,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ - IOCTL_IN(arg, struct cdrom_tocentry, entry); + if (IOCTL_IN(arg, struct cdrom_tocentry, entry)) + return -EFAULT; requested_format = entry.cdte_format; if (!((requested_format == CDROM_MSF) || (requested_format == CDROM_LBA))) @@ -1761,7 +1769,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return ret; sanitize_format(&entry.cdte_addr, &entry.cdte_format, requested_format); - IOCTL_OUT(arg, struct cdrom_tocentry, entry); + if (IOCTL_OUT(arg, struct cdrom_tocentry, entry)) + return -EFAULT; /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ return 0; } @@ -1770,7 +1779,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - IOCTL_IN(arg, struct cdrom_msf, msf); + if (IOCTL_IN(arg, struct cdrom_msf, msf)) + return -EFAULT; return cdo->audio_ioctl(cdi, cmd, &msf); } case CDROMPLAYTRKIND: { @@ -1778,7 +1788,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); - IOCTL_IN(arg, struct cdrom_ti, ti); + if (IOCTL_IN(arg, struct cdrom_ti, ti)) + return -EFAULT; CHECKAUDIO; return cdo->audio_ioctl(cdi, cmd, &ti); } @@ -1787,7 +1798,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n"); - IOCTL_IN(arg, struct cdrom_volctrl, volume); + if (IOCTL_IN(arg, struct cdrom_volctrl, volume)) + return -EFAULT; return cdo->audio_ioctl(cdi, cmd, &volume); } case CDROMVOLREAD: { @@ -1797,7 +1809,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n"); if ((ret=cdo->audio_ioctl(cdi, cmd, &volume))) return ret; - IOCTL_OUT(arg, struct cdrom_volctrl, volume); + if (IOCTL_OUT(arg, struct cdrom_volctrl, volume)) + return -EFAULT; return 0; } case CDROMSTART: @@ -1894,7 +1907,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, blocksize = CD_FRAMESIZE_RAW0; break; } - IOCTL_IN(arg, struct cdrom_msf, msf); + if (IOCTL_IN(arg, struct cdrom_msf, msf)) + return -EFAULT; lba = msf_to_lba(msf.cdmsf_min0,msf.cdmsf_sec0,msf.cdmsf_frame0); /* FIXME: we need upper bound checking, too!! */ if (lba < 0) @@ -1933,7 +1947,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, struct cdrom_read_audio ra; int lba, frames; - IOCTL_IN(arg, struct cdrom_read_audio, ra); + if (IOCTL_IN(arg, struct cdrom_read_audio, ra)) + return -EFAULT; if (ra.addr_format == CDROM_MSF) lba = msf_to_lba(ra.addr.msf.minute, @@ -1975,7 +1990,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMSUBCHNL: { struct cdrom_subchnl q; u_char requested, back; - IOCTL_IN(arg, struct cdrom_subchnl, q); + if (IOCTL_IN(arg, struct cdrom_subchnl, q)) + return -EFAULT; requested = q.cdsc_format; if (!((requested == CDROM_MSF) || (requested == CDROM_LBA))) @@ -1986,7 +2002,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, back = q.cdsc_format; /* local copy */ sanitize_format(&q.cdsc_absaddr, &back, requested); sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - IOCTL_OUT(arg, struct cdrom_subchnl, q); + if (IOCTL_OUT(arg, struct cdrom_subchnl, q)) + return -EFAULT; /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ return 0; } @@ -1994,7 +2011,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, struct cdrom_ti ti; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); - IOCTL_IN(arg, struct cdrom_ti, ti); + if (IOCTL_IN(arg, struct cdrom_ti, ti)) + return -EFAULT; cgc.cmd[0] = GPCMD_PLAY_AUDIO_TI; cgc.cmd[4] = ti.cdti_trk0; @@ -2006,7 +2024,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMPLAYMSF: { struct cdrom_msf msf; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - IOCTL_IN(arg, struct cdrom_msf, msf); + if (IOCTL_IN(arg, struct cdrom_msf, msf)) + return -EFAULT; cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF; cgc.cmd[3] = msf.cdmsf_min0; cgc.cmd[4] = msf.cdmsf_sec0; @@ -2020,7 +2039,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMPLAYBLK: { struct cdrom_blk blk; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n"); - IOCTL_IN(arg, struct cdrom_blk, blk); + if (IOCTL_IN(arg, struct cdrom_blk, blk)) + return -EFAULT; cgc.cmd[0] = GPCMD_PLAY_AUDIO_10; cgc.cmd[2] = (blk.from >> 24) & 0xff; cgc.cmd[3] = (blk.from >> 16) & 0xff; @@ -2038,7 +2058,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned short offset; cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n"); - IOCTL_IN(arg, struct cdrom_volctrl, volctrl); + if (IOCTL_IN(arg, struct cdrom_volctrl, volctrl)) + return -EFAULT; cgc.buffer = buffer; cgc.buflen = 24; @@ -2064,7 +2085,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, volctrl.channel1 = buffer[offset+11]; volctrl.channel2 = buffer[offset+13]; volctrl.channel3 = buffer[offset+15]; - IOCTL_OUT(arg, struct cdrom_volctrl, volctrl); + if (IOCTL_OUT(arg, struct cdrom_volctrl, volctrl)) + return -EFAULT; return 0; } @@ -2130,10 +2152,12 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, if (!CDROM_CAN(CDC_DVD)) return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n"); - IOCTL_IN(arg, dvd_authinfo, ai); + if (IOCTL_IN(arg, dvd_authinfo, ai)) + return -EFAULT; if ((ret = dvd_do_auth (cdi, &ai))) return ret; - IOCTL_OUT(arg, dvd_authinfo, ai); + if (IOCTL_OUT(arg, dvd_authinfo, ai)) + return -EFAULT; return 0; } @@ -2143,7 +2167,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, if (!CDROM_CAN(CDC_GENERIC_PACKET)) return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n"); - IOCTL_IN(arg, struct cdrom_generic_command, cgc); + if (IOCTL_IN(arg, struct cdrom_generic_command, cgc)) + return -EFAULT; copy = !!cgc.buflen; userbuf = cgc.buffer; cgc.buffer = NULL; @@ -2190,7 +2215,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); if ((ret = cdrom_get_next_writable(dev, &next))) return ret; - IOCTL_OUT(arg, long, next); + if (IOCTL_OUT(arg, long, next)) + return -EFAULT; return 0; } case CDROM_LAST_WRITTEN: { @@ -2198,7 +2224,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); if ((ret = cdrom_get_last_written(dev, &last))) return ret; - IOCTL_OUT(arg, long, last); + if (IOCTL_OUT(arg, long, last)) + return -EFAULT; return 0; } } /* switch */ diff --git a/drivers/char/drm/agpsupport.c b/drivers/char/drm/agpsupport.c index 42a1bc2f6d55..24fd59cdfe42 100644 --- a/drivers/char/drm/agpsupport.c +++ b/drivers/char/drm/agpsupport.c @@ -95,7 +95,8 @@ int drm_agp_info(struct inode *inode, struct file *filp, unsigned int cmd, info.id_vendor = kern->device->vendor; info.id_device = kern->device->device; - copy_to_user_ret((drm_agp_info_t *)arg, &info, sizeof(info), -EFAULT); + if (copy_to_user((drm_agp_info_t *)arg, &info, sizeof(info))) + return -EFAULT; return 0; } @@ -134,8 +135,8 @@ int drm_agp_enable(struct inode *inode, struct file *filp, unsigned int cmd, if (!dev->agp->acquired || !drm_agp.enable) return -EINVAL; - copy_from_user_ret(&mode, (drm_agp_mode_t *)arg, sizeof(mode), - -EFAULT); + if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode))) + return -EFAULT; dev->agp->mode = mode.mode; (*drm_agp.enable)(mode.mode); @@ -155,8 +156,8 @@ int drm_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long pages; u32 type; if (!dev->agp->acquired) return -EINVAL; - copy_from_user_ret(&request, (drm_agp_buffer_t *)arg, sizeof(request), - -EFAULT); + if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) + return -EFAULT; if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS))) return -ENOMEM; @@ -212,8 +213,8 @@ int drm_agp_unbind(struct inode *inode, struct file *filp, unsigned int cmd, drm_agp_mem_t *entry; if (!dev->agp->acquired) return -EINVAL; - copy_from_user_ret(&request, (drm_agp_binding_t *)arg, sizeof(request), - -EFAULT); + if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) + return -EFAULT; if (!(entry = drm_agp_lookup_entry(dev, request.handle))) return -EINVAL; if (!entry->bound) return -EINVAL; @@ -231,8 +232,8 @@ int drm_agp_bind(struct inode *inode, struct file *filp, unsigned int cmd, int page; if (!dev->agp->acquired || !drm_agp.bind_memory) return -EINVAL; - copy_from_user_ret(&request, (drm_agp_binding_t *)arg, sizeof(request), - -EFAULT); + if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) + return -EFAULT; if (!(entry = drm_agp_lookup_entry(dev, request.handle))) return -EINVAL; if (entry->bound) return -EINVAL; @@ -253,8 +254,8 @@ int drm_agp_free(struct inode *inode, struct file *filp, unsigned int cmd, drm_agp_mem_t *entry; if (!dev->agp->acquired) return -EINVAL; - copy_from_user_ret(&request, (drm_agp_buffer_t *)arg, sizeof(request), - -EFAULT); + if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) + return -EFAULT; if (!(entry = drm_agp_lookup_entry(dev, request.handle))) return -EINVAL; if (entry->bound) drm_unbind_agp(entry->memory); diff --git a/drivers/char/drm/auth.c b/drivers/char/drm/auth.c index 4556bd966091..80bb4b651b31 100644 --- a/drivers/char/drm/auth.c +++ b/drivers/char/drm/auth.c @@ -137,7 +137,8 @@ int drm_getmagic(struct inode *inode, struct file *filp, unsigned int cmd, } DRM_DEBUG("%u\n", auth.magic); - copy_to_user_ret((drm_auth_t *)arg, &auth, sizeof(auth), -EFAULT); + if (copy_to_user((drm_auth_t *)arg, &auth, sizeof(auth))) + return -EFAULT; return 0; } @@ -149,7 +150,8 @@ int drm_authmagic(struct inode *inode, struct file *filp, unsigned int cmd, drm_auth_t auth; drm_file_t *file; - copy_from_user_ret(&auth, (drm_auth_t *)arg, sizeof(auth), -EFAULT); + if (copy_from_user(&auth, (drm_auth_t *)arg, sizeof(auth))) + return -EFAULT; DRM_DEBUG("%u\n", auth.magic); if ((file = drm_find_file(dev, auth.magic))) { file->authenticated = 1; diff --git a/drivers/char/drm/bufs.c b/drivers/char/drm/bufs.c index c00f051a8409..28e0eb5f1cb0 100644 --- a/drivers/char/drm/bufs.c +++ b/drivers/char/drm/bufs.c @@ -133,12 +133,13 @@ int drm_addmap(struct inode *inode, struct file *filp, unsigned int cmd, dev->maplist[dev->map_count-1] = map; up(&dev->struct_sem); - copy_to_user_ret((drm_map_t *)arg, map, sizeof(*map), -EFAULT); + if (copy_to_user((drm_map_t *)arg, map, sizeof(*map))) + return -EFAULT; if (map->type != _DRM_SHM) { - copy_to_user_ret(&((drm_map_t *)arg)->handle, + if (copy_to_user(&((drm_map_t *)arg)->handle, &map->offset, - sizeof(map->offset), - -EFAULT); + sizeof(map->offset))) + return -EFAULT; } return 0; } @@ -166,10 +167,10 @@ int drm_addbufs(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; count = request.count; order = drm_order(request.size); @@ -295,10 +296,10 @@ int drm_addbufs(struct inode *inode, struct file *filp, unsigned int cmd, request.count = entry->buf_count; request.size = size; - copy_to_user_ret((drm_buf_desc_t *)arg, + if (copy_to_user((drm_buf_desc_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; atomic_dec(&dev->buf_alloc); return 0; @@ -324,10 +325,10 @@ int drm_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_info_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) { if (dma->bufs[i].buf_count) ++count; @@ -338,28 +339,26 @@ int drm_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, if (request.count >= count) { for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) { if (dma->bufs[i].buf_count) { - copy_to_user_ret(&request.list[count].count, + if (copy_to_user(&request.list[count].count, &dma->bufs[i].buf_count, sizeof(dma->bufs[0] - .buf_count), - -EFAULT); - copy_to_user_ret(&request.list[count].size, + .buf_count)) || + copy_to_user(&request.list[count].size, &dma->bufs[i].buf_size, - sizeof(dma->bufs[0].buf_size), - -EFAULT); - copy_to_user_ret(&request.list[count].low_mark, + sizeof(dma->bufs[0].buf_size)) || + copy_to_user(&request.list[count].low_mark, &dma->bufs[i] .freelist.low_mark, sizeof(dma->bufs[0] - .freelist.low_mark), - -EFAULT); - copy_to_user_ret(&request.list[count] + .freelist.low_mark)) || + copy_to_user(&request.list[count] .high_mark, &dma->bufs[i] .freelist.high_mark, sizeof(dma->bufs[0] - .freelist.high_mark), - -EFAULT); + .freelist.high_mark))) + return -EFAULT; + DRM_DEBUG("%d %d %d %d %d\n", i, dma->bufs[i].buf_count, @@ -372,10 +371,10 @@ int drm_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, } request.count = count; - copy_to_user_ret((drm_buf_info_t *)arg, + if (copy_to_user((drm_buf_info_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; return 0; } @@ -392,10 +391,10 @@ int drm_markbufs(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; DRM_DEBUG("%d, %d, %d\n", request.size, request.low_mark, request.high_mark); @@ -427,17 +426,17 @@ int drm_freebufs(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_free_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; DRM_DEBUG("%d\n", request.count); for (i = 0; i < request.count; i++) { - copy_from_user_ret(&idx, + if (copy_from_user(&idx, &request.list[i], - sizeof(idx), - -EFAULT); + sizeof(idx))) + return -EFAULT; if (idx < 0 || idx >= dma->buf_count) { DRM_ERROR("Index %d (of %d max)\n", idx, dma->buf_count - 1); @@ -480,10 +479,10 @@ int drm_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_map_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; if (request.count >= dma->buf_count) { down(¤t->mm->mmap_sem); @@ -529,10 +528,10 @@ done: request.count = dma->buf_count; DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode); - copy_to_user_ret((drm_buf_map_t *)arg, + if (copy_to_user((drm_buf_map_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; return retcode; } diff --git a/drivers/char/drm/context.c b/drivers/char/drm/context.c index ca491094eb36..933fd0cd2633 100644 --- a/drivers/char/drm/context.c +++ b/drivers/char/drm/context.c @@ -129,19 +129,21 @@ int drm_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i; DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); - copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT); + if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res))) + return -EFAULT; if (res.count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { ctx.handle = i; - copy_to_user_ret(&res.contexts[i], + if (copy_to_user(&res.contexts[i], &i, - sizeof(i), - -EFAULT); + sizeof(i))) + return -EFAULT; } } res.count = DRM_RESERVED_CONTEXTS; - copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT); + if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res))) + return -EFAULT; return 0; } @@ -153,7 +155,8 @@ int drm_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; if ((ctx.handle = drm_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) { /* Init kernel's context and get a new one. */ drm_init_queue(dev, dev->queuelist[ctx.handle], &ctx); @@ -161,7 +164,8 @@ int drm_addctx(struct inode *inode, struct file *filp, unsigned int cmd, } drm_init_queue(dev, dev->queuelist[ctx.handle], &ctx); DRM_DEBUG("%d\n", ctx.handle); - copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -173,7 +177,8 @@ int drm_modctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_ctx_t ctx; drm_queue_t *q; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); @@ -206,7 +211,8 @@ int drm_getctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_ctx_t ctx; drm_queue_t *q; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); @@ -223,7 +229,8 @@ int drm_getctx(struct inode *inode, struct file *filp, unsigned int cmd, ctx.flags = q->flags; atomic_dec(&q->use_count); - copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -235,7 +242,8 @@ int drm_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); return drm_context_switch(dev, dev->last_context, ctx.handle); } @@ -247,7 +255,8 @@ int drm_newctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); drm_context_switch_complete(dev, ctx.handle); @@ -263,7 +272,8 @@ int drm_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_queue_t *q; drm_buf_t *buf; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); if (ctx.handle >= dev->queue_count) return -EINVAL; diff --git a/drivers/char/drm/dma.c b/drivers/char/drm/dma.c index ac2d1bc5aac7..62340170bb49 100644 --- a/drivers/char/drm/dma.c +++ b/drivers/char/drm/dma.c @@ -486,14 +486,16 @@ static int drm_dma_get_buffers_of_order(drm_device_t *dev, drm_dma_t *d, buf->pending); } buf->pid = current->pid; - copy_to_user_ret(&d->request_indices[i], + if (copy_to_user(&d->request_indices[i], &buf->idx, - sizeof(buf->idx), - -EFAULT); - copy_to_user_ret(&d->request_sizes[i], + sizeof(buf->idx))) + return -EFAULT; + + if (copy_to_user(&d->request_sizes[i], &buf->total, - sizeof(buf->total), - -EFAULT); + sizeof(buf->total))) + return -EFAULT; + ++d->granted_count; } return 0; diff --git a/drivers/char/drm/drawable.c b/drivers/char/drm/drawable.c index 03839f5be544..1328054e2149 100644 --- a/drivers/char/drm/drawable.c +++ b/drivers/char/drm/drawable.c @@ -39,7 +39,8 @@ int drm_adddraw(struct inode *inode, struct file *filp, unsigned int cmd, draw.handle = 0; /* NOOP */ DRM_DEBUG("%d\n", draw.handle); - copy_to_user_ret((drm_draw_t *)arg, &draw, sizeof(draw), -EFAULT); + if (copy_to_user((drm_draw_t *)arg, &draw, sizeof(draw))) + return -EFAULT; return 0; } diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index e8ec9bdbcf30..d6de193d2147 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -57,10 +57,13 @@ #include #include #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) +#if LINUX_VERSION_CODE >= 0x020100 /* KERNEL_VERSION(2,1,0) */ #include #include #endif +#if LINUX_VERSION_CODE < 0x020400 +#include "compat-pre24.h" +#endif #include "drm.h" #define DRM_DEBUG_CODE 2 /* Include debugging code (if > 1, then @@ -138,11 +141,6 @@ typedef struct wait_queue *wait_queue_head_t; #endif #ifndef module_exit #define module_exit(x) void cleanup_module(void) { x(); } -#endif - - /* virt_to_page added in 2.4.0-test6 */ -#if LINUX_VERSION_CODE < 0x020400 -#define virt_to_page(kaddr) (mem_map + MAP_NR(kaddr)) #endif /* Generic cmpxchg added in 2.3.x */ diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c index a10b598985b5..4e8b29b73044 100644 --- a/drivers/char/drm/ffb_context.c +++ b/drivers/char/drm/ffb_context.c @@ -1,4 +1,4 @@ -/* $Id: ffb_context.c,v 1.3 2000/06/09 03:46:53 davem Exp $ +/* $Id: ffb_context.c,v 1.4 2000/08/29 07:01:55 davem Exp $ * ffb_context.c: Creator/Creator3D DRI/DRM context switching. * * Copyright (C) 2000 David S. Miller (davem@redhat.com) @@ -389,19 +389,21 @@ int ffb_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i; DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); - copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT); + if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res))) + return -EFAULT; if (res.count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { ctx.handle = i; - copy_to_user_ret(&res.contexts[i], + if (copy_to_user(&res.contexts[i], &i, - sizeof(i), - -EFAULT); + sizeof(i))) + return -EFAULT; } } res.count = DRM_RESERVED_CONTEXTS; - copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT); + if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res))) + return -EFAULT; return 0; } @@ -414,14 +416,16 @@ int ffb_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_ctx_t ctx; int idx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; idx = ffb_alloc_queue(dev, (ctx.flags & _DRM_CONTEXT_2DONLY)); if (idx < 0) return -ENFILE; DRM_DEBUG("%d\n", ctx.handle); ctx.handle = idx; - copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -435,7 +439,8 @@ int ffb_modctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_ctx_t ctx; int idx; - copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx))) + return -EFAULT; idx = ctx.handle; if (idx <= 0 || idx >= FFB_MAX_CTXS) @@ -463,7 +468,8 @@ int ffb_getctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_ctx_t ctx; int idx; - copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx))) + return -EFAULT; idx = ctx.handle; if (idx <= 0 || idx >= FFB_MAX_CTXS) @@ -478,7 +484,8 @@ int ffb_getctx(struct inode *inode, struct file *filp, unsigned int cmd, else ctx.flags = 0; - copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -490,7 +497,8 @@ int ffb_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); return ffb_context_switch(dev, dev->last_context, ctx.handle); } @@ -500,7 +508,8 @@ int ffb_newctx(struct inode *inode, struct file *filp, unsigned int cmd, { drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); return 0; @@ -515,7 +524,8 @@ int ffb_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1); int idx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); idx = ctx.handle - 1; diff --git a/drivers/char/drm/fops.c b/drivers/char/drm/fops.c index f3966d96b8d3..8e373e5adfa1 100644 --- a/drivers/char/drm/fops.c +++ b/drivers/char/drm/fops.c @@ -176,7 +176,8 @@ ssize_t drm_read(struct file *filp, char *buf, size_t count, loff_t *off) } else { cur = DRM_MIN(send, dev->buf_end - dev->buf_rp); } - copy_to_user_ret(buf, dev->buf_rp, cur, -EINVAL); + if (copy_to_user(buf, dev->buf_rp, cur)) + return -EFAULT; dev->buf_rp += cur; if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf; send -= cur; diff --git a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c index a99f24caeef1..794333877826 100644 --- a/drivers/char/drm/gamma_dma.c +++ b/drivers/char/drm/gamma_dma.c @@ -586,7 +586,8 @@ int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd, int retcode = 0; drm_dma_t d; - copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); + if (copy_from_user(&d, (drm_dma_t *)arg, sizeof(d))) + return -EFAULT; DRM_DEBUG("%d %d: %d send, %d req\n", current->pid, d.context, d.send_count, d.request_count); @@ -621,7 +622,8 @@ int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG("%d returning, granted = %d\n", current->pid, d.granted_count); - copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); + if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d))) + return -EFAULT; return retcode; } @@ -710,7 +712,8 @@ int gamma_control(struct inode *inode, struct file *filp, unsigned int cmd, drm_control_t ctl; int retcode; - copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT); + if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl))) + return -EFAULT; switch (ctl.func) { case DRM_INST_HANDLER: @@ -742,7 +745,8 @@ int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, dev->lck_start = start = get_cycles(); #endif - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -804,6 +808,15 @@ int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */ if (!ret) { + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); + if (lock.flags & _DRM_LOCK_READY) gamma_dma_ready(dev); if (lock.flags & _DRM_LOCK_QUIESCENT) { diff --git a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c index 13d37c2459f0..030122f59e35 100644 --- a/drivers/char/drm/gamma_drv.c +++ b/drivers/char/drm/gamma_drv.c @@ -405,17 +405,18 @@ int gamma_version(struct inode *inode, struct file *filp, unsigned int cmd, drm_version_t version; int len; - copy_from_user_ret(&version, + if (copy_from_user(&version, (drm_version_t *)arg, - sizeof(version), - -EFAULT); + sizeof(version))) + return -EFAULT; #define DRM_COPY(name,value) \ len = strlen(value); \ if (len > name##_len) len = name##_len; \ name##_len = strlen(value); \ if (len && name) { \ - copy_to_user_ret(name, value, len, -EFAULT); \ + if (copy_to_user(name, value, len)) \ + return -EFAULT; \ } version.version_major = GAMMA_MAJOR; @@ -426,10 +427,10 @@ int gamma_version(struct inode *inode, struct file *filp, unsigned int cmd, DRM_COPY(version.date, GAMMA_DATE); DRM_COPY(version.desc, GAMMA_DESC); - copy_to_user_ret((drm_version_t *)arg, + if (copy_to_user((drm_version_t *)arg, &version, - sizeof(version), - -EFAULT); + sizeof(version))) + return -EFAULT; return 0; } @@ -537,7 +538,8 @@ int gamma_unlock(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_lock_t lock; - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -564,5 +566,6 @@ int gamma_unlock(struct inode *inode, struct file *filp, unsigned int cmd, - dev->lck_start)]); #endif + unblock_all_signals(); return 0; } diff --git a/drivers/char/drm/i810_bufs.c b/drivers/char/drm/i810_bufs.c index fa1f84dcdf5d..a999e96b9386 100644 --- a/drivers/char/drm/i810_bufs.c +++ b/drivers/char/drm/i810_bufs.c @@ -56,10 +56,10 @@ int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; count = request.count; order = drm_order(request.size); @@ -155,10 +155,10 @@ int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, request.count = entry->buf_count; request.size = size; - copy_to_user_ret((drm_buf_desc_t *)arg, + if (copy_to_user((drm_buf_desc_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; atomic_dec(&dev->buf_alloc); dma->flags = _DRM_DMA_USE_AGP; @@ -170,10 +170,10 @@ int i810_addbufs(struct inode *inode, struct file *filp, unsigned int cmd, { drm_buf_desc_t request; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; if(request.flags & _DRM_AGP_BUFFER) return i810_addbufs_agp(inode, filp, cmd, arg); @@ -201,10 +201,10 @@ int i810_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_info_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) { if (dma->bufs[i].buf_count) ++count; @@ -215,28 +215,26 @@ int i810_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, if (request.count >= count) { for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) { if (dma->bufs[i].buf_count) { - copy_to_user_ret(&request.list[count].count, + if (copy_to_user(&request.list[count].count, &dma->bufs[i].buf_count, sizeof(dma->bufs[0] - .buf_count), - -EFAULT); - copy_to_user_ret(&request.list[count].size, + .buf_count)) || + copy_to_user(&request.list[count].size, &dma->bufs[i].buf_size, - sizeof(dma->bufs[0].buf_size), - -EFAULT); - copy_to_user_ret(&request.list[count].low_mark, + sizeof(dma->bufs[0].buf_size)) || + copy_to_user(&request.list[count].low_mark, &dma->bufs[i] .freelist.low_mark, sizeof(dma->bufs[0] - .freelist.low_mark), - -EFAULT); - copy_to_user_ret(&request.list[count] + .freelist.low_mark)) || + copy_to_user(&request.list[count] .high_mark, &dma->bufs[i] .freelist.high_mark, sizeof(dma->bufs[0] - .freelist.high_mark), - -EFAULT); + .freelist.high_mark))) + return -EFAULT; + DRM_DEBUG("%d %d %d %d %d\n", i, dma->bufs[i].buf_count, @@ -249,10 +247,10 @@ int i810_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, } request.count = count; - copy_to_user_ret((drm_buf_info_t *)arg, + if (copy_to_user((drm_buf_info_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; return 0; } @@ -269,10 +267,10 @@ int i810_markbufs(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; DRM_DEBUG("%d, %d, %d\n", request.size, request.low_mark, request.high_mark); @@ -304,17 +302,17 @@ int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_free_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; DRM_DEBUG("%d\n", request.count); for (i = 0; i < request.count; i++) { - copy_from_user_ret(&idx, + if (copy_from_user(&idx, &request.list[i], - sizeof(idx), - -EFAULT); + sizeof(idx))) + return -EFAULT; if (idx < 0 || idx >= dma->buf_count) { DRM_ERROR("Index %d (of %d max)\n", idx, dma->buf_count - 1); diff --git a/drivers/char/drm/i810_context.c b/drivers/char/drm/i810_context.c index 85c0877b6bfe..c331beed61bf 100644 --- a/drivers/char/drm/i810_context.c +++ b/drivers/char/drm/i810_context.c @@ -103,19 +103,21 @@ int i810_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i; DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); - copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT); + if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res))) + return -EFAULT; if (res.count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { ctx.handle = i; - copy_to_user_ret(&res.contexts[i], + if (copy_to_user(&res.contexts[i], &i, - sizeof(i), - -EFAULT); + sizeof(i))) + return -EFAULT; } } res.count = DRM_RESERVED_CONTEXTS; - copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT); + if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res))) + return -EFAULT; return 0; } @@ -126,7 +128,8 @@ int i810_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; if ((ctx.handle = i810_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ ctx.handle = i810_alloc_queue(dev); @@ -137,7 +140,8 @@ int i810_addctx(struct inode *inode, struct file *filp, unsigned int cmd, return -ENOMEM; } DRM_DEBUG("%d\n", ctx.handle); - copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -153,10 +157,12 @@ int i810_getctx(struct inode *inode, struct file *filp, unsigned int cmd, { drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx))) + return -EFAULT; /* This is 0, because we don't hanlde any context flags */ ctx.flags = 0; - copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -167,7 +173,8 @@ int i810_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); return i810_context_switch(dev, dev->last_context, ctx.handle); } @@ -179,7 +186,8 @@ int i810_newctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); i810_context_switch_complete(dev, ctx.handle); @@ -193,7 +201,8 @@ int i810_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); if(ctx.handle != DRM_KERNEL_CONTEXT) { drm_ctxbitmap_free(dev, ctx.handle); diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index 19b7bd9289ef..e2a86606817d 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c @@ -490,8 +490,8 @@ int i810_dma_init(struct inode *inode, struct file *filp, drm_i810_init_t init; int retcode = 0; - copy_from_user_ret(&init, (drm_i810_init_t *)arg, - sizeof(init), -EFAULT); + if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init))) + return -EFAULT; switch(init.func) { case I810_INIT_DMA: @@ -1005,7 +1005,8 @@ int i810_control(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG( "i810_control\n"); - copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT); + if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl))) + return -EFAULT; switch (ctl.func) { case DRM_INST_HANDLER: @@ -1178,7 +1179,8 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, int ret = 0; drm_lock_t lock; - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -1227,6 +1229,15 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, } if (!ret) { + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); + if (lock.flags & _DRM_LOCK_QUIESCENT) { DRM_DEBUG("_DRM_LOCK_QUIESCENT\n"); DRM_DEBUG("fred\n"); @@ -1266,8 +1277,8 @@ int i810_dma_vertex(struct inode *inode, struct file *filp, dev_priv->sarea_priv; drm_i810_vertex_t vertex; - copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex), - -EFAULT); + if (copy_from_user(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex))) + return -EFAULT; if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_dma_vertex called without lock held\n"); @@ -1298,8 +1309,8 @@ int i810_clear_bufs(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_i810_clear_t clear; - copy_from_user_ret(&clear, (drm_i810_clear_t *)arg, sizeof(clear), - -EFAULT); + if (copy_from_user(&clear, (drm_i810_clear_t *)arg, sizeof(clear))) + return -EFAULT; if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_clear_bufs called without lock held\n"); @@ -1356,7 +1367,8 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, dev_priv->sarea_priv; DRM_DEBUG("getbuf\n"); - copy_from_user_ret(&d, (drm_i810_dma_t *)arg, sizeof(d), -EFAULT); + if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d))) + return -EFAULT; if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_dma called without lock held\n"); @@ -1370,7 +1382,8 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", current->pid, retcode, d.granted); - copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); + if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d))) + return -EFAULT; sarea_priv->last_dispatch = (int) hw_status[5]; return retcode; @@ -1395,14 +1408,16 @@ int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, return -EINVAL; } - copy_from_user_ret(&d, (drm_i810_copy_t *)arg, sizeof(d), -EFAULT); + if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d))) + return -EFAULT; if(d.idx > dma->buf_count) return -EINVAL; buf = dma->buflist[ d.idx ]; buf_priv = buf->dev_private; if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM; - copy_from_user_ret(buf_priv->virtual, d.address, d.used, -EFAULT); + if (copy_from_user(buf_priv->virtual, d.address, d.used)) + return -EFAULT; sarea_priv->last_dispatch = (int) hw_status[5]; diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c index 275663a1bdb8..6bef56a236a6 100644 --- a/drivers/char/drm/i810_drv.c +++ b/drivers/char/drm/i810_drv.c @@ -428,17 +428,18 @@ int i810_version(struct inode *inode, struct file *filp, unsigned int cmd, drm_version_t version; int len; - copy_from_user_ret(&version, + if (copy_from_user(&version, (drm_version_t *)arg, - sizeof(version), - -EFAULT); + sizeof(version))) + return -EFAULT; #define DRM_COPY(name,value) \ len = strlen(value); \ if (len > name##_len) len = name##_len; \ name##_len = strlen(value); \ if (len && name) { \ - copy_to_user_ret(name, value, len, -EFAULT); \ + if (copy_to_user(name, value, len, -EFAULT)) \ + return -EFAULT; \ } version.version_major = I810_MAJOR; @@ -449,10 +450,10 @@ int i810_version(struct inode *inode, struct file *filp, unsigned int cmd, DRM_COPY(version.date, I810_DATE); DRM_COPY(version.desc, I810_DESC); - copy_to_user_ret((drm_version_t *)arg, + if (copy_to_user((drm_version_t *)arg, &version, - sizeof(version), - -EFAULT); + sizeof(version))) + return -EFAULT; return 0; } @@ -616,7 +617,8 @@ int i810_unlock(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_lock_t lock; - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -642,5 +644,6 @@ int i810_unlock(struct inode *inode, struct file *filp, unsigned int cmd, - dev->lck_start)]); #endif + unblock_all_signals(); return 0; } diff --git a/drivers/char/drm/ioctl.c b/drivers/char/drm/ioctl.c index b246f76e5980..2f4286b1c128 100644 --- a/drivers/char/drm/ioctl.c +++ b/drivers/char/drm/ioctl.c @@ -38,13 +38,15 @@ int drm_irq_busid(struct inode *inode, struct file *filp, unsigned int cmd, drm_irq_busid_t p; struct pci_dev *dev; - copy_from_user_ret(&p, (drm_irq_busid_t *)arg, sizeof(p), -EFAULT); + if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p))) + return -EFAULT; dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum)); if (dev) p.irq = dev->irq; else p.irq = 0; DRM_DEBUG("%d:%d:%d => IRQ %d\n", p.busnum, p.devnum, p.funcnum, p.irq); - copy_to_user_ret((drm_irq_busid_t *)arg, &p, sizeof(p), -EFAULT); + if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p))) + return -EFAULT; return 0; } @@ -55,13 +57,15 @@ int drm_getunique(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_unique_t u; - copy_from_user_ret(&u, (drm_unique_t *)arg, sizeof(u), -EFAULT); + if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u))) + return -EFAULT; if (u.unique_len >= dev->unique_len) { - copy_to_user_ret(u.unique, dev->unique, dev->unique_len, - -EFAULT); + if (copy_to_user(u.unique, dev->unique, dev->unique_len)) + return -EFAULT; } u.unique_len = dev->unique_len; - copy_to_user_ret((drm_unique_t *)arg, &u, sizeof(u), -EFAULT); + if (copy_to_user((drm_unique_t *)arg, &u, sizeof(u))) + return -EFAULT; return 0; } @@ -72,15 +76,19 @@ int drm_setunique(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_unique_t u; - if (dev->unique_len || dev->unique) return -EBUSY; + if (dev->unique_len || dev->unique) + return -EBUSY; - copy_from_user_ret(&u, (drm_unique_t *)arg, sizeof(u), -EFAULT); - if (!u.unique_len) return -EINVAL; + if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u))) + return -EFAULT; + + if (!u.unique_len) + return -EINVAL; dev->unique_len = u.unique_len; dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER); - copy_from_user_ret(dev->unique, u.unique, dev->unique_len, - -EFAULT); + if (copy_from_user(dev->unique, u.unique, dev->unique_len)) + return -EFAULT; dev->unique[dev->unique_len] = '\0'; dev->devname = drm_alloc(strlen(dev->name) + strlen(dev->unique) + 2, diff --git a/drivers/char/drm/lock.c b/drivers/char/drm/lock.c index 33b2cc03f8b8..e5fd435fb0c1 100644 --- a/drivers/char/drm/lock.c +++ b/drivers/char/drm/lock.c @@ -218,7 +218,8 @@ int drm_finish(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG("\n"); - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; ret = drm_flush_block_and_flush(dev, lock.context, lock.flags); drm_flush_unblock(dev, lock.context, lock.flags); return ret; diff --git a/drivers/char/drm/mga_bufs.c b/drivers/char/drm/mga_bufs.c index b97eb4959a0c..3ec28a76542c 100644 --- a/drivers/char/drm/mga_bufs.c +++ b/drivers/char/drm/mga_bufs.c @@ -57,10 +57,10 @@ int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; count = request.count; order = drm_order(request.size); @@ -173,10 +173,10 @@ int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, request.count = entry->buf_count; request.size = size; - copy_to_user_ret((drm_buf_desc_t *)arg, + if (copy_to_user((drm_buf_desc_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; atomic_dec(&dev->buf_alloc); @@ -219,10 +219,10 @@ int mga_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; count = request.count; order = drm_order(request.size); @@ -348,10 +348,10 @@ int mga_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd, request.count = entry->buf_count; request.size = size; - copy_to_user_ret((drm_buf_desc_t *)arg, + if (copy_to_user((drm_buf_desc_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; atomic_dec(&dev->buf_alloc); return 0; @@ -362,10 +362,10 @@ int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd, { drm_buf_desc_t request; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; if(request.flags & _DRM_AGP_BUFFER) return mga_addbufs_agp(inode, filp, cmd, arg); @@ -393,10 +393,10 @@ int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_info_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) { if (dma->bufs[i].buf_count) ++count; @@ -407,28 +407,26 @@ int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, if (request.count >= count) { for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) { if (dma->bufs[i].buf_count) { - copy_to_user_ret(&request.list[count].count, + if (copy_to_user(&request.list[count].count, &dma->bufs[i].buf_count, sizeof(dma->bufs[0] - .buf_count), - -EFAULT); - copy_to_user_ret(&request.list[count].size, + .buf_count)) || + copy_to_user(&request.list[count].size, &dma->bufs[i].buf_size, - sizeof(dma->bufs[0].buf_size), - -EFAULT); - copy_to_user_ret(&request.list[count].low_mark, + sizeof(dma->bufs[0].buf_size)) || + copy_to_user(&request.list[count].low_mark, &dma->bufs[i] .freelist.low_mark, sizeof(dma->bufs[0] - .freelist.low_mark), - -EFAULT); - copy_to_user_ret(&request.list[count] + .freelist.low_mark)) || + copy_to_user(&request.list[count] .high_mark, &dma->bufs[i] .freelist.high_mark, sizeof(dma->bufs[0] - .freelist.high_mark), - -EFAULT); + .freelist.high_mark))) + return -EFAULT; + DRM_DEBUG("%d %d %d %d %d\n", i, dma->bufs[i].buf_count, @@ -441,10 +439,10 @@ int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, } request.count = count; - copy_to_user_ret((drm_buf_info_t *)arg, + if (copy_to_user((drm_buf_info_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; return 0; } @@ -461,10 +459,10 @@ int mga_markbufs(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; DRM_DEBUG("%d, %d, %d\n", request.size, request.low_mark, request.high_mark); @@ -496,17 +494,17 @@ int mga_freebufs(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_free_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; DRM_DEBUG("%d\n", request.count); for (i = 0; i < request.count; i++) { - copy_from_user_ret(&idx, + if (copy_from_user(&idx, &request.list[i], - sizeof(idx), - -EFAULT); + sizeof(idx))) + return -EFAULT; if (idx < 0 || idx >= dma->buf_count) { DRM_ERROR("Index %d (of %d max)\n", idx, dma->buf_count - 1); @@ -550,10 +548,10 @@ int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_map_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; DRM_DEBUG("mga_mapbufs\n"); DRM_DEBUG("dma->flags : %x\n", dma->flags); @@ -628,10 +626,10 @@ int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, request.count = dma->buf_count; DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode); - copy_to_user_ret((drm_buf_map_t *)arg, + if (copy_to_user((drm_buf_map_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; DRM_DEBUG("retcode : %d\n", retcode); diff --git a/drivers/char/drm/mga_context.c b/drivers/char/drm/mga_context.c index 9a73e6c14f58..43733c1401e2 100644 --- a/drivers/char/drm/mga_context.c +++ b/drivers/char/drm/mga_context.c @@ -103,19 +103,21 @@ int mga_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i; DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); - copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT); + if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res))) + return -EFAULT; if (res.count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { ctx.handle = i; - copy_to_user_ret(&res.contexts[i], + if (copy_to_user(&res.contexts[i], &i, - sizeof(i), - -EFAULT); + sizeof(i))) + return -EFAULT; } } res.count = DRM_RESERVED_CONTEXTS; - copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT); + if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res))) + return -EFAULT; return 0; } @@ -126,7 +128,8 @@ int mga_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; if ((ctx.handle = mga_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ ctx.handle = mga_alloc_queue(dev); @@ -137,7 +140,8 @@ int mga_addctx(struct inode *inode, struct file *filp, unsigned int cmd, return -ENOMEM; } DRM_DEBUG("%d\n", ctx.handle); - copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -153,10 +157,12 @@ int mga_getctx(struct inode *inode, struct file *filp, unsigned int cmd, { drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx))) + return -EFAULT; /* This is 0, because we don't hanlde any context flags */ ctx.flags = 0; - copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -167,7 +173,8 @@ int mga_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); return mga_context_switch(dev, dev->last_context, ctx.handle); } @@ -179,7 +186,8 @@ int mga_newctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); mga_context_switch_complete(dev, ctx.handle); @@ -193,7 +201,8 @@ int mga_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); if(ctx.handle != DRM_KERNEL_CONTEXT) { drm_ctxbitmap_free(dev, ctx.handle); diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c index 0df0906e5e3d..67ec072ed0e9 100644 --- a/drivers/char/drm/mga_dma.c +++ b/drivers/char/drm/mga_dma.c @@ -82,6 +82,7 @@ static void mga_delay(void) return; } +#ifdef __i386__ void mga_flush_write_combine(void) { int xchangeDummy; @@ -92,6 +93,11 @@ void mga_flush_write_combine(void) " movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ;" " pop %%eax" : /* no outputs */ : /* no inputs */ ); } +#else +void mga_flush_write_combine(void) +{ +} +#endif /* These are two age tags that will never be sent to * the hardware */ @@ -850,7 +856,8 @@ int mga_dma_init(struct inode *inode, struct file *filp, DRM_DEBUG("%s\n", __FUNCTION__); - copy_from_user_ret(&init, (drm_mga_init_t *)arg, sizeof(init), -EFAULT); + if (copy_from_user(&init, (drm_mga_init_t *)arg, sizeof(init))) + return -EFAULT; switch(init.func) { case MGA_INIT_DMA: @@ -932,7 +939,8 @@ int mga_control(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_control_t ctl; - copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT); + if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl))) + return -EFAULT; DRM_DEBUG("%s\n", __FUNCTION__); @@ -1019,7 +1027,8 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, drm_lock_t lock; DRM_DEBUG("%s\n", __FUNCTION__); - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -1068,6 +1077,15 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, } if (!ret) { + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); + if (lock.flags & _DRM_LOCK_QUIESCENT) { DRM_DEBUG("_DRM_LOCK_QUIESCENT\n"); mga_flush_queue(dev); @@ -1088,7 +1106,8 @@ int mga_flush_ioctl(struct inode *inode, struct file *filp, drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_flush_ioctl called without lock held\n"); diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index acc42b833f27..d4b8cd274861 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c @@ -444,17 +444,18 @@ int mga_version(struct inode *inode, struct file *filp, unsigned int cmd, drm_version_t version; int len; - copy_from_user_ret(&version, + if (copy_from_user(&version, (drm_version_t *)arg, - sizeof(version), - -EFAULT); + sizeof(version))) + return -EFAULT; #define DRM_COPY(name,value) \ len = strlen(value); \ if (len > name##_len) len = name##_len; \ name##_len = strlen(value); \ if (len && name) { \ - copy_to_user_ret(name, value, len, -EFAULT); \ + if (copy_to_user(name, value, len)) \ + return -EFAULT; \ } version.version_major = MGA_MAJOR; @@ -465,10 +466,10 @@ int mga_version(struct inode *inode, struct file *filp, unsigned int cmd, DRM_COPY(version.date, MGA_DATE); DRM_COPY(version.desc, MGA_DESC); - copy_to_user_ret((drm_version_t *)arg, + if (copy_to_user((drm_version_t *)arg, &version, - sizeof(version), - -EFAULT); + sizeof(version))) + return -EFAULT; return 0; } @@ -633,7 +634,8 @@ int mga_unlock(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_lock_t lock; - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -655,5 +657,6 @@ int mga_unlock(struct inode *inode, struct file *filp, unsigned int cmd, DRM_ERROR("\n"); } + unblock_all_signals(); return 0; } diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h index fe9e3dbe9bb7..f49bd0f6c896 100644 --- a/drivers/char/drm/mga_drv.h +++ b/drivers/char/drm/mga_drv.h @@ -39,8 +39,8 @@ typedef struct { u32 buffer_status; - unsigned int num_dwords; - unsigned int max_dwords; + int num_dwords; + int max_dwords; u32 *current_dma_ptr; u32 *head; u32 phys_head; @@ -209,19 +209,27 @@ typedef struct { #define PRIMLOCALS u8 tempIndex[4]; u32 *dma_ptr; u32 phys_head; \ int outcount, num_dwords -#define PRIM_OVERFLOW(dev, dev_priv, length) do { \ - drm_mga_prim_buf_t *tmp_buf = \ - dev_priv->prim_bufs[dev_priv->current_prim_idx]; \ - if( test_bit(MGA_BUF_NEEDS_OVERFLOW, \ - &tmp_buf->buffer_status)) { \ - mga_advance_primary(dev); \ - mga_dma_schedule(dev, 1); \ - } else if( tmp_buf->max_dwords - tmp_buf->num_dwords < length ||\ - tmp_buf->sec_used > MGA_DMA_BUF_NR/2) { \ - set_bit(MGA_BUF_FORCE_FIRE, &tmp_buf->buffer_status); \ - mga_advance_primary(dev); \ - mga_dma_schedule(dev, 1); \ - } \ +#define PRIM_OVERFLOW(dev, dev_priv, length) do { \ + drm_mga_prim_buf_t *tmp_buf = \ + dev_priv->prim_bufs[dev_priv->current_prim_idx]; \ + if( test_bit(MGA_BUF_NEEDS_OVERFLOW, \ + &tmp_buf->buffer_status)) { \ + mga_advance_primary(dev); \ + mga_dma_schedule(dev, 1); \ + tmp_buf = dev_priv->prim_bufs[dev_priv->current_prim_idx]; \ + } else if( tmp_buf->max_dwords - tmp_buf->num_dwords < length || \ + tmp_buf->sec_used > MGA_DMA_BUF_NR/2) { \ + set_bit(MGA_BUF_FORCE_FIRE, &tmp_buf->buffer_status); \ + mga_advance_primary(dev); \ + mga_dma_schedule(dev, 1); \ + tmp_buf = dev_priv->prim_bufs[dev_priv->current_prim_idx]; \ + } \ + if(MGA_VERBOSE) \ + DRM_DEBUG("PRIMGETPTR in %s\n", __FUNCTION__); \ + dma_ptr = tmp_buf->current_dma_ptr; \ + num_dwords = tmp_buf->num_dwords; \ + phys_head = tmp_buf->phys_head; \ + outcount = 0; \ } while(0) #define PRIMGETPTR(dev_priv) do { \ diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c index 723ccc539e04..345abb194835 100644 --- a/drivers/char/drm/mga_state.c +++ b/drivers/char/drm/mga_state.c @@ -34,6 +34,22 @@ #include "mga_drv.h" #include "drm.h" +/* If you change the functions to set state, PLEASE + * change these values + */ + +#define MGAEMITCLIP_SIZE 10 +#define MGAEMITCTX_SIZE 15 +#define MGAG200EMITTEX_SIZE 20 +#define MGAG400EMITTEX0_SIZE 30 +#define MGAG400EMITTEX1_SIZE 25 +#define MGAG400EMITPIPE_SIZE 50 +#define MGAG200EMITPIPE_SIZE 15 + +#define MAX_STATE_SIZE ((MGAEMITCLIP_SIZE * MGA_NR_SAREA_CLIPRECTS) + \ + MGAEMITCTX_SIZE + MGAG400EMITTEX0_SIZE + \ + MGAG400EMITTEX1_SIZE + MGAG400EMITPIPE_SIZE) + static void mgaEmitClipRect(drm_mga_private_t * dev_priv, drm_clip_rect_t * box) { @@ -60,8 +76,8 @@ static void mgaEmitClipRect(drm_mga_private_t * dev_priv, PRIMOUTREG(MGAREG_DMAPAD, 0); PRIMOUTREG(MGAREG_CXBNDRY, ((box->x2) << 16) | (box->x1)); - PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / 2); - PRIMOUTREG(MGAREG_YBOT, box->y2 * dev_priv->stride / 2); + PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / dev_priv->cpp); + PRIMOUTREG(MGAREG_YBOT, box->y2 * dev_priv->stride / dev_priv->cpp); PRIMADVANCE(dev_priv); } @@ -224,7 +240,6 @@ static void mgaG400EmitTex1(drm_mga_private_t * dev_priv) PRIMADVANCE(dev_priv); } -#define EMIT_PIPE 50 static void mgaG400EmitPipe(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; @@ -492,7 +507,6 @@ static void mga_dma_dispatch_tex_blit(drm_device_t * dev, y2 = length / 64; PRIM_OVERFLOW(dev, dev_priv, 30); - PRIMGETPTR(dev_priv); PRIMOUTREG(MGAREG_DSTORG, destOrg); PRIMOUTREG(MGAREG_MACCESS, 0x00000000); @@ -526,7 +540,6 @@ static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf) int length = buf->used; int use_agp = PDEA_pagpxfer_enable; int i = 0; - int primary_needed; PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); @@ -542,9 +555,8 @@ static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf) * these numbers (Overestimating this doesn't hurt). */ buf_priv->dispatched = 1; - primary_needed = (50 + 15 + 15 + 30 + 25 + - 10 + 15 * MGA_NR_SAREA_CLIPRECTS); - PRIM_OVERFLOW(dev, dev_priv, primary_needed); + PRIM_OVERFLOW(dev, dev_priv, + (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS))); mgaEmitState(dev_priv); do { if (i < sarea_priv->nbox) { @@ -592,7 +604,6 @@ static void mga_dma_dispatch_indices(drm_device_t * dev, unsigned int address = (unsigned int) buf->bus_address; int use_agp = PDEA_pagpxfer_enable; int i = 0; - int primary_needed; PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); @@ -606,9 +617,8 @@ static void mga_dma_dispatch_indices(drm_device_t * dev, * these numbers (Overestimating this doesn't hurt). */ buf_priv->dispatched = 1; - primary_needed = (50 + 15 + 15 + 30 + 25 + - 10 + 15 * MGA_NR_SAREA_CLIPRECTS); - PRIM_OVERFLOW(dev, dev_priv, primary_needed); + PRIM_OVERFLOW(dev, dev_priv, + (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS))); mgaEmitState(dev_priv); do { @@ -657,7 +667,6 @@ static void mga_dma_dispatch_clear(drm_device_t * dev, int flags, drm_clip_rect_t *pbox = sarea_priv->boxes; unsigned int cmd; int i; - int primary_needed; PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); @@ -666,11 +675,7 @@ static void mga_dma_dispatch_clear(drm_device_t * dev, int flags, else cmd = MGA_CLEAR_CMD | DC_atype_rstr; - primary_needed = nbox * 70; - if (primary_needed == 0) - primary_needed = 70; - PRIM_OVERFLOW(dev, dev_priv, primary_needed); - PRIMGETPTR(dev_priv); + PRIM_OVERFLOW(dev, dev_priv, 35 * MGA_NR_SAREA_CLIPRECTS); for (i = 0; i < nbox; i++) { unsigned int height = pbox[i].y2 - pbox[i].y1; @@ -741,14 +746,12 @@ static void mga_dma_dispatch_swap(drm_device_t * dev) int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; int i; - int primary_needed; + int pixel_stride = dev_priv->stride / dev_priv->cpp; + PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); - primary_needed = nbox * 5; - primary_needed += 65; - PRIM_OVERFLOW(dev, dev_priv, primary_needed); - PRIMGETPTR(dev_priv); + PRIM_OVERFLOW(dev, dev_priv, (MGA_NR_SAREA_CLIPRECTS * 5) + 20); PRIMOUTREG(MGAREG_DMAPAD, 0); PRIMOUTREG(MGAREG_DMAPAD, 0); @@ -758,7 +761,7 @@ static void mga_dma_dispatch_swap(drm_device_t * dev) PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset); PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess); PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset); - PRIMOUTREG(MGAREG_AR5, dev_priv->stride / 2); + PRIMOUTREG(MGAREG_AR5, pixel_stride); PRIMOUTREG(MGAREG_DMAPAD, 0); PRIMOUTREG(MGAREG_DMAPAD, 0); @@ -767,7 +770,7 @@ static void mga_dma_dispatch_swap(drm_device_t * dev) for (i = 0; i < nbox; i++) { unsigned int h = pbox[i].y2 - pbox[i].y1; - unsigned int start = pbox[i].y1 * dev_priv->stride / 2; + unsigned int start = pbox[i].y1 * pixel_stride; DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n", pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2); @@ -799,8 +802,8 @@ int mga_clear_bufs(struct inode *inode, struct file *filp, drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_clear_t clear; - copy_from_user_ret(&clear, (drm_mga_clear_t *) arg, sizeof(clear), - -EFAULT); + if (copy_from_user(&clear, (drm_mga_clear_t *) arg, sizeof(clear))) + return -EFAULT; DRM_DEBUG("%s\n", __FUNCTION__); if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { @@ -868,8 +871,8 @@ int mga_iload(struct inode *inode, struct file *filp, DRM_DEBUG("%s\n", __FUNCTION__); DRM_DEBUG("Starting Iload\n"); - copy_from_user_ret(&iload, (drm_mga_iload_t *) arg, sizeof(iload), - -EFAULT); + if (copy_from_user(&iload, (drm_mga_iload_t *) arg, sizeof(iload))) + return -EFAULT; if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_iload called without lock held\n"); @@ -913,8 +916,8 @@ int mga_vertex(struct inode *inode, struct file *filp, drm_mga_vertex_t vertex; DRM_DEBUG("%s\n", __FUNCTION__); - copy_from_user_ret(&vertex, (drm_mga_vertex_t *) arg, - sizeof(vertex), -EFAULT); + if (copy_from_user(&vertex, (drm_mga_vertex_t *) arg, sizeof(vertex))) + return -EFAULT; if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_vertex called without lock held\n"); @@ -962,8 +965,8 @@ int mga_indices(struct inode *inode, struct file *filp, drm_mga_indices_t indices; DRM_DEBUG("%s\n", __FUNCTION__); - copy_from_user_ret(&indices, (drm_mga_indices_t *) arg, - sizeof(indices), -EFAULT); + if (copy_from_user(&indices, (drm_mga_indices_t *) arg, sizeof(indices))) + return -EFAULT; if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_indices called without lock held\n"); @@ -1008,10 +1011,11 @@ static int mga_dma_get_buffers(drm_device_t * dev, drm_dma_t * d) if (!buf) break; buf->pid = current->pid; - copy_to_user_ret(&d->request_indices[i], - &buf->idx, sizeof(buf->idx), -EFAULT); - copy_to_user_ret(&d->request_sizes[i], - &buf->total, sizeof(buf->total), -EFAULT); + if (copy_to_user(&d->request_indices[i], + &buf->idx, sizeof(buf->idx)) || + copy_to_user(&d->request_sizes[i], + &buf->total, sizeof(buf->total))) + return -EFAULT; ++d->granted_count; } return 0; @@ -1027,7 +1031,8 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, drm_dma_t d; DRM_DEBUG("%s\n", __FUNCTION__); - copy_from_user_ret(&d, (drm_dma_t *) arg, sizeof(d), -EFAULT); + if (copy_from_user(&d, (drm_dma_t *) arg, sizeof(d))) + return -EFAULT; DRM_DEBUG("%d %d: %d send, %d req\n", current->pid, d.context, d.send_count, d.request_count); @@ -1062,6 +1067,7 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG("%d returning, granted = %d\n", current->pid, d.granted_count); - copy_to_user_ret((drm_dma_t *) arg, &d, sizeof(d), -EFAULT); + if (copy_to_user((drm_dma_t *) arg, &d, sizeof(d))) + return -EFAULT; return retcode; } diff --git a/drivers/char/drm/r128_bufs.c b/drivers/char/drm/r128_bufs.c index bd81dcdc04c7..7e76441ee732 100644 --- a/drivers/char/drm/r128_bufs.c +++ b/drivers/char/drm/r128_bufs.c @@ -60,10 +60,10 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, if (!dma) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; count = request.count; order = drm_order(request.size); @@ -173,10 +173,10 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, request.count = entry->buf_count; request.size = size; - copy_to_user_ret((drm_buf_desc_t *)arg, + if (copy_to_user((drm_buf_desc_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; dma->flags = _DRM_DMA_USE_AGP; @@ -195,10 +195,10 @@ int r128_addbufs(struct inode *inode, struct file *filp, unsigned int cmd, if (!dev_priv || dev_priv->is_pci) return -EINVAL; - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_desc_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) if (request.flags & _DRM_AGP_BUFFER) @@ -234,10 +234,10 @@ int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); - copy_from_user_ret(&request, + if (copy_from_user(&request, (drm_buf_map_t *)arg, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; if (request.count >= dma->buf_count) { if (dma->flags & _DRM_DMA_USE_AGP) { @@ -300,10 +300,10 @@ int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, request.count = dma->buf_count; DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode); - copy_to_user_ret((drm_buf_map_t *)arg, + if (copy_to_user((drm_buf_map_t *)arg, &request, - sizeof(request), - -EFAULT); + sizeof(request))) + return -EFAULT; return retcode; } diff --git a/drivers/char/drm/r128_context.c b/drivers/char/drm/r128_context.c index 2dd716d4b9a8..9cadadbaf0cb 100644 --- a/drivers/char/drm/r128_context.c +++ b/drivers/char/drm/r128_context.c @@ -103,19 +103,21 @@ int r128_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i; DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); - copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT); + if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res))) + return -EFAULT; if (res.count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { ctx.handle = i; - copy_to_user_ret(&res.contexts[i], + if (copy_to_user(&res.contexts[i], &i, - sizeof(i), - -EFAULT); + sizeof(i))) + return -EFAULT; } } res.count = DRM_RESERVED_CONTEXTS; - copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT); + if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res))) + return -EFAULT; return 0; } @@ -127,7 +129,8 @@ int r128_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; if ((ctx.handle = r128_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ ctx.handle = r128_alloc_queue(dev); @@ -139,7 +142,8 @@ int r128_addctx(struct inode *inode, struct file *filp, unsigned int cmd, return -ENOMEM; } - copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -148,7 +152,8 @@ int r128_modctx(struct inode *inode, struct file *filp, unsigned int cmd, { drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx))) + return -EFAULT; if (ctx.flags==_DRM_CONTEXT_PRESERVED) r128_res_ctx.handle=ctx.handle; return 0; @@ -159,10 +164,12 @@ int r128_getctx(struct inode *inode, struct file *filp, unsigned int cmd, { drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx))) + return -EFAULT; /* This is 0, because we don't hanlde any context flags */ ctx.flags = 0; - copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -173,7 +180,8 @@ int r128_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); return r128_context_switch(dev, dev->last_context, ctx.handle); } @@ -185,7 +193,8 @@ int r128_newctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); r128_context_switch_complete(dev, ctx.handle); @@ -199,7 +208,8 @@ int r128_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); drm_ctxbitmap_free(dev, ctx.handle); diff --git a/drivers/char/drm/r128_dma.c b/drivers/char/drm/r128_dma.c index 16f79c1f6840..61e9cb2baeb1 100644 --- a/drivers/char/drm/r128_dma.c +++ b/drivers/char/drm/r128_dma.c @@ -68,6 +68,7 @@ int R128_READ_PLL(drm_device_t *dev, int addr) return R128_READ(R128_CLOCK_CNTL_DATA); } +#ifdef __i386__ static void r128_flush_write_combine(void) { int xchangeDummy; @@ -86,6 +87,11 @@ static void r128_flush_write_combine(void) "pop %%ebx ;" "pop %%eax" : /* no outputs */ : /* no inputs */ ); } +#else +static void r128_flush_write_combine(void) +{ +} +#endif static void r128_status(drm_device_t *dev) { @@ -211,8 +217,8 @@ int r128_init_cce(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_r128_init_t init; - copy_from_user_ret(&init, (drm_r128_init_t *)arg, sizeof(init), - -EFAULT); + if (copy_from_user(&init, (drm_r128_init_t *)arg, sizeof(init))) + return -EFAULT; switch (init.func) { case R128_INIT_CCE: @@ -680,8 +686,8 @@ int r128_submit_pkt(struct inode *inode, struct file *filp, return -EINVAL; } - copy_from_user_ret(&packet, (drm_r128_packet_t *)arg, sizeof(packet), - -EFAULT); + if (copy_from_user(&packet, (drm_r128_packet_t *)arg, sizeof(packet))) + return -EFAULT; c = packet.count; size = c * sizeof(*buffer); @@ -696,7 +702,8 @@ int r128_submit_pkt(struct inode *inode, struct file *filp, } if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM; - copy_from_user_ret(buffer, packet.buffer, size, -EFAULT); + if (copy_from_user(buffer, packet.buffer, size)) + return -EFAULT; if (dev_priv->cce_secure) ret = r128_submit_packets_ring_secure(dev, buffer, &c); @@ -706,7 +713,8 @@ int r128_submit_pkt(struct inode *inode, struct file *filp, c += left; } else { if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM; - copy_from_user_ret(buffer, packet.buffer, size, -EFAULT); + if (copy_from_user(buffer, packet.buffer, size)) + return -EFAULT; if (dev_priv->cce_secure) ret = r128_submit_packets_pio_secure(dev, buffer, &c); @@ -717,8 +725,8 @@ int r128_submit_pkt(struct inode *inode, struct file *filp, kfree(buffer); packet.count = c; - copy_to_user_ret((drm_r128_packet_t *)arg, &packet, sizeof(packet), - -EFAULT); + if (copy_to_user((drm_r128_packet_t *)arg, &packet, sizeof(packet))) + return -EFAULT; if (ret) return ret; else if (c > 0) return -EAGAIN; @@ -855,14 +863,13 @@ static int r128_get_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v) buf = r128_freelist_get(dev); if (!buf) break; buf->pid = current->pid; - copy_to_user_ret(&v->request_indices[i], + if (copy_to_user(&v->request_indices[i], &buf->idx, - sizeof(buf->idx), - -EFAULT); - copy_to_user_ret(&v->request_sizes[i], + sizeof(buf->idx)) || + copy_to_user(&v->request_sizes[i], &buf->total, - sizeof(buf->total), - -EFAULT); + sizeof(buf->total))) + return -EFAULT; ++v->granted_count; } return 0; @@ -889,7 +896,8 @@ int r128_vertex_buf(struct inode *inode, struct file *filp, unsigned int cmd, return -EINVAL; } - copy_from_user_ret(&v, (drm_r128_vertex_t *)arg, sizeof(v), -EFAULT); + if (copy_from_user(&v, (drm_r128_vertex_t *)arg, sizeof(v))) + return -EFAULT; DRM_DEBUG("%d: %d send, %d req\n", current->pid, v.send_count, v.request_count); @@ -916,7 +924,8 @@ int r128_vertex_buf(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG("%d returning, granted = %d\n", current->pid, v.granted_count); - copy_to_user_ret((drm_r128_vertex_t *)arg, &v, sizeof(v), -EFAULT); + if (copy_to_user((drm_r128_vertex_t *)arg, &v, sizeof(v))) + return -EFAULT; return retcode; } diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c index e0080e5950e1..c42c86b56454 100644 --- a/drivers/char/drm/r128_drv.c +++ b/drivers/char/drm/r128_drv.c @@ -420,17 +420,18 @@ int r128_version(struct inode *inode, struct file *filp, unsigned int cmd, drm_version_t version; int len; - copy_from_user_ret(&version, + if (copy_from_user(&version, (drm_version_t *)arg, - sizeof(version), - -EFAULT); + sizeof(version))) + return -EFAULT; #define DRM_COPY(name,value) \ len = strlen(value); \ if (len > name##_len) len = name##_len; \ name##_len = strlen(value); \ if (len && name) { \ - copy_to_user_ret(name, value, len, -EFAULT); \ + if (copy_to_user(name, value, len)) \ + return -EFAULT; \ } version.version_major = R128_MAJOR; @@ -441,10 +442,10 @@ int r128_version(struct inode *inode, struct file *filp, unsigned int cmd, DRM_COPY(version.date, R128_DATE); DRM_COPY(version.desc, R128_DESC); - copy_to_user_ret((drm_version_t *)arg, + if (copy_to_user((drm_version_t *)arg, &version, - sizeof(version), - -EFAULT); + sizeof(version))) + return -EFAULT; return 0; } @@ -559,7 +560,8 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, dev->lck_start = start = get_cycles(); #endif - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -698,7 +700,8 @@ int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_lock_t lock; - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", diff --git a/drivers/char/drm/tdfx_context.c b/drivers/char/drm/tdfx_context.c index d6903c0ae9e0..1fd733100199 100644 --- a/drivers/char/drm/tdfx_context.c +++ b/drivers/char/drm/tdfx_context.c @@ -105,19 +105,21 @@ int tdfx_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i; DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); - copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT); + if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res))) + return -EFAULT; if (res.count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { ctx.handle = i; - copy_to_user_ret(&res.contexts[i], + if (copy_to_user(&res.contexts[i], &i, - sizeof(i), - -EFAULT); + sizeof(i))) + return -EFAULT; } } res.count = DRM_RESERVED_CONTEXTS; - copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT); + if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res))) + return -EFAULT; return 0; } @@ -129,7 +131,8 @@ int tdfx_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; if ((ctx.handle = tdfx_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ ctx.handle = tdfx_alloc_queue(dev); @@ -141,7 +144,8 @@ int tdfx_addctx(struct inode *inode, struct file *filp, unsigned int cmd, return -ENOMEM; } - copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -150,7 +154,8 @@ int tdfx_modctx(struct inode *inode, struct file *filp, unsigned int cmd, { drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx))) + return -EFAULT; if (ctx.flags==_DRM_CONTEXT_PRESERVED) tdfx_res_ctx.handle=ctx.handle; return 0; @@ -161,10 +166,12 @@ int tdfx_getctx(struct inode *inode, struct file *filp, unsigned int cmd, { drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); - /* This is 0, because we don't hanlde any context flags */ + if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx))) + return -EFAULT; + /* This is 0, because we don't handle any context flags */ ctx.flags = 0; - copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT); + if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx))) + return -EFAULT; return 0; } @@ -175,7 +182,8 @@ int tdfx_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); return tdfx_context_switch(dev, dev->last_context, ctx.handle); } @@ -187,7 +195,8 @@ int tdfx_newctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); tdfx_context_switch_complete(dev, ctx.handle); @@ -201,7 +210,8 @@ int tdfx_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_ctx_t ctx; - copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx))) + return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); drm_ctxbitmap_free(dev, ctx.handle); diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c index 59f1019708b6..b37200423957 100644 --- a/drivers/char/drm/tdfx_drv.c +++ b/drivers/char/drm/tdfx_drv.c @@ -379,17 +379,18 @@ int tdfx_version(struct inode *inode, struct file *filp, unsigned int cmd, drm_version_t version; int len; - copy_from_user_ret(&version, + if (copy_from_user(&version, (drm_version_t *)arg, - sizeof(version), - -EFAULT); + sizeof(version))) + return -EFAULT; #define DRM_COPY(name,value) \ len = strlen(value); \ if (len > name##_len) len = name##_len; \ name##_len = strlen(value); \ if (len && name) { \ - copy_to_user_ret(name, value, len, -EFAULT); \ + if (copy_to_user(name, value, len)) \ + return -EFAULT; \ } version.version_major = TDFX_MAJOR; @@ -400,10 +401,10 @@ int tdfx_version(struct inode *inode, struct file *filp, unsigned int cmd, DRM_COPY(version.date, TDFX_DATE); DRM_COPY(version.desc, TDFX_DESC); - copy_to_user_ret((drm_version_t *)arg, + if (copy_to_user((drm_version_t *)arg, &version, - sizeof(version), - -EFAULT); + sizeof(version))) + return -EFAULT; return 0; } @@ -518,7 +519,8 @@ int tdfx_lock(struct inode *inode, struct file *filp, unsigned int cmd, dev->lck_start = start = get_cycles(); #endif - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -615,6 +617,15 @@ int tdfx_lock(struct inode *inode, struct file *filp, unsigned int cmd, #endif if (!ret) { + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); + if (lock.flags & _DRM_LOCK_READY) { /* Wait for space in DMA/FIFO */ } @@ -649,7 +660,8 @@ int tdfx_unlock(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_lock_t lock; - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) + return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -679,5 +691,6 @@ int tdfx_unlock(struct inode *inode, struct file *filp, unsigned int cmd, } #endif + unblock_all_signals(); return 0; } diff --git a/drivers/char/pcmcia/serial_cb.c b/drivers/char/pcmcia/serial_cb.c index 86bb70f57a24..f959b9c40153 100644 --- a/drivers/char/pcmcia/serial_cb.c +++ b/drivers/char/pcmcia/serial_cb.c @@ -2,7 +2,7 @@ A driver for CardBus serial devices - serial_cb.c 1.15 1999/11/24 02:52:06 + serial_cb.c 1.20 2000/08/07 19:02:03 Copyright 1998, 1999 by Donald Becker and David Hinds @@ -16,7 +16,7 @@ Donald Becker may be reached as becker@CESDIS.edu, or C/O USRA Center of Excellence in Space Data and Information Sciences Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771 - David Hinds may be reached at dhinds@pcmcia.sourceforge.org + David Hinds may be reached at dahinds@users.sourceforge.net ======================================================================*/ @@ -39,7 +39,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"serial_cb.c 1.15 1999/11/24 02:52:06 (David Hinds)"; +"serial_cb.c 1.20 2000/08/07 19:02:03 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -134,7 +134,7 @@ err_out: static void serial_detach(dev_node_t *node) { - DEBUG(0, "serial_detach(tty%02d)\n", node->minor - 0x40); + DEBUG(0, "serial_detach(ttyS%02d)\n", node->minor - 0x40); unregister_serial(node->minor - 0x40); kfree(node); MOD_DEC_USE_COUNT; diff --git a/drivers/char/pcmcia/serial_cs.c b/drivers/char/pcmcia/serial_cs.c index 55442dd337c6..af25aa9e9caa 100644 --- a/drivers/char/pcmcia/serial_cs.c +++ b/drivers/char/pcmcia/serial_cs.c @@ -2,7 +2,7 @@ A driver for PCMCIA serial devices - serial_cs.c 1.118 2000/05/04 01:29:47 + serial_cs.c 1.123 2000/08/24 18:46:38 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -58,7 +58,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"serial_cs.c 1.118 2000/05/04 01:29:47 (David Hinds)"; +"serial_cs.c 1.123 2000/08/24 18:46:38 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -242,12 +242,11 @@ static int setup_serial(serial_info_t *info, ioaddr_t port, int irq) memset(&serial, 0, sizeof(serial)); serial.port = port; serial.irq = irq; - serial.flags = ASYNC_SKIP_TEST; - serial.flags |= (info->multi || info->slave) ? ASYNC_SHARE_IRQ : 0; + serial.flags = ASYNC_SKIP_TEST | ASYNC_SHARE_IRQ; line = register_serial(&serial); if (line < 0) { - printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04x, " - "irq %d failed\n", serial.port, serial.irq); + printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04lx," + " irq %d failed\n", (u_long)serial.port, serial.irq); return -1; } @@ -290,7 +289,7 @@ static int simple_config(dev_link_t *link) cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; config_info_t config; - int i, j; + int i, j, try; /* If the card is already configured, look up the port and irq */ i = CardServices(GetConfigurationInfo, handle, &config); @@ -315,22 +314,26 @@ static int simple_config(dev_link_t *link) tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - if (i != CS_SUCCESS) goto next_entry; - if (cf->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = - cf->vpp1.param[CISTPL_POWER_VNOM]/10000; - if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && - (cf->io.win[0].base != 0)) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - i = CardServices(RequestIO, link->handle, &link->io); - if (i == CS_SUCCESS) goto found_port; + /* Two tries: without IO aliases, then with aliases */ + for (try = 0; try < 2; try++) { + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if (i != CS_SUCCESS) goto next_entry; + if (cf->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + cf->vpp1.param[CISTPL_POWER_VNOM]/10000; + if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && + (cf->io.win[0].base != 0)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = (try == 0) ? + 16 : cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) goto found_port; + } + next_entry: + i = next_tuple(handle, &tuple, &parse); } - next_entry: - i = next_tuple(handle, &tuple, &parse); } /* Second pass: try to find an entry that isn't picky about @@ -448,6 +451,9 @@ static int multi_config(dev_link_t *link) } setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); + /* The Nokia cards are not really multiport cards */ + if (info->manfid == MANFID_NOKIA) + return 0; for (i = 0; i < info->multi-1; i++) setup_serial(info, base2+(8*i), link->irq.AssignedIRQ); @@ -518,11 +524,13 @@ void serial_config(dev_link_t *link) (parse.funcid.func == CISTPL_FUNCID_MULTI) || (parse.funcid.func == CISTPL_FUNCID_SERIAL))) { tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - if ((first_tuple(handle, &tuple, &parse) == CS_SUCCESS) && - (((cf->io.nwin == 1) && (cf->io.win[0].len == 16)) || - ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && - (cf->io.win[1].len == 8)))) - info->multi = 2; + if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) + info->multi = cf->io.win[0].len >> 3; + if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && + (cf->io.win[1].len == 8)) + info->multi = 2; + } } if (info->multi > 1) diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index 7629e24ad571..582503ec3428 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -14,8 +14,8 @@ * * This Driver is currently maintained by Christoph Lameter (christoph@lameter.com) * - * Please contact digi for support issues at digilnux@dgii.com. Some - * information (mostly of historical interest) can be found at + * Please contact digi for support issues at digilnux@dgii.com. + * Some more information can be found at * http://lameter.com/digi. * * 1.5.2 Fall 1995 Bug fixes by David Nugent @@ -39,17 +39,13 @@ * and Xeve also. * 1.6.2 August, 7, 2000: Arnaldo Carvalho de Melo * get rid of panics, release previously allocated resources + * 1.6.3 August, 23, 2000: Arnaldo Carvalho de Melo + * cleaned up wrt verify_area. + * Christoph Lameter: Update documentation, email addresses + * and URLs. Remove some obsolete code. * */ -#undef SPEED_HACK -/* If you define SPEED_HACK then you get the following Baudrate translation - 19200 = 57600 - 38400 = 115K - The driver supports the native 57.6K and 115K Baudrates under Linux, but - some distributions like Slackware 3.0 don't like these high baudrates. -*/ - #include #include #include @@ -81,7 +77,7 @@ #include #include -#define VERSION "1.6.2" +#define VERSION "1.6.3" #include "digi.h" #include "fep.h" @@ -713,11 +709,10 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha tail &= (size - 1); stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1); count = MIN(stlen, count); - if (count) { - if (verify_area(VERIFY_READ, (char*)buf, count)) - count=0; - else copy_from_user(ch->tmp_buf, buf, count); - } + if (count) + if (copy_from_user(ch->tmp_buf, buf, count)) + count = 0; + buf = ch->tmp_buf; memoff(ch); restore_flags(flags); @@ -1896,11 +1891,6 @@ fepcmd(struct channel *ch, int cmd, int word_or_byte, int byte2, int ncmds, static unsigned termios2digi_c(struct channel *ch, unsigned cflag) { unsigned res = 0; -#ifdef SPEED_HACK - /* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */ - if ((cflag & CBAUD)== B38400) cflag=cflag - B38400 + B115200; - if ((cflag & CBAUD)== B19200) cflag=cflag - B19200 + B57600; -#endif if (cflag & CBAUDEX) { ch->digiext.digi_flags |= DIGI_FAST; @@ -2124,7 +2114,6 @@ static void receive_data(struct channel *ch) static int pcxe_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { - int error; struct channel *ch = (struct channel *) tty->driver_data; volatile struct board_chan *bc; int retval; @@ -2163,15 +2152,13 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, return 0; case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned int *) arg); + return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned int *)arg); case TIOCSSOFTCAR: { unsigned int value; - error = get_user( value, (unsigned int *) arg); - if (error) - return error; + if (get_user(value, (unsigned int *) arg)) + return -EFAULT; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (value ? CLOCAL : 0)); } return 0; @@ -2199,18 +2186,16 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, if(mstat & ch->dcd) mflag |= TIOCM_CD; - error = put_user(mflag, (unsigned int *) arg); - if(error) - return error; + if (put_user(mflag, (unsigned int *) arg)) + return -EFAULT; break; case TIOCMBIS: case TIOCMBIC: case TIOCMODS: case TIOCMSET: - error = get_user(mstat, (unsigned int *) arg); - if(error) - return error; + if (get_user(mstat, (unsigned int *) arg)) + return -EFAULT; mflag = 0; if(mstat & TIOCM_DTR) @@ -2262,10 +2247,8 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, break; case DIGI_GETA: - if((error=verify_area(VERIFY_WRITE, (char*)arg, sizeof(digi_t)))) - return(error); - - copy_to_user((char*)arg, &ch->digiext, sizeof(digi_t)); + if (copy_to_user((char*)arg, &ch->digiext, sizeof(digi_t))) + return -EFAULT; break; case DIGI_SETAW: @@ -2282,10 +2265,8 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, /* Fall Thru */ case DIGI_SETA: - if((error=verify_area(VERIFY_READ, (char*)arg,sizeof(digi_t)))) - return(error); - - copy_from_user(&ch->digiext, (char*)arg, sizeof(digi_t)); + if (copy_from_user(&ch->digiext, (char*)arg, sizeof(digi_t))) + return -EFAULT; #ifdef DEBUG_IOCTL printk("ioctl(DIGI_SETA): flags = %x\n", ch->digiext.digi_flags); #endif @@ -2319,10 +2300,8 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, memoff(ch); restore_flags(flags); - if((error=verify_area(VERIFY_WRITE, (char*)arg,sizeof(dflow)))) - return(error); - - copy_to_user((char*)arg, &dflow, sizeof(dflow)); + if (copy_to_user((char*)arg, &dflow, sizeof(dflow))) + return -EFAULT; break; case DIGI_SETAFLOW: @@ -2335,10 +2314,8 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, stopc = ch->stopca; } - if((error=verify_area(VERIFY_READ, (char*)arg,sizeof(dflow)))) - return(error); - - copy_from_user(&dflow, (char*)arg, sizeof(dflow)); + if (copy_from_user(&dflow, (char*)arg, sizeof(dflow))) + return -EFAULT; if(dflow.startc != startc || dflow.stopc != stopc) { cli(); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index cec43ae51c3b..0981a96c06f9 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -220,10 +220,10 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, sizeof(unsigned long)))?-EFAULT:0; case I2C_RDWR: - copy_from_user_ret(&rdwr_arg, - (struct i2c_rdwr_ioctl_data *)arg, - sizeof(rdwr_arg), - -EFAULT); + if (copy_from_user(&rdwr_arg, + (struct i2c_rdwr_ioctl_data *)arg, + sizeof(rdwr_arg))) + return -EFAULT; rdwr_pa = (struct i2c_msg *) kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), @@ -280,10 +280,10 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, return res; case I2C_SMBUS: - copy_from_user_ret(&data_arg, + if (copy_from_user(&data_arg, (struct i2c_smbus_ioctl_data *) arg, - sizeof(struct i2c_smbus_ioctl_data), - -EFAULT); + sizeof(struct i2c_smbus_ioctl_data))) + return -EFAULT; if ((data_arg.size != I2C_SMBUS_BYTE) && (data_arg.size != I2C_SMBUS_QUICK) && (data_arg.size != I2C_SMBUS_BYTE_DATA) && @@ -336,15 +336,18 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, datasize = sizeof(data_arg.data->block); if ((data_arg.size == I2C_SMBUS_PROC_CALL) || - (data_arg.read_write == I2C_SMBUS_WRITE)) - copy_from_user_ret(&temp,data_arg.data,datasize, - -EFAULT); + (data_arg.read_write == I2C_SMBUS_WRITE)) { + if (copy_from_user(&temp, data_arg.data, datasize)) + return -EFAULT; + } res = i2c_smbus_xfer(client->adapter,client->addr,client->flags, data_arg.read_write, data_arg.command,data_arg.size,&temp); if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || - (data_arg.read_write == I2C_SMBUS_READ))) - copy_to_user_ret(data_arg.data,&temp,datasize,-EFAULT); + (data_arg.read_write == I2C_SMBUS_READ))) { + if (copy_to_user(data_arg.data, &temp, datasize)) + return -EFAULT; + } return res; default: diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c index 6e860021ee8d..b4ef205d5053 100644 --- a/drivers/media/video/zr36120.c +++ b/drivers/media/video/zr36120.c @@ -1242,7 +1242,8 @@ int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg) case VIDIOCCAPTURE: { int v; - get_user_ret(v,(int*)arg, -EFAULT); + if (get_user(v, (int *)arg)) + return -EFAULT; DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v)); if (v==0) { @@ -1314,7 +1315,8 @@ int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg) case VIDIOCSYNC: { int i; - get_user_ret(i,(int*)arg, -EFAULT); + if (get_user(i, (int *) arg)) + return -EFAULT; DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i)); if (i<0 || i>ZORAN_MAX_FBUFFERS) return -EINVAL; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 7a5775af89f7..7f3f76ebf29a 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -2,7 +2,7 @@ Written 1993-1998 by Donald Becker, becker@cesdis.gsfc.nasa.gov, (driver core) and - David Hinds, dhinds@pcmcia.sourceforge.org (from his PC card code). + David Hinds, dahinds@users.sourceforge.net (from his PC card code). This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. @@ -327,7 +327,7 @@ static dev_link_t *tc574_attach(void) dev->stop = &el3_close; dev->tx_timeout = el3_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; - + /* Register with Card Services */ link->next = dev_list; dev_list = link; diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 9f4a54f803e2..3cbba20b9050 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -2,9 +2,9 @@ A PCMCIA ethernet driver for the 3com 3c589 card. - Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org + Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net - 3c589_cs.c 1.151 2000/05/08 22:03:18 + 3c589_cs.c 1.153 2000/06/12 21:27:25 The network driver code is based on Donald Becker's 3c589 code: @@ -117,7 +117,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"3c589_cs.c 1.151 2000/05/08 22:03:18 (David Hinds)"; +"3c589_cs.c 1.153 2000/06/12 21:27:25 (David Hinds)"; #else #define DEBUG(n, args...) #endif diff --git a/drivers/net/pcmcia/netwave_cs.c b/drivers/net/pcmcia/netwave_cs.c index a17ac13aeae9..04c0c0e4f1bd 100644 --- a/drivers/net/pcmcia/netwave_cs.c +++ b/drivers/net/pcmcia/netwave_cs.c @@ -6,7 +6,7 @@ * Status: Experimental. * Authors: John Markus Bjørndalen * Dag Brattli - * David Hinds + * David Hinds * Created at: A long time ago! * Modified at: Mon Nov 10 11:54:37 1997 * Modified by: Dag Brattli @@ -63,7 +63,7 @@ #ifdef CONFIG_NET_PCMCIA_RADIO #include -#endif /* CONFIG_NET_PCMCIA_RADIO */ +#endif #include #include @@ -130,8 +130,7 @@ #define NETWAVE_ASR_RXRDY 0x80 #define NETWAVE_ASR_TXBA 0x01 -#define TX_TIMEOUT 20 -#define WATCHDOG_JIFFIES 32 +#define TX_TIMEOUT ((32*HZ)/100) static const unsigned int imrConfRFU1 = 0x10; /* RFU interrupt mask, keep high */ static const unsigned int imrConfIENA = 0x02; /* Interrupt enable */ @@ -151,8 +150,6 @@ static const unsigned int txConfEUD = 0x10; /* Enable Uni-Data packets */ static const unsigned int txConfKey = 0x02; /* Scramble data packets */ static const unsigned int txConfLoop = 0x01; /* Loopback mode */ -static int netwave_debug = 0; - /* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If you do not define PCMCIA_DEBUG at all, all the debug code will be @@ -223,7 +220,6 @@ static void netwave_reset(struct net_device *dev); static int netwave_open(struct net_device *dev); /* Open the device */ static int netwave_close(struct net_device *dev); /* Close the device */ static int netwave_config(struct net_device *dev, struct ifmap *map); -static void netwave_tx_timeout (struct net_device *dev); /* Packet transmission and Packet reception */ static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev); @@ -231,7 +227,7 @@ static int netwave_rx( struct net_device *dev); /* Interrupt routines */ static void netwave_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void netwave_watchdog(u_long); /* Transmission watchdog */ +static void netwave_watchdog(struct net_device *); /* Statistics */ static void update_stats(struct net_device *dev); @@ -309,7 +305,6 @@ typedef struct netwave_private { u_char *ramBase; int timeoutCounter; int lastExec; - spinlock_t lock; struct timer_list watchdog; /* To avoid blocking state */ struct site_survey nss; struct net_device_stats stats; @@ -416,18 +411,6 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev) } #endif -/* - * Function netwave_init (dev) - * - * We never need to do anything when a device is "initialized" - * by the net software, because we only register already-found cards. - */ -int netwave_init(struct net_device *dev) -{ - /* We do all the initialization of this in netwave_attach instead */ - return 0; -} - /* * Function netwave_attach (void) * @@ -456,7 +439,6 @@ static dev_link_t *netwave_attach(void) priv = kmalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return NULL; memset(priv, 0, sizeof(*priv)); - priv->lock = SPIN_LOCK_UNLOCKED; link = &priv->link; dev = &priv->dev; link->priv = dev->priv = priv; link->release.function = &netwave_release; @@ -486,10 +468,6 @@ static dev_link_t *netwave_attach(void) link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; - /* Set the watchdog timer */ - priv->watchdog.function = &netwave_watchdog; - priv->watchdog.data = (unsigned long) dev; - /* Netwave specific entries in the device structure */ dev->hard_start_xmit = &netwave_start_xmit; dev->set_config = &netwave_config; @@ -501,14 +479,12 @@ static dev_link_t *netwave_attach(void) #endif dev->do_ioctl = &netwave_ioctl; + dev->tx_timeout = &netwave_watchdog; + dev->watchdog_timeo = TX_TIMEOUT; + ether_setup(dev); - strcpy(dev->name, priv->node.dev_name); - dev->init = &netwave_init; dev->open = &netwave_open; dev->stop = &netwave_close; - dev->tx_timeout = netwave_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; - netif_start_queue (dev); link->irq.Instance = dev; /* Register with Card Services */ @@ -545,30 +521,21 @@ static void netwave_detach(dev_link_t *link) { netwave_private *priv = link->priv; dev_link_t **linkp; - long flags; DEBUG(0, "netwave_detach(0x%p)\n", link); - save_flags(flags); - if (link->state & DEV_RELEASE_PENDING) { - del_timer(&link->release); - link->state &= ~DEV_RELEASE_PENDING; - } - cli(); - restore_flags(flags); - /* If the device is currently configured and active, we won't actually delete it yet. Instead, it is marked so that when the release() function is called, that will trigger a proper detach(). */ + del_timer(&link->release); if (link->state & DEV_CONFIG) { netwave_release((u_long) link); if (link->state & DEV_STALE_CONFIG) { DEBUG(1, "netwave_cs: detach postponed, '%s' still " "locked\n", link->dev->dev_name); - link->state |= DEV_STALE_LINK; return; } @@ -641,7 +608,7 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */ struct iwreq *wrq = (struct iwreq *) rq; #endif - DEBUG( 0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd); + DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd); /* Disable interrupts & save flags */ save_flags(flags); @@ -840,7 +807,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { struct net_device *dev = &priv->dev; tuple_t tuple; cisparse_t parse; - int i=0, j, last_ret, last_fn; + int i, j, last_ret, last_fn; u_char buf[64]; win_req_t req; memreq_t mem; @@ -862,16 +829,16 @@ static void netwave_pcmcia_config(dev_link_t *link) { CS_CHECK(ParseTuple, handle, &tuple, &parse); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - + /* Configure card */ link->state |= DEV_CONFIG; - + /* * Try allocating IO ports. This tries a few fixed addresses. * If you want, you can also read the card's config table to * pick addresses -- see the serial driver for an example. */ - for (j = 0x0; j < 0x400; j += 0x20) { + for (i = j = 0x0; j < 0x400; j += 0x20) { link->io.BasePort1 = j ^ 0x300; i = CardServices(RequestIO, link->handle, &link->io); if (i == CS_SUCCESS) break; @@ -880,19 +847,19 @@ static void netwave_pcmcia_config(dev_link_t *link) { cs_error(link->handle, RequestIO, i); goto failed; } - + /* * Now allocate an interrupt line. Note that this does not * actually assign a handler to the interrupt. */ CS_CHECK(RequestIRQ, handle, &link->irq); - + /* * This actually configures the PCMCIA socket -- setting up * the I/O windows and the interrupt mapping. */ CS_CHECK(RequestConfiguration, handle, &link->conf); - + /* * Allocate a 32K memory window. Note that the dev_link_t * structure provides space for one window handle -- if your @@ -900,7 +867,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { * the handles in your private data structure, link->priv. */ DEBUG(1, "Setting mem speed of %d\n", mem_speed); - + req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE; req.Base = 0; req.Size = 0x8000; req.AccessSpeed = mem_speed; @@ -908,26 +875,25 @@ static void netwave_pcmcia_config(dev_link_t *link) { CS_CHECK(RequestWindow, &link->win, &req); mem.CardOffset = 0x20000; mem.Page = 0; CS_CHECK(MapMemPage, link->win, &mem); - + /* Store base address of the common window frame */ ramBase = ioremap(req.Base, 0x8000); ((netwave_private*)dev->priv)->ramBase = ramBase; - + dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - netif_start_queue (dev); if (register_netdev(dev) != 0) { printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n"); goto failed; } - + + strcpy(priv->node.dev_name, dev->name); + link->dev = &priv->node; link->state &= ~DEV_CONFIG_PENDING; - - link->dev = &((netwave_private *)dev->priv)->node; /* Reset card before reading physical address */ netwave_doreset(dev->base_addr, ramBase); - + /* Read the ethernet address and fill in the Netwave registers. */ for (i = 0; i < 6; i++) dev->dev_addr[i] = readb(ramBase + NETWAVE_EREG_PA + i); @@ -949,7 +915,6 @@ cs_failed: cs_error(link->handle, last_fn, last_ret); failed: netwave_release((u_long)link); - return; } /* netwave_pcmcia_config */ /* @@ -975,7 +940,7 @@ static void netwave_release(u_long arg) { link->state |= DEV_STALE_CONFIG; return; } - + /* Don't bother checking to see if these succeed or not */ if (link->win) { iounmap(priv->ramBase); @@ -984,9 +949,9 @@ static void netwave_release(u_long arg) { CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); - - link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING | DEV_STALE_CONFIG); - + + link->state &= ~(DEV_CONFIG | DEV_STALE_CONFIG); + } /* netwave_release */ /* @@ -1020,8 +985,7 @@ static int netwave_event(event_t event, int priority, link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { netif_device_detach(dev); - link->release.expires = jiffies + 5; - add_timer(&link->release); + mod_timer(&link->release, jiffies + HZ/20); } break; case CS_EVENT_CARD_INSERTION: @@ -1035,7 +999,6 @@ static int netwave_event(event_t event, int priority, if (link->state & DEV_CONFIG) { if (link->open) netif_device_detach(dev); - CardServices(ReleaseConfiguration, link->handle); } break; @@ -1082,10 +1045,7 @@ static void netwave_reset(struct net_device *dev) { DEBUG(0, "netwave_reset: Done with hardware reset\n"); priv->timeoutCounter = 0; - - /* If watchdog was activated, kill it ! */ - del_timer(&priv->watchdog); - + /* Reset card */ netwave_doreset(iobase, ramBase); printk(KERN_DEBUG "netwave_reset: Done with hardware reset\n"); @@ -1172,7 +1132,7 @@ static int netwave_hw_xmit(unsigned char* data, int len, netwave_private *priv = (netwave_private *) dev->priv; u_char* ramBase = priv->ramBase; ioaddr_t iobase = dev->base_addr; - + /* Disable interrupts & save flags */ save_flags(flags); cli(); @@ -1183,9 +1143,10 @@ static int netwave_hw_xmit(unsigned char* data, int len, /* No buffers available */ printk(KERN_DEBUG "netwave_hw_xmit: %s - no xmit buffers available.\n", dev->name); + restore_flags(flags); return 1; } - + priv->stats.tx_bytes += len; DEBUG(3, "Transmitting with SPCQ %x SPU %x LIF %x ISPLQ %x\n", @@ -1222,29 +1183,11 @@ static int netwave_hw_xmit(unsigned char* data, int len, writeb(len & 0xff, ramBase + NETWAVE_EREG_CB + 1); writeb((len>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2); writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3); - - /* If watchdog not already active, activate it... */ - if (!timer_pending(&priv->watchdog)) { - /* set timer to expire in WATCHDOG_JIFFIES */ - priv->watchdog.expires = jiffies + WATCHDOG_JIFFIES; - add_timer(&priv->watchdog); - } + restore_flags( flags); return 0; } - -static void netwave_tx_timeout (struct net_device *dev) -{ - if (netwave_debug > 0) - printk (KERN_DEBUG "%s timed out.\n", dev->name); - netwave_reset (dev); - dev->trans_start = jiffies; - netif_start_queue (dev); -} - - - static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) { /* This flag indicate that the hardware can't perform a transmission. * Theoritically, NET3 check it before sending a packet to the driver, @@ -1252,23 +1195,15 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) { * As the watchdog will abort too long transmissions, we are quite safe... */ - /* Sending a NULL skb means some higher layer thinks we've missed an - * tx-done interrupt. Caution: dev_tint() handles the cli()/sti() - * itself. - */ + netif_stop_queue(dev); - /* Block a timer-based transmit from overlapping. This could - * better be done with atomic_swap(1, dev->tbusy, but set_bit() - * works as well - */ - netif_stop_queue (dev); - if (1) { + { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char* buf = skb->data; if (netwave_hw_xmit( buf, length, dev) == 1) { /* Some error, let's make them call us another time? */ - netif_start_queue (dev); + netif_start_queue(dev); } dev->trans_start = jiffies; } @@ -1295,11 +1230,9 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { dev_link_t *link = &priv->link; int i; - if ((dev == NULL) || !netif_device_present(dev)) + if (!netif_device_present(dev)) return; - spin_lock (&priv->lock); - iobase = dev->base_addr; ramBase = priv->ramBase; @@ -1313,9 +1246,9 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { status = inb(iobase + NETWAVE_REG_ASR); - if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) { - DEBUG( 1, "netwave_interupt: Interrupt with status 0x%x " - "from removed or suspended card!\n", status); + if (!DEV_OK(link)) { + DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x " + "from removed or suspended card!\n", status); break; } @@ -1393,21 +1326,15 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { DEBUG(3, "New status is TSER %x ASR %x\n", readb(ramBase + NETWAVE_EREG_TSER), inb(iobase + NETWAVE_REG_ASR)); - - /* If watchdog was activated, kill it ! */ - del_timer(&priv->watchdog); - netif_wake_queue (dev); + netif_wake_queue(dev); } /* TxBA, this would trigger on all error packets received */ /* if (status & 0x01) { - if (netwave_debug > 3) - printk(KERN_DEBUG "Transmit buffers available, %x\n", status); - } + DEBUG(4, "Transmit buffers available, %x\n", status); + } */ } - /* done.. */ - spin_unlock (&priv->lock); } /* netwave_interrupt */ /* @@ -1418,20 +1345,12 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { * it expire, we reset the card. * */ -static void netwave_watchdog(u_long a) { - struct net_device *dev; - ioaddr_t iobase; - - dev = (struct net_device *) a; - iobase = dev->base_addr; - - DEBUG( 1, "%s: netwave_watchdog: watchdog timer expired\n", dev->name); - - netwave_reset(dev); - - /* We are not waiting anymore... */ - netif_start_queue (dev); - +static void netwave_watchdog(struct net_device *dev) { + + DEBUG(1, "%s: netwave_watchdog: watchdog timer expired\n", dev->name); + netwave_reset(dev); + dev->trans_start = jiffies; + netif_start_queue(dev); } /* netwave_watchdog */ static struct net_device_stats *netwave_get_stats(struct net_device *dev) { @@ -1569,8 +1488,8 @@ static int netwave_open(struct net_device *dev) { link->open++; MOD_INC_USE_COUNT; - - netif_start_queue (dev); + + netif_start_queue(dev); netwave_reset(dev); return 0; @@ -1582,17 +1501,10 @@ static int netwave_close(struct net_device *dev) { DEBUG(1, "netwave_close: finishing.\n"); - netif_stop_queue (dev); - - /* If watchdog was activated, kill it ! */ - del_timer(&priv->watchdog); - link->open--; - if (link->state & DEV_STALE_CONFIG) { - link->release.expires = jiffies + 5; - link->state |= DEV_RELEASE_PENDING; - add_timer(&link->release); - } + netif_stop_queue(dev); + if (link->state & DEV_STALE_CONFIG) + mod_timer(&link->release, jiffies + HZ/20); MOD_DEC_USE_COUNT; return 0; diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 9084bfdc311c..0dccc399c8d9 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -28,7 +28,7 @@ References Dean Siasoyco, New Media Corporation Ken Lesniak, Silicon Graphics, Inc. Donald Becker - David Hinds + David Hinds The Linux client driver is based on the 3c589_cs.c client driver by David Hinds. diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 9eff09aab7e1..0f95529610da 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -9,9 +9,9 @@ Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory mode. It will also handle the Socket EA card in either mode. - Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org + Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net - pcnet_cs.c 1.117 2000/05/04 01:29:47 + pcnet_cs.c 1.124 2000/07/21 19:47:31 The network driver code is based on Donald Becker's NE2000 code: @@ -72,7 +72,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"pcnet_cs.c 1.117 2000/05/04 01:29:47 (David Hinds)"; +"pcnet_cs.c 1.124 2000/07/21 19:47:31 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -153,7 +153,8 @@ typedef struct hw_info_t { #define USE_BIG_BUF 0x04 #define HAS_IBM_MISC 0x08 #define IS_DL10019 0x10 -#define IS_AX88190 0x20 +#define IS_DL10022 0x20 +#define IS_AX88190 0x40 #define USE_SHMEM 0x80 /* autodetected */ static hw_info_t hw_info[] = { @@ -219,10 +220,9 @@ static hw_info_t hw_info[] = { #define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t)) -static hw_info_t default_info = -{ /* Unknown NE2000 Clone */ 0x00, 0x00, 0x00, 0x00, 0 }; -static hw_info_t dl10019_info = -{ /* D-Link DL10019 chipset */ 0x00, 0x00, 0x00, 0x00, IS_DL10019 }; +static hw_info_t default_info = { 0, 0, 0, 0, 0 }; +static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019 }; +static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10019|IS_DL10022 }; typedef struct pcnet_dev_t { struct net_device dev; /* so &dev == &pcnet_dev_t */ @@ -232,7 +232,7 @@ typedef struct pcnet_dev_t { caddr_t base; struct timer_list watchdog; int stale, fast_poll; - u_char link_status; + u_short link_status; } pcnet_dev_t; /*====================================================================== @@ -504,7 +504,8 @@ static hw_info_t *get_dl10019(dev_link_t *link) return NULL; for (i = 0; i < 6; i++) dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i); - return &dl10019_info; + i = inb(dev->base_addr + 0x1f); + return ((i == 0x91)||(i == 0x99)) ? &dl10022_info : &dl10019_info; } /*====================================================================== @@ -723,14 +724,18 @@ static void pcnet_config(dev_link_t *link) hw_info = get_hwired(link); if (hw_info == NULL) { - printk(KERN_NOTICE "pcnet_cs: unable to read hardware net address\n"); - goto config_undo; + printk(KERN_NOTICE "pcnet_cs: unable to read hardware net" + " address for io base %#3lx\n", dev->base_addr); + unregister_netdev(dev); + goto failed; } info->flags = hw_info->flags; /* Check for user overrides */ info->flags |= (delay_output) ? DELAY_OUTPUT : 0; - if ((manfid == MANFID_SOCKET) && (prodid == PRODID_SOCKET_LPE)) + if ((manfid == MANFID_SOCKET) && + ((prodid == PRODID_SOCKET_LPE) || + (prodid == PRODID_SOCKET_EIO))) info->flags &= ~USE_BIG_BUF; if (!use_big_buf) info->flags &= ~USE_BIG_BUF; @@ -760,8 +765,9 @@ static void pcnet_config(dev_link_t *link) if (info->flags & IS_DL10019) { dev->do_ioctl = &do_ioctl; - printk(KERN_INFO "%s: NE2000 (DL10019 rev %02x): ", - dev->name, inb(dev->base_addr + 0x1a)); + printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ", + dev->name, ((info->flags & IS_DL10022) ? 22 : 19), + inb(dev->base_addr + 0x1a)); } else if (info->flags & IS_AX88190) { printk(KERN_INFO "%s: NE2000 (AX88190): ", dev->name); } else @@ -776,9 +782,6 @@ static void pcnet_config(dev_link_t *link) printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); return; -config_undo: - unregister_netdev(dev); - goto failed; cs_failed: cs_error(link->handle, last_fn, last_ret); failed: @@ -876,6 +879,79 @@ static int pcnet_event(event_t event, int priority, return 0; } /* pcnet_event */ +/*====================================================================== + + MII interface support for DL10019 and DL10022 based cards + + On the DL10019, the MII IO direction bit is 0x10; on the DL10022 + it is 0x20. Setting both bits seems to work on both card types. + +======================================================================*/ + +#define DLINK_GPIO 0x1c +#define DLINK_DIAG 0x1d +#define MDIO_SHIFT_CLK 0x80 +#define MDIO_DATA_OUT 0x40 +#define MDIO_DIR_WRITE 0x30 +#define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE) +#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT) +#define MDIO_DATA_READ 0x10 +#define MDIO_MASK 0x0f + +static void mdio_sync(ioaddr_t addr) +{ + int bits, mask = inb(addr) & MDIO_MASK; + for (bits = 0; bits < 32; bits++) { + outb(mask | MDIO_DATA_WRITE1, addr); + outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr); + } +} + +static int mdio_read(ioaddr_t addr, int phy_id, int loc) +{ + u_int cmd = (0x06<<10)|(phy_id<<5)|loc; + int i, retval = 0, mask = inb(addr) & MDIO_MASK; + + mdio_sync(addr); + for (i = 13; i >= 0; i--) { + int dat = (cmd&(1< 0; i--) { + outb(mask, addr); + retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0); + outb(mask | MDIO_SHIFT_CLK, addr); + } + return (retval>>1) & 0xffff; +} + +static void mdio_write(ioaddr_t addr, int phy_id, int loc, int value) +{ + u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value; + int i, mask = inb(addr) & MDIO_MASK; + + mdio_sync(addr); + for (i = 31; i >= 0; i--) { + int dat = (cmd&(1<= 0; i--) { + outb(mask, addr); + outb(mask | MDIO_SHIFT_CLK, addr); + } +} + +static void mdio_reset(ioaddr_t addr, int phy_id) +{ + outb_p(0x08, addr); + outb_p(0x0c, addr); + outb_p(0x08, addr); + outb_p(0x0c, addr); + outb_p(0x00, addr); +} + /*====================================================================*/ static void set_misc_reg(struct net_device *dev) @@ -894,6 +970,12 @@ static void set_misc_reg(struct net_device *dev) tmp |= 8; outb_p(tmp, nic_base + PCNET_MISC); } + if (info->flags & IS_DL10022) { + mdio_reset(nic_base + DLINK_GPIO, 0); + /* Restart MII autonegotiation */ + mdio_write(nic_base + DLINK_GPIO, 0, 0, 0x0000); + mdio_write(nic_base + DLINK_GPIO, 0, 0, 0x1200); + } } /*====================================================================*/ @@ -914,8 +996,7 @@ static int pcnet_open(struct net_device *dev) set_misc_reg(dev); request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev); - /* Start by assuming the link is bad */ - info->link_status = 1; + info->link_status = 0x00; info->watchdog.function = &ei_watchdog; info->watchdog.data = (u_long)info; info->watchdog.expires = jiffies + HZ; @@ -1008,13 +1089,14 @@ static void ei_watchdog(u_long arg) pcnet_dev_t *info = (pcnet_dev_t *)(arg); struct net_device *dev = &info->dev; ioaddr_t nic_base = dev->base_addr; + u_short link; if (!netif_device_present(dev)) goto reschedule; /* Check for pending interrupt with expired latency timer: with this, we can limp along even if the interrupt is blocked */ outb_p(E8390_NODMA+E8390_PAGE0, nic_base + E8390_CMD); - if (info->stale++ && inb_p(nic_base + EN0_ISR)) { + if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { if (!info->fast_poll) printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); ei_irq_wrapper(dev->irq, dev, NULL); @@ -1027,15 +1109,30 @@ static void ei_watchdog(u_long arg) return; } - if (info->flags & IS_DL10019) { - u_char link = inb(dev->base_addr+0x1c) & 0x01; - if (link != info->link_status) { - printk(KERN_INFO "%s: %s link beat\n", dev->name, - (link) ? "lost" : "found"); - if (!link) - NS8390_init(dev, 1); - info->link_status = link; + if (!(info->flags & IS_DL10019)) + goto reschedule; + + link = mdio_read(dev->base_addr + DLINK_GPIO, 0, 1) & 0x0004; + if (link != info->link_status) { + u_short p = mdio_read(dev->base_addr + DLINK_GPIO, 0, 5); + printk(KERN_INFO "%s: %s link beat\n", dev->name, + (link) ? "found" : "lost"); + if (link && (info->flags & IS_DL10022)) { + /* Disable collision detection on full duplex links */ + outb((p & 0x0140) ? 4 : 0, dev->base_addr + DLINK_DIAG); + } + if (link) { + if (p) + printk(KERN_INFO "%s: autonegotiation complete: " + "%sbaseT-%cD selected\n", dev->name, + ((p & 0x0180) ? "100" : "10"), + ((p & 0x0140) ? 'F' : 'H')); + else + printk(KERN_INFO "%s: link partner did not autonegotiate\n", + dev->name); + NS8390_init(dev, 1); } + info->link_status = link; } reschedule: @@ -1043,83 +1140,22 @@ reschedule: add_timer(&info->watchdog); } -/*====================================================================== - - MII interface support for DL10019 based cards - - There are two types of DL10019 based cards. Some have the MII IO - direction bit as 0x10, others as 0x20; setting both bits seems to - work on all cards. - -======================================================================*/ - -#define MDIO_SHIFT_CLK 0x80 -#define MDIO_DATA_OUT 0x40 -#define MDIO_DIR_WRITE 0x30 -#define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE) -#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT) -#define MDIO_DATA_READ 0x10 -#define MDIO_MASK 0x0f - -static void mdio_sync(ioaddr_t addr) -{ - int bits, mask = inb(addr) & MDIO_MASK; - for (bits = 0; bits < 32; bits++) { - outb(mask | MDIO_DATA_WRITE1, addr); - outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr); - } -} - -static int mdio_read(ioaddr_t addr, int phy_id, int loc) -{ - u_int cmd = (0x06<<10)|(phy_id<<5)|loc; - int i, retval = 0, mask = inb(addr) & MDIO_MASK; - - mdio_sync(addr); - for (i = 13; i >= 0; i--) { - int dat = (cmd&(1< 0; i--) { - outb(mask, addr); - retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0); - outb(mask | MDIO_SHIFT_CLK, addr); - } - return (retval>>1) & 0xffff; -} - -static void mdio_write(ioaddr_t addr, int phy_id, int loc, int value) -{ - u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value; - int i, mask = inb(addr) & MDIO_MASK; - - mdio_sync(addr); - for (i = 31; i >= 0; i--) { - int dat = (cmd&(1<= 0; i--) { - outb(mask, addr); - outb(mask | MDIO_SHIFT_CLK, addr); - } -} +/*====================================================================*/ static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { u16 *data = (u16 *)&rq->ifr_data; - ioaddr_t addr = dev->base_addr + 0x1c; + ioaddr_t addr = dev->base_addr + DLINK_GPIO; switch (cmd) { case SIOCDEVPRIVATE: data[0] = 0; case SIOCDEVPRIVATE+1: - data[3] = mdio_read(addr, 0, data[1] & 0x1f); + data[3] = mdio_read(addr, data[0], data[1] & 0x1f); return 0; case SIOCDEVPRIVATE+2: if (!capable(CAP_NET_ADMIN)) return -EPERM; - mdio_write(addr, 0, data[1] & 0x1f, data[2]); + mdio_write(addr, data[0], data[1] & 0x1f, data[2]); return 0; } return -EOPNOTSUPP; diff --git a/drivers/net/pcmcia/ray_cs.c b/drivers/net/pcmcia/ray_cs.c index 4415239ab52d..0612ff81831c 100644 --- a/drivers/net/pcmcia/ray_cs.c +++ b/drivers/net/pcmcia/ray_cs.c @@ -318,6 +318,23 @@ static void cs_error(client_handle_t handle, int func, int ret) error_info_t err = { func, ret }; pcmcia_report_error(handle, &err); } +/*====================================================================== + + This bit of code is used to avoid unregistering network devices + at inappropriate times. 2.2 and later kernels are fairly picky + about when this can happen. + +======================================================================*/ + +static void flush_stale_links(void) +{ + dev_link_t *link, *next; + for (link = dev_list; link; link = next) { + next = link->next; + if (link->state & DEV_STALE_LINK) + ray_detach(link); + } +} /*============================================================================= ray_attach() creates an "instance" of the driver, allocating @@ -336,6 +353,7 @@ static dev_link_t *ray_attach(void) struct net_device *dev; DEBUG(1, "ray_attach()\n"); + flush_stale_links(); /* Initialize the dev_link_t structure */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); @@ -384,7 +402,6 @@ static dev_link_t *ray_attach(void) dev->priv = local; local->finder = link; - link->dev = &local->node; local->card_status = CARD_INSERTED; local->authentication_state = UNAUTHENTICATED; local->num_multi = 0; @@ -451,8 +468,6 @@ fail_alloc_dev: static void ray_detach(dev_link_t *link) { dev_link_t **linkp; - struct net_device *dev; - long flags; DEBUG(1, "ray_detach(0x%p)\n", link); @@ -462,19 +477,12 @@ static void ray_detach(dev_link_t *link) if (*linkp == NULL) return; - save_flags(flags); - cli(); - if (link->state & DEV_RELEASE_PENDING) { - del_timer(&link->release); - link->state &= ~DEV_RELEASE_PENDING; - } - restore_flags(flags); - /* If the device is currently configured and active, we won't actually delete it yet. Instead, it is marked so that when the release() function is called, that will trigger a proper detach(). */ + del_timer(&link->release); if (link->state & DEV_CONFIG) { ray_release((u_long)link); if(link->state & DEV_STALE_CONFIG) { @@ -490,10 +498,10 @@ static void ray_detach(dev_link_t *link) /* Unlink device structure, free pieces */ *linkp = link->next; if (link->priv) { - dev = link->priv; + struct net_device *dev = link->priv; + if (link->dev) unregister_netdev(dev); if (dev->priv) kfree(dev->priv); - kfree(link->priv); } kfree(link); @@ -606,6 +614,7 @@ static void ray_config(dev_link_t *link) } strcpy(local->node.dev_name, dev->name); + link->dev = &local->node; link->state &= ~DEV_CONFIG_PENDING; printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ", @@ -907,9 +916,7 @@ static void ray_release(u_long arg) return; } del_timer(&local->timer); - if (link->dev != '\0') unregister_netdev(dev); - /* Unlink the device chain */ - link->dev = NULL; + link->state &= ~DEV_CONFIG; iounmap(local->sram); iounmap(local->rmem); @@ -926,8 +933,6 @@ static void ray_release(u_long arg) i = pcmcia_release_irq(link->handle, &link->irq); if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i); - link->state &= ~DEV_CONFIG; - if (link->state & DEV_STALE_LINK) ray_detach(link); DEBUG(2,"ray_release ending\n"); } /* ray_release */ /*============================================================================= @@ -954,8 +959,7 @@ static int ray_event(event_t event, int priority, link->state &= ~DEV_PRESENT; netif_device_detach(dev); if (link->state & DEV_CONFIG) { - link->release.expires = jiffies + HZ/20; - add_timer(&link->release); + mod_timer(&link->release, jiffies + HZ/20); del_timer(&local->timer); } break; @@ -1006,7 +1010,7 @@ int ray_dev_init(struct net_device *dev) if ( (i = dl_startup_params(dev)) < 0) { printk(KERN_INFO "ray_dev_init dl_startup_params failed - " - "returns 0x%x/n",i); + "returns 0x%x\n",i); return -1; } @@ -1554,11 +1558,8 @@ static int ray_dev_close(struct net_device *dev) link->open--; netif_stop_queue(dev); - if (link->state & DEV_STALE_CONFIG) { - link->release.expires = jiffies + HZ/20; - link->state |= DEV_RELEASE_PENDING; - add_timer(&link->release); - } + if (link->state & DEV_STALE_CONFIG) + mod_timer(&link->release, jiffies + HZ/20); MOD_DEC_USE_COUNT; @@ -2773,10 +2774,9 @@ static void __exit exit_ray_cs(void) #endif unregister_pcmcia_driver(&dev_info); - while (dev_list != NULL) { - if (dev_list->state & DEV_CONFIG) ray_release((u_long)dev_list); + while (dev_list != NULL) ray_detach(dev_list); - } + #ifdef CONFIG_PROC_FS remove_proc_entry("driver/ray_cs/ray_cs", NULL); remove_proc_entry("driver/ray_cs/essid", NULL); diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index be17da056566..76e9ff28f961 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -6,13 +6,13 @@ Megahertz, Motorola, Ositech, and Psion Dacom ethernet/modem multifunction cards. - Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org + Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net - smc91c92_cs.c 1.96 2000/05/09 02:35:58 + smc91c92_cs.c 1.104 2000/08/31 21:25:13 This driver contains code written by Donald Becker (becker@cesdis.gsfc.nasa.gov), Rowan Hughes (x-csrdh@jcu.edu.au), - David Hinds (dhinds@pcmcia.sourceforge.org), and Erik Stahlman + David Hinds (dahinds@users.sourceforge.net), and Erik Stahlman (erik@vt.edu). Donald wrote the SMC 91c92 code using parts of Erik's SMC 91c94 driver. Rowan wrote a similar driver, and I've incorporated some parts of his driver here. I (Dave) wrote most @@ -635,11 +635,12 @@ static void mot_config(dev_link_t *link) mdelay(100); } -static int mot_setup(dev_link_t *link) { +static int mot_setup(dev_link_t *link) +{ struct smc_private *smc = link->priv; struct net_device *dev = &smc->dev; ioaddr_t ioaddr = dev->base_addr; - int i, wait=0, loop; + int i, wait, loop; u_int addr; /* Read Ethernet address from Serial EEPROM */ @@ -650,7 +651,7 @@ static int mot_setup(dev_link_t *link) { SMC_SELECT_BANK(1); outw((CTL_RELOAD | CTL_EE_SELECT), ioaddr + CONTROL); - for (loop = 0; loop < 200; loop++) { + for (loop = wait = 0; loop < 200; loop++) { udelay(10); wait = ((CTL_RELOAD | CTL_STORE) & inw(ioaddr + CONTROL)); if (wait == 0) break; @@ -751,7 +752,7 @@ static int osi_config(dev_link_t *link) struct smc_private *smc = link->priv; struct net_device *dev = &smc->dev; static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; - int i=0, j; + int i, j; link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; @@ -765,7 +766,7 @@ static int osi_config(dev_link_t *link) /* Enable Hard Decode, LAN, Modem */ link->conf.ConfigIndex = 0x23; - for (j = 0; j < 4; j++) { + for (i = j = 0; j < 4; j++) { link->io.BasePort2 = com[j]; i = CardServices(RequestIO, link->handle, &link->io); if (i == CS_SUCCESS) break; @@ -808,15 +809,16 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) for (i = 0; i < 6; i++) dev->dev_addr[i] = buf[i+2]; - if (manfid != MANFID_OSITECH) return 0; - - if (cardid == PRODID_OSITECH_SEVEN) { + if (((manfid == MANFID_OSITECH) && + (cardid == PRODID_OSITECH_SEVEN)) || + ((manfid == MANFID_PSION) && + (cardid == PRODID_PSION_NET100))) { /* Download the Seven of Diamonds firmware */ for (i = 0; i < sizeof(__Xilinx7OD); i++) { outb(__Xilinx7OD[i], link->io.BasePort1+2); udelay(50); } - } else { + } else if (manfid == MANFID_OSITECH) { /* Make sure both functions are powered up */ set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR); /* Now, turn on the interrupt for both card functions */ @@ -927,7 +929,8 @@ static void smc91c92_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; - if (smc->manfid == MANFID_OSITECH) { + if ((smc->manfid == MANFID_OSITECH) && + (smc->cardid != PRODID_OSITECH_SEVEN)) { i = osi_config(link); } else if ((smc->manfid == MANFID_MOTOROLA) || ((smc->manfid == MANFID_MEGAHERTZ) && @@ -1001,7 +1004,7 @@ static void smc91c92_config(dev_link_t *link) for (i = 0; i < 6; i++) printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); if (rev > 0) { - u_long mir, mcr, mii; + u_long mir, mcr; ioaddr_t ioaddr = dev->base_addr; SMC_SELECT_BANK(0); mir = inw(ioaddr + MEMINFO) & 0xff; @@ -1014,8 +1017,14 @@ static void smc91c92_config(dev_link_t *link) else printk(KERN_INFO " %lu kb", mir>>10); SMC_SELECT_BANK(1); - mii = inw(ioaddr + CONFIG) & CFG_MII_SELECT; - printk(" buffer, %s xcvr\n", mii ? "MII" : if_names[dev->if_port]); + smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT; + smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC; + if (smc->manfid == MANFID_OSITECH) + smc->cfg |= CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0; + if ((rev >> 4) >= 7) + smc->cfg |= CFG_MII_SELECT; + printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ? + "MII" : if_names[dev->if_port]); } return; @@ -1321,7 +1330,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) DEBUG(2, "%s: smc91c92_start_xmit(length = %d) called," " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2)); - + if (smc->saved_skb) { /* THIS SHOULD NEVER HAPPEN. */ smc->stats.tx_aborted_errors++; @@ -1808,9 +1817,6 @@ static void smc_reset(struct net_device *dev) Accept link errors, counter and Tx error interrupts. */ outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE, ioaddr + CONTROL); - smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT; - smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC | - (smc->manfid == MANFID_OSITECH ? (CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0) : 0); smc_set_xcvr(dev, dev->if_port); if ((smc->manfid == MANFID_OSITECH) && (smc->cardid != PRODID_OSITECH_SEVEN)) diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 289d1bccc877..cf98d7401e46 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -2,43 +2,14 @@ * Xircom CreditCard Ethernet Adapter IIps driver * Xircom Realport 10/100 (RE-100) driver * - * This driver originally was made by Werner Koch. Since the driver was left - * unmaintained for some time, there have been some improvements and changes - * since. These include supporting some of the "Realport" cards and develop- - * ing enhancements to support the new ones. - * It is made for CE2, CEM28, CEM33, CE33 and - * CEM56 cards. The CEM56 cards work both with their modem and ethernet - * interface. The RealPort 10/100 Modem and similar cards are supported but - * with some bugs which are being corrected as they are detected. + * This driver supports various Xircom CreditCard Ethernet adapters + * including the CE2, CE IIps, RE-10, CEM28, CEM33, CE33, CEM56, + * CE3-100, CE3B, RE-100, REM10BT, and REM56G-100. * - * Code revised and maintained by Allan Baker Ortegon - * al527261@prodigy.net.mx * Written originally by Werner Koch based on David Hinds' skeleton of the - * PCMCIA driver. The code has been modified as to make the newer cards - * available. + * PCMCIA driver. * - * The latest code for the driver, information on the development project - * for the Xircom RealPort and CE cards for the PCMCIA driver, and other - * related material, can be found at the following URL, which is underway: - * - * "http://xirc2ps.linuxbox.com/index.html" - * - * Any bugs regarding this driver, please send them to: - * alanyuu@linuxbox.com - * - * The driver is still evolving and there are many cards which will benefit - * from having alpha testers. If you have a particular card and would like - * to be involved in this ongoing effort, please send mail to the maintainer. - * - * Special thanks to David Hinds, to Xircom for the specifications and their - * software development kit, and all others who may have colaborated in the - * development of the driver: Koen Van Herck (Koen.Van.Herck@xircom.com), - * 4PC GmbH Duesseldorf, David Luger, et al. - * - * - ************************************************************************ * Copyright (c) 1997,1998 Werner Koch (dd9jn) - * Copyright (c) 1999 Allan Baker Ortegon * * This driver is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -87,9 +58,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Enable the bug fix for CEM56 to use modem and ethernet simultaneously */ -#define CEM56_FIX - #include #include #include @@ -118,16 +86,10 @@ #include #include -#ifndef MANFID_XIRCOM - #define MANFID_XIRCOM 0x0105 -#endif #ifndef MANFID_COMPAQ #define MANFID_COMPAQ 0x0138 #define MANFID_COMPAQ2 0x0183 /* is this correct? */ #endif -#ifndef MANFID_INTEL - #define MANFID_INTEL 0x0089 -#endif #include @@ -936,26 +898,26 @@ xirc2ps_config(dev_link_t * link) switch(parse.manfid.manf) { case MANFID_XIRCOM: local->manf_str = "Xircom"; - DEBUG(0, "found xircom card\n"); break; case MANFID_ACCTON: local->manf_str = "Accton"; - DEBUG(0, "found Accton card\n"); break; case MANFID_COMPAQ: case MANFID_COMPAQ2: local->manf_str = "Compaq"; - DEBUG(0, "found Compaq card\n"); break; case MANFID_INTEL: local->manf_str = "Intel"; - DEBUG(0, "found Intel card\n"); + break; + case MANFID_TOSHIBA: + local->manf_str = "Toshiba"; break; default: printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n", (unsigned)parse.manfid.manf); goto failure; } + DEBUG(0, "found %s card\n", local->manf_str); if (!set_card_type(link, buf)) { printk(KNOT_XIRC "this card is not supported\n"); @@ -1120,13 +1082,10 @@ xirc2ps_config(dev_link_t * link) } if (local->dingo) { - #ifdef CEM56_FIX conf_reg_t reg; - #endif win_req_t req; memreq_t mem; - #ifdef CEM56_FIX /* Reset the modem's BAR to the correct value * This is necessary because in the RequestConfiguration call, * the base address of the ethernet port (BasePort1) is written @@ -1148,7 +1107,6 @@ xirc2ps_config(dev_link_t * link) cs_error(link->handle, AccessConfigurationRegister, err); goto config_error; } - #endif /* There is no config entry for the Ethernet part which * is at 0x0800. So we allocate a window into the attribute @@ -1227,9 +1185,9 @@ xirc2ps_config(dev_link_t * link) goto config_error; } - link->state &= ~DEV_CONFIG_PENDING; strcpy(local->node.dev_name, dev->name); link->dev = &local->node; + link->state &= ~DEV_CONFIG_PENDING; if (local->dingo) do_reset(dev, 1); /* a kludge to make the cem56 work */ diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index be015f1957c7..130f6b27d830 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -1043,9 +1043,10 @@ static inline int cosa_download(struct cosa_data *cosa, struct cosa_download *d) return -EPERM; } - get_user_ret(addr, &(d->addr), -EFAULT); - get_user_ret(len, &(d->len), -EFAULT); - get_user_ret(code, &(d->code), -EFAULT); + if (get_user(addr, &(d->addr)) || + __get_user(len, &(d->len)) || + __get_user(code, &(d->code))) + return -EFAULT; if (d->addr < 0 || d->addr > COSA_MAX_FIRMWARE_SIZE) return -EINVAL; @@ -1083,9 +1084,10 @@ static inline int cosa_readmem(struct cosa_data *cosa, struct cosa_download *d) return -EPERM; } - get_user_ret(addr, &(d->addr), -EFAULT); - get_user_ret(len, &(d->len), -EFAULT); - get_user_ret(code, &(d->code), -EFAULT); + if (get_user(addr, &(d->addr)) || + __get_user(len, &(d->len)) || + __get_user(code, &(d->code))) + return -EFAULT; /* If something fails, force the user to reset the card */ cosa->firmware_status &= ~COSA_FW_RESET; @@ -1133,7 +1135,8 @@ static inline int cosa_start(struct cosa_data *cosa, int address) static inline int cosa_getidstr(struct cosa_data *cosa, char *string) { int l = strlen(cosa->id_string)+1; - copy_to_user_ret(string, cosa->id_string, l, -EFAULT); + if (copy_to_user(string, cosa->id_string, l)) + return -EFAULT; return l; } @@ -1141,7 +1144,8 @@ static inline int cosa_getidstr(struct cosa_data *cosa, char *string) static inline int cosa_gettype(struct cosa_data *cosa, char *string) { int l = strlen(cosa->type)+1; - copy_to_user_ret(string, cosa->type, l, -EFAULT); + if (copy_to_user(string, cosa->type, l)) + return -EFAULT; return l; } @@ -1429,7 +1433,8 @@ static int download(struct cosa_data *cosa, char *microcode, int length, int add while (length--) { char c; #ifndef SRP_DOWNLOAD_AT_BOOT - get_user_ret(c,microcode, -23); + if (get_user(c, microcode)) + return -23; /* ??? */ #else c = *microcode; #endif @@ -1507,7 +1512,8 @@ static int readmem(struct cosa_data *cosa, char *microcode, int length, int addr } c=i; #if 1 - put_user_ret(c,microcode, -23); + if (put_user(c, microcode)) + return -23; /* ??? */ #else *microcode = c; #endif diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c index 43e47c75b21f..e20918a25002 100644 --- a/drivers/pcmcia/bulkmem.c +++ b/drivers/pcmcia/bulkmem.c @@ -2,7 +2,7 @@ PCMCIA Bulk Memory Services - bulkmem.c 1.34 1999/11/17 01:37:55 + bulkmem.c 1.37 2000/06/12 21:29:35 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -62,7 +62,7 @@ static int do_mtd_request(memory_handle_t handle, mtd_request_t *req, caddr_t buf) { - int ret=0, tries; + int ret, tries; client_t *mtd; socket_info_t *s; @@ -70,7 +70,7 @@ static int do_mtd_request(memory_handle_t handle, mtd_request_t *req, if (mtd == NULL) return CS_GENERAL_FAILURE; s = SOCKET(mtd); - for (tries = 0; tries < 100; tries++) { + for (ret = tries = 0; tries < 100; tries++) { mtd->event_callback_args.mtdrequest = req; mtd->event_callback_args.buffer = buf; ret = EVENT(mtd, CS_EVENT_MTD_REQUEST, CS_EVENT_PRI_LOW); diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 92ecb49ba5eb..0216ed2b3ade 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -232,21 +232,6 @@ fail: =====================================================================*/ -static int cb_assign_irq(u32 mask) -{ - int irq, try; - - for (try = 0; try < 2; try++) { - for (irq = 1; irq < 32; irq++) { - if ((mask >> irq) & 1) { - if (try_irq(IRQ_TYPE_EXCLUSIVE, irq, try) == 0) - return irq; - } - } - } - return 0; -} - int cb_alloc(socket_info_t * s) { struct pci_bus *bus; @@ -310,8 +295,6 @@ int cb_alloc(socket_info_t * s) /* Does this function have an interrupt at all? */ pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin); if (irq_pin) { - if (!irq) - irq = cb_assign_irq(s->cap.irq_mask); dev->irq = irq; pci_writeb(dev, PCI_INTERRUPT_LINE, irq); } @@ -369,14 +352,7 @@ int cb_config(socket_info_t * s) void cb_release(socket_info_t * s) { - cb_config_t *c = s->cb_config; - DEBUG(0, "cs: cb_release(bus %d)\n", s->cap.cb_dev->subordinate->number); - -#ifdef CONFIG_ISA - if ((c[0].dev.irq != 0) && (c[0].dev.irq != s->cap.pci_irq)) - undo_irq(IRQ_TYPE_EXCLUSIVE, c[0].dev.irq); -#endif } /*===================================================================== diff --git a/drivers/pcmcia/cb_enabler.c b/drivers/pcmcia/cb_enabler.c index 0e5ddeb93039..a4d81a65e2ea 100644 --- a/drivers/pcmcia/cb_enabler.c +++ b/drivers/pcmcia/cb_enabler.c @@ -2,7 +2,7 @@ CardBus device enabler - cb_enabler.c 1.28 1999/12/09 20:57:37 + cb_enabler.c 1.31 2000/06/12 21:29:36 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -58,12 +58,12 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"cb_enabler.c 1.28 1999/12/09 20:57:37 (David Hinds)"; +"cb_enabler.c 1.31 2000/06/12 21:29:36 (David Hinds)"; #else #define DEBUG(n, args...) do { } while (0) #endif -MODULE_AUTHOR("David Hinds "); +MODULE_AUTHOR("David Hinds "); MODULE_DESCRIPTION("CardBus stub enabler module"); /*====================================================================*/ @@ -168,9 +168,9 @@ static void cb_detach(dev_link_t *link) driver_info_t *dev = link->priv; dev_link_t **linkp; bus_info_t *b = (void *)link->win; - + DEBUG(0, "cb_detach(0x%p)\n", link); - + /* Locate device structure */ for (linkp = &dev->dev_list; *linkp; linkp = &(*linkp)->next) if (*linkp == link) break; @@ -179,16 +179,16 @@ static void cb_detach(dev_link_t *link) if (link->state & DEV_CONFIG) cb_release((u_long)link); - + /* Don't drop Card Services connection if we are the bus owner */ - if ((b->flags != 0) && (link == b->owner)) { + if (b && (b->flags != 0) && (link == b->owner)) { link->state |= DEV_STALE_LINK; return; } - + if (link->handle) pcmcia_deregister_client(link->handle); - + *linkp = link->next; kfree(link); MOD_DEC_USE_COUNT; diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index acca173165fe..3f9fb1c7b5ba 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -2,7 +2,7 @@ PCMCIA Card Information Structure parser - cistpl.c 1.77 2000/01/16 19:19:01 + cistpl.c 1.90 2000/08/30 20:23:47 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -77,6 +77,14 @@ static const u_int exponent[] = { /* Upper limit on reasonable # of tuples */ #define MAX_TUPLES 200 +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") + +INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */ + /*====================================================================== Low-level functions to read and write CIS memory. I think the @@ -88,6 +96,17 @@ static const u_int exponent[] = { #define IS_ATTR 1 #define IS_INDIRECT 8 +static void set_cis_map(socket_info_t *s, pccard_mem_map *mem) +{ + s->ss_entry->set_mem_map(s->sock, mem); + if (s->cap.features & SS_CAP_STATIC_MAP) { + if (s->cis_virt) + bus_iounmap(s->cap.bus, s->cis_virt); + s->cis_virt = bus_ioremap(s->cap.bus, mem->sys_start, + s->cap.map_size); + } +} + void read_cis_mem(socket_info_t *s, int attr, u_int addr, u_int len, void *ptr) { @@ -99,16 +118,17 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr, memset(ptr, 0xff, len); return; } - mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB; - sys = s->cis_virt; + mem->flags = MAP_ACTIVE; + if (cis_width) mem->flags |= MAP_16BIT; if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed locations in common memory */ u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN; if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; } - mem->card_start = 0; - s->ss_entry->set_mem_map(s->sock, mem); + mem->card_start = 0; mem->flags = MAP_ACTIVE; + set_cis_map(s, mem); + sys = s->cis_virt; bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0); bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0); bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1); @@ -121,14 +141,15 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr, if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; } sys += (addr & (s->cap.map_size-1)); mem->card_start = addr & ~(s->cap.map_size-1); - - for (; len > 0; sys = s->cis_virt) { - s->ss_entry->set_mem_map(s->sock, mem); + while (len) { + set_cis_map(s, mem); + sys = s->cis_virt + (addr & (s->cap.map_size-1)); for ( ; len > 0; len--, buf++, sys += inc) { if (sys == s->cis_virt+s->cap.map_size) break; *buf = bus_readb(s->cap.bus, sys); } mem->card_start += s->cap.map_size; + addr = 0; } } DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n", @@ -144,16 +165,17 @@ void write_cis_mem(socket_info_t *s, int attr, u_int addr, DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len); if (setup_cis_mem(s) != 0) return; - mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB; - sys = s->cis_virt; + mem->flags = MAP_ACTIVE; + if (cis_width) mem->flags |= MAP_16BIT; if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed locations in common memory */ u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN; if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; } - mem->card_start = 0; - s->ss_entry->set_mem_map(s->sock, mem); + mem->card_start = 0; mem->flags = MAP_ACTIVE; + set_cis_map(s, mem); + sys = s->cis_virt; bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0); bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0); bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1); @@ -164,16 +186,16 @@ void write_cis_mem(socket_info_t *s, int attr, u_int addr, } else { int inc = 1; if (attr & IS_ATTR) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; } - sys += (addr & (s->cap.map_size-1)); mem->card_start = addr & ~(s->cap.map_size-1); - - for (; len > 0; sys = s->cis_virt) { - s->ss_entry->set_mem_map(s->sock, mem); + while (len) { + set_cis_map(s, mem); + sys = s->cis_virt + (addr & (s->cap.map_size-1)); for ( ; len > 0; len--, buf++, sys += inc) { if (sys == s->cis_virt+s->cap.map_size) break; bus_writeb(s->cap.bus, *buf, sys); } mem->card_start += s->cap.map_size; + addr = 0; } } } @@ -238,7 +260,8 @@ static int checksum_match(u_long base) int setup_cis_mem(socket_info_t *s) { - if (s->cis_mem.sys_start == 0) { + if (!(s->cap.features & SS_CAP_STATIC_MAP) && + (s->cis_mem.sys_start == 0)) { int low = !(s->cap.features & SS_CAP_PAGE_REGS); vs = s; validate_mem(cis_readable, checksum_match, low); @@ -262,9 +285,11 @@ void release_cis_mem(socket_info_t *s) if (s->cis_mem.sys_start != 0) { s->cis_mem.flags &= ~MAP_ACTIVE; s->ss_entry->set_mem_map(s->sock, &s->cis_mem); - release_mem_region(s->cis_mem.sys_start, s->cap.map_size); + if (!(s->cap.features & SS_CAP_STATIC_MAP)) + release_mem_region(s->cis_mem.sys_start, s->cap.map_size); bus_iounmap(s->cap.bus, s->cis_virt); s->cis_mem.sys_start = 0; + s->cis_virt = NULL; } } @@ -1278,6 +1303,25 @@ static int parse_org(tuple_t *tuple, cistpl_org_t *org) /*====================================================================*/ +static int parse_format(tuple_t *tuple, cistpl_format_t *fmt) +{ + u_char *p; + + if (tuple->TupleDataLen < 10) + return CS_BAD_TUPLE; + + p = tuple->TupleData; + + fmt->type = p[0]; + fmt->edc = p[1]; + fmt->offset = le32_to_cpu(*(u_int *)(p+2)); + fmt->length = le32_to_cpu(*(u_int *)(p+6)); + + return CS_SUCCESS; +} + +/*====================================================================*/ + int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) { int ret = CS_SUCCESS; @@ -1345,6 +1389,10 @@ int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse case CISTPL_ORG: ret = parse_org(tuple, &parse->org); break; + case CISTPL_FORMAT: + case CISTPL_FORMAT_A: + ret = parse_format(tuple, &parse->format); + break; case CISTPL_NO_LINK: case CISTPL_LINKTARGET: ret = CS_SUCCESS; @@ -1395,34 +1443,36 @@ int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) { tuple_t tuple; cisparse_t p; - int ret, reserved, errors; - + int ret, reserved, dev_ok = 0, ident_ok = 0; + if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; - - info->Chains = reserved = errors = 0; + + info->Chains = reserved = 0; tuple.DesiredTuple = RETURN_FIRST_TUPLE; tuple.Attributes = TUPLE_RETURN_COMMON; ret = pcmcia_get_first_tuple(handle, &tuple); if (ret != CS_SUCCESS) return CS_SUCCESS; - /* First tuple should be DEVICE */ - if (tuple.TupleCode != CISTPL_DEVICE) - errors++; - /* All cards should have a MANFID tuple */ - if (read_tuple(handle, CISTPL_MANFID, &p) != CS_SUCCESS) - errors++; - /* All cards should have either a VERS_1 or a VERS_2 tuple. But - at worst, we'll accept a CFTABLE_ENTRY that parses. */ - if ((read_tuple(handle, CISTPL_VERS_1, &p) != CS_SUCCESS) && - (read_tuple(handle, CISTPL_VERS_2, &p) != CS_SUCCESS) && - (read_tuple(handle, CISTPL_CFTABLE_ENTRY, &p) != CS_SUCCESS) && - (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, &p) != CS_SUCCESS)) - errors++; - if (errors > 1) + /* First tuple should be DEVICE; we should really have either that + or a CFTABLE_ENTRY of some sort */ + if ((tuple.TupleCode == CISTPL_DEVICE) || + (read_tuple(handle, CISTPL_CFTABLE_ENTRY, &p) == CS_SUCCESS) || + (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, &p) == CS_SUCCESS)) + dev_ok++; + + /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2 + tuple, for card identification. Certain old D-Link and Linksys + cards have only a broken VERS_2 tuple; hence the bogus test. */ + if ((read_tuple(handle, CISTPL_MANFID, &p) == CS_SUCCESS) || + (read_tuple(handle, CISTPL_VERS_1, &p) == CS_SUCCESS) || + (read_tuple(handle, CISTPL_VERS_2, &p) != CS_NO_MORE_ITEMS)) + ident_ok++; + + if (!dev_ok && !ident_ok) return CS_SUCCESS; - + for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) { ret = pcmcia_get_next_tuple(handle, &tuple); if (ret != CS_SUCCESS) break; @@ -1431,9 +1481,10 @@ int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) ((tuple.TupleCode > 0x90) && (tuple.TupleCode < 0xff))) reserved++; } - if ((info->Chains == MAX_TUPLES) || (reserved > 5)) + if ((info->Chains == MAX_TUPLES) || (reserved > 5) || + ((!dev_ok || !ident_ok) && (info->Chains > 10))) info->Chains = 0; - + return CS_SUCCESS; } diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 93228e5b5c90..547a18076a32 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -2,7 +2,7 @@ PCMCIA Card Services -- core services - cs.c 1.249 2000/02/10 23:26:11 + cs.c 1.267 2000/08/30 22:07:31 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -66,7 +66,7 @@ int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); static const char *version = -"cs.c 1.249 2000/02/10 23:26:11 (David Hinds)"; +"cs.c 1.267 2000/08/30 22:07:31 (David Hinds)"; #endif #ifdef CONFIG_PCI @@ -93,7 +93,7 @@ static const char *version = static const char *release = "Linux PCMCIA Card Services " CS_RELEASE; static const char *options = "options: " OPTIONS; -MODULE_AUTHOR("David Hinds "); +MODULE_AUTHOR("David Hinds "); MODULE_DESCRIPTION("Linux PCMCIA Card Services " CS_RELEASE "\n options:" OPTIONS); @@ -773,6 +773,13 @@ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base, *base, align); align = 0; } + /* Check for an already-allocated window that must conflict with + what was asked for. It is a hack because it does not catch all + potential conflicts, just the most obvious ones. */ + for (i = 0; i < MAX_IO_WIN; i++) + if ((s->io[i].NumPorts != 0) && + ((s->io[i].BasePort & (align-1)) == *base)) + return 1; for (i = 0; i < MAX_IO_WIN; i++) { if (s->io[i].NumPorts == 0) { if (find_io_region(base, num, align, name) == 0) { @@ -1676,11 +1683,13 @@ int pcmcia_request_configuration(client_handle_t handle, write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); } if (req->Present & PRESENT_OPTION) { - if (s->functions == 1) + if (s->functions == 1) { c->Option = req->ConfigIndex & COR_CONFIG_MASK; - else { + } else { c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK; - c->Option |= COR_FUNC_ENA|COR_ADDR_DECODE|COR_IREQ_ENA; + c->Option |= COR_FUNC_ENA|COR_IREQ_ENA; + if (req->Present & PRESENT_IOBASE_0) + c->Option |= COR_ADDR_DECODE; } if (c->state & CONFIG_IRQ_REQ) if (!(c->irq.Attributes & IRQ_FORCED_PULSE)) @@ -1829,8 +1838,8 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) if (c->state & CONFIG_IRQ_REQ) return CS_IN_USE; - /* Short cut: if the interrupt is PCI, there are no options */ - if (s->cap.irq_mask == (1 << s->cap.pci_irq)) + /* Short cut: if there are no ISA interrupts, then it is PCI */ + if (!s->cap.irq_mask) irq = s->cap.pci_irq; #ifdef CONFIG_ISA else if (s->irq.AssignedIRQ != 0) { @@ -1845,7 +1854,6 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) ret = CS_IN_USE; if (req->IRQInfo1 & IRQ_INFO2_VALID) { mask = req->IRQInfo2 & s->cap.irq_mask; - mask &= ~(1 << s->cap.pci_irq); for (try = 0; try < 2; try++) { for (irq = 0; irq < 32; irq++) if ((mask >> irq) & 1) { @@ -1910,11 +1918,12 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle req->Size : s->cap.map_size); if (req->Size & (s->cap.map_size-1)) return CS_BAD_SIZE; - if (req->Base & (align-1)) + if ((req->Base && (s->cap.features & SS_CAP_STATIC_MAP)) || + (req->Base & (align-1))) return CS_BAD_BASE; if (req->Base) align = 0; - + /* Allocate system memory window */ for (w = 0; w < MAX_WIN; w++) if (!(s->state & SOCKET_WIN_REQ(w))) break; @@ -1928,13 +1937,13 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle win->sock = s; win->base = req->Base; win->size = req->Size; - - if (find_mem_region(&win->base, win->size, align, + + if (!(s->cap.features & SS_CAP_STATIC_MAP) && + find_mem_region(&win->base, win->size, align, (req->Attributes & WIN_MAP_BELOW_1MB) || !(s->cap.features & SS_CAP_PAGE_REGS), (*handle)->dev_info)) return CS_IN_USE; - req->Base = win->base; (*handle)->state |= CLIENT_WIN_REQ(w); /* Configure the socket controller */ @@ -1949,14 +1958,15 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle win->ctl.flags |= MAP_16BIT; if (req->Attributes & WIN_USE_WAIT) win->ctl.flags |= MAP_USE_WAIT; - win->ctl.sys_start = req->Base; - win->ctl.sys_stop = req->Base + req->Size-1; + win->ctl.sys_start = win->base; + win->ctl.sys_stop = win->base + win->size-1; win->ctl.card_start = 0; if (set_mem_map(s, &win->ctl) != 0) return CS_BAD_ARGS; s->state |= SOCKET_WIN_REQ(w); /* Return window handle */ + req->Base = win->ctl.sys_start; *wh = win; return CS_SUCCESS; @@ -2168,7 +2178,7 @@ int CardServices(int func, void *a1, void *a2, void *a3) { #ifdef PCMCIA_DEBUG - if (pc_debug > 1) { + if (pc_debug > 2) { int i; for (i = 0; i < SERVICE_COUNT; i++) if (service_table[i].key == func) break; diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index a1373f9b1ab1..47efc86b08d8 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -1,5 +1,5 @@ /* - * cs_internal.h 1.46 1999/11/08 20:46:49 + * cs_internal.h 1.52 2000/06/12 21:29:37 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. */ diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a2a963215d4a..02c689855511 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -2,7 +2,7 @@ PC Card Driver Services - ds.c 1.104 2000/01/11 01:18:02 + ds.c 1.108 2000/08/07 19:06:15 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -61,12 +61,12 @@ int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static const char *version = -"ds.c 1.104 2000/01/11 01:18:02 (David Hinds)"; +"ds.c 1.108 2000/08/07 19:06:15 (David Hinds)"; #else #define DEBUG(n, args...) #endif -MODULE_AUTHOR("David Hinds "); +MODULE_AUTHOR("David Hinds "); MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE); /*====================================================================*/ @@ -81,6 +81,7 @@ typedef struct driver_info_t { typedef struct socket_bind_t { driver_info_t *driver; + u_char function; dev_link_t *instance; struct socket_bind_t *next; } socket_bind_t; @@ -391,7 +392,8 @@ static int bind_request(int i, bind_info_t *bind_info) } for (b = s->bind; b; b = b->next) - if (driver == b->driver) + if ((driver == b->driver) && + (bind_info->function == b->function)) break; if (b != NULL) { bind_info->instance = b->instance; @@ -413,6 +415,7 @@ static int bind_request(int i, bind_info_t *bind_info) driver->use_count++; b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL); b->driver = driver; + b->function = bind_info->function; b->instance = NULL; b->next = s->bind; s->bind = b; @@ -475,16 +478,14 @@ static int get_device_info(int i, bind_info_t *bind_info, int first) #endif for (b = s->bind; b; b = b->next) - if (strcmp((char *)b->driver->dev_info, - (char *)bind_info->dev_info) == 0) + if ((strcmp((char *)b->driver->dev_info, + (char *)bind_info->dev_info) == 0) && + (b->function == bind_info->function)) break; if (b == NULL) return -ENODEV; - - if (b->instance == NULL) - return -EAGAIN; - if (b->instance->state & DEV_CONFIG_PENDING) + if ((b->instance == NULL) || + (b->instance->state & DEV_CONFIG_PENDING)) return -EAGAIN; - if (first) node = b->instance->dev; else @@ -511,8 +512,9 @@ static int unbind_request(int i, bind_info_t *bind_info) DEBUG(2, "unbind_request(%d, '%s')\n", i, (char *)bind_info->dev_info); for (b = &s->bind; *b; b = &(*b)->next) - if (strcmp((char *)(*b)->driver->dev_info, - (char *)bind_info->dev_info) == 0) + if ((strcmp((char *)(*b)->driver->dev_info, + (char *)bind_info->dev_info) == 0) && + ((*b)->function == bind_info->function)) break; if (*b == NULL) return -ENODEV; diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index f156051239c8..4e06af9c519c 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -2,7 +2,7 @@ Resource management routines - rsrc_mgr.c 1.77 1999/11/16 03:32:59 + rsrc_mgr.c 1.79 2000/08/30 20:23:58 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -58,14 +58,12 @@ /* Parameters that can be set with 'insmod' */ -/* Should we probe resources for conflicts? */ -static int probe_mem = 1; -MODULE_PARM(probe_mem, "i"); +#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") + +INT_MODULE_PARM(probe_mem, 1); /* memory probe? */ #ifdef CONFIG_ISA -static int probe_io = 1; -static int mem_limit = 0x10000; -MODULE_PARM(probe_io, "i"); -MODULE_PARM(mem_limit, "i"); +INT_MODULE_PARM(probe_io, 1); /* IO port probe? */ +INT_MODULE_PARM(mem_limit, 0x10000); #endif /*====================================================================== diff --git a/drivers/pcmcia/rsrc_mgr.h b/drivers/pcmcia/rsrc_mgr.h index 739e03b2f936..2f45d2ca7d96 100644 --- a/drivers/pcmcia/rsrc_mgr.h +++ b/drivers/pcmcia/rsrc_mgr.h @@ -1,5 +1,5 @@ /* - * rsrc_mgr.h 1.19 1999/10/25 20:03:34 + * rsrc_mgr.h 1.20 2000/06/12 21:29:37 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/pnp/isapnp.c b/drivers/pnp/isapnp.c index ffd440dc3b9c..2bdd6f8172dc 100644 --- a/drivers/pnp/isapnp.c +++ b/drivers/pnp/isapnp.c @@ -529,7 +529,7 @@ static void __init isapnp_add_irq_resource(struct pci_dev *dev, (*res)->irq = irq; #ifdef CONFIG_PCI for (i=0; i<16; i++) - if (irq->map & i) + if (irq->map & (1< 0) { unsigned char byte; - get_user_ret(byte, c, -EFAULT); + if (get_user(byte, c)) + return -EFAULT; c += 1; rc = wait_for(BPP_GP_nAck, BPP_GP_Busy, TIME_IDLE_LIMIT, minor); @@ -735,7 +739,8 @@ static long write_ecp(unsigned minor, const char *c, unsigned long cnt) unsigned char byte; int rc; - get_user_ret(byte, c, -EFAULT); + if (get_user(byte, c)) + return -EFAULT; rc = wait_for(0, BPP_GP_Busy, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index c9d4ea0f63ec..2ee0aee37190 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -1,4 +1,4 @@ -/* $Id: display7seg.c,v 1.2 2000/08/02 06:22:35 davem Exp $ +/* $Id: display7seg.c,v 1.3 2000/08/29 07:01:55 davem Exp $ * * display7seg - Driver implementation for the 7-segment display * present on Sun Microsystems CP1400 and CP1500 @@ -18,7 +18,7 @@ #include /* request_region, check_region */ #include /* EBus device */ #include /* OpenProm Library */ -#include /* put_/get_user_ret */ +#include /* put_/get_user */ #include @@ -132,7 +132,8 @@ static int d7s_ioctl(struct inode *inode, struct file *f, /* assign device register values * we mask-out D7S_FLIP if in sol_compat mode */ - get_user_ret(ireg, (int *) arg, -EFAULT); + if (get_user(ireg, (int *) arg)) + return -EFAULT; if (0 != sol_compat) { (regs & D7S_FLIP) ? (ireg |= D7S_FLIP) : (ireg &= ~D7S_FLIP); @@ -147,7 +148,8 @@ static int d7s_ioctl(struct inode *inode, struct file *f, * This driver will not misinform you about the state * of your hardware while in sol_compat mode */ - put_user_ret(regs, (int *) arg, -EFAULT); + if (put_user(regs, (int *) arg)) + return -EFAULT; break; case D7SIOCTM: diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index c3810195793f..26e5ae8d95e5 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -73,7 +73,8 @@ static int copyin(struct openpromio *info, struct openpromio **opp_p) if (!info || !opp_p) return -EFAULT; - get_user_ret(bufsize, &info->oprom_size, -EFAULT); + if (get_user(bufsize, &info->oprom_size)) + return -EFAULT; if (bufsize == 0) return -EINVAL; @@ -132,7 +133,8 @@ static int getstrings(struct openpromio *info, struct openpromio **opp_p) */ static int copyout(void *info, struct openpromio *opp, int len) { - copy_to_user_ret(info, opp, len, -EFAULT); + if (copy_to_user(info, opp, len)) + return -EFAULT; return 0; } @@ -364,7 +366,8 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, switch (cmd) { case OPIOCGET: - copy_from_user_ret(&op, (void *)arg, sizeof(op), -EFAULT); + if (copy_from_user(&op, (void *)arg, sizeof(op))) + return -EFAULT; if (!goodnode(op.op_nodeid,data)) return -EINVAL; @@ -386,9 +389,10 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, if (len <= 0) { kfree(str); - /* Verified by the above copy_from_user_ret */ - __copy_to_user_ret((void *)arg, &op, - sizeof(op), -EFAULT); + /* Verified by the above copy_from_user */ + if (__copy_to_user((void *)arg, &op, + sizeof(op))) + return -EFAULT; return 0; } @@ -414,7 +418,8 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, return error; case OPIOCNEXTPROP: - copy_from_user_ret(&op, (void *)arg, sizeof(op), -EFAULT); + if (copy_from_user(&op, (void *)arg, sizeof(op))) + return -EFAULT; if (!goodnode(op.op_nodeid,data)) return -EINVAL; @@ -457,7 +462,8 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, return error; case OPIOCSET: - copy_from_user_ret(&op, (void *)arg, sizeof(op), -EFAULT); + if (copy_from_user(&op, (void *)arg, sizeof(op))) + return -EFAULT; if (!goodnode(op.op_nodeid,data)) return -EINVAL; @@ -485,13 +491,14 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, return 0; case OPIOCGETOPTNODE: - copy_to_user_ret((void *)arg, &options_node, - sizeof(int), -EFAULT); + if (copy_to_user((void *)arg, &options_node, sizeof(int))) + return -EFAULT; return 0; case OPIOCGETNEXT: case OPIOCGETCHILD: - copy_from_user_ret(&node, (void *)arg, sizeof(int), -EFAULT); + if (copy_from_user(&node, (void *)arg, sizeof(int))) + return -EFAULT; save_and_cli(flags); if (cmd == OPIOCGETNEXT) @@ -500,7 +507,8 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, node = __prom_getchild(node); restore_flags(flags); - __copy_to_user_ret((void *)arg, &node, sizeof(int), -EFAULT); + if (__copy_to_user((void *)arg, &node, sizeof(int))) + return -EFAULT; return 0; diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c index de875f5f6539..d8454cf25860 100644 --- a/drivers/sbus/char/rtc.c +++ b/drivers/sbus/char/rtc.c @@ -1,4 +1,4 @@ -/* $Id: rtc.c,v 1.22 2000/08/22 06:56:33 davem Exp $ +/* $Id: rtc.c,v 1.23 2000/08/29 07:01:55 davem Exp $ * * Linux/SPARC Real Time Clock Driver * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) @@ -97,7 +97,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case RTCGET: get_rtc_time(&rtc_tm); - copy_to_user_ret((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time), -EFAULT); + if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) + return -EFAULT; return 0; @@ -106,7 +107,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!capable(CAP_SYS_TIME)) return -EPERM; - copy_from_user_ret(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time), -EFAULT); + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time))) + return -EFAULT; set_rtc_time(&rtc_tm); diff --git a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c index cc71cab7e0d6..5540e734bb37 100644 --- a/drivers/sbus/char/sunkbd.c +++ b/drivers/sbus/char/sunkbd.c @@ -1346,19 +1346,22 @@ repeat: #ifdef CONFIG_SPARC32_COMPAT if (current->thread.flags & SPARC_FLAG_32BIT) { - copy_to_user_ret((Firm_event *)p, &this_event, - sizeof(Firm_event)-sizeof(struct timeval), - -EFAULT); + if (copy_to_user((Firm_event *)p, &this_event, + sizeof(Firm_event)-sizeof(struct timeval))) + return -EFAULT; p += sizeof(Firm_event)-sizeof(struct timeval); - __put_user_ret(this_event.time.tv_sec, (u32 *)p, -EFAULT); + if (__put_user(this_event.time.tv_sec, (u32 *)p)) + return -EFAULT; p += sizeof(u32); - __put_user_ret(this_event.time.tv_usec, (u32 *)p, -EFAULT); + if (__put_user(this_event.time.tv_usec, (u32 *)p)) + return -EFAULT; p += sizeof(u32); } else #endif { - copy_to_user_ret((Firm_event *)p, &this_event, - sizeof(Firm_event), -EFAULT); + if (copy_to_user((Firm_event *)p, &this_event, + sizeof(Firm_event))) + return -EFAULT; p += sizeof (Firm_event); } #ifdef KBD_DEBUG @@ -1401,22 +1404,27 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) switch (cmd){ case KIOCTYPE: /* return keyboard type */ - put_user_ret(sunkbd_type, (int *) arg, -EFAULT); + if (put_user(sunkbd_type, (int *) arg)) + return -EFAULT; break; case KIOCGTRANS: - put_user_ret(TR_UNTRANS_EVENT, (int *) arg, -EFAULT); + if (put_user(TR_UNTRANS_EVENT, (int *) arg)) + return -EFAULT; break; case KIOCTRANS: - get_user_ret(value, (int *) arg, -EFAULT); + if (get_user(value, (int *) arg)) + return -EFAULT; if (value != TR_UNTRANS_EVENT) return -EINVAL; break; case KIOCLAYOUT: - put_user_ret(sunkbd_layout, (int *) arg, -EFAULT); + if (put_user(sunkbd_layout, (int *) arg)) + return -EFAULT; break; case KIOCSDIRECT: #ifndef CODING_NEW_DRIVER - get_user_ret(value, (int *) arg, -EFAULT); + if (get_user(value, (int *) arg)) + return -EFAULT; if(value) kbd_redirected = fg_console + 1; else @@ -1425,7 +1433,8 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) #endif break; case KIOCCMD: - get_user_ret(value, (int *) arg, -EFAULT); + if (get_user(value, (int *) arg)) + return -EFAULT; c = (unsigned char) value; switch (c) { case SKBDCMD_CLICK: @@ -1444,8 +1453,9 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) return -EINVAL; } case KIOCSLED: - get_user_ret(c, (unsigned char *) arg, -EFAULT); - + if (get_user(c, (unsigned char *) arg)) + return -EFAULT; + if (c & LED_SCRLCK) leds |= (1 << VC_SCROLLOCK); if (c & LED_NLOCK) leds |= (1 << VC_NUMLOCK); if (c & LED_CLOCK) leds |= (1 << VC_CAPSLOCK); @@ -1453,7 +1463,8 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) sun_setledstate(kbd_table + fg_console, leds); break; case KIOCGLED: - put_user_ret(vcleds_to_sunkbd(getleds()), (unsigned char *) arg, -EFAULT); + if (put_user(vcleds_to_sunkbd(getleds()), (unsigned char *) arg)) + return -EFAULT; break; case KIOCGRATE: { @@ -1465,8 +1476,9 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) else rate.rate = 0; - copy_to_user_ret((struct kbd_rate *)arg, &rate, - sizeof(struct kbd_rate), -EFAULT); + if (copy_to_user((struct kbd_rate *)arg, &rate, + sizeof(struct kbd_rate))) + return -EFAULT; return 0; } @@ -1495,7 +1507,8 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) int count; count = kbd_head - kbd_tail; - put_user_ret((count < 0) ? KBD_QSIZE - count : count, (int *) arg, -EFAULT); + if (put_user((count < 0) ? KBD_QSIZE - count : count, (int *) arg)) + return -EFAULT; return 0; } default: diff --git a/drivers/sbus/char/sunmouse.c b/drivers/sbus/char/sunmouse.c index b9dd25653c7b..fd92bc4345c3 100644 --- a/drivers/sbus/char/sunmouse.c +++ b/drivers/sbus/char/sunmouse.c @@ -462,21 +462,24 @@ repeat: ((sizeof(Firm_event) - sizeof(struct timeval) + (sizeof(u32) * 2)))) break; - copy_to_user_ret((Firm_event *)p, &this_event, - sizeof(Firm_event)-sizeof(struct timeval), - -EFAULT); + if (copy_to_user((Firm_event *)p, &this_event, + sizeof(Firm_event)-sizeof(struct timeval))) + return -EFAULT; p += sizeof(Firm_event)-sizeof(struct timeval); - __put_user_ret(this_event.time.tv_sec, (u32 *)p, -EFAULT); + if (__put_user(this_event.time.tv_sec, (u32 *)p)) + return -EFAULT; p += sizeof(u32); - __put_user_ret(this_event.time.tv_usec, (u32 *)p, -EFAULT); + if (__put_user(this_event.time.tv_usec, (u32 *)p)) + return -EFAULT; p += sizeof(u32); } else #endif { if ((end - p) < sizeof(Firm_event)) break; - copy_to_user_ret((Firm_event *)p, &this_event, - sizeof(Firm_event), -EFAULT); + if (copy_to_user((Firm_event *)p, &this_event, + sizeof(Firm_event))) + return -EFAULT; p += sizeof (Firm_event); } spin_lock_irqsave(&sunmouse.lock, flags); @@ -540,16 +543,19 @@ sun_mouse_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsig switch (cmd){ /* VUIDGFORMAT - Get input device byte stream format */ case _IOR('v', 2, int): - put_user_ret(sunmouse.vuid_mode, (int *) arg, -EFAULT); + if (put_user(sunmouse.vuid_mode, (int *) arg)) + return -EFAULT; break; /* VUIDSFORMAT - Set input device byte stream format*/ case _IOW('v', 1, int): - get_user_ret(i, (int *) arg, -EFAULT); + if (get_user(i, (int *) arg)) + return -EFAULT; if (i == VUID_NATIVE || i == VUID_FIRM_EVENT){ int value; - get_user_ret(value, (int *)arg, -EFAULT); + if (get_user(value, (int *)arg)) + return -EFAULT; spin_lock_irq(&sunmouse.lock); sunmouse.vuid_mode = value; diff --git a/drivers/sbus/char/zs.c b/drivers/sbus/char/zs.c index 40284c603f4c..7acfb2abae01 100644 --- a/drivers/sbus/char/zs.c +++ b/drivers/sbus/char/zs.c @@ -1,4 +1,4 @@ -/* $Id: zs.c,v 1.58 2000/07/06 01:41:38 davem Exp $ +/* $Id: zs.c,v 1.59 2000/08/29 07:01:55 davem Exp $ * zs.c: Zilog serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -1319,7 +1319,8 @@ static int get_serial_info(struct sun_serial * info, tmp.close_delay = info->close_delay; tmp.closing_wait = info->closing_wait; tmp.custom_divisor = info->custom_divisor; - copy_to_user_ret(retinfo,&tmp,sizeof(*retinfo), -EFAULT); + if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) + return -EFAULT; return 0; } @@ -1390,7 +1391,8 @@ static int get_lsr_info(struct sun_serial * info, unsigned int *value) ZSDELAY(); ZSLOG(REGCTRL, status, 0); sti(); - put_user_ret(status, value, -EFAULT); + if (put_user(status, value)) + return -EFAULT; return 0; } @@ -1409,7 +1411,8 @@ static int get_modem_info(struct sun_serial * info, unsigned int *value) | ((status & DCD) ? TIOCM_CAR : 0) | ((status & SYNC) ? TIOCM_DSR : 0) | ((status & CTS) ? TIOCM_CTS : 0); - put_user_ret(result, value, -EFAULT); + if (put_user(result, value)) + return -EFAULT; return 0; } @@ -1418,7 +1421,8 @@ static int set_modem_info(struct sun_serial * info, unsigned int cmd, { unsigned int arg; - get_user_ret(arg, value, -EFAULT); + if (get_user(arg, value)) + return -EFAULT; switch (cmd) { case TIOCMBIS: if (arg & TIOCM_RTS) @@ -1494,11 +1498,13 @@ static int zs_ioctl(struct tty_struct *tty, struct file * file, send_break(info, arg ? arg*(HZ/10) : HZ/4); return 0; case TIOCGSOFTCAR: - put_user_ret(C_CLOCAL(tty) ? 1 : 0, - (unsigned long *) arg, -EFAULT); + if (put_user(C_CLOCAL(tty) ? 1 : 0, + (unsigned long *) arg)) + return -EFAULT; return 0; case TIOCSSOFTCAR: - get_user_ret(arg, (unsigned long *) arg, -EFAULT); + if (get_user(arg, (unsigned long *) arg)) + return -EFAULT; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); @@ -1519,8 +1525,9 @@ static int zs_ioctl(struct tty_struct *tty, struct file * file, return get_lsr_info(info, (unsigned int *) arg); case TIOCSERGSTRUCT: - copy_to_user_ret((struct sun_serial *) arg, - info, sizeof(struct sun_serial), -EFAULT); + if (copy_to_user((struct sun_serial *) arg, + info, sizeof(struct sun_serial))) + return -EFAULT; return 0; default: @@ -1906,7 +1913,7 @@ int zs_open(struct tty_struct *tty, struct file * filp) static void show_serial_version(void) { - char *revision = "$Revision: 1.58 $"; + char *revision = "$Revision: 1.59 $"; char *version, *p; version = strchr(revision, ' '); diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c index 6339d1e9046d..16d14b8cbd33 100644 --- a/drivers/scsi/esp.c +++ b/drivers/scsi/esp.c @@ -1,4 +1,4 @@ -/* $Id: esp.c,v 1.95 2000/08/23 22:32:37 davem Exp $ +/* $Id: esp.c,v 1.96 2000/08/24 03:51:26 davem Exp $ * esp.c: EnhancedScsiProcessor Sun SCSI driver code. * * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu) @@ -1599,7 +1599,9 @@ static void esp_exec_cmd(struct esp *esp) if (SDptr->sync) { /* this targets sync is known */ +#ifndef __sparc_v9__ do_sync_known: +#endif if (SDptr->disconnect) *cmdp++ = IDENTIFY(1, lun); else @@ -2583,6 +2585,8 @@ static int esp_do_data(struct esp *esp) esp_advance_phase(SCptr, thisphase); ESPDATA(("newphase<%s> ", (thisphase == in_datain) ? "DATAIN" : "DATAOUT")); hmuch = dma_can_transfer(esp, SCptr); + if (hmuch > (64 * 1024) && (esp->erev != fashme)) + hmuch = (64 * 1024); ESPDATA(("hmuch<%d> ", hmuch)); esp->current_transfer_size = hmuch; diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index e93fe8153bb6..bf738e91fb51 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -96,10 +96,6 @@ #define __PUT_USER __put_user #endif - #ifndef PUT_USER_RET - #define PUT_USER_RET put_user_ret - #endif - #ifndef GET_USER #define GET_USER get_user #endif @@ -108,10 +104,6 @@ #define __GET_USER __get_user #endif - #ifndef GET_USER_RET - #define GET_USER_RET get_user_ret - #endif - /* * Lock macros */ diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 195e131d01d1..75914a1a216d 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -5,7 +5,7 @@ This driver supports the Adaptec AHA-1460, the New Media Bus Toaster, and the New Media Toast & Jam. - aha152x_cs.c 1.53 2000/05/04 01:30:00 + aha152x_cs.c 1.54 2000/06/12 21:27:25 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -18,7 +18,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -62,7 +62,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"aha152x_cs.c 1.53 2000/05/04 01:30:00 (David Hinds)"; +"aha152x_cs.c 1.54 2000/06/12 21:27:25 (David Hinds)"; #else #define DEBUG(n, args...) #endif diff --git a/drivers/scsi/pcmcia/apa1480_stub.c b/drivers/scsi/pcmcia/apa1480_stub.c index a6419f194d30..24ee469cdc2a 100644 --- a/drivers/scsi/pcmcia/apa1480_stub.c +++ b/drivers/scsi/pcmcia/apa1480_stub.c @@ -2,7 +2,7 @@ A driver for the Adaptec APA1480 CardBus SCSI Host Adapter - apa1480_cb.c 1.19 2000/02/14 22:39:25 + apa1480_cb.c 1.22 2000/06/12 21:27:25 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -55,7 +55,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"apa1480_cb.c 1.19 2000/02/14 22:39:25 (David Hinds)"; +"apa1480_cb.c 1.22 2000/06/12 21:27:25 (David Hinds)"; #else #define DEBUG(n, args...) #endif diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 533bf5a50fc7..3c480a3ca06b 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -2,7 +2,7 @@ A driver for Future Domain-compatible PCMCIA SCSI cards - fdomain_cs.c 1.42 2000/05/04 01:30:00 + fdomain_cs.c 1.43 2000/06/12 21:27:25 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -59,7 +59,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"fdomain_cs.c 1.42 2000/05/04 01:30:00 (David Hinds)"; +"fdomain_cs.c 1.43 2000/06/12 21:27:25 (David Hinds)"; #else #define DEBUG(n, args...) #endif diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index bcbbecfb88b8..1cfee657fea4 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -2,7 +2,7 @@ A driver for the Qlogic SCSI card - qlogic_cs.c 1.78 2000/05/04 01:30:00 + qlogic_cs.c 1.79 2000/06/12 21:27:26 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -66,7 +66,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"qlogic_cs.c 1.78 2000/05/04 01:30:00 (David Hinds)"; +"qlogic_cs.c 1.79 2000/06/12 21:27:26 (David Hinds)"; #else #define DEBUG(n, args...) #endif diff --git a/drivers/sgi/char/graphics.c b/drivers/sgi/char/graphics.c index 62ca3c5e60d2..46f9402439c2 100644 --- a/drivers/sgi/char/graphics.c +++ b/drivers/sgi/char/graphics.c @@ -100,9 +100,10 @@ sgi_graphics_ioctl (struct inode *inode, struct file *file, unsigned int cmd, un i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct gfx_getboardinfo_args)); if (i) return i; - __get_user_ret (board, &bia->board, -EFAULT); - __get_user_ret (dest_buf, &bia->buf, -EFAULT); - __get_user_ret (max_len, &bia->len, -EFAULT); + if (__get_user (board, &bia->board) || + __get_user (dest_buf, &bia->buf) || + __get_user (max_len, &bia->len)) + return -EFAULT; if (board >= boards) return -EINVAL; @@ -125,8 +126,9 @@ sgi_graphics_ioctl (struct inode *inode, struct file *file, unsigned int cmd, un i = verify_area (VERIFY_READ, (void *)arg, sizeof (struct gfx_attach_board_args)); if (i) return i; - __get_user_ret (board, &att->board, -EFAULT); - __get_user_ret (vaddr, &att->vaddr, -EFAULT); + if (__get_user (board, &att->board) || + __get_user (vaddr, &att->vaddr)) + return -EFAULT; /* Ok for now we are assuming /dev/graphicsN -> head N even * if the ioctl api suggests that this is not quite the case. diff --git a/drivers/sgi/char/rrm.c b/drivers/sgi/char/rrm.c index 52bc76498b5a..57989c01481d 100644 --- a/drivers/sgi/char/rrm.c +++ b/drivers/sgi/char/rrm.c @@ -60,7 +60,8 @@ rrm_command (unsigned int cmd, void *arg) i = verify_area (VERIFY_READ, arg, rrm_functions [cmd].arg_size); if (i) return i; - __get_user_ret (rnid, (int *) arg, -EFAULT); + if (__get_user (rnid, (int *) arg)) + return -EFAULT; return (*(rrm_functions [cmd].r_fn))(rnid, arg); } diff --git a/drivers/sound/ac97_codec.c b/drivers/sound/ac97_codec.c index 23e94845a0bc..5ed418e304a6 100644 --- a/drivers/sound/ac97_codec.c +++ b/drivers/sound/ac97_codec.c @@ -419,7 +419,8 @@ static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned if (_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) { codec->modcnt++; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ diff --git a/drivers/sound/cmpci.c b/drivers/sound/cmpci.c index fbba125832d1..836579af24da 100644 --- a/drivers/sound/cmpci.c +++ b/drivers/sound/cmpci.c @@ -1038,7 +1038,8 @@ static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg) s->mix.modcnt++; switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; i = hweight32(val); for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) { if (!(val & (1 << i))) @@ -1056,7 +1057,8 @@ static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg) return 0; case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each recording source */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) { if (!(val & (1 << i))) continue; @@ -1075,7 +1077,8 @@ static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg) i = _IOC_NR(cmd); if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; l = val & 0xff; r = (val >> 8) & 0xff; if (l > 100) @@ -1469,7 +1472,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1485,7 +1489,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; fmtd = 0; fmtm = ~0; if (file->f_mode & FMODE_READ) { @@ -1508,7 +1513,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { fmtd = 0; fmtm = ~0; @@ -1537,7 +1543,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { fmtd = 0; fmtm = ~0; @@ -1574,7 +1581,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) @@ -1671,7 +1679,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; @@ -1698,7 +1707,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) diff --git a/drivers/sound/cs46xx.c b/drivers/sound/cs46xx.c index 6a9fec82b2dd..1c282b1cc987 100644 --- a/drivers/sound/cs46xx.c +++ b/drivers/sound/cs46xx.c @@ -1233,7 +1233,8 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0; case SNDCTL_DSP_SPEED: /* set smaple rate */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -1249,7 +1250,8 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(dmabuf->rate, (int *)arg); case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_WRITE) { stop_dac(state); dmabuf->ready = 0; @@ -1291,7 +1293,8 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(AFMT_S16_LE, (int *)arg); case SNDCTL_DSP_SETFMT: /* Select sample format */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { if(val==AFMT_S16_LE/* || val==AFMT_U8*/) { @@ -1315,7 +1318,8 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(AFMT_U8, (int *)arg); case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -1340,14 +1344,16 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un case SNDCTL_DSP_SUBDIVIDE: if (dmabuf->subdivision) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2) return -EINVAL; dmabuf->subdivision = val; return 0; case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; dmabuf->ossfragshift = val & 0xffff; dmabuf->ossmaxfrags = (val >> 16) & 0xffff; @@ -1408,7 +1414,8 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) diff --git a/drivers/sound/dmasound/dmasound_core.c b/drivers/sound/dmasound/dmasound_core.c index 1d8804b368ea..21f54bdb1192 100644 --- a/drivers/sound/dmasound/dmasound_core.c +++ b/drivers/sound/dmasound/dmasound_core.c @@ -523,7 +523,8 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, strncpy(info.name, dmasound.mach.name2, sizeof(info.name)); info.name[sizeof(info.name)-1] = 0; info.modify_counter = mixer.modify_counter; - copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT); + if (copy_to_user((int *)arg, &info, sizeof(info))) + return -EFAULT; return 0; } } diff --git a/drivers/sound/emu10k1/audio.c b/drivers/sound/emu10k1/audio.c index dca8d564d069..c06c5df2c0f3 100644 --- a/drivers/sound/emu10k1/audio.c +++ b/drivers/sound/emu10k1/audio.c @@ -361,7 +361,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_SPEED: DPF(2, "SNDCTL_DSP_SPEED:\n"); - get_user_ret(val, (int *) arg, -EFAULT); + if (get_user(val, (int *) arg)) + return -EFAULT; DPD(2, "val is %d\n", val); if (val > 0) { @@ -415,7 +416,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_STEREO: DPF(2, "SNDCTL_DSP_STEREO:\n"); - get_user_ret(val, (int *) arg, -EFAULT); + if (get_user(val, (int *) arg)) + return -EFAULT; DPD(2, " val is %d\n", val); if (file->f_mode & FMODE_READ) { @@ -460,7 +462,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_CHANNELS: DPF(2, "SNDCTL_DSP_CHANNELS:\n"); - get_user_ret(val, (int *) arg, -EFAULT); + if (get_user(val, (int *) arg)) + return -EFAULT; DPD(2, " val is %d\n", val); if (val > 0) { @@ -522,7 +525,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_SETFMT: /* Same as SNDCTL_DSP_SAMPLESIZE */ DPF(2, "SNDCTL_DSP_SETFMT:\n"); - get_user_ret(val, (int *) arg, -EFAULT); + if (get_user(val, (int *) arg)) + return -EFAULT; DPD(2, " val is %d\n", val); if (val != AFMT_QUERY) { @@ -624,7 +628,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_SETTRIGGER: DPF(2, "SNDCTL_DSP_SETTRIGGER:\n"); - get_user_ret(val, (int *) arg, -EFAULT); + if (get_user(val, (int *) arg)) + return -EFAULT; if (file->f_mode & FMODE_WRITE) { spin_lock_irqsave(&woinst->lock, flags); @@ -850,7 +855,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_SETFRAGMENT: DPF(2, "SNDCTL_DSP_SETFRAGMENT:\n"); - get_user_ret(val, (int *) arg, -EFAULT); + if (get_user(val, (int *) arg)) + return -EFAULT; DPD(2, "val is 0x%x\n", val); diff --git a/drivers/sound/emu10k1/mixer.c b/drivers/sound/emu10k1/mixer.c index f28787f87b6e..296b5058cce2 100644 --- a/drivers/sound/emu10k1/mixer.c +++ b/drivers/sound/emu10k1/mixer.c @@ -1038,7 +1038,8 @@ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned if (card->isaps) return -EINVAL; - get_user_ret(val, (int *) arg, -EFAULT); + if (get_user(val, (int *) arg)) + return -EFAULT; i = hweight32(val); if (i == 0) return 0; /* val = mixer_recmask(s); */ @@ -1062,7 +1063,8 @@ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned if (i >= SOUND_MIXER_NRDEVICES) return -EINVAL; - get_user_ret(val, (int *) arg, -EFAULT); + if (get_user(val, (int *) arg)) + return -EFAULT; if (emu10k1_mixer_wrch(card, i, val)) return -EINVAL; diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c index 01f2cf46f9db..d9d972acabd9 100644 --- a/drivers/sound/es1370.c +++ b/drivers/sound/es1370.c @@ -842,7 +842,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a VALIDATE_STATE(s); if (cmd == SOUND_MIXER_PRIVATE1) { /* enable/disable/query mixer preamp */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != -1) { s->mix.micpreamp = !!val; wrcodec(s, 0x19, s->mix.micpreamp); @@ -851,7 +852,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a } if (cmd == SOUND_MIXER_PRIVATE2) { /* enable/disable/query use of linein as second lineout */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != -1) { spin_lock_irqsave(&s->lock, flags); if (val) @@ -865,7 +867,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a } if (cmd == SOUND_MIXER_PRIVATE3) { /* enable/disable/query microphone impedance setting */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != -1) { spin_lock_irqsave(&s->lock, flags); if (val) @@ -941,12 +944,14 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a switch (_IOC_NR(cmd)) { case SOUND_MIXER_IMIX: - get_user_ret(s->mix.imix, (int *)arg, -EFAULT); + if (get_user(s->mix.imix, (int *)arg)) + return -EFAULT; set_recsrc(s, s->mix.recsrc); return 0; case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; set_recsrc(s, val); return 0; @@ -954,7 +959,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a i = _IOC_NR(cmd); if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].avail) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; l = val & 0xff; if (l > 100) l = 100; @@ -1382,7 +1388,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (s->open_mode & (~file->f_mode) & (FMODE_READ|FMODE_WRITE)) return -EINVAL; @@ -1401,7 +1408,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV), (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { stop_adc(s); s->dma_adc.ready = 0; @@ -1427,7 +1435,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1458,7 +1467,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1498,7 +1508,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) @@ -1609,7 +1620,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; @@ -1636,7 +1648,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) @@ -1916,7 +1929,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { stop_dac1(s); s->dma_dac1.ready = 0; @@ -1931,7 +1945,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL], (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; stop_dac1(s); s->dma_dac1.ready = 0; spin_lock_irqsave(&s->lock, flags); @@ -1944,7 +1959,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { if (s->dma_dac1.mapped) return -EINVAL; @@ -1964,7 +1980,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { stop_dac1(s); s->dma_dac1.ready = 0; @@ -1985,7 +2002,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val & PCM_ENABLE_OUTPUT) { if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) return ret; @@ -2044,7 +2062,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(s->dma_dac1.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; s->dma_dac1.ossfragshift = val & 0xffff; s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff; if (s->dma_dac1.ossfragshift < 4) @@ -2058,7 +2077,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int case SNDCTL_DSP_SUBDIVIDE: if (s->dma_dac1.subdivision) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; s->dma_dac1.subdivision = val; diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c index 4e340c3cc4f9..c32568281e68 100644 --- a/drivers/sound/es1371.c +++ b/drivers/sound/es1371.c @@ -1165,7 +1165,8 @@ static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned lon return 0; case SOUND_MIXER_WRITE_PCM: /* use SRC for PCM volume */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; right = ((val >> 8) & 0xff); left = (val & 0xff); if (right > 100) @@ -1570,7 +1571,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1586,7 +1588,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { stop_adc(s); s->dma_adc.ready = 0; @@ -1612,7 +1615,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1643,7 +1647,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1683,7 +1688,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) @@ -1794,7 +1800,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; @@ -1821,7 +1828,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) @@ -2100,7 +2108,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { stop_dac1(s); s->dma_dac1.ready = 0; @@ -2109,7 +2118,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(s->dac1rate, (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; stop_dac1(s); s->dma_dac1.ready = 0; spin_lock_irqsave(&s->lock, flags); @@ -2122,7 +2132,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { stop_dac1(s); s->dma_dac1.ready = 0; @@ -2140,7 +2151,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { stop_dac1(s); s->dma_dac1.ready = 0; @@ -2161,7 +2173,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val & PCM_ENABLE_OUTPUT) { if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) return ret; @@ -2220,7 +2233,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(s->dma_dac1.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; s->dma_dac1.ossfragshift = val & 0xffff; s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff; if (s->dma_dac1.ossfragshift < 4) @@ -2234,7 +2248,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int case SNDCTL_DSP_SUBDIVIDE: if (s->dma_dac1.subdivision) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; s->dma_dac1.subdivision = val; diff --git a/drivers/sound/esssolo1.c b/drivers/sound/esssolo1.c index 4c3bdaff83e3..3d75f8dacd39 100644 --- a/drivers/sound/esssolo1.c +++ b/drivers/sound/esssolo1.c @@ -686,7 +686,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar if (cmd == SOUND_MIXER_PRIVATE1) { /* enable/disable/query mixer preamp */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != -1) { val = val ? 0xff : 0xf7; write_mixer(s, 0x7d, (read_mixer(s, 0x7d) | 0x08) & val); @@ -696,7 +697,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar } if (cmd == SOUND_MIXER_PRIVATE2) { /* enable/disable/query spatializer */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != -1) { val &= 0x3f; write_mixer(s, 0x52, val); @@ -773,7 +775,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar 0xb4, read_ctrl(s, 0xb4)); } #endif - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; i = hweight32(val); if (i == 0) return 0; @@ -789,7 +792,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar return 0; case SOUND_MIXER_VOLUME: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; l = val & 0xff; if (l > 100) l = 100; @@ -820,7 +824,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar return put_user(s->mix.vol[9], (int *)arg); case SOUND_MIXER_SPEAKER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; l = val & 0xff; if (l > 100) l = 100; @@ -837,7 +842,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar return put_user(s->mix.vol[7], (int *)arg); case SOUND_MIXER_RECLEV: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; l = (val << 1) & 0x1fe; if (l > 200) l = 200; @@ -864,7 +870,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar i = _IOC_NR(cmd); if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; l = (val << 1) & 0x1fe; if (l > 200) l = 200; @@ -1268,7 +1275,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { stop_adc(s); stop_dac(s); @@ -1295,7 +1303,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(s->rate, (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; stop_adc(s); stop_dac(s); s->dma_adc.ready = s->dma_dac.ready = 0; @@ -1305,7 +1314,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { stop_adc(s); stop_dac(s); @@ -1320,7 +1330,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { stop_adc(s); stop_dac(s); @@ -1346,7 +1357,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) @@ -1459,7 +1471,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; @@ -1486,7 +1499,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) diff --git a/drivers/sound/i810_audio.c b/drivers/sound/i810_audio.c index 15b469cf59a7..54b50bb1e13f 100644 --- a/drivers/sound/i810_audio.c +++ b/drivers/sound/i810_audio.c @@ -1300,7 +1300,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0; case SNDCTL_DSP_SPEED: /* set smaple rate */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -1320,7 +1321,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(dmabuf->rate, (int *)arg); case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if(val==0) return -EINVAL; if (file->f_mode & FMODE_WRITE) { @@ -1351,7 +1353,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(AFMT_S16_LE, (int *)arg); case SNDCTL_DSP_SETFMT: /* Select sample format */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -1365,7 +1368,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(AFMT_S16_LE, (int *)arg); case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -1385,14 +1389,16 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case SNDCTL_DSP_SUBDIVIDE: if (dmabuf->subdivision) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; dmabuf->subdivision = val; return 0; case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; dmabuf->ossfragshift = val & 0xffff; dmabuf->ossmaxfrags = (val >> 16) & 0xffff; @@ -1450,7 +1456,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) diff --git a/drivers/sound/maestro.c b/drivers/sound/maestro.c index 9d848e2a77e9..c2cb30457f7b 100644 --- a/drivers/sound/maestro.c +++ b/drivers/sound/maestro.c @@ -2034,7 +2034,8 @@ static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long ar card->mix.modcnt++; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ @@ -2502,7 +2503,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -2518,7 +2520,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; fmtd = 0; fmtm = ~0; if (file->f_mode & FMODE_READ) { @@ -2541,7 +2544,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { fmtd = 0; fmtm = ~0; @@ -2570,7 +2574,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return put_user(AFMT_U8|AFMT_S16_LE, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { fmtd = 0; fmtm = ~0; @@ -2615,7 +2620,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) @@ -2712,7 +2718,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; M_printk("maestro: SETFRAGMENT: %0x\n",val); if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; @@ -2740,7 +2747,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) diff --git a/drivers/sound/nm256_audio.c b/drivers/sound/nm256_audio.c index a07029ad6c8e..9049b4ceaaa9 100644 --- a/drivers/sound/nm256_audio.c +++ b/drivers/sound/nm256_audio.c @@ -1419,7 +1419,8 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) switch (cmd) { case SOUND_PCM_WRITE_RATE: - get_user_ret(ret, (int *) arg, -EFAULT); + if (get_user(ret, (int *) arg)) + return -EFAULT; if (ret != 0) { oldinfo = card->sinfo[w].samplerate; @@ -1437,7 +1438,8 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) break; case SNDCTL_DSP_STEREO: - get_user_ret(ret, (int *) arg, -EFAULT); + if (get_user(ret, (int *) arg)) + return -EFAULT; card->sinfo[w].stereo = ret ? 1 : 0; ret = nm256_setInfo (dev, card); @@ -1447,7 +1449,8 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) break; case SOUND_PCM_WRITE_CHANNELS: - get_user_ret(ret, (int *) arg, -EFAULT); + if (get_user(ret, (int *) arg)) + return -EFAULT; if (ret < 1 || ret > 3) ret = card->sinfo[w].stereo + 1; @@ -1464,7 +1467,8 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) break; case SNDCTL_DSP_SETFMT: - get_user_ret(ret, (int *) arg, -EFAULT); + if (get_user(ret, (int *) arg) + return -EFAULT; if (ret != 0) { oldinfo = card->sinfo[w].bits; diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c index 099bbf1ab47b..1c77982c0357 100644 --- a/drivers/sound/sonicvibes.c +++ b/drivers/sound/sonicvibes.c @@ -1051,7 +1051,8 @@ static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg) if (cmd == OSS_GETVERSION) return put_user(SOUND_VERSION, (int *)arg); if (cmd == SOUND_MIXER_PRIVATE1) { /* SRS settings */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; spin_lock_irqsave(&s->lock, flags); if (val & 1) { if (val & 2) { @@ -1119,7 +1120,8 @@ static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg) s->mix.modcnt++; switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; i = hweight32(val); if (i == 0) return 0; /*val = mixer_recmask(s);*/ @@ -1143,7 +1145,8 @@ static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg) i = _IOC_NR(cmd); if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; l = val & 0xff; r = (val >> 8) & 0xff; if (mixtable[i].type == MT_4MUTEMONO) @@ -1582,7 +1585,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1598,7 +1602,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; fmtd = 0; fmtm = ~0; if (file->f_mode & FMODE_READ) { @@ -1621,7 +1626,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { fmtd = 0; fmtm = ~0; @@ -1650,7 +1656,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { fmtd = 0; fmtm = ~0; @@ -1687,7 +1694,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) @@ -1798,7 +1806,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; @@ -1825,7 +1834,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c index c85d409917b1..a76755e29a59 100644 --- a/drivers/sound/trident.c +++ b/drivers/sound/trident.c @@ -1633,7 +1633,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return 0; case SNDCTL_DSP_SPEED: /* set smaple rate */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -1653,7 +1654,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return put_user(dmabuf->rate, (int *)arg); case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_WRITE) { stop_dac(state); dmabuf->ready = 0; @@ -1688,7 +1690,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Select sample format */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -1711,7 +1714,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm AFMT_S16_LE : AFMT_U8, (int *)arg); case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -1740,14 +1744,16 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm case SNDCTL_DSP_SUBDIVIDE: if (dmabuf->subdivision) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; dmabuf->subdivision = val; return 0; case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; dmabuf->ossfragshift = val & 0xffff; dmabuf->ossmaxfrags = (val >> 16) & 0xffff; @@ -1805,7 +1811,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) @@ -1881,7 +1888,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val == DSP_BIND_QUERY) { val = dmabuf->channel->attribute | 0x3c00; val = attr2mask[val >> 8]; diff --git a/drivers/sound/via82cxxx_audio.c b/drivers/sound/via82cxxx_audio.c index 7ed78c980a1f..a58b333fd138 100644 --- a/drivers/sound/via82cxxx_audio.c +++ b/drivers/sound/via82cxxx_audio.c @@ -1900,7 +1900,8 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file, /* query or set current channel's PCM data format */ case SNDCTL_DSP_SETFMT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { rc = 0; @@ -1928,7 +1929,8 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file, /* query or set number of channels (1=mono, 2=stereo) */ case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { rc = 0; spin_lock_irq (&card->lock); @@ -1954,7 +1956,8 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file, /* enable (val is not zero) or disable (val == 0) stereo */ case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; rc = 0; spin_lock_irq (&card->lock); if (rc == 0 && rd) @@ -1969,7 +1972,8 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file, /* query or set sampling rate */ case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val < 0) return -EINVAL; if (val > 0) { @@ -2061,7 +2065,8 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file, /* set fragment size. implemented as a successful no-op for now */ case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; DPRINTK ("SNDCTL_DSP_SETFRAGMENT (fragshift==0x%04X (%d), maxfrags==0x%04X (%d))\n", val & 0xFFFF, diff --git a/drivers/sound/vwsnd.c b/drivers/sound/vwsnd.c index d46abd5699a3..3ba047962764 100644 --- a/drivers/sound/vwsnd.c +++ b/drivers/sound/vwsnd.c @@ -2476,7 +2476,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg); case SNDCTL_DSP_SPEED: /* _SIOWR('P', 2, int) */ - get_user_ret(ival, (int *) arg, -EFAULT); + if (get_user(ival, (int *) arg)) + return -EFAULT; DBGX("SNDCTL_DSP_SPEED %d\n", ival); if (ival) { if (aport->swstate != SW_INITIAL) { @@ -2497,7 +2498,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg); case SNDCTL_DSP_STEREO: /* _SIOWR('P', 3, int) */ - get_user_ret(ival, (int *) arg, -EFAULT); + if (get_user(ival, (int *) arg)) + return -EFAULT; DBGX("SNDCTL_DSP_STEREO %d\n", ival); if (ival != 0 && ival != 1) return -EINVAL; @@ -2510,7 +2512,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg); case SNDCTL_DSP_CHANNELS: /* _SIOWR('P', 6, int) */ - get_user_ret(ival, (int *) arg, -EFAULT); + if (get_user(ival, (int *) arg)) + return -EFAULT; DBGX("SNDCTL_DSP_CHANNELS %d\n", ival); if (ival != 1 && ival != 2) return -EINVAL; @@ -2533,7 +2536,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg); case SNDCTL_DSP_SETFRAGMENT: /* _SIOWR('P',10, int) */ - get_user_ret(ival, (int *) arg, -EFAULT); + if (get_user(ival, (int *) arg)) + return -EFAULT; DBGX("SNDCTL_DSP_SETFRAGMENT %d:%d\n", ival >> 16, ival & 0xFFFF); if (aport->swstate != SW_INITIAL) @@ -2571,7 +2575,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg); case SNDCTL_DSP_SUBDIVIDE: /* _SIOWR('P', 9, int) */ - get_user_ret(ival, (int *) arg, -EFAULT); + if (get_user(ival, (int *) arg)) + return -EFAULT; DBGX("SNDCTL_DSP_SUBDIVIDE %d\n", ival); if (aport->swstate != SW_INITIAL) return -EINVAL; @@ -2601,7 +2606,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return 0; case SNDCTL_DSP_SETFMT: /* _SIOWR('P',5, int) */ - get_user_ret(ival, (int *) arg, -EFAULT); + if (get_user(ival, (int *) arg)) + return -EFAULT; DBGX("SNDCTL_DSP_SETFMT %d\n", ival); if (ival != AFMT_QUERY) { if (aport->swstate != SW_INITIAL) { @@ -2809,7 +2815,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg); case SNDCTL_DSP_SETTRIGGER: /* _SIOW ('P',16, int) */ - get_user_ret(ival, (int *) arg, -EFAULT); + if (get_user(ival, (int *) arg)) + return -EFAULT; DBGX("SNDCTL_DSP_SETTRIGGER %d\n", ival); /* diff --git a/drivers/sound/waveartist.c b/drivers/sound/waveartist.c index 9eac1e3d840f..7badf8062608 100644 --- a/drivers/sound/waveartist.c +++ b/drivers/sound/waveartist.c @@ -1628,7 +1628,8 @@ vnc_private_ioctl(int dev, unsigned int cmd, caddr_t arg) u_int prev_spkr_mute, prev_line_mute, prev_auto_state; int val; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; /* check if parameter is logical */ if (val & ~(VNC_MUTE_INTERNAL_SPKR | @@ -1657,7 +1658,8 @@ vnc_private_ioctl(int dev, unsigned int cmd, caddr_t arg) } case SOUND_MIXER_PRIVATE2: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; switch (val) { #define VNC_SOUND_PAUSE 0x53 //to pause the DSP @@ -1681,8 +1683,10 @@ vnc_private_ioctl(int dev, unsigned int cmd, caddr_t arg) unsigned long flags; int mixer_reg[15], i, val; - get_user_ret(val, (int *)arg, -EFAULT); - copy_from_user_ret(mixer_reg, (void *)val, sizeof(mixer_reg), -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; + if (copy_from_user(mixer_reg, (void *)val, sizeof(mixer_reg))) + return -EFAULT; switch (mixer_reg[14]) { case MIXER_PRIVATE3_RESET: @@ -1708,7 +1712,8 @@ vnc_private_ioctl(int dev, unsigned int cmd, caddr_t arg) spin_unlock_irqrestore(&waveartist_lock, flags); - copy_to_user_ret((void *)val, mixer_reg, sizeof(mixer_reg), -EFAULT); + if (copy_to_user((void *)val, mixer_reg, sizeof(mixer_reg))) + return -EFAULT; break; default: diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c index 3efd73183690..12c308bce139 100644 --- a/drivers/usb/audio.c +++ b/drivers/usb/audio.c @@ -559,7 +559,8 @@ static int dmabuf_copyin_user(struct dmabuf *db, unsigned int ptr, const void *b rem = db->dmasize - ptr; if (pgrem > rem) pgrem = rem; - copy_from_user_ret((db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), buffer, pgrem, -EFAULT); + if (copy_from_user((db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), buffer, pgrem)) + return -EFAULT; size -= pgrem; (char *)buffer += pgrem; ptr += pgrem; @@ -583,7 +584,8 @@ static int dmabuf_copyout_user(struct dmabuf *db, unsigned int ptr, void *buffer rem = db->dmasize - ptr; if (pgrem > rem) pgrem = rem; - copy_to_user_ret(buffer, (db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), pgrem, -EFAULT); + if (copy_to_user(buffer, (db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), pgrem)) + return -EFAULT; size -= pgrem; (char *)buffer += pgrem; ptr += pgrem; @@ -2029,7 +2031,8 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign ms->modcnt++; switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; return set_rec_src(ms, val); default: @@ -2039,7 +2042,8 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++); if (j >= ms->numch) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (wrmixer(ms, j, val)) return -EIO; return put_user(ms->ch[j].value, (int *)arg); @@ -2352,7 +2356,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (val < 4000) val = 4000; @@ -2370,7 +2375,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; if (val == 1) @@ -2388,7 +2394,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { if (hweight32(val) != 1) return -EINVAL; @@ -2415,7 +2422,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as))) @@ -2509,7 +2517,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int return put_user(as->usbin.dma.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { as->usbin.dma.ossfragshift = val & 0xffff; as->usbin.dma.ossmaxfrags = (val >> 16) & 0xffff; @@ -2536,7 +2545,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int if ((file->f_mode & FMODE_READ && as->usbin.dma.subdivision) || (file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) diff --git a/drivers/usb/devio.c b/drivers/usb/devio.c index 00bd135e8f5a..8fb3b3c2147c 100644 --- a/drivers/usb/devio.c +++ b/drivers/usb/devio.c @@ -607,7 +607,8 @@ static int proc_control(struct dev_state *ps, void *arg) unsigned char *tbuf; int i, ret; - copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT); + if (copy_from_user(&ctrl, (void *)arg, sizeof(ctrl))) + return -EFAULT; switch (ctrl.requesttype & 0x1f) { case USB_RECIP_ENDPOINT: if ((ret = findintfep(ps->dev, ctrl.index & 0xff)) < 0) @@ -636,11 +637,13 @@ static int proc_control(struct dev_state *ps, void *arg) i = my_usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, ctrl.requesttype, ctrl.value, ctrl.index, tbuf, ctrl.length, tmo); if ((i > 0) && ctrl.length) { - copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT); + if (copy_to_user(ctrl.data, tbuf, ctrl.length)) + return -EFAULT; } } else { if (ctrl.length) { - copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT); + if (copy_from_user(tbuf, ctrl.data, ctrl.length)) + return -EFAULT; } i = my_usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, ctrl.requesttype, ctrl.value, ctrl.index, tbuf, ctrl.length, tmo); @@ -662,7 +665,8 @@ static int proc_bulk(struct dev_state *ps, void *arg) unsigned char *tbuf; int i, ret; - copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT); + if (copy_from_user(&bulk, (void *)arg, sizeof(bulk))) + return -EFAULT; if ((ret = findintfep(ps->dev, bulk.ep)) < 0) return ret; if ((ret = checkintf(ps, ret))) @@ -686,11 +690,13 @@ static int proc_bulk(struct dev_state *ps, void *arg) } i = my_usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); if (!i && len2) { - copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT); + if (copy_to_user(bulk.data, tbuf, len2)) + return -EFAULT; } } else { if (len1) { - copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT); + if (copy_from_user(tbuf, bulk.data, len1)) + return -EFAULT; } i = my_usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); } @@ -708,7 +714,8 @@ static int proc_resetep(struct dev_state *ps, void *arg) unsigned int ep; int ret; - get_user_ret(ep, (unsigned int *)arg, -EFAULT); + if (get_user(ep, (unsigned int *)arg)) + return -EFAULT; if ((ret = findintfep(ps->dev, ep)) < 0) return ret; if ((ret = checkintf(ps, ret))) @@ -723,7 +730,8 @@ static int proc_clearhalt(struct dev_state *ps, void *arg) int pipe; int ret; - get_user_ret(ep, (unsigned int *)arg, -EFAULT); + if (get_user(ep, (unsigned int *)arg)) + return -EFAULT; if ((ret = findintfep(ps->dev, ep)) < 0) return ret; if ((ret = checkintf(ps, ret))) @@ -743,7 +751,8 @@ static int proc_getdriver(struct dev_state *ps, void *arg) struct usb_interface *interface; int ret; - copy_from_user_ret(&gd, arg, sizeof(gd), -EFAULT); + if (copy_from_user(&gd, arg, sizeof(gd))) + return -EFAULT; if ((ret = findintfif(ps->dev, gd.interface)) < 0) return ret; interface = usb_ifnum_to_if(ps->dev, gd.interface); @@ -752,7 +761,8 @@ static int proc_getdriver(struct dev_state *ps, void *arg) if (!interface->driver) return -ENODATA; strcpy(gd.driver, interface->driver->name); - copy_to_user_ret(arg, &gd, sizeof(gd), -EFAULT); + if (copy_to_user(arg, &gd, sizeof(gd))) + return -EFAULT; return 0; } @@ -762,7 +772,8 @@ static int proc_connectinfo(struct dev_state *ps, void *arg) ci.devnum = ps->dev->devnum; ci.slow = ps->dev->slow; - copy_to_user_ret(arg, &ci, sizeof(ci), -EFAULT); + if (copy_to_user(arg, &ci, sizeof(ci))) + return -EFAULT; return 0; } @@ -798,7 +809,8 @@ static int proc_setintf(struct dev_state *ps, void *arg) struct usb_interface *interface; int ret; - copy_from_user_ret(&setintf, arg, sizeof(setintf), -EFAULT); + if (copy_from_user(&setintf, arg, sizeof(setintf))) + return -EFAULT; if ((ret = findintfif(ps->dev, setintf.interface)) < 0) return ret; interface = usb_ifnum_to_if(ps->dev, setintf.interface); @@ -817,7 +829,8 @@ static int proc_setconfig(struct dev_state *ps, void *arg) { unsigned int u; - get_user_ret(u, (unsigned int *)arg, -EFAULT); + if (get_user(u, (unsigned int *)arg)) + return -EFAULT; if (usb_set_configuration(ps->dev, u) < 0) return -EINVAL; return 0; @@ -831,7 +844,8 @@ static int proc_submiturb(struct dev_state *ps, void *arg) unsigned int u, totlen, isofrmlen; int ret; - copy_from_user_ret(&uurb, arg, sizeof(uurb), -EFAULT); + if (copy_from_user(&uurb, arg, sizeof(uurb))) + return -EFAULT; if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_DISABLE_SPD)) return -EINVAL; if (!uurb.buffer) @@ -948,18 +962,22 @@ static int processcompl(struct async *as) if (as->userbuffer) if (copy_to_user(as->userbuffer, as->urb.transfer_buffer, as->urb.transfer_buffer_length)) return -EFAULT; - put_user_ret(as->urb.status, &((struct usbdevfs_urb *)as->userurb)->status, -EFAULT); - put_user_ret(as->urb.actual_length, &((struct usbdevfs_urb *)as->userurb)->actual_length, -EFAULT); - put_user_ret(as->urb.error_count, &((struct usbdevfs_urb *)as->userurb)->error_count, -EFAULT); + if (put_user(as->urb.status, + &((struct usbdevfs_urb *)as->userurb)->status) || + __put_user(as->urb.actual_length, + &((struct usbdevfs_urb *)as->userurb)->actual_length) || + __put_user(as->urb.error_count, + &((struct usbdevfs_urb *)as->userurb)->error_count)) + return -EFAULT; + if (!(usb_pipeisoc(as->urb.pipe))) return 0; for (i = 0; i < as->urb.number_of_packets; i++) { - put_user_ret(as->urb.iso_frame_desc[i].actual_length, - &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length, - -EFAULT); - put_user_ret(as->urb.iso_frame_desc[i].status, - &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status, - -EFAULT); + if (put_user(as->urb.iso_frame_desc[i].actual_length, + &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length) || + __put_user(as->urb.iso_frame_desc[i].status, + &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status)) + return -EFAULT; } return 0; } @@ -990,7 +1008,8 @@ static int proc_reapurb(struct dev_state *ps, void *arg) free_async(as); if (ret) return ret; - put_user_ret(addr, (void **)arg, -EFAULT); + if (put_user(addr, (void **)arg)) + return -EFAULT; return 0; } if (signal_pending(current)) @@ -1011,7 +1030,8 @@ static int proc_reapurbnonblock(struct dev_state *ps, void *arg) free_async(as); if (ret) return ret; - put_user_ret(addr, (void **)arg, -EFAULT); + if (put_user(addr, (void **)arg)) + return -EFAULT; return 0; } @@ -1019,7 +1039,8 @@ static int proc_disconnectsignal(struct dev_state *ps, void *arg) { struct usbdevfs_disconnectsignal ds; - copy_from_user_ret(&ds, arg, sizeof(ds), -EFAULT); + if (copy_from_user(&ds, arg, sizeof(ds))) + return -EFAULT; if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX)) return -EINVAL; ps->discsignr = ds.signr; @@ -1032,7 +1053,8 @@ static int proc_claiminterface(struct dev_state *ps, void *arg) unsigned int intf; int ret; - get_user_ret(intf, (unsigned int *)arg, -EFAULT); + if (get_user(intf, (unsigned int *)arg)) + return -EFAULT; if ((ret = findintfif(ps->dev, intf)) < 0) return ret; return claimintf(ps, ret); @@ -1043,7 +1065,8 @@ static int proc_releaseinterface(struct dev_state *ps, void *arg) unsigned int intf; int ret; - get_user_ret(intf, (unsigned int *)arg, -EFAULT); + if (get_user(intf, (unsigned int *)arg)) + return -EFAULT; if ((ret = findintfif(ps->dev, intf)) < 0) return ret; return releaseintf(ps, intf); @@ -1057,7 +1080,8 @@ static int proc_ioctl (struct dev_state *ps, void *arg) int retval = 0; /* get input parameters and alloc buffer */ - copy_from_user_ret (&ctrl, (void *) arg, sizeof (ctrl), -EFAULT); + if (copy_from_user(&ctrl, (void *) arg, sizeof (ctrl))) + return -EFAULT; if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) { if ((buf = kmalloc (size, GFP_KERNEL)) == 0) return -ENOMEM; diff --git a/drivers/usb/rio500.c b/drivers/usb/rio500.c index c84a01fa65a1..59c97376e458 100644 --- a/drivers/usb/rio500.c +++ b/drivers/usb/rio500.c @@ -113,15 +113,15 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, data = (void *) arg; if (data == NULL) break; - copy_from_user_ret(&rio_cmd, data, sizeof(struct RioCommand), - -EFAULT); + if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) + return -EFAULT; if (rio_cmd.length > PAGE_SIZE) return -EINVAL; buffer = (unsigned char *) __get_free_page(GFP_KERNEL); if (buffer == NULL) return -ENOMEM; - copy_from_user_ret(buffer, rio_cmd.buffer, rio_cmd.length, - -EFAULT); + if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) + return -EFAULT; requesttype = rio_cmd.requesttype | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; @@ -150,8 +150,9 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, dbg("Executed ioctl. Result = %d (data=%04x)", le32_to_cpu(result), le32_to_cpu(*((long *) buffer))); - copy_to_user_ret(rio_cmd.buffer, buffer, - rio_cmd.length, -EFAULT); + if (copy_to_user(rio_cmd.buffer, buffer, + rio_cmd.length)) + return -EFAULT; retries = 0; } @@ -170,15 +171,15 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, data = (void *) arg; if (data == NULL) break; - copy_from_user_ret(&rio_cmd, data, sizeof(struct RioCommand), - -EFAULT); + if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) + return -EFAULT; if (rio_cmd.length > PAGE_SIZE) return -EINVAL; buffer = (unsigned char *) __get_free_page(GFP_KERNEL); if (buffer == NULL) return -ENOMEM; - copy_from_user_ret(buffer, rio_cmd.buffer, rio_cmd.length, - -EFAULT); + if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) + return -EFAULT; requesttype = rio_cmd.requesttype | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index f6206dd669e3..fb91aae15e6d 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.146 2000/07/26 23:02:51 davem Exp $ +/* $Id: atyfb.c,v 1.147 2000/08/29 07:01:56 davem Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven @@ -3010,7 +3010,8 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, fbtyp.fb_depth = info->current_par.crtc.bpp; fbtyp.fb_cmsize = disp->cmap.len; fbtyp.fb_size = info->total_vram; - copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT); + if (copy_to_user((struct fbtype *)arg, &fbtyp, sizeof(fbtyp))) + return -EFAULT; break; #endif /* __sparc__ */ #ifdef DEBUG @@ -3031,8 +3032,8 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, clk.dsp_precision = (dsp_config>>20) & 7; clk.dsp_on = dsp_on_off & 0x7ff; clk.dsp_off = (dsp_on_off>>16) & 0x7ff; - copy_to_user_ret((struct atyclk *)arg, &clk, sizeof(clk), - -EFAULT); + if (copy_to_user((struct atyclk *)arg, &clk, sizeof(clk))) + return -EFAULT; } else return -EINVAL; break; @@ -3040,8 +3041,8 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) { struct atyclk clk; struct pll_ct *pll = &info->current_par.pll.ct; - copy_from_user_ret(&clk, (struct atyclk *)arg, sizeof(clk), - -EFAULT); + if (copy_from_user(&clk, (struct atyclk *)arg, sizeof(clk))) + return -EFAULT; info->ref_clk_per = clk.ref_clk_per; pll->pll_ref_div = clk.pll_ref_div; pll->mclk_fb_div = clk.mclk_fb_div; diff --git a/drivers/video/cgfourteenfb.c b/drivers/video/cgfourteenfb.c index fe7fae535e7d..05a578bfd659 100644 --- a/drivers/video/cgfourteenfb.c +++ b/drivers/video/cgfourteenfb.c @@ -1,4 +1,4 @@ -/* $Id: cgfourteenfb.c,v 1.7 1999/11/19 09:57:01 davem Exp $ +/* $Id: cgfourteenfb.c,v 1.8 2000/08/29 07:01:56 davem Exp $ * cgfourteenfb.c: CGfourteen frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -299,15 +299,17 @@ static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned lon break; case MDI_GET_CFGINFO: mdii = (struct mdi_cfginfo *)arg; - put_user_ret(FBTYPE_MDICOLOR, &mdii->mdi_type, -EFAULT); - __put_user_ret(fb->type.fb_height, &mdii->mdi_height, -EFAULT); - __put_user_ret(fb->type.fb_width, &mdii->mdi_width, -EFAULT); - __put_user_ret(fb->s.cg14.mode, &mdii->mdi_mode, -EFAULT); - __put_user_ret(72, &mdii->mdi_pixfreq, -EFAULT); /* FIXME */ - __put_user_ret(fb->s.cg14.ramsize, &mdii->mdi_size, -EFAULT); + if (put_user(FBTYPE_MDICOLOR, &mdii->mdi_type) || + __put_user(fb->type.fb_height, &mdii->mdi_height) || + __put_user(fb->type.fb_width, &mdii->mdi_width) || + __put_user(fb->s.cg14.mode, &mdii->mdi_mode) || + __put_user(72, &mdii->mdi_pixfreq) || /* FIXME */ + __put_user(fb->s.cg14.ramsize, &mdii->mdi_size)) + return -EFAULT; break; case MDI_SET_PIXELMODE: - get_user_ret(mode, (int *)arg, -EFAULT); + if (get_user(mode, (int *)arg)) + return -EFAULT; spin_lock_irqsave(&fb->lock, flags); tmp = sbus_readb(mcr); diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 9a21d5dc7c50..b13b0aab75e6 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1030,7 +1030,8 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, err = matroxfb_get_vblank(PMINFO &vblank); if (err) return err; - copy_to_user_ret((struct fb_vblank*)arg, &vblank, sizeof(vblank), -EFAULT); + if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank))) + return -EFAULT; return 0; } case MATROXFB_SET_OUTPUT_MODE: @@ -1038,7 +1039,8 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, struct matroxioc_output_mode mom; int val; - copy_from_user_ret(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom), -EFAULT); + if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom))) + return -EFAULT; if (mom.output >= sizeof(u_int32_t)) return -EINVAL; switch (mom.output) { @@ -1084,7 +1086,8 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, struct matroxioc_output_mode mom; int val; - copy_from_user_ret(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom), -EFAULT); + if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom))) + return -EFAULT; if (mom.output >= sizeof(u_int32_t)) return -EINVAL; switch (mom.output) { @@ -1108,14 +1111,16 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, default: return -EINVAL; } - copy_to_user_ret((struct matroxioc_output_mode*)arg, &mom, sizeof(mom), -EFAULT); + if (copy_to_user((struct matroxioc_output_mode*)arg, &mom, sizeof(mom))) + return -EFAULT; return 0; } case MATROXFB_SET_OUTPUT_CONNECTION: { u_int32_t tmp; - copy_from_user_ret(&tmp, (u_int32_t*)arg, sizeof(tmp), -EFAULT); + if (copy_from_user(&tmp, (u_int32_t*)arg, sizeof(tmp))) + return -EFAULT; if (tmp & ~ACCESS_FBINFO(output.all)) return -EINVAL; if (tmp & ACCESS_FBINFO(output.sh)) @@ -1134,7 +1139,8 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, } case MATROXFB_GET_OUTPUT_CONNECTION: { - put_user_ret(ACCESS_FBINFO(output.ph), (u_int32_t*)arg, -EFAULT); + if (put_user(ACCESS_FBINFO(output.ph), (u_int32_t*)arg)) + return -EFAULT; return 0; } case MATROXFB_GET_AVAILABLE_OUTPUTS: @@ -1146,12 +1152,14 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, tmp &= ~MATROXFB_OUTPUT_CONN_SECONDARY; if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) tmp &= ~MATROXFB_OUTPUT_CONN_DFP; - put_user_ret(tmp, (u_int32_t*)arg, -EFAULT); + if (put_user(tmp, (u_int32_t*)arg)) + return -EFAULT; return 0; } case MATROXFB_GET_ALL_OUTPUTS: { - put_user_ret(ACCESS_FBINFO(output.all), (u_int32_t*)arg, -EFAULT); + if (put_user(ACCESS_FBINFO(output.all), (u_int32_t*)arg)) + return -EFAULT; return 0; } } diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index fff0a4f39334..515eb1e78a6a 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -509,7 +509,8 @@ static int matroxfb_dh_ioctl(struct inode* inode, err = matroxfb_dh_get_vblank(m2info, &vblank); if (err) return err; - copy_to_user_ret((struct fb_vblank*)arg, &vblank, sizeof(vblank), -EFAULT); + if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank))) + return -EFAULT; return 0; } case MATROXFB_SET_OUTPUT_MODE: @@ -522,7 +523,8 @@ static int matroxfb_dh_ioctl(struct inode* inode, { u_int32_t tmp; - get_user_ret(tmp, (u_int32_t*)arg, -EFAULT); + if (get_user(tmp, (u_int32_t*)arg)) + return -EFAULT; if (tmp & ~ACCESS_FBINFO(output.all)) return -EINVAL; if (tmp & ACCESS_FBINFO(output.ph)) @@ -539,7 +541,8 @@ static int matroxfb_dh_ioctl(struct inode* inode, } case MATROXFB_GET_OUTPUT_CONNECTION: { - put_user_ret(ACCESS_FBINFO(output.sh), (u_int32_t*)arg, -EFAULT); + if (put_user(ACCESS_FBINFO(output.sh), (u_int32_t*)arg)) + return -EFAULT; return 0; } case MATROXFB_GET_AVAILABLE_OUTPUTS: @@ -551,7 +554,8 @@ static int matroxfb_dh_ioctl(struct inode* inode, /* CRTC1 in DFP mode disables CRTC2 at all (I know, I'm lazy) */ if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP) tmp = 0; - put_user_ret(tmp, (u_int32_t*)arg, -EFAULT); + if (put_user(tmp, (u_int32_t*)arg)) + return -EFAULT; return 0; } } diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c index 63d2b7c76568..f9fa0d213c7d 100644 --- a/drivers/video/sbusfb.c +++ b/drivers/video/sbusfb.c @@ -584,22 +584,26 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, switch (cmd){ case FBIOGTYPE: /* return frame buffer type */ - copy_to_user_ret((struct fbtype *)arg, &fb->type, sizeof(struct fbtype), -EFAULT); + if (copy_to_user((struct fbtype *)arg, &fb->type, sizeof(struct fbtype))) + return -EFAULT; break; case FBIOGATTR: { struct fbgattr *fba = (struct fbgattr *) arg; i = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct fbgattr)); if (i) return i; - __put_user_ret(fb->emulations[0], &fba->real_type, -EFAULT); - __put_user_ret(0, &fba->owner, -EFAULT); - __copy_to_user_ret(&fba->fbtype, &fb->type, - sizeof(struct fbtype), -EFAULT); - __put_user_ret(0, &fba->sattr.flags, -EFAULT); - __put_user_ret(fb->type.fb_type, &fba->sattr.emu_type, -EFAULT); - __put_user_ret(-1, &fba->sattr.dev_specific[0], -EFAULT); - for (i = 0; i < 4; i++) - put_user_ret(fb->emulations[i], &fba->emu_types[i], -EFAULT); + if (__put_user(fb->emulations[0], &fba->real_type) || + __put_user(0, &fba->owner) || + __copy_to_user(&fba->fbtype, &fb->type, + sizeof(struct fbtype)) || + __put_user(0, &fba->sattr.flags) || + __put_user(fb->type.fb_type, &fba->sattr.emu_type) || + __put_user(-1, &fba->sattr.dev_specific[0])) + return -EFAULT; + for (i = 0; i < 4; i++) { + if (put_user(fb->emulations[i], &fba->emu_types[i])) + return -EFAULT; + } break; } case FBIOSATTR: @@ -612,7 +616,8 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, if (vt_cons[lastconsole]->vc_mode == KD_TEXT) break; } - get_user_ret(i, (int *)arg, -EFAULT); + if (get_user(i, (int *)arg)) + return -EFAULT; if (i){ if (!fb->blanked || !fb->unblank) break; @@ -627,7 +632,8 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, } break; case FBIOGVIDEO: - put_user_ret(fb->blanked, (int *) arg, -EFAULT); + if (put_user(fb->blanked, (int *) arg)) + return -EFAULT; break; case FBIOGETCMAP_SPARC: { char *rp, *gp, *bp; @@ -639,23 +645,29 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap)); if (i) return i; cmap = (struct fbcmap *) arg; - __get_user_ret(count, &cmap->count, -EFAULT); - __get_user_ret(index, &cmap->index, -EFAULT); + if (__get_user(count, &cmap->count) || + __get_user(index, &cmap->index)) + return -EFAULT; if ((index < 0) || (index > 255)) return -EINVAL; if (index + count > 256) count = 256 - index; - __get_user_ret(rp, &cmap->red, -EFAULT); - __get_user_ret(gp, &cmap->green, -EFAULT); - __get_user_ret(bp, &cmap->blue, -EFAULT); - if(verify_area (VERIFY_WRITE, rp, count)) return -EFAULT; - if(verify_area (VERIFY_WRITE, gp, count)) return -EFAULT; - if(verify_area (VERIFY_WRITE, bp, count)) return -EFAULT; + if (__get_user(rp, &cmap->red) || + __get_user(gp, &cmap->green) || + __get_user(bp, &cmap->blue)) + return -EFAULT; + if (verify_area (VERIFY_WRITE, rp, count)) + return -EFAULT; + if (verify_area (VERIFY_WRITE, gp, count)) + return -EFAULT; + if (verify_area (VERIFY_WRITE, bp, count)) + return -EFAULT; end = index + count; for (i = index; i < end; i++){ - __put_user_ret(fb->color_map CM(i,0), rp, -EFAULT); - __put_user_ret(fb->color_map CM(i,1), gp, -EFAULT); - __put_user_ret(fb->color_map CM(i,2), bp, -EFAULT); + if (__put_user(fb->color_map CM(i,0), rp) || + __put_user(fb->color_map CM(i,1), gp) || + __put_user(fb->color_map CM(i,2), bp)) + return -EFAULT; rp++; gp++; bp++; } (*fb->loadcmap)(fb, NULL, index, count); @@ -671,24 +683,32 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap)); if (i) return i; cmap = (struct fbcmap *) arg; - __get_user_ret(count, &cmap->count, -EFAULT); - __get_user_ret(index, &cmap->index, -EFAULT); + if (__get_user(count, &cmap->count) || + __get_user(index, &cmap->index)) + return -EFAULT; if ((index < 0) || (index > 255)) return -EINVAL; if (index + count > 256) count = 256 - index; - __get_user_ret(rp, &cmap->red, -EFAULT); - __get_user_ret(gp, &cmap->green, -EFAULT); - __get_user_ret(bp, &cmap->blue, -EFAULT); - if(verify_area (VERIFY_READ, rp, count)) return -EFAULT; - if(verify_area (VERIFY_READ, gp, count)) return -EFAULT; - if(verify_area (VERIFY_READ, bp, count)) return -EFAULT; + if (__get_user(rp, &cmap->red) || + __get_user(gp, &cmap->green) || + __get_user(bp, &cmap->blue)) + return -EFAULT; + if (verify_area (VERIFY_READ, rp, count)) + return -EFAULT; + if (verify_area (VERIFY_READ, gp, count)) + return -EFAULT; + if (verify_area (VERIFY_READ, bp, count)) + return -EFAULT; end = index + count; for (i = index; i < end; i++){ - __get_user_ret(fb->color_map CM(i,0), rp, -EFAULT); - __get_user_ret(fb->color_map CM(i,1), gp, -EFAULT); - __get_user_ret(fb->color_map CM(i,2), bp, -EFAULT); + if (__get_user(fb->color_map CM(i,0), rp)) + return -EFAULT; + if (__get_user(fb->color_map CM(i,1), gp)) + return -EFAULT; + if (__get_user(fb->color_map CM(i,2), bp)) + return -EFAULT; rp++; gp++; bp++; } (*fb->loadcmap)(fb, NULL, index, count); @@ -699,8 +719,9 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, if (!fb->setcursor) return -EINVAL; if(verify_area (VERIFY_WRITE, p, sizeof (struct fbcurpos))) return -EFAULT; - __put_user_ret(fb->cursor.hwsize.fbx, &p->fbx, -EFAULT); - __put_user_ret(fb->cursor.hwsize.fby, &p->fby, -EFAULT); + if (__put_user(fb->cursor.hwsize.fbx, &p->fbx) || + __put_user(fb->cursor.hwsize.fby, &p->fby)) + return -EFAULT; break; } case FBIOSCURSOR: diff --git a/drivers/video/sisfb.c b/drivers/video/sisfb.c index 994e8732ef41..0307995af153 100644 --- a/drivers/video/sisfb.c +++ b/drivers/video/sisfb.c @@ -1,5 +1,5 @@ /* - * SiS 300/630/540 frame buffer device For Kernal 2.3.x + * SiS 300/630/540 frame buffer device For Kernal 2.4.x * * This driver is partly based on the VBE 2.0 compliant graphic * boards framebuffer driver, which is @@ -10,6 +10,7 @@ #define EXPORT_SYMTAB #undef SISFBDEBUG +#undef CONFIG_FB_SIS_LINUXBIOS #include #include @@ -174,11 +175,10 @@ static struct board { u16 vendor, device; const char *name; } dev_list[] = { - { - PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, "SIS 300"}, { - PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5300, "SIS 540"}, { - PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_6300, "SIS 630"}, { - 0, 0, NULL} + {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, "SIS 300"}, + {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, "SIS 540"}, + {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, "SIS 630"}, + {0, 0, NULL} }; /* card parameters */ @@ -192,9 +192,16 @@ static int video_cmap_len; static int sisfb_off = 0; static struct fb_var_screeninfo default_var = { - 0, 0, 0, 0, 0, 0, 0, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, FB_ACTIVATE_NOW, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, + 0, + {0, 8, 0}, + {0, 8, 0}, + {0, 8, 0}, + {0, 0, 0}, + 0, + FB_ACTIVATE_NOW, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, FB_VMODE_NONINTERLACED, {0, 0, 0, 0, 0, 0} @@ -202,9 +209,11 @@ static struct fb_var_screeninfo default_var = { static struct display disp; static struct fb_info fb_info; + static struct { u16 blue, green, red, pad; } palette[256]; + static union { #ifdef FBCON_HAS_CFB16 u16 cfb16[16]; @@ -230,7 +239,7 @@ u16 P3c4, P3d4, P3c0, P3ce, P3c2, P3ca, P3c6, P3c7, P3c8, P3c9, P3da; u16 CRT1VCLKLen; u16 flag_clearbuffer; u16 CRT1VCLKLen; -int ModeIDOffset, StandTable, CRT1Table, ScreenOffset, MCLKData, ECLKData; +int ModeIDOffset, StandTable, CRT1Table, ScreenOffset; int REFIndex, ModeType; int VCLKData; int RAMType; @@ -249,26 +258,25 @@ static const struct _sisbios_mode { u16 cols; u16 rows; } sisbios_mode[] = { - { - "640x480x8", 0x2E, 640, 480, 8, 1, 80, 30}, { - "640x480x16", 0x44, 640, 480, 16, 1, 80, 30}, { - "640x480x32", 0x62, 640, 480, 32, 1, 80, 30}, { - "800x600x8", 0x30, 800, 600, 8, 2, 100, 37}, { - "800x600x16", 0x47, 800, 600, 16, 2, 100, 37}, { - "800x600x32", 0x63, 800, 600, 32, 2, 100, 37}, { - "1024x768x8", 0x38, 1024, 768, 8, 2, 128, 48}, { - "1024x768x16", 0x4A, 1024, 768, 16, 2, 128, 48}, { - "1024x768x32", 0x64, 1024, 768, 32, 2, 128, 48}, { - "1280x1024x8", 0x3A, 1280, 1024, 8, 2, 160, 64}, { - "1280x1024x16", 0x4D, 1280, 1024, 16, 2, 160, 64}, { - "1280x1024x32", 0x65, 1280, 1024, 32, 2, 160, 64}, { - "1600x1200x8", 0x3C, 1600, 1200, 8, 1, 200, 75}, { - "1600x1200x16", 0x3D, 1600, 1200, 16, 1, 200, 75}, { - "1600x1200x32", 0x66, 1600, 1200, 32, 1, 200, 75}, { - "1920x1440x8", 0x68, 1920, 1440, 8, 1, 240, 75}, { - "1920x1440x16", 0x69, 1920, 1440, 16, 1, 240, 75}, { - "1920x1440x32", 0x6B, 1920, 1440, 32, 1, 240, 75}, { - "\0", 0x00, 0, 0, 0, 0, 0, 0} + {"640x480x8", 0x2E, 640, 480, 8, 1, 80, 30}, + {"640x480x16", 0x44, 640, 480, 16, 1, 80, 30}, + {"640x480x32", 0x62, 640, 480, 32, 1, 80, 30}, + {"800x600x8", 0x30, 800, 600, 8, 2, 100, 37}, + {"800x600x16", 0x47, 800, 600, 16, 2, 100, 37}, + {"800x600x32", 0x63, 800, 600, 32, 2, 100, 37}, + {"1024x768x8", 0x38, 1024, 768, 8, 2, 128, 48}, + {"1024x768x16", 0x4A, 1024, 768, 16, 2, 128, 48}, + {"1024x768x32", 0x64, 1024, 768, 32, 2, 128, 48}, + {"1280x1024x8", 0x3A, 1280, 1024, 8, 2, 160, 64}, + {"1280x1024x16", 0x4D, 1280, 1024, 16, 2, 160, 64}, + {"1280x1024x32", 0x65, 1280, 1024, 32, 2, 160, 64}, + {"1600x1200x8", 0x3C, 1600, 1200, 8, 1, 200, 75}, + {"1600x1200x16", 0x3D, 1600, 1200, 16, 1, 200, 75}, + {"1600x1200x32", 0x66, 1600, 1200, 32, 1, 200, 75}, + {"1920x1440x8", 0x68, 1920, 1440, 8, 1, 240, 75}, + {"1920x1440x16", 0x69, 1920, 1440, 16, 1, 240, 75}, + {"1920x1440x32", 0x6B, 1920, 1440, 32, 1, 240, 75}, + {"\0", 0x00, 0, 0, 0, 0, 0, 0} }; static struct _vrate { @@ -277,57 +285,33 @@ static struct _vrate { u16 yres; u16 refresh; } vrate[] = { - { - 1, 640, 480, 60}, { - 2, 640, 480, 72}, { - 3, 640, 480, 75}, { - 4, 640, 480, 85}, { - 5, 640, 480, 100}, { - 6, 640, 480, 120}, { - 7, 640, 480, 160}, { - 8, 640, 480, 200}, { - 1, 800, 600, 56}, { - 2, 800, 600, 60}, { - 3, 800, 600, 72}, { - 4, 800, 600, 75}, { - 5, 800, 600, 85}, { - 6, 800, 600, 100}, { - 7, 800, 600, 120}, { - 8, 800, 600, 160}, { - 1, 1024, 768, 56}, { - 2, 1024, 768, 60}, { - 3, 1024, 768, 72}, { - 4, 1024, 768, 75}, { - 5, 1024, 768, 85}, { - 6, 1024, 768, 100}, { - 7, 1024, 768, 120}, { - 1, 1280, 1024, 43}, { - 2, 1280, 1024, 60}, { - 3, 1280, 1024, 75}, { - 4, 1280, 1024, 85}, { - 1, 1600, 1200, 60}, { - 2, 1600, 1200, 65}, { - 3, 1600, 1200, 70}, { - 4, 1600, 1200, 75}, { - 5, 1600, 1200, 85}, { - 1, 1920, 1440, 60}, { - 0, 0, 0, 0} + {1, 640, 480, 60}, {2, 640, 480, 72}, {3, 640, 480, 75}, {4, 640, 480, 85}, + {5, 640, 480, 100}, {6, 640, 480, 120}, {7, 640, 480, 160}, {8, 640, 480, 200}, + {1, 800, 600, 56}, {2, 800, 600, 60}, {3, 800, 600, 72}, {4, 800, 600, 75}, + {5, 800, 600, 85}, {6, 800, 600, 100}, {7, 800, 600, 120}, {8, 800, 600, 160}, + {1, 1024, 768, 43}, {2, 1024, 768, 60}, {3, 1024, 768, 70}, {4, 1024, 768, 75}, + {5, 1024, 768, 85}, {6, 1024, 768, 100}, {7, 1024, 768, 120}, + {1, 1280, 1024, 43}, {2, 1280, 1024, 60}, {3, 1280, 1024, 75}, {4, 1280, 1024, 85}, + {1, 1600, 1200, 60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75}, + {5, 1600, 1200, 85}, + {1, 1920, 1440, 60}, + {0, 0, 0, 0} }; - -u16 DRAMType[17][5] = - { {0x0C, 0x0A, 0x02, 0x40, 0x39}, {0x0D, 0x0A, 0x01, 0x40, 0x48}, -{0x0C, 0x09, 0x02, 0x20, 0x35}, {0x0D, 0x09, 0x01, 0x20, 0x44}, -{0x0C, 0x08, 0x02, 0x10, 0x31}, {0x0D, 0x08, 0x01, 0x10, 0x40}, -{0x0C, 0x0A, 0x01, 0x20, 0x34}, {0x0C, 0x09, 0x01, 0x08, 0x32}, -{0x0B, 0x08, 0x02, 0x08, 0x21}, {0x0C, 0x08, 0x01, 0x08, 0x30}, -{0x0A, 0x08, 0x02, 0x04, 0x11}, {0x0B, 0x0A, 0x01, 0x10, 0x28}, -{0x09, 0x08, 0x02, 0x02, 0x01}, {0x0B, 0x09, 0x01, 0x08, 0x24}, -{0x0B, 0x08, 0x01, 0x04, 0x20}, {0x0A, 0x08, 0x01, 0x02, 0x10}, -{0x09, 0x08, 0x01, 0x01, 0x00} +u16 DRAMType[17][5] = { + {0x0C, 0x0A, 0x02, 0x40, 0x39}, {0x0D, 0x0A, 0x01, 0x40, 0x48}, + {0x0C, 0x09, 0x02, 0x20, 0x35}, {0x0D, 0x09, 0x01, 0x20, 0x44}, + {0x0C, 0x08, 0x02, 0x10, 0x31}, {0x0D, 0x08, 0x01, 0x10, 0x40}, + {0x0C, 0x0A, 0x01, 0x20, 0x34}, {0x0C, 0x09, 0x01, 0x08, 0x32}, + {0x0B, 0x08, 0x02, 0x08, 0x21}, {0x0C, 0x08, 0x01, 0x08, 0x30}, + {0x0A, 0x08, 0x02, 0x04, 0x11}, {0x0B, 0x0A, 0x01, 0x10, 0x28}, + {0x09, 0x08, 0x02, 0x02, 0x01}, {0x0B, 0x09, 0x01, 0x08, 0x24}, + {0x0B, 0x08, 0x01, 0x04, 0x20}, {0x0A, 0x08, 0x01, 0x02, 0x10}, + {0x09, 0x08, 0x01, 0x01, 0x00} }; -u16 MDA_DAC[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +u16 MDA_DAC[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, @@ -337,7 +321,8 @@ u16 MDA_DAC[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F }; -u16 CGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, +u16 CGA_DAC[] = { + 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F, 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F, @@ -347,7 +332,8 @@ u16 CGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F }; -u16 EGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15, +u16 EGA_DAC[] = { + 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15, 0x20, 0x30, 0x24, 0x34, 0x21, 0x31, 0x25, 0x35, 0x08, 0x18, 0x0C, 0x1C, 0x09, 0x19, 0x0D, 0x1D, 0x28, 0x38, 0x2C, 0x3C, 0x29, 0x39, 0x2D, 0x3D, @@ -357,7 +343,8 @@ u16 EGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15, 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F }; -u16 VGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, +u16 VGA_DAC[] = { + 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F, 0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18, 0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F, @@ -369,6 +356,55 @@ u16 VGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, 0x0B, 0x0C, 0x0D, 0x0F, 0x10 }; +#ifdef CONFIG_FB_SIS_LINUXBIOS + +#define Monitor1Sense 0x20 + +unsigned char SRegsInit[] = { + 0x03, 0x00, 0x03, 0x00, 0x02, 0xa1, 0x00, 0x13, + 0x2f, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa1, 0x76, 0xb2, 0xf6, 0x0d, 0x00, 0x00, 0x00, + 0x37, 0x61, 0x80, 0x1b, 0xe1, 0x01, 0x55, 0x43, + 0x80, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x8e, 0x40, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff +}; + +unsigned char SRegs[] = { + 0x03, 0x01, 0x0F, 0x00, 0x0E, 0xA1, 0x02, 0x13, + 0x3F, 0x86, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x0B, 0x0F, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x40, 0x00, + 0xA1, 0xB6, 0xB2, 0xF6, 0x0D, 0x00, 0xF8, 0xF0, + 0x37, 0x61, 0x80, 0x1B, 0xE1, 0x80, 0x55, 0x43, + 0x80, 0x00, 0x11, 0xFF, 0x00, 0x00, 0x00, 0xFF, + 0x8E, 0x40, 0x00, 0x00, 0x08, 0x00, 0xFF, 0xFF +}; + +unsigned char CRegs[] = { + 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe9, 0x0b, 0xdf, 0x50, 0x40, 0xe7, 0x04, 0xa3, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff +}; // clear CR11[7] + +unsigned char GRegs[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, 0x00 +}; + +unsigned char ARegs[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char MReg = 0x6f; + +#endif + + /* HEAP stuff */ struct OH { @@ -463,6 +499,7 @@ static void set_reg3(u16 port, u16 data); static void set_reg4(u16 port, unsigned long data); static u8 get_reg1(u16 port, u16 index); static u8 get_reg2(u16 port); +//#ifndef CONFIG_FB_SIS_LINUXBIOS static u32 get_reg3(u16 port); static u16 get_modeID_length(unsigned long ROMAddr, u16 ModeNo); static int search_modeID(unsigned long ROMAddr, u16 ModeNo); @@ -488,6 +525,7 @@ static void set_crt1_FIFO(unsigned long ROMAddr); static void set_crt1_FIFO2(unsigned long ROMAddr); static void set_crt1_mode_regs(unsigned long ROMAddr, u16 ModeNo); static void set_interlace(unsigned long ROMAddr, u16 ModeNo); +//#endif static void write_DAC(u16 dl, u16 ah, u16 al, u16 dh); static void load_DAC(unsigned long ROMAddr); static void display_on(void); @@ -781,6 +819,7 @@ static void sisfb_set_disp(int con, struct fb_var_screeninfo *var) sw = &fbcon_cfb8; break; #endif + #ifdef FBCON_HAS_CFB16 case 15: case 16: @@ -788,18 +827,21 @@ static void sisfb_set_disp(int con, struct fb_var_screeninfo *var) display->dispsw_data = fbcon_cmap.cfb16; break; #endif + #ifdef FBCON_HAS_CFB24 case 24: sw = &fbcon_cfb24; display->dispsw_data = fbcon_cmap.cfb24; break; #endif + #ifdef FBCON_HAS_CFB32 case 32: sw = &fbcon_cfb32; display->dispsw_data = fbcon_cmap.cfb32; break; #endif + default: sw = &fbcon_dummy; return; @@ -810,7 +852,6 @@ static void sisfb_set_disp(int con, struct fb_var_screeninfo *var) display->scrollmode = SCROLL_YREDRAW; sisfb_sw.bmove = fbcon_redraw_bmove; - } /* @@ -818,9 +859,8 @@ static void sisfb_set_disp(int con, struct fb_var_screeninfo *var) * Return != 0 for invalid regno. */ -static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *fb_info) +static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, + unsigned *transp, struct fb_info *fb_info) { if (regno >= video_cmap_len) return 1; @@ -838,9 +878,8 @@ static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, * entries in the var structure). Return != 0 for invalid regno. */ -static int sis_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *fb_info) +static int sis_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *fb_info) { if (regno >= video_cmap_len) @@ -949,14 +988,13 @@ static int do_set_var(struct fb_var_screeninfo *var, int isactive, return 1; } - if (search_refresh_rate(ivideo.refresh_rate) == 0) { /* not supported rate */ + if (search_refresh_rate(ivideo.refresh_rate) == 0) { + /* not supported rate */ rate_idx = sisbios_mode[mode_idx].rate_idx; ivideo.refresh_rate = 60; } - - if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) - && isactive) { + if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) { pre_setmode(); if (SiSSetMode(mode_no)) { @@ -1020,7 +1058,8 @@ static int sisfb_heap_init(void) struct OH *poh; u8 jTemp, tq_state; - if(ivideo.video_size > 0x800000) /* video ram is large than 8M */ + if (ivideo.video_size > 0x800000) + /* video ram is large than 8M */ heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_8M; else heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_4M; @@ -1401,22 +1440,28 @@ static u32 get_reg3(u16 port) static u16 get_modeID_length(unsigned long ROMAddr, u16 ModeNo) { -#if 0 unsigned char ModeID; u16 modeidlength; u16 usModeIDOffset; + unsigned short PreviousWord,CurrentWord; - modeidlength = 0; - usModeIDOffset = *((u16 *) (ROMAddr + 0x20A)); - ModeID = *((unsigned char *) (ROMAddr + usModeIDOffset)); - while (ModeID != 0x2E) { - modeidlength++; - usModeIDOffset = usModeIDOffset + 1; - ModeID = *((unsigned char *) (ROMAddr + usModeIDOffset)); - } - return (modeidlength); -#endif return(10); + + modeidlength=0; + usModeIDOffset=*((unsigned short *)(ROMAddr+0x20A)); // Get EModeIDTable + + CurrentWord=*((unsigned short *)(ROMAddr+usModeIDOffset)); // Offset 0x20A + PreviousWord=*((unsigned short *)(ROMAddr+usModeIDOffset-2)); // Offset 0x20A + while((CurrentWord!=0x2E07)||(PreviousWord!=0x0801)) + { + modeidlength++; + usModeIDOffset=usModeIDOffset+1; // 10 <= ExtStructSize + CurrentWord=*((unsigned short *)(ROMAddr+usModeIDOffset)); + PreviousWord=*((unsigned short *)(ROMAddr+usModeIDOffset-2)); + } + modeidlength++; + + return(modeidlength); } static int search_modeID(unsigned long ROMAddr, u16 ModeNo) @@ -1470,8 +1515,7 @@ static void get_mode_ptr(unsigned long ROMAddr, u16 ModeNo) StandTable = *((u16 *) (ROMAddr + 0x202)); if (ModeNo <= 13) - index = - *((unsigned char *) (ROMAddr + ModeIDOffset + 0x03)); + index = *((unsigned char *) (ROMAddr + ModeIDOffset + 0x03)); else { if (ModeType <= 0x02) index = 0x1B; @@ -1488,26 +1532,40 @@ static void set_seq_regs(unsigned long ROMAddr) unsigned char SRdata; u16 i; +#ifdef CONFIG_FB_SIS_LINUXBIOS + SRdata = SRegs[0x01]; +#else set_reg1(P3c4, 0x00, 0x03); StandTable = StandTable + 0x05; SRdata = *((unsigned char *) (ROMAddr + StandTable)); +#endif + SRdata = SRdata | 0x20; set_reg1(P3c4, 0x01, SRdata); + for (i = 02; i <= 04; i++) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + SRdata = SRegs[i]; +#else StandTable++; SRdata = *((unsigned char *) (ROMAddr + StandTable)); +#endif set_reg1(P3c4, i, SRdata); } } static void set_misc_regs(unsigned long ROMAddr) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + set_reg3(P3c2, 0x23); +#else unsigned char Miscdata; StandTable++; Miscdata = *((unsigned char *) (ROMAddr + StandTable)); set_reg3(P3c2, Miscdata); +#endif } static void set_crtc_regs(unsigned long ROMAddr) @@ -1516,13 +1574,19 @@ static void set_crtc_regs(unsigned long ROMAddr) u16 i; CRTCdata = (unsigned char) get_reg1(P3d4, 0x11); +#ifndef CONFIG_FB_SIS_LINUXBIOS CRTCdata = CRTCdata & 0x7f; +#endif set_reg1(P3d4, 0x11, CRTCdata); for (i = 0; i <= 0x18; i++) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + set_reg1(P3d4, i, CRegs[i]); +#else StandTable++; CRTCdata = *((unsigned char *) (ROMAddr + StandTable)); set_reg1(P3d4, i, CRTCdata); +#endif } } @@ -1532,17 +1596,23 @@ static void set_attregs(unsigned long ROMAddr) u16 i; for (i = 0; i <= 0x13; i++) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + get_reg2(P3da); + set_reg3(P3c0, i); + set_reg3(P3c0, ARegs[i]); +#else StandTable++; ARdata = *((unsigned char *) (ROMAddr + StandTable)); get_reg2(P3da); set_reg3(P3c0, i); set_reg3(P3c0, ARdata); +#endif } + get_reg2(P3da); set_reg3(P3c0, 0x14); set_reg3(P3c0, 0x00); - get_reg2(P3da); set_reg3(P3c0, 0x20); } @@ -1553,15 +1623,22 @@ static void set_grc_regs(unsigned long ROMAddr) u16 i; for (i = 0; i <= 0x08; i++) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + set_reg1(P3ce, i, GRegs[i]); +#else StandTable++; GRdata = *((unsigned char *) (ROMAddr + StandTable)); set_reg1(P3ce, i, GRdata); +#endif } + +#ifndef CONFIG_FB_SIS_LINUXBIOS if (ModeType > ModeVGA) { GRdata = (unsigned char) get_reg1(P3ce, 0x05); GRdata = GRdata & 0xBF; set_reg1(P3ce, 0x05, GRdata); } +#endif } static void ClearExt1Regs(void) @@ -1637,6 +1714,9 @@ static int get_rate_ptr(unsigned long ROMAddr, u16 ModeNo) static void set_sync(unsigned long ROMAddr) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + set_reg3(P3c2, MReg); +#else u16 sync; u16 temp; @@ -1645,10 +1725,33 @@ static void set_sync(unsigned long ROMAddr) temp = 0x2F; temp = temp | sync; set_reg3(P3c2, temp); +#endif } static void set_crt1_crtc(unsigned long ROMAddr) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + unsigned char data; + u16 i; + + data = (unsigned char) get_reg1(P3d4, 0x11); + data = data & 0x7F; + set_reg1(P3d4, 0x11, data); + + for (i = 0; i <= 0x07; i++) + set_reg1(P3d4, i, CRegs[i]); + for (i = 0x10; i <= 0x12; i++) + set_reg1(P3d4, i, CRegs[i]); + for (i = 0x15; i <= 0x16; i++) + set_reg1(P3d4, i, CRegs[i]); + for (i = 0x0A; i <= 0x0C; i++) + set_reg1(P3c4, i, SRegs[i]); + + data = SRegs[0x0E] & 0xE0; + set_reg1(P3c4, 0x0E, data); + + set_reg1(P3d4, 0x09, CRegs[0x09]); +#else unsigned char index; unsigned char data; u16 i; @@ -1707,10 +1810,16 @@ static void set_crt1_crtc(unsigned long ROMAddr) if (ModeType > 0x03) set_reg1(P3d4, 0x14, 0x4F); +#endif } + static void set_crt1_offset(unsigned long ROMAddr) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + set_reg1(P3c4, 0x0E, SRegs[0x0E]); + set_reg1(P3c4, 0x10, SRegs[0x10]); +#else u16 temp, ah, al; u16 temp2, i; u16 DisplayUnit; @@ -1773,6 +1882,7 @@ static void set_crt1_offset(unsigned long ROMAddr) else ah = ah + 2; set_reg1(P3c4, 0x10, ah); +#endif } static u16 get_vclk_len(unsigned long ROMAddr) @@ -1792,31 +1902,44 @@ static u16 get_vclk_len(unsigned long ROMAddr) static void set_crt1_vclk(unsigned long ROMAddr) { u16 i; + +#ifndef CONFIG_FB_SIS_LINUXBIOS unsigned char index, data; index = *((unsigned char *) (ROMAddr + REFIndex + 0x03)); + index &= 0x03F; CRT1VCLKLen = get_vclk_len(ROMAddr); data = index * CRT1VCLKLen; VCLKData = *((u16 *) (ROMAddr + 0x208)); VCLKData = VCLKData + data; +#endif set_reg1(P3c4, 0x31, 0); for (i = 0x2B; i <= 0x2C; i++) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + set_reg1(P3c4, i, SRegs[i]); +#else data = *((unsigned char *) (ROMAddr + VCLKData)); set_reg1(P3c4, i, data); VCLKData++; +#endif } set_reg1(P3c4, 0x2D, 0x80); } - static void set_vclk_state(unsigned long ROMAddr, u16 ModeNo) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + set_reg1(P3c4, 0x32, SRegs[0x32]); + set_reg1(P3c4, 0x07, SRegs[0x07]); +#else + u16 data, data2; u16 VCLK; unsigned char index; index = *((unsigned char *) (ROMAddr + REFIndex + 0x03)); + index &= 0x3F; CRT1VCLKLen = get_vclk_len(ROMAddr); data = index * CRT1VCLKLen; VCLKData = *((u16 *) (ROMAddr + 0x208)); @@ -1849,6 +1972,7 @@ static void set_vclk_state(unsigned long ROMAddr, u16 ModeNo) data = data & 0xFC; data = data | data2; set_reg1(P3c4, 0x07, data); +#endif } static u16 calc_delay2(unsigned long ROMAddr, u16 key) @@ -1926,6 +2050,7 @@ static void set_crt1_FIFO(unsigned long ROMAddr) u16 ah, bl, A, B; index = *((unsigned char *) (ROMAddr + REFIndex + 0x03)); + index &= 0x3F; CRT1VCLKLen = get_vclk_len(ROMAddr); data = index * CRT1VCLKLen; VCLKData = *((u16 *) (ROMAddr + 0x208)); @@ -2017,14 +2142,26 @@ static void set_crt1_FIFO(unsigned long ROMAddr) set_reg1(P3c4, 0x09, data2); } - static void set_crt1_FIFO2(unsigned long ROMAddr) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + set_reg1(P3c4, 0x15, SRegs[0x15]); + + set_reg4(0xcf8, 0x80000050); + set_reg4(0xcfc, 0xc5041e04); + + set_reg1(P3c4, 0x08, SRegs[0x08]); + set_reg1(P3c4, 0x0F, SRegs[0x0F]); + set_reg1(P3c4, 0x3b, 0x00); + set_reg1(P3c4, 0x09, SRegs[0x09]); +#else + u16 index, data, VCLK, data2, MCLKOffset, MCLK, colorth = 1; u16 ah, bl, B; unsigned long eax; index = *((unsigned char *) (ROMAddr + REFIndex + 0x03)); + index &= 0x3F; CRT1VCLKLen = get_vclk_len(ROMAddr); data = index * CRT1VCLKLen; VCLKData = *((u16 *) (ROMAddr + 0x208)); @@ -2115,10 +2252,17 @@ static void set_crt1_FIFO2(unsigned long ROMAddr) data2 = data2 & 0xF0; data2 = data2 | data; set_reg1(P3c4, 0x09, data2); +#endif } static void set_crt1_mode_regs(unsigned long ROMAddr, u16 ModeNo) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + set_reg1(P3c4, 0x06, SRegs[0x06]); + set_reg1(P3c4, 0x01, SRegs[0x01]); + set_reg1(P3c4, 0x0F, SRegs[0x0F]); + set_reg1(P3c4, 0x21, SRegs[0x21]); +#else u16 data, data2, data3; @@ -2166,11 +2310,16 @@ static void set_crt1_mode_regs(unsigned long ROMAddr, u16 ModeNo) else data = data | 0xA0; set_reg1(P3c4, 0x21, data); +#endif } - static void set_interlace(unsigned long ROMAddr, u16 ModeNo) { +#ifdef CONFIG_FB_SIS_LINUXBIOS + set_reg1(P3d4, 0x19, CRegs[0x19]); + set_reg1(P3d4, 0x1A, CRegs[0x1A]); +#else + unsigned long Temp; u16 data, Temp2; @@ -2201,6 +2350,7 @@ static void set_interlace(unsigned long ROMAddr, u16 ModeNo) if (ModeNo == 0x37) Temp2 = Temp2 | 0x40; set_reg1(P3d4, 0x1A, (u16) Temp2); +#endif } static void write_DAC(u16 dl, u16 ah, u16 al, u16 dh) @@ -2239,6 +2389,7 @@ static void load_DAC(unsigned long ROMAddr) u16 al, ah, dh; u16 *table = VGA_DAC; +#ifndef CONFIG_FB_SIS_LINUXBIOS data = *((u16 *) (ROMAddr + ModeIDOffset + 0x01)); data = data & DACInfoFlag; time = 64; @@ -2252,6 +2403,11 @@ static void load_DAC(unsigned long ROMAddr) time = 256; table = VGA_DAC; } +#else + time = 256; + table = VGA_DAC; +#endif + if (time == 256) j = 16; else @@ -2316,12 +2472,339 @@ static void display_on(void) set_reg1(P3c4, 0x01, data); } +void SetMemoryClock(void) +{ + unsigned char i; + int idx; + + u8 MCLK[] = { + 0x5A, 0x64, 0x80, 0x66, 0x00, // SDRAM + 0xB3, 0x45, 0x80, 0x83, 0x00, // SGRAM + 0x37, 0x61, 0x80, 0x00, 0x01, // ESDRAM + 0x37, 0x22, 0x80, 0x33, 0x01, + 0x37, 0x61, 0x80, 0x00, 0x01, + 0x37, 0x61, 0x80, 0x00, 0x01, + 0x37, 0x61, 0x80, 0x00, 0x01, + 0x37, 0x61, 0x80, 0x00, 0x01 + }; + + u8 ECLK[] = { + 0x54, 0x43, 0x80, 0x00, 0x01, + 0x53, 0x43, 0x80, 0x00, 0x01, + 0x55, 0x43, 0x80, 0x00, 0x01, + 0x52, 0x43, 0x80, 0x00, 0x01, + 0x3f, 0x42, 0x80, 0x00, 0x01, + 0x54, 0x43, 0x80, 0x00, 0x01, + 0x54, 0x43, 0x80, 0x00, 0x01, + 0x54, 0x43, 0x80, 0x00, 0x01 + }; + + idx = RAMType * 5; + + for (i = 0x28; i <= 0x2A; i++) { // Set MCLK + set_reg1(P3c4, i, MCLK[idx]); + idx++; + } + + idx = RAMType * 5; + for (i = 0x2E; i <= 0x30; i++) { // Set ECLK + set_reg1(P3c4, i, ECLK[idx]); + idx++; + } +} + +void ClearDAC(u16 port) +{ + int i; + + set_reg3(P3c8, 0x00); + for (i = 0; i < (256 * 3); i++) + set_reg3(P3c9, 0x00); +} + +void ClearALLBuffer(void) +{ + unsigned long AdapterMemorySize; + + AdapterMemorySize = get_reg1(P3c4, 0x14); + AdapterMemorySize = AdapterMemorySize & 0x3F; + AdapterMemorySize++; + + memset((char *) ivideo.video_vbase, 0, AdapterMemorySize); +} + +void LongWait(void) +{ + unsigned long temp; + + for (temp = 1; temp > 0;) { + temp = get_reg2(P3da); + temp = temp & 0x08; + } + for (; temp == 0;) { + temp = get_reg2(P3da); + temp = temp & 0x08; + } +} + +void WaitDisplay(void) +{ + unsigned short temp; + + for (temp = 0; temp == 0;) { + temp = get_reg2(P3da); + temp = temp & 0x01; + } + for (; temp == 1;) { + temp = get_reg2(P3da); + temp = temp & 0x01; + } +} + +int TestMonitorType(unsigned short d1, unsigned short d2, unsigned short d3) +{ + unsigned short temp; + set_reg3(P3c6, 0xFF); + set_reg3(P3c8, 0x00); + set_reg3(P3c9, d1); + set_reg3(P3c9, d2); + set_reg3(P3c9, d3); + WaitDisplay(); //wait horizontal retrace + temp = get_reg2(P3c2); + if (temp & 0x10) + return 1; + else + return 0; +} + +void SetRegANDOR(unsigned short Port, unsigned short Index, + unsigned short DataAND, unsigned short DataOR) +{ + unsigned short temp1; + temp1 = get_reg1(Port, Index); //part1port index 02 + temp1 = (temp1 & (DataAND)) | DataOR; + set_reg1(Port, Index, temp1); +} + + +int DetectMonitor(void) +{ + unsigned short flag1; + unsigned short DAC_TEST_PARMS[3] = { 0x0F, 0x0F, 0x0F }; + unsigned short DAC_CLR_PARMS[3] = { 0x00, 0x00, 0x00 }; + + flag1 = get_reg1(P3c4, 0x38); //call BridgeisOn + if ((flag1 & 0x20)) { + set_reg1(P3d4, 0x30, 0x41); + } + + SiSSetMode(0x2E); //set mode to 0x2E instead of 0x3 + + ClearDAC(P3c8); + ClearALLBuffer(); + + LongWait(); + LongWait(); + + flag1 = TestMonitorType(DAC_TEST_PARMS[0], DAC_TEST_PARMS[1], + DAC_TEST_PARMS[2]); + if (flag1 == 0) { + flag1 = TestMonitorType(DAC_TEST_PARMS[0], DAC_TEST_PARMS[1], + DAC_TEST_PARMS[2]); + } + + if (flag1 == 1) { + SetRegANDOR(P3d4, 0x32, ~Monitor1Sense, Monitor1Sense); + } else { + SetRegANDOR(P3d4, 0x32, ~Monitor1Sense, 0x0); + } + + TestMonitorType(DAC_CLR_PARMS[0], DAC_CLR_PARMS[1], + DAC_CLR_PARMS[2]); + + set_reg1(P3d4, 0x34, 0x4A); + + return 1; +} + +int SiSInit300(void) +{ + //unsigned long ROMAddr = rom_vbase; + u16 BaseAddr = (u16) ivideo.vga_base; + unsigned char i, temp, AGP; + unsigned long j, k, ulTemp; + unsigned char SR11, SR19, SR1A, SR21, SR22; + unsigned char SR14; + unsigned long Temp; + + P3c4 = BaseAddr + 0x14; + P3d4 = BaseAddr + 0x24; + P3c0 = BaseAddr + 0x10; + P3ce = BaseAddr + 0x1e; + P3c2 = BaseAddr + 0x12; + P3ca = BaseAddr + 0x1a; + P3c6 = BaseAddr + 0x16; + P3c7 = BaseAddr + 0x17; + P3c8 = BaseAddr + 0x18; + P3c9 = BaseAddr + 0x19; + P3da = BaseAddr + 0x2A; + + set_reg1(P3c4, 0x05, 0x86); // 1.Openkey + + SR14 = (unsigned char) get_reg1(P3c4, 0x14); + SR19 = (unsigned char) get_reg1(P3c4, 0x19); + SR1A = (unsigned char) get_reg1(P3c4, 0x1A); + + for (i = 0x06; i < 0x20; i++) + set_reg1(P3c4, i, 0); // 2.Reset Extended register + for (i = 0x21; i <= 0x27; i++) + set_reg1(P3c4, i, 0); // Reset Extended register + for (i = 0x31; i <= 0x3D; i++) + set_reg1(P3c4, i, 0); + for (i = 0x30; i <= 0x37; i++) + set_reg1(P3d4, i, 0); + +#if 0 + if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan)) + // 3.Set Define Extended register + temp = (unsigned char) SR1A; + else { + temp = *((unsigned char *) (ROMAddr + SoftSettingAddr)); + if ((temp & SoftDRAMType) == 0) { + // 3.Set Define Extended register + temp = (unsigned char) get_reg1(P3c4, 0x3A); + } + } +#endif + + // 3.Set Define Extended register + temp = (unsigned char) SR1A; + + RAMType = temp & 0x07; + SetMemoryClock(); + for (k = 0; k < 5; k++) + for (j = 0; j < 0xffff; j++) + ulTemp = (unsigned long) get_reg1(P3c4, 0x05); + + Temp = (unsigned long) get_reg1(P3c4, 0x3C); + Temp = Temp | 0x01; + set_reg1(P3c4, 0x3C, (unsigned short) Temp); + for (k = 0; k < 5; k++) + for (j = 0; j < 0xffff; j++) + Temp = (unsigned long) get_reg1(P3c4, 0x05); + + Temp = (unsigned long) get_reg1(P3c4, 0x3C); + Temp = Temp & 0xFE; + set_reg1(P3c4, 0x3C, (unsigned short) Temp); + for (k = 0; k < 5; k++) + for (j = 0; j < 0xffff; j++) + Temp = (unsigned long) get_reg1(P3c4, 0x05); + + //SR07=*((unsigned char *)(ROMAddr+0xA4)); // todo + set_reg1(P3c4, 0x07, SRegsInit[0x07]); +#if 0 + if (HwDeviceExtension->jChipID == SIS_Glamour) + for (i = 0x15; i <= 0x1C; i++) { + temp = *((unsigned char *) (ROMAddr + 0xA5 + ((i - 0x15) * 8) + RAMType)); + set_reg1(P3c4, i, temp); + } +#endif + + //SR1F=*((unsigned char *)(ROMAddr+0xE5)); + set_reg1(P3c4, 0x1F, SRegsInit[0x1F]); + + // Get AGP + AGP = 1; + temp = (unsigned char) get_reg1(P3c4, 0x3A); + temp = temp & 0x30; + if (temp == 0x30) + // PCI + AGP = 0; + + //SR21=*((unsigned char *)(ROMAddr+0xE6)); + SR21 = SRegsInit[0x21]; + if (AGP == 0) + SR21 = SR21 & 0xEF; // PCI + set_reg1(P3c4, 0x21, SR21); + + //SR22=*((unsigned char *)(ROMAddr+0xE7)); + SR22 = SRegsInit[0x22]; + if (AGP == 1) + SR22 = SR22 & 0x20; // AGP + set_reg1(P3c4, 0x22, SR22); + + //SR23=*((unsigned char *)(ROMAddr+0xE8)); + set_reg1(P3c4, 0x23, SRegsInit[0x23]); + + //SR24=*((unsigned char *)(ROMAddr+0xE9)); + set_reg1(P3c4, 0x24, SRegsInit[0x24]); + + //SR25=*((unsigned char *)(ROMAddr+0xEA)); + set_reg1(P3c4, 0x25, SRegsInit[0x25]); + + //SR32=*((unsigned char *)(ROMAddr+0xEB)); + set_reg1(P3c4, 0x32, SRegsInit[0x32]); + + SR11 = 0x0F; + set_reg1(P3c4, 0x11, SR11); + +#if 0 + if (IF_DEF_LVDS == 1) { + //LVDS + temp = ExtChipLVDS; + } else if (IF_DEF_TRUMPION == 1) { + //Trumpion + temp = ExtChipTrumpion; + } else { + //301 + temp = ExtChip301; + } +#endif + + // 301; + temp = 0x02; + set_reg1(P3d4, 0x37, temp); + +#if 0 + //09/07/99 modify by domao for 630/540 MM + if (HwDeviceExtension->jChipID == SIS_Glamour) { + //For SiS 300 Chip + SetDRAMSize(HwDeviceExtension); + SetDRAMSize(HwDeviceExtension); + } else { + //For SiS 630/540 Chip + //Restore SR14, SR19 and SR1A + set_reg1(P3c4, 0x14, SR14); + set_reg1(P3c4, 0x19, SR19); + set_reg1(P3c4, 0x1A, SR1A); + } +#endif + + set_reg1(P3c4, 0x14, SR14); + set_reg1(P3c4, 0x19, SR19); + set_reg1(P3c4, 0x1A, SR1A); + set_reg3(P3c6, 0xff); + ClearDAC(P3c8); + DetectMonitor(); + +#if 0 + //sense CRT2 + GetSenseStatus(HwDeviceExtension, BaseAddr, ROMAddr); +#endif + + return (TRUE); +} + static int SiSSetMode(u16 ModeNo) { + //#ifndef CONFIG_FB_SIS_LINUXBIOS unsigned long temp; + //#endif + u16 cr30flag, cr31flag; unsigned long ROMAddr = rom_vbase; u16 BaseAddr = (u16) ivideo.vga_base; + u_short i; P3c4 = BaseAddr + 0x14; P3d4 = BaseAddr + 0x24; @@ -2335,6 +2818,7 @@ static int SiSSetMode(u16 ModeNo) P3c9 = BaseAddr + 0x19; P3da = BaseAddr + 0x2A; +#ifndef CONFIG_FB_SIS_LINUXBIOS temp = search_modeID(ROMAddr, ModeNo); if (temp == 0) @@ -2343,39 +2827,186 @@ static int SiSSetMode(u16 ModeNo) temp = check_memory_size(ROMAddr); if (temp == 0) return (0); +#endif +#if 1 cr30flag = (unsigned char) get_reg1(P3d4, 0x30); if (((cr30flag & 0x01) == 1) || ((cr30flag & 0x02) == 0)) { +#ifndef CONFIG_FB_SIS_LINUXBIOS get_mode_ptr(ROMAddr, ModeNo); +#endif set_seq_regs(ROMAddr); set_misc_regs(ROMAddr); set_crtc_regs(ROMAddr); set_attregs(ROMAddr); set_grc_regs(ROMAddr); ClearExt1Regs(); + +#ifndef CONFIG_FB_SIS_LINUXBIOS temp = get_rate_ptr(ROMAddr, ModeNo); if (temp) { +#endif set_sync(ROMAddr); set_crt1_crtc(ROMAddr); set_crt1_offset(ROMAddr); set_crt1_vclk(ROMAddr); set_vclk_state(ROMAddr, ModeNo); - if ((ivideo.chip_id == SIS_Trojan) - || (ivideo.chip_id == SIS_Spartan)) + + if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan)) set_crt1_FIFO2(ROMAddr); else /* SiS 300 */ set_crt1_FIFO(ROMAddr); +#ifndef CONFIG_FB_SIS_LINUXBIOS } +#endif set_crt1_mode_regs(ROMAddr, ModeNo); + if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan)) + set_interlace(ROMAddr, ModeNo); + load_DAC(ROMAddr); + + /* clear OnScreen */ + memset((char *) ivideo.video_vbase, 0, + video_linelength * ivideo.video_height); + } +#else + cr30flag = (unsigned char) get_reg1(P3d4, 0x30); + if (((cr30flag & 0x01) == 1) || ((cr30flag & 0x02) == 0)) { + //set_seq_regs(ROMAddr); + { + unsigned char SRdata; + SRdata = SRegs[0x01] | 0x20; + set_reg1(P3c4, 0x01, SRdata); + + for (i = 02; i <= 04; i++) + set_reg1(P3c4, i, SRegs[i]); + } + + //set_misc_regs(ROMAddr); + { + set_reg3(P3c2, 0x23); + } + + //set_crtc_regs(ROMAddr); + { + unsigned char CRTCdata; + + CRTCdata = (unsigned char) get_reg1(P3d4, 0x11); + set_reg1(P3d4, 0x11, CRTCdata); + + for (i = 0; i <= 0x18; i++) + set_reg1(P3d4, i, CRegs[i]); + } + + //set_attregs(ROMAddr); + { + for (i = 0; i <= 0x13; i++) { + get_reg2(P3da); + set_reg3(P3c0, i); + set_reg3(P3c0, ARegs[i]); + } + get_reg2(P3da); + set_reg3(P3c0, 0x14); + set_reg3(P3c0, 0x00); + get_reg2(P3da); + set_reg3(P3c0, 0x20); + } + + //set_grc_regs(ROMAddr); + { + for (i = 0; i <= 0x08; i++) + set_reg1(P3ce, i, GRegs[i]); + } + + //ClearExt1Regs(); + { + for (i = 0x0A; i <= 0x0E; i++) + set_reg1(P3c4, i, 0x00); + } + + //set_sync(ROMAddr); + { + set_reg3(P3c2, MReg); + } + + //set_crt1_crtc(ROMAddr); + { + unsigned char data; + + data = (unsigned char) get_reg1(P3d4, 0x11); + data = data & 0x7F; + set_reg1(P3d4, 0x11, data); + + for (i = 0; i <= 0x07; i++) + set_reg1(P3d4, i, CRegs[i]); + for (i = 0x10; i <= 0x12; i++) + set_reg1(P3d4, i, CRegs[i]); + for (i = 0x15; i <= 0x16; i++) + set_reg1(P3d4, i, CRegs[i]); + for (i = 0x0A; i <= 0x0C; i++) + set_reg1(P3c4, i, SRegs[i]); + + data = SRegs[0x0E] & 0xE0; + set_reg1(P3c4, 0x0E, data); + + set_reg1(P3d4, 0x09, CRegs[0x09]); + + } + + //set_crt1_offset(ROMAddr); + { + set_reg1(P3c4, 0x0E, SRegs[0x0E]); + set_reg1(P3c4, 0x10, SRegs[0x10]); + } + + //set_crt1_vclk(ROMAddr); + { + set_reg1(P3c4, 0x31, 0); + + for (i = 0x2B; i <= 0x2C; i++) + set_reg1(P3c4, i, SRegs[i]); + set_reg1(P3c4, 0x2D, 0x80); + } + + //set_vclk_state(ROMAddr, ModeNo); + { + set_reg1(P3c4, 0x32, SRegs[0x32]); + set_reg1(P3c4, 0x07, SRegs[0x07]); + } + if ((ivideo.chip_id == SIS_Trojan) - || (ivideo.chip_id == - SIS_Spartan)) set_interlace(ROMAddr, ModeNo); + || (ivideo.chip_id == SIS_Spartan)) { + //set_crt1_FIFO2(ROMAddr); + set_reg1(P3c4, 0x15, SRegs[0x15]); + + set_reg4(0xcf8, 0x80000050); + set_reg4(0xcfc, 0xc5041e04); + + set_reg1(P3c4, 0x08, SRegs[0x08]); + set_reg1(P3c4, 0x0F, SRegs[0x0F]); + set_reg1(P3c4, 0x3b, 0x00); + set_reg1(P3c4, 0x09, SRegs[0x09]); + } + + //set_crt1_mode_regs(ROMAddr, ModeNo); + { + set_reg1(P3c4, 0x06, SRegs[0x06]); + set_reg1(P3c4, 0x01, SRegs[0x01]); + set_reg1(P3c4, 0x0F, SRegs[0x0F]); + set_reg1(P3c4, 0x21, SRegs[0x21]); + } + + if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan)) { + //set_interlace(ROMAddr, ModeNo); + set_reg1(P3d4, 0x19, CRegs[0x19]); + set_reg1(P3d4, 0x1A, CRegs[0x1A]); + } load_DAC(ROMAddr); /* clear OnScreen */ memset((char *) ivideo.video_vbase, 0, video_linelength * ivideo.video_height); } +#endif cr31flag = (unsigned char) get_reg1(P3d4, 0x31); display_on(); @@ -2508,8 +3139,7 @@ static int sisfb_get_var(struct fb_var_screeninfo *var, int con, DPRINTK("sisfb: sisfb_get_var:[%d]\n", con); if (con == -1) - memcpy(var, &default_var, - sizeof(struct fb_var_screeninfo)); + memcpy(var, &default_var, sizeof(struct fb_var_screeninfo)); else *var = fb_display[con].var; return 0; @@ -2570,8 +3200,8 @@ static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else - fb_copy_cmap(fb_default_cmap(video_cmap_len), - cmap, kspc ? 0 : 2); + fb_copy_cmap(fb_default_cmap(video_cmap_len), cmap, kspc ? 0 : 2); + return 0; } @@ -2602,12 +3232,12 @@ static int sisfb_ioctl(struct inode *inode, struct file *file, { switch (cmd) { case FBIO_ALLOC: - if(!capable(CAP_SYS_RAWIO)) + if (!capable(CAP_SYS_RAWIO)) return -EPERM; sis_malloc((struct sis_memreq *) arg); break; case FBIO_FREE: - if(!capable(CAP_SYS_RAWIO)) + if (!capable(CAP_SYS_RAWIO)) return -EPERM; sis_free(*(unsigned long *) arg); break; @@ -2668,9 +3298,9 @@ static int sisfb_mmap(struct fb_info *info, struct file *file, if (boot_cpu_data.x86 > 3) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; #endif - if (io_remap_page_range(vma->vm_start, off, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) return -EAGAIN; + if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start, + vma->vm_page_prot)) + return -EAGAIN; return 0; } @@ -2695,7 +3325,7 @@ int sisfb_setup(char *options) if (!options || !*options) return 0; - for (this_opt = strtok(options, ","); this_opt; + for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { if (!*this_opt) continue; @@ -2786,10 +3416,13 @@ static void sisfb_blank(int blank, struct fb_info *info) int __init sisfb_init(void) { - struct pci_dev *pdev; + struct pci_dev *pdev = NULL; struct board *b; int pdev_valid = 0; unsigned char jTemp; + u32 cmd; + + outb(0x77, 0x80); if (sisfb_off) return -ENXIO; @@ -2814,12 +3447,45 @@ int __init sisfb_init(void) if (!pdev_valid) return -1; - ivideo.video_base = pdev->resource[0].start & ~0x7FFFFF; - ivideo.mmio_base = pdev->resource[1].start & ~0x3FFF; - ivideo.vga_base = (pdev->resource[2].start & 0xFFFFFC) + 0x30; - rom_base = 0x000C0000; +#ifdef CONFIG_FB_SIS_LINUXBIOS + pci_read_config_dword(pdev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_IO; + cmd |= PCI_COMMAND_MEMORY; + pci_write_config_dword(pdev, PCI_COMMAND, cmd); +#endif + ivideo.video_base = pci_resource_start(pdev, 0); + if (!request_mem_region(ivideo.video_base, pci_resource_len(pdev, 0), + "sisfb FB")) { + printk(KERN_ERR "sisfb: cannot reserve frame buffer memory\n"); + return -ENODEV; + } + ivideo.mmio_base = pci_resource_start(pdev, 1); + if (!request_mem_region(ivideo.mmio_base, pci_resource_len(pdev, 1), + "sisfb MMIO")) { + printk(KERN_ERR "sisfb: cannot reserve MMIO region\n"); + release_mem_region(pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1)); + return -ENODEV; + } + ivideo.vga_base = pci_resource_start(pdev, 2); + if (!request_region(ivideo.vga_base, pci_resource_len(pdev, 2), + "sisfb IO")) { + printk(KERN_ERR "sisfb: cannot reserve I/O ports\n"); + release_mem_region(pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1)); + release_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + return -ENODEV; + } + ivideo.vga_base += 0x30; + +#ifndef CONFIG_FB_SIS_LINUXBIOS + rom_base = 0x000C0000; request_region(rom_base, 32, "sisfb"); +#else + rom_base = 0x0; +#endif /* set passwd */ vgawb(SEQ_ADR, IND_SIS_PASSWORD); @@ -2839,13 +3505,21 @@ int __init sisfb_init(void) if (mode_idx < 0) mode_idx = DEFAULT_MODE; /* 0:640x480x8 */ +#ifdef CONFIG_FB_SIS_LINUXBIOS + mode_idx = DEFAULT_MODE; + rate_idx = sisbios_mode[mode_idx].rate_idx; + /* set to default refresh rate 60MHz */ + ivideo.refresh_rate = 60; +#endif + mode_no = sisbios_mode[mode_idx].mode_no; if (ivideo.refresh_rate != 0) search_refresh_rate(ivideo.refresh_rate); if (rate_idx == 0) { - rate_idx = sisbios_mode[mode_idx].rate_idx; /* set to default refresh rate 60MHz */ + rate_idx = sisbios_mode[mode_idx].rate_idx; + /* set to default refresh rate 60MHz */ ivideo.refresh_rate = 60; } @@ -2854,25 +3528,14 @@ int __init sisfb_init(void) ivideo.video_height = sisbios_mode[mode_idx].yres; video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3); - if (!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB")) - { - printk(KERN_ERR - "sisfb: abort, cannot reserve video memory at 0x%lx\n", - ivideo.video_base); - return -1; - } - - if (!request_mem_region(ivideo.mmio_base, MMIO_SIZE, "sisfb MMIO")) - { - printk(KERN_ERR - "sisfb: abort, cannot reserve mmio memory at 0x%lx\n", - ivideo.mmio_base); - return -1; - } - ivideo.video_vbase = ioremap(ivideo.video_base, ivideo.video_size); ivideo.mmio_vbase = ioremap(ivideo.mmio_base, MMIO_SIZE); + +#ifndef CONFIG_FB_SIS_LINUXBIOS rom_vbase = (unsigned long) ioremap(rom_base, MAX_ROM_SCAN); +#endif + + SiSInit300(); printk(KERN_INFO "sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", diff --git a/fs/Makefile b/fs/Makefile index 4e67ec80867e..6abc44d603ad 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -11,9 +11,10 @@ FILESYSTEMS = $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o)) O_TARGET := fs.o O_OBJS = open.o read_write.o devices.o file_table.o buffer.o \ super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \ - ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \ + ioctl.o readdir.o select.o fifo.o locks.o \ dcache.o inode.o attr.o bad_inode.o file.o iobuf.o \ $(BINFMTS) $(FILESYSTEMS) +OX_OBJS := filesystems.o ALL_SUB_DIRS := coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \ hpfs sysv smbfs ncpfs ufs efs affs romfs autofs hfs lockd \ diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c index 7b6573dd745f..7c7c8baf2502 100644 --- a/fs/autofs/waitq.c +++ b/fs/autofs/waitq.c @@ -53,7 +53,7 @@ static int autofs_write(struct file *file, const void *addr, int bytes) /** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/ - sigpipe = sigismember(¤t->signal, SIGPIPE); + sigpipe = sigismember(¤t->pending.signal, SIGPIPE); /* Save pointer to user space and point back to kernel space */ fs = get_fs(); @@ -71,7 +71,7 @@ static int autofs_write(struct file *file, const void *addr, int bytes) SIGPIPE unless it was already supposed to get one */ if (wr == -EPIPE && !sigpipe) { spin_lock_irqsave(¤t->sigmask_lock, flags); - sigdelset(¤t->signal, SIGPIPE); + sigdelset(¤t->pending.signal, SIGPIPE); recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); } diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index f49f213e0c10..a76cde227584 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -57,7 +57,7 @@ static int autofs4_write(struct file *file, const void *addr, int bytes) /** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/ - sigpipe = sigismember(¤t->signal, SIGPIPE); + sigpipe = sigismember(¤t->pending.signal, SIGPIPE); /* Save pointer to user space and point back to kernel space */ fs = get_fs(); @@ -75,7 +75,7 @@ static int autofs4_write(struct file *file, const void *addr, int bytes) SIGPIPE unless it was already supposed to get one */ if (wr == -EPIPE && !sigpipe) { spin_lock_irqsave(¤t->sigmask_lock, flags); - sigdelset(¤t->signal, SIGPIPE); + sigdelset(¤t->pending.signal, SIGPIPE); recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 4225311580b9..445c47aa6ad6 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1045,7 +1045,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) notes[0].datasz = sizeof(prstatus); notes[0].data = &prstatus; prstatus.pr_info.si_signo = prstatus.pr_cursig = signr; - prstatus.pr_sigpend = current->signal.sig[0]; + prstatus.pr_sigpend = current->pending.signal.sig[0]; prstatus.pr_sighold = current->blocked.sig[0]; psinfo.pr_pid = prstatus.pr_pid = current->pid; psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid; diff --git a/fs/buffer.c b/fs/buffer.c index ca6e2f919882..05f52aa2db84 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2606,8 +2606,8 @@ int kupdate(void *sem) if (signal_pending(tsk)) { int stopped = 0; spin_lock_irq(&tsk->sigmask_lock); - if (sigismember(&tsk->signal, SIGSTOP)) { - sigdelset(&tsk->signal, SIGSTOP); + if (sigismember(&tsk->pending.signal, SIGSTOP)) { + sigdelset(&tsk->pending.signal, SIGSTOP); stopped = 1; } recalc_sigpending(tsk); @@ -2625,9 +2625,9 @@ int kupdate(void *sem) static int __init bdflush_init(void) { DECLARE_MUTEX_LOCKED(sem); - kernel_thread(bdflush, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + kernel_thread(bdflush, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); down(&sem); - kernel_thread(kupdate, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + kernel_thread(kupdate, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); down(&sem); return 0; } diff --git a/fs/exec.c b/fs/exec.c index f0c64b43a708..1cab95172aad 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -427,7 +427,7 @@ static int exec_mmap(void) * This function makes sure the current process has its own signal table, * so that flush_signal_handlers can later reset the handlers without * disturbing other processes. (Other processes might share the signal - * table via the CLONE_SIGHAND option to clone().) + * table via the CLONE_SIGNAL option to clone().) */ static inline int make_private_signals(void) diff --git a/fs/ext2/Makefile b/fs/ext2/Makefile index 456f9ba75779..7321f45c8f68 100644 --- a/fs/ext2/Makefile +++ b/fs/ext2/Makefile @@ -9,7 +9,7 @@ O_TARGET := ext2.o O_OBJS := acl.o balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ - ioctl.o namei.o super.o symlink.o truncate.o + ioctl.o namei.o super.o symlink.o M_OBJS := $(O_TARGET) include $(TOPDIR)/Rules.make diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index c99f7f2c8937..6f5ecebe8b02 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -398,9 +398,13 @@ repeat: ext2_error (sb, "ext2_new_inode", "Free inodes count corrupted in group %d", i); - unlock_super (sb); - iput (inode); - return NULL; + if (sb->s_flags & MS_RDONLY) { + unlock_super (sb); + iput (inode); + return NULL; + } + gdp->bg_free_inodes_count = 0; + mark_buffer_dirty(bh2, 1); } goto repeat; } @@ -411,6 +415,7 @@ repeat: "block_group = %d,inode=%d", i, j); unlock_super (sb); iput (inode); + *err = -EIO; return NULL; } gdp->bg_free_inodes_count = diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 4f0b78da37e7..9c2abac552a2 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -704,6 +704,285 @@ struct address_space_operations ext2_aops = { bmap: ext2_bmap }; +/* + * Probably it should be a library function... search for first non-zero word + * or memcmp with zero_page, whatever is better for particular architecture. + * Linus? + */ +static inline int all_zeroes(u32 *p, u32 *q) +{ + while (p < q) + if (*p++) + return 1; + return 0; +} + +/** + * ext2_find_shared - find the indirect blocks for partial truncation. + * @inode: inode in question + * @depth: depth of the affected branch + * @offsets: offsets of pointers in that branch (see ext2_block_to_path) + * @chain: place to store the pointers to partial indirect blocks + * @top: place to the (detached) top of branch + * + * This is a helper function used by ext2_truncate(). + * + * When we do truncate() we may have to clean the ends of several indirect + * blocks but leave the blocks themselves alive. Block is partially + * truncated if some data below the new i_size is refered from it (and + * it is on the path to the first completely truncated data block, indeed). + * We have to free the top of that path along with everything to the right + * of the path. Since no allocation past the truncation point is possible + * until ext2_truncate() finishes, we may safely do the latter, but top + * of branch may require special attention - pageout below the truncation + * point might try to populate it. + * + * We atomically detach the top of branch from the tree, store the block + * number of its root in *@top, pointers to buffer_heads of partially + * truncated blocks - in @chain[].bh and pointers to their last elements + * that should not be removed - in @chain[].p. Return value is the pointer + * to last filled element of @chain. + * + * The work left to caller to do the actual freeing of subtrees: + * a) free the subtree starting from *@top + * b) free the subtrees whose roots are stored in + * (@chain[i].p+1 .. end of @chain[i].bh->b_data) + * c) free the subtrees growing from the inode past the @chain[0].p + * (no partially truncated stuff there). + */ + +static Indirect *ext2_find_shared(struct inode *inode, + int depth, + int offsets[4], + Indirect chain[4], + u32 *top) +{ + Indirect *partial, *p; + int k, err; + + *top = 0; + for (k = depth; k > 1 && !offsets[k-1]; k--) + ; + partial = ext2_get_branch(inode, k, offsets, chain, &err); + /* Writer: pointers */ + if (!partial) + partial = chain + k-1; + /* + * If the branch acquired continuation since we've looked at it - + * fine, it should all survive and (new) top doesn't belong to us. + */ + if (!partial->key && *partial->p) + /* Writer: end */ + goto no_top; + for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--) + ; + /* + * OK, we've found the last block that must survive. The rest of our + * branch should be detached before unlocking. However, if that rest + * of branch is all ours and does not grow immediately from the inode + * it's easier to cheat and just decrement partial->p. + */ + if (p == chain + k - 1 && p > chain) { + p->p--; + } else { + *top = *p->p; + *p->p = 0; + } + /* Writer: end */ + + while(partial > p) + { + brelse(partial->bh); + partial--; + } +no_top: + return partial; +} + +/** + * ext2_free_data - free a list of data blocks + * @inode: inode we are dealing with + * @p: array of block numbers + * @q: points immediately past the end of array + * + * We are freeing all blocks refered from that array (numbers are + * stored as little-endian 32-bit) and updating @inode->i_blocks + * appropriately. + */ +static inline void ext2_free_data(struct inode *inode, u32 *p, u32 *q) +{ + int blocks = inode->i_sb->s_blocksize / 512; + unsigned long block_to_free = 0, count = 0; + unsigned long nr; + + for ( ; p < q ; p++) { + nr = le32_to_cpu(*p); + if (nr) { + *p = 0; + /* accumulate blocks to free if they're contiguous */ + if (count == 0) + goto free_this; + else if (block_to_free == nr - count) + count++; + else { + /* Writer: ->i_blocks */ + inode->i_blocks -= blocks * count; + /* Writer: end */ + ext2_free_blocks (inode, block_to_free, count); + mark_inode_dirty(inode); + free_this: + block_to_free = nr; + count = 1; + } + } + } + if (count > 0) { + /* Writer: ->i_blocks */ + inode->i_blocks -= blocks * count; + /* Writer: end */ + ext2_free_blocks (inode, block_to_free, count); + mark_inode_dirty(inode); + } +} + +/** + * ext2_free_branches - free an array of branches + * @inode: inode we are dealing with + * @p: array of block numbers + * @q: pointer immediately past the end of array + * @depth: depth of the branches to free + * + * We are freeing all blocks refered from these branches (numbers are + * stored as little-endian 32-bit) and updating @inode->i_blocks + * appropriately. + */ +static void ext2_free_branches(struct inode *inode, u32 *p, u32 *q, int depth) +{ + struct buffer_head * bh; + unsigned long nr; + + if (depth--) { + int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); + for ( ; p < q ; p++) { + nr = le32_to_cpu(*p); + if (!nr) + continue; + *p = 0; + bh = bread (inode->i_dev, nr, inode->i_sb->s_blocksize); + /* + * A read failure? Report error and clear slot + * (should be rare). + */ + if (!bh) { + ext2_error(inode->i_sb, "ext2_free_branches", + "Read failure, inode=%ld, block=%ld", + inode->i_ino, nr); + continue; + } + ext2_free_branches(inode, + (u32*)bh->b_data, + (u32*)bh->b_data + addr_per_block, + depth); + bforget(bh); + /* Writer: ->i_blocks */ + inode->i_blocks -= inode->i_sb->s_blocksize / 512; + /* Writer: end */ + ext2_free_blocks(inode, nr, 1); + mark_inode_dirty(inode); + } + } else + ext2_free_data(inode, p, q); +} + +void ext2_truncate (struct inode * inode) +{ + u32 *i_data = inode->u.ext2_i.i_data; + int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); + int offsets[4]; + Indirect chain[4]; + Indirect *partial; + int nr = 0; + int n; + long iblock; + + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) + return; + if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + return; + + ext2_discard_prealloc(inode); + + iblock = (inode->i_size + inode->i_sb->s_blocksize-1) + >> EXT2_BLOCK_SIZE_BITS(inode->i_sb); + + n = ext2_block_to_path(inode, iblock, offsets); + if (n == 0) + return; + + if (n == 1) { + ext2_free_data(inode, i_data+offsets[0], + i_data + EXT2_NDIR_BLOCKS); + goto do_indirects; + } + + partial = ext2_find_shared(inode, n, offsets, chain, &nr); + /* Kill the top of shared branch (already detached) */ + if (nr) { + if (partial == chain) + mark_inode_dirty(inode); + else + mark_buffer_dirty(partial->bh, 1); + ext2_free_branches(inode, &nr, &nr+1, (chain+n-1) - partial); + } + /* Clear the ends of indirect blocks on the shared branch */ + while (partial > chain) { + ext2_free_branches(inode, + partial->p + 1, + (u32*)partial->bh->b_data + addr_per_block, + (chain+n-1) - partial); + mark_buffer_dirty(partial->bh, 1); + if (IS_SYNC(inode)) { + ll_rw_block (WRITE, 1, &partial->bh); + wait_on_buffer (partial->bh); + } + brelse (partial->bh); + partial--; + } +do_indirects: + /* Kill the remaining (whole) subtrees */ + switch (offsets[0]) { + default: + nr = i_data[EXT2_IND_BLOCK]; + if (nr) { + i_data[EXT2_IND_BLOCK] = 0; + mark_inode_dirty(inode); + ext2_free_branches(inode, &nr, &nr+1, 1); + } + case EXT2_IND_BLOCK: + nr = i_data[EXT2_DIND_BLOCK]; + if (nr) { + i_data[EXT2_DIND_BLOCK] = 0; + mark_inode_dirty(inode); + ext2_free_branches(inode, &nr, &nr+1, 2); + } + case EXT2_DIND_BLOCK: + nr = i_data[EXT2_TIND_BLOCK]; + if (nr) { + i_data[EXT2_TIND_BLOCK] = 0; + mark_inode_dirty(inode); + ext2_free_branches(inode, &nr, &nr+1, 3); + } + case EXT2_TIND_BLOCK: + ; + } + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + if (IS_SYNC(inode)) + ext2_sync_inode (inode); + else + mark_inode_dirty(inode); +} + void ext2_read_inode (struct inode * inode) { struct buffer_head * bh; @@ -781,30 +1060,22 @@ void ext2_read_inode (struct inode * inode) inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */ inode->i_blocks = le32_to_cpu(raw_inode->i_blocks); inode->i_version = ++event; - inode->u.ext2_i.i_new_inode = 0; inode->u.ext2_i.i_flags = le32_to_cpu(raw_inode->i_flags); inode->u.ext2_i.i_faddr = le32_to_cpu(raw_inode->i_faddr); inode->u.ext2_i.i_frag_no = raw_inode->i_frag; inode->u.ext2_i.i_frag_size = raw_inode->i_fsize; - inode->u.ext2_i.i_osync = 0; inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl); if (S_ISDIR(inode->i_mode)) inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); else { - inode->u.ext2_i.i_dir_acl = 0; inode->u.ext2_i.i_high_size = le32_to_cpu(raw_inode->i_size_high); inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32; } inode->i_generation = le32_to_cpu(raw_inode->i_generation); inode->u.ext2_i.i_block_group = block_group; - inode->u.ext2_i.i_next_alloc_block = 0; - inode->u.ext2_i.i_next_alloc_goal = 0; - if (inode->u.ext2_i.i_prealloc_count) - ext2_error (inode->i_sb, "ext2_read_inode", - "New inode has non-zero prealloc count!"); /* - * NOTE! The in-memory inode i_blocks array is in little-endian order + * NOTE! The in-memory inode i_data array is in little-endian order * even on big-endian machines: we do NOT byteswap the block numbers! */ for (block = 0; block < EXT2_N_BLOCKS; block++) @@ -940,9 +1211,23 @@ static int ext2_update_inode(struct inode * inode, int do_sync) raw_inode->i_file_acl = cpu_to_le32(inode->u.ext2_i.i_file_acl); if (S_ISDIR(inode->i_mode)) raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl); - else + else { raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32); - + if (raw_inode->i_size_high) { + struct super_block *sb = inode->i_sb; + struct ext2_super_block *es = sb->u.ext2_sb.s_es; + if (!(es->s_feature_ro_compat & cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) { + /* If this is the first large file + * created, add a flag to the superblock. + */ + lock_kernel(); + es->s_feature_ro_compat |= cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE); + unlock_kernel(); + ext2_write_super(sb); + } + } + } + raw_inode->i_generation = cpu_to_le32(inode->i_generation); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); @@ -966,7 +1251,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync) void ext2_write_inode (struct inode * inode, int wait) { lock_kernel(); - ext2_update_inode (inode, 0); + ext2_update_inode (inode, wait); unlock_kernel(); } diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 46e2739353e9..44423a62009e 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -366,12 +366,9 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode) struct inode * inode; int err; - /* - * N.B. Several error exits in ext2_new_inode don't set err. - */ inode = ext2_new_inode (dir, mode, &err); if (!inode) - return -EIO; + return err; inode->i_op = &ext2_file_inode_operations; inode->i_fop = &ext2_file_operations; @@ -397,7 +394,7 @@ static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int inode = ext2_new_inode (dir, mode, &err); if (!inode) - return -EIO; + return err; inode->i_uid = current->fsuid; init_special_inode(inode, mode, rdev); @@ -428,7 +425,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) inode = ext2_new_inode (dir, S_IFDIR, &err); if (!inode) - return -EIO; + return err; inode->i_op = &ext2_dir_inode_operations; inode->i_fop = &ext2_dir_operations; @@ -634,7 +631,7 @@ static int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * return -ENAMETOOLONG; if (!(inode = ext2_new_inode (dir, S_IFLNK, &err))) - return -EIO; + return err; inode->i_mode = S_IFLNK | S_IRWXUGO; diff --git a/fs/ext2/truncate.c b/fs/ext2/truncate.c deleted file mode 100644 index ba839719669e..000000000000 --- a/fs/ext2/truncate.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * linux/fs/ext2/truncate.c - * - * Copyright (C) 1992, 1993, 1994, 1995 - * Remy Card (card@masi.ibp.fr) - * Laboratoire MASI - Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * from - * - * linux/fs/minix/truncate.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * Big-endian to little-endian byte-swapping/bitmaps by - * David S. Miller (davem@caip.rutgers.edu), 1995 - * - * General cleanup and race fixes, wsh, 1998 - */ - -#include -#include - - -/* - * Real random numbers for secure rm added 94/02/18 - * Idea from Pierre del Perugia - */ - -#if 0 - -/* - * Secure deletion currently doesn't work. It interacts very badly - * with buffers shared with memory mappings, and for that reason - * can't be done in the truncate() routines. It should instead be - * done separately in "release()" before calling the truncate routines - * that will release the actual file blocks. - * - * Linus - */ -static int ext2_secrm_seed = 152; /* Random generator base */ - -#define RANDOM_INT (ext2_secrm_seed = ext2_secrm_seed * 69069l +1) -#endif - -/* - * Macros to return the block number for the inode size and offset. - * Currently we always hold the inode semaphore during truncate, so - * there's no need to test for changes during the operation. - */ -#define DIRECT_BLOCK(inode) \ - ((unsigned long) ((inode->i_size + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits)) -#define INDIRECT_BLOCK(inode,offset) ((int)DIRECT_BLOCK(inode) - offset) -#define DINDIRECT_BLOCK(inode,offset) \ - (INDIRECT_BLOCK(inode,offset) / addr_per_block) -#define TINDIRECT_BLOCK(inode,offset) \ - (INDIRECT_BLOCK(inode,offset) / (addr_per_block*addr_per_block)) - -/* - * Truncate has the most races in the whole filesystem: coding it is - * a pain in the a**. Especially as I don't do any locking... - * - * The code may look a bit weird, but that's just because I've tried to - * handle things like file-size changes in a somewhat graceful manner. - * Anyway, truncating a file at the same time somebody else writes to it - * is likely to result in pretty weird behaviour... - * - * The new code handles normal truncates (size = 0) as well as the more - * general case (size = XXX). I hope. - * - * - * Truncate operations have been rewritten to avoid various races. The - * previous code was allowing blocking operations to precede a call to - * bforget(), possible allowing the buffer to be used again. - * - * We now ensure that b_count == 1 before calling bforget() and that the - * parent buffer (if any) is unlocked before clearing the block pointer. - * The operations are always performed in this order: - * (1) Make sure that the parent buffer is unlocked. - * (2) Use find_buffer() to find the block buffer without blocking, - * and set 'retry' if the buffer is locked or b_count > 1. - * (3) Clear the block pointer in the parent (buffer or inode). - * (4) Update the inode block count and mark the inode dirty. - * (5) Forget the block buffer, if any. This call won't block, as - * we know the buffer is unlocked from (2). - * (6) If the block pointer is in a (parent) buffer, mark the buffer - * dirty. (Note that this can block on a loop device.) - * (7) Accumulate the blocks to free and/or update the block bitmap. - * (This operation will frequently block.) - * - * The requirement that parent buffers be unlocked follows from the general - * principle of not modifying a buffer that may be undergoing I/O. With the - * the present kernels there's no problem with modifying a locked inode, as - * the I_DIRTY bit is cleared before setting I_LOCK. - * -- WSH, 1998 - */ - -/* - * Check whether any of the slots in an indirect block are - * still in use, and if not free the block. - */ -static int check_block_empty(struct inode *inode, struct buffer_head *bh, - u32 *p, struct buffer_head *ind_bh) -{ - int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); - u32 * ind = (u32 *) bh->b_data; - int i, retry; - - /* Make sure both buffers are unlocked */ - do { - retry = 0; - if (buffer_locked(bh)) { - __wait_on_buffer(bh); - retry = 1; - } - if (ind_bh && buffer_locked(ind_bh)) { - __wait_on_buffer(ind_bh); - retry = 1; - } - } while (retry); - - for (i = 0; i < addr_per_block; i++) - if (*(ind++)) - goto in_use; - - if (atomic_read(&bh->b_count) == 1) { - int tmp; - tmp = le32_to_cpu(*p); - *p = 0; - inode->i_blocks -= (inode->i_sb->s_blocksize / 512); - mark_inode_dirty(inode); - /* - * Forget the buffer, then mark the parent buffer dirty. - */ - bforget(bh); - if (ind_bh) - mark_buffer_dirty(ind_bh, 1); - ext2_free_blocks(inode, tmp, 1); - goto out; - } - retry = 1; - -in_use: - if (IS_SYNC(inode) && buffer_dirty(bh)) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } - brelse (bh); - -out: - return retry; -} - -#define DATA_BUFFER_USED(bh) \ - (atomic_read(&bh->b_count) || buffer_locked(bh)) - -static int trunc_direct (struct inode * inode) -{ - int i, retry = 0; - unsigned long block_to_free = 0, free_count = 0; - int blocks = inode->i_sb->s_blocksize / 512; - int direct_block = DIRECT_BLOCK(inode); - - for (i = direct_block ; i < EXT2_NDIR_BLOCKS ; i++) { - u32 * p = inode->u.ext2_i.i_data + i; - int tmp = le32_to_cpu(*p); - - if (!tmp) - continue; - - *p = 0; - inode->i_blocks -= blocks; - mark_inode_dirty(inode); - - /* accumulate blocks to free if they're contiguous */ - if (free_count == 0) - goto free_this; - else if (block_to_free == tmp - free_count) - free_count++; - else { - ext2_free_blocks (inode, block_to_free, free_count); - free_this: - block_to_free = tmp; - free_count = 1; - } - } - if (free_count > 0) - ext2_free_blocks (inode, block_to_free, free_count); - return retry; -} - -static int trunc_indirect (struct inode * inode, int offset, u32 * p, struct buffer_head *dind_bh) -{ - struct buffer_head * ind_bh; - int i, tmp, retry = 0; - unsigned long block_to_free = 0, free_count = 0; - int indirect_block, addr_per_block, blocks; - - tmp = le32_to_cpu(*p); - if (!tmp) - return 0; - ind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize); - if (tmp != le32_to_cpu(*p)) { - brelse (ind_bh); - return 1; - } - /* A read failure? Report error and clear slot (should be rare). */ - if (!ind_bh) { - ext2_error(inode->i_sb, "trunc_indirect", - "Read failure, inode=%ld, block=%d", - inode->i_ino, tmp); - *p = 0; - if (dind_bh) - mark_buffer_dirty(dind_bh, 1); - else - mark_inode_dirty(inode); - return 0; - } - - blocks = inode->i_sb->s_blocksize / 512; - addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); - indirect_block = INDIRECT_BLOCK(inode, offset); - if (indirect_block < 0) - indirect_block = 0; - for (i = indirect_block ; i < addr_per_block ; i++) { - u32 * ind = i + (u32 *) ind_bh->b_data; - - wait_on_buffer(ind_bh); - tmp = le32_to_cpu(*ind); - if (!tmp) - continue; - - *ind = 0; - inode->i_blocks -= blocks; - mark_inode_dirty(inode); - mark_buffer_dirty(ind_bh, 1); - - /* accumulate blocks to free if they're contiguous */ - if (free_count == 0) - goto free_this; - else if (block_to_free == tmp - free_count) - free_count++; - else { - ext2_free_blocks (inode, block_to_free, free_count); - free_this: - block_to_free = tmp; - free_count = 1; - } - } - if (free_count > 0) - ext2_free_blocks (inode, block_to_free, free_count); - /* - * Check the block and dispose of the ind_bh buffer. - */ - retry |= check_block_empty(inode, ind_bh, p, dind_bh); - - return retry; -} - -static int trunc_dindirect (struct inode * inode, int offset, u32 * p, - struct buffer_head * tind_bh) -{ - struct buffer_head * dind_bh; - int i, tmp, retry = 0; - int dindirect_block, addr_per_block; - - tmp = le32_to_cpu(*p); - if (!tmp) - return 0; - dind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize); - if (tmp != le32_to_cpu(*p)) { - brelse (dind_bh); - return 1; - } - /* A read failure? Report error and clear slot (should be rare). */ - if (!dind_bh) { - ext2_error(inode->i_sb, "trunc_dindirect", - "Read failure, inode=%ld, block=%d", - inode->i_ino, tmp); - *p = 0; - if (tind_bh) - mark_buffer_dirty(tind_bh, 1); - else - mark_inode_dirty(inode); - return 0; - } - - addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); - dindirect_block = DINDIRECT_BLOCK(inode, offset); - if (dindirect_block < 0) - dindirect_block = 0; - for (i = dindirect_block ; i < addr_per_block ; i++) { - u32 * dind = i + (u32 *) dind_bh->b_data; - - retry |= trunc_indirect(inode, - offset + (i * addr_per_block), - dind, dind_bh); - } - /* - * Check the block and dispose of the dind_bh buffer. - */ - retry |= check_block_empty(inode, dind_bh, p, tind_bh); - - return retry; -} - -static int trunc_tindirect (struct inode * inode) -{ - u32 * p = inode->u.ext2_i.i_data + EXT2_TIND_BLOCK; - struct buffer_head * tind_bh; - int i, tmp, retry = 0; - int tindirect_block, addr_per_block, offset; - - tmp = le32_to_cpu(*p); - if (!tmp) - return 0; - tind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize); - if (tmp != le32_to_cpu(*p)) { - brelse (tind_bh); - return 1; - } - /* A read failure? Report error and clear slot (should be rare). */ - if (!tind_bh) { - ext2_error(inode->i_sb, "trunc_tindirect", - "Read failure, inode=%ld, block=%d", - inode->i_ino, tmp); - *p = 0; - mark_inode_dirty(inode); - return 0; - } - - addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); - offset = EXT2_NDIR_BLOCKS + addr_per_block + - (addr_per_block * addr_per_block); - tindirect_block = TINDIRECT_BLOCK(inode, offset); - if (tindirect_block < 0) - tindirect_block = 0; - for (i = tindirect_block ; i < addr_per_block ; i++) { - u32 * tind = i + (u32 *) tind_bh->b_data; - - retry |= trunc_dindirect(inode, - offset + (i * addr_per_block * addr_per_block), - tind, tind_bh); - } - /* - * Check the block and dispose of the tind_bh buffer. - */ - retry |= check_block_empty(inode, tind_bh, p, NULL); - - return retry; -} - -void ext2_truncate (struct inode * inode) -{ - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - ext2_discard_prealloc(inode); - while (1) { - int retry = trunc_direct(inode); - retry |= trunc_indirect (inode, - EXT2_IND_BLOCK, - (u32 *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK], - NULL); - retry |= trunc_dindirect (inode, - EXT2_IND_BLOCK+EXT2_ADDR_PER_BLOCK(inode->i_sb), - (u32 *)&inode->u.ext2_i.i_data[EXT2_DIND_BLOCK], - NULL); - retry |= trunc_tindirect (inode); - if (!retry) - break; - if (IS_SYNC(inode) && (inode->i_state & I_DIRTY)) - ext2_sync_inode (inode); - run_task_queue(&tq_disk); - current->policy |= SCHED_YIELD; - schedule(); - } - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); -} diff --git a/fs/filesystems.c b/fs/filesystems.c index e57b7b3df0f5..30c18c2514c1 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c @@ -16,12 +16,10 @@ #include #include #include -#ifdef CONFIG_KMOD #include -#endif -#include -#include #include +#include +#include #ifdef CONFIG_CODA_FS extern int init_coda(void); @@ -48,32 +46,28 @@ void __init filesystem_setup(void) #endif } -#ifndef CONFIG_NFSD -#ifdef CONFIG_NFSD_MODULE -long (*do_nfsservctl)(int, void *, void *); -#endif +#if defined(CONFIG_NFSD_MODULE) +struct nfsd_linkage *nfsd_linkage = NULL; + long asmlinkage sys_nfsservctl(int cmd, void *argp, void *resp) { -#ifndef CONFIG_NFSD_MODULE - return -ENOSYS; -#else int ret = -ENOSYS; lock_kernel(); - if (do_nfsservctl) { - ret = do_nfsservctl(cmd, argp, resp); - goto out; - } -#ifdef CONFIG_KMOD - if (request_module ("nfsd") == 0) { - if (do_nfsservctl) - ret = do_nfsservctl(cmd, argp, resp); - } -#endif /* CONFIG_KMOD */ -out: + + if (nfsd_linkage || + (request_module ("nfsd") == 0 && nfsd_linkage)) + ret = nfsd_linkage->do_nfsservctl(cmd, argp, resp); + unlock_kernel(); return ret; -#endif /* CONFIG_NFSD_MODULE */ +} +EXPORT_SYMBOL(nfsd_linkage); + +#elif ! defined (CONFIG_NFSD) +asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp) +{ + return -ENOSYS; } #endif /* CONFIG_NFSD */ diff --git a/fs/locks.c b/fs/locks.c index ae4cc806914d..1aeb4d7ae27c 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1040,17 +1040,12 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) */ if (IS_MANDLOCK(inode) && (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) { - struct vm_area_struct *vma; struct address_space *mapping = inode->i_mapping; - spin_lock(&mapping->i_shared_lock); - for(vma = mapping->i_mmap;vma;vma = vma->vm_next_share) { - if (!(vma->vm_flags & VM_MAYSHARE)) - continue; - spin_unlock(&mapping->i_shared_lock); + + if (mapping->i_mmap_shared != NULL) { error = -EAGAIN; goto out_putf; } - spin_unlock(&mapping->i_shared_lock); } error = -EINVAL; @@ -1199,17 +1194,12 @@ int fcntl_setlk64(unsigned int fd, unsigned int cmd, struct flock64 *l) */ if (IS_MANDLOCK(inode) && (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) { - struct vm_area_struct *vma; struct address_space *mapping = inode->i_mapping; - spin_lock(&mapping->i_shared_lock); - for(vma = mapping->i_mmap;vma;vma = vma->vm_next_share) { - if (!(vma->vm_flags & VM_MAYSHARE)) - continue; - spin_unlock(&mapping->i_shared_lock); + + if (mapping->i_mmap_shared != NULL) { error = -EAGAIN; goto out_putf; } - spin_unlock(&mapping->i_shared_lock); } error = -EINVAL; diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index f1c9099bc479..4df91abe3a35 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -290,7 +290,8 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return -EACCES; } /* get only low 8 bits... */ - get_user_ret(newstate, (unsigned char*)arg, -EFAULT); + if (get_user(newstate, (unsigned char *) arg)) + return -EFAULT; if (server->sign_active) { /* cannot turn signatures OFF when active */ if (!newstate) return -EINVAL; diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 20e82fa7a8f8..5509212c7a37 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -312,7 +312,9 @@ done: EXPORT_NO_SYMBOLS; MODULE_AUTHOR("Olaf Kirch "); -extern long (*do_nfsservctl)(int, void *, void *); +struct nfsd_linkage nfsd_linkage_s = { + do_nfsservctl: handle_sys_nfsservctl, +}; /* * Initialize the module @@ -321,7 +323,7 @@ int init_module(void) { printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); - do_nfsservctl = handle_sys_nfsservctl; + nfsd_linkage = &nfsd_linkage_s; return 0; } @@ -331,7 +333,7 @@ init_module(void) void cleanup_module(void) { - do_nfsservctl = NULL; + nfsd_linkage = NULL; nfsd_export_shutdown(); nfsd_cache_shutdown(); remove_proc_entry("fs/nfs/exports", NULL); diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 11297fef53fc..7fa97f65655a 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -213,7 +213,7 @@ nfsd(struct svc_rqst *rqstp) unsigned int signo; for (signo = 1; signo <= _NSIG; signo++) - if (sigismember(¤t->signal, signo) && + if (sigismember(¤t->pending.signal, signo) && !sigismember(¤t->blocked, signo)) break; printk(KERN_WARNING "nfsd: terminating on signal %d\n", signo); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 20fa7fafeecf..bcd5281795f7 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -142,6 +142,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, } else dentry = dget(dparent->d_parent); } else { + fh_lock(fhp); dentry = lookup_one(name, dparent); err = PTR_ERR(dentry); if (IS_ERR(dentry)) diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 29b93e5a5589..32ff58703b27 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -228,24 +228,35 @@ unsigned int get_ptable_blocksize(kdev_t dev) } #ifdef CONFIG_PROC_FS -int get_partition_list(char * page) +int get_partition_list(char *page, char **start, off_t offset, int count) { - struct gendisk *p; - char buf[64]; - int n, len; + struct gendisk *dsk; + int len; len = sprintf(page, "major minor #blocks name\n\n"); - for (p = gendisk_head; p; p = p->next) { - for (n=0; n < (p->nr_real << p->minor_shift); n++) { - if (p->part[n].nr_sects && len < PAGE_SIZE - 80) { - len += sprintf(page+len, + for (dsk = gendisk_head; dsk; dsk = dsk->next) { + int n; + + for (n = 0; n < (dsk->nr_real << dsk->minor_shift); n++) + if (dsk->part[n].nr_sects) { + char buf[64]; + + len += sprintf(page + len, "%4d %4d %10d %s\n", - p->major, n, p->sizes[n], - disk_name(p, n, buf)); + dsk->major, n, dsk->sizes[n], + disk_name(dsk, n, buf)); + if (len < offset) + offset -= len, len = 0; + else if (len >= offset + count) + goto leave_loops; } - } } - return len; +leave_loops: + *start = page + offset; + len -= offset; + if (len < 0) + len = 0; + return len > count ? count : len; } #endif diff --git a/fs/proc/array.c b/fs/proc/array.c index 9b00883cdc53..f7f9038a51b9 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -241,7 +241,7 @@ static inline char * task_sig(struct task_struct *p, char *buffer) sigset_t ign, catch; buffer += sprintf(buffer, "SigPnd:\t"); - buffer = render_sigset_t(&p->signal, buffer); + buffer = render_sigset_t(&p->pending.signal, buffer); *buffer++ = '\n'; buffer += sprintf(buffer, "SigBlk:\t"); buffer = render_sigset_t(&p->blocked, buffer); @@ -382,7 +382,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer) * It must be decimal for Linux 2.0 compatibility. * Use /proc/#/status for real-time signals. */ - task->signal .sig[0] & 0x7fffffffUL, + task->pending.signal.sig[0] & 0x7fffffffUL, task->blocked.sig[0] & 0x7fffffffUL, sigign .sig[0] & 0x7fffffffUL, sigcatch .sig[0] & 0x7fffffffUL, diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 600ff9987837..576d1beaa3c9 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -56,7 +56,7 @@ extern int get_module_list(char *); extern int get_ksyms_list(char *, char **, off_t, int); #endif extern int get_device_list(char *); -extern int get_partition_list(char *); +extern int get_partition_list(char *, char **, off_t, int); extern int get_filesystem_list(char *); extern int get_filesystem_info(char *); extern int get_exec_domain_list(char *); @@ -375,12 +375,8 @@ static int devices_read_proc(char *page, char **start, off_t off, static int partitions_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = get_partition_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; + int len = get_partition_list(page, start, off, count); + if (len < count) *eof = 1; return len; } diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h index 69bfdcaf1d88..c93491f1a366 100644 --- a/include/asm-alpha/bitops.h +++ b/include/asm-alpha/bitops.h @@ -175,13 +175,10 @@ extern inline unsigned long ffz_b(unsigned long x) extern inline unsigned long ffz(unsigned long word) { -#if 0 && defined(__alpha_cix__) - /* Swine architects -- a year after they publish v3 of the - handbook, in the 21264 data sheet they quietly change CIX - to FIX and remove the spiffy counting instructions. */ +#if defined(__alpha_cix__) && defined(__alpha_fix__) /* Whee. EV6 can calculate it directly. */ unsigned long result; - __asm__("ctlz %1,%0" : "=r"(result) : "r"(~word)); + __asm__("cttz %1,%0" : "=r"(result) : "r"(~word)); return result; #else unsigned long bits, qofs, bofs; @@ -214,10 +211,7 @@ extern inline int ffs(int word) * of bits set) of a N-bit word */ -#if 0 && defined(__alpha_cix__) -/* Swine architects -- a year after they publish v3 of the handbook, in - the 21264 data sheet they quietly change CIX to FIX and remove the - spiffy counting instructions. */ +#if defined(__alpha_cix__) && defined(__alpha_fix__) /* Whee. EV6 can calculate it directly. */ extern __inline__ unsigned long hweight64(unsigned long w) { diff --git a/include/asm-alpha/core_irongate.h b/include/asm-alpha/core_irongate.h index c97283d89e49..e2c9fa968547 100644 --- a/include/asm-alpha/core_irongate.h +++ b/include/asm-alpha/core_irongate.h @@ -83,247 +83,24 @@ typedef struct { igcsr32 agpmode; /* 0xB0 - AGP/GART mode control */ } Irongate0; -/* Bitfield and mask register definitions */ - -/* Device, vendor IDs - offset 0x00 */ - -typedef union { - igcsr32 i; /* integer value of CSR */ - struct { - unsigned v : 16; - unsigned d : 16; - } r; /* structured interpretation */ -} ig_dev_vendor_t; - - -/* Status, command registers - offset 0x04 */ - -typedef union { - igcsr32 i; - struct { - unsigned command; - unsigned status; - } s; - struct { - /* command register fields */ - unsigned iospc : 1; /* always reads zero */ - unsigned memspc : 1; /* PCI memory space accesses? */ - unsigned iten : 1; /* always 1: can be bus initiator */ - unsigned scmon : 1; /* always 0 special cycles not chckd */ - unsigned mwic : 1; /* always 0 - no mem write & invalid */ - unsigned vgaps : 1; /* always 0 - palette rds not special */ - unsigned per : 1; /* parity error resp: always 0 */ - unsigned step : 1; /* address/data stepping : always 0 */ - unsigned serre : 1; /* 1 = sys err output driver enable */ - unsigned fbbce : 1; /* fast back-back cycle : always 0 */ - unsigned zero1 : 6; /* must be zero */ - - /* status register fields */ - unsigned zero2 : 4; /* must be zero */ - unsigned cl : 1; /* config space capa list: always 1 */ - unsigned pci66 : 1; /* 66 MHz PCI support - always 0 */ - unsigned udf : 1; /* user defined features - always 0 */ - unsigned fbbc : 1; /* back-back transactions - always 0 */ - unsigned ppe : 1; /* PCI parity error detected (0) */ - unsigned devsel : 2; /* DEVSEL timing (always 01) */ - unsigned sta : 1; /* signalled target abort (0) */ - unsigned rta : 1; /* recvd target abort */ - unsigned ria : 1; /* recvd initiator abort */ - unsigned serr : 1; /* SERR has been asserted */ - unsigned dpe : 1; /* DRAM parity error (0) */ - } r; -} ig_stat_cmd_t; - - -/* Revision ID, Programming interface, subclass, baseclass - offset 0x08 */ - -typedef union { - igcsr32 i; - struct { - /* revision ID */ - unsigned step : 4; /* stepping Revision ID */ - unsigned die : 4; /* die Revision ID */ - unsigned pif : 8; /* programming interface (0x00) */ - unsigned sub : 8; /* subclass code (0x00) */ - unsigned base: 8; /* baseclass code (0x06) */ - } r; -} ig_class_t; - - -/* Latency Timer, PCI Header type - offset 0x0C */ - -typedef union { - igcsr32 i; - struct { - unsigned zero1:8; /* reserved */ - unsigned lat : 8; /* latency in PCI bus clocks */ - unsigned hdr : 8; /* PCI header type */ - unsigned zero2:8; /* reserved */ - } r; -} ig_latency_t; - - -/* Base Address Register 0 - offset 0x10 */ - -typedef union { - igcsr32 i; - struct { - unsigned mem : 1; /* Reg pts to memory (always 0) */ - unsigned type: 2; /* 32 bit register = 0b00 */ - unsigned pref: 1; /* graphics mem prefetchable=1 */ - unsigned baddrl : 21; /* 32M = minimum alloc -> all zero */ - unsigned size : 6; /* size requirements for AGP */ - unsigned zero : 1; /* reserved=0 */ - } r; -} ig_bar0_t; - - -/* Base Address Register 1 - offset 0x14 */ - -typedef union { - igcsr32 i; - struct { - unsigned mem : 1; /* BAR0 maps to memory -> 0 */ - unsigned type : 2; /* BAR1 is 32-bit -> 0b00 */ - unsigned pref : 1; /* graphics mem prefetchable=1 */ - unsigned baddrl : 8; /* 4K alloc for AGP CSRs -> 0b00 */ - unsigned baddrh : 20; /* base addr of AGP CSRs A[30:11] */ - } r; -} ig_bar1_t; - - -/* Base Address Register 2 - offset 0x18 */ - -typedef union { - igcsr32 i; - struct { - unsigned io : 1; /* BAR2 maps to I/O space -> 1 */ - unsigned zero1: 1; /* reserved */ - unsigned addr : 22; /* BAR2[31:10] - PM2_BLK base */ - unsigned zero2: 8; /* reserved */ - } r; -} ig_bar2_t; - - -/* Capabilities Pointer - offset 0x34 */ - -typedef union { - igcsr32 i; - struct { - unsigned cap : 8; /* =0xA0, offset of AGP ctrl regs */ - unsigned zero: 24; /* reserved */ - } r; -} ig_capptr_t; - - -/* Base Address Chip Select Register 1,0 - offset 0x40 */ -/* Base Address Chip Select Register 3,2 - offset 0x44 */ -/* Base Address Chip Select Register 5,4 - offset 0x48 */ - -typedef union { - - igcsr32 i; - struct { - /* lower bank */ - unsigned en0 : 1; /* memory bank enabled */ - unsigned mask0 : 6; /* Address mask for A[28:23] */ - unsigned base0 : 9; /* Bank Base Address A[31:23] */ - - /* upper bank */ - unsigned en1 : 1; /* memory bank enabled */ - unsigned mask1 : 6; /* Address mask for A[28:23] */ - unsigned base1 : 9; /* Bank Base Address A[31:23] */ - } r; -} ig_bacsr_t, ig_bacsr10_t, ig_bacsr32_t, ig_bacsr54_t; - - -/* SDRAM Address Mapping Control Register - offset 0x50 */ - -typedef union { - igcsr32 i; - struct { - unsigned z1 : 1; /* reserved */ - unsigned bnks0: 1; /* 0->2 banks in chip select 0 */ - unsigned am0 : 1; /* row/column addressing */ - unsigned z2 : 1; /* reserved */ - - unsigned z3 : 1; /* reserved */ - unsigned bnks1: 1; /* 0->2 banks in chip select 1 */ - unsigned am1 : 1; /* row/column addressing */ - unsigned z4 : 1; /* reserved */ - - unsigned z5 : 1; /* reserved */ - unsigned bnks2: 1; /* 0->2 banks in chip select 2 */ - unsigned am2 : 1; /* row/column addressing */ - unsigned z6 : 1; /* reserved */ - - unsigned z7 : 1; /* reserved */ - unsigned bnks3: 1; /* 0->2 banks in chip select 3 */ - unsigned am3 : 1; /* row/column addressing */ - unsigned z8 : 1; /* reserved */ - - unsigned z9 : 1; /* reserved */ - unsigned bnks4: 1; /* 0->2 banks in chip select 4 */ - unsigned am4 : 1; /* row/column addressing */ - unsigned z10 : 1; /* reserved */ - - unsigned z11 : 1; /* reserved */ - unsigned bnks5: 1; /* 0->2 banks in chip select 5 */ - unsigned am5 : 1; /* row/column addressing */ - unsigned z12 : 1; /* reserved */ - - unsigned rsrvd: 8; /* reserved */ - } r; -} ig_drammap_t; - - -/* DRAM timing and driver strength register - offset 0x54 */ - -typedef union { - igcsr32 i; - struct { - /* DRAM timing parameters */ - unsigned trcd : 2; - unsigned tcl : 2; - unsigned tras: 3; - unsigned trp : 2; - unsigned trc : 3; - unsigned icl: 2; - unsigned ph : 2; - - /* Chipselect driver strength */ - unsigned adra : 1; - unsigned adrb : 1; - unsigned ctrl : 3; - unsigned dqm : 1; - unsigned cs : 1; - unsigned clk: 1; - unsigned rsrvd:8; - } r; -} ig_dramtm_t; - - -/* DRAM Mode / Status and ECC Register - offset 0x58 */ - -typedef union { - igcsr32 i; - struct { - unsigned chipsel : 6; /* failing ECC chip select */ - unsigned zero1 : 2; /* always reads zero */ - unsigned status : 2; /* ECC Detect logic status */ - unsigned zero2 : 6; /* always reads zero */ - - unsigned cycles : 2; /* cycles per refresh, see table */ - unsigned en : 1; /* ECC enable */ - unsigned r : 1; /* Large burst enable (=0) */ - unsigned bre : 1; /* Burst refresh enable */ - unsigned zero3 : 2; /* reserved = 0 */ - unsigned mwe : 1; /* Enable writes to DRAM mode reg */ - unsigned type : 1; /* SDRAM = 0, default */ - unsigned sdraminit : 1; /* SDRAM init - set params first! */ - unsigned zero4 : 6; /* reserved = 0 */ - } r; -} ig_dramms_t; + +typedef struct { + + igcsr32 dev_vendor; /* 0x00 - Device and Vendor IDs */ + igcsr32 stat_cmd; /* 0x04 - Status and Command regs */ + igcsr32 class; /* 0x08 - subclass, baseclass etc */ + igcsr32 htype; /* 0x0C - header type (at 0x0E) */ + igcsr32 rsrvd0[2]; /* 0x10-0x17 reserved */ + igcsr32 busnos; /* 0x18 - Primary, secondary bus nos */ + igcsr32 io_baselim_regs; /* 0x1C - IO base, IO lim, AGP status */ + igcsr32 mem_baselim; /* 0x20 - memory base, memory lim */ + igcsr32 pfmem_baselim; /* 0x24 - prefetchable base, lim */ + igcsr32 rsrvd1[2]; /* 0x28-0x2F reserved */ + igcsr32 io_baselim; /* 0x30 - IO base, IO limit */ + igcsr32 rsrvd2[2]; /* 0x34-0x3B - reserved */ + igcsr32 interrupt; /* 0x3C - interrupt, PCI bridge ctrl */ + +} Irongate1; /* @@ -343,7 +120,21 @@ typedef union { #define IRONGATE_IO (IDENT_ADDR | IRONGATE_BIAS | 0x1FC000000UL) #define IRONGATE_CONF (IDENT_ADDR | IRONGATE_BIAS | 0x1FE000000UL) -#define IRONGATE0 ((Irongate0 *) IRONGATE_CONF) +/* + * PCI Configuration space accesses are formed like so: + * + * 0x1FE << 24 | : 2 2 2 2 1 1 1 1 : 1 1 1 1 1 1 0 0 : 0 0 0 0 0 0 0 0 : + * : 3 2 1 0 9 8 7 6 : 5 4 3 2 1 0 9 8 : 7 6 5 4 3 2 1 0 : + * ---bus numer--- -device-- -fun- ---register---- + */ + +#define IGCSR(dev,fun,reg) ( IRONGATE_CONF | \ + ((dev)<<11) | \ + ((fun)<<8) | \ + (reg) ) + +#define IRONGATE0 ((Irongate0 *) IGCSR(0, 0, 0)) +#define IRONGATE1 ((Irongate1 *) IGCSR(1, 0, 0)) /* * Data structure for handling IRONGATE machine checks: diff --git a/include/asm-alpha/uaccess.h b/include/asm-alpha/uaccess.h index 98c446942f05..eeb5b85406dd 100644 --- a/include/asm-alpha/uaccess.h +++ b/include/asm-alpha/uaccess.h @@ -78,24 +78,6 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) #define __get_user(x,ptr) \ __get_user_nocheck((x),(ptr),sizeof(*(ptr))) -/* - * The "xxx_ret" versions return constant specified in third argument, if - * something bad happens. These macros can be optimized for the - * case of just returning from the function xxx_ret is used. - */ - -#define put_user_ret(x,ptr,ret) ({ \ -if (put_user(x,ptr)) return ret; }) - -#define get_user_ret(x,ptr,ret) ({ \ -if (get_user(x,ptr)) return ret; }) - -#define __put_user_ret(x,ptr,ret) ({ \ -if (__put_user(x,ptr)) return ret; }) - -#define __get_user_ret(x,ptr,ret) ({ \ -if (__get_user(x,ptr)) return ret; }) - /* * The "lda %1, 2b-1b(%0)" bits are magic to get the assembler to * encode the bits we need for resolving the exception. See the @@ -417,16 +399,6 @@ copy_from_user(void *to, const void *from, long n) return __copy_tofrom_user(to, from, n, from); } -#define copy_to_user_ret(to,from,n,retval) ({ \ -if (copy_to_user(to,from,n)) \ - return retval; \ -}) - -#define copy_from_user_ret(to,from,n,retval) ({ \ -if (copy_from_user(to,from,n)) \ - return retval; \ -}) - extern void __do_clear_user(void); extern inline long diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h index add086e55406..7e8040d73f90 100644 --- a/include/asm-arm/uaccess.h +++ b/include/asm-arm/uaccess.h @@ -59,9 +59,6 @@ extern __inline__ int verify_area(int type, const void * addr, unsigned long siz * address space - it must have been done previously with a separate * "access_ok()" call. * - * The "xxx_ret" versions return constant specified in the third - * argument if something bad happens. - * * The "xxx_error" versions set the third argument to EFAULT if an * error occurs, and leave it unchanged on success. Note that these * versions are void (ie, don't return a value as such). @@ -69,14 +66,10 @@ extern __inline__ int verify_area(int type, const void * addr, unsigned long siz #define get_user(x,p) __get_user_check((x),(p),sizeof(*(p))) #define __get_user(x,p) __get_user_nocheck((x),(p),sizeof(*(p))) #define __get_user_error(x,p,e) __get_user_nocheck_error((x),(p),sizeof(*(p)),(e)) -#define get_user_ret(x,p,r) ({ if (get_user(x,p)) return r; }) -#define __get_user_ret(x,p,r) ({ if (__get_user(x,p)) return r; }) #define put_user(x,p) __put_user_check((__typeof(*(p)))(x),(p),sizeof(*(p))) #define __put_user(x,p) __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p))) #define __put_user_error(x,p,e) __put_user_nocheck_error((x),(p),sizeof(*(p)),(e)) -#define put_user_ret(x,p,r) ({ if (put_user(x,p)) return r; }) -#define __put_user_ret(x,p,r) ({ if (__put_user(x,p)) return r; }) static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n) { @@ -91,9 +84,6 @@ static __inline__ unsigned long __copy_from_user(void *to, const void *from, uns return n; } -#define copy_from_user_ret(t,f,n,r) \ - ({ if (copy_from_user(t,f,n)) return r; }) - static __inline__ unsigned long copy_to_user(void *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) @@ -107,9 +97,6 @@ static __inline__ unsigned long __copy_to_user(void *to, const void *from, unsig return n; } -#define copy_to_user_ret(t,f,n,r) \ - ({ if (copy_to_user(t,f,n)) return r; }) - static __inline__ unsigned long clear_user (void *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h index 3f3bc50f4067..67347daea1ec 100644 --- a/include/asm-i386/uaccess.h +++ b/include/asm-i386/uaccess.h @@ -232,20 +232,6 @@ do { \ : "=r"(err), ltype (x) \ : "m"(__m(addr)), "i"(-EFAULT), "0"(err)) -/* - * The "xxx_ret" versions return constant specified in third argument, if - * something bad happens. These macros can be optimized for the - * case of just returning from the function xxx_ret is used. - */ - -#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; }) - -#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; }) - -#define __put_user_ret(x,ptr,ret) ({ if (__put_user(x,ptr)) return ret; }) - -#define __get_user_ret(x,ptr,ret) ({ if (__get_user(x,ptr)) return ret; }) - /* * Copy To/From Userspace @@ -583,10 +569,6 @@ __constant_copy_from_user_nocheck(void *to, const void *from, unsigned long n) __constant_copy_from_user((to),(from),(n)) : \ __generic_copy_from_user((to),(from),(n))) -#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; }) - -#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; }) - #define __copy_to_user(to,from,n) \ (__builtin_constant_p(n) ? \ __constant_copy_to_user_nocheck((to),(from),(n)) : \ diff --git a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h index e530e7f3548e..319784a5bc14 100644 --- a/include/asm-ia64/uaccess.h +++ b/include/asm-ia64/uaccess.h @@ -86,16 +86,6 @@ verify_area (int type, const void *addr, unsigned long size) #define __put_user(x,ptr) __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) #define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr))) -/* - * The "xxx_ret" versions return constant specified in third argument, if - * something bad happens. These macros can be optimized for the - * case of just returning from the function xxx_ret is used. - */ -#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; }) -#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; }) -#define __put_user_ret(x,ptr,ret) ({ if (__put_user(x,ptr)) return ret; }) -#define __get_user_ret(x,ptr,ret) ({ if (__get_user(x,ptr)) return ret; }) - extern void __get_user_unknown (void); #define __get_user_nocheck(x,ptr,size) \ @@ -280,18 +270,6 @@ extern unsigned long __copy_user (void *to, const void *from, unsigned long coun __cu_len; \ }) -#define copy_to_user_ret(to,from,n,retval) \ -({ \ - if (copy_to_user(to,from,n)) \ - return retval; \ -}) - -#define copy_from_user_ret(to,from,n,retval) \ -({ \ - if (copy_from_user(to,from,n)) \ - return retval; \ -}) - extern unsigned long __do_clear_user (void *, unsigned long); #define __clear_user(to,n) \ diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h index 82897ade9400..1fe589f66d52 100644 --- a/include/asm-m68k/uaccess.h +++ b/include/asm-m68k/uaccess.h @@ -759,10 +759,6 @@ __constant_copy_to_user(void *to, const void *from, unsigned long n) #define __copy_from_user(to, from, n) copy_from_user(to, from, n) #define __copy_to_user(to, from, n) copy_to_user(to, from, n) -#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; }) - -#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; }) - /* * Copy a null terminated string from userspace. */ diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h index 2d3cc959dad4..c94006594bc9 100644 --- a/include/asm-mips/uaccess.h +++ b/include/asm-mips/uaccess.h @@ -84,24 +84,6 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) #define __get_user(x,ptr) \ __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) -/* - * The "xxx_ret" versions return constant specified in third argument, if - * something bad happens. These macros can be optimized for the - * case of just returning from the function xxx_ret is used. - */ - -#define put_user_ret(x,ptr,ret) ({ \ -if (put_user(x,ptr)) return ret; }) - -#define get_user_ret(x,ptr,ret) ({ \ -if (get_user(x,ptr)) return ret; }) - -#define __put_user_ret(x,ptr,ret) ({ \ -if (__put_user(x,ptr)) return ret; }) - -#define __get_user_ret(x,ptr,ret) ({ \ -if (__get_user(x,ptr)) return ret; }) - struct __large_struct { unsigned long buf[100]; }; #define __m(x) (*(struct __large_struct *)(x)) @@ -281,16 +263,6 @@ extern void __put_user_unknown(void); "jal\t" #destination "\n\t" #endif -#define copy_to_user_ret(to,from,n,retval) ({ \ -if (copy_to_user(to,from,n)) \ - return retval; \ -}) - -#define copy_from_user_ret(to,from,n,retval) ({ \ -if (copy_from_user(to,from,n)) \ - return retval; \ -}) - extern size_t __copy_user(void *__to, const void *__from, size_t __n); #define __copy_to_user(to,from,n) ({ \ diff --git a/include/asm-mips64/uaccess.h b/include/asm-mips64/uaccess.h index 2a9f2ee167aa..1727b8de23e0 100644 --- a/include/asm-mips64/uaccess.h +++ b/include/asm-mips64/uaccess.h @@ -84,18 +84,6 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) #define __get_user(x,ptr) \ __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) -/* - * The "xxx_ret" versions return constant specified in third argument, if - * something bad happens. These macros can be optimized for the - * case of just returning from the function xxx_ret is used. - */ - -#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; }) -#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; }) - -#define __put_user_ret(x,ptr,ret) ({ if (__put_user(x,ptr)) return ret; }) -#define __get_user_ret(x,ptr,ret) ({ if (__get_user(x,ptr)) return ret; }) - struct __large_struct { unsigned long buf[100]; }; #define __m(x) (*(struct __large_struct *)(x)) @@ -213,16 +201,6 @@ extern void __put_user_unknown(void); "jal\t" #destination "\n\t" #endif -#define copy_to_user_ret(to,from,n,retval) ({ \ -if (copy_to_user(to,from,n)) \ - return retval; \ -}) - -#define copy_from_user_ret(to,from,n,retval) ({ \ -if (copy_from_user(to,from,n)) \ - return retval; \ -}) - extern size_t __copy_user(void *__to, const void *__from, size_t __n); #define __copy_to_user(to,from,n) ({ \ diff --git a/include/asm-ppc/uaccess.h b/include/asm-ppc/uaccess.h index 3eafdbd9137a..fcb22706b1e3 100644 --- a/include/asm-ppc/uaccess.h +++ b/include/asm-ppc/uaccess.h @@ -87,25 +87,6 @@ extern unsigned long search_exception_table(unsigned long); #define __put_user(x,ptr) \ __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) -/* - * The "xxx_ret" versions return constant specified in third argument, if - * something bad happens. These macros can be optimized for the - * case of just returning from the function xxx_ret is used. - */ - -#define put_user_ret(x,ptr,ret) ({ \ -if (put_user(x,ptr)) return ret; }) - -#define get_user_ret(x,ptr,ret) ({ \ -if (get_user(x,ptr)) return ret; }) - -#define __put_user_ret(x,ptr,ret) ({ \ -if (__put_user(x,ptr)) return ret; }) - -#define __get_user_ret(x,ptr,ret) ({ \ -if (__get_user(x,ptr)) return ret; }) - - extern long __put_user_bad(void); #define __put_user_nocheck(x,ptr,size) \ @@ -236,10 +217,6 @@ copy_to_user(void *to, const void *from, unsigned long n) return n; } -#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; }) - -#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; }) - #define __copy_from_user(to, from, size) \ __copy_tofrom_user((to), (from), (size)) #define __copy_to_user(to, from, size) \ diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h index 9f448fc50c0a..a19cfa29f040 100644 --- a/include/asm-s390/uaccess.h +++ b/include/asm-s390/uaccess.h @@ -407,10 +407,6 @@ __copy_from_user_asm(void* to, const void* from, long n) err; \ }) -#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; }) - -#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; }) - /* * Copy a null terminated string from userspace. */ diff --git a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h index 2237d34a468f..5434ccb5fd7e 100644 --- a/include/asm-sh/uaccess.h +++ b/include/asm-sh/uaccess.h @@ -83,24 +83,6 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) #define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr))) #define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr))) -/* - * The "xxx_ret" versions return constant specified in third argument, if - * something bad happens. These macros can be optimized for the - * case of just returning from the function xxx_ret is used. - */ - -#define put_user_ret(x,ptr,ret) ({ \ -if (put_user(x,ptr)) return ret; }) - -#define get_user_ret(x,ptr,ret) ({ \ -if (get_user(x,ptr)) return ret; }) - -#define __put_user_ret(x,ptr,ret) ({ \ -if (__put_user(x,ptr)) return ret; }) - -#define __get_user_ret(x,ptr,ret) ({ \ -if (__get_user(x,ptr)) return ret; }) - struct __large_struct { unsigned long buf[100]; }; #define __m(x) (*(struct __large_struct *)(x)) @@ -256,20 +238,10 @@ __copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ } else __copy_res = __copy_size; \ __copy_res; }) -#define copy_to_user_ret(to,from,n,retval) ({ \ -if (copy_to_user(to,from,n)) \ - return retval; \ -}) - #define __copy_to_user(to,from,n) \ __copy_user((void *)(to), \ (void *)(from), n) -#define __copy_to_user_ret(to,from,n,retval) ({ \ -if (__copy_to_user(to,from,n)) \ - return retval; \ -}) - #define copy_from_user(to,from,n) ({ \ void *__copy_to = (void *) (to); \ void *__copy_from = (void *) (from); \ @@ -280,20 +252,10 @@ __copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ } else __copy_res = __copy_size; \ __copy_res; }) -#define copy_from_user_ret(to,from,n,retval) ({ \ -if (copy_from_user(to,from,n)) \ - return retval; \ -}) - #define __copy_from_user(to,from,n) \ __copy_user((void *)(to), \ (void *)(from), n) -#define __copy_from_user_ret(to,from,n,retval) ({ \ -if (__copy_from_user(to,from,n)) \ - return retval; \ -}) - /* XXX: Not sure it works well.. should be such that: 4byte clear and the rest. */ extern __inline__ __kernel_size_t diff --git a/include/asm-sparc/hardirq.h b/include/asm-sparc/hardirq.h index cfee071dc3ad..00205d6ef017 100644 --- a/include/asm-sparc/hardirq.h +++ b/include/asm-sparc/hardirq.h @@ -1,7 +1,7 @@ /* hardirq.h: 32-bit Sparc hard IRQ support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 1998-2000 Anton Blanchard (anton@linuxcare.com) */ #ifndef __SPARC_HARDIRQ_H @@ -9,77 +9,83 @@ #include #include +#include +#include /* entry.S is sensitive to the offsets of these fields */ typedef struct { unsigned int __softirq_active; unsigned int __softirq_mask; +#ifndef CONFIG_SMP unsigned int __local_irq_count; +#else + unsigned int __unused_on_SMP; /* DaveM says use brlock for SMP irq. KAO */ +#endif unsigned int __local_bh_count; unsigned int __syscall_count; } ____cacheline_aligned irq_cpustat_t; #include /* Standard mappings for irq_cpustat_t above */ +/* Note that local_irq_count() is replaced by sparc64 specific version for SMP */ + +#ifndef CONFIG_SMP +#define irq_enter(cpu, irq) ((void)(irq), local_irq_count(cpu)++) +#define irq_exit(cpu, irq) ((void)(irq), local_irq_count(cpu)--) +#else +#undef local_irq_count +#define local_irq_count(cpu) (__brlock_array[cpu][BR_GLOBALIRQ_LOCK]) +#define irq_enter(cpu, irq) br_read_lock(BR_GLOBALIRQ_LOCK) +#define irq_exit(cpu, irq) br_read_unlock(BR_GLOBALIRQ_LOCK) +#endif /* * Are we in an interrupt context? Either doing bottom half * or hardware interrupt processing? */ -#define in_interrupt() ({ int __cpu = smp_processor_id(); \ - (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); }) +#define in_interrupt() ((local_irq_count(smp_processor_id()) + \ + local_bh_count(smp_processor_id())) != 0) -#define in_irq() ({ int __cpu = smp_processor_id(); \ - (local_irq_count(__cpu) != 0); }) +/* This tests only the local processors hw IRQ context disposition. */ +#define in_irq() (local_irq_count(smp_processor_id()) != 0) #ifndef CONFIG_SMP -#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) -#define hardirq_endlock(cpu) do { (void)(cpu); } while (0) - -#define hardirq_enter(cpu) (++local_irq_count(cpu)) -#define hardirq_exit(cpu) (--local_irq_count(cpu)) +#define hardirq_trylock(cpu) ((void)(cpu), local_irq_count(smp_processor_id()) == 0) +#define hardirq_endlock(cpu) do { (void)(cpu); } while(0) #define synchronize_irq() barrier() -#else +#else /* (CONFIG_SMP) */ -#include -#include -#include -#include +static __inline__ int irqs_running(void) +{ + int i; + + for (i = 0; i < smp_num_cpus; i++) + if (local_irq_count(cpu_logical_map(i))) + return 1; + return 0; +} extern unsigned char global_irq_holder; -extern spinlock_t global_irq_lock; -extern atomic_t global_irq_count; static inline void release_irqlock(int cpu) { - /* if we didn't own the irq lock, just ignore.. */ - if (global_irq_holder == (unsigned char) cpu) { + /* if we didn't own the irq lock, just ignore... */ + if(global_irq_holder == (unsigned char) cpu) { global_irq_holder = NO_PROC_ID; - spin_unlock(&global_irq_lock); + br_write_unlock(BR_GLOBALIRQ_LOCK); } } -static inline void hardirq_enter(int cpu) -{ - ++local_irq_count(cpu); - atomic_inc(&global_irq_count); -} - -static inline void hardirq_exit(int cpu) -{ - atomic_dec(&global_irq_count); - --local_irq_count(cpu); -} - static inline int hardirq_trylock(int cpu) { - return (! atomic_read(&global_irq_count) && - ! spin_is_locked (&global_irq_lock)); + spinlock_t *lock = &__br_write_locks[BR_GLOBALIRQ_LOCK].lock; + + return (!local_irq_count(cpu) && !spin_is_locked(lock)); } -#define hardirq_endlock(cpu) do { } while (0) +#define hardirq_endlock(cpu) do { (void)(cpu); } while (0) extern void synchronize_irq(void); diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h index a58a80810b23..6008023a5651 100644 --- a/include/asm-sparc/irq.h +++ b/include/asm-sparc/irq.h @@ -1,4 +1,4 @@ -/* $Id: irq.h,v 1.31 2000/08/05 10:48:41 davem Exp $ +/* $Id: irq.h,v 1.32 2000/08/26 02:42:28 anton Exp $ * irq.h: IRQ registers on the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -21,18 +21,6 @@ BTFIXUPDEF_CALL(char *, __irq_itoa, unsigned int) #define NR_IRQS 15 -/* IRQ handler dispatch entry and exit. */ -#ifdef CONFIG_SMP -#define irq_enter(cpu, irq) \ -do { hardirq_enter(cpu); \ - spin_unlock_wait(&global_irq_lock); \ - } while(0) -#define irq_exit(cpu, irq) hardirq_exit(cpu) -#else -#define irq_enter(cpu, irq) (++local_irq_count(cpu)) -#define irq_exit(cpu, irq) (--local_irq_count(cpu)) -#endif - /* Dave Redman (djhr@tadpole.co.uk) * changed these to function pointers.. it saves cycles and will allow * the irq dependencies to be split into different files at a later date diff --git a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h index 396f9ef07425..4e2e6015735b 100644 --- a/include/asm-sparc/oplib.h +++ b/include/asm-sparc/oplib.h @@ -1,4 +1,4 @@ -/* $Id: oplib.h,v 1.20 1998/09/17 11:05:25 jj Exp $ +/* $Id: oplib.h,v 1.21 2000/08/26 02:38:04 anton Exp $ * oplib.h: Describes the interface and available routines in the * Linux Prom library. * @@ -9,6 +9,7 @@ #define __SPARC_OPLIB_H #include +#include /* The master romvec pointer... */ extern struct linux_romvec *romvec; @@ -311,6 +312,7 @@ extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nr /* Apply ranges of any prom node (and optionally parent node as well) to registers. */ extern void prom_apply_generic_ranges(int node, int parent, struct linux_prom_registers *sbusregs, int nregs); - + +extern spinlock_t prom_lock; #endif /* !(__SPARC_OPLIB_H) */ diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h index c026a21fa9ba..1587f92f968a 100644 --- a/include/asm-sparc/uaccess.h +++ b/include/asm-sparc/uaccess.h @@ -1,4 +1,4 @@ -/* $Id: uaccess.h,v 1.21 2000/01/08 16:38:23 anton Exp $ +/* $Id: uaccess.h,v 1.22 2000/08/29 07:01:58 davem Exp $ * uaccess.h: User space memore access functions. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -94,27 +94,17 @@ extern void __ret_efault(void); unsigned long __pu_addr = (unsigned long)(ptr); \ __put_user_check((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); }) -#define put_user_ret(x,ptr,retval) ({ \ -unsigned long __pu_addr = (unsigned long)(ptr); \ -__put_user_check_ret((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr)),retval); }) - #define get_user(x,ptr) ({ \ unsigned long __gu_addr = (unsigned long)(ptr); \ __get_user_check((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); }) -#define get_user_ret(x,ptr,retval) ({ \ -unsigned long __gu_addr = (unsigned long)(ptr); \ -__get_user_check_ret((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr)),retval); }) - /* * The "__xxx" versions do not do address space checking, useful when * doing multiple accesses to the same area (the user has to do the * checks by hand with "access_ok()") */ #define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr))) -#define __put_user_ret(x,ptr,retval) __put_user_nocheck_ret((x),(ptr),sizeof(*(ptr)),retval) #define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr))) -#define __get_user_ret(x,ptr,retval) __get_user_nocheck_ret((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr)),retval) struct __large_struct { unsigned long buf[100]; }; #define __m(x) ((struct __large_struct *)(x)) @@ -303,20 +293,10 @@ __copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ } else __copy_res = __copy_size; \ __copy_res; }) -#define copy_to_user_ret(to,from,n,retval) ({ \ -if (copy_to_user(to,from,n)) \ - return retval; \ -}) - #define __copy_to_user(to,from,n) \ __copy_user((void *)(to), \ (void *)(from), n) -#define __copy_to_user_ret(to,from,n,retval) ({ \ -if (__copy_to_user(to,from,n)) \ - return retval; \ -}) - #define copy_from_user(to,from,n) ({ \ void *__copy_to = (void *) (to); \ void *__copy_from = (void *) (from); \ @@ -327,20 +307,10 @@ __copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ } else __copy_res = __copy_size; \ __copy_res; }) -#define copy_from_user_ret(to,from,n,retval) ({ \ -if (copy_from_user(to,from,n)) \ - return retval; \ -}) - #define __copy_from_user(to,from,n) \ __copy_user((void *)(to), \ (void *)(from), n) -#define __copy_from_user_ret(to,from,n,retval) ({ \ -if (__copy_from_user(to,from,n)) \ - return retval; \ -}) - extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size) { __kernel_size_t ret; @@ -368,11 +338,6 @@ __clear_res = __clear_user(__clear_addr, __clear_size); \ } else __clear_res = __clear_size; \ __clear_res; }) -#define clear_user_ret(addr,size,retval) ({ \ -if (clear_user(addr,size)) \ - return retval; \ -}) - extern int __strncpy_from_user(unsigned long dest, unsigned long src, int count); #define strncpy_from_user(dest,src,count) ({ \ diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h index 72c2c691676c..bf60670f47b3 100644 --- a/include/asm-sparc64/uaccess.h +++ b/include/asm-sparc64/uaccess.h @@ -1,4 +1,4 @@ -/* $Id: uaccess.h,v 1.32 1999/11/23 08:56:48 davem Exp $ */ +/* $Id: uaccess.h,v 1.33 2000/08/29 07:01:58 davem Exp $ */ #ifndef _ASM_UACCESS_H #define _ASM_UACCESS_H @@ -102,22 +102,12 @@ extern void __ret_efault(void); unsigned long __pu_addr = (unsigned long)(ptr); \ __put_user_nocheck((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); }) -#define put_user_ret(x,ptr,retval) ({ \ -unsigned long __pu_addr = (unsigned long)(ptr); \ -__put_user_nocheck_ret((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr)),retval); }) - #define get_user(x,ptr) ({ \ unsigned long __gu_addr = (unsigned long)(ptr); \ __get_user_nocheck((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); }) -#define get_user_ret(x,ptr,retval) ({ \ -unsigned long __gu_addr = (unsigned long)(ptr); \ -__get_user_nocheck_ret((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr)),retval); }) - #define __put_user(x,ptr) put_user(x,ptr) -#define __put_user_ret(x,ptr,retval) put_user_ret(x,ptr,retval) #define __get_user(x,ptr) get_user(x,ptr) -#define __get_user_ret(x,ptr,retval) get_user_ret(x,ptr,retval) struct __large_struct { unsigned long buf[100]; }; #define __m(x) ((struct __large_struct *)(x)) @@ -288,44 +278,14 @@ extern __kernel_size_t __copy_in_user(void *to, const void *from, __copy_from_user((void *)(to), \ (void *)(from), (__kernel_size_t)(n)) -#define copy_from_user_ret(to,from,n,retval) ({ \ -if (copy_from_user(to,from,n)) \ - return retval; \ -}) - -#define __copy_from_user_ret(to,from,n,retval) ({ \ -if (__copy_from_user(to,from,n)) \ - return retval; \ -}) - #define copy_to_user(to,from,n) \ __copy_to_user((void *)(to), \ (void *) (from), (__kernel_size_t)(n)) -#define copy_to_user_ret(to,from,n,retval) ({ \ -if (copy_to_user(to,from,n)) \ - return retval; \ -}) - -#define __copy_to_user_ret(to,from,n,retval) ({ \ -if (__copy_to_user(to,from,n)) \ - return retval; \ -}) - #define copy_in_user(to,from,n) \ __copy_in_user((void *)(to), \ (void *) (from), (__kernel_size_t)(n)) -#define copy_in_user_ret(to,from,n,retval) ({ \ -if (copy_in_user(to,from,n)) \ - return retval; \ -}) - -#define __copy_in_user_ret(to,from,n,retval) ({ \ -if (__copy_in_user(to,from,n)) \ - return retval; \ -}) - extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size) { extern __kernel_size_t __bzero_noasi(void *addr, __kernel_size_t size); @@ -336,11 +296,6 @@ extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size) #define clear_user(addr,n) \ __clear_user((void *)(addr), (__kernel_size_t)(n)) -#define clear_user_ret(addr,size,retval) ({ \ -if (clear_user(addr,size)) \ - return retval; \ -}) - extern int __strncpy_from_user(unsigned long dest, unsigned long src, int count); #define strncpy_from_user(dest,src,count) \ diff --git a/include/linux/fs.h b/include/linux/fs.h index 3ce2c58bdeed..6f52059c7174 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -361,7 +361,8 @@ struct address_space { unsigned long nrpages; /* number of pages */ struct address_space_operations *a_ops; /* methods */ void *host; /* owner: inode, block_device */ - struct vm_area_struct *i_mmap; /* list of mappings */ + struct vm_area_struct *i_mmap; /* list of private mappings */ + struct vm_area_struct *i_mmap_shared; /* list of shared mappings */ spinlock_t i_shared_lock; /* and spinlock protecting it */ }; diff --git a/include/linux/mm.h b/include/linux/mm.h index f606186cfcbc..bac6318ab6b1 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -52,7 +52,8 @@ struct vm_area_struct { struct vm_area_struct * vm_avl_left; struct vm_area_struct * vm_avl_right; - /* For areas with inode, the list inode->i_mapping->i_mmap, + /* For areas with an address space and backing store, + * one of the address_space->i_mmap{,shared} lists, * for shm areas, the list of attaches, otherwise unused. */ struct vm_area_struct *vm_next_share; diff --git a/include/linux/nfsd/interface.h b/include/linux/nfsd/interface.h new file mode 100644 index 000000000000..afa9edc08bbd --- /dev/null +++ b/include/linux/nfsd/interface.h @@ -0,0 +1,21 @@ +/* + * include/linux/nfsd/interface.h + * + * defines interface between nfsd and other bits of + * the kernel. Particularly filesystems (eventually). + * + * Copyright (C) 2000 Neil Brown + */ + +#ifndef LINUX_NFSD_INTERFACE_H +#define LINUX_NFSD_INTERFACE_H + +#ifdef CONFIG_NFSD_MODULE + +extern struct nfsd_linkage { + long (*do_nfsservctl)(int cmd, void *argp, void *resp); +} * nfsd_linkage; + +#endif + +#endif /* LINUX_NFSD_INTERFACE_H */ diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index dacab21982d8..f183f57a5e87 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -21,7 +21,7 @@ #include #include #include - +#include /* * nfsd version */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 7f68d19517f8..09a5895545cb 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -333,9 +333,11 @@ #define PCI_DEVICE_ID_SI_300 0x0300 #define PCI_DEVICE_ID_SI_530 0x0530 #define PCI_DEVICE_ID_SI_540 0x0540 +#define PCI_DEVICE_ID_SI_540_VGA 0x5300 #define PCI_DEVICE_ID_SI_601 0x0601 #define PCI_DEVICE_ID_SI_620 0x0620 #define PCI_DEVICE_ID_SI_630 0x0630 +#define PCI_DEVICE_ID_SI_630_VGA 0x6300 #define PCI_DEVICE_ID_SI_5107 0x5107 #define PCI_DEVICE_ID_SI_5300 0x5300 #define PCI_DEVICE_ID_SI_5511 0x5511 diff --git a/include/linux/sched.h b/include/linux/sched.h index 50ed51863448..2d22dd6143c7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -33,12 +33,13 @@ extern unsigned long event; #define CLONE_VM 0x00000100 /* set if VM shared between processes */ #define CLONE_FS 0x00000200 /* set if fs info shared between processes */ #define CLONE_FILES 0x00000400 /* set if open files shared between processes */ -#define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */ +#define CLONE_SIGNAL 0x00000800 /* set if signal handlers and blocked signals shared */ #define CLONE_PID 0x00001000 /* set if pid shared */ #define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */ #define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ #define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */ -#define CLONE_THREAD 0x00010000 /* set if we want to clone the "thread group" */ + +#define CLONE_SIGHAND CLONE_SIGNAL /* Old name */ /* * These are the constant used to fake the fixed-point load-average @@ -233,6 +234,7 @@ struct mm_struct { struct signal_struct { atomic_t count; struct k_sigaction action[_NSIG]; + struct sigpending pending; spinlock_t siglock; }; @@ -240,6 +242,7 @@ struct signal_struct { #define INIT_SIGNALS { \ ATOMIC_INIT(1), \ { {{0,}}, }, \ + { NULL, &init_signals.pending.head, }, \ SPIN_LOCK_UNLOCKED } /* @@ -366,8 +369,10 @@ struct task_struct { /* signal handlers */ spinlock_t sigmask_lock; /* Protects signal and blocked */ struct signal_struct *sig; - sigset_t signal, blocked; - struct signal_queue *sigqueue, **sigqueue_tail; + + sigset_t blocked; + struct sigpending pending; + unsigned long sas_ss_sp; size_t sas_ss_size; int (*notifier)(void *priv); @@ -455,10 +460,8 @@ struct task_struct { files: &init_files, \ sigmask_lock: SPIN_LOCK_UNLOCKED, \ sig: &init_signals, \ - signal: {{0}}, \ + pending: { NULL, &tsk.pending.head, {{0}}}, \ blocked: {{0}}, \ - sigqueue: NULL, \ - sigqueue_tail: &tsk.sigqueue, \ alloc_lock: SPIN_LOCK_UNLOCKED \ } @@ -575,11 +578,11 @@ static inline int signal_pending(struct task_struct *p) return (p->sigpending != 0); } -/* Reevaluate whether the task has signals pending delivery. - This is required every time the blocked sigset_t changes. - All callers should have t->sigmask_lock. */ - -static inline void recalc_sigpending(struct task_struct *t) +/* + * Re-calculate pending state from the set of locally pending + * signals, globally pending signals, and blocked signals. + */ +static inline int has_pending_signals(sigset_t *p1, sigset_t *p2, sigset_t *blocked) { unsigned long ready; long i; @@ -587,23 +590,31 @@ static inline void recalc_sigpending(struct task_struct *t) switch (_NSIG_WORDS) { default: for (i = _NSIG_WORDS, ready = 0; --i >= 0 ;) - ready |= t->signal.sig[i] &~ t->blocked.sig[i]; + ready |= (p1->sig[i] | p2->sig[i]) &~ blocked->sig[i]; break; - case 4: ready = t->signal.sig[3] &~ t->blocked.sig[3]; - ready |= t->signal.sig[2] &~ t->blocked.sig[2]; - ready |= t->signal.sig[1] &~ t->blocked.sig[1]; - ready |= t->signal.sig[0] &~ t->blocked.sig[0]; + case 4: ready = (p1->sig[3] | p2->sig[3]) &~ blocked->sig[3]; + ready |= (p1->sig[2] | p2->sig[2]) &~ blocked->sig[2]; + ready |= (p1->sig[1] | p2->sig[1]) &~ blocked->sig[1]; + ready |= (p1->sig[0] | p2->sig[0]) &~ blocked->sig[0]; break; - case 2: ready = t->signal.sig[1] &~ t->blocked.sig[1]; - ready |= t->signal.sig[0] &~ t->blocked.sig[0]; + case 2: ready = (p1->sig[1] | p2->sig[1]) &~ blocked->sig[1]; + ready |= (p1->sig[0] | p2->sig[0]) &~ blocked->sig[0]; break; - case 1: ready = t->signal.sig[0] &~ t->blocked.sig[0]; + case 1: ready = (p1->sig[0] | p2->sig[0]) &~ blocked->sig[0]; } + return ready != 0; +} + +/* Reevaluate whether the task has signals pending delivery. + This is required every time the blocked sigset_t changes. + All callers should have t->sigmask_lock. */ - t->sigpending = (ready != 0); +static inline void recalc_sigpending(struct task_struct *t) +{ + t->sigpending = has_pending_signals(&t->pending.signal, &t->sig->pending.signal, &t->blocked); } /* True if we are on the alternate signal stack. */ diff --git a/include/linux/signal.h b/include/linux/signal.h index d6e82ae0535d..b3c5eb4c2d8f 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -9,12 +9,16 @@ * Real Time signals may be queued. */ -struct signal_queue -{ - struct signal_queue *next; +struct sigqueue { + struct sigqueue *next; siginfo_t info; }; +struct sigpending { + struct sigqueue *head, **tail; + sigset_t signal; +}; + /* * Define some primitives to manipulate sigset_t. */ @@ -207,6 +211,13 @@ extern inline void siginitsetinv(sigset_t *set, unsigned long mask) #endif /* __HAVE_ARCH_SIG_SETOPS */ +static inline void init_sigpending(struct sigpending *sig) +{ + sigemptyset(&sig->signal); + sig->head = NULL; + sig->tail = &sig->head; +} + #endif /* __KERNEL__ */ #endif /* _LINUX_SIGNAL_H */ diff --git a/include/pcmcia/bulkmem.h b/include/pcmcia/bulkmem.h index c920e3d41620..c9bdab7a102f 100644 --- a/include/pcmcia/bulkmem.h +++ b/include/pcmcia/bulkmem.h @@ -1,7 +1,7 @@ /* * Definitions for bulk memory services * - * bulkmem.h 1.11 1999/10/25 20:23:16 + * bulkmem.h 1.12 2000/06/12 21:55:41 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -14,7 +14,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/bus_ops.h b/include/pcmcia/bus_ops.h index 29e13547a3dc..bd4c2958f850 100644 --- a/include/pcmcia/bus_ops.h +++ b/include/pcmcia/bus_ops.h @@ -1,5 +1,5 @@ /* - * bus_ops.h 1.8 1999/10/25 20:23:16 + * bus_ops.h 1.10 2000/06/12 21:55:41 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h index e5c3280540dc..d449b42349d2 100644 --- a/include/pcmcia/ciscode.h +++ b/include/pcmcia/ciscode.h @@ -1,5 +1,5 @@ /* - * ciscode.h 1.40 2000/02/01 19:06:40 + * ciscode.h 1.45 2000/08/12 02:08:23 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the @@ -78,6 +78,9 @@ #define MANFID_NEW_MEDIA 0x0057 +#define MANFID_NOKIA 0x0124 +#define PRODID_NOKIA_CARDPHONE 0x0900 + #define MANFID_OLICOM 0x0121 #define PRODID_OLICOM_OC2231 0x3122 #define PRODID_OLICOM_OC2232 0x3222 @@ -94,6 +97,7 @@ #define MANFID_PIONEER 0x000b #define MANFID_PSION 0x016c +#define PRODID_PSION_NET100 0x0023 #define MANFID_QUATECH 0x0137 #define PRODID_QUATECH_SPP100 0x0003 @@ -106,12 +110,15 @@ #define MANFID_SOCKET 0x0104 #define PRODID_SOCKET_DUAL_RS232 0x0006 +#define PRODID_SOCKET_EIO 0x000a #define PRODID_SOCKET_LPE 0x000d #define MANFID_SUNDISK 0x0045 #define MANFID_TDK 0x0105 +#define MANFID_TOSHIBA 0x0098 + #define MANFID_XIRCOM 0x0105 #endif /* _LINUX_CISCODE_H */ diff --git a/include/pcmcia/cisreg.h b/include/pcmcia/cisreg.h index 8036605034e4..884d46de0fd4 100644 --- a/include/pcmcia/cisreg.h +++ b/include/pcmcia/cisreg.h @@ -1,5 +1,5 @@ /* - * cisreg.h 1.16 2000/01/16 19:19:14 + * cisreg.h 1.17 2000/06/12 21:55:41 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h index d53e446461a7..5f9701fe2ff6 100644 --- a/include/pcmcia/cistpl.h +++ b/include/pcmcia/cistpl.h @@ -1,5 +1,5 @@ /* - * cistpl.h 1.32 2000/01/11 19:06:50 + * cistpl.h 1.34 2000/06/19 23:18:12 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the @@ -68,6 +68,7 @@ #define CISTPL_BYTEORDER 0x43 #define CISTPL_DATE 0x44 #define CISTPL_BATTERY 0x45 +#define CISTPL_FORMAT_A 0x47 /* Layer 3 tuples */ #define CISTPL_ORG 0x46 #define CISTPL_SPCL 0x90 @@ -530,6 +531,21 @@ typedef struct cistpl_org_t { #define CISTPL_ORG_APPSPEC 0x01 #define CISTPL_ORG_XIP 0x02 +typedef struct cistpl_format_t { + u_char type; + u_char edc; + u_int offset; + u_int length; +} cistpl_format_t; + +#define CISTPL_FORMAT_DISK 0x00 +#define CISTPL_FORMAT_MEM 0x01 + +#define CISTPL_EDC_NONE 0x00 +#define CISTPL_EDC_CKSUM 0x01 +#define CISTPL_EDC_CRC 0x02 +#define CISTPL_EDC_PCC 0x03 + typedef union cisparse_t { cistpl_device_t device; cistpl_checksum_t checksum; @@ -548,6 +564,7 @@ typedef union cisparse_t { cistpl_device_geo_t device_geo; cistpl_vers_2_t vers_2; cistpl_org_t org; + cistpl_format_t format; } cisparse_t; typedef struct tuple_t { diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 669de1eac5ab..bfbf3d744d61 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -1,5 +1,5 @@ /* - * cs.h 1.69 1999/10/25 20:23:17 + * cs.h 1.71 2000/08/29 00:54:20 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the @@ -251,11 +251,6 @@ typedef struct eventmask_t { #define PRESENT_IOBASE_3 0x100 #define PRESENT_IOSIZE 0x200 -/* Attributes for Request/GetConfiguration */ -#define CONF_ENABLE_IRQ 0x01 -#define EXCLUSIVE_USE 0x02 -#define VALID_CLIENT 0x04 - /* For GetMemPage, MapMemPage */ typedef struct memreq_t { u_int CardOffset; diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h index 92feb63226d1..186ce9f3e577 100644 --- a/include/pcmcia/cs_types.h +++ b/include/pcmcia/cs_types.h @@ -1,5 +1,5 @@ /* - * cs_types.h 1.17 2000/01/18 01:14:36 + * cs_types.h 1.18 2000/06/12 21:55:40 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/driver_ops.h b/include/pcmcia/driver_ops.h index 337076a24307..bb95644b3692 100644 --- a/include/pcmcia/driver_ops.h +++ b/include/pcmcia/driver_ops.h @@ -1,5 +1,5 @@ /* - * driver_ops.h 1.14 1999/10/25 20:23:17 + * driver_ops.h 1.15 2000/06/12 21:55:40 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index ddb271ec9c43..e50033bc6e21 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -1,5 +1,5 @@ /* - * ds.h 1.55 1999/10/25 20:23:17 + * ds.h 1.56 2000/06/12 21:55:40 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/ftl.h b/include/pcmcia/ftl.h index 0fb527845d7b..deab295b63d4 100644 --- a/include/pcmcia/ftl.h +++ b/include/pcmcia/ftl.h @@ -1,5 +1,5 @@ /* - * ftl.h 1.7 1999/10/25 20:23:17 + * ftl.h 1.8 2000/06/12 21:55:40 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/mem_op.h b/include/pcmcia/mem_op.h index 38101ab10d73..d7f70599d0aa 100644 --- a/include/pcmcia/mem_op.h +++ b/include/pcmcia/mem_op.h @@ -1,5 +1,5 @@ /* - * mem_op.h 1.12 1999/10/25 20:23:17 + * mem_op.h 1.13 2000/06/12 21:55:40 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/memory.h b/include/pcmcia/memory.h index 5c0cdb69fe76..c87a3645f57b 100644 --- a/include/pcmcia/memory.h +++ b/include/pcmcia/memory.h @@ -1,5 +1,5 @@ /* - * memory.h 1.6 1999/10/25 20:23:17 + * memory.h 1.7 2000/06/12 21:55:40 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index b53657fadb7c..e00757ca446e 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -1,5 +1,5 @@ /* - * ss.h 1.26 2000/02/04 20:35:21 + * ss.h 1.28 2000/06/12 21:55:40 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the @@ -61,6 +61,7 @@ typedef struct socket_cap_t { #define SS_CAP_PAGE_REGS 0x0001 #define SS_CAP_VIRTUAL_BUS 0x0002 #define SS_CAP_MEM_ALIGN 0x0004 +#define SS_CAP_STATIC_MAP 0x0008 #define SS_CAP_PCCARD 0x4000 #define SS_CAP_CARDBUS 0x8000 diff --git a/include/pcmcia/version.h b/include/pcmcia/version.h index 4f6ffc70221c..70f3d8a48804 100644 --- a/include/pcmcia/version.h +++ b/include/pcmcia/version.h @@ -1,4 +1,4 @@ -/* version.h 1.83 2000/02/03 02:16:14 (David Hinds) */ +/* version.h 1.92 2000/07/21 18:26:56 (David Hinds) */ -#define CS_RELEASE "3.1.11" -#define CS_RELEASE_CODE 0x310b +#define CS_RELEASE "3.1.20" +#define CS_RELEASE_CODE 0x3115 diff --git a/init/main.c b/init/main.c index 049815fb29c5..ab9fd0876a60 100644 --- a/init/main.c +++ b/init/main.c @@ -584,7 +584,7 @@ asmlinkage void __init start_kernel(void) * make syscalls (and thus be locked). */ smp_init(); - kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); unlock_kernel(); current->need_resched = 1; cpu_idle(); diff --git a/kernel/exit.c b/kernel/exit.c index 580c021a5760..255446884efa 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -267,26 +267,6 @@ void exit_fs(struct task_struct *tsk) __exit_fs(tsk); } -static inline void __exit_sighand(struct task_struct *tsk) -{ - struct signal_struct * sig = tsk->sig; - - if (sig) { - spin_lock_irq(&tsk->sigmask_lock); - tsk->sig = NULL; - spin_unlock_irq(&tsk->sigmask_lock); - if (atomic_dec_and_test(&sig->count)) - kmem_cache_free(sigact_cachep, sig); - } - - flush_signals(tsk); -} - -void exit_sighand(struct task_struct *tsk) -{ - __exit_sighand(tsk); -} - /* * We can use these to temporarily drop into * "lazy TLB" mode and back. @@ -461,7 +441,7 @@ fake_volatile: __exit_mm(tsk); __exit_files(tsk); __exit_fs(tsk); - __exit_sighand(tsk); + exit_sighand(tsk); exit_thread(); tsk->state = TASK_ZOMBIE; tsk->exit_code = code; diff --git a/kernel/fork.c b/kernel/fork.c index 64dd0f995c20..8ef76f185afc 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -500,15 +500,21 @@ out_release: static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk) { - if (clone_flags & CLONE_SIGHAND) { + struct signal_struct *sig; + + if (clone_flags & CLONE_SIGNAL) { atomic_inc(¤t->sig->count); return 0; } - tsk->sig = kmem_cache_alloc(sigact_cachep, GFP_KERNEL); - if (!tsk->sig) + sig = kmem_cache_alloc(sigact_cachep, GFP_KERNEL); + tsk->sig = sig; + if (!sig) return -1; - spin_lock_init(&tsk->sig->siglock); - atomic_set(&tsk->sig->count, 1); + spin_lock_init(&sig->siglock); + atomic_set(&sig->count, 1); + + init_sigpending(&sig->pending); + memcpy(tsk->sig->action, current->sig->action, sizeof(tsk->sig->action)); return 0; } @@ -591,9 +597,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) spin_lock_init(&p->alloc_lock); p->sigpending = 0; - sigemptyset(&p->signal); - p->sigqueue = NULL; - p->sigqueue_tail = &p->sigqueue; + init_sigpending(&p->pending); p->it_real_value = p->it_virt_value = p->it_prof_value = 0; p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0; @@ -664,7 +668,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) p->tgid = retval; INIT_LIST_HEAD(&p->thread_group); write_lock_irq(&tasklist_lock); - if (clone_flags & CLONE_THREAD) { + if (clone_flags & CLONE_SIGNAL) { p->tgid = current->tgid; list_add(&p->thread_group, ¤t->thread_group); } diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 660d492f68ce..35c089c80409 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -55,9 +55,6 @@ extern int console_loglevel; extern void set_device_ro(kdev_t dev,int flag); -#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE) -extern long (*do_nfsservctl)(int, void *, void *); -#endif extern void *sys_call_table; @@ -265,10 +262,6 @@ EXPORT_SYMBOL(filemap_swapout); EXPORT_SYMBOL(filemap_sync); EXPORT_SYMBOL(lock_page); -#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE) -EXPORT_SYMBOL(do_nfsservctl); -#endif - /* device registration */ EXPORT_SYMBOL(register_chrdev); EXPORT_SYMBOL(unregister_chrdev); diff --git a/kernel/sched.c b/kernel/sched.c index 8b47b558a376..6ad8f4cab8e3 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -213,7 +213,9 @@ static inline int preemption_goodness(struct task_struct * prev, struct task_str * This function must be inline as anything that saves and restores * flags has to do so within the same register window on sparc (Anton) */ -static inline void reschedule_idle(struct task_struct * p, unsigned long flags) +static FASTCALL(void reschedule_idle(struct task_struct * p)); + +static void reschedule_idle(struct task_struct * p) { #ifdef CONFIG_SMP int this_cpu = smp_processor_id(); @@ -284,7 +286,6 @@ static inline void reschedule_idle(struct task_struct * p, unsigned long flags) goto preempt_now; } - spin_unlock_irqrestore(&runqueue_lock, flags); return; send_now_idle: @@ -296,12 +297,10 @@ send_now_idle: if ((tsk->processor != current->processor) && !tsk->need_resched) smp_send_reschedule(tsk->processor); tsk->need_resched = 1; - spin_unlock_irqrestore(&runqueue_lock, flags); return; preempt_now: tsk->need_resched = 1; - spin_unlock_irqrestore(&runqueue_lock, flags); /* * the APIC stuff can go outside of the lock because * it uses no task information, only CPU#. @@ -316,7 +315,6 @@ preempt_now: tsk = cpu_curr(this_cpu); if (preemption_goodness(tsk, p, this_cpu) > 1) tsk->need_resched = 1; - spin_unlock_irqrestore(&runqueue_lock, flags); #endif } @@ -365,9 +363,7 @@ inline void wake_up_process(struct task_struct * p) if (task_on_runqueue(p)) goto out; add_to_runqueue(p); - reschedule_idle(p, flags); // spin_unlocks runqueue - - return; + reschedule_idle(p); out: spin_unlock_irqrestore(&runqueue_lock, flags); } @@ -480,10 +476,9 @@ out_unlock: * current process as well.) */ running_again: - if (prev == idle_task(smp_processor_id())) - goto out_unlock; - reschedule_idle(prev, flags); // spin_unlocks runqueue - return; + if (prev != idle_task(smp_processor_id())) + reschedule_idle(prev); + goto out_unlock; #endif /* CONFIG_SMP */ } @@ -656,6 +651,9 @@ still_running_back: same_process: reacquire_kernel_lock(current); + if (current->need_resched) + goto tq_scheduler_back; + return; recalculate: @@ -1142,13 +1140,13 @@ static void show_task(struct task_struct * p) printk("\n"); { - struct signal_queue *q; + struct sigqueue *q; char s[sizeof(sigset_t)*2+1], b[sizeof(sigset_t)*2+1]; - render_sigset_t(&p->signal, s); + render_sigset_t(&p->pending.signal, s); render_sigset_t(&p->blocked, b); printk(" sig: %d %s %s :", signal_pending(p), s, b); - for (q = p->sigqueue; q ; q = q->next) + for (q = p->pending.head; q ; q = q->next) printk(" %d", q->info.si_signo); printk(" X\n"); } diff --git a/kernel/signal.c b/kernel/signal.c index 77a9b8eb2b3d..caa59d512711 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -28,52 +28,53 @@ #define SIG_SLAB_DEBUG 0 #endif -static kmem_cache_t *signal_queue_cachep; +static kmem_cache_t *sigqueue_cachep; atomic_t nr_queued_signals; int max_queued_signals = 1024; void __init signals_init(void) { - signal_queue_cachep = - kmem_cache_create("signal_queue", - sizeof(struct signal_queue), - __alignof__(struct signal_queue), + sigqueue_cachep = + kmem_cache_create("sigqueue", + sizeof(struct sigqueue), + __alignof__(struct sigqueue), SIG_SLAB_DEBUG, NULL, NULL); - if (!signal_queue_cachep) - panic("signals_init(): cannot create signal_queue SLAB cache"); + if (!sigqueue_cachep) + panic("signals_init(): cannot create sigueue SLAB cache"); } /* Given the mask, find the first available signal that should be serviced. */ static int -next_signal(sigset_t *signal, sigset_t *mask) +next_signal(struct task_struct *tsk, sigset_t *mask) { - unsigned long i, *s, *m, x; + unsigned long i, *s1, *s2, *m, x; int sig = 0; - s = signal->sig; + s1 = tsk->pending.signal.sig; + s2 = tsk->sig->pending.signal.sig; m = mask->sig; switch (_NSIG_WORDS) { default: - for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m) - if ((x = *s &~ *m) != 0) { + for (i = 0; i < _NSIG_WORDS; ++i, ++s1, ++s2, ++m) + if ((x = (*s1 | *s2) &~ *m) != 0) { sig = ffz(~x) + i*_NSIG_BPW + 1; break; } break; - case 2: if ((x = s[0] &~ m[0]) != 0) + case 2: if ((x = (s1[0] | s2[0]) &~ m[0]) != 0) sig = 1; - else if ((x = s[1] &~ m[1]) != 0) + else if ((x = (s1[1] | s2[1]) &~ m[1]) != 0) sig = _NSIG_BPW + 1; else break; sig += ffz(~x); break; - case 1: if ((x = *s &~ *m) != 0) + case 1: if ((x = (*s1 | *s2) &~ *m) != 0) sig = ffz(~x) + 1; break; } @@ -81,6 +82,23 @@ next_signal(sigset_t *signal, sigset_t *mask) return sig; } +static void flush_sigqueue(struct sigpending *queue) +{ + struct sigqueue *q, *n; + + sigemptyset(&queue->signal); + q = queue->head; + queue->head = NULL; + queue->tail = &queue->head; + + while (q) { + n = q->next; + kmem_cache_free(sigqueue_cachep, q); + atomic_dec(&nr_queued_signals); + q = n; + } +} + /* * Flush all pending signals for a task. */ @@ -88,20 +106,26 @@ next_signal(sigset_t *signal, sigset_t *mask) void flush_signals(struct task_struct *t) { - struct signal_queue *q, *n; - t->sigpending = 0; - sigemptyset(&t->signal); - q = t->sigqueue; - t->sigqueue = NULL; - t->sigqueue_tail = &t->sigqueue; + flush_sigqueue(&t->pending); + flush_sigqueue(&t->pending); +} - while (q) { - n = q->next; - kmem_cache_free(signal_queue_cachep, q); - atomic_dec(&nr_queued_signals); - q = n; +void exit_sighand(struct task_struct *tsk) +{ + struct signal_struct * sig = tsk->sig; + + spin_lock_irq(&tsk->sigmask_lock); + if (sig) { + tsk->sig = NULL; + if (atomic_dec_and_test(&sig->count)) { + flush_sigqueue(&sig->pending); + kmem_cache_free(sigact_cachep, sig); + } } + tsk->sigpending = 0; + flush_sigqueue(&tsk->pending); + spin_unlock_irq(&tsk->sigmask_lock); } /* @@ -148,6 +172,53 @@ unblock_all_signals(void) recalc_sigpending(current); } +static int collect_signal(int sig, struct sigpending *list, siginfo_t *info) +{ + if (sigismember(&list->signal, sig)) { + /* Collect the siginfo appropriate to this signal. */ + struct sigqueue *q, **pp; + pp = &list->head; + while ((q = *pp) != NULL) { + if (q->info.si_signo == sig) + goto found_it; + pp = &q->next; + } + + /* Ok, it wasn't in the queue. We must have + been out of queue space. So zero out the + info. */ + info->si_signo = sig; + info->si_errno = 0; + info->si_code = 0; + info->si_pid = 0; + info->si_uid = 0; + return 1; + +found_it: + if ((*pp = q->next) == NULL) + list->tail = pp; + + /* Copy the sigqueue information and free the queue entry */ + copy_siginfo(info, &q->info); + kmem_cache_free(sigqueue_cachep,q); + atomic_dec(&nr_queued_signals); + + /* Non-RT signals can exist multiple times.. */ + if (sig >= SIGRTMIN) { + while ((q = *pp) != NULL) { + if (q->info.si_signo == sig) + goto found_another; + pp = &q->next; + } + } + + sigdelset(&list->signal, sig); +found_another: + return 1; + } + return 0; +} + /* * Dequeue a signal and return the element to the caller, which is * expected to free it. @@ -165,7 +236,7 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid, signal_pending(current)); #endif - sig = next_signal(¤t->signal, mask); + sig = next_signal(current, mask); if (current->notifier) { sigset_t merged; int i; @@ -174,7 +245,7 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid, for (i = 0; i < _NSIG_WORDS; i++) merged.sig[i] = mask->sig[i] | current->notifier_mask->sig[i]; - altsig = next_signal(¤t->signal, &merged); + altsig = next_signal(current, &merged); if (sig != altsig) { if (!(current->notifier)(current->notifier_data)) { current->sigpending = 0; @@ -184,63 +255,14 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid, } if (sig) { - int reset = 1; - - /* Collect the siginfo appropriate to this signal. */ - struct signal_queue *q, **pp; - pp = ¤t->sigqueue; - q = current->sigqueue; - - /* Find the one we're interested in ... */ - for ( ; q ; pp = &q->next, q = q->next) - if (q->info.si_signo == sig) - break; - if (q) { - if ((*pp = q->next) == NULL) - current->sigqueue_tail = pp; - copy_siginfo(info, &q->info); - kmem_cache_free(signal_queue_cachep,q); - atomic_dec(&nr_queued_signals); - - /* Then see if this signal is still pending. - (Non rt signals may not be queued twice.) - */ - if (sig >= SIGRTMIN) - for (q = *pp; q; q = q->next) - if (q->info.si_signo == sig) { - reset = 0; - break; - } - - } else { - /* Ok, it wasn't in the queue. We must have - been out of queue space. So zero out the - info. */ - info->si_signo = sig; - info->si_errno = 0; - info->si_code = 0; - info->si_pid = 0; - info->si_uid = 0; - } - - if (reset) { - sigdelset(¤t->signal, sig); - recalc_sigpending(current); - } - + if (!collect_signal(sig, ¤t->pending, info)) + if (!collect_signal(sig, ¤t->sig->pending, info)) + sig = 0; + /* XXX: Once POSIX.1b timers are in, if si_code == SI_TIMER, we need to xchg out the timer overrun values. */ - } else { - /* XXX: Once CLONE_PID is in to join those "threads" that are - part of the same "process", look for signals sent to the - "process" as well. */ - - /* Sanity check... */ - if (mask == ¤t->blocked && signal_pending(current)) { - printk(KERN_CRIT "SIG: sigpending lied\n"); - current->sigpending = 0; - } } + recalc_sigpending(current); #if DEBUG_SIG printk(" %d -> %d\n", signal_pending(current), sig); @@ -249,43 +271,41 @@ printk(" %d -> %d\n", signal_pending(current), sig); return sig; } -/* - * Remove signal sig from queue and from t->signal. - * Returns 1 if sig was found in t->signal. - * - * All callers must be holding t->sigmask_lock. - */ -static int rm_sig_from_queue(int sig, struct task_struct *t) +static int rm_from_queue(int sig, struct sigpending *s) { - struct signal_queue *q, **pp; + struct sigqueue *q, **pp; - if (sig >= SIGRTMIN) { - printk(KERN_CRIT "SIG: rm_sig_from_queue() doesn't support rt signals\n"); + if (!sigismember(&s->signal, sig)) return 0; - } - if (!sigismember(&t->signal, sig)) - return 0; - - sigdelset(&t->signal, sig); + sigdelset(&s->signal, sig); - pp = &t->sigqueue; - q = t->sigqueue; + pp = &s->head; - /* Find the one we're interested in ... - It may appear only once. */ - for ( ; q ; pp = &q->next, q = q->next) - if (q->info.si_signo == sig) - break; - if (q) { - if ((*pp = q->next) == NULL) - t->sigqueue_tail = pp; - kmem_cache_free(signal_queue_cachep,q); - atomic_dec(&nr_queued_signals); + while ((q = *pp) != NULL) { + if (q->info.si_signo == sig) { + if ((*pp = q->next) == NULL) + s->tail = pp; + kmem_cache_free(sigqueue_cachep,q); + atomic_dec(&nr_queued_signals); + continue; + } + pp = &q->next; } return 1; } +/* + * Remove signal sig from t->pending. + * Returns 1 if sig was found. + * + * All callers must be holding t->sigmask_lock. + */ +static int rm_sig_from_queue(int sig, struct task_struct *t) +{ + return rm_from_queue(sig, &t->pending) | rm_from_queue(sig, &t->sig->pending); +} + /* * Bad permissions for sending the signal */ @@ -298,6 +318,46 @@ int bad_signal(int sig, struct siginfo *info, struct task_struct *t) && !capable(CAP_KILL); } +/* + * Signal type: + * < 0 : global action (kill - spread to all non-blocked threads) + * = 0 : ignored + * > 0 : wake up. + */ +static int signal_type(int sig, struct signal_struct *signals) +{ + unsigned long handler; + + if (!signals) + return 0; + + handler = (unsigned long) signals->action[sig-1].sa.sa_handler; + if (handler > 1) + return 1; + + /* "Ignore" handler.. Illogical, but that has an implicit handler for SIGCHLD */ + if (handler == 1) + return sig == SIGCHLD; + + /* Default handler. Normally lethal, but.. */ + switch (sig) { + + /* Ignored */ + case SIGCONT: case SIGWINCH: + case SIGCHLD: case SIGURG: + return 0; + + /* Implicit behaviour */ + case SIGTSTP: case SIGTTIN: case SIGTTOU: + return 1; + + /* Implicit actions (kill or do special stuff) */ + default: + return -1; + } +} + + /* * Determine whether a signal should be posted or not. * @@ -308,41 +368,18 @@ int bad_signal(int sig, struct siginfo *info, struct task_struct *t) */ static int ignored_signal(int sig, struct task_struct *t) { - struct signal_struct *signals; - struct k_sigaction *ka; - /* Don't ignore traced or blocked signals */ if ((t->ptrace & PT_PTRACED) || sigismember(&t->blocked, sig)) return 0; - - signals = t->sig; - if (!signals) - return 1; - - ka = &signals->action[sig-1]; - switch ((unsigned long) ka->sa.sa_handler) { - case (unsigned long) SIG_DFL: - if (sig == SIGCONT || - sig == SIGWINCH || - sig == SIGCHLD || - sig == SIGURG) - break; - return 0; - case (unsigned long) SIG_IGN: - if (sig != SIGCHLD) - break; - /* fallthrough */ - default: - return 0; - } - return 1; + return signal_type(sig, t->sig) == 0; } /* - * Handle TASK_STOPPED. - * Also, return true for the unblockable signals that we - * should deliver to all threads.. + * Handle TASK_STOPPED cases etc implicit behaviour + * of certain magical signals. + * + * SIGKILL gets spread out to every thread. */ static void handle_stop_signal(int sig, struct task_struct *t) { @@ -352,24 +389,23 @@ static void handle_stop_signal(int sig, struct task_struct *t) if (t->state == TASK_STOPPED) wake_up_process(t); t->exit_code = 0; - if (rm_sig_from_queue(SIGSTOP, t) || rm_sig_from_queue(SIGTSTP, t) || - rm_sig_from_queue(SIGTTOU, t) || rm_sig_from_queue(SIGTTIN, t)) - recalc_sigpending(t); + rm_sig_from_queue(SIGSTOP, t); + rm_sig_from_queue(SIGTSTP, t); + rm_sig_from_queue(SIGTTOU, t); + rm_sig_from_queue(SIGTTIN, t); break; case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: /* If we're stopping again, cancel SIGCONT */ - if (rm_sig_from_queue(SIGCONT, t)) - recalc_sigpending(t); + rm_sig_from_queue(SIGCONT, t); break; } - return 0; } -static int deliver_signal(int sig, struct siginfo *info, struct task_struct *t) +static int send_signal(int sig, struct siginfo *info, struct sigpending *signals) { - struct signal_queue * q = NULL; + struct sigqueue * q = NULL; /* Real-time signals must be queued if sent by sigqueue, or some other real-time mechanism. It is implementation @@ -380,14 +416,14 @@ static int deliver_signal(int sig, struct siginfo *info, struct task_struct *t) pass on the info struct. */ if (atomic_read(&nr_queued_signals) < max_queued_signals) { - q = kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC); + q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC); } if (q) { atomic_inc(&nr_queued_signals); q->next = NULL; - *t->sigqueue_tail = q; - t->sigqueue_tail = &q->next; + *signals->tail = q; + signals->tail = &q->next; switch ((unsigned long) info) { case 0: q->info.si_signo = sig; @@ -416,46 +452,57 @@ static int deliver_signal(int sig, struct siginfo *info, struct task_struct *t) return -EAGAIN; } - sigaddset(&t->signal, sig); - if (!sigismember(&t->blocked, sig)) { - t->sigpending = 1; -#ifdef CONFIG_SMP - /* - * If the task is running on a different CPU - * force a reschedule on the other CPU - note that - * the code below is a tad loose and might occasionally - * kick the wrong CPU if we catch the process in the - * process of changing - but no harm is done by that - * other than doing an extra (lightweight) IPI interrupt. - * - * note that we rely on the previous spin_lock to - * lock interrupts for us! No need to set need_resched - * since signal event passing goes through ->blocked. - */ - spin_lock(&runqueue_lock); - if (t->has_cpu && t->processor != smp_processor_id()) - smp_send_reschedule(t->processor); - spin_unlock(&runqueue_lock); -#endif /* CONFIG_SMP */ - } + sigaddset(&signals->signal, sig); return 0; } - /* - * Send a thread-group-wide signal. + * Tell a process that it has a new active signal.. * - * Rule: SIGSTOP and SIGKILL get delivered to _everybody_. + * NOTE! we rely on the previous spin_lock to + * lock interrupts for us! We can only be called with + * "sigmask_lock" held, and the local interrupt must + * have been disabled when that got aquired! * - * Others get delivered to the thread that doesn't have them - * blocked (just one such thread). + * No need to set need_resched since signal event passing + * goes through ->blocked + */ +static inline void signal_wake_up(struct task_struct *t) +{ + t->sigpending = 1; + + if (t->state & TASK_INTERRUPTIBLE) { + wake_up_process(t); + return; + } + +#ifdef CONFIG_SMP + /* + * If the task is running on a different CPU + * force a reschedule on the other CPU to make + * it notice the new signal quickly. + * + * The code below is a tad loose and might occasionally + * kick the wrong CPU if we catch the process in the + * process of changing - but no harm is done by that + * other than doing an extra (lightweight) IPI interrupt. + */ + spin_lock(&runqueue_lock); + if (t->has_cpu && t->processor != smp_processor_id()) + smp_send_reschedule(t->processor); + spin_unlock(&runqueue_lock); +#endif /* CONFIG_SMP */ +} + +/* + * Send a thread-group-wide signal. * - * If all threads have it blocked, it gets delievered to the - * thread group leader. + * Just add it to the shared signal queue. And + * make sure to inform everybody. */ static int send_tg_sig_info(int sig, struct siginfo *info, struct task_struct *p) { - int retval = 0; + int retval, type; struct task_struct *tsk; if (sig < 0 || sig > _NSIG) @@ -464,13 +511,24 @@ static int send_tg_sig_info(int sig, struct siginfo *info, struct task_struct *p if (bad_signal(sig, info, p)) return -EPERM; - if (!sig) + if (!sig || !p->sig) return 0; + /* Have we already delivered this non-queued signal? */ + if (sig < SIGRTMIN && sigismember(&p->sig->pending.signal, sig)) + return 0; + + /* Add the signal to the global queue */ + retval = send_signal(sig, info, &p->sig->pending); + if (retval < 0) + return retval; + + type = signal_type(sig, p->sig); + + /* Inform all threads about it.. */ tsk = p; do { unsigned long flags; - tsk = next_thread(tsk); /* Zombie? Ignore */ if (!tsk->sig) @@ -479,30 +537,35 @@ static int send_tg_sig_info(int sig, struct siginfo *info, struct task_struct *p spin_lock_irqsave(&tsk->sigmask_lock, flags); handle_stop_signal(sig, tsk); - /* Is the signal ignored by this thread? */ - if (ignored_signal(sig, tsk)) + /* Blocked? */ + if (sigismember(&tsk->blocked, sig)) goto next; - /* Have we already delivered this non-queued signal? */ - if (sig < SIGRTMIN && sigismember(&tsk->signal, sig)) + /* Is the signal ignored by this thread? */ + switch (type) { + case 0: goto next; - - /* Not blocked? Go, girl, go! */ - if (tsk == p || !sigismember(&tsk->blocked, sig)) { - retval = deliver_signal(sig, info, tsk); - - /* Signals other than SIGKILL and SIGSTOP have "once" semantics */ - if (sig != SIGKILL && sig != SIGSTOP) - tsk = p; + case -1: /* affects all threads? */ + sigaddset(&tsk->pending.signal, sig); } + + /* Go, girl, go! */ + signal_wake_up(tsk); next: spin_unlock_irqrestore(&tsk->sigmask_lock, flags); - if ((tsk->state & TASK_INTERRUPTIBLE) && signal_pending(tsk)) - wake_up_process(tsk); - } while (tsk != p); - return retval; + } while ((tsk = next_thread(tsk)) != p); + return 0; } +static int deliver_signal(int sig, struct siginfo *info, struct task_struct *t) +{ + int retval = send_signal(sig, info, &t->pending); + + if (!retval && !sigismember(&t->blocked, sig)) + signal_wake_up(t); + + return retval; +} int send_sig_info(int sig, struct siginfo *info, struct task_struct *t) @@ -542,7 +605,7 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig); /* Support queueing exactly one non-rt signal, so that we can get more detailed information about the cause of the signal. */ - if (sig < SIGRTMIN && sigismember(&t->signal, sig)) + if (sig < SIGRTMIN && sigismember(&t->pending.signal, sig)) goto out; ret = deliver_signal(sig, info, t); @@ -669,9 +732,11 @@ static int kill_tg_info(int sig, struct siginfo *info, pid_t pid) error = -ESRCH; if (p) { /* Is it the leader? Otherwise it degenerates into a per-thread thing */ - if (p->tgid == pid) + if (p->tgid == pid) { + spin_lock(&p->sig->siglock); error = send_tg_sig_info(sig, info, p); - else + spin_unlock(&p->sig->siglock); + } else error = send_sig_info(sig, info, p); } read_unlock(&tasklist_lock); @@ -921,7 +986,8 @@ sys_rt_sigpending(sigset_t *set, size_t sigsetsize) goto out; spin_lock_irq(¤t->sigmask_lock); - sigandsets(&pending, ¤t->blocked, ¤t->signal); + sigorsets(&pending, ¤t->pending.signal, ¤t->sig->pending.signal); + sigandsets(&pending, ¤t->blocked, &pending); spin_unlock_irq(¤t->sigmask_lock); error = -EFAULT; @@ -1032,7 +1098,7 @@ sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo) info.si_signo = sig; /* POSIX.1b doesn't mention process groups. */ - return kill_proc_info(sig, &info, pid); + return kill_tg_info(sig, &info, pid); } int @@ -1044,10 +1110,12 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) (act && (sig == SIGKILL || sig == SIGSTOP))) return -EINVAL; - spin_lock_irq(¤t->sigmask_lock); k = ¤t->sig->action[sig-1]; - if (oact) *oact = *k; + spin_lock(¤t->sig->siglock); + + if (oact) + *oact = *k; if (act) { *k = *act; @@ -1075,33 +1143,14 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) && (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH))) { - /* So dequeue any that might be pending. - XXX: process-wide signals? */ - if (sig >= SIGRTMIN && - sigismember(¤t->signal, sig)) { - struct signal_queue *q, **pp; - pp = ¤t->sigqueue; - q = current->sigqueue; - while (q) { - if (q->info.si_signo != sig) - pp = &q->next; - else { - if ((*pp = q->next) == NULL) - current->sigqueue_tail = pp; - kmem_cache_free(signal_queue_cachep, q); - atomic_dec(&nr_queued_signals); - } - q = *pp; - } - - } - sigdelset(¤t->signal, sig); - recalc_sigpending(current); + spin_lock_irq(¤t->sigmask_lock); + if (rm_sig_from_queue(sig, current)) + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); } } - spin_unlock_irq(¤t->sigmask_lock); - + spin_unlock(¤t->sig->siglock); return 0; } @@ -1228,7 +1277,7 @@ sys_sigpending(old_sigset_t *set) old_sigset_t pending; spin_lock_irq(¤t->sigmask_lock); - pending = current->blocked.sig[0] & current->signal.sig[0]; + pending = current->blocked.sig[0] & (current->pending.signal.sig[0] | current->sig->pending.signal.sig[0]); spin_unlock_irq(¤t->sigmask_lock); error = -EFAULT; diff --git a/mm/filemap.c b/mm/filemap.c index 9772254320d6..750421a5b520 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1074,6 +1074,13 @@ found_page: goto page_not_up_to_date; generic_file_readahead(reada_ok, filp, inode, page); page_ok: + /* If users can be writing to this page using arbitrary + * virtual addresses, take care about potential aliasing + * before reading the page on the kernel side. + */ + if (page->mapping->i_mmap_shared != NULL) + flush_dcache_page(page); + /* * Ok, we have the page, and it's up-to-date, so * now we can copy it to user space... diff --git a/mm/memory.c b/mm/memory.c index 07708bc2f4ab..0a23e5e1e778 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -924,33 +924,9 @@ static void partial_clear(struct vm_area_struct *vma, unsigned long address) memclear_highpage_flush(page, offset, PAGE_SIZE - offset); } -/* - * Handle all mappings that got truncated by a "truncate()" - * system call. - * - * NOTE! We have to be ready to update the memory sharing - * between the file and the memory map for a potential last - * incomplete page. Ugly, but necessary. - */ -void vmtruncate(struct inode * inode, loff_t offset) +static void vmtruncate_list(struct vm_area_struct *mpnt, + unsigned long pgoff, unsigned long partial) { - unsigned long partial, pgoff; - struct vm_area_struct * mpnt; - struct address_space *mapping = inode->i_mapping; - unsigned long limit; - - if (inode->i_size < offset) - goto do_expand; - inode->i_size = offset; - truncate_inode_pages(mapping, offset); - spin_lock(&mapping->i_shared_lock); - if (!mapping->i_mmap) - goto out_unlock; - - pgoff = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - partial = (unsigned long)offset & (PAGE_CACHE_SIZE - 1); - - mpnt = mapping->i_mmap; do { struct mm_struct *mm = mpnt->vm_mm; unsigned long start = mpnt->vm_start; @@ -983,6 +959,39 @@ void vmtruncate(struct inode * inode, loff_t offset) zap_page_range(mm, start, len); flush_tlb_range(mm, start, end); } while ((mpnt = mpnt->vm_next_share) != NULL); +} + + +/* + * Handle all mappings that got truncated by a "truncate()" + * system call. + * + * NOTE! We have to be ready to update the memory sharing + * between the file and the memory map for a potential last + * incomplete page. Ugly, but necessary. + */ +void vmtruncate(struct inode * inode, loff_t offset) +{ + unsigned long partial, pgoff; + struct address_space *mapping = inode->i_mapping; + unsigned long limit; + + if (inode->i_size < offset) + goto do_expand; + inode->i_size = offset; + truncate_inode_pages(mapping, offset); + spin_lock(&mapping->i_shared_lock); + if (!mapping->i_mmap && !mapping->i_mmap_shared) + goto out_unlock; + + pgoff = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + partial = (unsigned long)offset & (PAGE_CACHE_SIZE - 1); + + if (mapping->i_mmap != NULL) + vmtruncate_list(mapping->i_mmap, pgoff, partial); + if (mapping->i_mmap_shared != NULL) + vmtruncate_list(mapping->i_mmap_shared, pgoff, partial); + out_unlock: spin_unlock(&mapping->i_shared_lock); /* this should go into ->truncate */ @@ -1095,15 +1104,12 @@ static int do_swap_page(struct mm_struct * mm, */ static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma, pte_t *page_table, int write_access, unsigned long addr) { - int high = 0; struct page *page = NULL; pte_t entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot)); if (write_access) { page = alloc_page(GFP_HIGHUSER); if (!page) return -1; - if (PageHighMem(page)) - high = 1; clear_user_highpage(page, addr); entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))); mm->rss++; diff --git a/mm/mmap.c b/mm/mmap.c index 9667d19dbfab..9c002756304a 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -906,15 +906,21 @@ void insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vmp) if (file) { struct inode * inode = file->f_dentry->d_inode; struct address_space *mapping = inode->i_mapping; + struct vm_area_struct **head; + if (vmp->vm_flags & VM_DENYWRITE) atomic_dec(&inode->i_writecount); + + head = &mapping->i_mmap; + if (vmp->vm_flags & VM_SHARED) + head = &mapping->i_mmap_shared; /* insert vmp into inode's share list */ spin_lock(&mapping->i_shared_lock); - if((vmp->vm_next_share = mapping->i_mmap) != NULL) - mapping->i_mmap->vm_pprev_share = &vmp->vm_next_share; - mapping->i_mmap = vmp; - vmp->vm_pprev_share = &mapping->i_mmap; + if((vmp->vm_next_share = *head) != NULL) + (*head)->vm_pprev_share = &vmp->vm_next_share; + *head = vmp; + vmp->vm_pprev_share = head; spin_unlock(&mapping->i_shared_lock); } } diff --git a/mm/vmscan.c b/mm/vmscan.c index 95098e4d1be7..6e327e6524a0 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -646,7 +646,7 @@ static int __init kswapd_init(void) { printk("Starting kswapd v1.7\n"); swap_setup(); - kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); return 0; } diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 1c79056bba04..bc04ecc67be0 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -155,7 +155,10 @@ static ssize_t proc_mpc_read(struct file *file, char *buff, if (*pos >= length) length = 0; else { if ((count + *pos) > length) count = length - *pos; - copy_to_user(buff, (char *)page , count); + if (copy_to_user(buff, (char *)page , count)) { + free_page(page); + return -EFAULT; + } *pos += count; } @@ -198,7 +201,7 @@ static ssize_t proc_mpc_write(struct file *file, const char *buff, *ppos += incoming; page[incoming] = '\0'; - retval = parse_qos(buff, incoming); + retval = parse_qos(page, incoming); if (retval == 0) printk("mpoa: proc_mpc_write: could not parse '%s'\n", page); diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 57718cf00e1e..8723b1263737 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -100,6 +100,7 @@ * with only 6 digipeaters and sockaddr_ax25 in ax25_bind(), * ax25_connect() and ax25_sendmsg() * Joerg(DL1BKE) Added support for SO_BINDTODEVICE + * Arnaldo C. Melo s/suser/capable(CAP_NET_ADMIN)/, some more cleanups */ #include @@ -817,10 +818,7 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op if (put_user(length, optlen)) return -EFAULT; - if (copy_to_user(optval, valptr, length)) - return -EFAULT; - - return 0; + return copy_to_user(optval, valptr, length) ? -EFAULT : 0; } static int ax25_listen(struct socket *sock, int backlog) @@ -1070,7 +1068,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EINVAL; call = ax25_findbyuid(current->euid); - if (call == NULL && ax25_uid_policy && !suser()) + if (call == NULL && ax25_uid_policy && !capable(CAP_NET_ADMIN)) return -EACCES; if (call == NULL) @@ -1584,9 +1582,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); if (amount < 0) amount = 0; - if (put_user(amount, (int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (int *)arg); } case TIOCINQ: { @@ -1595,18 +1591,14 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */ if ((skb = skb_peek(&sk->receive_queue)) != NULL) amount = skb->len; - if (put_user(amount, (int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (int *)arg); } case SIOCGSTAMP: if (sk != NULL) { if (sk->stamp.tv_sec == 0) return -ENOENT; - if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) : -EFAULT : 0; } return -EINVAL; @@ -1621,7 +1613,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCAX25NOUID: { /* Set the default policy (default/bar) */ long amount; - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (get_user(amount, (long *)arg)) return -EFAULT; @@ -1634,12 +1626,12 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCADDRT: case SIOCDELRT: case SIOCAX25OPTRT: - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; return ax25_rt_ioctl(cmd, (void *)arg); case SIOCAX25CTLCON: - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; return ax25_ctl_ioctl(cmd, (void *)arg); @@ -1688,7 +1680,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCAX25ADDFWD: case SIOCAX25DELFWD: { struct ax25_fwd_struct ax25_fwd; - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user(&ax25_fwd, (void *)arg, sizeof(ax25_fwd))) return -EFAULT; diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 6d58c5d04459..32a7ab515712 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -38,6 +38,7 @@ * Joerg(DL1BKE) Moved BPQ Ethernet driver to separate device. * AX.25 035 Frederic(F1OAT) Support for pseudo-digipeating. * Jonathan(G4KLX) Support for packet forwarding. + * Arnaldo C. Melo s/suser/capable/ */ #include @@ -363,7 +364,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) return -EHOSTUNREACH; if ((call = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !suser()) + if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) return -EPERM; call = (ax25_address *)ax25->ax25_dev->dev->dev_addr; } diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index 1cce0dd6d352..eb226b14cdf7 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c @@ -78,7 +78,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) return -ENOENT; case SIOCAX25ADDUID: - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (ax25_findbyuid(sax->sax25_uid)) return -EEXIST; @@ -95,7 +95,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) return 0; case SIOCAX25DELUID: - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) { if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 5322b3a89af2..348c30fce6d5 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -32,6 +32,7 @@ * Patrick Caulfield: Fixes to delayed acceptance logic. * David S. Miller: New socket locking * Steve Whitehouse: Socket list hashing/locking + * Arnaldo C. Melo: use capable, not suser */ @@ -688,7 +689,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (dn_ntohs(saddr->sdn_nodeaddrl) && (dn_ntohs(saddr->sdn_nodeaddrl) != 2)) return -EINVAL; - if (saddr->sdn_objnum && !suser()) + if (saddr->sdn_objnum && !capable(CAP_NET_BIND_SERVICE)) return -EPERM; if (dn_ntohs(saddr->sdn_objnamel) > DN_MAXOBJL) @@ -698,7 +699,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EINVAL; if (saddr->sdn_flags & SDF_WILD) { - if (!suser()) + if (!capable(CAP_NET_BIND_SERVICE)) return -EPERM; } else { if (dn_ntohs(saddr->sdn_nodeaddrl)) { @@ -1101,7 +1102,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) #if 0 case SIOCSIFADDR: - if (!suser()) return -EPERM; + if (!capable(CAP_NET_ADMIN)) return -EPERM; if ((err = copy_from_user(devname, ioarg->devname, 5)) != 0) break; @@ -1143,7 +1144,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) #if 0 case SIOCSNETADDR: - if (!suser()) { + if (!capable(CAP_NET_ADMIN)) { err = -EPERM; break; } @@ -1174,7 +1175,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break; #endif case OSIOCSNETADDR: - if (!suser()) { + if (!capable(CAP_NET_ADMIN)) { err = -EPERM; break; } @@ -1189,8 +1190,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break; case OSIOCGNETADDR: - if ((err = put_user(decnet_address, (unsigned short *)arg)) != 0) - break; + err = put_user(decnet_address, (unsigned short *)arg); break; case SIOCGIFCONF: case SIOCGIFFLAGS: diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index cb9b3d11ed38..7a2a815ce4a8 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -641,17 +641,15 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void *arg) static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; - int err; int pid; switch(cmd) { case FIOSETOWN: case SIOCSPGRP: - err = get_user(pid, (int *) arg); - if (err) - return err; - if (current->pid != pid && current->pgrp != -pid && !suser()) + if (get_user(pid, (int *) arg)) + return -EFAULT; + if (current->pid != pid && current->pgrp != -pid && !capable(CAP_NET_ADMIN)) return -EPERM; sk->proc = pid; return(0); @@ -661,10 +659,7 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg case SIOCGSTAMP: if(sk->stamp.tv_sec==0) return -ENOENT; - err = -EFAULT; - if (!copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - err = 0; - return err; + return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0; case SIOCGIFFLAGS: case SIOCSIFFLAGS: case SIOCGIFCONF: diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index ef7fc36cbb1c..cf39195c39a8 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_minisocks.c,v 1.1 2000/08/09 11:59:04 davem Exp $ + * Version: $Id: tcp_minisocks.c,v 1.2 2000/08/28 04:32:52 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -742,7 +742,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, /* Back to base struct sock members. */ newsk->err = 0; newsk->priority = 0; - atomic_set(&newsk->refcnt, 1); + atomic_set(&newsk->refcnt, 2); #ifdef INET_REFCNT_DEBUG atomic_inc(&inet_sock_nr); #endif @@ -966,5 +966,6 @@ int tcp_child_process(struct sock *parent, struct sock *child, } bh_unlock_sock(child); + sock_put(child); return ret; } diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index d4e4802b9c2d..27d95703b750 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -30,6 +30,7 @@ * Jonathan(G4KLX) Removed hdrincl. * NET/ROM 007 Jonathan(G4KLX) New timer architecture. * Impmented Idle timer. + * Arnaldo C. Melo s/suser/capable/, micro cleanups */ #include @@ -437,10 +438,7 @@ static int nr_getsockopt(struct socket *sock, int level, int optname, if (put_user(len, optlen)) return -EFAULT; - if (copy_to_user(optval, &val, len)) - return -EFAULT; - - return 0; + return copy_to_user(optval, &val, len) ? -EFAULT : 0; } static int nr_listen(struct socket *sock, int backlog) @@ -616,7 +614,7 @@ full_sockaddr_ax25)) * Only the super user can set an arbitrary user callsign. */ if (addr->fsa_ax25.sax25_ndigis == 1) { - if (!suser()) + if (!capable(CAP_NET_BIND_SERVICE)) return -EACCES; sk->protinfo.nr->user_addr = addr->fsa_digipeater[0]; sk->protinfo.nr->source_addr = addr->fsa_ax25.sax25_call; @@ -624,7 +622,7 @@ full_sockaddr_ax25)) source = &addr->fsa_ax25.sax25_call; if ((user = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !suser()) + if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) return -EPERM; user = source; } @@ -680,7 +678,7 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, source = (ax25_address *)dev->dev_addr; if ((user = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !suser()) + if (ax25_uid_policy && !capable(CAP_NET_ADMIN)) return -EPERM; user = source; } @@ -1111,9 +1109,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); if (amount < 0) amount = 0; - if (put_user(amount, (int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (int *)arg); } case TIOCINQ: { @@ -1122,18 +1118,14 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */ if ((skb = skb_peek(&sk->receive_queue)) != NULL) amount = skb->len; - if (put_user(amount, (int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (int *)arg); } case SIOCGSTAMP: if (sk != NULL) { if (sk->stamp.tv_sec == 0) return -ENOENT; - if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0; } return -EINVAL; @@ -1152,7 +1144,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCADDRT: case SIOCDELRT: case SIOCNRDECOBS: - if (!suser()) return -EPERM; + if (!capable(CAP_NET_ADMIN)) return -EPERM; return nr_rt_ioctl(cmd, (void *)arg); default: diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 990431eb85f6..b7827f09fdc7 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -5,7 +5,7 @@ * * PACKET - implements raw packet sockets. * - * Version: $Id: af_packet.c,v 1.41 2000/08/10 01:21:14 davem Exp $ + * Version: $Id: af_packet.c,v 1.42 2000/08/29 03:44:56 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 1bf9f7ab633e..f61d9cd34df1 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -21,6 +21,7 @@ * Implemented idle timer. * Added use count to neighbour. * Tomi(OH2BNS) Fixed rose_getname(). + * Arnaldo C. Melo s/suser/capable/ + micro cleanups */ #include @@ -510,10 +511,7 @@ static int rose_getsockopt(struct socket *sock, int level, int optname, if (put_user(len, optlen)) return -EFAULT; - if (copy_to_user(optval, &val, len)) - return -EFAULT; - - return 0; + return copy_to_user(optval, &val, len) ? -EFAULT : 0; } static int rose_listen(struct socket *sock, int backlog) @@ -695,7 +693,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) source = &addr->srose_call; if ((user = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !suser()) + if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) return -EACCES; user = source; } @@ -1236,9 +1234,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); if (amount < 0) amount = 0; - if (put_user(amount, (unsigned int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (unsigned int *)arg); } case TIOCINQ: { @@ -1247,18 +1243,14 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */ if ((skb = skb_peek(&sk->receive_queue)) != NULL) amount = skb->len; - if (put_user(amount, (unsigned int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (unsigned int *)arg); } case SIOCGSTAMP: if (sk != NULL) { if (sk->stamp.tv_sec == 0) return -ENOENT; - if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0; } return -EINVAL; @@ -1284,9 +1276,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) struct rose_cause_struct rose_cause; rose_cause.cause = sk->protinfo.rose->cause; rose_cause.diagnostic = sk->protinfo.rose->diagnostic; - if (copy_to_user((void *)arg, &rose_cause, sizeof(struct rose_cause_struct))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &rose_cause, sizeof(struct rose_cause_struct)) ? -EFAULT : 0; } case SIOCRSSCAUSE: { @@ -1299,7 +1289,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } case SIOCRSSL2CALL: - if (!suser()) return -EPERM; + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) ax25_listen_release(&rose_callsign, NULL); if (copy_from_user(&rose_callsign, (void *)arg, sizeof(ax25_address))) @@ -1309,9 +1299,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return 0; case SIOCRSGL2CALL: - if (copy_to_user((void *)arg, &rose_callsign, sizeof(ax25_address))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &rose_callsign, sizeof(ax25_address)) ? -EFAULT : 0; case SIOCRSACCEPT: if (sk->protinfo.rose->state == ROSE_STATE_5) { diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index ebaaa7242bf8..79880595d7e9 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -20,6 +20,7 @@ * 2000-22-03 Daniela Squassoni Allowed disabling/enabling of * facilities negotiation and increased * the throughput upper limit. + * 2000-27-08 Arnaldo C. Melo s/suser/capable/ + micro cleanups */ #include @@ -402,10 +403,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, if (put_user(len, optlen)) return -EFAULT; - if (copy_to_user(optval, &val, len)) - return -EFAULT; - - return 0; + return copy_to_user(optval, &val, len) ? -EFAULT : 0; } static int x25_listen(struct socket *sock, int backlog) @@ -1067,9 +1065,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); if (amount < 0) amount = 0; - if (put_user(amount, (unsigned int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (unsigned int *)arg); } case TIOCINQ: { @@ -1078,18 +1074,14 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */ if ((skb = skb_peek(&sk->receive_queue)) != NULL) amount = skb->len; - if (put_user(amount, (unsigned int *)arg)) - return -EFAULT; - return 0; + return put_user(amount, (unsigned int *)arg); } case SIOCGSTAMP: if (sk != NULL) { if (sk->stamp.tv_sec == 0) return -ENOENT; - if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0; } return -EINVAL; @@ -1114,15 +1106,13 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return x25_subscr_ioctl(cmd, (void *)arg); case SIOCX25SSUBSCRIP: - if (!suser()) return -EPERM; + if (!capable(CAP_NET_ADMIN)) return -EPERM; return x25_subscr_ioctl(cmd, (void *)arg); case SIOCX25GFACILITIES: { struct x25_facilities facilities; facilities = sk->protinfo.x25->facilities; - if (copy_to_user((void *)arg, &facilities, sizeof(facilities))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &facilities, sizeof(facilities)) ? -EFAULT : 0; } case SIOCX25SFACILITIES: { @@ -1148,9 +1138,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCX25GCALLUSERDATA: { struct x25_calluserdata calluserdata; calluserdata = sk->protinfo.x25->calluserdata; - if (copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)) ? -EFAULT : 0; } case SIOCX25SCALLUSERDATA: { @@ -1166,9 +1154,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCX25GCAUSEDIAG: { struct x25_causediag causediag; causediag = sk->protinfo.x25->causediag; - if (copy_to_user((void *)arg, &causediag, sizeof(causediag))) - return -EFAULT; - return 0; + return copy_to_user((void *)arg, &causediag, sizeof(causediag)) ? -EFAULT : 0; } default: