From cef52a34bc46c618574413d61d05aab7bcd72b13 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:32:57 -0500 Subject: [PATCH] Import 2.3.99pre2-1 --- CREDITS | 7 + Documentation/Changes | 8 +- Documentation/Configure.help | 65 ++++- Documentation/DocBook/Makefile | 20 +- Documentation/DocBook/kernel-api.tmpl | 92 ++++++ Documentation/DocBook/videobook.tmpl | 2 +- Documentation/sysrq.txt | 36 ++- Makefile | 2 +- arch/alpha/kernel/alpha_ksyms.c | 3 + arch/alpha/kernel/time.c | 6 +- arch/i386/kernel/i386_ksyms.c | 3 + arch/i386/kernel/time.c | 22 +- arch/sparc/config.in | 4 +- arch/sparc/kernel/sparc_ksyms.c | 6 +- arch/sparc/kernel/sys_solaris.c | 1 + arch/sparc/kernel/sys_sunos.c | 32 +-- arch/sparc/kernel/systbls.S | 6 +- arch/sparc64/config.in | 26 +- arch/sparc64/defconfig | 73 ++--- arch/sparc64/kernel/ioctl32.c | 425 +++++++++++++++++++++++++++- arch/sparc64/kernel/sparc64_ksyms.c | 9 +- arch/sparc64/kernel/sys_sparc32.c | 95 +++---- arch/sparc64/kernel/sys_sunos32.c | 29 +- arch/sparc64/kernel/systbls.S | 10 +- arch/sparc64/lib/blockops.S | 85 +++++- arch/sparc64/mm/fault.c | 4 +- drivers/block/floppy.c | 52 ---- drivers/block/ll_rw_blk.c | 4 +- drivers/block/lvm.c | 8 +- drivers/block/nbd.c | 2 +- drivers/cdrom/cm206.c | 2 +- drivers/char/amiserial.c | 2 +- drivers/char/drm/bufs.c | 1 + drivers/char/drm/drmP.h | 1 - drivers/char/drm/gamma_drv.c | 1 + drivers/char/drm/tdfx_drv.c | 1 + drivers/char/pc_keyb.c | 5 +- drivers/char/rtc.c | 9 +- drivers/net/shaper.c | 1 + drivers/net/sunhme.c | 4 +- drivers/net/tokenring/olympic.c | 37 ++- drivers/net/tokenring/olympic.h | 2 +- drivers/parport/ChangeLog | 5 + drivers/parport/parport_pc.c | 5 +- drivers/sbus/sbus.c | 5 +- drivers/sound/bin2hex.c | 2 +- drivers/usb/Config.in | 6 +- drivers/usb/dc2xx.c | 23 +- drivers/usb/dsbr100.c | 6 - drivers/usb/usb-storage.c | 514 ++++++++++++++++++++-------------- drivers/usb/usb-uhci.c | 1 + fs/buffer.c | 12 +- fs/smbfs/inode.c | 2 +- fs/super.c | 63 +++-- include/asm-alpha/page.h | 4 + include/asm-arm/page.h | 3 + include/asm-i386/hw_irq.h | 25 +- include/asm-i386/page.h | 3 + include/asm-ia64/page.h | 3 + include/asm-m68k/page.h | 3 + include/asm-mips/page.h | 2 + include/asm-mips64/page.h | 2 + include/asm-ppc/page.h | 2 + include/asm-sh/page.h | 2 + include/asm-sparc/mman.h | 9 +- include/asm-sparc/page.h | 13 +- include/asm-sparc64/mman.h | 9 +- include/asm-sparc64/page.h | 4 +- include/asm-sparc64/parport.h | 3 +- include/linux/highmem.h | 20 ++ include/linux/kernel.h | 2 + include/linux/pci.h | 4 +- ipc/shm.c | 104 +++++-- kernel/ksyms.c | 1 + mm/filemap.c | 2 +- mm/memory.c | 6 +- 76 files changed, 1463 insertions(+), 610 deletions(-) create mode 100644 Documentation/DocBook/kernel-api.tmpl diff --git a/CREDITS b/CREDITS index b98bae810..612d97d27 100644 --- a/CREDITS +++ b/CREDITS @@ -2248,6 +2248,13 @@ S: 22 Irvington Cres. S: Willowdale, Ontario S: Canada M2N 2Z1 +N: Adam Sulmicki +E: adam@cfar.umd.edu +W: http://www.eax.com +D: core networking fixes +D: patch-kernel enhancements +D: misc kernel fixes and updates + N: Adrian Sun E: asun@cobaltnet.com D: hfs support diff --git a/Documentation/Changes b/Documentation/Changes index 9be04dcd6..bf650d417 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -62,7 +62,7 @@ running, the suggested command should tell you. - Bash 1.14.7 ; bash -version - Ncpfs 2.2.0 ; ncpmount -v - Pcmcia-cs 3.1.2 ; cardmgr -V -- PPP 2.3.9 ; pppd --version +- PPP 2.3.11 ; pppd --version - Util-linux 2.9i ; chsh -v - isdn4k-utils v3.1beta7 ; isdnctrl 2>&1|grep version @@ -390,7 +390,7 @@ PPP Due to changes in the PPP driver and routing code, those of you using PPP networking will need to upgrade your pppd to at least -version 2.3.9. See ftp://cs.anu.edu.au/pub/software/ppp/ for newest +version 2.3.11. See ftp://cs.anu.edu.au/pub/software/ppp/ for newest versions. You must make sure that the special device file /dev/ppp exists. @@ -715,8 +715,8 @@ ftp://metalab.unc.edu/pub/Linux/system/serial/setserial-2.15.tar.gz PPP === -The 2.3.9 release: -ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.9.tar.gz +The 2.3.11 release: +ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.11.tar.gz IP Chains ========= diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 64bdd50f2..98dcf4d09 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -320,6 +320,24 @@ CONFIG_BLK_DEV_NBD If unsure, say N. +ATA/IDE/MFM/RLL support +CONFIG_IDE + If you say Y here, your kernel will be able to manage low cost mass storage + units such as ATA,IDE and ATAPI units. + ATA is. + Integrated Disk Electronics (IDE) is a subset of the ATA interface. Quite a + number of disks use IDE interface. State of the art disks use SCSI + interface. + ATAPI is a protocol used by IDE tape and CDROM drives, similar in many + respects to the SCSI protocol. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called ide.o. + + If unsure, say Y. + Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support CONFIG_BLK_DEV_IDE If you say Y here, you will use the full-featured IDE driver to @@ -5793,6 +5811,26 @@ CONFIG_NETDEVICES Guide", to be found in ftp://metalab.unc.edu/pub/Linux/docs/LDP . If unsure, say Y. +Bonding driver support +CONFIG_BONDING + Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet + Channels together. This is called 'Etherchannel' by Cisco, 'Trunking' + by Sun, and 'Bonding' in Linux. + + If you have two ethernet connections to some other computer, you can + make them behave like one double speed connection using this driver. + Naturally, this has to be supported at the other end as well, either + with a similar Bonding Linux driver, a Cisco 5500 switch or a + SunTrunking SunSoft driver. + + This is similar to the EQL driver, but it merge etherner segments instead + of serial lines. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called bonding.o. + Dummy net driver support CONFIG_DUMMY This is essentially a bit-bucket device (i.e. traffic you send to @@ -7085,11 +7123,12 @@ CONFIG_NE2K_PCI module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. -PCI DM9102 support +PCI DM9102(A)/DM9132/DM9801 support CONFIG_DM9102 This driver is for DM9102 compatible PCI cards from Davicom - (http://www.davicom.com.tw) - If you have a PCI DM9102 network (Ethernet) card, say Y. + (http://www.davicom.com.tw) including models DM9132 & DM9801. + If you have a PCI DM9102, DM9132 or DM9801 network (Ethernet) + card, say Y. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -8221,6 +8260,14 @@ CONFIG_SKFP say M here and read Documentation/modules.txt. This is recommended. The module will be called skfp.o. +Linux telephony support +CONFIG_PHONE + This option enable the kernel to manage telephony cards. + + There is very few supported cards at this moment. + + If unsure, say N. + HIgh Performance Parallel Interface support (EXPERIMENTAL) CONFIG_HIPPI HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and @@ -9454,7 +9501,7 @@ CONFIG_ROMFS_FS answer N. QNX4 file system support (read only) (EXPERIMENTAL) -CONFIG_QNX4FS_FS +CONFIG_QNX4FS_FS This is the file system used by the operating system QNX 4. Say Y if you intend to mount QNX hard disks or floppies. Unless you say Y to "QNX4FS write support" below, you will only be able to read @@ -11077,6 +11124,16 @@ CONFIG_APPLICOM If unsure, say N. +Power Management support +CONFIG_PM + This enable the kernel to lower the requested computer power by making some + devices enter in lower power levels (standy, sleep, ... modes). + Basically, this let you save power. + Two majors interfaces exist between the hardware and the OS, the older + Advanced Power Management (APM) and the newer Advanced Configuration and + Power Interface (ACPI). + Both are supported by the Linux Kernel. + Enter S1 for sleep (EXPERIMENTAL) CONFIG_ACPI_S1_SLEEP This enable ACPI compliant devices to enter level 1 of ACPI saving diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 6bc727e43..adc131d1b 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -1,4 +1,4 @@ -BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml +BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml kernel-api.sgml books: docproc $(BOOKS) @@ -10,7 +10,7 @@ wanbook.sgml: wanbook.tmpl wanbook.sgml z8530book.sgml: z8530book.tmpl - $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/net/wan/syncppp.c \ + $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/net/wan/z85230.c \ z8530book.sgml mcabook.sgml: mcabook.tmpl @@ -21,9 +21,23 @@ videobook.sgml: videobook.tmpl $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/char/videodev.c \ videobook.sgml +kernel-api.sgml: kernel-api.tmpl + $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/char/videodev.c \ + $(TOPDIR)/arch/i386/kernel/mca.c \ + $(TOPDIR)/arch/i386/kernel/mtrr.c \ + $(TOPDIR)/drivers/char/misc.c \ + $(TOPDIR)/drivers/char/serial.c \ + $(TOPDIR)/drivers/char/videodev.c \ + $(TOPDIR)/drivers/sound/sound_core.c \ + $(TOPDIR)/drivers/sound/sound_firmware.c \ + $(TOPDIR)/drivers/net/wan/syncppp.c \ + $(TOPDIR)/drivers/net/wan/z85230.c \ + $(TOPDIR)/kernel/pm.c \ + kernel-api.sgml + clean: rm -f core *~ - rm -r $(BOOKS) + rm -f $BOOKS include $(TOPDIR)/Rules.make diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl new file mode 100644 index 000000000..96dd9ecc0 --- /dev/null +++ b/Documentation/DocBook/kernel-api.tmpl @@ -0,0 +1,92 @@ + + + + The Linux Kernel API + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + + + + + + Interrupt Handling +!Iarch/i386/kernel/irq.c + + + MTRR Handling +!Earch/i386/kernel/mtrr.c + + + + Power Management +!Ekernel/pm.c + + + + Miscellaneous Device +!Edrivers/char/misc.c + + + + Video4Linux +!Edrivers/char/videodev.c + + + + Sound Devices +!Edrivers/sound/sound_core.c +!Idrivers/sound/sound_firmware.c + + + + MCA Architecture + MCA Device Functions +!Earch/i386/kernel/mca.c + + MCA Bus DMA +!Iinclude/asm-i386/mca_dma.h + + + + + Synchronous PPP +!Edrivers/net/wan/syncppp.c + + + + 16x50 UART Driver +!Edrivers/char/serial.c + + + + Z85230 Support Library +!Edrivers/net/wan/z85230.c + + + diff --git a/Documentation/DocBook/videobook.tmpl b/Documentation/DocBook/videobook.tmpl index c152abf31..597413bf9 100644 --- a/Documentation/DocBook/videobook.tmpl +++ b/Documentation/DocBook/videobook.tmpl @@ -1642,7 +1642,7 @@ static struct video_buffer capture_fb; - API Deficiences + API Deficiencies The existing API poorly reflects compression capable devices. There diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index c17774865..49faf2dab 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -1,6 +1,7 @@ - MAGIC SYSRQ KEY DOCUMENTATION v1.2 + + MAGIC SYSRQ KEY DOCUMENTATION v1.31 ------------------------------------ - [Sat May 16 01:09:21 EDT 1998] + [Mon Mar 13 21:45:48 EST 2000] * What is the magic SysRQ key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -11,7 +12,10 @@ regardless of whatever else it is doing, unless it is completely locked up. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when configuring the kernel. This option is only available in 2.1.x or later -kernels. +kernels. Once you boot the new kernel, you need to enable it manually +using following command: + + echo "1" > /proc/sys/kernel/sysrq * How do I use the magic SysRQ key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -28,7 +32,8 @@ On other - If you know of the key combos for other architectures, please ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'r' - Turns off keyboard raw mode and sets it to XLATE. -'k' - Kills all programs on the current virtual console. +'k' - Secure Access Key (SAK) Kills all programs on the current virtual + console. NOTE: See important comments below in SAK section. 'b' - Will immediately reboot the system without syncing or unmounting your disks. @@ -58,12 +63,23 @@ On other - If you know of the key combos for other architectures, please 'l' - Send a SIGKILL to all processes, INCLUDING init. (Your system will be non-functional after this.) +'h' - Will display help ( actually any other key than those listed + above will display help. but 'h' is easy to remember :-) + * Okay, so what can I use them for? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Well, un'R'aw is very handy when your X server or a svgalib program crashes. -sa'K' (system attention key) is useful when you want to exit a program -that will not let you switch consoles. (For example, X or a svgalib program.) +sa'K' (Secure Access Key) is usefull when you want to be sure there are no +trojan program is running at console and which could grab your password +when you would try to login. It will kill all programs on given console +and thus letting you make sure that the login prompt you see is actually +the one from init, not some trojan program. +IMPORTANT:In its true form it is not a true SAK like the one in :IMPORTANT +IMPORTATN:c2 compliant systems, and it should be mistook as such. :IMPORTANT + It seems other find it usefull as (System Attention Key) which is +useful when you want to exit a program that will not let you switch consoles. +(For example, X or a svgalib program.) re'B'oot is good when you're unable to shut down. But you should also 'S'ync and 'U'mount first. @@ -108,6 +124,10 @@ you exit 'showkey' by not typing anything for ten seconds. * I have more questions, who can I ask? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You may feel free to send email to myrdraal@deathsdoor.com, and I will -respond as soon as possible. If that email address does not work, use -myrdraal@jackalz.dyn.ml.org. +respond as soon as possible. -Myrdraal + +* Credits +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Written by Mydraal +Updated by Adam Sulmicki diff --git a/Makefile b/Makefile index c8bf2bcd3..aef535ce2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 3 SUBLEVEL = 99 -EXTRAVERSION = -pre1 +EXTRAVERSION = -pre2 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 25d9583dd..4e8236c34 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -37,6 +37,7 @@ extern struct hwrpb_struct *hwrpb; extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); extern spinlock_t kernel_flag; +extern spinlock_t rtc_lock; /* these are C runtime functions with special calling conventions: */ extern void __divl (void); @@ -202,6 +203,8 @@ EXPORT_SYMBOL(__local_bh_count); EXPORT_SYMBOL(__local_irq_count); #endif /* __SMP__ */ +EXPORT_SYMBOL(rtc_lock); + /* * The following are special because they're not called * explicitly (the C compiler or assembler generates them in diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index 291682e33..6119ea371 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -48,6 +48,7 @@ extern volatile unsigned long lost_ticks; /* kernel/sched.c */ static int set_rtc_mmss(unsigned long); +spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; /* * Shift amount by which scaled_ticks_per_cycle is scaled. Shifting @@ -163,7 +164,7 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon, } void -common_init_rtc() +common_init_rtc(void) { unsigned char x; @@ -406,6 +407,8 @@ set_rtc_mmss(unsigned long nowtime) int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; + /* irq are locally disabled here */ + spin_lock(&rtc_lock); /* Tell the clock it's being set */ save_control = CMOS_READ(RTC_CONTROL); CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); @@ -455,6 +458,7 @@ set_rtc_mmss(unsigned long nowtime) */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + spin_unlock(&rtc_lock); return retval; } diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index e21c33b6f..5327f24a4 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -25,6 +25,7 @@ extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(elf_fpregset_t *); +extern spinlock_t rtc_lock; #ifdef CONFIG_SMP extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); @@ -131,3 +132,5 @@ EXPORT_SYMBOL(screen_info); EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(irq_stat); + +EXPORT_SYMBOL(rtc_lock); diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index b4a7753b8..bcec04401 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -79,6 +79,9 @@ static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */ unsigned long fast_gettimeoffset_quotient=0; extern rwlock_t xtime_lock; +extern volatile unsigned long lost_ticks; + +spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; static inline unsigned long do_fast_gettimeoffset(void) { @@ -113,6 +116,8 @@ static inline unsigned long do_fast_gettimeoffset(void) #ifndef CONFIG_X86_TSC +spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED; + /* This function must be called with interrupts disabled * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs * @@ -157,6 +162,8 @@ static unsigned long do_slow_gettimeoffset(void) */ unsigned long jiffies_t; + /* gets recalled with irq locally disabled */ + spin_lock(&i8253_lock); /* timer count may underflow right here */ outb_p(0x00, 0x43); /* latch the count ASAP */ @@ -215,6 +222,7 @@ static unsigned long do_slow_gettimeoffset(void) } } else jiffies_p = jiffies_t; + spin_unlock(&i8253_lock); count_p = count; @@ -238,7 +246,6 @@ static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; */ void do_gettimeofday(struct timeval *tv) { - extern volatile unsigned long lost_ticks; unsigned long flags; unsigned long usec, sec; @@ -272,6 +279,7 @@ void do_settimeofday(struct timeval *tv) * would have done, and then undo it! */ tv->tv_usec -= do_gettimeoffset(); + tv->tv_usec -= lost_ticks * (1000000 / HZ); while (tv->tv_usec < 0) { tv->tv_usec += 1000000; @@ -302,6 +310,8 @@ static int set_rtc_mmss(unsigned long nowtime) int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; + /* gets recalled with irq locally disabled */ + spin_lock(&rtc_lock); save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); @@ -347,6 +357,7 @@ static int set_rtc_mmss(unsigned long nowtime) */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + spin_unlock(&rtc_lock); return retval; } @@ -448,10 +459,19 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) rdtscl(last_tsc_low); +#if 0 /* + * SUBTLE: this is not necessary from here because it's implicit in the + * write xtime_lock. + */ + spin_lock(&i8253_lock); +#endif outb_p(0x00, 0x43); /* latch the count ASAP */ count = inb_p(0x40); /* read the latched count */ count |= inb(0x40) << 8; +#if 0 + spin_unlock(&i8253_lock); +#endif count = ((LATCH-1) - count) * TICK_SIZE; delay_at_last_interrupt = (count + LATCH/2) / LATCH; diff --git a/arch/sparc/config.in b/arch/sparc/config.in index adb0ebe4c..21f47fd59 100644 --- a/arch/sparc/config.in +++ b/arch/sparc/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.88 2000/03/13 03:40:27 davem Exp $ +# $Id: config.in,v 1.89 2000/03/14 07:31:19 jj Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -74,7 +74,7 @@ fi endmenu mainmenu_option next_comment -comment 'Floppy and other block devices' +comment 'Block devices' bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index e0bb41045..3ca74e26d 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.94 2000/02/28 04:00:53 anton Exp $ +/* $Id: sparc_ksyms.c,v 1.95 2000/03/14 08:29:26 davem Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -85,10 +85,10 @@ extern int __sparc_dot_ ## sym (int) __asm__("." #sym); \ __EXPORT_SYMBOL(__sparc_dot_ ## sym, "." #sym) #define EXPORT_SYMBOL_PRIVATE(sym) \ -extern int __sparc_priv_ ## sym (int) __asm__("__" ## #sym); \ +extern int __sparc_priv_ ## sym (int) __asm__("__" #sym); \ const struct module_symbol __export_priv_##sym \ __attribute__((section("__ksymtab"))) = \ -{ (unsigned long) &__sparc_priv_ ## sym, "__" ## #sym } +{ (unsigned long) &__sparc_priv_ ## sym, "__" #sym } /* used by various drivers */ EXPORT_SYMBOL(sparc_cpu_model); diff --git a/arch/sparc/kernel/sys_solaris.c b/arch/sparc/kernel/sys_solaris.c index 8a9d54913..eb79c344c 100644 --- a/arch/sparc/kernel/sys_solaris.c +++ b/arch/sparc/kernel/sys_solaris.c @@ -14,6 +14,7 @@ #include #include #include +#include /* CHECKME: this stuff looks rather bogus */ asmlinkage int diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index 262f6afdd..0a8a5827c 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.115 2000/03/13 21:57:23 davem Exp $ +/* $Id: sys_sunos.c,v 1.117 2000/03/15 02:43:32 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -267,35 +267,6 @@ asmlinkage void sunos_vadvise(unsigned long strategy) unlock_kernel(); } -/* Same as vadvise, and just as bogus, but for a range of virtual - * process address space. - */ -#define MADV_NORMAL 0 /* Nothing special... */ -#define MADV_RANDOM 1 /* I am emacs... */ -#define MADV_SEQUENTIAL 2 /* I am researcher code... */ -#define MADV_WILLNEED 3 /* Pages in this range will be needed */ -#define MADV_DONTNEED 4 /* Pages in this range won't be needed */ - -static char *mstrings[] = { - "MADV_NORMAL", - "MADV_RANDOM", - "MADV_SEQUENTIAL", - "MADV_WILLNEED", - "MADV_DONTNEED", -}; - -asmlinkage void sunos_madvise(unsigned long address, unsigned long len, - unsigned long strategy) -{ - /* I wanna see who uses this... */ - lock_kernel(); - printk("%s: Advises us to use %s paging strategy for addr<%08lx> len<%08lx>\n", - current->comm, - strategy <= 4 ? mstrings[strategy] : "BOGUS", - address, len); - unlock_kernel(); -} - /* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE * resource limit and is for backwards compatibility with older sunos * revs. @@ -733,7 +704,6 @@ static int get_default (int value, int def_value) asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) { - int ret = -ENODEV; int server_fd; char *the_name; struct nfs_mount_data linux_nfs_mount; diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index 42c072164..431f03daf 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.95 2000/03/13 21:57:23 davem Exp $ +/* $Id: systbls.S,v 1.96 2000/03/15 02:43:32 davem Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -33,7 +33,7 @@ sys_call_table: /*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize /*65*/ .long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_geteuid /*70*/ .long sys_getegid, sys_mmap, sys_setreuid, sys_munmap, sys_mprotect -/*75*/ .long sys_nis_syscall, sys_vhangup, sys_truncate64, sys_mincore, sys_getgroups16 +/*75*/ .long sys_madvise, sys_vhangup, sys_truncate64, sys_mincore, sys_getgroups16 /*80*/ .long sys_setgroups16, sys_getpgrp, sys_setgroups, sys_setitimer, sys_ftruncate64 /*85*/ .long sys_swapon, sys_getitimer, sys_setuid, sys_sethostname, sys_setgid /*90*/ .long sys_dup2, sys_setfsuid, sys_fcntl, sys_select, sys_setfsgid @@ -103,7 +103,7 @@ sunos_sys_table: .long sys_msync, sys_vfork, sunos_nosys .long sunos_nosys, sunos_sbrk, sunos_sstk .long sunos_mmap, sunos_vadvise, sys_munmap - .long sys_mprotect, sunos_madvise, sys_vhangup + .long sys_mprotect, sys_madvise, sys_vhangup .long sunos_nosys, sys_mincore, sys_getgroups16 .long sys_setgroups16, sys_getpgrp, sunos_setpgrp .long sys_setitimer, sunos_nosys, sys_swapon diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in index a1fb222c1..fefd4e71a 100644 --- a/arch/sparc64/config.in +++ b/arch/sparc64/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.101 2000/03/13 05:49:55 jj Exp $ +# $Id: config.in,v 1.102 2000/03/14 07:31:35 jj Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -32,16 +32,6 @@ define_bool CONFIG_SUN_IO y bool 'PCI support' CONFIG_PCI source drivers/pci/Config.in -mainmenu_option next_comment -comment 'Console drivers' -bool 'PROM console' CONFIG_PROM_CONSOLE -bool 'Support Frame buffer devices' CONFIG_FB -source drivers/video/Config.in -endmenu - -source drivers/sbus/char/Config.in -source drivers/sbus/audio/Config.in - tristate 'Openprom tree appears in /proc/openprom' CONFIG_SUN_OPENPROMFS bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC @@ -78,7 +68,17 @@ fi endmenu mainmenu_option next_comment -comment 'Floppy, IDE, and other block devices' +comment 'Console drivers' +bool 'PROM console' CONFIG_PROM_CONSOLE +bool 'Support Frame buffer devices' CONFIG_FB +source drivers/video/Config.in +endmenu + +source drivers/sbus/char/Config.in +source drivers/sbus/audio/Config.in + +mainmenu_option next_comment +comment 'Block devices' bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD @@ -98,6 +98,8 @@ fi tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP tristate 'Network block device support' CONFIG_BLK_DEV_NBD +endmenu + if [ "$CONFIG_NET" = "y" ]; then source net/Config.in fi diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index db85cfe1e..d3656a632 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -26,6 +26,42 @@ CONFIG_SUN_AUXIO=y CONFIG_SUN_IO=y CONFIG_PCI=y CONFIG_PCI_NAMES=y +CONFIG_SUN_OPENPROMFS=m +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_KCORE_ELF=y +CONFIG_SPARC32_COMPAT=y +CONFIG_BINFMT_ELF32=y +# CONFIG_BINFMT_AOUT32 is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +# CONFIG_SUNOS_EMUL is not set +CONFIG_SOLARIS_EMUL=m + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_FIFO=y +# CONFIG_PARPORT_PC_SUPERIO is not set +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set +# CONFIG_PARPORT_SUNBPP is not set +# CONFIG_PARPORT_OTHER is not set +CONFIG_PARPORT_1284=y +CONFIG_PRINTER=m +CONFIG_ENVCTRL=m + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y # # Console drivers @@ -84,44 +120,9 @@ CONFIG_SPARCAUDIO=y CONFIG_SPARCAUDIO_CS4231=y # CONFIG_SPARCAUDIO_DBRI is not set # CONFIG_SPARCAUDIO_DUMMY is not set -CONFIG_SUN_OPENPROMFS=m -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -CONFIG_SPARC32_COMPAT=y -CONFIG_BINFMT_ELF32=y -# CONFIG_BINFMT_AOUT32 is not set -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -# CONFIG_SUNOS_EMUL is not set -CONFIG_SOLARIS_EMUL=m - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_FIFO=y -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y -CONFIG_PRINTER=m -CONFIG_ENVCTRL=m - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y # -# Floppy, IDE, and other block devices +# Block devices # CONFIG_BLK_DEV_FD=y # CONFIG_BLK_DEV_MD is not set diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index d3a3814a8..0ba88adf6 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.82 2000/03/13 21:57:27 davem Exp $ +/* $Id: ioctl32.c,v 1.83 2000/03/14 07:31:25 jj Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -8,6 +8,7 @@ * ioctls. */ +#include #include #include #include @@ -44,6 +45,14 @@ #include #include #include +#include +#include +#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) +/* Ugh. This header really is not clean */ +#define min min +#define max max +#include +#endif /* LVM */ #include /* Ugly hack. */ @@ -1980,6 +1989,353 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) return -EINVAL; } +#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) +/* Ugh, LVM. Pitty it was not cleaned up before accepted :((. */ +typedef struct { + uint8_t vg_name[NAME_LEN]; + uint32_t vg_number; + uint32_t vg_access; + uint32_t vg_status; + uint32_t lv_max; + uint32_t lv_cur; + uint32_t lv_open; + uint32_t pv_max; + uint32_t pv_cur; + uint32_t pv_act; + uint32_t dummy; + uint32_t vgda; + uint32_t pe_size; + uint32_t pe_total; + uint32_t pe_allocated; + uint32_t pvg_total; + u32 proc; + u32 pv[ABS_MAX_PV + 1]; + u32 lv[ABS_MAX_LV + 1]; +} vg32_t; + +typedef struct { + uint8_t id[2]; + uint16_t version; + lvm_disk_data_t pv_on_disk; + lvm_disk_data_t vg_on_disk; + lvm_disk_data_t pv_namelist_on_disk; + lvm_disk_data_t lv_on_disk; + lvm_disk_data_t pe_on_disk; + uint8_t pv_name[NAME_LEN]; + uint8_t vg_name[NAME_LEN]; + uint8_t system_id[NAME_LEN]; + kdev_t pv_dev; + uint32_t pv_number; + uint32_t pv_status; + uint32_t pv_allocatable; + uint32_t pv_size; + uint32_t lv_cur; + uint32_t pe_size; + uint32_t pe_total; + uint32_t pe_allocated; + uint32_t pe_stale; + u32 pe; + u32 inode; +} pv32_t; + +typedef struct { + char lv_name[NAME_LEN]; + u32 lv; +} lv_req32_t; + +typedef struct { + u32 lv_index; + u32 lv; +} lv_status_byindex_req32_t; + +typedef struct { + uint8_t lv_name[NAME_LEN]; + kdev_t old_dev; + kdev_t new_dev; + u32 old_pe; + u32 new_pe; +} le_remap_req32_t; + +typedef struct { + char pv_name[NAME_LEN]; + u32 pv; +} pv_status_req32_t; + +typedef struct { + uint8_t lv_name[NAME_LEN]; + uint8_t vg_name[NAME_LEN]; + uint32_t lv_access; + uint32_t lv_status; + uint32_t lv_open; + kdev_t lv_dev; + uint32_t lv_number; + uint32_t lv_mirror_copies; + uint32_t lv_recovery; + uint32_t lv_schedule; + uint32_t lv_size; + u32 lv_current_pe; + uint32_t lv_current_le; + uint32_t lv_allocated_le; + uint32_t lv_stripes; + uint32_t lv_stripesize; + uint32_t lv_badblock; + uint32_t lv_allocation; + uint32_t lv_io_timeout; + uint32_t lv_read_ahead; + /* delta to version 1 starts here */ + u32 lv_snapshot_org; + u32 lv_snapshot_prev; + u32 lv_snapshot_next; + u32 lv_block_exception; + uint32_t lv_remap_ptr; + uint32_t lv_remap_end; + uint32_t lv_chunk_size; + uint32_t lv_snapshot_minor; + char dummy[200]; +} lv32_t; + +typedef struct { + u32 hash[2]; + u32 rsector_org; + kdev_t rdev_org; + u32 rsector_new; + kdev_t rdev_new; +} lv_block_exception32_t; + +static void put_lv_t(lv_t *l) +{ + if (l->lv_current_pe) vfree(l->lv_current_pe); + if (l->lv_block_exception) vfree(l->lv_block_exception); + kfree(l); +} + +static lv_t *get_lv_t(u32 p, int *errp) +{ + int err, i; + u32 ptr1, ptr2; + size_t size; + lv_block_exception32_t *lbe32; + lv_block_exception_t *lbe; + lv32_t *ul = (lv32_t *)A(p); + lv_t *l = (lv_t *)kmalloc(sizeof(lv_t), GFP_KERNEL); + if (!l) { + *errp = -ENOMEM; + return NULL; + } + memset(l, 0, sizeof(lv_t)); + err = copy_from_user(l, ul, (long)&((lv32_t *)0)->lv_current_pe); + err |= __copy_from_user(&l->lv_current_le, &ul->lv_current_le, + ((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le)); + err |= __copy_from_user(&l->lv_remap_ptr, &ul->lv_remap_ptr, + ((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr)); + err |= __get_user(ptr1, &ul->lv_current_pe); + err |= __get_user(ptr2, &ul->lv_block_exception); + if (err) { + kfree(l); + *errp = -EFAULT; + return NULL; + } + if (ptr1) { + size = l->lv_allocated_le * sizeof(pe_t); + l->lv_current_pe = vmalloc(size); + if (l->lv_current_pe) + err = copy_from_user(l->lv_current_pe, (void *)A(ptr1), size); + } + if (!err && ptr2) { + size = l->lv_remap_end * sizeof(lv_block_exception_t); + l->lv_block_exception = lbe = vmalloc(size); + if (l->lv_block_exception) { + lbe32 = (lv_block_exception32_t *)A(ptr2); + memset(lbe, 0, size); + for (i = 0; i < l->lv_remap_end; i++, lbe++, lbe32++) { + err |= get_user(lbe->rsector_org, &lbe32->rsector_org); + err |= __get_user(lbe->rdev_org, &lbe32->rdev_org); + err |= __get_user(lbe->rsector_new, &lbe32->rsector_new); + err |= __get_user(lbe->rdev_new, &lbe32->rdev_new); + } + } + } + if (err || (ptr1 && !l->lv_current_pe) || (ptr2 && !l->lv_block_exception)) { + if (!err) + *errp = -ENOMEM; + else + *errp = -EFAULT; + put_lv_t(l); + return NULL; + } + return l; +} + +static int copy_lv_t(u32 ptr, lv_t *l) +{ + int err; + lv32_t *ul = (lv32_t *)A(ptr); + u32 ptr1; + size_t size; + + err = get_user(ptr1, &ul->lv_current_pe); + if (err) + return -EFAULT; + err = copy_to_user(ul, l, (long)&((lv32_t *)0)->lv_current_pe); + err |= __copy_to_user(&ul->lv_current_le, &l->lv_current_le, + ((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le)); + err |= __copy_to_user(&ul->lv_remap_ptr, &l->lv_remap_ptr, + ((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr)); + size = l->lv_allocated_le * sizeof(pe_t); + err |= __copy_to_user((void *)A(ptr1), l->lv_current_pe, size); + return -EFAULT; +} + +static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + vg_t *v; + union { + lv_req_t lv_req; + le_remap_req_t le_remap; + lv_status_byindex_req_t lv_byindex; + pv_status_req32_t pv_status; + } u; + pv_t p; + int err; + u32 ptr = 0; + int i; + mm_segment_t old_fs; + void *karg = &u; + + switch (cmd) { + case VG_STATUS: + v = kmalloc(sizeof(vg_t), GFP_KERNEL); + if (!v) return -ENOMEM; + karg = v; + break; + case VG_CREATE: + v = kmalloc(sizeof(vg_t), GFP_KERNEL); + if (!v) return -ENOMEM; + if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc) || + __get_user(v->proc, &((vg32_t *)arg)->proc)) { + kfree(v); + return -EFAULT; + } + karg = v; + memset(v->pv, 0, sizeof(v->pv) + sizeof(v->lv)); + if (v->pv_max > ABS_MAX_PV || v->lv_max == ABS_MAX_LV) return -EPERM; + for (i = 0; i < v->pv_max; i++) { + err = __get_user(ptr, &((vg32_t *)arg)->pv[i]); + if (err) break; + if (ptr) { + v->pv[i] = kmalloc(sizeof(pv_t), GFP_KERNEL); + if (!v->pv[i]) { + err = -ENOMEM; + break; + } + err = copy_from_user(v->pv[i], (void *)A(ptr), sizeof(pv32_t) - 8); + if (err) { + err = -EFAULT; + break; + } + v->pv[i]->pe = NULL; v->pv[i]->inode = NULL; + } + } + if (!err) { + for (i = 0; i < v->lv_max; i++) { + err = __get_user(ptr, &((vg32_t *)arg)->lv[i]); + if (err) break; + if (ptr) { + v->lv[i] = get_lv_t(ptr, &err); + if (err) break; + } + } + } + break; + case LV_CREATE: + case LV_EXTEND: + case LV_REDUCE: + case LV_REMOVE: + case LV_STATUS_BYNAME: + err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name)); + if (err) return -EFAULT; + if (cmd != LV_REMOVE) { + err = __get_user(ptr, &((lv_req32_t *)arg)->lv); + if (err) return err; + u.lv_req.lv = get_lv_t(ptr, &err); + } else + u.lv_req.lv = NULL; + break; + case LV_STATUS_BYINDEX: + err = get_user(u.lv_byindex.lv_index, &((lv_status_byindex_req32_t *)arg)->lv_index); + err |= __get_user(ptr, &((lv_status_byindex_req32_t *)arg)->lv); + if (err) return err; + u.lv_byindex.lv = get_lv_t(ptr, &err); + break; + case VG_EXTEND: + err = copy_from_user(&p, (void *)arg, sizeof(pv32_t) - 8); + if (err) return -EFAULT; + p.pe = NULL; p.inode = NULL; + karg = &p; + break; + case LE_REMAP: + err = copy_from_user(&u.le_remap, (void *)arg, sizeof(le_remap_req32_t)); + if (err) return -EFAULT; + u.le_remap.new_pe = ((le_remap_req32_t *)&u.le_remap)->new_pe; + u.le_remap.old_pe = ((le_remap_req32_t *)&u.le_remap)->old_pe; + break; + case PV_CHANGE: + case PV_STATUS: + err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name)); + if (err) return -EFAULT; + err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv); + if (err) return err; + u.pv_status.pv = &p; + if (cmd == PV_CHANGE) { + err = copy_from_user(&p, (void *)A(ptr), sizeof(pv32_t) - 8); + if (err) return -EFAULT; + p.pe = NULL; p.inode = NULL; + } + break; + } + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)karg); + set_fs (old_fs); + switch (cmd) { + case VG_STATUS: + if (!err) { + if (copy_to_user((void *)arg, v, (long)&((vg32_t *)0)->proc) || + clear_user(&((vg32_t *)arg)->proc, sizeof(vg32_t) - (long)&((vg32_t *)0)->proc)) + err = -EFAULT; + } + kfree(v); + break; + case VG_CREATE: + for (i = 0; i < v->pv_max; i++) + if (v->pv[i]) kfree(v->pv[i]); + for (i = 0; i < v->lv_max; i++) + if (v->lv[i]) put_lv_t(v->lv[i]); + kfree(v); + break; + case LV_STATUS_BYNAME: + if (!err && u.lv_req.lv) err = copy_lv_t(ptr, u.lv_req.lv); + /* Fall through */ + case LV_CREATE: + case LV_EXTEND: + case LV_REDUCE: + if (u.lv_req.lv) put_lv_t(u.lv_req.lv); + break; + case LV_STATUS_BYINDEX: + if (u.lv_byindex.lv) { + if (!err) err = copy_lv_t(ptr, u.lv_byindex.lv); + put_lv_t(u.lv_byindex.lv); + } + case PV_STATUS: + if (!err) { + err = copy_to_user((void *)A(ptr), &p, sizeof(pv32_t) - 8); + if (err) return -EFAULT; + } + break; + } + return err; +} +#endif + static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) { return -EINVAL; @@ -2027,6 +2383,39 @@ static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioc return err; } +typedef struct blkelv_ioctl32_arg_s { + u32 queue_ID; + int read_latency; + int write_latency; + int max_bomb_segments; +} blkelv_ioctl32_arg_t; + +static int do_blkelv_ioctl(unsigned int fd, unsigned int cmd, blkelv_ioctl32_arg_t *arg) +{ + blkelv_ioctl_arg_t b; + int err; + mm_segment_t old_fs = get_fs(); + + if (cmd == BLKELVSET) { + err = get_user((long)b.queue_ID, &arg->queue_ID); + err |= __get_user(b.read_latency, &arg->read_latency); + err |= __get_user(b.write_latency, &arg->write_latency); + err |= __get_user(b.max_bomb_segments, &arg->max_bomb_segments); + if (err) return err; + } + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&b); + set_fs (old_fs); + if (cmd == BLKELVGET && !err) { + err = put_user((long)b.queue_ID, &arg->queue_ID); + err |= __put_user(b.read_latency, &arg->read_latency); + err |= __put_user(b.write_latency, &arg->write_latency); + err |= __put_user(b.max_bomb_segments, &arg->max_bomb_segments); + if (err) return err; + } + return err; +} + static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) { return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); @@ -2548,6 +2937,24 @@ COMPATIBLE_IOCTL(ATMTCP_CREATE) COMPATIBLE_IOCTL(ATMTCP_REMOVE) COMPATIBLE_IOCTL(ATMMPC_CTRL) COMPATIBLE_IOCTL(ATMMPC_DATA) +#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) +/* 0xfe - lvm */ +COMPATIBLE_IOCTL(VG_SET_EXTENDABLE) +COMPATIBLE_IOCTL(VG_STATUS_GET_COUNT) +COMPATIBLE_IOCTL(VG_STATUS_GET_NAMELIST) +COMPATIBLE_IOCTL(VG_REMOVE) +COMPATIBLE_IOCTL(VG_REDUCE) +COMPATIBLE_IOCTL(PE_LOCK_UNLOCK) +COMPATIBLE_IOCTL(PV_FLUSH) +COMPATIBLE_IOCTL(LVM_LOCK_LVM) +COMPATIBLE_IOCTL(LVM_GET_IOP_VERSION) +#ifdef LVM_TOTAL_RESET +COMPATIBLE_IOCTL(LVM_RESET) +#endif +COMPATIBLE_IOCTL(LV_SET_ACCESS) +COMPATIBLE_IOCTL(LV_SET_STATUS) +COMPATIBLE_IOCTL(LV_SET_ALLOCATION) +#endif /* LVM */ /* And these ioctls need translation */ HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) @@ -2594,6 +3001,8 @@ HANDLE_IOCTL(0x1260, broken_blkgetsize) HANDLE_IOCTL(BLKFRAGET, w_long) HANDLE_IOCTL(BLKSECTGET, w_long) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) +HANDLE_IOCTL(BLKELVGET, do_blkelv_ioctl) +HANDLE_IOCTL(BLKELVSET, do_blkelv_ioctl) HANDLE_IOCTL(FBIOPUTCMAP32, fbiogetputcmap) HANDLE_IOCTL(FBIOGETCMAP32, fbiogetputcmap) HANDLE_IOCTL(FBIOSCURSOR32, fbiogscursor) @@ -2677,6 +3086,20 @@ HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl) HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl) HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) +#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) +HANDLE_IOCTL(VG_STATUS, do_lvm_ioctl) +HANDLE_IOCTL(VG_CREATE, do_lvm_ioctl) +HANDLE_IOCTL(VG_EXTEND, do_lvm_ioctl) +HANDLE_IOCTL(LV_CREATE, do_lvm_ioctl) +HANDLE_IOCTL(LV_REMOVE, do_lvm_ioctl) +HANDLE_IOCTL(LV_EXTEND, do_lvm_ioctl) +HANDLE_IOCTL(LV_REDUCE, do_lvm_ioctl) +HANDLE_IOCTL(LV_STATUS_BYNAME, do_lvm_ioctl) +HANDLE_IOCTL(LV_STATUS_BYINDEX, do_lvm_ioctl) +HANDLE_IOCTL(LE_REMAP, do_lvm_ioctl) +HANDLE_IOCTL(PV_CHANGE, do_lvm_ioctl) +HANDLE_IOCTL(PV_STATUS, do_lvm_ioctl) +#endif /* LVM */ IOCTL_TABLE_END unsigned int ioctl32_hash_table[1024]; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index f798358ce..45128d749 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.75 2000/02/21 15:50:08 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.76 2000/03/14 08:29:29 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -109,10 +109,10 @@ extern unsigned long phys_base; */ #define EXPORT_SYMBOL_PRIVATE(sym) \ -extern int __sparc_priv_ ## sym (int) __asm__("__" ## #sym); \ +extern int __sparc_priv_ ## sym (int) __asm__("__" #sym); \ const struct module_symbol __export_priv_##sym \ __attribute__((section("__ksymtab"))) = \ -{ (unsigned long) &__sparc_priv_ ## sym, "__" ## #sym } +{ (unsigned long) &__sparc_priv_ ## sym, "__" #sym } /* used by various drivers */ #ifdef __SMP__ @@ -288,6 +288,9 @@ EXPORT_SYMBOL(move_addr_to_user); EXPORT_SYMBOL(__memcpy); EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(clear_page); +EXPORT_SYMBOL(copy_page); +EXPORT_SYMBOL(clear_user_page); +EXPORT_SYMBOL(copy_user_page); EXPORT_SYMBOL(__bzero); EXPORT_SYMBOL(__memscan_zero); EXPORT_SYMBOL(__memscan_generic); diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index d4ecb0f4f..a24c53e45 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.136 2000/03/13 21:57:29 davem Exp $ +/* $Id: sys_sparc32.c,v 1.137 2000/03/14 07:31:22 jj Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -1746,70 +1746,58 @@ static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel) return 0; } -extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, - unsigned long new_flags, void *data); +extern long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page, + unsigned long new_flags, unsigned long data_page); #define SMBFS_NAME "smbfs" #define NCPFS_NAME "ncpfs" asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data) { - unsigned long type_page; + unsigned long type_page = 0; + unsigned long data_page = 0; int err, is_smb, is_ncp; - if(!capable(CAP_SYS_ADMIN)) - return -EPERM; is_smb = is_ncp = 0; + + lock_kernel(); err = copy_mount_stuff_to_kernel((const void *)type, &type_page); - if(err) - return err; - if(type_page) { - is_smb = !strcmp((char *)type_page, SMBFS_NAME); - is_ncp = !strcmp((char *)type_page, NCPFS_NAME); + if (err) + goto out; + + if (!type_page) { + err = -EINVAL; + goto out; } - if(!is_smb && !is_ncp) { - if(type_page) - free_page(type_page); - return sys_mount(dev_name, dir_name, type, new_flags, (void *)AA(data)); - } else { - unsigned long dev_page, dir_page, data_page; - mm_segment_t old_fs; - err = copy_mount_stuff_to_kernel((const void *)dev_name, &dev_page); - if(err) - goto out; - err = copy_mount_stuff_to_kernel((const void *)dir_name, &dir_page); - if(err) - goto dev_out; - err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page); - if(err) - goto dir_out; - if(is_ncp) + is_smb = !strcmp((char *)type_page, SMBFS_NAME); + is_ncp = !strcmp((char *)type_page, NCPFS_NAME); + + err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page); + if (err) + goto type_out; + + if (!is_smb && !is_ncp) { + err = do_sys_mount(dev_name, dir_name, type_page, new_flags, + data_page); + } else { + if (is_ncp) do_ncp_super_data_conv((void *)data_page); - else if(is_smb) - do_smb_super_data_conv((void *)data_page); else - panic("The problem is here..."); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_mount((char *)dev_page, (char *)dir_page, - (char *)type_page, new_flags, - (void *)data_page); - set_fs(old_fs); + do_smb_super_data_conv((void *)data_page); - if(data_page) - free_page(data_page); - dir_out: - if(dir_page) - free_page(dir_page); - dev_out: - if(dev_page) - free_page(dev_page); - out: - if(type_page) - free_page(type_page); - return err; + err = do_sys_mount(dev_name, dir_name, type_page, new_flags, + data_page); } + + free_page(data_page); + +type_out: + free_page(type_page); + +out: + unlock_kernel(); + return err; } struct rusage32 { @@ -4218,12 +4206,3 @@ out_sem: out: return ret; } - -extern asmlinkage long sys_mincore(unsigned long start, size_t len, unsigned char *vec); - -asmlinkage long sys32_mincore(unsigned long start, u32 __len, unsigned char *vec) -{ - size_t len = (size_t) __len; - - return sys_mincore(start, len, vec); -} diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index f7f5964e9..a572e4976 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.41 2000/03/13 21:57:31 davem Exp $ +/* $Id: sys_sunos32.c,v 1.42 2000/03/15 02:43:35 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -225,33 +225,6 @@ asmlinkage void sunos_vadvise(u32 strategy) unlock_kernel(); } -/* Same as vadvise, and just as bogus, but for a range of virtual - * process address space. - */ -#define MADV_NORMAL 0 /* Nothing special... */ -#define MADV_RANDOM 1 /* I am emacs... */ -#define MADV_SEQUENTIAL 2 /* I am researcher code... */ -#define MADV_WILLNEED 3 /* Pages in this range will be needed */ -#define MADV_DONTNEED 4 /* Pages in this range won't be needed */ - -static char *mstrings[] = { - "MADV_NORMAL", - "MADV_RANDOM", - "MADV_SEQUENTIAL", - "MADV_WILLNEED", - "MADV_DONTNEED", -}; - -asmlinkage void sunos_madvise(u32 address, u32 len, u32 strategy) -{ - /* I wanna see who uses this... */ - lock_kernel(); - printk("%s: Advises us to use %s paging strategy for addr<%08x> len<%08x>\n", - current->comm, strategy <= 4 ? mstrings[strategy] : "BOGUS", - address, len); - unlock_kernel(); -} - /* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE * resource limit and is for backwards compatibility with older sunos * revs. diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 0a0edbf82..d86649bf7 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.69 2000/03/13 21:57:28 davem Exp $ +/* $Id: systbls.S,v 1.71 2000/03/15 02:43:36 davem Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -34,7 +34,7 @@ sys_call_table32: /*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize .word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_geteuid /*70*/ .word sys_getegid, sys32_mmap, sys_setreuid, sys_munmap, sys_mprotect - .word sys_nis_syscall, sys_vhangup, sys32_truncate64, sys32_mincore, sys32_getgroups16 + .word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys32_getgroups16 /*80*/ .word sys32_setgroups16, sys_getpgrp, sys_setgroups, sys32_setitimer, sys32_ftruncate64 .word sys_swapon, sys32_getitimer, sys_setuid, sys_sethostname, sys_setgid /*90*/ .word sys_dup2, sys_setfsuid, sys32_fcntl, sys32_select, sys_setfsgid @@ -93,7 +93,7 @@ sys_call_table: /*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize .word sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall /*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys64_munmap, sys_mprotect - .word sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups + .word sys_madvise, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups /*80*/ .word sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall .word sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall /*90*/ .word sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall @@ -163,8 +163,8 @@ sunos_sys_table: .word sys_msync, sys_vfork, sunos_nosys .word sunos_nosys, sunos_sbrk, sunos_sstk .word sunos_mmap, sunos_vadvise, sys_munmap - .word sys_mprotect, sunos_madvise, sys_vhangup - .word sunos_nosys, sys32_mincore, sys32_getgroups16 + .word sys_mprotect, sys_madvise, sys_vhangup + .word sunos_nosys, sys_mincore, sys32_getgroups16 .word sys32_setgroups16, sys_getpgrp, sunos_setpgrp .word sys32_setitimer, sunos_nosys, sys_swapon .word sys32_getitimer, sys_gethostname, sys_sethostname diff --git a/arch/sparc64/lib/blockops.S b/arch/sparc64/lib/blockops.S index 1cdbf09da..b4a91b97c 100644 --- a/arch/sparc64/lib/blockops.S +++ b/arch/sparc64/lib/blockops.S @@ -1,8 +1,8 @@ -/* $Id: blockops.S,v 1.20 2000/03/03 23:48:38 davem Exp $ +/* $Id: blockops.S,v 1.22 2000/03/15 07:18:55 davem Exp $ * blockops.S: UltraSparc block zero optimized routines. * - * Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1996, 1998, 1999, 2000 David S. Miller (davem@redhat.com) + * Copyright (C) 1997 Jakub Jelinek (jakub@redhat.com) */ #include "VIS.h" @@ -24,23 +24,63 @@ #define TLBTEMP_ENTSZ (1 << 3) .text + .align 32 .globl copy_page .type copy_page,@function copy_page: /* %o0=dest, %o1=src */ VISEntry - ldx [%g6 + AOFF_task_active_mm], %o2 + membar #LoadStore | #StoreStore | #StoreLoad + ldda [%o1] ASI_BLK_P, %f0 + add %o1, 0x40, %o1 + ldda [%o1] ASI_BLK_P, %f16 + add %o1, 0x40, %o1 + sethi %hi(8192), %o2 +1: TOUCH(f0, f2, f4, f6, f8, f10, f12, f14) + ldda [%o1] ASI_BLK_P, %f32 + add %o1, 0x40, %o1 + sub %o2, 0x40, %o2 + stda %f48, [%o0] ASI_BLK_P + add %o0, 0x40, %o0 + TOUCH(f16, f18, f20, f22, f24, f26, f28, f30) + ldda [%o1] ASI_BLK_P, %f0 + add %o1, 0x40, %o1 + sub %o2, 0x40, %o2 + stda %f48, [%o0] ASI_BLK_P + add %o0, 0x40, %o0 + TOUCH(f32, f34, f36, f38, f40, f42, f44, f46) + ldda [%o1] ASI_BLK_P, %f16 + add %o1, 0x40, %o1 + sub %o2, 0x40, %o2 + stda %f48, [%o0] ASI_BLK_P + cmp %o2, 0x80 + bne,pt %xcc, 1b + add %o0, 0x40, %o0 + membar #Sync + stda %f0, [%o0] ASI_BLK_P + add %o0, 0x40, %o0 + stda %f16, [%o0] ASI_BLK_P + membar #Sync + VISExit + retl + nop + + .globl copy_user_page + .type copy_user_page,@function +copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */ + VISEntry + sethi %hi(PAGE_SIZE), %g3 sub %o0, %g4, %g1 + and %o2, %g3, %o0 + sethi %hi(TLBTEMP_BASE), %o3 sethi %uhi(_PAGE_VALID), %g3 sub %o1, %g4, %g2 sllx %g3, 32, %g3 - ldx [%o2 + AOFF_mm_segments], %o0 + mov TLB_TAG_ACCESS, %o2 or %g3, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W), %g3 + sethi %hi(DCACHE_SIZE), %o1 or %g1, %g3, %g1 or %g2, %g3, %g2 - mov TLB_TAG_ACCESS, %o2 - sethi %hi(TLBTEMP_BASE), %o3 - sethi %hi(DCACHE_SIZE), %o1 add %o0, %o3, %o0 add %o0, %o1, %o1 sethi %hi(TLBTEMP_ENT1), %o3 @@ -129,17 +169,25 @@ copy_page: /* %o0=dest, %o1=src */ .align 32 .globl clear_page .type clear_page,@function -clear_page: /* %o0=dest */ +clear_page: /* %o0=dest */ VISEntryHalf - ldx [%g6 + AOFF_task_active_mm], %o2 + ba,pt %xcc, clear_page_common + clr %o4 + + .align 32 + .globl clear_user_page + .type clear_user_page,@function +clear_user_page: /* %o0=dest, %o1=vaddr */ + VISEntryHalf + sethi %hi(PAGE_SIZE), %g3 sub %o0, %g4, %g1 + and %o1, %g3, %o0 + mov TLB_TAG_ACCESS, %o2 sethi %uhi(_PAGE_VALID), %g3 + sethi %hi(TLBTEMP_BASE), %o3 sllx %g3, 32, %g3 or %g3, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W), %g3 - ldx [%o2 + AOFF_mm_segments], %o0 or %g1, %g3, %g1 - mov TLB_TAG_ACCESS, %o2 - sethi %hi(TLBTEMP_BASE), %o3 add %o0, %o3, %o0 sethi %hi(TLBTEMP_ENT2), %o3 rdpr %pstate, %g3 @@ -162,6 +210,9 @@ clear_page: /* %o0=dest */ stxa %g1, [%o3] ASI_DTLB_DATA_ACCESS membar #Sync + mov 1, %o4 + +clear_page_common: fzero %f0 ! FPA Group mov 32, %o1 ! IEU0 fzero %f2 ! FPA Group @@ -187,7 +238,13 @@ clear_page: /* %o0=dest */ membar #Sync ! LSU Group VISExitHalf - stxa %g5, [%o2] ASI_DMMU + brnz,pt %o4, 1f + nop + + retl + nop + +1: stxa %g5, [%o2] ASI_DMMU stxa %g7, [%o3] ASI_DTLB_DATA_ACCESS membar #Sync jmpl %o7 + 0x8, %g0 diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 226246980..6063d002e 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.42 2000/01/21 11:39:13 jj Exp $ +/* $Id: fault.c,v 1.43 2000/03/14 03:59:46 davem Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -245,7 +245,7 @@ good_area: if(!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } - current->mm->segments = (void *) (address & PAGE_SIZE); + { int fault = handle_mm_fault(current, vma, address, write); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index ade376b51..07f727910 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4375,60 +4375,12 @@ static void __init parse_floppy_cfg_string(char *cfg) } } -static void __init mod_setup(char *pattern, int (*setup)(char *)) -{ - unsigned long i; - char c; - int j; - int match; - char buffer[100]; - int length = strlen(pattern)+1; - - match=0; - j=1; - - for (i=current->mm->env_start; i< current->mm->env_end; i ++){ - get_user(c, (char *)i); - if (match){ - if (j==99) - c='\0'; - buffer[j] = c; - if (!c || c == ' ' || c == '\t'){ - if (j){ - buffer[j] = '\0'; - setup(buffer); - } - j=0; - } else - j++; - if (!c) - break; - continue; - } - if ((!j && !c) || (j && c == pattern[j-1])) - j++; - else - j=0; - if (j==length){ - match=1; - j=0; - } - } -} - - -#ifdef __cplusplus -extern "C" { -#endif int init_module(void) { printk(KERN_INFO "inserting floppy driver for " UTS_RELEASE "\n"); if(floppy) parse_floppy_cfg_string(floppy); - else - mod_setup("floppy=", floppy_setup); - return floppy_init(); } @@ -4450,10 +4402,6 @@ MODULE_PARM(FLOPPY_DMA,"i"); MODULE_AUTHOR("Alain L. Knaff"); MODULE_SUPPORTED_DEVICE("fd"); -#ifdef __cplusplus -} -#endif - #else __setup ("floppy=", floppy_setup); diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index ce3e65890..811d0266c 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -319,9 +319,9 @@ static struct request * __get_request_wait(int n, kdev_t dev) DECLARE_WAITQUEUE(wait, current); unsigned long flags; - add_wait_queue(&wait_for_request, &wait); + add_wait_queue_exclusive(&wait_for_request, &wait); for (;;) { - current->state = TASK_UNINTERRUPTIBLE; + __set_current_state(TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE); spin_lock_irqsave(&io_request_lock,flags); req = get_request(n, dev); spin_unlock_irqrestore(&io_request_lock,flags); diff --git a/drivers/block/lvm.c b/drivers/block/lvm.c index 9f58a48d5..beb4f1364 100644 --- a/drivers/block/lvm.c +++ b/drivers/block/lvm.c @@ -892,8 +892,8 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, "%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n", lvm_name, lv_ptr->lv_size); #endif - copy_to_user((long *) arg, &lv_ptr->lv_size, - sizeof(lv_ptr->lv_size)); + if (put_user(lv_ptr->lv_size, (long *)arg)) + return -EFAULT; break; @@ -931,8 +931,8 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, printk(KERN_DEBUG "%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name); #endif - copy_to_user((long *) arg, &lv_ptr->lv_read_ahead, - sizeof(lv_ptr->lv_read_ahead)); + if (put_user(lv->lv_read_ahead, (long *)arg)) + return -EFAULT; break; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index a0b63a8c8..0c3f5429f 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -299,7 +299,7 @@ void nbd_clear_que(struct nbd_device *lo) static void do_nbd_request(request_queue_t * q) { struct request *req; - int dev; + int dev = 0; struct nbd_device *lo; while (!QUEUE_EMPTY) { diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index 05aff4b59..27ea344b9 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c @@ -1483,6 +1483,6 @@ __setup("cm206=", cm206_setup); #endif /* !MODULE */ /* * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -D__SMP__ -pipe -fno-strength-reduce -m486 -DCPU=486 -D__SMP__ -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -c -o cm206.o cm206.c" + * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -m486 -DCPU=486 -D__SMP__ -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -c -o cm206.o cm206.c" * End: */ diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index ea828cc24..969a75331 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -2259,6 +2259,6 @@ void cleanup_module(void) /* Local variables: - compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce -DCPU=686 -march=i686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c" + compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce -DCPU=686 -march=i686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c amiserial.c" End: */ diff --git a/drivers/char/drm/bufs.c b/drivers/char/drm/bufs.c index 1bb7bd612..4e8c50c59 100644 --- a/drivers/char/drm/bufs.c +++ b/drivers/char/drm/bufs.c @@ -29,6 +29,7 @@ */ #define __NO_VERSION__ +#include #include "drmP.h" #include "linux/un.h" diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 3a371c23d..4d003ba2c 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -50,7 +50,6 @@ #include #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) -#include #include #endif #include "drm.h" diff --git a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c index 6df4440f3..7e0d6e53e 100644 --- a/drivers/char/drm/gamma_drv.c +++ b/drivers/char/drm/gamma_drv.c @@ -28,6 +28,7 @@ * */ +#include #include "drmP.h" #include "gamma_drv.h" EXPORT_SYMBOL(gamma_init); diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c index 82b2ac9a2..7934c66b9 100644 --- a/drivers/char/drm/tdfx_drv.c +++ b/drivers/char/drm/tdfx_drv.c @@ -29,6 +29,7 @@ * */ +#include #include "drmP.h" #include "tdfx_drv.h" diff --git a/drivers/char/pc_keyb.c b/drivers/char/pc_keyb.c index 9f3e06586..5641e47e7 100644 --- a/drivers/char/pc_keyb.c +++ b/drivers/char/pc_keyb.c @@ -442,8 +442,11 @@ static unsigned char handle_kbd_event(void) scancode = kbd_read_input(); +#if 0 /* Ignore error bytes */ - if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR))) { + if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR))) +#endif + { if (status & KBD_STAT_MOUSE_OBF) handle_mouse_event(scancode); else diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index b0412bbef..239c61acc 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -87,7 +87,7 @@ static struct fasync_struct *rtc_async_queue; static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); -static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; +extern spinlock_t rtc_lock; static struct timer_list rtc_irq_timer; @@ -141,8 +141,11 @@ static const unsigned char days_in_mo[] = #ifndef __alpha__ /* * A very tiny interrupt handler. It runs with SA_INTERRUPT set, - * so that there is no possibility of conflicting with the - * set_rtc_mmss() call that happens during some timer interrupts. + * but there is possibility of conflicting with the set_rtc_mmss() + * call (the rtc irq and the timer irq can easily run at the same + * time in two different CPUs). So we need to serializes + * accesses to the chip with the rtc_lock spinlock that each + * architecture should implement in the timer code. * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) */ diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c index 9190b5a87..c3a552b43 100644 --- a/drivers/net/shaper.c +++ b/drivers/net/shaper.c @@ -66,6 +66,7 @@ * 1999/06/18 Jordi Murgo */ +#include #include #include #include diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 059d4a4ea..d4f6e5b19 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1,4 +1,4 @@ -/* $Id: sunhme.c,v 1.93 2000/03/12 04:02:14 davem Exp $ +/* $Id: sunhme.c,v 1.94 2000/03/15 06:47:04 davem Exp $ * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, * auto carrier detecting ethernet driver. Also known as the * "Happy Meal Ethernet" found on SunSwift SBUS cards. @@ -2953,7 +2953,7 @@ static int __init happy_meal_probe(void) } -static void __exit cleanup_module(void) +static void __exit happy_meal_cleanup_module(void) { #ifdef MODULE /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index d4b2e0380..0787d8d75 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -27,6 +27,8 @@ * the pci resource. * 1/11/00 - Added spinlocks for smp * 2/23/00 - Updated to dev_kfree_irq + * 3/10/00 - Fixed FDX enable which triggered other bugs also + * squashed. * * To Do: * @@ -83,11 +85,11 @@ * Version Number = a.b.c.d where a.b.c is the level of code and d is the latest author. * So 0.0.1.pds = Peter, 0.0.1.mlp = Mike * - * Official releases will only have an a.b.c version number format. + * Official releases will only have an a.b.c version number format. */ static char *version = -"Olympic.c v0.3.2 2/23/00 - Peter De Schrijver & Mike Phillips" ; +"Olympic.c v0.5.0 3/10/00 - Peter De Schrijver & Mike Phillips" ; static char *open_maj_error[] = {"No error", "Lobe Media Test", "Physical Insertion", "Address Verification", "Neighbor Notification (Ring Poll)", @@ -319,6 +321,14 @@ static int __init olympic_init(struct net_device *dev) return -1; } + if (olympic_priv->olympic_message_level) { + if ( readb(init_srb +2) & 0x40) { + printk(KERN_INFO "Olympic: Adapter is FDX capable.\n") ; + } else { + printk(KERN_INFO "Olympic: Adapter cannot do FDX.\n"); + } + } + uaa_addr=ntohs(readw(init_srb+8)); #if OLYMPIC_DEBUG @@ -401,7 +411,7 @@ static int olympic_open(struct net_device *dev) #if OLYMPIC_NETWORK_MONITOR writew(ntohs(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON),init_srb+8); #else - writew(OPEN_ADAPTER_ENABLE_FDX,init_srb+8); + writew(ntohs(OPEN_ADAPTER_ENABLE_FDX),init_srb+8); #endif if (olympic_priv->olympic_laa[0]) { @@ -941,9 +951,9 @@ static void olympic_set_rx_mode(struct net_device *dev) options = olympic_priv->olympic_copy_all_options; if (dev->flags&IFF_PROMISC) - options |= (3<<5) ; /* All LLC and MAC frames, all through the main rx channel */ + options |= 0x61 ; else - options &= ~(3<<5) ; + options &= ~0x61 ; /* Only issue the srb if there is a change in options */ @@ -1182,7 +1192,7 @@ static void olympic_arb_cmd(struct net_device *dev) __u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */ __u8 fdx_prot_error ; __u16 next_ptr; - + int i ; #if OLYMPIC_NETWORK_MONITOR struct trh_hdr *mac_hdr ; #endif @@ -1242,7 +1252,7 @@ static void olympic_arb_cmd(struct net_device *dev) /* Is the ASB free ? */ - if (!(readl(olympic_priv->olympic_mmio + SISR) & SISR_ASB_FREE)) { + if (readb(asb_block + 2) != 0xff) { olympic_priv->asb_queued = 1 ; writel(LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM); return ; @@ -1261,7 +1271,7 @@ static void olympic_arb_cmd(struct net_device *dev) return ; } else if (readb(arb_block) == ARB_LAN_CHANGE_STATUS) { /* Lan.change.status */ - lan_status = readw(arb_block+6); + lan_status = ntohs(readw(arb_block+6)); fdx_prot_error = readb(arb_block+8) ; /* Issue ARB Free */ @@ -1288,10 +1298,19 @@ static void olympic_arb_cmd(struct net_device *dev) writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL); netif_stop_queue(dev); olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ; + + olympic_priv->rx_status_last_received++; + olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1; + for(i=0;irx_ring_skb[olympic_priv->rx_status_last_received]); + olympic_priv->rx_status_last_received++; + olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1; + } + free_irq(dev->irq,dev); printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; - + MOD_DEC_USE_COUNT ; } /* If serious error */ if (olympic_priv->olympic_message_level) { diff --git a/drivers/net/tokenring/olympic.h b/drivers/net/tokenring/olympic.h index ba83366c7..5974e4e4f 100644 --- a/drivers/net/tokenring/olympic.h +++ b/drivers/net/tokenring/olympic.h @@ -282,7 +282,7 @@ struct olympic_parameters_table { __u8 phys_addr[4] ; __u8 up_node_addr[6] ; - __u8 up_phys_addr[6] ; + __u8 up_phys_addr[4] ; __u8 poll_addr[6] ; __u16 reserved ; __u16 acc_priority ; diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog index 8d01df21e..d0b742359 100644 --- a/drivers/parport/ChangeLog +++ b/drivers/parport/ChangeLog @@ -1,3 +1,8 @@ +2000-03-15 Tim Waugh + + * parport_pc.c (cleanup_module): Don't call pci_unregister_driver + if we didn't call pci_register_driver first. + 2000-03-13 * parport_pc.c (parport_pc_init): Moved from asm/parport.h. diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 7117c847e..81c464b80 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -2487,7 +2487,10 @@ int init_module(void) void cleanup_module(void) { struct parport *p = parport_enumerate(), *tmp; - pci_unregister_driver (&parport_pc_pci_driver); + + if (!user_specified) + pci_unregister_driver (&parport_pc_pci_driver); + while (p) { tmp = p->next; if (p->modes & PARPORT_MODE_PCSPP) { diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index f29dc114e..acbc1880c 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.83 1999/10/18 01:47:01 zaitcev Exp $ +/* $Id: sbus.c,v 1.84 2000/03/15 01:51:16 davem Exp $ * sbus.c: SBus support routines. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -205,6 +205,7 @@ static void __init sbus_do_child_siblings(int start_node, this_dev->child = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); this_dev->child->bus = sbus; + this_dev->child->next = 0; fill_sbus_device(prom_getchild(this_node), this_dev->child); sbus_do_child_siblings(prom_getchild(this_node), this_dev->child, this_dev, sbus); @@ -424,6 +425,7 @@ void __init sbus_init(void) GFP_ATOMIC); /* Fill it */ this_dev->child->bus = sbus; + this_dev->child->next = 0; fill_sbus_device(prom_getchild(sbus_devs), this_dev->child); sbus_do_child_siblings(prom_getchild(sbus_devs), @@ -453,6 +455,7 @@ void __init sbus_init(void) GFP_ATOMIC); /* Fill it */ this_dev->child->bus = sbus; + this_dev->child->next = 0; fill_sbus_device(prom_getchild(sbus_devs), this_dev->child); sbus_do_child_siblings(prom_getchild(sbus_devs), diff --git a/drivers/sound/bin2hex.c b/drivers/sound/bin2hex.c index 100f18f9c..3b546b93c 100644 --- a/drivers/sound/bin2hex.c +++ b/drivers/sound/bin2hex.c @@ -33,6 +33,6 @@ int main( int argc, const char * argv [] ) i++; } - printf( "};\n#define %sLen %d\n", varname, i ); + printf( "};\nstatic int %sLen = %d;\n", varname, i ); return 0; } diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in index fbb7562dc..8df28dfdc 100644 --- a/drivers/usb/Config.in +++ b/drivers/usb/Config.in @@ -8,7 +8,9 @@ tristate 'Support for USB' CONFIG_USB if [ ! "$CONFIG_USB" = "n" ]; then comment 'USB Controllers' - dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB + if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then + dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB + fi if [ "$CONFIG_USB_UHCI" != "y" ]; then dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB if [ "$CONFIG_USB_UHCI_ALT" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then @@ -39,7 +41,7 @@ comment 'USB Devices' dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB - dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB + dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB m if [ "$CONFIG_USB_STORAGE" != "n" ]; then bool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG fi diff --git a/drivers/usb/dc2xx.c b/drivers/usb/dc2xx.c index 3a2df9155..9dff6bda1 100644 --- a/drivers/usb/dc2xx.c +++ b/drivers/usb/dc2xx.c @@ -25,7 +25,8 @@ * and have fun! * * This should also work for a number of other digital (non-Kodak) cameras, - * by adding the vendor and product IDs to the table below. + * by adding the vendor and product IDs to the table below. They'll need + * to be the sort using USB just as a fast bulk data channel. */ /* @@ -100,7 +101,8 @@ static const struct camera { // { 0x03f0, 0xffff }, // HP PhotoSmart C500 /* Other USB devices may well work here too, so long as they - * just stick to half duplex bulk packet exchanges. + * just stick to half duplex bulk packet exchanges. That + * means, among other things, no iso or interrupt endpoints. */ }; @@ -162,7 +164,7 @@ static ssize_t camera_read (struct file *file, usb_rcvbulkpipe (camera->dev, camera->inEP), camera->buf, len, &count, HZ*10); - dbg ("read (%d) - 0x%x %ld", len, result, count); + dbg ("read (%d) - 0x%x %d", len, result, count); if (!result) { if (copy_to_user (buf, camera->buf, count)) @@ -382,7 +384,7 @@ static void * camera_probe(struct usb_device *dev, unsigned int ifnum) err ("no memory!"); return NULL; } - camera->dev = dev; + camera->info = camera_info; camera->subminor = i; camera->isActive = 0; camera->buf = NULL; @@ -413,19 +415,22 @@ static void * camera_probe(struct usb_device *dev, unsigned int ifnum) || endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK ) { dbg ("Bogus endpoints"); - camera->dev = NULL; - return NULL; + goto error; } if (usb_set_configuration (dev, dev->config[0].bConfigurationValue)) { err ("Failed usb_set_configuration"); - camera->dev = NULL; - return NULL; + goto error; } - camera->info = camera_info; + camera->dev = dev; return camera; + +error: + minor_data [camera->subminor] = NULL; + kfree (camera); + return NULL; } static void camera_disconnect(struct usb_device *dev, void *ptr) diff --git a/drivers/usb/dsbr100.c b/drivers/usb/dsbr100.c index 8b81e06c0..22c21bb33 100644 --- a/drivers/usb/dsbr100.c +++ b/drivers/usb/dsbr100.c @@ -48,12 +48,6 @@ #include - -#if CONFIG_MODVERSIONS==1 -#define MODVERSIONS -#include -#endif - #include #include #include diff --git a/drivers/usb/usb-storage.c b/drivers/usb/usb-storage.c index 956e80a0a..0cac2ef13 100644 --- a/drivers/usb/usb-storage.c +++ b/drivers/usb/usb-storage.c @@ -52,6 +52,10 @@ /* direction table -- this indicates the direction of the data * transfer for each command code -- a 1 indicates input */ +/* FIXME: we need to use the new direction indicators in the Scsi_Cmnd + * structure, not this table. First we need to evaluate if it's being set + * correctly for us, though + */ unsigned char us_direction[256/8] = { 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, @@ -81,13 +85,12 @@ struct us_data { __u8 ep_int; /* interrupt . */ __u8 subclass; /* as in overview */ __u8 protocol; /* .............. */ - __u8 attention_done; /* force attn on first cmd */ trans_cmnd transport; /* protocol specific do cmd */ trans_reset transport_reset; /* .......... device reset */ proto_cmnd proto_handler; /* protocol handler */ GUID(guid); /* unique dev id */ struct Scsi_Host *host; /* our dummy host data */ - Scsi_Host_Template *htmplt; /* own host template */ + Scsi_Host_Template htmplt; /* own host template */ int host_number; /* to find us */ int host_no; /* allocated by scsi */ Scsi_Cmnd *srb; /* current srb */ @@ -114,7 +117,9 @@ struct us_data { #define US_ACT_BUS_RESET 4 #define US_ACT_HOST_RESET 5 +/* The list of structures and the protective lock for them */ static struct us_data *us_list; +spinlock_t us_list_spinlock = SPIN_LOCK_UNLOCKED; static void * storage_probe(struct usb_device *dev, unsigned int ifnum); static void storage_disconnect(struct usb_device *dev, void *ptr); @@ -225,7 +230,7 @@ static void us_transfer(Scsi_Cmnd *srb, int dir_in) srb->result = result; } -/* calculate the length of the data transfer (not the command) for any +/* Calculate the length of the data transfer (not the command) for any * given SCSI command */ static unsigned int us_transfer_length(Scsi_Cmnd *srb) @@ -243,14 +248,18 @@ static unsigned int us_transfer_length(Scsi_Cmnd *srb) case TEST_UNIT_READY: return 0; + /* FIXME: these should be removed and tested */ case REQUEST_SENSE: case INQUIRY: case MODE_SENSE: return srb->cmnd[4]; + /* FIXME: this needs to come out when the other + * fix is in place */ case READ_CAPACITY: return 8; + /* FIXME: these should be removed and tested */ case LOG_SENSE: case MODE_SENSE_10: return (srb->cmnd[7] << 8) + srb->cmnd[8]; @@ -795,7 +804,7 @@ static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_ERROR; } - /* FIXME: we need to handle NAKs here */ + /* FIXME: we need to handle NAKs here */ return USB_STOR_TRANSPORT_ERROR; } @@ -812,7 +821,9 @@ static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us) /* STATUS STAGE */ /* go to sleep until we get this interrup */ - /* FIXME: this should be changed to use a timeout */ + /* FIXME: this should be changed to use a timeout -- or let the + * device reset routine up() this for us to unjam us + */ down(&(us->ip_waitq)); /* FIXME: currently this code is unreachable, but the idea is @@ -827,8 +838,8 @@ static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us) US_DEBUGP("Got interrupt data 0x%x\n", us->ip_data); /* UFI gives us ASC and ASCQ, like a request sense */ - /* FIXME: is this right? Do REQUEST_SENSE and INQUIRY need special - * case handling? + /* REQUEST_SENSE and INQUIRY don't affect the sense data, so we + * ignore the information for those commands */ if (us->subclass == US_SC_UFI) { if (srb->cmnd[0] == REQUEST_SENSE || @@ -887,7 +898,7 @@ static int CB_transport(Scsi_Cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_ERROR; } - /* FIXME: we need to handle NAKs here */ + /* FIXME: we need to handle NAKs here */ return USB_STOR_TRANSPORT_ERROR; } @@ -1103,7 +1114,8 @@ static int us_detect(struct SHT *sht) static int us_release(struct Scsi_Host *psh) { struct us_data *us = (struct us_data *)psh->hostdata[0]; - struct us_data *prev = (struct us_data *)&us_list; + struct us_data *prev; + unsigned long flags; if (us->irq_handle) { usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe); @@ -1111,18 +1123,20 @@ static int us_release(struct Scsi_Host *psh) } /* FIXME: release the interface claim here? */ - // if (us->pusb_dev) - // usb_deregister(&storage_driver); - /* FIXME - leaves hanging host template copy */ - /* (because scsi layer uses it after removal !!!) */ + /* FIXME: we need to move this elsewhere -- + * the remove function only gets called to remove the module + */ + spin_lock_irqsave(&us_list_spinlock, flags); if (us_list == us) us_list = us->next; else { + prev = us_list; while (prev->next != us) prev = prev->next; prev->next = us->next; } + spin_unlock_irqrestore(&us_list_spinlock, flags); return 0; } @@ -1190,11 +1204,20 @@ static int us_host_reset( Scsi_Cmnd *srb ) int usb_stor_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout) { - struct us_data *us = us_list; + struct us_data *us; char *pos = buffer; char *tmp_ptr; + unsigned long flags; + + /* if someone is sending us data, just throw it away */ + if (inout) + return length; + + /* lock the data structures */ + spin_lock_irqsave(&us_list_spinlock, flags); /* find our data from hostno */ + us = us_list; while (us) { if (us->host_no == hostno) break; @@ -1202,13 +1225,11 @@ int usb_stor_proc_info (char *buffer, char **start, off_t offset, } /* if we couldn't find it, we return an error */ - if (!us) + if (!us) { + spin_unlock_irqrestore(&us_list_spinlock, flags); return -ESRCH; - - /* if someone is sending us data, just throw it away */ - if (inout) - return length; - + } + /* print the controler name */ SPRINTF ("Host scsi%d: usb-storage\n", hostno); @@ -1254,6 +1275,9 @@ int usb_stor_proc_info (char *buffer, char **start, off_t offset, /* show the GUID of the device */ SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid)); + /* release our lock on the data structures */ + spin_unlock_irqrestore(&us_list_spinlock, flags); + /* * Calculate start of next buffer, and return value. */ @@ -1365,6 +1389,7 @@ static int usb_stor_control_thread(void * __us) switch (action) { case US_ACT_COMMAND: /* bad device */ + /* FIXME: we need to enable and test multiple LUNs */ if (us->srb->target || us->srb->lun) { US_DEBUGP( "Bad device number (%d/%d) or dev 0x%x\n", us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev); @@ -1378,9 +1403,12 @@ static int usb_stor_control_thread(void * __us) /* our device has gone - pretend not ready */ /* FIXME: we also need to handle INQUIRY here, * probably */ + /* FIXME: fix return codes and sense buffer handling */ if (!us->pusb_dev) { + US_DEBUGP("Request is for removed device\n"); if (us->srb->cmnd[0] == REQUEST_SENSE) { - memcpy(us->srb->request_buffer, sense_notready, + memcpy(us->srb->request_buffer, + sense_notready, sizeof(sense_notready)); us->srb->result = DID_OK << 16; } else { @@ -1443,34 +1471,29 @@ static int usb_stor_control_thread(void * __us) /* Probe to see if a new device is actually a SCSI device */ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) { - struct usb_interface_descriptor *interface; int i; char mf[32]; /* manufacturer */ char prod[32]; /* product */ char serial[32]; /* serial number */ struct us_data *ss = NULL; - unsigned int flags = 0; GUID(guid); /* Global Unique Identifier */ - struct us_data *prev; - int protocol = 0; - int subclass = 0; + int result; + unsigned long flags; + + /* these are temporary copies -- we test on these, then put them + * in the us-data structure + */ + __u8 ep_in = 0; + __u8 ep_out = 0; + __u8 ep_int = 0; + __u8 subclass = 0; + __u8 protocol = 0; + + /* the altsettting 0 on the interface we're probing */ struct usb_interface_descriptor *altsetting = &(dev->actconfig->interface[ifnum].altsetting[0]); - /* clear the GUID and fetch the strings */ - GUID_CLEAR(guid); - memset(mf, 0, sizeof(mf)); - memset(prod, 0, sizeof(prod)); - memset(serial, 0, sizeof(serial)); - if (dev->descriptor.iManufacturer) - usb_string(dev, dev->descriptor.iManufacturer, mf, sizeof(mf)); - if (dev->descriptor.iProduct) - usb_string(dev, dev->descriptor.iProduct, prod, sizeof(prod)); - if (dev->descriptor.iSerialNumber) - usb_string(dev, dev->descriptor.iSerialNumber, serial, sizeof(serial)); - - /* let's examine the device now */ - + /* FIXME: this isn't quite right... */ /* We make an exception for the shuttle E-USB */ if (dev->descriptor.idVendor == 0x04e6 && dev->descriptor.idProduct == 0x0001) { @@ -1487,6 +1510,91 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) /* At this point, we know we've got a live one */ US_DEBUGP("USB Mass Storage device detected\n"); + /* + * We are expecting a minimum of 2 endpoints - in and out (bulk). + * An optional interrupt is OK (necessary for CBI protocol). + * We will ignore any others. + */ + for (i = 0; i < altsetting->bNumEndpoints; i++) { + /* is it an BULK endpoint? */ + if ((altsetting->endpoint[i].bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { + if (altsetting->endpoint[i].bEndpointAddress & + USB_DIR_IN) + ep_in = altsetting->endpoint[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + else + ep_out = altsetting->endpoint[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + } + + /* is it an interrupt endpoint? */ + if ((altsetting->endpoint[i].bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { + ep_int = altsetting->endpoint[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + } + } + US_DEBUGP("Endpoints In %d Out %d Int %d\n", + ep_in, ep_out, ep_int); + + /* set the interface -- STALL is an acceptable response here */ + result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0); + US_DEBUGP("Result from usb_set_interface is %d\n", result); + if (result == -EPIPE) { + usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); + } else if (result != 0) { + /* it's not a stall, but another error -- time to bail */ + return NULL; + } + + /* shuttle E-USB */ + /* FIXME: all we should need to do here is determine the protocol */ + if (dev->descriptor.idVendor == 0x04e6 && + dev->descriptor.idProduct == 0x0001) { + __u8 qstat[2]; + + result = usb_control_msg(ss->pusb_dev, + usb_rcvctrlpipe(dev,0), + 1, 0xC0, + 0, ss->ifnum, + qstat, 2, HZ*5); + US_DEBUGP("C0 status 0x%x 0x%x\n", qstat[0], qstat[1]); + init_MUTEX_LOCKED(&(ss->ip_waitq)); + ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); + result = usb_request_irq(ss->pusb_dev, ss->irqpipe, + CBI_irq, 255, (void *)ss, + &ss->irq_handle); + if (result < 0) + return NULL; + + /* FIXME: what is this?? */ + down(&(ss->ip_waitq)); + } + + /* Do some basic sanity checks, and bail if we find a problem */ + if (!ep_in || !ep_out || (protocol == US_PR_CBI && !ep_int)) { + US_DEBUGP("Problems with device\n"); + return NULL; + } + + /* At this point, we're committed to using the device */ + + /* clear the GUID and fetch the strings */ + GUID_CLEAR(guid); + memset(mf, 0, sizeof(mf)); + memset(prod, 0, sizeof(prod)); + memset(serial, 0, sizeof(serial)); + if (dev->descriptor.iManufacturer) + usb_string(dev, dev->descriptor.iManufacturer, mf, + sizeof(mf)); + if (dev->descriptor.iProduct) + usb_string(dev, dev->descriptor.iProduct, prod, + sizeof(prod)); + if (dev->descriptor.iSerialNumber) + usb_string(dev, dev->descriptor.iSerialNumber, serial, + sizeof(serial)); + /* Create a GUID for this device */ if (dev->descriptor.iSerialNumber && serial[0]) { /* If we have a serial number, and it's a non-NULL string */ @@ -1498,23 +1606,50 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) dev->descriptor.idProduct, "0"); } - /* Now check if we have seen this GUID before, and restore - * the flags if we find it + /* lock access to the data structures */ + spin_lock_irqsave(&us_list_spinlock, flags); + + /* + * Now check if we have seen this GUID before + * We're looking for a device with a matching GUID that isn't + * allready on the system */ - for (ss = us_list; ss != NULL; ss = ss->next) { - if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid)) { - US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", - GUID_ARGS(guid)); - flags = ss->flags; - break; + ss = us_list; + while ((ss != NULL) && + ((ss->pusb_dev) || !GUID_EQUAL(guid, ss->guid))) + ss = ss->next; + + if (ss != NULL) { + /* Existing device -- re-connect */ + US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", + GUID_ARGS(guid)); + + /* establish the connection to the new device upon reconnect */ + ss->ifnum = ifnum; + ss->pusb_dev = dev; + + /* hook up the IRQ handler again */ + if (ss->protocol == US_PR_CBI) { + /* set up so we'll wait for notification */ + init_MUTEX_LOCKED(&(ss->ip_waitq)); + + /* set up the IRQ pipe and handler */ + /* FIXME: This needs to get period from the device */ + US_DEBUGP("Allocating IRQ for CBI transport\n"); + ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); + result = usb_request_irq(ss->pusb_dev, ss->irqpipe, + CBI_irq, 255, + (void *)ss, &ss->irq_handle); + US_DEBUGP("usb_request_irq returned %d\n", result); } - } - - /* If ss == NULL, then this is a new device. Allocate memory for it */ - if (!ss) { - if ((ss = (struct us_data *)kmalloc(sizeof(*ss), + } else { + /* New device -- Allocate memory and initialize */ + US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); + + if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data), GFP_KERNEL)) == NULL) { printk(KERN_WARNING USB_STORAGE "Out of memory\n"); + spin_unlock_irqrestore(&us_list_spinlock, flags); return NULL; } memset(ss, 0, sizeof(struct us_data)); @@ -1522,104 +1657,66 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) /* Initialize the mutexes only when the struct is new */ init_MUTEX_LOCKED(&(ss->sleeper)); init_MUTEX(&(ss->queue_exclusion)); - } - - /* establish the connection to the new device */ - interface = altsetting; - ss->flags = flags; - ss->ifnum = ifnum; - ss->attention_done = 0; - ss->pusb_dev = dev; - - /* If the device has subclass and protocol, then use that. Otherwise, - * take data from the specific interface. - */ - if (subclass) { - ss->subclass = subclass; - ss->protocol = protocol; - } else { - ss->subclass = interface->bInterfaceSubClass; - ss->protocol = interface->bInterfaceProtocol; - } - /* set the handler pointers based on the protocol */ - US_DEBUGP("Transport: "); - switch (ss->protocol) { - case US_PR_CB: - US_DEBUGPX("Control/Bulk\n"); - ss->transport = CB_transport; - ss->transport_reset = CB_reset; - break; - - case US_PR_CBI: - US_DEBUGPX("Control/Bulk/Interrupt\n"); - ss->transport = CBI_transport; - ss->transport_reset = CB_reset; - break; - - case US_PR_BULK: - US_DEBUGPX("Bulk\n"); - ss->transport = Bulk_transport; - ss->transport_reset = Bulk_reset; - break; - - default: - US_DEBUGPX("Unknown\n"); - kfree(ss); - return NULL; - break; - } - - /* - * We are expecting a minimum of 2 endpoints - in and out (bulk). - * An optional interrupt is OK (necessary for CBI protocol). - * We will ignore any others. - */ - for (i = 0; i < interface->bNumEndpoints; i++) { - /* is it an BULK endpoint? */ - if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_BULK) { - if (interface->endpoint[i].bEndpointAddress & USB_DIR_IN) - ss->ep_in = interface->endpoint[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - else - ss->ep_out = interface->endpoint[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - } - - /* is it an interrupt endpoint? */ - if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_INT) { - ss->ep_int = interface->endpoint[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; + /* + * If we've allready determined the subclass and protocol, + * use that. Otherwise, use the interface ones. This + * allows us to support devices which are compliant but + * don't announce it. Note that this information is + * maintained in the us_data struct so we only have to do + * this for new devices. + */ + if (subclass) { + ss->subclass = subclass; + ss->protocol = protocol; + } else { + ss->subclass = altsetting->bInterfaceSubClass; + ss->protocol = altsetting->bInterfaceProtocol; } - } - US_DEBUGP("Endpoints In %d Out %d Int %d\n", - ss->ep_in, ss->ep_out, ss->ep_int); - /* Do some basic sanity checks, and bail if we find a problem */ - if (usb_set_interface(dev, interface->bInterfaceNumber, 0) || - !ss->ep_in || !ss->ep_out || - (ss->protocol == US_PR_CBI && ss->ep_int == 0)) { - US_DEBUGP("Problems with device\n"); - if (ss->host) { - kfree(ss->htmplt->name); - kfree(ss->htmplt); - } + /* copy over the endpoint data */ + ss->ep_in = ep_in; + ss->ep_out = ep_out; + ss->ep_int = ep_int; - kfree(ss); - return NULL; - } + /* establish the connection to the new device */ + ss->ifnum = ifnum; + ss->pusb_dev = dev; - /* If this is a new device (i.e. we haven't seen it before), we need to - * generate a scsi host definition, and register with scsi above us - */ - if (!ss->host) { /* copy the GUID we created before */ - US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); memcpy(ss->guid, guid, sizeof(guid)); + + /* + * Set the handler pointers based on the protocol + * Again, this data is persistant across reattachments + */ + US_DEBUGP("Transport: "); + switch (ss->protocol) { + case US_PR_CB: + US_DEBUGPX("Control/Bulk\n"); + ss->transport = CB_transport; + ss->transport_reset = CB_reset; + break; + + case US_PR_CBI: + US_DEBUGPX("Control/Bulk/Interrupt\n"); + ss->transport = CBI_transport; + ss->transport_reset = CB_reset; + break; + + case US_PR_BULK: + US_DEBUGPX("Bulk\n"); + ss->transport = Bulk_transport; + ss->transport_reset = Bulk_reset; + break; + + default: + US_DEBUGPX("Unknown\n"); + kfree(ss); + return NULL; + break; + } - /* set class specific stuff */ US_DEBUGP("Protocol: "); switch (ss->subclass) { case US_SC_RBC: @@ -1656,97 +1753,75 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) break; } - /* Allocate memory for the SCSI Host Template */ - if ((ss->htmplt = (Scsi_Host_Template *) - kmalloc(sizeof(Scsi_Host_Template),GFP_KERNEL))==NULL ) { - printk(KERN_WARNING USB_STORAGE "Out of memory\n"); - - kfree(ss); - return NULL; + if (ss->protocol == US_PR_CBI) { + /* set up so we'll wait for notification */ + init_MUTEX_LOCKED(&(ss->ip_waitq)); + + /* set up the IRQ pipe and handler */ + /* FIXME: This needs to get period from the device */ + US_DEBUGP("Allocating IRQ for CBI transport\n"); + ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); + result = usb_request_irq(ss->pusb_dev, ss->irqpipe, + CBI_irq, 255, + (void *)ss, &ss->irq_handle); + US_DEBUGP("usb_request_irq returned %d", result); } + + /* + * Since this is a new device, we need to generate a scsi + * host definition, and register with the higher SCSI layers + */ /* Initialize the host template based on the default one */ - memcpy(ss->htmplt, &my_host_template, sizeof(my_host_template)); + memcpy(&(ss->htmplt), &my_host_template, + sizeof(my_host_template)); /* Grab the next host number */ ss->host_number = my_host_number++; - - /* MDD: FIXME: this is bad. We abuse this pointer so we + + /* FIXME: this is bad. We abuse this pointer so we * can pass the ss pointer to the host controler thread * in us_detect */ - (struct us_data *)ss->htmplt->proc_dir = ss; - - /* shuttle E-USB */ - if (dev->descriptor.idVendor == 0x04e6 && - dev->descriptor.idProduct == 0x0001) { - __u8 qstat[2]; - int result; - - result = usb_control_msg(ss->pusb_dev, - usb_rcvctrlpipe(dev,0), - 1, 0xC0, - 0, ss->ifnum, - qstat, 2, HZ*5); - US_DEBUGP("C0 status 0x%x 0x%x\n", qstat[0], qstat[1]); - init_MUTEX_LOCKED(&(ss->ip_waitq)); - ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); - result = usb_request_irq(ss->pusb_dev, ss->irqpipe, - CBI_irq, 255, (void *)ss, - &ss->irq_handle); - if (result < 0) - return NULL; - /* FIXME: what is this?? */ - down(&(ss->ip_waitq)); - } else if (ss->protocol == US_PR_CBI) { - int result; - - /* set up so we'll wait for notification */ - init_MUTEX_LOCKED(&(ss->ip_waitq)); - - /* set up the IRQ pipe and handler */ - /* FIXME: This needs to get the period from the device */ - ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); - result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq, - 255, (void *)ss, &ss->irq_handle); - if (result) { - US_DEBUGP("usb_request_irq failed (0x%x), No interrupt for CBI\n", - result); - } - } - - - /* start up our thread */ + (struct us_data *)ss->htmplt.proc_dir = ss; + + /* start up our thread */ { DECLARE_MUTEX_LOCKED(sem); - + ss->notify = &sem; ss->pid = kernel_thread(usb_stor_control_thread, ss, - CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + CLONE_FS | CLONE_FILES | + CLONE_SIGHAND); if (ss->pid < 0) { - printk(KERN_WARNING USB_STORAGE "Unable to start control thread\n"); - kfree(ss->htmplt); - + printk(KERN_WARNING USB_STORAGE + "Unable to start control thread\n"); kfree(ss); return NULL; } - - /* wait for it to start */ + + /* wait for it to start */ down(&sem); } - + /* now register - our detect function will be called */ - ss->htmplt->module = &__this_module; - scsi_register_module(MODULE_SCSI_HA, ss->htmplt); - + ss->htmplt.module = &__this_module; + scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt)); + /* put us in the list */ ss->next = us_list; - us_list = ss; + us_list = ss; } - printk(KERN_DEBUG "WARNING: USB Mass Storage data integrity not assured\n"); - printk(KERN_DEBUG "USB Mass Storage device found at %d\n", dev->devnum); + /* release the data structure lock */ + spin_unlock_irqrestore(&us_list_spinlock, flags); + printk(KERN_DEBUG + "WARNING: USB Mass Storage data integrity not assured\n"); + printk(KERN_DEBUG + "USB Mass Storage device found at %d\n", dev->devnum); + + /* return a pointer for the disconnect function */ return ss; } @@ -1758,6 +1833,14 @@ static void storage_disconnect(struct usb_device *dev, void *ptr) if (!ss) return; + /* FIXME: we need mututal exclusion and resource freeing here */ + + /* release the IRQ, if we have one */ + if (ss->irq_handle) { + usb_release_irq(ss->pusb_dev, ss->irq_handle, ss->irqpipe); + ss->irq_handle = NULL; + } + ss->pusb_dev = NULL; } @@ -1788,12 +1871,15 @@ void __exit usb_stor_exit(void) { static struct us_data *ptr; - // FIXME: this needs to be put back to free _all_ the hosts - // for (ptr = us_list; ptr != NULL; ptr = ptr->next) - // scsi_unregister_module(MODULE_SCSI_HA, ptr->htmplt); - printk("MDD: us_list->htmplt is 0x%x\n", (unsigned int)(us_list->htmplt)); - scsi_unregister_module(MODULE_SCSI_HA, us_list->htmplt); + /* unregister all the virtual hosts */ + for (ptr = us_list; ptr != NULL; ptr = ptr->next) + scsi_unregister_module(MODULE_SCSI_HA, &(ptr->htmplt)); + + /* free up the data structures */ + + /* kill the threads */ + /* deregister the driver */ usb_deregister(&storage_driver) ; } diff --git a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c index 85a5cd476..5dbde2959 100644 --- a/drivers/usb/usb-uhci.c +++ b/drivers/usb/usb-uhci.c @@ -28,6 +28,7 @@ #include #include /* for in_interrupt() */ #include +#include #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,44) #include #endif diff --git a/fs/buffer.c b/fs/buffer.c index dabf1d39c..617188db0 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -147,13 +147,13 @@ void __wait_on_buffer(struct buffer_head * bh) atomic_inc(&bh->b_count); add_wait_queue(&bh->b_wait, &wait); -repeat: - run_task_queue(&tq_disk); - set_task_state(tsk, TASK_UNINTERRUPTIBLE); - if (buffer_locked(bh)) { + do { + run_task_queue(&tq_disk); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (!buffer_locked(bh)) + break; schedule(); - goto repeat; - } + } while (buffer_locked(bh)); tsk->state = TASK_RUNNING; remove_wait_queue(&bh->b_wait, &wait); atomic_dec(&bh->b_count); diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index cef1e93cf..9ed649a3b 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -546,7 +546,7 @@ static int __init init_smb_fs(void) smb_current_vmalloced = 0; #endif - return init_smb_fs(); + return register_filesystem(&smb_fs_type); } static void __exit exit_smb_fs(void) diff --git a/fs/super.c b/fs/super.c index 8aed9ce90..d54e850df 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1093,8 +1093,8 @@ static int copy_mount_options (const void * data, unsigned long *where) * aren't used, as the syscall assumes we are talking to an older * version that didn't understand them. */ -asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, - unsigned long new_flags, void * data) +long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page, + unsigned long new_flags, unsigned long data_page) { struct file_system_type * fstype; struct dentry * dentry = NULL; @@ -1102,28 +1102,19 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, struct block_device *bdev = NULL; int retval; unsigned long flags = 0; - unsigned long page = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - lock_kernel(); + if ((new_flags & (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) { - retval = copy_mount_options (data, &page); - if (retval < 0) - goto out; retval = do_remount(dir_name, new_flags & ~MS_MGC_MSK & ~MS_REMOUNT, - (char *) page); - free_page(page); + (char *) data_page); goto out; } - retval = copy_mount_options (type, &page); - if (retval < 0) - goto out; - fstype = get_fs_type((char *) page); - free_page(page); + fstype = get_fs_type((char *) type_page); retval = -ENODEV; if (!fstype) goto out; @@ -1150,22 +1141,50 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, if (bdops) bdev->bd_op = bdops; } - page = 0; - if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) { + if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) flags = new_flags & ~MS_MGC_MSK; - retval = copy_mount_options(data, &page); - if (retval < 0) - goto dput_and_out; - } + retval = do_mount(bdev, dev_name, dir_name, fstype->name, flags, - (void *) page); - free_page(page); + (void *) data_page); dput_and_out: dput(dentry); fs_out: put_filesystem(fstype); out: + return retval; +} + +asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, + unsigned long new_flags, void * data) +{ + int retval; + unsigned long data_page = 0; + unsigned long type_page = 0; + + lock_kernel(); + retval = copy_mount_options (type, &type_page); + if (retval < 0) + goto out; + + /* copy_mount_options allows a NULL user pointer, + * and just returns zero in that case. But if we + * allow the type to be NULL we will crash. + * Previously we did not check this case. + */ + if (type_page == 0) { + retval = -EINVAL; + goto out; + } + + retval = copy_mount_options (data, &data_page); + if (retval >= 0) { + retval = do_sys_mount(dev_name, dir_name, type_page, + new_flags, data_page); + free_page(data_page); + } + free_page(type_page); +out: unlock_kernel(); return retval; } diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h index d1dde606e..62a72144f 100644 --- a/include/asm-alpha/page.h +++ b/include/asm-alpha/page.h @@ -38,6 +38,8 @@ static inline void clear_page(void * page) } while (count); } +#define clear_user_page(page, vaddr) clear_page(page) + static inline void copy_page(void * _to, void * _from) { unsigned long count = PAGE_SIZE/64; @@ -68,6 +70,8 @@ static inline void copy_page(void * _to, void * _from) } while (count); } +#define copy_user_page(to, from, vaddr) copy_page(to, from) + #ifdef STRICT_MM_TYPECHECKS /* * These are used to make use of C type-checking.. diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h index e33597ff6..e1de021c4 100644 --- a/include/asm-arm/page.h +++ b/include/asm-arm/page.h @@ -14,6 +14,9 @@ #define clear_page(page) memzero((void *)(page), PAGE_SIZE) extern void copy_page(void *to, void *from); +#define clear_user_page(page, vaddr) clear_page(page) +#define copy_user_page(to, from, vaddr) copy_page(to, from) + #ifdef STRICT_MM_TYPECHECKS /* * These are used to make use of C type-checking.. diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h index eb5d9124e..b371bd79f 100644 --- a/include/asm-i386/hw_irq.h +++ b/include/asm-i386/hw_irq.h @@ -189,6 +189,9 @@ extern unsigned long prof_shift; */ static inline void x86_do_profile (unsigned long eip) { + if (!prof_buffer) + return; + /* * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. * (default is all CPUs.) @@ -196,18 +199,16 @@ static inline void x86_do_profile (unsigned long eip) if (!((1<>= prof_shift; - /* - * Don't ignore out-of-bounds EIP values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (eip > prof_len-1) - eip = prof_len-1; - atomic_inc((atomic_t *)&prof_buffer[eip]); - } + eip -= (unsigned long) &_stext; + eip >>= prof_shift; + /* + * Don't ignore out-of-bounds EIP values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (eip > prof_len-1) + eip = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[eip]); } #ifdef __SMP__ /*more of this file should probably be ifdefed SMP */ diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h index 9e159523a..78d07c207 100644 --- a/include/asm-i386/page.h +++ b/include/asm-i386/page.h @@ -30,6 +30,9 @@ #endif +#define clear_user_page(page, vaddr) clear_page(page) +#define copy_user_page(to, from, vaddr) copy_page(to, from) + /* * These are used to make use of C type-checking.. */ diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index 2361bc06d..648ff8a12 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h @@ -40,6 +40,9 @@ extern void clear_page (void *page); extern void copy_page (void *to, void *from); +#define clear_user_page(page, vaddr) clear_page(page) +#define copy_user_page(to, from, vaddr) copy_page(to, from) + # ifdef STRICT_MM_TYPECHECKS /* * These are used to make use of C type-checking.. diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h index 117abf25d..7cf002fb7 100644 --- a/include/asm-m68k/page.h +++ b/include/asm-m68k/page.h @@ -76,6 +76,9 @@ static inline void clear_page(void *page) #define copy_page(to,from) memcpy((to), (from), PAGE_SIZE) #endif +#define clear_user_page(page, vaddr) clear_page(page) +#define copy_user_page(to, from, vaddr) copy_page(to, from) + /* * These are used to make use of C type-checking.. */ diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h index f6c3459b5..fd391fb85 100644 --- a/include/asm-mips/page.h +++ b/include/asm-mips/page.h @@ -28,6 +28,8 @@ extern void (*_copy_page)(void * to, void * from); #define clear_page(page) _clear_page(page) #define copy_page(to, from) _copy_page(to, from) +#define clear_user_page(page, vaddr) clear_page(page) +#define copy_user_page(to, from, vaddr) copy_page(to, from) /* * These are used to make use of C type-checking.. diff --git a/include/asm-mips64/page.h b/include/asm-mips64/page.h index 8f00bf33e..27bcf8346 100644 --- a/include/asm-mips64/page.h +++ b/include/asm-mips64/page.h @@ -29,6 +29,8 @@ extern void (*_copy_page)(void * to, void * from); #define clear_page(page) _clear_page(page) #define copy_page(to, from) _copy_page(to, from) +#define clear_user_page(page, vaddr) clear_page(page) +#define copy_user_page(to, from, vaddr) copy_page(to, from) /* * These are used to make use of C type-checking.. diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h index 1be8ddfa5..e069f8b15 100644 --- a/include/asm-ppc/page.h +++ b/include/asm-ppc/page.h @@ -78,6 +78,8 @@ typedef unsigned long pgprot_t; extern void clear_page(void *page); extern void copy_page(void *to, void *from); +#define clear_user_page(page, vaddr) clear_page(page) +#define copy_user_page(to, from, vaddr) copy_page(to, from) /* map phys->virtual and virtual->phys for RAM pages */ static inline unsigned long ___pa(unsigned long v) diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index 23309458c..1348466a9 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h @@ -26,6 +26,8 @@ #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) #define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) +#define clear_user_page(page, vaddr) clear_page(page) +#define copy_user_page(to, from, vaddr) copy_page(to, from) /* * These are used to make use of C type-checking.. diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h index 68bc526a1..e6011ebbd 100644 --- a/include/asm-sparc/mman.h +++ b/include/asm-sparc/mman.h @@ -1,4 +1,4 @@ -/* $Id: mman.h,v 1.8 1996/10/27 08:55:28 davem Exp $ */ +/* $Id: mman.h,v 1.9 2000/03/15 02:44:23 davem Exp $ */ #ifndef __SPARC_MMAN_H__ #define __SPARC_MMAN_H__ @@ -42,6 +42,13 @@ #define MC_LOCKAS 5 /* Lock an entire address space of the calling process */ #define MC_UNLOCKAS 6 /* Unlock entire address space of calling process */ +#define MADV_NORMAL 0x0 /* default page-in behavior */ +#define MADV_RANDOM 0x1 /* page-in minimum required */ +#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ +#define MADV_WILLNEED 0x3 /* pre-fault pages */ +#define MADV_DONTNEED 0x4 /* discard these pages */ +#define MADV_FREE 0x5 /* (Solaris) contents can be freed */ + /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS #define MAP_FILE 0 diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h index 3c61eb636..0fc2aa247 100644 --- a/include/asm-sparc/page.h +++ b/include/asm-sparc/page.h @@ -1,4 +1,4 @@ -/* $Id: page.h,v 1.48 2000/02/16 07:34:51 davem Exp $ +/* $Id: page.h,v 1.51 2000/03/15 07:19:25 davem Exp $ * page.h: Various defines and such for MMU operations on the Sparc for * the Linux kernel. * @@ -14,7 +14,12 @@ #else #define PAGE_SHIFT 12 #endif +#ifndef __ASSEMBLY__ +/* I have my suspicions... -DaveM */ +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#else #define PAGE_SIZE (1 << PAGE_SHIFT) +#endif #define PAGE_MASK (~(PAGE_SIZE-1)) #ifdef __KERNEL__ @@ -33,8 +38,10 @@ BUG(); \ } while (0) -#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) -#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) +#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) +#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) +#define clear_user_page(page, vaddr) clear_page(page) +#define copy_user_page(to, from, vaddr) copy_page(to, from) /* The following structure is used to hold the physical * memory configuration of the machine. This is filled in diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h index bfb510af7..553e42906 100644 --- a/include/asm-sparc64/mman.h +++ b/include/asm-sparc64/mman.h @@ -1,4 +1,4 @@ -/* $Id: mman.h,v 1.1 1996/12/02 00:07:29 davem Exp $ */ +/* $Id: mman.h,v 1.2 2000/03/15 02:44:26 davem Exp $ */ #ifndef __SPARC64_MMAN_H__ #define __SPARC64_MMAN_H__ @@ -42,6 +42,13 @@ #define MC_LOCKAS 5 /* Lock an entire address space of the calling process */ #define MC_UNLOCKAS 6 /* Unlock entire address space of calling process */ +#define MADV_NORMAL 0x0 /* default page-in behavior */ +#define MADV_RANDOM 0x1 /* page-in minimum required */ +#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ +#define MADV_WILLNEED 0x3 /* pre-fault pages */ +#define MADV_DONTNEED 0x4 /* discard these pages */ +#define MADV_FREE 0x5 /* (Solaris) contents can be freed */ + /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS #define MAP_FILE 0 diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h index 7653f4af1..757f43c4d 100644 --- a/include/asm-sparc64/page.h +++ b/include/asm-sparc64/page.h @@ -1,4 +1,4 @@ -/* $Id: page.h,v 1.30 2000/02/16 07:34:54 davem Exp $ */ +/* $Id: page.h,v 1.32 2000/03/15 07:19:28 davem Exp $ */ #ifndef _SPARC64_PAGE_H #define _SPARC64_PAGE_H @@ -23,6 +23,8 @@ extern void clear_page(void *page); extern void copy_page(void *to, void *from); +extern void clear_user_page(void *page, unsigned long vaddr); +extern void copy_user_page(void *to, void *from, unsigned long vaddr); /* GROSS, defining this makes gcc pass these types as aggregates, * and thus on the stack, turn this crap off... -DaveM diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h index dac004a6b..0d1ca71cd 100644 --- a/include/asm-sparc64/parport.h +++ b/include/asm-sparc64/parport.h @@ -1,4 +1,4 @@ -/* $Id: parport.h,v 1.7 2000/01/28 13:43:14 jj Exp $ +/* $Id: parport.h,v 1.8 2000/03/14 04:37:53 davem Exp $ * parport.h: sparc64 specific parport initialization and dma. * * Copyright (C) 1999 Eddie C. Dost (ecd@skynet.be) @@ -7,7 +7,6 @@ #ifndef _ASM_SPARC64_PARPORT_H #define _ASM_SPARC64_PARPORT_H 1 -#include #include #include diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 2e31d77f2..3049ad259 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -29,6 +29,15 @@ extern inline unsigned int nr_free_highpages(void) { return 0; } #endif /* CONFIG_HIGHMEM */ /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ +extern inline void clear_user_highpage(struct page *page, unsigned long vaddr) +{ + unsigned long kaddr; + + kaddr = kmap(page); + clear_user_page((void *)kaddr, vaddr); + kunmap(page); +} + extern inline void clear_highpage(struct page *page) { unsigned long kaddr; @@ -64,6 +73,17 @@ extern inline void memclear_highpage_flush(struct page *page, unsigned int offse kunmap(page); } +extern inline void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr) +{ + unsigned long vfrom, vto; + + vfrom = kmap(from); + vto = kmap(to); + copy_user_page((void *)vto, (void *)vfrom, vaddr); + kunmap(from); + kunmap(to); +} + extern inline void copy_highpage(struct page *to, struct page *from) { unsigned long vfrom, vto; diff --git a/include/linux/kernel.h b/include/linux/kernel.h index d5b204c2c..02341868d 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -15,8 +15,10 @@ #define barrier() __asm__ __volatile__("": : :"memory") #define INT_MAX ((int)(~0U>>1)) +#define INT_MIN (-INT_MAX - 1) #define UINT_MAX (~0U) #define LONG_MAX ((long)(~0UL>>1)) +#define LONG_MIN (-LONG_MAX - 1) #define ULONG_MAX (~0UL) #define STACK_MAGIC 0xdeadbeef diff --git a/include/linux/pci.h b/include/linux/pci.h index 589ddd4e4..413def0a9 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -578,8 +578,8 @@ extern inline void pci_set_master(struct pci_dev *dev) { } extern inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } extern inline int pci_module_init(struct pci_driver *drv) { return -ENODEV; } extern inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;} -extern inline int pci_register_driver(struct pci_driver *) { return 0;} -extern inline void pci_unregister_driver(struct pci_driver *) { } +extern inline int pci_register_driver(struct pci_driver *drv) { return 0;} +extern inline void pci_unregister_driver(struct pci_driver *drv) { } #else diff --git a/ipc/shm.c b/ipc/shm.c index cb7e2c33a..64039d6fd 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -71,6 +71,7 @@ struct shmid_kernel /* private to the kernel */ unsigned long shm_npages; /* size of segment (pages) */ pte_t **shm_dir; /* ptr to arr of ptrs to frames */ int id; + int destroyed; /* set if the final detach kills */ union permap { struct shmem { time_t atime; @@ -115,6 +116,7 @@ static int newseg (key_t key, const char *name, int namelen, int shmflg, size_t static void killseg_core(struct shmid_kernel *shp, int doacc); static void shm_open (struct vm_area_struct *shmd); static void shm_close (struct vm_area_struct *shmd); +static void shm_remove_name(int id); static struct page * shm_nopage(struct vm_area_struct *, unsigned long, int); static int shm_swapout(struct page *, struct file *); #ifdef CONFIG_PROC_FS @@ -310,6 +312,20 @@ static int shm_remount_fs (struct super_block *sb, int *flags, char *data) return 0; } +static struct fs_struct *shm_push_root(void) +{ + struct fs_struct *old,*new; + new=init_task_union.task.fs; + old=current->fs; + current->fs=new; + return old; +} + +static void shm_pop_root(struct fs_struct *saved) +{ + current->fs=saved; +} + static void shm_put_super(struct super_block *sb) { struct super_block **p = &shm_sb; @@ -881,9 +897,8 @@ char * shm_getname(int id) { char *result; - result = __getname (); - if (IS_ERR(result)) - return result; + if (!(result = __getname ())) + return ERR_PTR(-ENOMEM); sprintf (result, "%s/" SHM_FMT, shm_path, id); return result; @@ -1018,18 +1033,36 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) } case IPC_RMID: { - char *name; + /* + * We cannot simply remove the file. The SVID states + * that the block remains until the last person + * detaches from it, then is deleted. A shmat() on + * an RMID segment is legal in older Linux and if + * we change it apps break... + * + * Instead we set a destroyed flag, and then blow + * the name away when the usage hits zero. + */ if ((shmid % SEQ_MULTIPLIER)== zero_id) return -EINVAL; - name = shm_getname(shmid); - if (IS_ERR(name)) - return PTR_ERR(name); lock_kernel(); - err = do_unlink (name); + shp = shm_lock(shmid); + if(shp==NULL) + { + unlock_kernel(); + return -EINVAL; + } + err=-EIDRM; + if(shm_checkid(shp,shmid)==0) + { + if(shp->shm_nattch==0) + shm_remove_name(shmid); + else + shp->destroyed=1; + err=0; + } + shm_unlock(shmid); unlock_kernel(); - putname (name); - if (err == -ENOENT) - err = -EINVAL; return err; } @@ -1109,6 +1142,7 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) int err; int flags; char *name; + struct fs_struct *saved; if (!shm_sb || (shmid % SEQ_MULTIPLIER) == zero_id) return -EINVAL; @@ -1130,12 +1164,14 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) return PTR_ERR (name); lock_kernel(); + saved=shm_push_root(); file = filp_open (name, O_RDWR, 0); + shm_pop_root(saved); + putname (name); - if (IS_ERR (file)) { - unlock_kernel(); + if (IS_ERR (file)) goto bad_file; - } + *raddr = do_mmap (file, addr, file->f_dentry->d_inode->i_size, (shmflg & SHM_RDONLY ? PROT_READ : PROT_READ | PROT_WRITE), flags, 0); @@ -1148,6 +1184,7 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) return err; bad_file: + unlock_kernel(); if ((err = PTR_ERR(file)) == -ENOENT) return -EINVAL; return err; @@ -1160,6 +1197,23 @@ static void shm_open (struct vm_area_struct *shmd) } /* + * Remove a name. Must be called with lock_kernel + */ + +static void shm_remove_name(int id) +{ + char *name = shm_getname(id); + if (!IS_ERR(name)) + { + struct fs_struct *saved; + saved=shm_push_root(); + do_unlink (name); + shm_pop_root(saved); + putname (name); + } +} + +/* * remove the attach descriptor shmd. * free memory for segment if it is marked destroyed. * The descriptor has already been removed from the current->mm->mmap list @@ -1176,7 +1230,14 @@ static void shm_close (struct vm_area_struct *shmd) shp->shm_lprid = current->pid; shp->shm_dtim = CURRENT_TIME; shp->shm_nattch--; - shm_unlock(id); + if(shp->shm_nattch==0 && shp->destroyed) + { + shp->destroyed=0; + shm_remove_name(id); + shm_unlock(id); + } + else + shm_unlock(id); } /* @@ -1214,13 +1275,13 @@ static int shm_swapout(struct page * page, struct file *file) /* * page not present ... go through shm_dir */ -static struct page * shm_nopage_core(struct shmid_kernel *shp, unsigned int idx, int *swp, int *rss) +static struct page * shm_nopage_core(struct shmid_kernel *shp, unsigned int idx, int *swp, int *rss, unsigned long address) { pte_t pte; struct page * page; if (idx >= shp->shm_npages) - goto sigbus; + return NOPAGE_SIGBUS; pte = SHM_ENTRY(shp,idx); if (!pte_present(pte)) { @@ -1232,7 +1293,7 @@ static struct page * shm_nopage_core(struct shmid_kernel *shp, unsigned int idx, page = alloc_page(GFP_HIGHUSER); if (!page) goto oom; - clear_highpage(page); + clear_user_highpage(page, address); if ((shp != shm_lock(shp->id)) && (shp->id != zero_id)) BUG(); } else { @@ -1267,9 +1328,8 @@ static struct page * shm_nopage_core(struct shmid_kernel *shp, unsigned int idx, return pte_page(pte); oom: + shm_lock(shp->id); return NOPAGE_OOM; -sigbus: - return NOPAGE_SIGBUS; } static struct page * shm_nopage(struct vm_area_struct * shmd, unsigned long address, int no_share) @@ -1285,7 +1345,7 @@ static struct page * shm_nopage(struct vm_area_struct * shmd, unsigned long addr down(&inode->i_sem); if(!(shp = shm_lock(inode->i_ino))) BUG(); - page = shm_nopage_core(shp, idx, &shm_swp, &shm_rss); + page = shm_nopage_core(shp, idx, &shm_swp, &shm_rss, address); shm_unlock(inode->i_ino); up(&inode->i_sem); return(page); @@ -1657,7 +1717,7 @@ static struct page * shmzero_nopage(struct vm_area_struct * shmd, unsigned long shp = VMA_TO_SHP(shmd); down(&shp->zsem); shm_lock(zero_id); - page = shm_nopage_core(shp, idx, &dummy, &zshm_rss); + page = shm_nopage_core(shp, idx, &dummy, &zshm_rss, address); shm_unlock(zero_id); up(&shp->zsem); return(page); diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 0a22f820a..760d2e468 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -360,6 +360,7 @@ EXPORT_SYMBOL(free_kiovec); EXPORT_SYMBOL(expand_kiobuf); EXPORT_SYMBOL(map_user_kiobuf); +EXPORT_SYMBOL(unmap_kiobuf); EXPORT_SYMBOL(lock_kiovec); EXPORT_SYMBOL(unlock_kiovec); EXPORT_SYMBOL(brw_kiovec); diff --git a/mm/filemap.c b/mm/filemap.c index 3fb7d011c..124ddfae3 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1413,7 +1413,7 @@ success: struct page *new_page = page_cache_alloc(); if (new_page) { - copy_highpage(new_page, old_page); + copy_user_highpage(new_page, old_page, address); flush_page_to_ram(new_page); } else new_page = NOPAGE_OOM; diff --git a/mm/memory.c b/mm/memory.c index dbcdd0052..9d1a131ff 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -61,10 +61,10 @@ struct page *highmem_start_page; static inline void copy_cow_page(struct page * from, struct page * to, unsigned long address) { if (from == ZERO_PAGE(address)) { - clear_highpage(to); + clear_user_highpage(to, address); return; } - copy_highpage(to, from); + copy_user_highpage(to, from, address); } mem_map_t * mem_map = NULL; @@ -1073,7 +1073,7 @@ static int do_anonymous_page(struct task_struct * tsk, struct vm_area_struct * v return -1; if (PageHighMem(page)) high = 1; - clear_highpage(page); + clear_user_highpage(page, addr); entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))); vma->vm_mm->rss++; tsk->min_flt++; -- 2.11.4.GIT