From 2f89c9c7facad8f39c25016488154b85fc1b4248 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 23 Nov 2007 15:19:37 -0500 Subject: [PATCH] Linux 2.2.13pre1 o execve() fix - based on one by (Tymm Twillman) p ext2fs flag fixes (Matthias Riese) o i2c tuner update (from Pauline Middelink) o bttv schedule on irq fix o Console race fixes/klogd (Andrea Arcangeli) o Ensure version is up to date (David Woodhouse) o QlogicFC fixes (Chris Loveland) o Fix memory leaks in the serial layer (Armin Groesslinger) o ARM sound fixes (Phil Blundell) o Assorted warning cleanups (Riley Williams) o Fix arcnet bug in 2.2.12 (Riley Williams) o Small NFS fixes (Trond Myklebust) o Updated sb1000 docs (Clemmitt Sigler) o Fix IPX packet handling (Kelly French) o PCI multifunction fixes (Martin Mares) o Back out mmap resource change (Dick Streefland) o Minor cleanups (Mikael Pettersson) o Fix vt console print (Andrea Arcangeli) o Rate limit a.out binfmt errors (Alan Cox) o Generate different ksyms for 1G/2G (Alan Cox) o Small cleanups (David Weinehall) o Munmap, vm cache fix (Stephen Tweedie) --- Documentation/networking/README.sb1000 | 340 +++++++++++++++---------- Rules.make | 12 + arch/i386/Makefile | 1 + arch/i386/boot/Makefile | 4 +- arch/i386/kernel/apm.c | 2 +- drivers/char/bttv.c | 20 +- drivers/char/console.c | 6 +- drivers/char/lp.c | 5 +- drivers/char/n_tty.c | 1 + drivers/char/pms.c | 12 +- drivers/char/serial.c | 6 + drivers/char/tty_io.c | 20 +- drivers/char/tuner.c | 15 +- drivers/net/arcnet.c | 2 +- drivers/net/e2100.c | 2 +- drivers/net/sb1000.c | 1 + drivers/net/tlan.c | 4 +- drivers/pci/pci.c | 4 +- drivers/scsi/qlogicfc.c | 64 +++-- drivers/scsi/sd.c | 6 +- drivers/sound/ad1848.c | 7 +- drivers/sound/dmabuf.c | 13 +- drivers/sound/opl3sa.c | 2 +- drivers/sound/sonicvibes.c | 3 +- fs/binfmt_aout.c | 13 +- fs/exec.c | 2 +- fs/ext2/file.c | 3 +- fs/ext2/inode.c | 8 +- fs/nfs/inode.c | 4 +- include/asm-i386/spinlock.h | 6 +- include/linux/i2c.h | 1 + include/linux/pagemap.h | 1 + kernel/ksyms.c | 1 + kernel/printk.c | 146 +++++++---- mm/filemap.c | 39 ++- mm/mmap.c | 7 +- net/ipx/af_ipx.c | 1 + 37 files changed, 509 insertions(+), 275 deletions(-) diff --git a/Documentation/networking/README.sb1000 b/Documentation/networking/README.sb1000 index 025a245f242c..37c39a0c86f8 100644 --- a/Documentation/networking/README.sb1000 +++ b/Documentation/networking/README.sb1000 @@ -1,133 +1,207 @@ -This is the new release of a module network device driver for General -Instruments (also known as NextLevel) SB1000 cable modem board (also -called internal SURFboard). -I have tested and I am running this module on kernel 2.0.33. -Steven N. Hirsch gave me a diff patch -(sb1000-1.1.2_127.patch to be applied with 'patch -p') that allows -you to compile and run the driver with kernel versions 2.1.x. -Thanks very much Steve! - -Here you'll the following files: - -- README -- Makefile -- sb1000.c the actual device driver -- cmconfig.c an ifconfig-like program to correctly set the SB1000 -- cmping.c a ping-like program to test your connection -- ftptest.c a small program to test your connection speed with FTP - (requires ftplib version >= 3.0) - -The directory ppp/ contains the files I am using to connect to MediaOne -here in Jacksonville, to show how you can use the driver and the cmconfig -program. - -Clemmitt Sigler wrote a very good and useful web page and installation -script (for Adelphia PowerLink users but easy to port to other ISPs) -about this SB1000 driver for Linux. -You can find it here: - http://home.adelphia.net/~siglercm/sb1000.html -Thanks very much Clemmitt! - -To install and run it: -- cd sb1000-1.1.2 -- make -- make install -- configure the SB1000 card using the isapnp tools setting the correct - I/O's and IRQ. You can find more info about the isapnp tools at: - http://www.roestock.demon.co.uk/isapnptools/ - (once you're happy with it, you may want to set the configuration - at boot time in one of the /etc/init.d/ scripts) - IMPORTANT NOTICE: after configuring isapnp, please look in the file - /etc/isapnp.conf for the line beginning with: - (READPORT - if it says: '(READPORT 0x0203)' (which should be the default), then - go to the next step. If instead it says something like: - '(READPORT 0x020b)' or '(READPORT 0x)', then please - follow the instructions at the end of this README file before going - to the next step. -- install the PPP configuration files in the /etc/ppp directory; you - definitely have to change the file ppp@gi-on (the start up file), - setting the correct login name, the phone number for the PPP connection - and the frequency (k stands for kHz, M for MHz) for the cablemodem. - You'll also have to change the last line in the pap-secrets file - writing your login and password there (read the whole file for more - site specific configurations). - You may have to change the firewall file to suit your needs (IPs and - ports allowed to connect). -- start the PPP connection with ppp@gi-on and see what happens; you may - want to set 'pppd' (the last command in the ppp@gi-on file) to debug - mode adding 'debug' at the end of the command ('pppd' prints its info in - the file /var/log/messages and/or /var/log/ppp.log). To make sure 'chat' - s not having problems you may want to add a '-v' (verbose) after the 'chat' - command in 'ppp-on-dialer' and check the results in /var/log/messages) -- if everything is working fine you should see after a few seconds a message - likes this: - cm0: sb1000 at (0x120,0x310), csn 1, S/N 0x2a0d16d8, IRQ 9. - sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net) - and ifconfig -a should show you two new interfaces: ppp0 and cm0. - Typing 'cmconfig cm0' will show you more info about the cablemodem interface. -- please let me know if you see any other message coming from 'cm0' in - your '/var/log/messages' or '/var/log/debug' file, to help me debug the - code -- also let me know if you have any problem; if everything works (hopefully), - let me know which speed you can reach downloading the 5Mb test file using - this driver. -- if everything seems to work fine but your computer locks up after a while - (and typically during a lengthy download through the cablemodem), you may - need to add a short delay in the driver to 'slow down' the SURFboard - because your PC might not be able to keep up with the transfer rate of - the SB1000. To do this, edit the 'Makefile' and look for the 'SB1000_DELAY' - define: uncomment those 'CFLAGS' lines (and comment the default ones) - and try setting the delay to something like 60 microseconds with: - '-DSB1000_DELAY=60'; if it still doesn't work or you like playing with - the driver, you may try other numbers: remember though that the higher - the delay, the slower the driver (which slows down the rest of the PC - too when it is actively used). Thanks to Ed Daiga for this tip! - -This release has a few things fixed and a better handling of the frame errors. - -I also have slightly modified the 'cablemodem' script in the 'ppp' so -you may interested in having a look at it: I basically have added filtering -out broadcast messages (you shouldn't get them with a point-to-point -interface and so far the ones I have received were from hosts trying to -attack my system) and lower debug levels for the driver to avoid seeing -the 'frame error' messages (so far noone has noticed any problem with the -driver even with those messages). - -For questions, infos, etc, feel free to email me at: - fventuri@mediaone.net - -Good luck, -Franco Venturi - -Thanks to Edge for his useful comments and to Steven N. Hirsch -for his patch to run the driver with 2.1.x kernels. -Thanks also to Ed Daiga for his help in finding that adding a delay -in the driver fixes some lock up problems with some slow PCs. -Many thanks to Clemmitt Sigler for his (much needed) web page about the -SB1000 driver for Linux. -An interesting URL for Linux + MediaOne (although with an external modem) -is: http://rlz.ne.mediaone.net/linux/home.shtml -Today, Sep 22 1998, I finished writing a short utility (ftptest.c) to -'measure' your cablemodem speed connection in Linux, downloading to -memory the same file several times. To compile it you need ftplib, version -3 or above. To run it, type: - ftptest URL n -where URL is in the form: ftp://ftp.site.local.isp/pub/testfile -and n is the number of simultaneous FTP connections that you want to run - ---------------------------------------------------------------------------- -IMPORTANT NOTICE: if in your file /etc/isapnp.conf, you found something -like '(READPORT 0x020b)' or '(READPORT 0x)', (anything -different from the default 0x0203), you have to change the READ_DATA_PORT -parameter in the sb1000.c file as follows. - - edit the sb1000.c file, look for: - READ_DATA_PORT - (it should be around line 127 in version 1.1.2) - - change the value of READ_DATA_PORT to the same value found in - /etc/isapnp.conf; for instance, if you found a: '(READPORT 0x020b)', - then in sb1000.c you should have: - static const int READ_DATA_PORT = 0x20b; - - save sb1000.c - - compile and install again the driver - (i.e. do a 'make' and a 'make install'). +sb1000 is a module network device driver for the General Instrument (also known +as NextLevel) SURFboard1000 internal cable modem board. This is an ISA card +which is used by a number of cable TV companies to provide cable modem access. +It's a one-way downstream-only cable modem, meaning that your upstream net link +is provided by your regular phone modem. + +This driver was written by Franco Venturi . He deserves +a great deal of thanks for this wonderful piece of code! + +----------------------------------------------------------------------------- + +Support for this device is now a part of the standard Linux kernel. The +driver source code file is drivers/net/sb1000.c. In addition to this +you will need: + +1.) The "cmconfig" program. This is a utility which supplements "ifconfig" +to configure the cable modem and network interface (usually called "cm0"); +and + +2.) Several PPP scripts which live in /etc/ppp to make connecting via your +cable modem easy. + + These utilities can be obtained from: + + http://www.jacksonville.net/~fventuri/ + + in Franco's original source code distribution .tar.gz file. Support for + the sb1000 driver can be found at: + + http://home.adelphia.net/~siglercm/sb1000.html + http://linuxpower.cx/~cable/ + + along with these utilties. + +3.) The standard isapnp tools. These are necessary to configure your SB1000 +card at boot time (or afterwards by hand) since it's a PnP card. + + If you don't have these installed as a standard part of your Linux + distribution, you can find them at: + + http://www.roestock.demon.co.uk/isapnptools/ + + or check your Linux distribution binary CD or their web site. For help with + isapnp, pnpdump, or /etc/isapnp.conf, go to: + + http://www.roestock.demon.co.uk/isapnptools/isapnpfaq.html + +----------------------------------------------------------------------------- + +To make the SB1000 card work, follow these steps: + +1.) Run `make config', or `make menuconfig', or `make xconfig', whichever +you prefer, in the top kernel tree directory to set up your kernel +configuration. Make sure to say "Y" to "Prompt for development drivers" +and to say "M" to the sb1000 driver. Also say "Y" or "M" to all the standard +networking questions to get TCP/IP and PPP networking support. + +2.) *BEFORE* you build the kernel, edit drivers/net/sb1000.c. Make sure +to redefine the value of READ_DATA_PORT to match the I/O address used +by isapnp to access your PnP cards. This is the value of READPORT in +/etc/isapnp.conf or given by the output of pnpdump. + +3.) Build and install the kernel and modules as usual. + +4.) Boot your new kernel following the usual procedures. + +5.) Set up to configure the new SB1000 PnP card by capturing the output +of "pnpdump" to a file and editing this file to set the correct I/O ports, +IRQ, and DMA settings for all your PnP cards. Make sure none of the settings +conflict with one another. Then test this configuration by running the +"isapnp" command with your new config file as the input. Check for +errors and fix as necessary. (As an aside, I use I/O ports 0x110 and +0x310 and IRQ 11 for my SB1000 card and these work well for me. YMMV.) +Then save the finished config file as /etc/isapnp.conf for proper configuration +on subsequent reboots. + +6.) Download the original file sb1000-1.1.2.tar.gz from Franco's site or one of +the others referenced above. As root, unpack it into a temporary directory and +do a `make cmconfig' and then `install -c cmconfig /usr/local/sbin'. Don't do +`make install' because it expects to find all the utilities built and ready for +installation, not just cmconfig. + +7.) As root, copy all the files under the ppp/ subdirectory in Franco's +tar file into /etc/ppp, being careful not to overwrite any files that are +already in there. Then modify ppp@gi-on to set the correct login name, +phone number, and frequency for the cable modem. Also edit pap-secrets +to specify your login name and password and any site-specific information +you need. + +8.) Be sure to modify /etc/ppp/firewall to use ipchains instead of +the older ipfwadm commands from the 2.0.x kernels. There's a neat utility to +convert ipfwadm commands to ipchains commands: + + http://users.dhp.com/~whisper/ipfwadm2ipchains/ + +You may also wish to modify the firewall script to implement a different +firewalling scheme. + +9.) Start the PPP connection via the script /etc/ppp/ppp@gi-on. You must be +root to do this. It's better to use a utility like sudo to execute +frequently used commands like this with root permissions if possible. If you +connect successfully the cable modem interface will come up and you'll see a +driver message like this at the console: + + cm0: sb1000 at (0x110,0x310), csn 1, S/N 0x2a0d16d8, IRQ 11. + sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net) + +The "ifconfig" command should show two new interfaces, ppp0 and cm0. +The command "cmconfig cm0" will give you information about the cable modem +interface. + +10.) Try pinging a site via `ping -c 5 www.yahoo.com', for example. You should +see packets received. + +11.) If you can't get site names (like www.yahoo.com) to resolve into +IP addresses (like 204.71.200.67), be sure your /etc/resolv.conf file +has no syntax errors and has the right nameserver IP addresses in it. +If this doesn't help, try something like `ping -c 5 204.71.200.67' to +see if the networking is running but the DNS resolution is where the +problem lies. + +12.) If you still have problems, go to the support web sites mentioned above +and read the information and documentation there. + +----------------------------------------------------------------------------- + +Common problems: + +1.) Packets go out on the ppp0 interface but don't come back on the cm0 +interface. It looks like I'm connected but I can't even ping any +numerical IP addresses. (This happens predominantly on Debian systems due +to a default boot-time configuration script.) + +Solution -- As root `echo 0 > /proc/sys/net/ipv4/conf/cm0/rp_filter' so it +can share the same IP address as the ppp0 interface. Note that this +command should probably be added to the /etc/ppp/cablemodem script +*right*between* the "/sbin/ifconfig" and "/sbin/cmconfig" commands. +You may need to do this to /proc/sys/net/ipv4/conf/ppp0/rp_filter as well. +If you do this to /proc/sys/net/ipv4/conf/default/rp_filter on each reboot +(in rc.local or some such) then any interfaces can share the same IP +addresses. + +2.) I get "unresolved symbol" error messages on executing `insmod sb1000.o'. + +Solution -- You probably have a non-matching kernel source tree and +/usr/include/linux and /usr/include/asm header files. Make sure you +install the correct versions of the header files in these two directories. +Then rebuild and reinstall the kernel. + +3.) When isapnp runs it reports an error, and my SB1000 card isn't working. + +Solution -- There's a problem with later versions of isapnp using the "(CHECK)" +option in the lines that allocate the two I/O addresses for the SB1000 card. +This first popped up on RH 6.0. Delete "(CHECK)" for the SB1000 I/O addresses. +Make sure they don't conflict with any other pieces of hardware first! Then +rerun isapnp and go from there. + +4.) I can't execute the /etc/ppp/ppp@gi-on file. + +Solution -- As root do `chmod ug+x /etc/ppp/ppp@gi-on'. + +5.) The firewall script isn't working (with 2.2.x and higher kernels). + +Solution -- Use the ipfwadm2ipchains script referenced above to convert the +/etc/ppp/firewall script from the deprecated ipfwadm commands to ipchains. + +6.) I'm getting *tons* of firewall deny messages in the /var/kern.log, +/var/messages, and/or /var/syslog files, and they're filling up my /var +partition!!! + +Solution -- First, tell your ISP that you're receiving DoS (Denial of Service) +and/or portscanning (UDP connection attempts) attacks! Look over the deny +messages to figure out what the attack is and where it's coming from. Next, +edit /etc/ppp/cablemodem and make sure the ",nobroadcast" option is turned on +to the "cmconfig" command (uncomment that line). If you're not receiving these +denied packets on your broadcast interface (IP address xxx.yyy.zzz.255 +typically), then someone is attacking your machine in particular. Be careful +out there.... + +7.) Everything seems to work fine but my computer locks up after a while +(and typically during a lengthy download through the cable modem)! + +Solution -- You may need to add a short delay in the driver to 'slow down' the +SURFboard because your PC might not be able to keep up with the transfer rate +of the SB1000. To do this, it's probably best to download Franco's +sb1000-1.1.2.tar.gz archive and build and install sb1000.o manually. You'll +want to edit the 'Makefile' and look for the 'SB1000_DELAY' +define. Uncomment those 'CFLAGS' lines (and comment out the default ones) +and try setting the delay to something like 60 microseconds with: +'-DSB1000_DELAY=60'. Then do `make' and as root `make install' and try +it out. If it still doesn't work or you like playing with the driver, you may +try other numbers. Remember though that the higher the delay, the slower the +driver (which slows down the rest of the PC too when it is actively +used). Thanks to Ed Daiga for this tip! + +----------------------------------------------------------------------------- + +Credits: This README came from Franco Venturi's original README file which is +still supplied with his driver .tar.gz archive. I and all other sb1000 users +owe Franco a tremendous "Thank you!" Additional thanks goes to Carl Patten +and Ralph Bonnell who are now managing the Linux SB1000 web site, and to +the SB1000 users who reported and helped debug the common problems listed +above. + + + Clemmitt Sigler + csigler@vt.edu diff --git a/Rules.make b/Rules.make index 948c33dcd583..9d0311f8f44d 100644 --- a/Rules.make +++ b/Rules.make @@ -203,6 +203,18 @@ else genksyms_smp_prefix := endif +# +# Differ 1 and 2Gig kernels to avoid module misload errors +# + +ifdef CONFIG_2GB +ifdef CONFIG_SMP + genksyms_smp_prefix := -p smp2gig_ +else + genksyms_smp_prefix := -p 2gig_ +endif +endif + $(MODINCL)/%.ver: %.c @if [ ! -r $(MODINCL)/$*.stamp -o $(MODINCL)/$*.stamp -ot $< ]; then \ echo '$(CC) $(CFLAGS) -E -D__GENKSYMS__ $<'; \ diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 5fdf91e83d94..bcd555c3b574 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -96,6 +96,7 @@ archclean: @$(MAKEBOOT) clean archmrproper: + rm -f arch/i386/vmlinux.lds archdep: @$(MAKEBOOT) dep diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile index 64b9377a2688..eccc87ddb288 100644 --- a/arch/i386/boot/Makefile +++ b/arch/i386/boot/Makefile @@ -51,7 +51,7 @@ setup: setup.o setup.o: setup.s $(AS86) -o $@ $< -setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h +setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ bsetup: bsetup.o @@ -60,7 +60,7 @@ bsetup: bsetup.o bsetup.o: bsetup.s $(AS86) -o $@ $< -bsetup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h +bsetup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h $(CPP) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ bootsect: bootsect.o diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 6eba89025997..e77575e0703f 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -289,7 +289,7 @@ extern void apm_unregister_callback(int (*)(apm_event_t)); /* * Local variables */ -static asmlinkage struct { +static struct { unsigned long offset; unsigned short segment; } apm_bios_entry; diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index 25316c0148d0..d74959adef0f 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -1288,7 +1288,7 @@ static inline void bt848_set_eogeo(struct bttv *btv, int odd, u8 vtc, } -static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt) +static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt, int pll) { u16 vscale, hscale; u32 xsf, sr; @@ -1297,9 +1297,13 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt) u16 inter; u8 crop, vtc; struct tvnorm *tvn; + unsigned long flags; if (!width || !height) return; + + save_flags(flags); + cli(); tvn=&tvnorms[btv->win.norm]; @@ -1324,7 +1328,8 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt) btwrite(1, BT848_VBI_PACK_DEL); btv->pll.pll_ofreq = tvn->Fsc; - set_pll(btv); + if(pll) + set_pll(btv); btwrite(fmt, BT848_COLOR_FMT); #ifdef __sparc__ @@ -1372,6 +1377,7 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt) hdelay, vdelay, crop); bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, vactive, hdelay, vdelay, crop); + restore_flags(flags); } @@ -1400,7 +1406,7 @@ static void bt848_set_winsize(struct bttv *btv) else btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL); - bt848_set_geo(btv, btv->win.width, btv->win.height, format); + bt848_set_geo(btv, btv->win.width, btv->win.height, format, 1); } /* @@ -3436,14 +3442,14 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) btv->risc_jmp[11]=cpu_to_le32(btv->gre); bt848_set_geo(btv, btv->gwidth, btv->gheight, - btv->gfmt); + btv->gfmt, 0); } else { bt848_set_risc_jmps(btv); btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI); btand(~BT848_VSCALE_COMB, BT848_O_VSCALE_HI); bt848_set_geo(btv, btv->win.width, btv->win.height, - btv->win.color_fmt); + btv->win.color_fmt, 0); } wake_up_interruptible(&btv->capq); break; @@ -3454,7 +3460,7 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) btv->risc_jmp[11]=cpu_to_le32(btv->gre); btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP); bt848_set_geo(btv, btv->gwidth, btv->gheight, - btv->gfmt); + btv->gfmt, 0); } } if (astat&BT848_INT_OCERR) @@ -3557,7 +3563,7 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) remap[bttv_num]|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK); pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, remap[bttv_num]); pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dw); - btv->dev->base_address[0] = btv->bt848_adr; + btv->dev->base_address[0] = btv->bt848_adr = dw; } btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK; pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); diff --git a/drivers/char/console.c b/drivers/char/console.c index cea651b2827e..98c8e56daf9b 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -1984,7 +1984,7 @@ void vt_console_print(struct console *co, const char * b, unsigned count) static unsigned long printing = 0; const ushort *start; ushort cnt = 0; - ushort myx = x; + ushort myx; /* console busy or not yet initialized */ if (!printable || test_and_set_bit(0, &printing)) @@ -1993,6 +1993,10 @@ void vt_console_print(struct console *co, const char * b, unsigned count) if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) currcons = kmsg_redirect - 1; + /* read `x' only after setting currecons properly (otherwise + the `x' macro will read the x of the foreground console). */ + myx = x; + if (!vc_cons_allocated(currcons)) { /* impossible */ printk("vt_console_print: tty %d not allocated ??\n", currcons+1); diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 996c15019520..308ad9f1833b 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -249,7 +249,8 @@ static __inline__ void lp_schedule(int minor, long timeout) lp_table[minor].irq_missed = 1; schedule_timeout(timeout); lp_parport_claim(minor); - } else + } + else schedule_timeout(timeout); } @@ -412,6 +413,7 @@ static void lp_error(int minor) if (LP_POLLED(minor) || LP_PREEMPTED(minor)) { current->state = TASK_INTERRUPTIBLE; lp_parport_release(minor); + current->state = TASK_INTERRUPTIBLE; schedule_timeout(LP_TIMEOUT_POLLED); lp_parport_claim(minor); lp_table[minor].irq_missed = 1; @@ -641,6 +643,7 @@ static ssize_t lp_read(struct file * file, char * buf, /* Data available. */ /* Hack: Wait 10ms (between events 6 and 7) */ + current->state = TASK_INTERRUPTIBLE; schedule_timeout((HZ+99)/100); break; } diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 1c6f93f44817..3c4190ab7bfe 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -854,6 +854,7 @@ static inline int copy_from_read_buf(struct tty_struct *tty, retval = 0; n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail)); if (n) { + mb(); retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n); n -= retval; tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); diff --git a/drivers/char/pms.c b/drivers/char/pms.c index 72653aa1975e..5a9b41c9f799 100644 --- a/drivers/char/pms.c +++ b/drivers/char/pms.c @@ -1024,12 +1024,6 @@ static int init_mediavision(void) return 0; } -static void shutdown_mediavision(void) -{ - release_region(io_port,3); - release_region(0x9A01, 1); -} - /* * Module stuff */ @@ -1062,6 +1056,12 @@ int init_pms_cards(struct video_init *v) MODULE_PARM(io_port,"i"); MODULE_PARM(mem_base,"i"); +static void shutdown_mediavision(void) +{ + release_region(io_port,3); + release_region(0x9A01, 1); +} + void cleanup_module(void) { shutdown_mediavision(); diff --git a/drivers/char/serial.c b/drivers/char/serial.c index f7d95a713932..1bf31d626b61 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -3289,6 +3289,7 @@ void cleanup_module(void) unsigned long flags; int e1, e2; int i; + struct async_struct *info; /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ save_flags(flags); @@ -3308,6 +3309,11 @@ void cleanup_module(void) for (i = 0; i < NR_PORTS; i++) { if (rs_table[i].type != PORT_UNKNOWN) release_region(rs_table[i].port, 8); + info = rs_table[i].info; + if (info) { + rs_table[i].info = NULL; + kfree_s(info, sizeof(struct async_struct)); + } } if (tmp_buf) { free_page((unsigned long) tmp_buf); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 9a33cd86124e..661a0faf5cc3 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1979,7 +1979,8 @@ int tty_unregister_driver(struct tty_driver *driver) { int retval; struct tty_driver *p; - int found = 0; + int i, found = 0; + struct termios *tp; const char *othername = NULL; if (*driver->refcount) @@ -2010,6 +2011,23 @@ int tty_unregister_driver(struct tty_driver *driver) if (driver->next) driver->next->prev = driver->prev; + /* + * Free the termios and termios_locked structures because + * we don't want to get memory leaks when modular tty + * drivers are removed from the kernel. + */ + for (i = 0; i < driver->num; i++) { + tp = driver->termios[i]; + if (tp) { + driver->termios[i] = NULL; + kfree_s(tp, sizeof(struct termios)); + } + tp = driver->termios_locked[i]; + if (tp) { + driver->termios_locked[i] = NULL; + kfree_s(tp, sizeof(struct termios)); + } + } proc_tty_unregister_driver(driver); return 0; } diff --git a/drivers/char/tuner.c b/drivers/char/tuner.c index 55ff8eacc835..fc01a5a42153 100644 --- a/drivers/char/tuner.c +++ b/drivers/char/tuner.c @@ -84,9 +84,11 @@ static struct tunertype tuners[] = { // 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,0xc2,623}, 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,0xc2,623}, {"Temic 4036 FY5 NTSC", TEMIC, NTSC, - 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732}, - {"Alps HSBH1", TEMIC, NTSC, - 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,0xc2,732}, + 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732}, + {"Alps TSBH1",TEMIC,NTSC, + 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,0xc2,732}, + {"Alps TSBE1",TEMIC,PAL, + 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,0xc2,732}, }; /* ---------------------------------------------------------------------- */ @@ -192,12 +194,13 @@ static int tuner_attach(struct i2c_device *device) /* * For now we only try and attach these tuners to the BT848 - * bus. This same module will however work different species - * of card using these chips. Just change the constraints + * or ZORAN bus. This same module will however work different + * species of card using these chips. Just change the constraints * (i2c doesn't have a totally clash free 'address' space) */ - if(device->bus->id!=I2C_BUSID_BT848) + if(device->bus->id!=I2C_BUSID_BT848 || + device->bus->id!=I2C_BUSID_ZORAN) return -EINVAL; device->data = t = kmalloc(sizeof(struct tuner),GFP_KERNEL); diff --git a/drivers/net/arcnet.c b/drivers/net/arcnet.c index dabc745f8382..756c4f55eda3 100644 --- a/drivers/net/arcnet.c +++ b/drivers/net/arcnet.c @@ -472,7 +472,7 @@ arcnet_open(struct device *dev) #ifdef CONFIG_ARCNET_1051 /* Initialize the RFC1051-encap protocol driver */ lp->sdev=(struct device *)kmalloc(sizeof(struct device)+10,GFP_KERNEL); - if(lp->sdev = NULL) + if(lp->sdev == NULL) { if(lp->edev) kfree(lp->edev); diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c index 529158e81649..8ca6da0a9b4d 100644 --- a/drivers/net/e2100.c +++ b/drivers/net/e2100.c @@ -75,7 +75,7 @@ extern inline void mem_on(short port, volatile char *mem_base, { /* This is a little weird: set the shared memory window by doing a read. The low address bits specify the starting page. */ - mem_base[start_page]; + readb(mem_base+start_page); inb(port + E21_MEM_ENABLE); outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON); } diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index 3ed54576478a..aaf334c25f0c 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -913,6 +913,7 @@ printk("cm0: IP identification: %02x%02x fragment offset: %02x%02x\n", buffer[3 /* datagram completed: send to upper level */ skb_trim(skb, dlen); netif_rx(skb); + stats->rx_bytes+=dlen; stats->rx_packets++; lp->rx_bytes += dlen; lp->rx_skb[ns] = 0; diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index f476b62596e6..eec9c97a1b99 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -2528,13 +2528,13 @@ void TLan_MiiSendData( u16 base_port, u32 data, unsigned num_bits ) for ( i = ( 0x1 << ( num_bits - 1 ) ); i; i >>= 1 ) { TLan_ClearBit( TLAN_NET_SIO_MCLK, sio ); - TLan_GetBit( TLAN_NET_SIO_MCLK, sio ); + (void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio ); if ( data & i ) TLan_SetBit( TLAN_NET_SIO_MDATA, sio ); else TLan_ClearBit( TLAN_NET_SIO_MDATA, sio ); TLan_SetBit( TLAN_NET_SIO_MCLK, sio ); - TLan_GetBit( TLAN_NET_SIO_MCLK, sio ); + (void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio ); } } /* TLan_MiiSendData */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f0701066d314..1d77366d7c1b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -178,10 +178,8 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus)) if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) || /* some broken boards return 0 if a slot is empty: */ - l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) { - is_multi = 0; + l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) continue; - } dev = kmalloc(sizeof(*dev), GFP_ATOMIC); if(dev==NULL) diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c index 43dbbf3d04d5..9eb18fb925c8 100644 --- a/drivers/scsi/qlogicfc.c +++ b/drivers/scsi/qlogicfc.c @@ -635,7 +635,8 @@ struct init_cb { #define AS_FIRMWARE_DEAD -1 #define AS_LOOP_DOWN 0 #define AS_LOOP_GOOD 1 -#define AS_REDO_PORTDB 2 +#define AS_REDO_FABRIC_PORTDB 2 +#define AS_REDO_LOOP_PORTDB 4 struct isp2x00_hostdata { u_char revision; @@ -965,30 +966,31 @@ int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int } printk("qlogicfc%d : Fabric found.\n", hostdata->host_id); - - memset(&req, 0, sizeof(req)); - - req.len = 8; - req.response_low = virt_to_bus_low32(sns_response); - req.response_high = virt_to_bus_high32(sns_response); - req.sub_len = 22; - req.data[0] = 0x17; - req.data[1] = 0x02; - req.data[8] = (u_char) (hostdata->port_id & 0xff); - req.data[9] = (u_char) (hostdata->port_id >> 8 & 0xff); - req.data[10] = (u_char) (hostdata->port_id >> 16 & 0xff); - req.data[13] = 0x01; - param[0] = MBOX_SEND_SNS; - param[1] = 30; - param[2] = virt_to_bus_low32(&req) >> 16; - param[3] = virt_to_bus_low32(&req); - param[6] = virt_to_bus_high32(&req) >> 16; - param[7] = virt_to_bus_high32(&req); + if (hostdata->adapter_state & AS_REDO_LOOP_PORTDB){ + memset(&req, 0, sizeof(req)); - isp2x00_mbox_command(host, param); + req.len = 8; + req.response_low = virt_to_bus_low32(sns_response); + req.response_high = virt_to_bus_high32(sns_response); + req.sub_len = 22; + req.data[0] = 0x17; + req.data[1] = 0x02; + req.data[8] = (u_char) (hostdata->port_id & 0xff); + req.data[9] = (u_char) (hostdata->port_id >> 8 & 0xff); + req.data[10] = (u_char) (hostdata->port_id >> 16 & 0xff); + req.data[13] = 0x01; + param[0] = MBOX_SEND_SNS; + param[1] = 30; + param[2] = virt_to_bus_low32(&req) >> 16; + param[3] = virt_to_bus_low32(&req); + param[6] = virt_to_bus_high32(&req) >> 16; + param[7] = virt_to_bus_high32(&req); + + isp2x00_mbox_command(host, param); - if (param[0] != MBOX_COMMAND_COMPLETE) - printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id); + if (param[0] != MBOX_COMMAND_COMPLETE) + printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id); + } port_id = hostdata->port_id; while (!done) { @@ -1131,9 +1133,9 @@ int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *)) DEBUG(isp2x00_print_scsi_cmd(Cmnd)); - if (hostdata->adapter_state == AS_REDO_PORTDB) { - hostdata->adapter_state = AS_LOOP_GOOD; + if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) { isp2x00_make_portdb(host); + hostdata->adapter_state = AS_LOOP_GOOD; printk("qlogicfc%d : Port Database\n", hostdata->host_id); for (i = 0; hostdata->port_db[i].wwn != 0; i++) { printk("wwn: %08x%08x scsi_id: %x loop_id: %x\n", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i, hostdata->port_db[i].loop_id); @@ -1270,6 +1272,9 @@ int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *)) } switch (Cmnd->cmnd[0]) { + case TEST_UNIT_READY: + case START_STOP: + break; case WRITE_10: case WRITE_6: case WRITE_BUFFER: @@ -1378,7 +1383,7 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) case LOOP_UP: case POINT_TO_POINT_UP: printk("qlogicfc%d : link is up\n", hostdata->host_id); - hostdata->adapter_state = AS_REDO_PORTDB; + hostdata->adapter_state = AS_REDO_FABRIC_PORTDB | AS_REDO_LOOP_PORTDB; break; case LOOP_DOWN: printk("qlogicfc%d : link is down\n", hostdata->host_id); @@ -1387,12 +1392,15 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) case CONNECTION_MODE: printk("received CONNECTION_MODE irq %x\n", inw(host->io_port + MBOX1)); break; - case LIP_OCCURED: case CHANGE_NOTIFICATION: + if (hostdata->adapter_state == AS_LOOP_GOOD) + hostdata->adapter_state = AS_REDO_FABRIC_PORTDB; + break; + case LIP_OCCURED: case PORT_DB_CHANGED: case LIP_RECEIVED: if (hostdata->adapter_state == AS_LOOP_GOOD) - hostdata->adapter_state = AS_REDO_PORTDB; + hostdata->adapter_state = AS_REDO_LOOP_PORTDB; break; case SYSTEM_ERROR: printk("qlogicfc%d : The firmware just choked.\n", hostdata->host_id); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 7dbb827cf2cb..895d244c0c20 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1358,14 +1358,15 @@ static int sd_init_onedisk(int i) rscsi_disks[i].capacity = 0; } else { printk ("scsi : deleting disk entry.\n"); + sd_detach(rscsi_disks[i].device); rscsi_disks[i].device = NULL; - sd_template.nr_dev--; - SD_GENDISK(i).nr_real--; /* Wake up a process waiting for device */ wake_up(&SCpnt->device->device_wait); scsi_release_command(SCpnt); SCpnt = NULL; + scsi_free(buffer, 512); + spin_unlock_irq(&io_request_lock); return i; } @@ -1715,6 +1716,7 @@ int revalidate_scsidisk(kdev_t dev, int maxusage) { #endif sd_gendisks->part[start].nr_sects = CAPACITY; + if (!rscsi_disks[target].device) return -EBUSY; resetup_one_dev(&SD_GENDISK(target), target % SCSI_DISKS_PER_MAJOR); diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c index baa0907711a0..8de63a0682b6 100644 --- a/drivers/sound/ad1848.c +++ b/drivers/sound/ad1848.c @@ -106,7 +106,7 @@ int soundpro = 1; int soundpro = 0; #endif -static volatile char irq2dev[17] = { +static volatile signed char irq2dev[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; @@ -2434,11 +2434,12 @@ int probe_ms_sound(struct address_info *hw_config) void attach_ms_sound(struct address_info *hw_config) { - static char interrupt_bits[12] = + static signed char interrupt_bits[12] = { -1, -1, -1, -1, -1, 0x00, -1, 0x08, -1, 0x10, 0x18, 0x20 }; - char bits, dma2_bit = 0; + signed char bits; + char dma2_bit = 0; static char dma_bits[4] = { diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c index 85bde7d48fc3..e70c108411e5 100644 --- a/drivers/sound/dmabuf.c +++ b/drivers/sound/dmabuf.c @@ -187,7 +187,7 @@ static int open_dmap(struct audio_operations *adev, int mode, struct dma_buffpar printk(KERN_WARNING "Sound: DMA buffers not available\n"); return -ENOSPC; /* Memory allocation failed during boot */ } - if (sound_open_dma(dmap->dma, adev->name)) { + if (dmap->dma >= 0 && sound_open_dma(dmap->dma, adev->name)) { printk(KERN_WARNING "Unable to grab(2) DMA%d for the audio driver\n", dmap->dma); return -EBUSY; } @@ -209,15 +209,16 @@ static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap { unsigned long flags; - sound_close_dma(dmap->dma); + if (dmap->dma >= 0) { + sound_close_dma(dmap->dma); + flags=claim_dma_lock(); + disable_dma(dmap->dma); + release_dma_lock(flags); + } if (dmap->flags & DMA_BUSY) dmap->dma_mode = DMODE_NONE; dmap->flags &= ~DMA_BUSY; - flags=claim_dma_lock(); - disable_dma(dmap->dma); - release_dma_lock(flags); - if (sound_dmap_flag == DMAP_FREE_ON_CLOSE) sound_free_dmap(dmap); } diff --git a/drivers/sound/opl3sa.c b/drivers/sound/opl3sa.c index 341438748842..9e5fd5a6bd29 100644 --- a/drivers/sound/opl3sa.c +++ b/drivers/sound/opl3sa.c @@ -187,7 +187,7 @@ int probe_opl3sa_mpu(struct address_info *hw_config) { #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) unsigned char conf; - static char irq_bits[] = { + static signed char irq_bits[] = { -1, -1, -1, -1, -1, 1, -1, 2, -1, 3, 4 }; diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c index 9f9400a83cc1..cdf4a6955286 100644 --- a/drivers/sound/sonicvibes.c +++ b/drivers/sound/sonicvibes.c @@ -504,9 +504,8 @@ static void frobindir(struct sv_state *s, unsigned char idx, unsigned char mask, static unsigned setpll(struct sv_state *s, unsigned char reg, unsigned rate) { unsigned long flags; - unsigned char r, m, n; + unsigned char r, m=0, n=0; unsigned xm, xn, xr, xd, metric = ~0U; - /* the warnings about m and n used uninitialized are bogus and may safely be ignored */ if (rate < 625000/ADCMULT) rate = 625000/ADCMULT; diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index a4ed4eb34e80..008a7b39ffc5 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -311,6 +311,7 @@ static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs unsigned long fd_offset; unsigned long rlim; int retval; + static unsigned long error_time=0; ex = *((struct exec *) bprm->buf); /* exec-header */ if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && @@ -324,7 +325,11 @@ static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs #ifdef __i386__ if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) { - printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n"); + if((jiffies-error_time) >5) + { + printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n"); + error_time=jiffies; + } return -ENOEXEC; } @@ -332,7 +337,11 @@ static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs bprm->dentry->d_inode->i_op && bprm->dentry->d_inode->i_op->bmap && (fd_offset < bprm->dentry->d_inode->i_sb->s_blocksize)) { - printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n"); + if((jiffies-error_time) >5) + { + printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n"); + error_time=jiffies; + } return -ENOEXEC; } #endif diff --git a/fs/exec.c b/fs/exec.c index 6212a061038a..7a0e3c6be0e9 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -271,7 +271,7 @@ unsigned long copy_strings(int argc,char ** argv,unsigned long *page, } p -= len; pos = p; - while (len) { + while (len>0) { char *pag; int offset, bytes_to_copy; diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 4f9b53c8ab93..9ce7a231176e 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -324,7 +324,8 @@ static ssize_t ext2_file_write (struct file * filp, const char * buf, break; } mark_buffer_dirty(bh, 0); - update_vm_cache(inode, pos, bh->b_data + offset, c); + update_vm_cache_conditional(inode, pos, bh->b_data + offset, c, + (unsigned long) buf); pos += c; written += c; buf += c; diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index b67ad0efacdd..315d71b0f656 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -761,28 +761,28 @@ int ext2_notify_change(struct dentry *dentry, struct iattr *iattr) flags = iattr->ia_attr_flags; if (flags & ATTR_FLAG_SYNCRONOUS) { inode->i_flags |= MS_SYNCHRONOUS; - inode->u.ext2_i.i_flags = EXT2_SYNC_FL; + inode->u.ext2_i.i_flags |= EXT2_SYNC_FL; } else { inode->i_flags &= ~MS_SYNCHRONOUS; inode->u.ext2_i.i_flags &= ~EXT2_SYNC_FL; } if (flags & ATTR_FLAG_NOATIME) { inode->i_flags |= MS_NOATIME; - inode->u.ext2_i.i_flags = EXT2_NOATIME_FL; + inode->u.ext2_i.i_flags |= EXT2_NOATIME_FL; } else { inode->i_flags &= ~MS_NOATIME; inode->u.ext2_i.i_flags &= ~EXT2_NOATIME_FL; } if (flags & ATTR_FLAG_APPEND) { inode->i_flags |= S_APPEND; - inode->u.ext2_i.i_flags = EXT2_APPEND_FL; + inode->u.ext2_i.i_flags |= EXT2_APPEND_FL; } else { inode->i_flags &= ~S_APPEND; inode->u.ext2_i.i_flags &= ~EXT2_APPEND_FL; } if (flags & ATTR_FLAG_IMMUTABLE) { inode->i_flags |= S_IMMUTABLE; - inode->u.ext2_i.i_flags = EXT2_IMMUTABLE_FL; + inode->u.ext2_i.i_flags |= EXT2_IMMUTABLE_FL; } else { inode->i_flags &= ~S_IMMUTABLE; inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c46eeb57bb50..afa07f00179c 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -408,6 +408,8 @@ restart: unhashed = 0; while ((tmp = tmp->next) != head) { struct dentry *dentry = list_entry(tmp, struct dentry, d_alias); + if (!list_empty(&dentry->d_subdirs)) + shrink_dcache_parent(dentry); dprintk("nfs_free_dentries: found %s/%s, d_count=%d, hashed=%d\n", dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count, !list_empty(&dentry->d_hash)); @@ -417,7 +419,7 @@ restart: dput(dentry); goto restart; } - if (!list_empty(&dentry->d_hash)) + if (list_empty(&dentry->d_hash)) unhashed++; } return unhashed; diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h index 00e238407f6a..65af8e0be548 100644 --- a/include/asm-i386/spinlock.h +++ b/include/asm-i386/spinlock.h @@ -21,7 +21,7 @@ #endif #define spin_lock_init(lock) do { } while(0) -#define spin_lock(lock) do { } while(0) +#define spin_lock(lock) (void)(lock) /* Not "unused variable". */ #define spin_trylock(lock) (1) #define spin_unlock_wait(lock) do { } while(0) #define spin_unlock(lock) do { } while(0) @@ -99,9 +99,9 @@ typedef struct { #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } #endif -#define read_lock(lock) do { } while(0) +#define read_lock(lock) (void)(lock) /* Not "unused variable." */ #define read_unlock(lock) do { } while(0) -#define write_lock(lock) do { } while(0) +#define write_lock(lock) (void)(lock) /* Not "unused variable." */ #define write_unlock(lock) do { } while(0) #define read_lock_irq(lock) cli() #define read_unlock_irq(lock) sti() diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 273b2a7187af..6082de3dd76a 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -39,6 +39,7 @@ struct i2c_device; #define I2C_BUSID_BT848 1 /* I2C bus on a BT848 */ /* 2 is used in 2.3.x */ #define I2C_BUSID_BUZ 3 /* I2C bus on a BUZ */ +#define I2C_BUSID_ZORAN 4 /* I2C bus on a Zoran */ /* * struct for a driver for a i2c chip (tuner, soundprocessor, diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 3e1e89b44daa..1f5a62dd9926 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -148,6 +148,7 @@ static inline void wait_on_page(struct page * page) __wait_on_page(page); } +extern void update_vm_cache_conditional(struct inode *, unsigned long, const char *, int, unsigned long); extern void update_vm_cache(struct inode *, unsigned long, const char *, int); #endif diff --git a/kernel/ksyms.c b/kernel/ksyms.c index f49dac89b326..14a1cbaba1fa 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -106,6 +106,7 @@ EXPORT_SYMBOL(remap_page_range); EXPORT_SYMBOL(max_mapnr); EXPORT_SYMBOL(high_memory); EXPORT_SYMBOL(update_vm_cache); +EXPORT_SYMBOL(update_vm_cache_conditional); EXPORT_SYMBOL(vmtruncate); EXPORT_SYMBOL(find_vma); EXPORT_SYMBOL(get_unmapped_area); diff --git a/kernel/printk.c b/kernel/printk.c index 36414fcf3c6d..d7d22d557234 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -10,6 +10,8 @@ * elsewhere, in preparation for a serial line console (someday). * Ted Ts'o, 2/11/93. * Modified for sysctl support, 1/8/97, Chris Horn. + * Fixed SMP synchronization, 08/08/99, Manfred Spraul + * manfreds@colorfullife.com */ #include @@ -21,6 +23,7 @@ #include #define LOG_BUF_LEN (16384) +#define LOG_BUF_MASK (LOG_BUF_LEN-1) static char buf[1024]; @@ -40,6 +43,8 @@ int default_message_loglevel = DEFAULT_MESSAGE_LOGLEVEL; int minimum_console_loglevel = MINIMUM_CONSOLE_LOGLEVEL; int default_console_loglevel = DEFAULT_CONSOLE_LOGLEVEL; +spinlock_t console_lock = SPIN_LOCK_UNLOCKED; + struct console *console_drivers = NULL; static char log_buf[LOG_BUF_LEN]; static unsigned long log_start = 0; @@ -115,12 +120,11 @@ void __init console_setup(char *str, int *ints) */ int do_syslog(int type, char * buf, int len) { - unsigned long i, j, count, flags; + unsigned long i, j, limit, count; int do_clear = 0; char c; int error = -EPERM; - lock_kernel(); error = 0; switch (type) { case 0: /* Close log */ @@ -141,18 +145,18 @@ int do_syslog(int type, char * buf, int len) if (error) goto out; i = 0; + spin_lock_irq(&console_lock); while (log_size && i < len) { - c = *((char *) log_buf+log_start); + c = log_buf[log_start & LOG_BUF_MASK]; log_start++; log_size--; - log_start &= LOG_BUF_LEN-1; - sti(); + spin_unlock_irq(&console_lock); __put_user(c,buf); buf++; i++; - cli(); + spin_lock_irq(&console_lock); } - sti(); + spin_unlock_irq(&console_lock); error = i; break; case 4: /* Read/clear last kernel messages */ @@ -168,35 +172,56 @@ int do_syslog(int type, char * buf, int len) error = verify_area(VERIFY_WRITE,buf,len); if (error) goto out; - /* - * The logged_chars, log_start, and log_size values may - * change from an interrupt, so we disable interrupts. - */ - __save_flags(flags); - __cli(); + spin_lock_irq(&console_lock); count = len; if (count > LOG_BUF_LEN) count = LOG_BUF_LEN; if (count > logged_chars) count = logged_chars; - j = log_start + log_size - count; - __restore_flags(flags); - for (i = 0; i < count; i++) { - c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1))); - __put_user(c, buf++); - } if (do_clear) logged_chars = 0; + limit = log_start + log_size; + /* + * __put_user() could sleep, and while we sleep + * printk() could overwrite the messages + * we try to copy to user space. Therefore + * the messages are copied in reverse. + */ + for(i=0;i < count;i++) { + j = limit-1-i; + if (j+LOG_BUF_LEN < log_start+log_size) + break; + c = log_buf[ j & LOG_BUF_MASK ]; + spin_unlock_irq(&console_lock); + __put_user(c,&buf[count-1-i]); + spin_lock_irq(&console_lock); + } + spin_unlock_irq(&console_lock); error = i; + if(i != count) { + int offset = count-error; + /* buffer overflow during copy, correct user buffer. */ + for(i=0;iflags & CON_ENABLED) && c->write) c->write(c, s, len); c = c->next; } + spin_unlock_irqrestore(&console_lock,flags); } void unblank_console(void) { - struct console *c = console_drivers; + struct console *c; + unsigned long flags; + + spin_lock_irqsave(&console_lock,flags); + c = console_drivers; while(c) { if ((c->flags & CON_ENABLED) && c->unblank) c->unblank(); c = c->next; } + spin_unlock_irqrestore(&console_lock,flags); } /* @@ -318,11 +349,12 @@ void unblank_console(void) */ void register_console(struct console * console) { - int i,j,len; - int p = log_start; + int i, j,len; + int p; char buf[16]; signed char msg_level = -1; char *q; + unsigned long flags; /* * See if we want to use this console driver. If we @@ -368,6 +400,7 @@ void register_console(struct console * console) * Put this console in the list - keep the * preferred driver at the head of the list. */ + spin_lock_irqsave(&console_lock,flags); if ((console->flags & CON_CONSDEV) || console_drivers == NULL) { console->next = console_drivers; console_drivers = console; @@ -375,23 +408,33 @@ void register_console(struct console * console) console->next = console_drivers->next; console_drivers->next = console; } - if ((console->flags & CON_PRINTBUFFER) == 0) return; - + if ((console->flags & CON_PRINTBUFFER) == 0) + goto done; /* * Print out buffered log messages. */ + p = log_start & LOG_BUF_MASK; + for (i=0,j=0; i < log_size; i++) { buf[j++] = log_buf[p]; - p++; p &= LOG_BUF_LEN-1; + p = (p+1) & LOG_BUF_MASK; if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf)-1) continue; buf[j] = 0; q = buf; len = j; if (msg_level < 0) { - msg_level = buf[1] - '0'; - q = buf + 3; - len -= 3; + if(buf[0] == '<' && + buf[1] >= '0' && + buf[1] <= '7' && + buf[2] == '>') { + msg_level = buf[1] - '0'; + q = buf + 3; + len -= 3; + } else + { + msg_level = default_message_loglevel; + } } if (msg_level < console_loglevel) console->write(console, q, len); @@ -399,26 +442,35 @@ void register_console(struct console * console) msg_level = -1; j = 0; } +done: + spin_unlock_irqrestore(&console_lock,flags); } int unregister_console(struct console * console) { struct console *a,*b; - + unsigned long flags; + int res = 1; + + spin_lock_irqsave(&console_lock,flags); if (console_drivers == console) { console_drivers=console->next; - return (0); - } - for (a=console_drivers->next, b=console_drivers ; - a; b=a, a=b->next) { - if (a == console) { - b->next = a->next; - return 0; - } + res = 0; + } else + { + for (a=console_drivers->next, b=console_drivers ; + a; b=a, a=b->next) { + if (a == console) { + b->next = a->next; + res = 0; + break; + } + } } - return (1); + spin_unlock_irqrestore(&console_lock,flags); + return res; } /* diff --git a/mm/filemap.c b/mm/filemap.c index 62d85dc02071..25512ab57b42 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -215,8 +215,25 @@ int shrink_mmap(int priority, int gfp_mask) /* * Update a page cache copy, when we're doing a "write()" system call * See also "update_vm_cache()". + * + * This function is conditional in that it checks whether the original + * source of the data is the same as the ultimate destination, and + * aborts the update if so. + * + * The "source_address" is the virtual address of the original location + * of the data we are injecting. For writes from user mode, it is the + * user VA. However, for filemap_sync writes, "source_address", it is + * the page cache address. In both cases, "buf" points to the copy we + * have already made in kernel space and we use that pointer for the + * transfer. source_address just allows us to detect an update_vm_cache + * which is being sourced from the copy of the data already in the page + * cache. + * + * This prevents munmap() and msync() from stomping all over shared + * memory maps. --sct */ -void update_vm_cache(struct inode * inode, unsigned long pos, const char * buf, int count) + +void update_vm_cache_conditional(struct inode * inode, unsigned long pos, const char * buf, int count, unsigned long source_address) { unsigned long offset, len; @@ -230,8 +247,12 @@ void update_vm_cache(struct inode * inode, unsigned long pos, const char * buf, len = count; page = find_page(inode, pos); if (page) { - wait_on_page(page); - memcpy((void *) (offset + page_address(page)), buf, len); + char *dest = (char*) (offset + page_address(page)); + + if (dest != source_address) { + wait_on_page(page); + memcpy(dest, buf, len); + } page_cache_release(page); } count -= len; @@ -242,6 +263,12 @@ void update_vm_cache(struct inode * inode, unsigned long pos, const char * buf, } while (count); } +void update_vm_cache(struct inode * inode, unsigned long pos, const char * buf, int count) +{ + update_vm_cache_conditional(inode, pos, buf, count, 0); +} + + static inline void add_to_page_cache(struct page * page, struct inode * inode, unsigned long offset, struct page **hash) @@ -1482,6 +1509,8 @@ generic_file_write(struct file *file, const char *buf, while (count) { unsigned long bytes, pgpos, offset; + char * dest; + /* * Try to find the page in the cache. If it isn't there, * allocate a free page. @@ -1516,7 +1545,9 @@ generic_file_write(struct file *file, const char *buf, * the writer needs to increment the page use counts until he * is done with the page. */ - bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes); + dest = (char *) page_address(page) + offset; + if (dest != buf) /* See comment in update_vm_cache_cond. */ + bytes -= copy_from_user(dest, buf, bytes); status = -EFAULT; if (bytes) status = inode->i_op->updatepage(file, page, offset, bytes, sync); diff --git a/mm/mmap.c b/mm/mmap.c index 8106eae571b6..89ad16071b96 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -361,11 +361,8 @@ unsigned long get_unmapped_area(unsigned long addr, unsigned long len) if (len > TASK_SIZE) return 0; - if (!addr) { - addr = current->rlim[RLIMIT_DATA].rlim_cur; - if (addr >= RLIM_INFINITY) - addr = TASK_UNMAPPED_BASE; - } + if (!addr) + addr = TASK_UNMAPPED_BASE; addr = PAGE_ALIGN(addr); for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index b6ccfa7117fe..ac858a5cee67 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -775,6 +775,7 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb) { /* < 8 hops && input itfc not in list */ *l = intrfc->if_netnum; /* insert recvd netnum into list */ + ipx->ipx_tctrl++; /* xmit on all other interfaces... */ for(ifcs = ipx_interfaces; ifcs != NULL; ifcs = ifcs->if_next) { -- 2.39.5