From 6258f70d3d16a666c50952de5c0621a3b6e09664 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:13:11 -0500 Subject: [PATCH] Import 2.1.37pre3 --- Documentation/Changes | 6 +- Documentation/Configure.help | 22 +- Documentation/devices.tex | 50 ++- Documentation/devices.txt | 32 +- Documentation/m68k/00-INDEX | 9 + .../m68k/{amiboot.README => amiboot.txt} | 75 +++- Documentation/m68k/framebuffer.txt | 370 ++++++++++++++++++ Documentation/m68k/kernel-options.txt | 12 + Documentation/networking/net-modules.txt | 21 + Documentation/serial-console.txt | 2 +- Makefile | 2 + arch/alpha/kernel/entry.S | 31 +- arch/alpha/kernel/head.S | 8 +- arch/alpha/kernel/process.c | 10 +- arch/alpha/kernel/ptrace.c | 6 +- arch/alpha/kernel/setup.c | 2 +- arch/alpha/mm/init.c | 3 +- arch/alpha/vmlinux.lds | 6 +- arch/i386/kernel/bios32.c | 20 +- arch/i386/kernel/head.S | 14 +- arch/i386/kernel/irq.c | 81 ++-- arch/i386/kernel/process.c | 3 +- arch/i386/kernel/smp.c | 63 ++- arch/i386/kernel/trampoline.S | 4 - arch/i386/kernel/traps.c | 10 +- arch/i386/lib/Makefile | 2 +- arch/i386/lib/checksum.c | 168 +------- arch/i386/lib/checksumcopy.S | 259 ++++++++++++ arch/i386/lib/locks.S | 3 +- arch/i386/vmlinux.lds | 1 + arch/m68k/Makefile | 12 +- arch/m68k/amiga/amifb.c | 6 +- arch/m68k/amiga/amiints.c | 3 +- arch/m68k/amiga/amikeyb.c | 3 +- arch/m68k/amiga/amisound.c | 5 +- arch/m68k/amiga/chipram.c | 10 +- arch/m68k/amiga/cia.c | 3 +- arch/m68k/amiga/config.c | 9 +- arch/m68k/amiga/cyberfb.c | 7 +- arch/m68k/amiga/retz3fb.c | 5 +- arch/m68k/amiga/zorro.c | 10 +- arch/m68k/atari/atafb.c | 5 +- arch/m68k/atari/ataints.c | 3 +- arch/m68k/atari/atakeyb.c | 3 +- arch/m68k/atari/config.c | 21 +- arch/m68k/atari/joystick.c | 3 +- arch/m68k/atari/stdma.c | 4 +- arch/m68k/atari/stram.c | 3 +- arch/m68k/boot/amiga/linuxboot.c | 17 +- arch/m68k/boot/amiga/linuxboot.h | 2 +- arch/m68k/kernel/ints.c | 3 +- arch/m68k/kernel/m68k_ksyms.c | 4 + arch/m68k/kernel/process.c | 11 +- arch/m68k/kernel/setup.c | 29 +- arch/m68k/kernel/signal.c | 6 +- arch/m68k/kernel/time.c | 21 + arch/m68k/kernel/traps.c | 3 +- arch/m68k/mm/init.c | 44 ++- arch/m68k/vmlinux.lds | 56 +++ arch/sparc/Makefile | 4 +- arch/sparc/kernel/Makefile | 4 +- arch/sparc/kernel/etrap.S | 14 +- arch/sparc/kernel/head.S | 15 +- arch/sparc/kernel/init_task.c | 18 + arch/sparc/kernel/process.c | 29 +- arch/sparc/kernel/smp.c | 142 ++++--- arch/sparc/kernel/tadpole.c | 2 + arch/sparc/kernel/trampoline.S | 34 +- arch/sparc/kernel/wof.S | 15 +- arch/sparc/kernel/wuf.S | 16 +- arch/sparc/lib/irqlock.S | 2 +- arch/sparc/mm/srmmu.c | 89 ++--- arch/sparc/mm/sun4c.c | 118 ++---- arch/sparc/prom/console.c | 10 +- arch/sparc/prom/devmap.c | 6 +- arch/sparc/prom/devops.c | 8 +- arch/sparc/prom/misc.c | 10 +- arch/sparc/prom/mp.c | 10 +- arch/sparc/prom/segment.c | 4 +- arch/sparc/prom/tree.c | 4 +- arch/sparc64/kernel/entry.S | 26 +- arch/sparc64/kernel/etrap.S | 87 ++-- arch/sparc64/kernel/process.c | 16 - arch/sparc64/lib/checksum.S | 2 +- arch/sparc64/lib/copy_from_user.S | 15 +- arch/sparc64/lib/copy_to_user.S | 15 +- arch/sparc64/mm/init.c | 7 +- drivers/block/amiflop.c | 5 +- drivers/block/ataflop.c | 11 +- drivers/block/ez.c | 19 +- drivers/block/floppy.c | 17 +- drivers/block/genhd.c | 26 +- drivers/block/hd.c | 5 +- drivers/block/ide.c | 17 +- drivers/block/linear.c | 3 +- drivers/block/loop.c | 5 +- drivers/block/md.c | 3 +- drivers/block/ps2esdi.c | 12 +- drivers/block/rd.c | 32 +- drivers/block/xd.c | 31 +- drivers/block/z2ram.c | 5 +- drivers/cdrom/aztcd.c | 5 +- drivers/cdrom/bpcd.c | 21 +- drivers/cdrom/cdi.c | 5 +- drivers/cdrom/cdu31a.c | 17 +- drivers/cdrom/cm206.c | 11 +- drivers/cdrom/gscd.c | 11 +- drivers/cdrom/isp16.c | 25 +- drivers/cdrom/mcd.c | 5 +- drivers/cdrom/mcdx.c | 5 +- drivers/cdrom/optcd.c | 7 +- drivers/cdrom/sbpcd.c | 18 +- drivers/cdrom/sjcd.c | 5 +- drivers/cdrom/sonycd535.c | 9 +- drivers/char/busmouse.c | 2 +- drivers/char/console.c | 3 +- drivers/char/consolemap.c | 5 +- drivers/char/dsp56k.c | 3 +- drivers/char/fbmem.c | 5 +- drivers/char/ftape/kernel-interface.c | 3 +- drivers/char/lp.c | 2 +- drivers/char/lp_intern.c | 20 +- drivers/char/lp_m68k.c | 5 +- drivers/char/mem.c | 6 +- drivers/char/misc.c | 4 + drivers/char/msbusmouse.c | 2 +- drivers/char/pcxx.c | 2 +- drivers/char/riscom8.c | 2 +- drivers/char/tga.c | 37 +- drivers/char/tpqic02.c | 6 +- drivers/char/vga.c | 9 +- drivers/char/wdt.c | 2 +- drivers/isdn/sc/Makefile | 2 +- drivers/net/eexpress.c | 9 +- drivers/net/sk_g16.c | 7 +- drivers/net/skeleton.c | 9 +- drivers/net/soundmodem/sm.c | 8 +- drivers/net/wavelan.c | 14 +- drivers/net/wavelan.p.h | 1 + drivers/pci/pci.c | 13 +- drivers/sbus/audio/amd7930.c | 1 + drivers/sbus/audio/cs4231.c | 1 + drivers/sbus/char/vfc.h | 12 +- drivers/sbus/char/vfc_dev.c | 111 +++--- drivers/sbus/char/vfc_i2c.c | 24 +- drivers/scsi/a2091.c | 17 +- drivers/scsi/a3000.c | 3 +- drivers/scsi/atari_NCR5380.c | 8 +- drivers/scsi/atari_scsi.c | 5 +- drivers/scsi/gvp11.c | 3 +- drivers/scsi/sd.c | 3 +- fs/affs/Changes | 95 +++++ fs/affs/amigaffs.c | 96 +++-- fs/affs/bitmap.c | 46 +-- fs/affs/dir.c | 25 +- fs/affs/file.c | 99 +++-- fs/affs/inode.c | 201 ++++++---- fs/affs/namei.c | 37 +- fs/affs/symlink.c | 4 +- fs/autofs/Makefile | 29 +- fs/autofs/autofs_i.h | 157 ++++++++ fs/autofs/dir.c | 2 +- fs/autofs/dirhash.c | 49 ++- fs/autofs/init.c | 22 +- fs/autofs/inode.c | 11 +- fs/autofs/root.c | 83 +++- fs/autofs/symlink.c | 2 +- fs/autofs/waitq.c | 6 +- fs/proc/array.c | 3 +- fs/super.c | 7 +- include/asm-alpha/atomic.h | 16 +- include/asm-alpha/bitops.h | 12 +- include/asm-alpha/current.h | 6 - include/asm-alpha/processor.h | 12 +- include/asm-alpha/semaphore.h | 4 +- include/asm-alpha/softirq.h | 4 +- include/asm-alpha/spinlock.h | 13 +- include/asm-alpha/system.h | 10 +- include/asm-i386/checksum.h | 25 +- include/asm-i386/current.h | 7 - include/asm-i386/smp_lock.h | 17 +- include/asm-i386/spinlock.h | 12 +- include/asm-i386/system.h | 4 +- include/asm-m68k/fpu.h | 20 - include/asm-m68k/hardirq.h | 13 - include/asm-m68k/init.h | 16 +- include/asm-m68k/semaphore.h | 17 + include/asm-m68k/sigcontext.h | 4 +- include/asm-sparc/asm_offsets.h | 146 ++++--- include/asm-sparc/asmmacro.h | 14 +- include/asm-sparc/auxio.h | 47 ++- include/asm-sparc/processor.h | 9 +- include/asm-sparc/semaphore.h | 26 +- include/asm-sparc/smp.h | 4 +- include/asm-sparc/spinlock.h | 28 +- include/asm-sparc/system.h | 12 +- include/asm-sparc/winmacro.h | 9 +- include/asm-sparc64/asm_offsets.h | 160 ++++---- include/asm-sparc64/head.h | 4 +- include/linux/affs_fs.h | 88 ++--- include/linux/affs_fs_i.h | 36 +- include/linux/affs_fs_sb.h | 10 +- include/linux/affs_hardblocks.h | 84 ++-- include/linux/amigaffs.h | 166 ++++---- include/linux/auto_fs.h | 151 +------ include/linux/console.h | 27 +- include/linux/fb.h | 2 + include/linux/lp_m68k.h | 11 +- include/linux/major.h | 1 + include/linux/sched.h | 15 +- include/linux/skbuff.h | 3 + include/linux/smp.h | 1 + include/linux/sysctl.h | 7 + include/net/sock.h | 1 + include/net/tcp.h | 68 +++- init/main.c | 3 + ipc/msg.c | 3 +- ipc/sem.c | 3 +- ipc/shm.c | 8 +- ipc/util.c | 3 +- kernel/exit.c | 1 + kernel/fork.c | 159 ++++++-- kernel/ksyms.c | 1 - kernel/panic.c | 3 +- kernel/printk.c | 3 +- kernel/resource.c | 3 +- kernel/sched.c | 16 +- kernel/sys.c | 42 +- kernel/sysctl.c | 3 +- mm/kmalloc.c | 3 +- mm/mmap.c | 3 +- mm/page_alloc.c | 5 +- mm/slab.c | 13 +- mm/swap.c | 5 +- mm/swap_state.c | 5 +- net/802/llc_macinit.c | 3 +- net/802/p8022.c | 3 +- net/802/p8022tr.c | 3 +- net/802/psnap.c | 3 +- net/802/tr.c | 3 +- net/appletalk/aarp.c | 3 +- net/appletalk/ddp.c | 3 +- net/ax25/af_ax25.c | 3 +- net/core/firewall.c | 3 +- net/core/skbuff.c | 1 + net/core/sock.c | 70 ++-- net/core/sysctl_net_core.c | 18 +- net/ethernet/eth.c | 9 +- net/ipv4/af_inet.c | 3 +- net/ipv4/arp.c | 3 +- net/ipv4/fib.c | 3 +- net/ipv4/icmp.c | 5 +- net/ipv4/ip_alias.c | 3 +- net/ipv4/ip_fragment.c | 2 +- net/ipv4/ip_fw.c | 3 +- net/ipv4/ip_masq.c | 3 +- net/ipv4/ip_masq_app.c | 3 +- net/ipv4/ip_masq_ftp.c | 3 +- net/ipv4/ip_masq_irc.c | 3 +- net/ipv4/ip_masq_quake.c | 3 +- net/ipv4/ip_masq_raudio.c | 5 +- net/ipv4/ip_output.c | 18 +- net/ipv4/ipmr.c | 3 +- net/ipv4/rarp.c | 5 +- net/ipv4/route.c | 3 +- net/ipv4/tcp.c | 9 +- net/ipv4/tcp_input.c | 41 +- net/ipv4/tcp_ipv4.c | 109 ++++-- net/ipv4/tcp_output.c | 146 ++++++- net/ipv6/addrconf.c | 5 +- net/ipv6/af_inet6.c | 5 +- net/ipv6/datagram.c | 5 +- net/ipv6/icmp.c | 5 +- net/ipv6/ip6_fw.c | 5 +- net/ipv6/ipv6_sockglue.c | 7 +- net/ipv6/mcast.c | 5 +- net/ipv6/ndisc.c | 5 +- net/ipv6/route.c | 5 +- net/ipv6/sit.c | 5 +- net/ipv6/tcp_ipv6.c | 88 ++++- net/ipv6/udp.c | 5 +- net/ipx/af_ipx.c | 3 +- net/lapb/lapb_iface.c | 3 +- net/netbeui/af_netbeui.c | 3 +- net/netlink.c | 3 +- net/netrom/af_netrom.c | 3 +- net/netrom/sysctl_net_netrom.c | 3 +- net/netsyms.c | 4 + net/rose/af_rose.c | 3 +- net/rose/sysctl_net_rose.c | 3 +- net/socket.c | 5 +- net/unix/af_unix.c | 3 +- net/wanrouter/wanmain.c | 3 +- net/wanrouter/wanproc.c | 3 +- net/x25/af_x25.c | 3 +- net/x25/sysctl_net_x25.c | 3 +- 296 files changed, 3995 insertions(+), 2332 deletions(-) create mode 100644 Documentation/m68k/00-INDEX rename Documentation/m68k/{amiboot.README => amiboot.txt} (76%) create mode 100644 Documentation/m68k/framebuffer.txt create mode 100644 arch/i386/lib/checksumcopy.S create mode 100644 arch/m68k/vmlinux.lds create mode 100644 arch/sparc/kernel/init_task.c create mode 100644 fs/affs/Changes create mode 100644 fs/autofs/autofs_i.h diff --git a/Documentation/Changes b/Documentation/Changes index 78509d856498..612fb76b1cdc 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -49,7 +49,7 @@ encountered a bug! - Net-tools 1.32-alpha - Loadlin 1.6a - Sh-utils 1.16 -- Autofs 0.2.2 +- Autofs 0.3.0 - NFS 0.4.21 Upgrade notes @@ -301,8 +301,8 @@ ftp://ftp.win.tue.nl/pub/linux/util/mount-2.6g.tar.gz Autofs ====== -The 0.2.2 release: -ftp://ftp.kernel.org/pub/linux/daemons/autofs/autofs-0.2.2.tar.gz +The 0.3.0 release: +ftp://ftp.kernel.org/pub/linux/daemons/autofs/autofs-0.3.0.tar.gz NFS === diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 062bf99434f7..7473fcf702c2 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -4928,9 +4928,13 @@ CONFIG_RMW_INSNS Amiga AutoConfig Identification CONFIG_ZORRO This enables support for automatic identification of Amiga expansion - cards that obey the AutoConfig(tm) specification. You should say Y - to this question unless you have no expansion cards and no intention - of getting any. + cards that obey the AutoConfig(tm) specification. + Say Y if you want your expansion cards to be identified on bootup; + it will enlarge your kernel by about 10KB. The identification + information is also available through /proc/zorro (say Y to + "/proc filesystem support"!). + Note that even if you say N here, you can still use your expansion + cards. If in doubt, say Y. Amiga OCS chipset support CONFIG_AMIFB_OCS @@ -4958,6 +4962,8 @@ CONFIG_FB_CYBER Please note that its use is not all that intuitive (i.e. if you have any questions, be sure to ask!). Say N unless you have a Cybervision 64 or plan to get one before you next recompile the kernel. + Please note that this driver DOES NOT support the Cybervision 64 3D + card at present, as they use incompatible video chips. Amiga GSP (TMS340x0) support CONFIG_AMIGA_GSP @@ -5198,6 +5204,16 @@ CONFIG_ATARI_MIDI want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +Atari DSP56k Digital Signal Processor support +CONFIG_ATARI_DSP56K + If you want to be able to use the DSP56001 in Falcons, say Y. + This driver is still experimental, and if you don't know what it is, + or if you don't have this processor, just say N. + This driver is also available as a module ( = code which can be inserted + in and removed from the running kernel whenever you want). If you + want to compile it as a module, say M here and read + Documentation/modules.txt. + Amiga builtin serial support CONFIG_AMIGA_BUILTIN_SERIAL If you want to use your Amiga's built-in serial port in Linux, say diff --git a/Documentation/devices.tex b/Documentation/devices.tex index 80dc0f9de005..536fb90bee0d 100644 --- a/Documentation/devices.tex +++ b/Documentation/devices.tex @@ -15,6 +15,7 @@ % \begin{document} \newcommand{\file}{\tt} % Style to use for a filename +\newcommand{\url}{\it} % Style to use for an URL \newcommand{\hex}{\tt} % Style to use for a hex number \newcommand{\ud}{(Under development)} % Abbreviation \newcommand{\1}{\({}^1\)} @@ -46,7 +47,7 @@ foo \kill}% % \title{{\bf Linux Allocated Devices}} \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$} -\date{Last revised: April 7, 1997} +\date{Last revised: May 1, 1997} \maketitle % \noindent @@ -60,17 +61,19 @@ sources in \LaTeX\ and ASCII form. In case of discrepancy, the \LaTeX\ version is authoritative. This document is included by reference into the Linux Filesystem -Standard (FSSTND). The FSSTND is available via FTP from -tsx-11.mit.edu in the directory {\file -/pub/linux/docs/linux-standards/fsstnd}. +Standard (FSSTND). The FSSTND is available from +{\url ftp://tsx-11.mit.edu/pub/linux/docs/linux-standards/fsstnd/}. To have a major number allocated, or a minor number in situations where that applies (e.g.\ busmice), please contact me with the -appropriate device information. Also, if you have additional -information regarding any of the devices listed below, or if I have -made a mistake, I would greatly appreciate a note. When sending me -mail, {\em please\/} include the word ``device'' in the subject so -your mail won't accidentally get buried! +appropriate device information. I *very* much appreciate if you send +me a device description in the same format as the ones already in this +file. Also, if you have additional information regarding any of the +devices listed below, or if I have made a mistake, I would greatly +appreciate a note. + +NOTE: When sending me mail, {\em please\/} include the word ``device'' +in the subject so your mail won't accidentally get buried! Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga platform only. Allocations marked (68k/Atari) apply to Linux/68k on @@ -207,7 +210,9 @@ reply. \major{79}{}{char }{PAM Software's multimodem boards -- alternate devices} \major{80}{}{char }{Photometrics AT200 CCD camera} \major{81}{}{char }{Brooktree Bt848 frame grabbers} -\major{82}{--119}{}{Unallocated} +\major{82}{}{char }{WiNRADiO communications receiver card} +\major{83}{}{char }{Teletext/videotext interfaces} +\major{84}{--119}{}{Unallocated} \major{120}{--127}{}{Local/experimental use} \major{128}{--239}{}{Unallocated} \major{240}{--254}{}{Local/experimental use} @@ -1243,7 +1248,7 @@ $<$jth@prosig.demon.co.uk$>$ for information. \end{devicelist} \noindent -See {\em http://www.coda.cs.cmu.edu\/} for information about Coda. +See {\url http://www.coda.cs.cmu.edu\/} for information about Coda. \begin{devicelist} \major{68}{}{char }{CAPI 2.0 interface} @@ -1392,7 +1397,28 @@ Currently for Dolphin Interconnect Solutions' PCI-SCI bridge. \end{devicelist} \begin{devicelist} -\major{82}{--119}{}{Unallocated} +\major{82}{}{char }{WiNRADiO communications receiver card} + \major{0}{/dev/winradio0}{First WiNRADiO card} + \major{1}{/dev/winradio1}{Second WiNRADiO card} + \minordots +\end{devicelist} + +\noindent +The driver and documentation may be obtained from +{\url http://www.proximity.com.au/~brian/winradio/\/}. + +\begin{devicelist} +\major{83}{}{char }{Teletext/videotext interfaces} + \minor{0}{/dev/vtx}{Teletext decoder} + \minor{16}{/dev/vttuner}{TV tuner on teletext interface} +\end{devicelist} + +\noindent +Devices for the driver contained in the VideoteXt package. More information +on {\url http://home.pages.de/~videotext/\/}. + +\begin{devicelist} +\major{84}{--119}{}{Unallocated} \end{devicelist} \begin{devicelist} diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 17a99de9548b..6373052a5269 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -1,7 +1,7 @@ LINUX ALLOCATED DEVICES Maintained by H. Peter Anvin - Last revised: April 7, 1997 + Last revised: May 1, 1997 This list is the successor to Rick Miller's Linux Device List, which he stopped maintaining when he got busy with other things in 1993. It @@ -18,11 +18,14 @@ tsx-11.mit.edu in the directory /pub/linux/docs/linux-standards/fsstnd. To have a major number allocated, or a minor number in situations where that applies (e.g. busmice), please contact me with the -appropriate device information. Also, if you have additional -information regarding any of the devices listed below, or if I have -made a mistake, I would greatly appreciate a note. When sending me -mail, *please* include the word "device" in the subject so your mail -won't accidentally get buried! +appropriate device information. I *very* much appreciate if you send +me a device description in the same format as the ones already in this +file. Also, if you have additional information regarding any of the +devices listed below, or if I have made a mistake, I would greatly +appreciate a note. + +NOTE: When sending me mail, *please* include the word "device" in the +subject so your mail won't accidentally get buried! Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga platform only. Allocations marked (68k/Atari) apply to Linux/68k on @@ -979,7 +982,22 @@ reply. 33 = /dev/bttv-vbi1 VBI data of second Bt848 card ... - 82-119 UNALLOCATED + 82 char WiNRADiO communications receiver card + 0 = /dev/winradio0 First WiNRADiO card + 1 = /dev/winradio1 Second WiNRADiO card + ... + + The driver and documentation may be obtained from + http://www.proximity.com.au/~brian/winradio/ + + 83 char Teletext/videotext interfaces + 0 = /dev/vtx Teletext decoder + 16 = /dev/vttuner TV tuner on teletext interface + + Devices for the driver contained in the VideoteXt package. + More information on http://home.pages.de/~videotext/ + + 84-119 UNALLOCATED 120-127 LOCAL/EXPERIMENTAL USE diff --git a/Documentation/m68k/00-INDEX b/Documentation/m68k/00-INDEX new file mode 100644 index 000000000000..ae5b93488d51 --- /dev/null +++ b/Documentation/m68k/00-INDEX @@ -0,0 +1,9 @@ +00-INDEX + - this file +amiboot.txt + - info and options for the Linux/m68k Amiga bootstrap (Amiboot) +framebuffer.txt + - info about the Linux/m68k frame buffer device +kernel-options.txt + - command line options for Linux/m68k + diff --git a/Documentation/m68k/amiboot.README b/Documentation/m68k/amiboot.txt similarity index 76% rename from Documentation/m68k/amiboot.README rename to Documentation/m68k/amiboot.txt index 1e25e1d377f4..c119c6357b49 100644 --- a/Documentation/m68k/amiboot.README +++ b/Documentation/m68k/amiboot.txt @@ -1,7 +1,10 @@ - Linux/m68k Amiga Bootstrap version 5.1 + Linux/m68k Amiga Bootstrap version 5.5 -------------------------------------- +Maintained by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) +Last revised: March 27, 1997 + 0. Introduction --------------- @@ -10,7 +13,7 @@ Amiboot is used to boot Linux/m68k on Amiga from the CLI/Shell. Before you try to boot Linux/m68k for the first time, please read the FAQ - http://www-agrw.informatik.uni-kl.de/~jmayer/linux68k/linux68k-faq + http://www.clark.net/pub/lawrencc/linux/faq/faq.html and the Installation Guide @@ -19,7 +22,7 @@ and the Installation Guide first. Although the Installation Guide is getting a bit outdated, it's still a good starting point. -Amiboot 5.1 is meant for Linux/m68k 2.0.x, 2.1.x or higher (kernel bootinfo +Amiboot 5.5 is meant for Linux/m68k 2.0.x, 2.1.x or higher (kernel bootinfo interface versions 1.x and 2.x). Please use an older version for older kernels. @@ -30,23 +33,27 @@ The Amiboot invocation syntax looks like amiboot [options] [kernel command line] -Valid options are: +Basic options: --help Display the usage information --kernel file Use kernel image `file' (default is `vmlinux') - --ramdisk file Use ramdisk image `file'. + --ramdisk file Use ramdisk image `file' + +Advanced options: --debug Enable debug mode - --baud Set the serial port speed (default is 9600) + --baud speed Set the serial port speed (default is 9600 bps) --memfile file Use memory file `file' --keep-video Don't reset the video mode - --model id Set the Amiga model to `id'. + --model id Set the Amiga model to `id' + + --processor cfm Set the processor type to `cfm' The kernel command line contains the options you want to pass to the kernel and to init, the process that's started first by Linux. Please read @@ -57,6 +64,10 @@ Linux/m68k kernel image, and --ramdisk if you want to boot from a ramdisk file, i.e. a file containing a complete file system, instead of from a hard disk partition. +Note that both the kernel image and the ramdisk image can be compressed with +gzip. Amiboot knows how to deal with gzipped kernel images, and the kernel +recognizes gzipped ramdisk images. + Example: amiboot -k vmlinux-2.1.13 root=/dev/hda3 video=font:PEARL8x8 @@ -65,8 +76,8 @@ Amiboot will boot the kernel image `vmlinux-2.1.13' and will pass `root=/dev/hda3 video=font:PEARL8x8' to the kernel. -The other options are more specialized. Don't use them unless you really have -to and you know what you're doing. +The other options are more advanced. Don't use them unless you really have to +and you know what you're doing. The --baud option allows you to specify the serial port speed for initial boot information and initial kernel messages. Note: this option does not work with @@ -79,8 +90,9 @@ The --keep-video option is necessary if you want to retain the current graphics mode (on a graphics board) under Linux. Currently this is only useful if you have a CyberVision 64 graphics board. -Finally, --model allows you to specify your Amiga model, and --debug is for -debugging purposes. +Finally, --model and --processor allow you to specify your Amiga model and +processor type if they are detected incorrectly, and --debug dumps some +information which simplifies debugging. 2. The memory file @@ -98,7 +110,7 @@ format for the file is: ... For example, if you don't want Linux to use your 2nd meg of chipram, you would -create a file that looks contains only: +create a file that contains only: 1048576 @@ -149,7 +161,33 @@ Please send me the output of amiboot used with the --debug option if your Amiga model is detected incorrectly. -4. Abbreviations +4. Processor types +------------------ + +If your processor is detected incorrectly, you can override this using the +`--processor cfm' option. `cfm' must be a three-digit number with + + - `c' the CPU (Central Processing Unit) type, + - 'f' the FPU (Floating Point Unit) type, + - 'm' the MMU (Memory Management Unit) type, + +from the table below: + + value | CPU | FPU | MMU + -------+-------+-------+------- + 0 | - | - | - + 1 | 68020 | 68881 | 68851 + 2 | 68030 | 68882 | 68030 + 3 | 68040 | 68040 | 68040 + 4 | 68060 | 68060 | 68060 + +e.g. `444' if you have a 68060 and `303' if you have a 68LC040. + +Note that normally you don't have to use this option. It's only needed for some +combinations of an old Kickstart ROM and a new processor (e.g. a 68060). + + +5. Abbreviations ---------------- All options also have a shorthand: @@ -162,9 +200,10 @@ All options also have a shorthand: --memfile -m --keep-video -v --model -t + --processor -p -5. Miscellaneous +6. Miscellaneous ---------------- Some expansion boards keep on generating interrupts once they were initialized @@ -186,7 +225,7 @@ routine for them yet: If you write a routine to disable an expansion board, please let me know. -6. Troubleshooting +7. Troubleshooting ------------------ - Amiboot says @@ -222,11 +261,13 @@ If you write a routine to disable an expansion board, please let me know. o If that doesn't work, remove any expansion devices and retry. + o Check the detected Amiga model and processor type. + o Look at the characters that are dumped to the serial port during booting. -7. Amiga-Lilo +8. Amiga-Lilo ------------- Once you have a stable Linux/m68k installation, you may want to try Amiga-Lilo. @@ -234,7 +275,7 @@ Amiga-Lilo allows you to boot Linux/m68k without the overhead of booting AmigaOS first, and it provides you with a boot menu. -8. Credits +9. Credits ---------- This readme was written by Geert Uytterhoeven. A lot of information was taken diff --git a/Documentation/m68k/framebuffer.txt b/Documentation/m68k/framebuffer.txt new file mode 100644 index 000000000000..490a33793952 --- /dev/null +++ b/Documentation/m68k/framebuffer.txt @@ -0,0 +1,370 @@ + + The Linux/m68k Frame Buffer Device + ---------------------------------- + +Maintained by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) +Last revised: March 23, 1997 + + +0. Introduction +--------------- + +The frame buffer device provides an abstraction for the graphics hardware. It +represents the frame buffer of some video hardware and allows application +software to access the graphics hardware through a well-defined interface, so +the software doesn't need to know anything about the low-level (hardware +register) stuff. + +The device is accessed through special device nodes, usually located in the +/dev directory, i.e. /dev/fb*. + + +1. User's View of /dev/fb* +-------------------------- + +From the user's point of view, the frame buffer device looks just like any +other device in /dev. It's a character device using major 29, the minor is +divided into a frame buffer number in the upper 3 bits (allowing max. 8 frame +buffers simultaneously) and a resolution code in the lower 5 bits of the minor. + +By convention, the following device nodes are used (numbers indicate the device +minor numbers): + + First frame buffer + 0 = /dev/fb0current Current resolution + 1 = /dev/fb0autodetect Default resolution + 2 = /dev/fb0predefined0 Predefined resolutions (22) + ... + 23 = /dev/fb0predefined21 + 24 = /dev/fb0user0 User defined resolutions (8) + ... + 31 = /dev/fb0user7 + + Second frame buffer + 32 = /dev/fb1current Current resolution + 33 = /dev/fb1autodetect Default resolution + 34 = /dev/fb1predefined0 Predefined resolutions (22) + ... + 55 = /dev/fb1predefined21 + 56 = /dev/fb1user0 User defined resolutions (8) + ... + 63 = /dev/fb1user7 + +and so on... + +The device with (minor & 31) == 0 (/dev/fb?current) stands for the frame buffer +together with the currently set video parameters; (minor & 31) == 1 +(/dev/fb?autodetect) is the video mode detected at boot time. Any other minor +stands for some predefined or user defined video mode. + +The predefined entries (/dev/fb?predefined*) usually have a device dependent +name, e.g. for major 29, minor 5, we have /dev/fb0multiscan on Amiga and +/dev/fb0ttmid on Atari. These are meant to contain hardware dependent +resolutions. + +The user defined resolutions (/dev/fb?user?) are meant to be filled in by the +user. This way the user can store his favorite 8 resolutions during boot up. + +Note: if you need more than 8 user defined resolutions, you can always override +the predefined resolutions by storing them in one of the predefined entries. +But this is not recommended. Similarly, if there are more than 22 predefined +resolutions, the device writer can decide to store them in the user defined +entries. + +If the device is opened (for writing), the frame buffer driver switches to the +selected video mode. Thus, you can switch video modes by writing to a frame +buffer device, e.g. + + > /dev/fb0ttlow + +will switch your video to TT low mode. Note: if you specify a resolution which +contains a value that's not possible on your hardware, the frame buffer device +will round it up (if possible) or return an error condition. + +The frame buffer devices are also `normal' memory devices, this means, you can +read and write their contents. You can, for example, make a screen snapshot by + + cp /dev/fb0current myfile + +There also can be more than one frame buffer at a time, e.g. if you have a +graphics card in addition to the built-in hardware. The corresponding frame +buffer devices (/dev/fb0* and /dev/fb1* etc.) work independently. + +Application software that uses the frame buffer device (e.g. the X server) will +use /dev/fb0current by default. You can specify an alternative resolution by +setting the environment variable $FRAMEBUFFER to the path name of a frame +buffer device, e.g. (for sh/bash users): + + export FRAMEBUFFER=/dev/fb0multiscan + +or (for csh users): + + setenv FRAMEBUFFER /dev/fb0multiscan + +After this the X server will use the multiscan video mode. + + +2. Programmer's View of /dev/fb* +-------------------------------- + +As you already know, a frame buffer device is a memory device like /dev/mem and +it has the same features. You can read it, write it, seek to some location in +it and mmap() it (the main usage). The difference is just that the memory that +appears in the special file is not the whole memory, but the frame buffer of +some video hardware. + +/dev/fb* also allows several ioctls on it, by which lots of information about +the hardware can be queried and set. The color map handling works via ioctls, +too. Look into for more information on what ioctls exist and on +which data structures they work. Here's just a brief overview: + + - You can request unchangeable information about the hardware, like name, + organization of the screen memory (planes, packed pixels, ...) and address + and length of the screen memory. + + - You can request and change variable information about the hardware, like + visible and virtual geometry, depth, color map format, timing, and so on. + If you try to change that informations, the driver maybe will round up some + values to meet the hardware's capabilities (or return EINVAL if that isn't + possible). + + - You can get and set parts of the color map. Communication is done with 16 + bit per color part (red, green, blue, transparency) to support all existing + hardware. The driver does all the computations needed to bring it into the + hardware (round it down to less bits, maybe throw away transparency). + +All this hardware abstraction makes the implementation of application programs +easier and more portable. E.g. the X server works completely on /dev/fb* and +thus doesn't need to know, for example, how the color registers of the concrete +hardware are organized. XF68_FBDev is a general X server for bitmapped, +unaccelerated video hardware. The only thing that has to be built into +application programs is the screen organization (bitplanes or chunky pixels +etc.), because it works on the frame buffer image data directly. + +For the future it is planned that frame buffer drivers for graphics cards and +the like can be implemented as kernel modules that are loaded at runtime. Such +a driver just has to call register_framebuffer() and supply some functions. +Writing and distributing such drivers independently from the kernel will save +much trouble... + + +3. Frame Buffer Resolution Maintenance +-------------------------------------- + +Frame buffer resolutions are maintained using the utility `fbset'. It allows to +change the video mode properties of the current or a user defined resolution. +It's main usage is to tune video modes and to store custom resolutions into one +of the /dev/fb?user? entries, e.g. during boot up in one of your /etc/rc.* or +/etc/init.d/* files, after which those resolutions can be used by applications. + +Fbset uses a video mode database stored in a configuration file, so you can +easily add your own modes and refer to them with a simple identifier. The fbset +install script also creates the special device nodes for the device dependent +predefined resolutions. + + +4. The X Server +--------------- + +The X server (XF68_FBDev) is the most notable application program for the frame +buffer device. The current X server is part of the XFree86/XFree68 release 3.2 +package and has 2 modes: + + - If the `Display' subsection for the `fbdev' driver in the /etc/XF86Config + file contains a + + Modes "default" + + line, the X server will use the scheme discussed above, i.e. it will start + up in the resolution determined by /dev/fb0current (or $FRAMEBUFFER, if + set). This is the default for the configuration file supplied with XFree68 + 3.2. It's the most simple configuration (and the only possible one if you + want to have a broadcast compatible display, e.g. PAL or NTSC), but it has + some limitations. + + - Therefore it's also possible to specify resolutions in the /etc/XF86Config + file. This allows for on-the-fly resolution switching while retaining the + same virtual desktop size. The frame buffer device that's used is still + /dev/fb0current (or $FRAMEBUFFER), but the available resolutions are + defined by /etc/XF86Config now. The disadvantage is that you have to + specify the timings in a different format (but `fbset -x' may help) and + that you can't have a broadcast compatible display (e.g. no PAL or NTSC). + +To tune a video mode, you can use fbset or xvidtune. Note that xvidtune doesn't +work 100% with XF68_FBDev: the reported clock values are always incorrect. + +There exists also an accelerated X server for the Cybervision 64 graphics +board, but that's not discussed here. + + +5. Video Mode Timings +--------------------- + +A monitor draws an image on the screen by using an electron beam (3 electron +beams for most color models, 1 electron beam for Trinitron color monitors and +monochrone monitors). The front of the screen is covered by a pattern of +colored phospors (pixels). If a phospor is hit by an electron, it emits a +photon and thus becomes visible. + +The electron beam draws horizontal lines (scanlines) from left to right, and +from the top to the bottom of the screen. By modifying the intensity of the +electron beam, pixels with various colors and intensities can be shown. + +After each scanline the electron beam has to move back to the left side of the +screen and to the next line: this is called the horizontal retrace. After the +whole screen (frame) was painted, the beam moves back to the upper left corner: +this is called the vertical retrace. During both the horizontal and vertical +retrace, the electron beam is turned off (blanked). + +The speed at which the electron beam paints the pixels is determined by the +dotclock in the graphics board. For a dotclock of e.g. 28.37516 MHz (millions +of cycles per second), each pixel is 35242 ps (picoseconds) long: + + 1/(28.37516E6 Hz) = 35.242E-9 s + +If the screen resolution is 640x480, it will take + + 640*35.242E-9 s = 22.555E-6 s + +to paint the 640 (xres) pixels on one scanline. But the horizontal retrace +also takes time (e.g. 272 `pixels'), so a full scanline takes + + (640+272)*35.242E-9 s = 32.141E-6 s + +We'll say that the horizontal scanrate is about 31 kHz: + + 1/(32.141E-6 s) = 31.113E3 Hz + +A full screen counts 480 (yres) lines, but we have to consider the vertical +retrace too (e.g. 49 `pixels'). So a full screen will take + + (480+49)*32.141E-6 s = 17.002E-3 s + +The vertical scanrate is about 59 Hz: + + 1/(17.002E-3 s) = 58.815 Hz + +This means the screen data is refreshed about 59 times per second. To have a +stable picture without visible flicker, VESA recommends a vertical scanrate of +at least 72 Hz. But the perceived flicker is very human dependent: some people +can use 50 Hz without any trouble, while I'll notice if it's less than 80 Hz. + +Since the monitor doesn't know when a new scanline starts, the graphics board +will supply a synchronization pulse (horizontal sync or hsync) for each +scanline. Similarly it supplies a synchronization pulse (vertical sync or +vsync) for each new frame. The position of the image on the screen is +influenced by the moments at which the synchronization pulses occur. + +The following picture summarizes all timings. The horizontal retrace time is +the sum of the left margin, the right margin and the hsync length, while the +vertical retrace time is the sum of the upper margin, the lower margin and the +vsync length. + + +----------+---------------------------------------------+----------+-------+ + | | ^ | | | + | | |upper_margin | | | + | | ¥ | | | + +----------###############################################----------+-------+ + | # ^ # | | + | # | # | | + | # | # | | + | # | # | | + | left # | # right | hsync | + | margin # | xres # margin | len | + |<-------->#<---------------+--------------------------->#<-------->|<----->| + | # | # | | + | # | # | | + | # | # | | + | # |yres # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # ¥ # | | + +----------###############################################----------+-------+ + | | ^ | | | + | | |lower_margin | | | + | | ¥ | | | + +----------+---------------------------------------------+----------+-------+ + | | ^ | | | + | | |vsync_len | | | + | | ¥ | | | + +----------+---------------------------------------------+----------+-------+ + +The frame buffer device expects all horizontal timings in number of dotclocks +(in picoseconds, 1E-12 s), and vertical timings in number of scanlines. + + +6. Converting XFree86 timing values info frame buffer device timings +-------------------------------------------------------------------- + +An XFree86 mode line consists of the following fields: + "800x600" 50 800 856 976 1040 600 637 643 666 + < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL + +The frame buffer device uses the following fields: + + - pixclock: pixel clock in ps (pico seconds) + - left_margin: time from sync to picture + - right_margin: time from picture to sync + - upper_margin: time from sync to picture + - lower_margin: time from picture to sync + - hsync_len: length of horizontal sync + - vsync_len: length of vertical sync + +1) Pixelclock: + xfree: in MHz + fb: In Picoseconds (ps) + + pixclock = 1000000 / DCF + +2) horizontal timings: + left_margin = HFL - SH2 + right_margin = SH1 - HR + hsync_len = SH2 - SH1 + +3) vertical timings: + upper_margin = VFL - SV2 + lower_margin = SV1 - VR + vsync_len = SV2 - SV1 + +Good examples for VESA timings can be found in the XFree86 source tree, +under "xc/programs/Xserver/hw/xfree86/doc/modeDB.txt". + + +7. References +------------- + +For more specific information about the frame buffer device and its +applications, please refer to the following documentation: + + - The manual pages for fbset: fbset(8), fb.modes(5) + - The manual pages for XFree68: XF68_FBDev(1), XF86Config(4/5) + - The mighty kernel sources: + o linux/include/linux/fb.h + o linux/drivers/char/fbmem.c + o linux/arch/m68k/*/*fb.c + + +8. Downloading +-------------- + +All necessary files can be found at + + ftp://ftp.uni-erlangen.de/pub/Linux/LOCAL/680x0/ + +and on its mirrors. + + +9. Credits +---------- + +This readme was written by Geert Uytterhoeven, partly based on the original +`X-framebuffer.README' by Roman Hodek and Martin Schaller. Section 6 was +provided by Frank Neumann. + +The frame buffer device abstraction was designed by Martin Schaller. diff --git a/Documentation/m68k/kernel-options.txt b/Documentation/m68k/kernel-options.txt index b5878662d3e4..ed0c203d0388 100644 --- a/Documentation/m68k/kernel-options.txt +++ b/Documentation/m68k/kernel-options.txt @@ -800,6 +800,18 @@ hostadapters. No argument. Used to separate blocks of keywords when there's more than one host adapter in the system. +5.3.7) nodma +------------ + +Syntax: nodma:x + + If x is 1 (or if the option is just written as "nodma"), the WD33c93 +controller will not use DMA (= direct memory access) to access the +Amiga's memory. This is useful for some systems (like A3000's and +A4000's with the A3640 accelerator, revision 3.0) that have problems +using DMA to chip memory. The default is 0, i.e. to use DMA if +possible. + 5.4) gvp11= ----------- diff --git a/Documentation/networking/net-modules.txt b/Documentation/networking/net-modules.txt index b83d2bd9f92c..bdf5a34a1d67 100644 --- a/Documentation/networking/net-modules.txt +++ b/Documentation/networking/net-modules.txt @@ -109,6 +109,10 @@ Card/Module List - Configurable Parameters and Default Values 8390.c: (No public options, several other modules need this one) +a2065.c: + Since this is a Zorro board, it supports full autoprobing, even for + multiple boards. (m68k/Amiga) + ac3200.c: io = 0 (Checks 0x1000 to 0x8fff in 0x1000 intervals) irq = 0 (Read from config register) @@ -133,11 +137,24 @@ arcnet.c: 0x310, 0x320, 0x330, 0x340, 0x350, 0x360, 0x370, 0x380, 0x390, 0x3A0, 0x3E0, 0x3F0 ) +ariadne.c: + Since this is a Zorro board, it supports full autoprobing, even for + multiple boards. (m68k/Amiga) + at1700.c: io = 0x260 irq = 0 (Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300) +atari_bionet.c: + Supports full autoprobing. (m68k/Atari) + +atari_pamsnet.c: + Supports full autoprobing. (m68k/Atari) + +atarilance.c: + Supports full autoprobing. (m68k/Atari) + atp.c: *Not modularized* (Probes ports: 0x378, 0x278, 0x3BC; fixed IRQs: 5 and 7 ) @@ -212,6 +229,10 @@ hp100.c: On ISA-bus probes all ports from 0x100 thru to 0x3E0 in increments of 0x020) +hydra.c: + Since this is a Zorro board, it supports full autoprobing, even for + multiple boards. (m68k/Amiga) + ibmtr.c: io = 0xa20, 0xa24 (autoprobed by default) irq = 0 (driver cannot select irq - read from hardware) diff --git a/Documentation/serial-console.txt b/Documentation/serial-console.txt index 22f02e2b77ba..4d81e4c98c11 100644 --- a/Documentation/serial-console.txt +++ b/Documentation/serial-console.txt @@ -47,7 +47,7 @@ as the serial console. Replace as needed. Sysvinit remembers its stty settings in a file in /etc, called `/etc/ioctl.save'. REMOVE THIS FILE before using the serial console for the first time, because otherwise init will probably - set the baudrate to 38400 (bausdrate of the virtual console). + set the baudrate to 38400 (baudrate of the virtual console). 5. /dev/console and X Programs that want to do something with the virtual console usually diff --git a/Makefile b/Makefile index 84506010cfc4..c4cafd1e7574 100644 --- a/Makefile +++ b/Makefile @@ -352,6 +352,8 @@ distclean: mrproper rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS + rm -f drivers/sound/Config.in + cp drivers/sound/Config.std drivers/sound/Config.in backup: mrproper cd .. && tar cf - linux/ | gzip -9 > backup.gz diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index ef582b80e74a..af26f8996d57 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -126,7 +126,8 @@ .ent entInt entInt: SAVE_ALL - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 jsr $26,do_entInt br $31,ret_from_sys_call .end entInt @@ -147,7 +148,8 @@ entMM: stq $15,48($30) addq $30,56,$19 /* handle the fault */ - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 jsr $26,do_page_fault /* reload the registers after the exception code played. */ ldq $9,0($30) @@ -167,7 +169,8 @@ entMM: .ent entArith entArith: SAVE_ALL - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 /* How much of a win is this clockwise? We are, after all, messing up the call/return prefetch stack. -- rth */ lda $27,do_entArith @@ -180,7 +183,8 @@ entArith: .ent entIF entIF: SAVE_ALL - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 lda $27,do_entIF lda $26,ret_from_sys_call jsr $31,($27),do_entIF @@ -221,12 +225,13 @@ kernel_clone: .globl __kernel_thread .ent __kernel_thread __kernel_thread: + ldgp $29,0($27) /* we can be called from a module */ .frame $30, 4*8, $26 subq $30,4*8,$30 stq $10,16($30) stq $9,8($30) stq $26,0($30) - .prologue 0 + .prologue 1 bis $17,$17,$9 /* save fn */ bis $18,$18,$10 /* save arg */ bsr $26,kernel_clone @@ -238,10 +243,9 @@ __kernel_thread: ret $31,($26),1 /* this is in child: look out as we don't have any stack here.. */ 1: bis $9,$9,$27 /* get fn */ - br $29,2f -2: ldgp $29,0($29) + lda $8,0x3fff bis $10,$10,$16 /* get arg */ - ldq $8,current_set + bic $30,$8,$8 /* get current */ jsr $26,($27) bis $0,$0,$16 jsr $26,sys_exit @@ -382,7 +386,8 @@ entUna: stq $29,232($30) stq $30,240($30) stq $31,248($30) - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 jsr $26,do_entUna ldq $0,0($30) ldq $1,8($30) @@ -432,7 +437,8 @@ entUnaUser: stq $14,40($30) stq $15,48($30) bis $31,$30,$19 - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 jsr $26,do_entUnaUser ldq $9,0($30) ldq $10,8($30) @@ -497,7 +503,8 @@ alpha_switch_to: .ent entSys entSys: SAVE_ALL - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 lda $4,NR_SYSCALLS($31) stq $16,SP_OFF+24($30) lda $5,sys_call_table @@ -532,7 +539,7 @@ ret_from_handle_bh: ret_from_reschedule: lda $0,need_resched ldl $2,0($0) - lda $4,init_task + lda $4,init_task_union bne $2,reschedule xor $4,$8,$4 beq $4,restore_all diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S index 17ca4581a112..a9e132666ec6 100644 --- a/arch/alpha/kernel/head.S +++ b/arch/alpha/kernel/head.S @@ -23,9 +23,11 @@ _stext: __start: br $27,1f 1: ldgp $29,0($27) - /* We need to get current loaded up with our first task. */ - ldq $8,current_set - /* And then we can start the kernel. */ + /* We need to get current loaded up with our first task... */ + lda $8,init_task_union + /* ... and find our stack ... */ + lda $30,0x4000($8) + /* ... and then we can start the kernel. */ jsr $26,start_kernel halt .end __start diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 4db00a97ea31..b6c97e726310 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -37,6 +37,7 @@ #include #include #include +#include /* * Initial task structure. Make this a per-architecture thing, @@ -44,15 +45,16 @@ * alignment requirements and potentially different initial * setup. */ -static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; + unsigned long init_user_stack[1024] = { STACK_MAGIC, }; static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; - struct mm_struct init_mm = INIT_MM; -struct task_struct init_task = INIT_TASK; + +union task_union init_task_union __attribute__((section("init_task"))) + = { task: INIT_TASK }; /* * No need to acquire the kernel lock, we're entirely local.. @@ -202,7 +204,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, stack_offset = PAGE_SIZE - sizeof(struct pt_regs); if (!(regs->ps & 8)) stack_offset = (PAGE_SIZE-1) & (unsigned long) regs; - childregs = (struct pt_regs *) (p->kernel_stack_page + stack_offset); + childregs = (struct pt_regs *) (stack_offset + PAGE_SIZE + (unsigned long)p); *childregs = *regs; childregs->r0 = 0; diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index b434d356d46a..edfbb80eaabb 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -67,7 +67,7 @@ * | | | * | | v * +================================+ <------------------------- - * task->kernel_stack_page + * task + PAGE_SIZE */ #define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ + (long)&((struct pt_regs *)0)->reg) @@ -120,7 +120,7 @@ static inline long get_reg(struct task_struct * task, long regno) zero = 0; addr = &zero; } else { - addr = (long *) (task->kernel_stack_page + regoff[regno]); + addr = (long *) (regoff[regno] + PAGE_SIZE + (long)task); } return *addr; } @@ -137,7 +137,7 @@ static inline int put_reg(struct task_struct *task, long regno, long data) } else if (regno == 31) { addr = &zero; } else { - addr = (long *) (task->kernel_stack_page + regoff[regno]); + addr = (long *) (regoff[regno] + PAGE_SIZE + (long)task); } *addr = data; return 0; diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 0fa1129eee8a..31a1f21fcbe8 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -21,9 +21,9 @@ #include #include #include /* CONFIG_ALPHA_LCA etc */ +#include #ifdef CONFIG_RTC -#include #include #endif diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index 13e8e4ce4e85..67faa97d4d14 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -133,7 +133,6 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) init_task.tss.ptbr = newptbr; init_task.tss.pal_flags = 1; /* set FEN, clear everything else */ init_task.tss.flags = 0; - init_task.kernel_stack_page = INIT_STACK; load_PCB(&init_task.tss); flush_tlb_all(); @@ -182,7 +181,7 @@ void free_initmem (void) atomic_set(&mem_map[MAP_NR(addr)].count, 1); free_page(addr); } - printk ("Freeing unused kernel memory: %dk freed\n", + printk ("Freeing unused kernel memory: %ldk freed\n", (&__init_end - &__init_begin) >> 10); } diff --git a/arch/alpha/vmlinux.lds b/arch/alpha/vmlinux.lds index 2a5f00989718..0fb2276eabd7 100644 --- a/arch/alpha/vmlinux.lds +++ b/arch/alpha/vmlinux.lds @@ -5,6 +5,7 @@ SECTIONS . = 0xfffffc0000310000; _text = .; .text : { *(.text) } + .text2 : { *(.text2) } _etext = .; /* Exception table */ @@ -25,9 +26,12 @@ SECTIONS __init_begin = .; .text.init : { *(.text.init) } .data.init : { *(.data.init) } - . = ALIGN(8192); + . = ALIGN(2*8192); /* Align double page for init_task_union */ __init_end = .; + /* The initial task and kernel stack */ + init_task : { *(init_task) } + /* Global data */ _data = .; .rodata : { *(.rodata) } diff --git a/arch/i386/kernel/bios32.c b/arch/i386/kernel/bios32.c index e128000c38a5..ac46f9e4ce84 100644 --- a/arch/i386/kernel/bios32.c +++ b/arch/i386/kernel/bios32.c @@ -52,6 +52,9 @@ * Feb 3, 1997 : Set internal functions to static, save/restore flags * avoid dead locks reading broken PCI BIOS, werner@suse.de * + * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS + * (mj@atrey.karlin.mff.cuni.cz) + * */ #include @@ -173,10 +176,10 @@ static unsigned long bios32_service(unsigned long service) case 0: return address + entry; case 0x80: /* Not present */ - printk("bios32_service(%ld) : not present\n", service); + printk("bios32_service(0x%lx) : not present\n", service); return 0; default: /* Shouldn't happen */ - printk("bios32_service(%ld) : returned 0x%x, mail drew@colorado.edu\n", + printk("bios32_service(0x%lx) : returned 0x%x, mail drew@colorado.edu\n", service, return_code); return 0; } @@ -189,7 +192,7 @@ static struct { } pci_indirect = { 0, KERNEL_CS }; -__initfunc(static unsigned long check_pcibios(unsigned long memory_start, unsigned long memory_end)) +__initfunc(static int check_pcibios(void)) { unsigned long signature; unsigned char present_status; @@ -212,7 +215,7 @@ __initfunc(static unsigned long check_pcibios(unsigned long memory_start, unsign : "1" (PCIBIOS_PCI_BIOS_PRESENT), "D" (&pci_indirect) : "bx", "cx"); - restore_flags(flags); + restore_flags(flags); present_status = (pack >> 16) & 0xff; major_revision = (pack >> 8) & 0xff; @@ -232,9 +235,10 @@ __initfunc(static unsigned long check_pcibios(unsigned long memory_start, unsign if (pcibios_entry) { printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n", major_revision, minor_revision, pcibios_entry); + return 1; } } - return memory_start; + return 0; } @@ -912,13 +916,11 @@ __initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long bios32_entry = check->fields.entry; printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); bios32_indirect.address = bios32_entry + PAGE_OFFSET; - access_pci = &pci_bios_access; } } } - if (bios32_entry) { - memory_start = check_pcibios (memory_start, memory_end); - } + if (bios32_entry && check_pcibios()) + access_pci = &pci_bios_access; #endif return memory_start; } diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index f815352b0a70..a42b87b1bb95 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -69,24 +69,16 @@ startup_32: movl $1f,%eax jmp *%eax /* make sure eip is relocated */ 1: + /* Set up the stack pointer */ + lss stack_start,%esp #ifdef __SMP__ orw %bx,%bx jz 1f /* Initial CPU cleans BSS */ -/* - * Set up the stack - */ - movl $(KERNEL_DS),%eax /* walken modif */ - mov %ax,%ss - xorl %eax,%eax - movw %cx, %ax - movl %eax,%esp - addl $0xC0000000, %esp /* shift it to the upper mapping */ pushl $0 popfl jmp checkCPUtype 1: - lss stack_start,%esp #endif __SMP__ /* * Clear BSS first so that there are no surprises... @@ -307,7 +299,7 @@ rp_sidt: jne rp_sidt ret -stack_start: +ENTRY(stack_start) .long SYMBOL_NAME(init_task_union)+8192 .long KERNEL_DS diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index f8bc39514174..be88c7bbf444 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -44,9 +44,6 @@ extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS]; #define CR0_NE 32 -/* This contains the irq mask for both irq controllers */ -static unsigned long cached_irq_mask = 0xffff; - unsigned int local_irq_count[NR_CPUS]; #ifdef __SMP__ atomic_t __intel_bh_counter; @@ -58,32 +55,64 @@ int __intel_bh_counter; static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},}; #endif -static inline void ack_irq(int irq_nr) +/* + * This contains the irq mask for both irq controllers + */ +static unsigned int cached_irq_mask = 0xffff; + +#define cached_21 (((char *)(&cached_irq_mask))[0]) +#define cached_A1 (((char *)(&cached_irq_mask))[1]) + +spinlock_t irq_controller_lock; + +/* + * This is always called from an interrupt context + * with local interrupts disabled. Don't worry about + * irq-safe locks. + * + * Note that we always ack the primary irq controller, + * even if the interrupt came from the secondary, as + * the primary will still have routed it. Oh, the joys + * of PC hardware. + */ +static inline void mask_and_ack_irq(int irq_nr) { + spin_lock(&irq_controller_lock); + cached_irq_mask |= 1 << irq_nr; if (irq_nr & 8) { + inb(0xA1); /* DUMMY */ + outb(cached_A1,0xA1); outb(0x20,0xA0); + } else { + inb(0x21); /* DUMMY */ + outb(cached_21,0x21); } outb(0x20,0x20); + spin_unlock(&irq_controller_lock); } static inline void set_irq_mask(int irq_nr) { if (irq_nr & 8) { - outb(cached_irq_mask>>8,0xA1); + outb(cached_A1,0xA1); } else { - outb(cached_irq_mask,0x21); + outb(cached_21,0x21); } -} +} +/* + * These have to be protected by the spinlock + * before being called. + */ static inline void mask_irq(unsigned int irq_nr) { - set_bit(irq_nr, &cached_irq_mask); + cached_irq_mask |= 1 << irq_nr; set_irq_mask(irq_nr); } static inline void unmask_irq(unsigned int irq_nr) { - clear_bit(irq_nr, &cached_irq_mask); + cached_irq_mask &= ~(1 << irq_nr); set_irq_mask(irq_nr); } @@ -91,20 +120,19 @@ void disable_irq(unsigned int irq_nr) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&irq_controller_lock, flags); mask_irq(irq_nr); + spin_unlock_irqrestore(&irq_controller_lock, flags); synchronize_irq(); - restore_flags(flags); } void enable_irq(unsigned int irq_nr) { unsigned long flags; - save_flags(flags); - cli(); + + spin_lock_irqsave(&irq_controller_lock, flags); unmask_irq(irq_nr); - restore_flags(flags); + spin_unlock_irqrestore(&irq_controller_lock, flags); } /* @@ -511,11 +539,19 @@ asmlinkage void do_IRQ(struct pt_regs regs) { int irq = regs.orig_eax & 0xff; struct irqaction * action; - int status, cpu = smp_processor_id(); + int status, cpu; + + /* + * mask and ack quickly, we don't want the irq controller + * thinking we're snobs just because some other CPU has + * disabled global interrupts (we have already done the + * INT_ACK cycles, it's too late to try to pretend to the + * controller that we aren't taking the interrupt). + */ + mask_and_ack_irq(irq); + cpu = smp_processor_id(); irq_enter(cpu, irq); - mask_irq(irq); - ack_irq(irq); kstat.interrupts[irq]++; /* Return with this interrupt masked if no action */ @@ -531,7 +567,9 @@ asmlinkage void do_IRQ(struct pt_regs regs) add_interrupt_randomness(irq); __cli(); + spin_lock(&irq_controller_lock); unmask_irq(irq); + spin_unlock(&irq_controller_lock); } irq_exit(cpu, irq); @@ -575,8 +613,9 @@ int setup_x86_irq(int irq, struct irqaction * new) *p = new; if (!shared) { - set_intr_gate(0x20+irq,interrupt[irq]); + spin_lock(&irq_controller_lock); unmask_irq(irq); + spin_unlock(&irq_controller_lock); } restore_flags(flags); return 0; @@ -678,10 +717,6 @@ int probe_irq_off (unsigned long irqs) __initfunc(void init_IRQ(void)) { int i; - static unsigned char smptrap=0; - if(smptrap) - return; - smptrap=1; /* set the clock to 100 Hz */ outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index f738eb9a3075..6843a60c7ecd 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -30,6 +30,7 @@ #include #include #include +#include #if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF) #include #endif @@ -184,7 +185,7 @@ static long no_idt[2] = {0, 0}; static int reboot_mode = 0; static int reboot_thru_bios = 0; -void reboot_setup(char *str, int *ints) +__initfunc(void reboot_setup(char *str, int *ints)) { while(1) { switch (*str) { diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 476657e2ea8b..e4e08c82f110 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -122,7 +122,6 @@ struct cpuinfo_x86 cpu_data[NR_CPUS]; /* Per cpu bogomips and other parameters static unsigned int num_processors = 1; /* Internal processor count */ static unsigned long io_apic_addr = 0xFEC00000; /* Address of the I/O apic (not yet used) */ unsigned char boot_cpu_id = 0; /* Processor that is doing the boot up */ -static unsigned char *kstack_base,*kstack_end; /* Kernel stack list pointers */ static int smp_activated = 0; /* Tripped once we need to start cross invalidating */ int apic_version[NR_CPUS]; /* APIC version number */ static volatile int smp_commenced=0; /* Tripped when we start scheduling */ @@ -535,6 +534,7 @@ __initfunc(int smp_scan_config(unsigned long base, unsigned long length)) extern unsigned char trampoline_data []; extern unsigned char trampoline_end []; +static unsigned char *trampoline_base; /* * Currently trivial. Write the real->protected mode @@ -542,33 +542,22 @@ extern unsigned char trampoline_end []; * has made sure it's suitably aligned. */ -__initfunc(static void install_trampoline(unsigned char *mp)) +__initfunc(static unsigned long setup_trampoline(void)) { - memcpy(mp, trampoline_data, trampoline_end - trampoline_data); + memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data); + return virt_to_phys(trampoline_base); } /* - * We are called very early to get the low memory for the trampoline/kernel stacks - * This has to be done by mm/init.c to parcel us out nice low memory. We allocate - * the kernel stacks at 4K, 8K, 12K... currently (0-03FF is preserved for SMM and - * other things). + * We are called very early to get the low memory for the + * SMP bootup trampoline page. */ - __initfunc(unsigned long smp_alloc_memory(unsigned long mem_base)) { - int size=(num_processors-1)*PAGE_SIZE; /* Number of stacks needed */ - - /* - * Our stacks have to be below the 1Mb line, and mem_base on entry - * is 4K aligned. - */ - - if(virt_to_phys((void *)(mem_base+size))>=0x9F000) - panic("smp_alloc_memory: Insufficient low memory for kernel stacks 0x%lx.\n", mem_base); - kstack_base=(void *)mem_base; - mem_base+=size; - kstack_end=(void *)mem_base; - return mem_base; + if (virt_to_phys((void *)mem_base) >= 0x9F000) + panic("smp_alloc_memory: Insufficient low memory for kernel trampoline 0x%lx.\n", mem_base); + trampoline_base = (void *)mem_base; + return mem_base + PAGE_SIZE; } /* @@ -663,8 +652,6 @@ extern int cpu_idle(void * unused); */ __initfunc(int start_secondary(void *unused)) { - trap_init(); - init_IRQ(); smp_callin(); cpu_idle(NULL); } @@ -672,7 +659,7 @@ __initfunc(int start_secondary(void *unused)) /* * Everything has been set up for the secondary * CPU's - they just need to reload everything - * from the task structude + * from the task structure */ __initfunc(void initialize_secondary(void)) { @@ -680,8 +667,9 @@ __initfunc(void initialize_secondary(void)) /* * We don't actually need to load the full TSS, - * just the stack pointer and the eip. + * basically just the stack pointer and the eip. */ + asm volatile("lldt %%ax": :"a" (p->ldt)); asm volatile("ltr %%ax": :"a" (p->tr)); asm volatile( "movl %0,%%esp\n\t" @@ -690,14 +678,19 @@ __initfunc(void initialize_secondary(void)) :"r" (p->esp),"r" (p->eip)); } +extern struct { + void * esp; + unsigned short ss; +} stack_start; + __initfunc(static void do_boot_cpu(int i)) { unsigned long cfg; pgd_t maincfg; - void *stack; struct task_struct *idle; unsigned long send_status, accept_status; int timeout, num_starts, j; + unsigned long start_eip; /* * We need an idle process for each processor. @@ -714,11 +707,11 @@ __initfunc(static void do_boot_cpu(int i)) cpu_logical_map[cpucount] = i; cpu_number_map[i] = cpucount; - /* This MUST be in the low 1MB range. That's ok, we're cool */ - stack = (void *) (4096+(char *)idle); - install_trampoline(stack); + /* start_eip had better be page-aligned! */ + start_eip = setup_trampoline(); - printk("Booting processor %d stack %p: ",i,stack); /* So we set what's up */ + printk("Booting processor %d eip %lx: ", i, start_eip); /* So we see what's up */ + stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle); /* * This grunge runs the startup process for @@ -730,9 +723,9 @@ __initfunc(static void do_boot_cpu(int i)) CMOS_WRITE(0xa, 0xf); local_flush_tlb(); SMP_PRINTK(("1.\n")); - *((volatile unsigned short *) phys_to_virt(0x469)) = ((unsigned long)stack)>>4; + *((volatile unsigned short *) phys_to_virt(0x469)) = start_eip >> 4; SMP_PRINTK(("2.\n")); - *((volatile unsigned short *) phys_to_virt(0x467)) = 0; + *((volatile unsigned short *) phys_to_virt(0x467)) = start_eip & 0xf; SMP_PRINTK(("3.\n")); maincfg=swapper_pg_dir[0]; @@ -821,7 +814,7 @@ __initfunc(static void do_boot_cpu(int i)) cfg&=~0xCDFFF; /* Clear bits */ cfg |= (APIC_DEST_FIELD | APIC_DEST_DM_STARTUP - | (virt_to_phys(stack) >> 12)); /* Boot on the stack */ + | (start_eip >> 12)); /* Boot on the stack */ SMP_PRINTK(("Before start apic_write.\n")); apic_write(APIC_ICR, cfg); /* Kick the second */ @@ -1602,11 +1595,11 @@ __initfunc(int calibrate_APIC_clock (void)) calibration_result)); - printk("\n..... CPU clock speed is %ld.%ld MHz.\n", + printk("\n..... CPU clock speed is %ld.%04ld MHz.\n", ((long)(t2-t1)/LOOPS)/(1000000/HZ), ((long)(t2-t1)/LOOPS)%(1000000/HZ) ); - printk("..... APIC bus clock speed is %ld.%ld MHz.\n", + printk("..... APIC bus clock speed is %ld.%04ld MHz.\n", calibration_result/(1000000/HZ), calibration_result%(1000000/HZ) ); #undef LOOPS diff --git a/arch/i386/kernel/trampoline.S b/arch/i386/kernel/trampoline.S index b6d7d54de15a..d0a726f6b2c7 100644 --- a/arch/i386/kernel/trampoline.S +++ b/arch/i386/kernel/trampoline.S @@ -39,10 +39,6 @@ r_base = . mov %cs, %ax # Code and data in the same place mov %ax, %ds - mov %ax, %cx # Pass stack info to the 32bit boot - shl $4, %cx # Segment -> Offset - add $1024, %cx # Don't overwrite end of page (filled in by kernel_thread) - mov $1, %bx # Flag an SMP trampoline cli # We should be safe anyway diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index feef85d8a3d9..7d99d9400f88 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -384,15 +384,7 @@ __initfunc(void trap_init(void)) { int i; struct desc_struct * p; - static int smptrap=0; - - if(smptrap) - { - __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); - load_ldt(0); - return; - } - smptrap++; + if (readl(0x0FFFD9) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24)) EISA_bus = 1; set_call_gate(&default_ldt,lcall7); diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile index 7ea3f1e29195..d56bfe459131 100644 --- a/arch/i386/lib/Makefile +++ b/arch/i386/lib/Makefile @@ -11,6 +11,6 @@ else endif L_TARGET = lib.a -L_OBJS = checksum.o semaphore.o locks.o +L_OBJS = checksum.o checksumcopy.o semaphore.o locks.o include $(TOPDIR)/Rules.make diff --git a/arch/i386/lib/checksum.c b/arch/i386/lib/checksum.c index 4a0f82440eeb..00048dae5f71 100644 --- a/arch/i386/lib/checksum.c +++ b/arch/i386/lib/checksum.c @@ -11,21 +11,25 @@ * Lots of code moved from tcp.c and ip.c; see those files * for more names. * - * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception - * handling. - * * This program 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. */ +#include #include /* - * computes a partial checksum, e.g. for TCP/UDP fragments + * Computes a partial checksum + * + * mostly used for IP header checksumming. Thus we define the following + * fastpath: len==20, buff is 4 byte aligned. + * */ +unsigned int csum_partial_bug=0; + unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) { /* * Experiments with ethernet and slip connections show that buff @@ -34,7 +38,9 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) * Fortunately, it is easy to convert 2-byte alignment to 4-byte * alignment for the unrolled loop. */ + __asm__(" + testl $2, %%esi # Check alignment. jz 2f # Jump if alignment is ok. subl $2, %%ecx # Alignment uses up two bytes. @@ -92,155 +98,11 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) adcl $0, %%eax 7: " : "=a"(sum) - : "0"(sum), "c"(len), "S"(buff) + : "0"(sum), "c"(len), "S"(buff), "m"(csum_partial_bug) : "bx", "cx", "dx", "si"); return(sum); } -/* - * Copy from ds while checksumming, otherwise like csum_partial - * - * The macros SRC and DST specify the type of access for the instruction. - * thus we can call a custom exception handler for all access types. - * - * FIXME: could someone double check wether i havent mixed up some SRC and - * DST definitions? It's damn hard to trigger all cases, i hope i got - * them all but theres no guarantee ... - */ - -#define SRC(y...) \ -" 9999: "#y"; \n \ - .section __ex_table, \"a\"; \n \ - .long 9999b, src_access_fault \n \ - .previous" - -#define DST(y...) \ -" 9999: "#y"; \n \ - .section __ex_table, \"a\"; \n \ - .long 9999b, dst_access_fault \n \ - .previous" - -unsigned int csum_partial_copy_generic (const char *src, char *dst, - int len, int sum, int *src_err_ptr, int *dst_err_ptr) -{ - __asm__ __volatile__ ( " - testl $2, %%edi # Check alignment. - jz 2f # Jump if alignment is ok. - subl $2, %%ecx # Alignment uses up two bytes. - jae 1f # Jump if we had at least two bytes. - addl $2, %%ecx # ecx was < 2. Deal with it. - jmp 4f -"SRC( 1: movw (%%esi), %%bx )" - addl $2, %%esi -"DST( movw %%bx, (%%edi) )" - addl $2, %%edi - addw %%bx, %%ax - adcl $0, %%eax - 2: - pushl %%ecx - shrl $5, %%ecx - jz 2f - testl %%esi, %%esi -"SRC( 1: movl (%%esi), %%ebx )" -"SRC( movl 4(%%esi), %%edx )" - adcl %%ebx, %%eax -"DST( movl %%ebx, (%%edi) )" - adcl %%edx, %%eax -"DST( movl %%edx, 4(%%edi) )" - -"SRC( movl 8(%%esi), %%ebx )" -"SRC( movl 12(%%esi), %%edx )" - adcl %%ebx, %%eax -"DST( movl %%ebx, 8(%%edi) )" - adcl %%edx, %%eax -"DST( movl %%edx, 12(%%edi) )" - -"SRC( movl 16(%%esi), %%ebx )" -"SRC( movl 20(%%esi), %%edx )" - adcl %%ebx, %%eax -"DST( movl %%ebx, 16(%%edi) )" - adcl %%edx, %%eax -"DST( movl %%edx, 20(%%edi) )" - -"SRC( movl 24(%%esi), %%ebx )" -"SRC( movl 28(%%esi), %%edx )" - adcl %%ebx, %%eax -"DST( movl %%ebx, 24(%%edi) )" - adcl %%edx, %%eax -"DST( movl %%edx, 28(%%edi) )" - -"SRC( lea 32(%%esi), %%esi )" -"DST( lea 32(%%edi), %%edi )" - dec %%ecx - jne 1b - adcl $0, %%eax - 2: popl %%edx - movl %%edx, %%ecx - andl $0x1c, %%edx - je 4f - shrl $2, %%edx # This clears CF -"SRC( 3: movl (%%esi), %%ebx )" - adcl %%ebx, %%eax -"DST( movl %%ebx, (%%edi) )" -"SRC( lea 4(%%esi), %%esi )" -"DST( lea 4(%%edi), %%edi )" - dec %%edx - jne 3b - adcl $0, %%eax - 4: andl $3, %%ecx - jz 7f - cmpl $2, %%ecx - jb 5f -"SRC( movw (%%esi), %%cx )" -"SRC( leal 2(%%esi), %%esi )" -"DST( movw %%cx, (%%edi) )" -"DST( leal 2(%%edi), %%edi )" - je 6f - shll $16,%%ecx -"SRC( 5: movb (%%esi), %%cl )" -"DST( movb %%cl, (%%edi) )" - 6: addl %%ecx, %%eax - adcl $0, %%eax - 7: - -end_of_body: - -# Exception handler: -################################################ - # -.section .fixup, \"a\" # - # -common_fixup: # - # - movl %7, (%%ebx) # - # -# FIXME: do zeroing of rest of the buffer here. # - # - jmp end_of_body # - # -src_access_fault: # - movl %1, %%ebx # - jmp common_fixup # - # -dst_access_fault: # - movl %2, %%ebx # - jmp common_fixup # - # -.previous # - # -################################################ - -" - : "=a" (sum), "=m" (src_err_ptr), "=m" (dst_err_ptr) - : "0" (sum), "c" (len), "S" (src), "D" (dst), - "i" (-EFAULT) - : "bx", "cx", "dx", "si", "di" ); - - return(sum); -} - -#undef SRC -#undef DST /* * FIXME: old compatibility stuff, will be removed soon. @@ -250,12 +112,14 @@ unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum) { int src_err=0, dst_err=0; - sum = csum_partial_copy_generic ( src, dst, len, sum, &src_err, &dst_err); + if (!access_ok(VERIFY_READ, src, len)) + src = NULL; + + sum = __csum_partial_copy_i386_generic ( src, dst, len, sum, &src_err, &dst_err); if (src_err || dst_err) - printk("old csum_partial_copy_fromuser(), tell mingo to convert me.\n"); + printk("old csum_partial_copy() exception, tell mingo to convert me.\n"); return sum; } - diff --git a/arch/i386/lib/checksumcopy.S b/arch/i386/lib/checksumcopy.S new file mode 100644 index 000000000000..21fc91c2ccf0 --- /dev/null +++ b/arch/i386/lib/checksumcopy.S @@ -0,0 +1,259 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * IP/TCP/UDP checksumming routines + * + * Authors: Jorge Cwik, + * Arnt Gulbrandsen, + * Tom May, + * Lots of code moved from tcp.c and ip.c; see those files + * for more names. + * + * Changes: Ingo Molnar, converted to 2.1 exception handling + * Istvan Marosi, fixed lots of bugs in the converted + * assembly code. + * + * This program 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. + */ + +#include +#include +#include +#define ASSEMBLY +#include +#include + +/* + * Copy from ds while checksumming, otherwise like csum_partial + * + * ok, from now on better close your eyes. This file is a top canditate for + * the 'ugliest place in LinuxLand' award. + * + * The macros SRC_* and DST_* specify the type of access for the instruction. + * thus we can call a custom exception handler for all access types. + * + * Damn damn damn. We mess up the stack frame thus we have to have exception + * handlers for all these cases: + * + * 1) source fault + clean stack + * 2) source fault + 32 bits pushed to the stack + * 3) destination fault + clean stack + * 4) destination fault + 32 bits pushed to stack + * + * {the _S postfix below means 'clean up the stack'} + */ + +#define SRC(x...) \ + 9999: x; \ + .section __ex_table, "a"; \ + .long 9999b, src_access_fault; \ + .previous + +#define SRC_S(x...) \ + 9999: x; \ + .section __ex_table, "a"; \ + .long 9999b, src_access_fault_stack; \ + .previous + +#define DST(x...) \ + 9999: x; \ + .section __ex_table, "a"; \ + .long 9999b, dst_access_fault; \ + .previous + +#define DST_S(x...) \ + 9999: x; \ + .section __ex_table, "a"; \ + .long 9999b, dst_access_fault_stack; \ + .previous + +ENTRY(__csum_partial_copy_i386_generic) + +# As we are a .S, we have to get all parameters from the stack ourselves :( +# +# stack layout after register saving (dont break it ..): +# +# char *src --------------> 0x14(%esp) +# char *dst --------------> 0x18(%esp) +# int len ----------------> 0x1c(%esp) +# int sum ----------------> 0x20(%esp) +# int *src_err_ptr -------> 0x24(%esp) +# int *dst_err_ptr -------> 0x28(%esp) + + pushl %edi + pushl %esi + pushl %ebx + pushl %ecx + + movl 0x14(%esp), %esi + movl 0x18(%esp), %edi + movl 0x1c(%esp), %ecx + movl 0x20(%esp), %eax + + testl $2, %edi # Check alignment. + jz 2f # Jump if alignment is ok. + subl $2, %ecx # Alignment uses up two bytes. + jae 1f # Jump if we had at least two bytes. + addl $2, %ecx # ecx was < 2. Deal with it. + jmp 4f +SRC( 1: movw (%esi), %bx ) + addl $2, %esi +DST( movw %bx, (%edi) ) + addl $2, %edi + addw %bx, %ax + adcl $0, %eax + 2: + pushl %ecx + +# from here on we have 32 bits on the stack. + + shrl $5, %ecx + jz 2f + testl %esi, %esi +SRC_S( 1: movl (%esi), %ebx ) +SRC_S( movl 4(%esi), %edx ) + adcl %ebx, %eax +DST_S( movl %ebx, (%edi) ) + adcl %edx, %eax +DST_S( movl %edx, 4(%edi) ) + +SRC_S( movl 8(%esi), %ebx ) +SRC_S( movl 12(%esi), %edx ) + adcl %ebx, %eax +DST_S( movl %ebx, 8(%edi) ) + adcl %edx, %eax +DST_S( movl %edx, 12(%edi) ) + +SRC_S( movl 16(%esi), %ebx ) +SRC_S( movl 20(%esi), %edx ) + adcl %ebx, %eax +DST_S( movl %ebx, 16(%edi) ) + adcl %edx, %eax +DST_S( movl %edx, 20(%edi) ) + +SRC_S( movl 24(%esi), %ebx ) +SRC_S( movl 28(%esi), %edx ) + adcl %ebx, %eax +DST_S( movl %ebx, 24(%edi) ) + adcl %edx, %eax +DST_S( movl %edx, 28(%edi) ) + +# lea cannot fault, it's just pointer preparation: + + lea 32(%esi), %esi + lea 32(%edi), %edi + dec %ecx + jne 1b + adcl $0, %eax + 2: popl %edx + +# from here on we have a clean stack again + + movl %edx, %ecx + andl $0x1c, %edx + je 4f + shrl $2, %edx # This clears CF + +SRC( 3: movl (%esi), %ebx ) + lea 4(%esi), %esi + adcl %ebx, %eax +DST( movl %ebx, (%edi) ) + lea 4(%edi), %edi + dec %edx + jne 3b + + adcl $0, %eax + 4: andl $3, %ecx + jz 7f + cmpl $2, %ecx + jb 5f +SRC( movw (%esi), %cx ) +SRC( leal 2(%esi), %esi ) +DST( movw %cx, (%edi) ) +DST( leal 2(%edi), %edi ) + je 6f + shll $16,%ecx +SRC( 5: movb (%esi), %cl ) +DST( movb %cl, (%edi) ) + 6: addl %ecx, %eax + adcl $0, %eax + 7: + +end_of_body: + popl %ecx + popl %ebx + popl %esi + popl %edi + + ret + +# Exception handlers: +################################################ + +.section .fixup, "a" + +common_src_fixup: + +# the _from_user() stuff has to zero out the kernel buffer, to prevent +# sending out random kernel data. + +# This inefficient but safe. We do not care too much about exception handler +# efficiency, they are totally dead code usually. + +# We cannot use %ecx easily, as it could contain 'real length', or +# 'real length/32'. So we simply reload %ecx from our parameter block +# and zero the whole buffer. This means we set sum = input sum too. + +# We assume that writing into %edi is safe. So if we are ever so crazy to +# do some kind of user_to_user checksum with copying, be prepared to fix +# this ... + + movl 0x24(%esp), %ebx + movl $(-EFAULT), %eax + movl %eax, (%ebx) + + movl 0x18(%esp), %edi + movl 0x1c(%esp), %ecx + + xorl %eax,%eax + cld + rep + stosb + + movl 0x20(%esp), %eax + + jmp end_of_body + +src_access_fault: + jmp common_src_fixup + +src_access_fault_stack: + popl %ebx # <--- clean up the stack + jmp common_src_fixup + +# Currently we do not copy and checksum towards user space, +# but the code is ready anyways ... + + +common_dst_fixup: + movl 0x28(%esp), %ebx + movl $(-EFAULT), (%ebx) + movl 0x20(%esp), %eax + + jmp end_of_body + +dst_access_fault: + jmp common_dst_fixup + +dst_access_fault_stack: + popl %ebx # <--- clean up the stack + jmp common_dst_fixup + +.previous + + diff --git a/arch/i386/lib/locks.S b/arch/i386/lib/locks.S index b9d8b0a9c86e..a927a0c7ee5f 100644 --- a/arch/i386/lib/locks.S +++ b/arch/i386/lib/locks.S @@ -10,7 +10,6 @@ * %eax contains callers PC and %edx holds this cpu ID. */ ENTRY(__lock_kernel) - pushl %eax ! return address 1: lock btsl $0, SYMBOL_NAME(kernel_flag) @@ -21,8 +20,10 @@ ENTRY(__lock_kernel) lock btrl %dl, SYMBOL_NAME(smp_invalidate_needed) jnc 0f + pushl %eax movl %cr3, %eax movl %eax, %cr3 + popl %eax 0: btl $0, SYMBOL_NAME(kernel_flag) jc 2b diff --git a/arch/i386/vmlinux.lds b/arch/i386/vmlinux.lds index 6d11950131dd..7a1fd3d08b0f 100644 --- a/arch/i386/vmlinux.lds +++ b/arch/i386/vmlinux.lds @@ -13,6 +13,7 @@ SECTIONS *(.fixup) *(.gnu.warning) } = 0x9090 + .text.lock : { *(.text.lock) } /* out-of-line lock text */ .rodata : { *(.rodata) } .kstrtab : { *(.kstrtab) } diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index 939a80387cb2..a40e39e5ff10 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -24,17 +24,7 @@ ifneq ($(COMPILE_ARCH),$(ARCH)) CROSS_COMPILE = m68k-linux- endif -# -# Set these to indicate how to link it.. -# -# -zmagic: -# -# LINKFLAGS = -Ttext 0x100000 -# -# -qmagic (we need to remove the 32 byte header for bootup purposes) -# - -LINKFLAGS = -Ttext 0x1000 +LINKFLAGS = -T $(TOPDIR)/arch/m68k/vmlinux.lds CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce diff --git a/arch/m68k/amiga/amifb.c b/arch/m68k/amiga/amifb.c index c97609611eff..eb72970d7e5b 100644 --- a/arch/m68k/amiga/amifb.c +++ b/arch/m68k/amiga/amifb.c @@ -50,12 +50,14 @@ #include #include #include +#include +#include + #include #include #include #include #include -#include #define DEBUG @@ -1802,7 +1804,7 @@ static int amiga_fb_set_cursorstate(struct fb_cursorstate *state, int con) * Initialisation */ -struct fb_info *amiga_fb_init(long *mem_start) +__initfunc(struct fb_info *amiga_fb_init(long *mem_start)) { int err, tag, i; u_long chipptr; diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index b527a8c6c467..9df5083c1b95 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -68,7 +69,7 @@ static void ami_badint(int irq, void *dev_id, struct pt_regs *fp) * the amiga IRQ handling routines. */ -void amiga_init_IRQ(void) +__initfunc(void amiga_init_IRQ(void)) { int i; diff --git a/arch/m68k/amiga/amikeyb.c b/arch/m68k/amiga/amikeyb.c index f2e826023eb3..1058270dd019 100644 --- a/arch/m68k/amiga/amikeyb.c +++ b/arch/m68k/amiga/amikeyb.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -295,7 +296,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp) } } -int amiga_keyb_init(void) +__initfunc(int amiga_keyb_init(void)) { if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) return -EIO; diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c index b2b2e30558ee..d5656d17051d 100644 --- a/arch/m68k/amiga/amisound.c +++ b/arch/m68k/amiga/amisound.c @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -39,7 +40,7 @@ u_short amiga_audio_period = MAX_PERIOD; static u_long clock_constant; -static void init_sound(void) +__initfunc(static void init_sound(void)) { snd_data = amiga_chip_alloc(sizeof(sine_data)); if (!snd_data) { @@ -84,7 +85,7 @@ void amiga_mksound( unsigned int hz, unsigned int ticks ) custom.aud[2].audlc = snd_data; custom.aud[2].audlen = sizeof(sine_data)/2; custom.aud[2].audper = (u_short)period; - custom.aud[2].audvol = 64; /* maxvol */ + custom.aud[2].audvol = 32; /* 50% of maxvol */ if (ticks) { sound_timer.expires = jiffies + ticks; diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c index 237662c939ef..50d5a0de0be0 100644 --- a/arch/m68k/amiga/chipram.c +++ b/arch/m68k/amiga/chipram.c @@ -8,6 +8,7 @@ #include #include +#include #include struct chip_desc { @@ -21,19 +22,18 @@ struct chip_desc { #define DP(ptr) ((struct chip_desc *)(ptr)) u_long amiga_chip_size; -static unsigned long chipavail; /*MILAN*/ +static unsigned long chipavail; -/*MILAN*/ unsigned long amiga_chip_avail( void ) { #ifdef DEBUG - printk("chip_avail : %ld bytes\n",chipavail); + printk("chip_avail : %ld bytes\n",chipavail); #endif - return chipavail; + return chipavail; } -void amiga_chip_init (void) +__initfunc(void amiga_chip_init (void)) { struct chip_desc *dp; diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index 02b1ad564250..408dcbf5ac8e 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -152,7 +153,7 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp) amiga_do_irq_list(base->server_irq, fp, &base->server); } -void cia_init_IRQ(struct ciabase *base) +__initfunc(void cia_init_IRQ(struct ciabase *base)) { int i; diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index 8e6ae531cf5e..08396a5bce29 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -148,7 +149,7 @@ int amiga_parse_bootinfo(const struct bi_record *record) * Setup the Amiga configuration info */ -void config_amiga(void) +__initfunc(void config_amiga(void)) { /* Fill in some default values, if necessary */ if (amiga_eclock == 0) @@ -376,8 +377,8 @@ void config_amiga(void) static unsigned short jiffy_ticks; -static void amiga_sched_init(void (*timer_routine)(int, void *, - struct pt_regs *)) +__initfunc(static void amiga_sched_init(void (*timer_routine)(int, void *, + struct pt_regs *))) { jiffy_ticks = (amiga_eclock+HZ/2)/HZ; @@ -796,7 +797,7 @@ void amiga_serial_gets(char *s, int len) } #endif -static void amiga_debug_init(void) +__initfunc(static void amiga_debug_init(void)) { if (!strcmp( m68k_debug_device, "ser" )) { /* no initialization required (?) */ diff --git a/arch/m68k/amiga/cyberfb.c b/arch/m68k/amiga/cyberfb.c index d74d52c4f1e6..31e2a460858a 100644 --- a/arch/m68k/amiga/cyberfb.c +++ b/arch/m68k/amiga/cyberfb.c @@ -29,12 +29,13 @@ #include #include #include +#include +#include +#include #include #include #include -#include #include -#include #include "s3blit.h" @@ -1157,7 +1158,7 @@ void Cyber_video_setup(char *options, int *ints) * Initialization */ -struct fb_info *Cyber_fb_init(long *mem_start) +__initfunc(struct fb_info *Cyber_fb_init(long *mem_start)) { int err; struct Cyber_fb_par par; diff --git a/arch/m68k/amiga/retz3fb.c b/arch/m68k/amiga/retz3fb.c index 04157a2f6d74..a98c2b3c5725 100644 --- a/arch/m68k/amiga/retz3fb.c +++ b/arch/m68k/amiga/retz3fb.c @@ -30,10 +30,11 @@ #include #include #include +#include +#include #include #include #include -#include #include #include "retz3fb.h" @@ -1650,7 +1651,7 @@ void retz3_video_setup(char *options, int *ints) * Initialization */ -struct fb_info *retz3_fb_init(long *mem_start) +__initfunc(struct fb_info *retz3_fb_init(long *mem_start)) { int err; struct retz3_fb_par par; diff --git a/arch/m68k/amiga/zorro.c b/arch/m68k/amiga/zorro.c index acca3e6bc332..d64ad8ce39b0 100644 --- a/arch/m68k/amiga/zorro.c +++ b/arch/m68k/amiga/zorro.c @@ -13,10 +13,11 @@ #include #include #include +#include +#include #include #include #include -#include #ifdef CONFIG_ZORRO @@ -415,10 +416,6 @@ BEGIN_PROD(MASOBOSHI) PROD("MVD 819", MVD_819) END -BEGIN_PROD(DELACOMP) - PROD("RAM Expansion 2000", DELACOMP_RAM_2000) -END - BEGIN_PROD(VILLAGE_TRONIC) PROD("Domino Graphics Board (RAM)", DOMINO_RAM) PROD("Domino Graphics Board (REG)", DOMINO_REG) @@ -656,7 +653,6 @@ BEGIN_MANUF MANUF("Helfrich", HELFRICH1) MANUF("Software Result Enterprises", SW_RESULT_ENTS) MANUF("Masoboshi", MASOBOSHI) - MANUF("DelaComp", DELACOMP) MANUF("Village Tronic", VILLAGE_TRONIC) MANUF("Utilities Unlimited", UTILITIES_ULTD) MANUF("Amitrix", AMITRIX) @@ -992,7 +988,7 @@ static void mark_region(u_long addr, u_long size, int flag) * Initialization */ -void zorro_init(void) +__initfunc(void zorro_init(void)) { int i; struct ConfigDev *cd; diff --git a/arch/m68k/atari/atafb.c b/arch/m68k/atari/atafb.c index 64c9a62d3eca..efa6fc8b838b 100644 --- a/arch/m68k/atari/atafb.c +++ b/arch/m68k/atari/atafb.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -2911,8 +2912,8 @@ atafb_setcmap(struct fb_cmap *cmap, int con) return(atari_fb_set_cmap(cmap, 1, con)); } -struct fb_info * -atari_fb_init(long *mem_start) +__initfunc(struct fb_info * +atari_fb_init(long *mem_start)) { int err; int pad; diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index b65beefb1415..6944d1c54362 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -331,7 +332,7 @@ extern void atari_microwire_cmd( int cmd ); * the atari IRQ handling routines. */ -void atari_init_IRQ(void) +__initfunc(void atari_init_IRQ(void)) { int i; diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index 4f57cb928c10..beccf9a84b01 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -804,7 +805,7 @@ void atari_kbd_leds (unsigned int leds) * Martin Rogge, 20 Aug 1995 */ -int atari_keyb_init(void) +__initfunc(int atari_keyb_init(void)) { /* setup key map */ key_maps[0] = ataplain_map; diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c index 0d0607da05ce..3cc2a840a891 100644 --- a/arch/m68k/atari/config.c +++ b/arch/m68k/atari/config.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -106,7 +107,7 @@ extern void (*kd_mksound)(unsigned int, unsigned int); * a temporary VBR and a vector table for the duration of the test. */ -static int hwreg_present( volatile void *regp ) +__initfunc(static int hwreg_present( volatile void *regp )) { int ret = 0; long save_sp, save_vbr; @@ -132,9 +133,8 @@ static int hwreg_present( volatile void *regp ) } #if 0 -static int hwreg_present_bywrite( volatile void *regp, - unsigned char val ) - +__initfunc(static int +hwreg_present_bywrite(volatile void *regp, unsigned char val)) { int ret; long save_sp, save_vbr; @@ -166,7 +166,7 @@ static int hwreg_present_bywrite( volatile void *regp, /* Basically the same, but writes a value into a word register, protected * by a bus error handler */ -static int hwreg_write( volatile void *regp, unsigned short val ) +__initfunc(static int hwreg_write( volatile void *regp, unsigned short val )) { int ret; long save_sp, save_vbr; @@ -201,7 +201,7 @@ static int hwreg_write( volatile void *regp, unsigned short val ) * should be readable without trouble (from channel A!). */ -static int scc_test( volatile char *ctla ) +__initfunc(static int scc_test( volatile char *ctla )) { if (!hwreg_present( ctla )) return( 0 ); @@ -228,7 +228,7 @@ static int scc_test( volatile char *ctla ) * Parse an Atari-specific record in the bootinfo */ -int atari_parse_bootinfo(const struct bi_record *record) +__initfunc(int atari_parse_bootinfo(const struct bi_record *record)) { int unknown = 0; const u_long *data = record->data; @@ -247,7 +247,7 @@ int atari_parse_bootinfo(const struct bi_record *record) * Setup the Atari configuration info */ -void config_atari(void) +__initfunc(void config_atari(void)) { memset(&atari_hw_present, 0, sizeof(atari_hw_present)); @@ -493,7 +493,8 @@ void config_atari(void) } } -static void atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) +__initfunc(static void +atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))) { /* set Timer C data Register */ mfp.tim_dt_c = INT_TICKS; @@ -976,7 +977,7 @@ static void atari_par_console_write (const char *str, unsigned int count) } -static void atari_debug_init(void) +__initfunc(static void atari_debug_init(void)) { #ifdef CONFIG_KGDB /* if the m68k_debug_device is used by the GDB stub, do nothing here */ diff --git a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c index de6014171906..2e33b151fd34 100644 --- a/arch/m68k/atari/joystick.c +++ b/arch/m68k/atari/joystick.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -128,7 +129,7 @@ struct file_operations atari_joystick_fops = { release_joystick }; -int atari_joystick_init(void) +__initfunc(int atari_joystick_init(void)) { joystick[0].active = joystick[1].active = 0; joystick[0].ready = joystick[1].ready = 0; diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c index 247b9f684de3..9dc82de18640 100644 --- a/arch/m68k/atari/stdma.c +++ b/arch/m68k/atari/stdma.c @@ -32,6 +32,8 @@ #include #include #include +#include + #include #include #include @@ -171,7 +173,7 @@ int stdma_islocked(void) * */ -void stdma_init(void) +__initfunc(void stdma_init(void)) { stdma_isr = NULL; request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW, diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c index 565b205355a2..4e5f57bc9ebc 100644 --- a/arch/m68k/atari/stram.c +++ b/arch/m68k/atari/stram.c @@ -149,6 +149,7 @@ atari_stram_free (void *ptr) #else #include +#include /* ++roman: * @@ -190,7 +191,7 @@ static unsigned long stram_end; /* Overall end of ST-Ram */ -void atari_stram_init( void ) +__initfunc(void atari_stram_init( void )) { int i; diff --git a/arch/m68k/boot/amiga/linuxboot.c b/arch/m68k/boot/amiga/linuxboot.c index d35966686fbd..23b7fa9d0a98 100644 --- a/arch/m68k/boot/amiga/linuxboot.c +++ b/arch/m68k/boot/amiga/linuxboot.c @@ -22,6 +22,8 @@ * for more details. * * History: + * 27 Mar 1997 FPU-less machines couldn't boot kernels that use bootinfo + * interface version 1.0 (Geert) * 03 Feb 1997 Implemented kernel decompression (Geert, based on Roman's * code for ataboot) * 30 Dec 1996 Reverted the CPU detection to the old scheme @@ -791,6 +793,7 @@ static u_long get_chipset(void) static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu) { *cpu = *fpu = 0; + if (SysBase->AttnFlags & AFF_68060) *cpu = CPU_68060; else if (SysBase->AttnFlags & AFF_68040) @@ -799,15 +802,15 @@ static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu) *cpu = CPU_68030; else if (SysBase->AttnFlags & AFF_68020) *cpu = CPU_68020; + if (*cpu == CPU_68040 || *cpu == CPU_68060) { if (SysBase->AttnFlags & AFF_FPU40) *fpu = *cpu; - } else { - if (SysBase->AttnFlags & AFF_68882) - *fpu = FPU_68882; - else if (SysBase->AttnFlags & AFF_68881) - *fpu = FPU_68881; - } + } else if (SysBase->AttnFlags & AFF_68882) + *fpu = FPU_68882; + else if (SysBase->AttnFlags & AFF_68881) + *fpu = FPU_68881; + *mmu = *cpu; } @@ -1047,7 +1050,7 @@ static int create_compat_bootinfo(void) compat_bootinfo.cputype |= COMPAT_FPU_68040; else if (bi.fputype & FPU_68060) compat_bootinfo.cputype |= COMPAT_FPU_68060; - else { + else if (bi.fputype) { Printf("FPU type 0x%08lx not supported by kernel\n", bi.fputype); return(0); } diff --git a/arch/m68k/boot/amiga/linuxboot.h b/arch/m68k/boot/amiga/linuxboot.h index 8ebfe63b4453..e04425a3ad76 100644 --- a/arch/m68k/boot/amiga/linuxboot.h +++ b/arch/m68k/boot/amiga/linuxboot.h @@ -31,7 +31,7 @@ * Amiboot Version */ -#define AMIBOOT_VERSION "5.4" +#define AMIBOOT_VERSION "5.5" /* diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index f49c38cd3844..39e1fbce62f7 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -79,7 +80,7 @@ void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq; * the IRQ handling routines. */ -void init_IRQ(void) +__initfunc(void init_IRQ(void)) { int i; diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 3138d99df53f..f6bb0689b826 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include @@ -14,6 +16,7 @@ #include #include #include +#include asmlinkage long long __ashrdi3 (long long, int); extern char m68k_debug_device[]; @@ -40,6 +43,7 @@ EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(local_irq_count); +EXPORT_SYMBOL(__m68k_bh_counter); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 53a3e56d4525..b2f92641a455 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -10,6 +10,7 @@ * This file handles the architecture-dependent parts of process handling.. */ +#include #include #include #include @@ -62,8 +63,16 @@ asmlinkage int sys_idle(void) /* endless idle loop with no priority at all */ current->priority = -100; current->counter = -100; - for (;;) + for (;;){ + if (!need_resched) +#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) + /* block out HSYNC on the atari (falcon) */ + __asm__("stop #0x2200" : : : "cc"); +#else /* portable version */ + __asm__("stop #0x2000" : : : "cc"); +#endif /* machine compilation types */ schedule(); + } ret = 0; out: unlock_kernel(); diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index dfd91d0d42a8..def50a747dcb 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -55,13 +56,13 @@ static struct mem_info m68k_ramdisk = { 0, 0 }; static char m68k_command_line[CL_SIZE]; char saved_command_line[CL_SIZE]; -void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)); +void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata; /* machine dependent keyboard functions */ -int (*mach_keyb_init) (void); +int (*mach_keyb_init) (void) __initdata; int (*mach_kbdrate) (struct kbd_repeat *) = NULL; void (*mach_kbd_leds) (unsigned int) = NULL; /* machine dependent irq functions */ -void (*mach_init_IRQ) (void); +void (*mach_init_IRQ) (void) __initdata; void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL; void (*mach_get_model) (char *model) = NULL; int (*mach_get_hardware_list) (char *buffer) = NULL; @@ -73,12 +74,12 @@ void (*mach_gettod) (int*, int*, int*, int*, int*, int*); int (*mach_hwclk) (int, struct hwclk_time*) = NULL; int (*mach_set_clock_mmss) (unsigned long) = NULL; void (*mach_reset)( void ); -struct fb_info *(*mach_fb_init)(long *); +struct fb_info *(*mach_fb_init)(long *) __initdata; long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ -void (*mach_video_setup) (char *, int *); +void (*mach_video_setup) (char *, int *) __initdata; #ifdef CONFIG_BLK_DEV_FD -int (*mach_floppy_init) (void) = NULL; -void (*mach_floppy_setup) (char *, int *) = NULL; +int (*mach_floppy_init) (void) __initdata = NULL; +void (*mach_floppy_setup) (char *, int *) __initdata = NULL; void (*mach_floppy_eject) (void) = NULL; #endif @@ -94,7 +95,7 @@ extern void config_apollo(void); #define MASK_256K 0xfffc0000 -static void m68k_parse_bootinfo(const struct bi_record *record) +__initfunc(static void m68k_parse_bootinfo(const struct bi_record *record)) { while (record->tag != BI_LAST) { int unknown = 0; @@ -141,8 +142,8 @@ static void m68k_parse_bootinfo(const struct bi_record *record) } } -void setup_arch(char **cmdline_p, unsigned long * memory_start_p, - unsigned long * memory_end_p) + __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, + unsigned long * memory_end_p)) { unsigned long memory_start, memory_end; extern int _etext, _edata, _end; @@ -337,7 +338,7 @@ int get_hardware_list(char *buffer) } #ifdef CONFIG_BLK_DEV_FD -int floppy_init(void) +__initfunc(int floppy_init(void)) { if (mach_floppy_init) return mach_floppy_init(); @@ -345,7 +346,7 @@ int floppy_init(void) return 0; } -void floppy_setup(char *str, int *ints) +__initfunc(void floppy_setup(char *str, int *ints)) { if (mach_floppy_setup) mach_floppy_setup (str, ints); @@ -358,7 +359,7 @@ void floppy_eject(void) } #endif -unsigned long arch_kbd_init(void) +__initfunc(unsigned long arch_kbd_init(void)) { return mach_keyb_init(); } @@ -372,7 +373,7 @@ void arch_gettod(int *year, int *mon, int *day, int *hour, *year = *mon = *day = *hour = *min = *sec = 0; } -void video_setup (char *options, int *ints) +__initfunc(void video_setup (char *options, int *ints)) { if (mach_video_setup) mach_video_setup (options, ints); diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index c60e82b0b5c7..52c13445df26 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -42,7 +42,9 @@ #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) -asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); +asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, + int options, unsigned long *ru); + asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs); const int frame_extra_sizes[16] = { @@ -466,7 +468,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs) if (signr != SIGCHLD) continue; /* check for SIGCHLD: it's special */ - while (sys_waitpid(-1,NULL,WNOHANG) > 0) + while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) /* nothing */; continue; } diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index dbff49276287..7b3acdfa607a 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -27,6 +27,24 @@ static inline int set_rtc_mmss(unsigned long nowtime) return -1; } +static inline void do_profile (unsigned long pc) +{ + if (prof_buffer && current->pid) { + extern int _stext; + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + if (pc < prof_len) + ++prof_buffer[pc]; + else + /* + * Dont ignore out-of-bounds PC values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + ++prof_buffer[prof_len-1]; + } +} + /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -38,6 +56,9 @@ static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs) do_timer(regs); + if (!user_mode(regs)) + do_profile(regs->pc); + /* * If we have an externally synchronized Linux clock, then update * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index 1cc547907be8..024544cedcf8 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -63,7 +64,7 @@ asm(".text\n" __ALIGN_STR "\n" SYMBOL_NAME_STR(nmihandler) ": rte"); -void trap_init (void) +__initfunc(void trap_init (void)) { int i; diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c index 01cd315ddf1f..4b4da34cf4b0 100644 --- a/arch/m68k/mm/init.c +++ b/arch/m68k/mm/init.c @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef CONFIG_BLK_DEV_RAM #include #endif @@ -116,9 +117,8 @@ pte_t *kernel_page_table (unsigned long *memavailp) return ptablep; } -static unsigned long map_chunk (unsigned long addr, - unsigned long size, - unsigned long *memavailp) +__initfunc(static unsigned long +map_chunk (unsigned long addr, unsigned long size, unsigned long *memavailp)) { #define ONEMEG (1024*1024) #define L3TREESIZE (256*1024) @@ -283,6 +283,11 @@ static unsigned long map_chunk (unsigned long addr, extern unsigned long free_area_init(unsigned long, unsigned long); +/* References to section boundaries */ + +extern char _text, _etext, _edata, __bss_start, _end; +extern char __init_begin, __init_end; + extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* @@ -291,7 +296,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; * The parameters are pointers to where to stick the starting and ending * addresses of available kernel virtual memory. */ -unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) +__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)) { int chunk; unsigned long mem_avail = 0; @@ -395,12 +400,12 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) return PAGE_ALIGN(free_area_init (start_mem, end_mem)); } -void mem_init(unsigned long start_mem, unsigned long end_mem) +__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) { int codepages = 0; int datapages = 0; + int initpages = 0; unsigned long tmp; - extern int _etext; end_mem &= PAGE_MASK; high_memory = (void *) end_mem; @@ -448,8 +453,15 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) if (VTOP (tmp) >= mach_max_dma_address) clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags); if (PageReserved(mem_map+MAP_NR(tmp))) { - if (tmp < (unsigned long)&_etext) - codepages++; + if (tmp >= (unsigned long)&_text + && tmp < (unsigned long)&_edata) { + if (tmp < (unsigned long) &_etext) + codepages++; + else + datapages++; + } else if (tmp >= (unsigned long) &__init_begin + && tmp < (unsigned long) &__init_end) + initpages++; else datapages++; continue; @@ -461,16 +473,26 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) #endif free_page(tmp); } - printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n", + printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n", (unsigned long) nr_free_pages << (PAGE_SHIFT-10), max_mapnr << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), - datapages << (PAGE_SHIFT-10)); + datapages << (PAGE_SHIFT-10), + initpages << (PAGE_SHIFT-10)); } void free_initmem(void) { - /* To be written */ + unsigned long addr; + + addr = (unsigned long)&__init_begin; + for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) { + mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); + atomic_set(&mem_map[MAP_NR(addr)].count, 1); + free_page(addr); + } + printk ("Freeing unused kernel memory: %dk freed\n", + (&__init_end - &__init_begin) >> 10); } void si_meminfo(struct sysinfo *val) diff --git a/arch/m68k/vmlinux.lds b/arch/m68k/vmlinux.lds new file mode 100644 index 000000000000..8aa663796092 --- /dev/null +++ b/arch/m68k/vmlinux.lds @@ -0,0 +1,56 @@ +/* ld script to make m68k Linux kernel */ +OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k") +OUTPUT_ARCH(m68k) +ENTRY(_start) +SECTIONS +{ + . = 0x1000; + _text = .; /* Text and read-only data */ + .text : { + *(.text) + *(.fixup) + *(.gnu.warning) + } = 0x4e75 + .rodata : { *(.rodata) } + .kstrtab : { *(.kstrtab) } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + + _etext = .; /* End of text section */ + + .data : { /* Data */ + *(.data) + CONSTRUCTORS + } + + _edata = .; /* End of data section */ + + . = ALIGN(4096); /* Init code and data */ + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; /* BSS */ + .bss : { + *(.bss) + } + _end = . ; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index 587cfc616147..92c73de3248c 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.27 1997/04/07 06:54:08 davem Exp $ +# $Id: Makefile,v 1.28 1997/05/01 01:41:21 davem Exp $ # sparc/Makefile # # Makefile for the architecture dependent flags and dependencies on the @@ -21,7 +21,7 @@ CFLAGS := $(CFLAGS) -pipe -fcall-used-g5 -fcall-used-g7 #LINKFLAGS = -N -Ttext 0xf0004000 LINKFLAGS = -T arch/sparc/vmlinux.lds -HEAD := arch/sparc/kernel/head.o +HEAD := arch/sparc/kernel/head.o arch/sparc/kernel/init_task.o SUBDIRS := $(SUBDIRS) arch/sparc/kernel arch/sparc/lib arch/sparc/mm \ arch/sparc/prom diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index f73a52fb3d14..d3307e4632cd 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.39 1997/04/01 02:21:44 davem Exp $ +# $Id: Makefile,v 1.40 1997/05/01 01:40:36 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -28,7 +28,7 @@ else CHECKASM_CC = $(CC) endif -all: kernel.o head.o +all: kernel.o head.o init_task.o O_TARGET := kernel.o IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o diff --git a/arch/sparc/kernel/etrap.S b/arch/sparc/kernel/etrap.S index b930949192c1..fc6c4ceadeed 100644 --- a/arch/sparc/kernel/etrap.S +++ b/arch/sparc/kernel/etrap.S @@ -1,4 +1,4 @@ -/* $Id: etrap.S,v 1.23 1997/03/04 16:26:25 jj Exp $ +/* $Id: etrap.S,v 1.26 1997/05/01 08:53:32 davem Exp $ * etrap.S: Sparc trap window preparation for entry into the * Linux kernel. * @@ -129,15 +129,23 @@ tsetup_patch2: trap_setup_from_user: /* We can't use %curptr yet. */ LOAD_CURRENT(t_kstack, t_twinmask) + + mov 1, %t_twinmask + sll %t_twinmask, (PAGE_SHIFT + 1), %t_twinmask + sub %t_twinmask, (TRACEREG_SZ + REGWIN_SZ), %t_twinmask + add %t_kstack, %t_twinmask, %t_kstack + mov 1, %t_twinmask - ld [%t_kstack + AOFF_task_saved_kernel_stack], %t_kstack sll %t_twinmask, %t_psr, %t_twinmask ! t_twinmask = (1 << psr) /* Build pt_regs frame. */ STORE_PT_ALL(t_kstack, t_psr, t_pc, t_npc, g2) /* Clear current->tss.w_saved */ - LOAD_CURRENT(curptr, g1) + mov 1, %curptr + sll %curptr, (PAGE_SHIFT + 1), %curptr + sub %curptr, (TRACEREG_SZ + REGWIN_SZ), %curptr + sub %t_kstack, %curptr, %curptr st %g0, [%curptr + AOFF_task_tss + AOFF_thread_w_saved] /* See if we are in the trap window. */ diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S index eea3528bf236..90965e26eab6 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head.S @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.81 1997/04/16 07:15:48 davem Exp $ +/* $Id: head.S,v 1.82 1997/05/01 01:40:38 davem Exp $ * head.S: The initial boot code for the Sparc port of Linux. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -393,12 +393,6 @@ C_LABEL(trapbase_cpu3): BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) - .globl C_LABEL(cpu0_stack), C_LABEL(cpu1_stack), C_LABEL(cpu2_stack) - .globl C_LABEL(cpu3_stack) -C_LABEL(cpu0_stack): .skip 0x2000 -C_LABEL(cpu1_stack): .skip 0x2000 -C_LABEL(cpu2_stack): .skip 0x2000 -C_LABEL(cpu3_stack): .skip 0x2000 #endif .skip 4096 @@ -742,6 +736,9 @@ go_to_highmem: jmpl %g1, %g0 nop + /* This is to align init_task_union properly, be careful. -DaveM */ + .align 8192 + /* The code above should be at beginning and we have to take care about * short jumps, as branching to .text.init section from .text is usually * impossible */ @@ -986,12 +983,10 @@ sun4c_continue_boot: /* Initialize the umask value for init_task just in case. * But first make current_set[0] point to something useful. */ - set C_LABEL(init_task), %g6 + set C_LABEL(init_task_union), %g6 set C_LABEL(current_set), %g2 st %g6, [%g2] - set C_LABEL(bootup_kernel_stack), %g3 - st %g3, [%g6 + AOFF_task_kernel_stack_page] st %g0, [%g6 + AOFF_task_tss + AOFF_thread_uwinmask] /* Compute NWINDOWS and stash it away. Now uses %wim trick explained diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c new file mode 100644 index 000000000000..d0fc09346eca --- /dev/null +++ b/arch/sparc/kernel/init_task.c @@ -0,0 +1,18 @@ +#include +#include + +#include +#include + +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; +struct mm_struct init_mm = INIT_MM; + +/* .text section in head.S is aligned at 2 page boundry and this gets linked + * right after that so that the init_task_union is aligned properly as well. + * We really don't need this special alignment like the Intel does, but + * I do it anyways for completeness. + */ +union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK }; diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index d23d6e0f1b52..7faf0203f7d6 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.93 1997/04/11 08:55:40 davem Exp $ +/* $Id: process.c,v 1.96 1997/05/01 08:53:33 davem Exp $ * linux/arch/sparc/kernel/process.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -39,22 +39,6 @@ #include #include -/* - * Initial task structure. Make this a per-architecture thing, - * because different architectures tend to have different - * alignment requirements and potentially different initial - * setup. - */ -static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; -unsigned long init_user_stack[1024] = { STACK_MAGIC, }; -static struct vm_area_struct init_mmap = INIT_MMAP; -static struct fs_struct init_fs = INIT_FS; -static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS; - -struct mm_struct init_mm = INIT_MM; -struct task_struct init_task = INIT_TASK; - extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *); #ifndef __SMP__ @@ -457,12 +441,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, if(regs->psr & PSR_PS) stack_offset -= REGWIN_SZ; - childregs = ((struct pt_regs *) (p->kernel_stack_page + stack_offset)); + childregs = ((struct pt_regs *) (((unsigned long)p) + stack_offset)); copy_regs(childregs, regs); new_stack = (((struct reg_window *) childregs) - 1); copy_regwin(new_stack, (((struct reg_window *) regs) - 1)); - p->tss.ksp = p->saved_kernel_stack = (unsigned long) new_stack; + p->tss.ksp = (unsigned long) new_stack; #ifdef __SMP__ p->tss.kpc = (((unsigned long) ret_from_smpfork) - 0x8); p->tss.kpsr = current->tss.fork_kpsr | PSR_PIL; @@ -483,7 +467,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, p->tss.flags &= ~SPARC_FLAG_KTHREAD; p->tss.current_ds = USER_DS; - if (sp != current->tss.kregs->u_regs[UREG_FP]) { + if (sp != regs->u_regs[UREG_FP]) { struct sparc_stackf *childstack; struct sparc_stackf *parentstack; @@ -491,9 +475,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, * This is a clone() call with supplied user stack. * Set some valid stack frames to give to the child. */ - childstack = (struct sparc_stackf *)sp; - parentstack = (struct sparc_stackf *) - current->tss.kregs->u_regs[UREG_FP]; + childstack = (struct sparc_stackf *) sp; + parentstack = (struct sparc_stackf *) regs->u_regs[UREG_FP]; #if 0 printk("clone: parent stack:\n"); diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index 6622f88f0dbf..8398d263030f 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -4,16 +4,18 @@ */ #include -#include -#include #include +#include #include #include #include #include #include +#include +#include + #include #include #include @@ -24,6 +26,9 @@ #include #include +#define __KERNEL_SYSCALLS__ +#include + #define IRQ_RESCHEDULE 13 #define IRQ_STOP_CPU 14 #define IRQ_CROSS_CALL 15 @@ -118,16 +123,6 @@ void smp_store_cpu_info(int id) cpu_data[id].udelay_val = loops_per_sec; /* this is it on sparc. */ } -/* - * Architecture specific routine called by the kernel just before init is - * fired off. This allows the BP to have everything in order [we hope]. - * At the end of this all the AP's will hit the system scheduling and off - * we go. Each AP will load the system gdt's and jump through the kernel - * init into idle(). At this point the scheduler will one day take over - * and give them jobs to do. smp_callin is a standard routine - * we use to track CPU's as they power up. - */ - void smp_commence(void) { /* @@ -144,7 +139,7 @@ static void smp_setup_percpu_timer(void); void smp_callin(void) { - int cpuid = smp_processor_id(); + int cpuid = hard_smp_processor_id(); local_flush_cache_all(); local_flush_tlb_all(); @@ -183,6 +178,25 @@ void smp_callin(void) __sti(); } +extern int cpu_idle(void *unused); +extern void init_IRQ(void); + +/* Only broken Intel needs this, thus it should not even be referenced + * globally... + */ +void initialize_secondary(void) +{ +} + +/* Activate a secondary processor. */ +int start_secondary(void *unused) +{ + trap_init(); + init_IRQ(); + smp_callin(); + return cpu_idle(NULL); +} + void cpu_panic(void) { printk("CPU[%d]: Returns from cpu_idle!\n", smp_processor_id()); @@ -220,6 +234,7 @@ void smp_boot_cpus(void) cpu_number_map[boot_cpu_id] = 0; cpu_logical_map[0] = boot_cpu_id; klock_info.akp = boot_cpu_id; + current->processor = boot_cpu_id; smp_store_cpu_info(boot_cpu_id); set_irq_udt(mid_xlate[boot_cpu_id]); smp_setup_percpu_timer(); @@ -233,10 +248,19 @@ void smp_boot_cpus(void) if(cpu_present_map & (1 << i)) { extern unsigned long sparc_cpu_startup; unsigned long *entry = &sparc_cpu_startup; + struct task_struct *p; int timeout; + /* Cook up an idler for this guy. */ + kernel_thread(start_secondary, NULL, CLONE_PID); + + p = task[++cpucount]; + + p->processor = i; + current_set[i] = p; + /* See trampoline.S for details... */ - entry += ((i-1) * 6); + entry += ((i-1) * 3); /* whirrr, whirrr, whirrrrrrrrr... */ printk("Starting CPU %d at %p\n", i, entry); @@ -253,10 +277,10 @@ void smp_boot_cpus(void) } if(cpu_callin_map[i]) { /* Another "Red Snapper". */ - cpucount++; cpu_number_map[i] = i; cpu_logical_map[i] = i; } else { + cpucount--; printk("Processor %d is stuck.\n", i); } } @@ -376,14 +400,11 @@ static spinlock_t cross_call_lock = SPIN_LOCK_UNLOCKED; void smp_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { - unsigned long me = smp_processor_id(); - unsigned long flags, mask; - int i, timeout; - if(smp_processors_ready) { - __save_flags(flags); - __cli(); - spin_lock(&cross_call_lock); + register int ncpus = smp_num_cpus; + unsigned long flags; + + spin_lock_irqsave(&cross_call_lock, flags); /* Init function glue. */ ccall_info.func = func; @@ -393,56 +414,47 @@ void smp_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, ccall_info.arg4 = arg4; ccall_info.arg5 = arg5; - /* Init receive/complete mapping. */ - for(i = 0; i < smp_num_cpus; i++) { - ccall_info.processors_in[i] = 0; - ccall_info.processors_out[i] = 0; + /* Init receive/complete mapping, plus fire the IPI's off. */ + { + register void (*send_ipi)(int,int) = set_cpu_int; + register unsigned long mask; + register int i; + + mask = (cpu_present_map & ~(1 << smp_processor_id())); + for(i = 0; i < ncpus; i++) { + if(mask & (1 << i)) { + ccall_info.processors_in[i] = 0; + ccall_info.processors_out[i] = 0; + send_ipi(mid_xlate[i], IRQ_CROSS_CALL); + } else { + ccall_info.processors_in[i] = 1; + ccall_info.processors_out[i] = 1; + } + } } - ccall_info.processors_in[me] = 1; - ccall_info.processors_out[me] = 1; - /* Fire it off. */ - mask = (cpu_present_map & ~(1 << me)); - for(i = 0; i < 4; i++) { - if(mask & (1 << i)) - set_cpu_int(mid_xlate[i], IRQ_CROSS_CALL); - } + /* First, run local copy. */ + func(arg1, arg2, arg3, arg4, arg5); - /* For debugging purposes right now we can timeout - * on both callin and callexit. - */ - timeout = CCALL_TIMEOUT; - for(i = 0; i < smp_num_cpus; i++) { - while(!ccall_info.processors_in[i] && timeout-- > 0) - barrier(); - if(!ccall_info.processors_in[i]) - goto procs_time_out; - } + { + register int i; - /* Run local copy. */ - func(arg1, arg2, arg3, arg4, arg5); + i = 0; + do { + while(!ccall_info.processors_in[i]) + barrier(); + } while(++i < ncpus); - /* Spin on proc dispersion. */ - timeout = CCALL_TIMEOUT; - for(i = 0; i < smp_num_cpus; i++) { - while(!ccall_info.processors_out[i] && timeout-- > 0) - barrier(); - if(!ccall_info.processors_out[i]) - goto procs_time_out; + i = 0; + do { + while(!ccall_info.processors_out[i]) + barrier(); + } while(++i < ncpus); } - spin_unlock(&cross_call_lock); - __restore_flags(flags); - return; /* made it... */ - -procs_time_out: - printk("smp: Wheee, penguin drops off the bus\n"); - spin_unlock(&cross_call_lock); - __restore_flags(flags); - return; /* why me... why me... */ - } - /* Just need to run local copy. */ - func(arg1, arg2, arg3, arg4, arg5); + spin_unlock_irqrestore(&cross_call_lock, flags); + } else + func(arg1, arg2, arg3, arg4, arg5); /* Just need to run local copy. */ } void smp_flush_cache_all(void) diff --git a/arch/sparc/kernel/tadpole.c b/arch/sparc/kernel/tadpole.c index bea6336c5a56..03fe3cff9107 100644 --- a/arch/sparc/kernel/tadpole.c +++ b/arch/sparc/kernel/tadpole.c @@ -4,6 +4,8 @@ */ #include +#include +#include #include #include diff --git a/arch/sparc/kernel/trampoline.S b/arch/sparc/kernel/trampoline.S index c59a2531ad39..9ee5bd14a38d 100644 --- a/arch/sparc/kernel/trampoline.S +++ b/arch/sparc/kernel/trampoline.S @@ -1,4 +1,4 @@ -/* $Id: trampoline.S,v 1.6 1997/04/14 05:38:33 davem Exp $ +/* $Id: trampoline.S,v 1.9 1997/05/01 08:53:34 davem Exp $ * trampoline.S: SMP cpu boot-up trampoline code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -25,27 +26,18 @@ C_LABEL(sparc_cpu_startup): cpu1_startup: sethi %hi(C_LABEL(trapbase_cpu1)), %g3 - or %g3, %lo(C_LABEL(trapbase_cpu1)), %g3 - sethi %hi(C_LABEL(cpu1_stack)), %g2 - or %g2, %lo(C_LABEL(cpu1_stack)), %g2 b 1f - nop + or %g3, %lo(C_LABEL(trapbase_cpu1)), %g3 cpu2_startup: sethi %hi(C_LABEL(trapbase_cpu2)), %g3 - or %g3, %lo(C_LABEL(trapbase_cpu2)), %g3 - sethi %hi(C_LABEL(cpu2_stack)), %g2 - or %g2, %lo(C_LABEL(cpu2_stack)), %g2 b 1f - nop + or %g3, %lo(C_LABEL(trapbase_cpu2)), %g3 cpu3_startup: sethi %hi(C_LABEL(trapbase_cpu3)), %g3 - or %g3, %lo(C_LABEL(trapbase_cpu3)), %g3 - sethi %hi(C_LABEL(cpu3_stack)), %g2 - or %g2, %lo(C_LABEL(cpu3_stack)), %g2 b 1f - nop + or %g3, %lo(C_LABEL(trapbase_cpu3)), %g3 1: /* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */ @@ -62,14 +54,16 @@ cpu3_startup: wr %g3, 0x0, %tbr WRITE_PAUSE - /* Give ourselves a stack. */ - set 0x2000, %g5 - add %g2, %g5, %g2 ! end of stack - sub %g2, REGWIN_SZ, %sp - mov 0, %fp + /* Give ourselves a stack and curptr. */ + set C_LABEL(current_set), %g5 + srl %g3, 10, %g4 + and %g4, 0xc, %g4 + ld [%g5 + %g4], %g6 - /* Set up curptr. */ - set C_LABEL(init_task), %g6 + mov 1, %sp + sll %sp, (PAGE_SHIFT + 1), %sp + sub %sp, REGWIN_SZ, %sp + add %g6, %sp, %sp /* Turn on traps (PSR_ET). */ rd %psr, %g1 diff --git a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S index bad0088f48f2..890676bfb1e2 100644 --- a/arch/sparc/kernel/wof.S +++ b/arch/sparc/kernel/wof.S @@ -1,4 +1,4 @@ -/* $Id: wof.S,v 1.33 1997/03/04 16:26:35 jj Exp $ +/* $Id: wof.S,v 1.36 1997/05/01 08:53:35 davem Exp $ * wof.S: Sparc window overflow handler. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -234,15 +234,20 @@ spwin_user_stack_is_bolixed: spnwin_patch3: and %twin_tmp, 0xff, %twin_tmp ! patched on 7win Sparcs st %twin_tmp, [%curptr + AOFF_task_tss + AOFF_thread_uwinmask] - /* Jump onto kernel stack for this process... */ - ld [%curptr + AOFF_task_saved_kernel_stack], %sp + mov 1, %sp + sll %sp, (PAGE_SHIFT + 1), %sp + sub %sp, (TRACEREG_SZ + REGWIN_SZ), %sp + add %curptr, %sp, %sp /* Restore the saved globals and build a pt_regs frame. */ mov %saved_g5, %g5 - mov %g6, %l4 mov %saved_g6, %g6 STORE_PT_ALL(sp, t_psr, t_pc, t_npc, g1) - mov %l4, %g6 + + mov 1, %g6 + sll %g6, (PAGE_SHIFT + 1), %g6 + sub %g6, (TRACEREG_SZ + REGWIN_SZ), %g6 + sub %sp, %g6, %g6 /* Turn on traps and call c-code to deal with it. */ wr %t_psr, PSR_ET, %psr diff --git a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S index 7550dd627354..cb407aa6922a 100644 --- a/arch/sparc/kernel/wuf.S +++ b/arch/sparc/kernel/wuf.S @@ -1,4 +1,4 @@ -/* $Id: wuf.S,v 1.31 1997/03/04 16:26:37 jj Exp $ +/* $Id: wuf.S,v 1.34 1997/05/01 08:53:36 davem Exp $ * wuf.S: Window underflow trap handler for the Sparc. * * Copyright (C) 1995 David S. Miller @@ -145,14 +145,17 @@ fwin_user_stack_is_bolixed: * to the trap window and call c-code to deal with this. */ LOAD_CURRENT(l4, l5) - ld [%l4 + AOFF_task_saved_kernel_stack], %l5 + + mov 1, %l5 + sll %l5, (PAGE_SHIFT + 1), %l5 + sub %l5, (TRACEREG_SZ + REGWIN_SZ), %l5 + add %l4, %l5, %l5 /* Store globals into pt_regs frame. */ STORE_PT_GLOBALS(l5) STORE_PT_YREG(l5, g3) - /* Save kernel %sp in global while we change windows. */ - mov %l5, %g2 + /* Save current in a global while we change windows. */ mov %l4, %curptr save %g0, %g0, %g0 @@ -166,7 +169,10 @@ fwin_user_stack_is_bolixed: /* LOCATION: Window 'T' */ - mov %g2, %sp /* Jump onto kernel %sp being held */ + mov 1, %sp + sll %sp, (PAGE_SHIFT + 1), %sp + sub %sp, (TRACEREG_SZ + REGWIN_SZ), %sp + add %curptr, %sp, %sp /* Build rest of pt_regs. */ STORE_PT_INS(sp) diff --git a/arch/sparc/lib/irqlock.S b/arch/sparc/lib/irqlock.S index db7dd26c3771..23194e72327b 100644 --- a/arch/sparc/lib/irqlock.S +++ b/arch/sparc/lib/irqlock.S @@ -1,4 +1,4 @@ -/* $Id: irqlock.S,v 1.2 1997/04/19 04:33:37 davem Exp $ +/* $Id: irqlock.S,v 1.4 1997/05/01 02:26:54 davem Exp $ * irqlock.S: High performance IRQ global locking and interrupt entry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 9d3afdbdf679..a7f081d6efd7 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.136 1997/04/20 14:11:51 ecd Exp $ +/* $Id: srmmu.c,v 1.140 1997/05/01 08:53:39 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -659,27 +659,6 @@ static void srmmu_set_pte_cacheable(pte_t *ptep, pte_t pteval) srmmu_set_entry(ptep, pte_val(pteval)); } -static void srmmu_set_pte_nocache_hyper(pte_t *ptep, pte_t pteval) -{ - unsigned long page = ((unsigned long)ptep) & PAGE_MASK; - - srmmu_set_entry(ptep, pte_val(pteval)); - __asm__ __volatile__(" - lda [%0] %2, %%g4 - orcc %%g4, 0x0, %%g0 - be 2f - sethi %%hi(%7), %%g5 -1: subcc %%g5, %6, %%g5 ! hyper_flush_cache_page - bne 1b - sta %%g0, [%1 + %%g5] %3 - lda [%4] %5, %%g0 -2:" : /* no outputs */ - : "r" (page | 0x400), "r" (page), "i" (ASI_M_FLUSH_PROBE), - "i" (ASI_M_FLUSH_PAGE), "r" (SRMMU_FAULT_STATUS), "i" (ASI_M_MMUREGS), - "r" (vac_line_size), "i" (PAGE_SIZE) - : "g4", "g5", "cc"); -} - static void srmmu_set_pte_nocache_cypress(pte_t *ptep, pte_t pteval) { register unsigned long a, b, c, d, e, f, g; @@ -860,30 +839,12 @@ static void srmmu_unlockarea(char *vaddr, unsigned long len) */ struct task_struct *srmmu_alloc_task_struct(void) { - return (struct task_struct *) kmalloc(sizeof(struct task_struct), GFP_KERNEL); -} - -unsigned long srmmu_alloc_kernel_stack(struct task_struct *tsk) -{ - unsigned long kstk = __get_free_pages(GFP_KERNEL, 1, 0); - - if(!kstk) - kstk = (unsigned long) vmalloc(PAGE_SIZE << 1); - - return kstk; + return (struct task_struct *) __get_free_pages(GFP_KERNEL, 1, 0); } static void srmmu_free_task_struct(struct task_struct *tsk) { - kfree(tsk); -} - -static void srmmu_free_kernel_stack(unsigned long stack) -{ - if(stack < VMALLOC_START) - free_pages(stack, 1); - else - vfree((char *)stack); + free_pages((unsigned long)tsk, 1); } /* Tsunami flushes. It's page level tlb invalidation is not very @@ -1365,17 +1326,28 @@ extern void hypersparc_flush_tlb_mm(struct mm_struct *mm); extern void hypersparc_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end); extern void hypersparc_flush_tlb_page(struct vm_area_struct *vma, unsigned long page); +static void srmmu_set_pte_nocache_hyper(pte_t *ptep, pte_t pteval) +{ + unsigned long page = ((unsigned long)ptep) & PAGE_MASK; + + srmmu_set_entry(ptep, pte_val(pteval)); + hypersparc_flush_page_to_ram(page); +} + static void hypersparc_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp) { + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) pgdp) >> 4)))); + hypersparc_flush_page_to_ram((unsigned long)ctxp); hyper_flush_whole_icache(); - set_pte((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) pgdp) >> 4)))); } static void hypersparc_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) { unsigned long page = ((unsigned long) pgdp) & PAGE_MASK; - hypersparc_flush_page_to_ram(page); + if(pgdp != swapper_pg_dir) + hypersparc_flush_page_to_ram(page); + if(tsk->mm->context != NO_CONTEXT) { flush_cache_mm(tsk->mm); ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp); @@ -1429,26 +1401,29 @@ static void cypress_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) static void hypersparc_switch_to_context(struct task_struct *tsk) { - hyper_flush_whole_icache(); if(tsk->mm->context == NO_CONTEXT) { + ctxd_t *ctxp; + alloc_context(tsk->mm); - flush_cache_mm(tsk->mm); - ctxd_set(&srmmu_context_table[tsk->mm->context], tsk->mm->pgd); - flush_tlb_mm(tsk->mm); + ctxp = &srmmu_context_table[tsk->mm->context]; + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) tsk->mm->pgd) >> 4)))); + hypersparc_flush_page_to_ram((unsigned long)ctxp); } + hyper_flush_whole_icache(); srmmu_set_context(tsk->mm->context); } static void hypersparc_init_new_context(struct mm_struct *mm) { - hyper_flush_whole_icache(); + ctxd_t *ctxp; alloc_context(mm); - flush_cache_mm(mm); - ctxd_set(&srmmu_context_table[mm->context], mm->pgd); - flush_tlb_mm(mm); + ctxp = &srmmu_context_table[mm->context]; + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) mm->pgd) >> 4)))); + hypersparc_flush_page_to_ram((unsigned long)ctxp); + hyper_flush_whole_icache(); if(mm == current->mm) srmmu_set_context(mm->context); } @@ -2355,13 +2330,19 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma, static void hypersparc_destroy_context(struct mm_struct *mm) { if(mm->context != NO_CONTEXT && mm->count == 1) { + ctxd_t *ctxp; + /* HyperSparc is copy-back, any data for this * process in a modified cache line is stale * and must be written back to main memory now * else we eat shit later big time. */ flush_cache_mm(mm); - ctxd_set(&srmmu_context_table[mm->context], swapper_pg_dir); + + ctxp = &srmmu_context_table[mm->context]; + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) swapper_pg_dir) >> 4)))); + hypersparc_flush_page_to_ram((unsigned long)ctxp); + flush_tlb_mm(mm); free_context(mm->context); mm->context = NO_CONTEXT; @@ -3014,9 +2995,7 @@ __initfunc(void ld_mmu_srmmu(void)) mmu_p2v = srmmu_p2v; /* Task struct and kernel stack allocating/freeing. */ - alloc_kernel_stack = srmmu_alloc_kernel_stack; alloc_task_struct = srmmu_alloc_task_struct; - free_kernel_stack = srmmu_free_kernel_stack; free_task_struct = srmmu_free_task_struct; quick_kernel_fault = srmmu_quick_kernel_fault; diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index ebeada4c74a0..0574558f46d0 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.143 1997/04/11 00:42:14 davem Exp $ +/* $Id: sun4c.c,v 1.147 1997/05/01 08:53:42 davem Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -1093,8 +1093,7 @@ static void sun4c_quick_kernel_fault(unsigned long address) panic("sun4c kernel fault handler bolixed..."); } -/* - * 4 page buckets for task struct and kernel stack allocation. +/* 2 page buckets for task struct and kernel stack allocation. * * TASK_STACK_BEGIN * bucket[0] @@ -1105,24 +1104,17 @@ static void sun4c_quick_kernel_fault(unsigned long address) * * Each slot looks like: * - * page 1 -- task struct - * page 2 -- unmapped, for stack redzone (maybe use for pgd) - * page 3/4 -- kernel stack + * page 1 -- task struct + beginning of kernel stack + * page 2 -- rest of kernel stack */ -struct task_bucket { - struct task_struct task; - char _unused1[PAGE_SIZE - sizeof(struct task_struct)]; - char kstack[(PAGE_SIZE*3)]; -}; - -struct task_bucket *sun4c_bucket[NR_TASKS]; +union task_union *sun4c_bucket[NR_TASKS]; static int sun4c_lowbucket_avail; -#define BUCKET_EMPTY ((struct task_bucket *) 0) -#define BUCKET_SIZE (PAGE_SIZE << 2) -#define BUCKET_SHIFT 14 /* log2(sizeof(struct task_bucket)) */ +#define BUCKET_EMPTY ((union task_union *) 0) +#define BUCKET_SHIFT (PAGE_SHIFT + 1) /* log2(sizeof(struct task_bucket)) */ +#define BUCKET_SIZE (1 << BUCKET_SHIFT) #define BUCKET_NUM(addr) ((((addr) - SUN4C_LOCK_VADDR) >> BUCKET_SHIFT)) #define BUCKET_ADDR(num) (((num) << BUCKET_SHIFT) + SUN4C_LOCK_VADDR) #define BUCKET_PTE(page) \ @@ -1177,10 +1169,10 @@ static inline void garbage_collect(int entry) { int start, end; - /* 16 buckets per segment... */ - entry &= ~15; + /* 32 buckets per segment... */ + entry &= ~31; start = entry; - for(end = (start + 16); start < end; start++) + for(end = (start + 32); start < end; start++) if(sun4c_bucket[start] != BUCKET_EMPTY) return; @@ -1190,121 +1182,70 @@ static inline void garbage_collect(int entry) static struct task_struct *sun4c_alloc_task_struct(void) { - unsigned long addr, page; + unsigned long addr, pages; int entry; - page = get_free_page(GFP_KERNEL); - if(!page) + pages = __get_free_pages(GFP_KERNEL, 1, 0); + if(!pages) return (struct task_struct *) 0; for(entry = sun4c_lowbucket_avail; entry < NR_TASKS; entry++) if(sun4c_bucket[entry] == BUCKET_EMPTY) break; if(entry == NR_TASKS) { - free_page(page); + free_pages(pages, 1); return (struct task_struct *) 0; } if(entry >= sun4c_lowbucket_avail) sun4c_lowbucket_avail = entry + 1; addr = BUCKET_ADDR(entry); - sun4c_bucket[entry] = (struct task_bucket *) addr; + sun4c_bucket[entry] = (union task_union *) addr; if(sun4c_get_segmap(addr) == invalid_segment) get_locked_segment(addr); - sun4c_put_pte(addr, BUCKET_PTE(page)); + sun4c_put_pte(addr, BUCKET_PTE(pages)); + sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE)); return (struct task_struct *) addr; } -static unsigned long sun4c_alloc_kernel_stack(struct task_struct *tsk) -{ - unsigned long saddr = (unsigned long) tsk; - unsigned long page[2]; - - if(!saddr) - return 0; - page[0] = __get_free_page(GFP_KERNEL); - if(!page[0]) - return 0; - page[1] = __get_free_page(GFP_KERNEL); - if(!page[1]) { - free_page(page[0]); - return 0; - } - - saddr += PAGE_SIZE << 1; - sun4c_put_pte(saddr, BUCKET_PTE(page[0])); - sun4c_put_pte(saddr + PAGE_SIZE, BUCKET_PTE(page[1])); - return saddr; -} - -static void sun4c_free_kernel_stack_hw(unsigned long stack) -{ - unsigned long page[2]; - - page[0] = BUCKET_PTE_PAGE(sun4c_get_pte(stack)); - page[1] = BUCKET_PTE_PAGE(sun4c_get_pte(stack+PAGE_SIZE)); - - /* We are deleting a mapping, so the flushes here are mandatory. */ - sun4c_flush_page_hw(stack); - sun4c_flush_page_hw(stack + PAGE_SIZE); - - sun4c_put_pte(stack, 0); - sun4c_put_pte(stack + PAGE_SIZE, 0); - free_page(page[0]); - free_page(page[1]); -} - static void sun4c_free_task_struct_hw(struct task_struct *tsk) { unsigned long tsaddr = (unsigned long) tsk; - unsigned long page = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr)); + unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr)); int entry = BUCKET_NUM(tsaddr); /* We are deleting a mapping, so the flush here is mandatory. */ sun4c_flush_page_hw(tsaddr); + sun4c_flush_page_hw(tsaddr + PAGE_SIZE); sun4c_put_pte(tsaddr, 0); + sun4c_put_pte(tsaddr + PAGE_SIZE, 0); sun4c_bucket[entry] = BUCKET_EMPTY; if(entry < sun4c_lowbucket_avail) sun4c_lowbucket_avail = entry; - free_page(page); + free_pages(pages, 1); garbage_collect(entry); } -static void sun4c_free_kernel_stack_sw(unsigned long stack) -{ - unsigned long page[2]; - - page[0] = BUCKET_PTE_PAGE(sun4c_get_pte(stack)); - page[1] = BUCKET_PTE_PAGE(sun4c_get_pte(stack+PAGE_SIZE)); - - /* We are deleting a mapping, so the flushes here are mandatory. */ - sun4c_flush_page_sw(stack); - sun4c_flush_page_sw(stack + PAGE_SIZE); - - sun4c_put_pte(stack, 0); - sun4c_put_pte(stack + PAGE_SIZE, 0); - free_page(page[0]); - free_page(page[1]); -} - static void sun4c_free_task_struct_sw(struct task_struct *tsk) { unsigned long tsaddr = (unsigned long) tsk; - unsigned long page = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr)); + unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr)); int entry = BUCKET_NUM(tsaddr); /* We are deleting a mapping, so the flush here is mandatory. */ sun4c_flush_page_sw(tsaddr); + sun4c_flush_page_sw(tsaddr + PAGE_SIZE); sun4c_put_pte(tsaddr, 0); + sun4c_put_pte(tsaddr + PAGE_SIZE, 0); sun4c_bucket[entry] = BUCKET_EMPTY; if(entry < sun4c_lowbucket_avail) sun4c_lowbucket_avail = entry; - free_page(page); + free_pages(pages, 1); garbage_collect(entry); } @@ -1312,8 +1253,8 @@ __initfunc(static void sun4c_init_buckets(void)) { int entry; - if(sizeof(struct task_bucket) != (PAGE_SIZE << 2)) { - prom_printf("task bucket not 4 pages!\n"); + if(sizeof(union task_union) != (PAGE_SIZE << 1)) { + prom_printf("task union not 2 pages!\n"); prom_halt(); } for(entry = 0; entry < NR_TASKS; entry++) @@ -2645,7 +2586,6 @@ __initfunc(void ld_mmu_sun4c(void)) flush_tlb_mm = sun4c_flush_tlb_mm_hw; flush_tlb_range = sun4c_flush_tlb_range_hw; flush_tlb_page = sun4c_flush_tlb_page_hw; - free_kernel_stack = sun4c_free_kernel_stack_hw; free_task_struct = sun4c_free_task_struct_hw; switch_to_context = sun4c_switch_to_context_hw; destroy_context = sun4c_destroy_context_hw; @@ -2658,7 +2598,6 @@ __initfunc(void ld_mmu_sun4c(void)) flush_tlb_mm = sun4c_flush_tlb_mm_sw; flush_tlb_range = sun4c_flush_tlb_range_sw; flush_tlb_page = sun4c_flush_tlb_page_sw; - free_kernel_stack = sun4c_free_kernel_stack_sw; free_task_struct = sun4c_free_task_struct_sw; switch_to_context = sun4c_switch_to_context_sw; destroy_context = sun4c_destroy_context_sw; @@ -2736,7 +2675,6 @@ __initfunc(void ld_mmu_sun4c(void)) mmu_p2v = sun4c_p2v; /* Task struct and kernel stack allocating/freeing. */ - alloc_kernel_stack = sun4c_alloc_kernel_stack; alloc_task_struct = sun4c_alloc_task_struct; quick_kernel_fault = sun4c_quick_kernel_fault; diff --git a/arch/sparc/prom/console.c b/arch/sparc/prom/console.c index 9551094d0948..330a1f5beacb 100644 --- a/arch/sparc/prom/console.c +++ b/arch/sparc/prom/console.c @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.11 1997/03/18 17:58:10 jj Exp $ +/* $Id: console.c,v 1.12 1997/05/01 01:41:30 davem Exp $ * console.c: Routines that deal with sending and receiving IO * to/from the current console device using the PROM. * @@ -42,7 +42,7 @@ prom_nbgetchar(void) break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return i; /* Ugh, we could spin forever on unsupported proms ;( */ @@ -83,7 +83,7 @@ prom_nbputchar(char c) break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return i; /* Ugh, we could spin forever on unsupported proms ;( */ @@ -130,7 +130,7 @@ prom_query_input_device() save_flags(flags); cli(); st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); if(prom_node_has_property(st_p, "keyboard")) @@ -177,7 +177,7 @@ prom_query_output_device() save_flags(flags); cli(); st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb)); diff --git a/arch/sparc/prom/devmap.c b/arch/sparc/prom/devmap.c index 841d63a47e40..9be58efed94a 100644 --- a/arch/sparc/prom/devmap.c +++ b/arch/sparc/prom/devmap.c @@ -1,4 +1,4 @@ -/* $Id: devmap.c,v 1.3 1996/09/19 20:27:19 davem Exp $ +/* $Id: devmap.c,v 1.4 1997/05/01 01:41:31 davem Exp $ * promdevmap.c: Map device/IO areas to virtual addresses. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -33,7 +33,7 @@ prom_mapio(char *vhint, int ios, unsigned int paddr, unsigned int num_bytes) ret = (*(romvec->pv_v2devops.v2_dumb_mmap))(vhint, ios, paddr, num_bytes); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return ret; @@ -49,7 +49,7 @@ prom_unmapio(char *vaddr, unsigned int num_bytes) save_flags(flags); cli(); (*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return; diff --git a/arch/sparc/prom/devops.c b/arch/sparc/prom/devops.c index 2b33dd2b74b0..81abc0227f0e 100644 --- a/arch/sparc/prom/devops.c +++ b/arch/sparc/prom/devops.c @@ -1,4 +1,4 @@ -/* $Id: devops.c,v 1.7 1997/03/18 17:58:19 jj Exp $ +/* $Id: devops.c,v 1.8 1997/05/01 01:41:31 davem Exp $ * devops.c: Device operations using the PROM. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -35,7 +35,7 @@ prom_devopen(char *dstr) break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); @@ -60,7 +60,7 @@ prom_devclose(int dhandle) break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return 0; @@ -86,7 +86,7 @@ prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); diff --git a/arch/sparc/prom/misc.c b/arch/sparc/prom/misc.c index d23d93f61607..5c6887aba975 100644 --- a/arch/sparc/prom/misc.c +++ b/arch/sparc/prom/misc.c @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.13 1997/04/10 05:12:59 davem Exp $ +/* $Id: misc.c,v 1.14 1997/05/01 01:41:32 davem Exp $ * misc.c: Miscellaneous prom functions that don't belong * anywhere else. * @@ -22,7 +22,7 @@ prom_reboot(char *bcommand) (*(romvec->pv_reboot))(bcommand); /* Never get here. */ __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); } @@ -40,7 +40,7 @@ prom_feval(char *fstring) else (*(romvec->pv_fortheval.v2_eval))(fstring); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); } @@ -72,7 +72,7 @@ prom_cmdline(void) save_flags(flags); cli(); (*(romvec->pv_abort))(); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); install_linux_ticker(); @@ -97,7 +97,7 @@ again: (*(romvec->pv_halt))(); /* Never get here. */ __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); goto again; /* PROM is out to get me -DaveM */ diff --git a/arch/sparc/prom/mp.c b/arch/sparc/prom/mp.c index cf71cca605b7..bfce3929979d 100644 --- a/arch/sparc/prom/mp.c +++ b/arch/sparc/prom/mp.c @@ -1,4 +1,4 @@ -/* $Id: mp.c,v 1.7 1997/03/18 17:58:23 jj Exp $ +/* $Id: mp.c,v 1.8 1997/05/01 01:41:32 davem Exp $ * mp.c: OpenBoot Prom Multiprocessor support routines. Don't call * these on a UP or else you will halt and catch fire. ;) * @@ -36,7 +36,7 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); @@ -65,7 +65,7 @@ prom_stopcpu(int cpunode) break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); @@ -94,7 +94,7 @@ prom_idlecpu(int cpunode) break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); @@ -123,7 +123,7 @@ prom_restartcpu(int cpunode) break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); diff --git a/arch/sparc/prom/segment.c b/arch/sparc/prom/segment.c index cb1def0e1d2a..c517628ebaea 100644 --- a/arch/sparc/prom/segment.c +++ b/arch/sparc/prom/segment.c @@ -1,4 +1,4 @@ -/* $Id: segment.c,v 1.3 1996/09/19 20:27:28 davem Exp $ +/* $Id: segment.c,v 1.4 1997/05/01 01:41:33 davem Exp $ * segment.c: Prom routine to map segments in other contexts before * a standalone is completely mapped. This is for sun4 and * sun4c architectures only. @@ -22,7 +22,7 @@ prom_putsegment(int ctx, unsigned long vaddr, int segment) save_flags(flags); cli(); (*(romvec->pv_setctxt))(ctx, (char *) vaddr, segment); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return; diff --git a/arch/sparc/prom/tree.c b/arch/sparc/prom/tree.c index e5e2ceb3de6b..d0c92eea4f37 100644 --- a/arch/sparc/prom/tree.c +++ b/arch/sparc/prom/tree.c @@ -1,4 +1,4 @@ -/* $Id: tree.c,v 1.16 1997/03/19 14:53:16 davem Exp $ +/* $Id: tree.c,v 1.17 1997/05/01 01:41:33 davem Exp $ * tree.c: Basic device tree traversal/scanning for the Linux * prom library. * @@ -18,7 +18,7 @@ /* Macro to restore "current" to the g6 register. */ #define restore_current() __asm__ __volatile__("ld [%0], %%g6\n\t" : : \ - "r" (¤t_set[smp_processor_id()]) : \ + "r" (¤t_set[hard_smp_processor_id()]) : \ "memory") static char promlib_buf[128]; diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 16fe5c8a0006..3b8269426a7f 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.14 1997/04/14 06:56:54 davem Exp $ +/* $Id: entry.S,v 1.15 1997/04/28 14:57:08 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -34,21 +34,37 @@ sparc64_dtlb_fault: call sparc64_dtlb_fault_handler nop + /* Note, DMMU SFAR not updated for fast tlb data access miss + * traps, so we must use tag access to find the right page. + */ sparc64_dtlb_refbit_catch: + wr %g0, ASI_DMMU, %asi rdpr %pstate, %g1 wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate + ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5 + srlx %g5, PAGE_SHIFT, %g5 + ldxa [%g0 + TLB_SFSR] %asi, %g4 + sllx %g5, PAGE_SHIFT, %g5 ba,pt %xcc, etrap rd %pc, %g7 - call sparc64_dtlb_refbit_handler - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + + clr %o1 ! text_fault == 0 + mov %l5, %o3 ! address == sfar + and %l4, 0x4, %o2 ! write == sfsr.W + call do_sparc64_fault + add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr sparc64_itlb_refbit_catch: rdpr %pstate, %g1 wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate ba,pt %xcc, etrap rd %pc, %g7 - call sparc64_dtlb_refbit_handler - nop + + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %o3 + mov 1, %o1 ! text_fault == 1 + clr %o2 ! write == 0 + call do_sparc64_fault + add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr /* Note check out head.h, this code isn't even used for UP, * for SMP things will be different. In particular the data diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S index 7d293a88b01f..4a8a62ba6792 100644 --- a/arch/sparc64/kernel/etrap.S +++ b/arch/sparc64/kernel/etrap.S @@ -1,7 +1,7 @@ -/* $Id: etrap.S,v 1.11 1997/04/14 17:04:45 jj Exp $ +/* $Id: etrap.S,v 1.12 1997/04/28 14:57:07 davem Exp $ * etrap.S: Preparing for entry into the kernel on Sparc V9. * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ @@ -11,24 +11,28 @@ #include #include -/* We assume that pstate, when entering this, has AG and IE bits set, MG and IG clear */ + /* We assume that pstate, when entering this, has AG and + * IE bits set, MG and IG clear. + * + * We also guarentee for caller that AG %g4 and %g5 will have + * their values preserved and left in %l4 and %l5 respectively + * for him (fault handling needs this). + */ .text .align 32 .globl etrap, etrap_irq etrap: - rdpr %pil, %g4 + rdpr %pil, %g2 etrap_irq: rdpr %tstate, %g1 - sllx %g4, 20, %g4 - rdpr %tpc, %g2 - or %g1, %g4, %g1 - rdpr %tnpc, %g3 + sllx %g2, 20, %g2 + or %g1, %g2, %g1 /* What happens more often? etrap when already in priv or from userland? */ andcc %g1, TSTATE_PRIV, %g0 bne,a,pn %xcc, 1f - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g5 + sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 /* Just when going from userland to privileged mode, * we have to change this stuff. @@ -38,41 +42,47 @@ etrap_irq: * trap level until PRIMARY_CONTEXT is set to zero, else * we fall out of NUCLEUS too soon and crash hard. */ - rdpr %wstate, %g5 - mov PRIMARY_CONTEXT, %g7 - ldxa [%g7] ASI_DMMU, %g4 - mov SECONDARY_CONTEXT, %g6 - stxa %g0, [%g7] ASI_DMMU - stxa %g4, [%g6] ASI_DMMU - wrpr %g0, 0x0, %tl + mov PRIMARY_CONTEXT, %g1 + ldxa [%g1] ASI_DMMU, %g2 + stxa %g0, [%g1] ASI_DMMU - sll %g5, 3, %g5 - sethi %uhi(KERNBASE), %g4 - or %g4, %ulo(KERNBASE), %g4 - sethi %hi(current_set), %g6 - or %g6, %lo(current_set), %g6 - sllx %g4, 32, %g4 - wrpr %g5, %wstate - rdpr %canrestore, %g5 - ldx [%g6 + %g4], %g6 + mov SECONDARY_CONTEXT, %g1 + stxa %g2, [%g1] ASI_DMMU + + rdpr %wstate, %g1 + sll %g1, 3, %g1 + wrpr %g1, %wstate + + sethi %uhi(KERNBASE), %g2 + or %g2, %ulo(KERNBASE), %g2 + sethi %hi(current_set), %g1 + or %g1, %lo(current_set), %g1 + sllx %g2, 32, %g2 + ldx [%g1 + %g2], %g1 #ifdef __SMP__ /* FIXME: Fix the above insn for SMP */ #endif + rdpr %canrestore, %g2 wrpr %g0, 0, %canrestore - wrpr %g5, 0, %otherwin - ba,pt %xcc, 2f - ldx [%g6 + AOFF_task_saved_kernel_stack], %g5 + wrpr %g2, 0, %otherwin + + ldx [%g1 + AOFF_task_saved_kernel_stack], %g2 1: + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE] + rdpr %tpc, %g1 + rdpr %tnpc, %g3 + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TPC] + rd %y, %g1 + stx %g3, [%g2 + REGWIN_SZ + PT_V9_TNPC] + stx %g1, [%g2 + REGWIN_SZ + PT_V9_Y] + wrpr %g0, 0x0, %tl -2: - rd %y, %g4 - stx %g1, [%g5 + REGWIN_SZ + PT_V9_TSTATE] - stx %g2, [%g5 + REGWIN_SZ + PT_V9_TPC] - stx %g3, [%g5 + REGWIN_SZ + PT_V9_TNPC] - stx %g4, [%g5 + REGWIN_SZ + PT_V9_Y] + rdpr %pstate, %g1 - save %g5, -STACK_BIAS, %sp + save %g2, -STACK_BIAS, %sp mov %g1, %l1 + mov %g4, %l4 + mov %g5, %l5 mov %g7, %l2 wrpr %l1, PSTATE_AG, %pstate stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] @@ -104,11 +114,6 @@ etrap_irq: .globl etraptl1 etraptl1: - rdpr %tl, %g4 rdpr %tstate, %g1 - sub %g4, 1, %g4 - rdpr %tpc, %g2 - rdpr %tnpc, %g3 - wrpr %g4, 0x0, %tl ba,pt %xcc, 1b - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g5 + sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 60cc2ede31e5..5ec62a6b699f 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -37,22 +37,6 @@ #include #include -/* - * Initial task structure. Make this a per-architecture thing, - * because different architectures tend to have different - * alignment requirements and potentially different initial - * setup. - */ -static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; -unsigned long init_user_stack[1024] = { STACK_MAGIC, }; -static struct vm_area_struct init_mmap = INIT_MMAP; -static struct fs_struct init_fs = INIT_FS; -static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS; - -struct mm_struct init_mm = INIT_MM; -struct task_struct init_task = INIT_TASK; - #ifndef __SMP__ /* diff --git a/arch/sparc64/lib/checksum.S b/arch/sparc64/lib/checksum.S index 8a06003ee613..944594e50bb1 100644 --- a/arch/sparc64/lib/checksum.S +++ b/arch/sparc64/lib/checksum.S @@ -555,7 +555,7 @@ __csum_partial_copy_end: add %i1, %i2, %i1 2: mov %i1, %o0 - wr %%g0, ASI_S, %%asi + wr %g0, ASI_S, %asi call __bzero_noasi mov %i3, %o1 1: diff --git a/arch/sparc64/lib/copy_from_user.S b/arch/sparc64/lib/copy_from_user.S index ba26a1c01bfc..50ec7bb3dc3f 100644 --- a/arch/sparc64/lib/copy_from_user.S +++ b/arch/sparc64/lib/copy_from_user.S @@ -15,12 +15,16 @@ #include #include +#include + +#define PRE_RETL sethi %uhi(KERNBASE), %g4; sllx %g4, 32, %g4; #define EX(x,y,a,b,z) \ 98: x,y; \ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ -99: retl; \ +99: PRE_RETL \ + retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ .align 4; \ @@ -33,6 +37,7 @@ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ 99: c, d, e; \ + PRE_RETL \ retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ @@ -234,6 +239,7 @@ copy_user_last7: EX(lduba [%o1] %asi, %g2, add %g0, 1,#) stb %g2, [%o0] 1: + PRE_RETL retl clr %o0 @@ -332,6 +338,7 @@ short_table_end: EX(lduba [%o1] %asi, %g2, add %g0, 1,#) stb %g2, [%o0] 1: + PRE_RETL retl clr %o0 @@ -355,6 +362,7 @@ short_aligned_end: .section .fixup,#alloc,#execinstr .align 4 97: + PRE_RETL retl mov %o2, %o0 /* exception routine sets %g2 to (broken_insn - first_insn)>>2 */ @@ -388,6 +396,7 @@ short_aligned_end: 1: and %g1, 0x7f, %o0 add %o0, %g7, %o0 + PRE_RETL retl sub %o0, %g2, %o0 51: @@ -413,6 +422,7 @@ short_aligned_end: 3: sll %g2, 2, %g2 2: + PRE_RETL retl add %g1, %g2, %o0 52: @@ -431,6 +441,7 @@ short_aligned_end: add %g2, %g4, %g2 and %o2, 0xf, %o0 add %o0, %o3, %o0 + PRE_RETL retl sub %o0, %g2, %o0 54: @@ -441,6 +452,7 @@ short_aligned_end: and %o2, 0xf, %o2 sub %o3, %o1, %o3 sub %o2, %o4, %o2 + PRE_RETL retl add %o2, %o3, %o0 55: @@ -452,5 +464,6 @@ short_aligned_end: and %g2, 1, %g2 sll %o1, 1, %o1 add %o2, %g2, %o0 + PRE_RETL retl add %o0, %o1, %o0 diff --git a/arch/sparc64/lib/copy_to_user.S b/arch/sparc64/lib/copy_to_user.S index 47a6bd337a13..733953743d55 100644 --- a/arch/sparc64/lib/copy_to_user.S +++ b/arch/sparc64/lib/copy_to_user.S @@ -14,13 +14,17 @@ */ #include +#include #include +#define PRE_RETL sethi %uhi(KERNBASE), %g4; sllx %g4, 32, %g4; + #define EX(x,y,a,b,z) \ 98: x,y; \ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ -99: retl; \ +99: PRE_RETL \ + retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ .align 4; \ @@ -33,6 +37,7 @@ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ 99: c, d, e; \ + PRE_RETL \ retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ @@ -234,6 +239,7 @@ copy_user_last7: ldub [%o1], %g2 EX(stba %g2, [%o0] %asi, add %g0, 1,#) 1: + PRE_RETL retl clr %o0 @@ -332,6 +338,7 @@ short_table_end: ldub [%o1], %g2 EX(stba %g2, [%o0] %asi, add %g0, 1,#) 1: + PRE_RETL retl clr %o0 @@ -355,6 +362,7 @@ short_aligned_end: .section .fixup,#alloc,#execinstr .align 4 97: + PRE_RETL retl mov %o2, %o0 /* exception routine sets %g2 to (broken_insn - first_insn)>>2 */ @@ -388,6 +396,7 @@ short_aligned_end: 1: and %g1, 0x7f, %o0 add %o0, %g7, %o0 + PRE_RETL retl sub %o0, %g2, %o0 51: @@ -413,6 +422,7 @@ short_aligned_end: 3: sll %g2, 2, %g2 2: + PRE_RETL retl add %g1, %g2, %o0 52: @@ -431,6 +441,7 @@ short_aligned_end: add %g2, %g4, %g2 and %o2, 0xf, %o0 add %o0, %o3, %o0 + PRE_RETL retl sub %o0, %g2, %o0 54: @@ -441,6 +452,7 @@ short_aligned_end: and %o2, 0xf, %o2 sub %o3, %o1, %o3 sub %o2, %o4, %o2 + PRE_RETL retl add %o2, %o3, %o0 55: @@ -452,5 +464,6 @@ short_aligned_end: and %g2, 1, %g2 sll %o1, 1, %o1 add %o2, %g2, %o0 + PRE_RETL retl add %o0, %o1, %o0 diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 57ca5eb92b0a..b27b47ff87d2 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.24 1997/04/17 21:49:41 jj Exp $ +/* $Id: init.c,v 1.25 1997/04/28 14:57:11 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -694,6 +694,11 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) min_free_pages = 16; free_pages_low = min_free_pages + (min_free_pages >> 1); free_pages_high = min_free_pages + min_free_pages; + +#if 0 + printk("Testing fault handling...\n"); + *(char *)0x00000deadbef0000UL = 0; +#endif } void free_initmem (void) diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 12c0fcd52944..ab11b62a8e2d 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -1712,7 +1713,7 @@ static void fd_probe(int dev) } -static void probe_drives(void) +__initfunc(static void probe_drives(void)) { int drive,found; @@ -1860,7 +1861,7 @@ static void fd_block_done(int irq, void *dummy, struct pt_regs *fp) } -int amiga_floppy_init(void) +__initfunc(int amiga_floppy_init(void)) { int i; diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 3cf489712061..7a08808f206a 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -75,6 +75,7 @@ #include #include #include +#include #include #include @@ -1777,7 +1778,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, /* Initialize the 'unit' variable for drive 'drive' */ -static void fd_probe( int drive ) +__initfunc(static void fd_probe( int drive )) { UD.connected = 0; UDT = NULL; @@ -1820,7 +1821,7 @@ static void fd_probe( int drive ) * declared absent. */ -static int fd_test_drive_present( int drive ) +__initfunc(static int fd_test_drive_present( int drive )) { unsigned long timeout; unsigned char status; @@ -1867,7 +1868,7 @@ static int fd_test_drive_present( int drive ) * floppies, additionally start the disk-change and motor-off timers. */ -static void config_types( void ) +__initfunc(static void config_types( void )) { int drive, cnt = 0; @@ -2010,7 +2011,7 @@ static struct file_operations floppy_fops = { floppy_revalidate, /* revalidate */ }; -int atari_floppy_init (void) +__initfunc(int atari_floppy_init (void)) { int i; @@ -2070,7 +2071,7 @@ int atari_floppy_init (void) } -void atari_floppy_setup( char *str, int *ints ) +__initfunc(void atari_floppy_setup( char *str, int *ints )) { int i; diff --git a/drivers/block/ez.c b/drivers/block/ez.c index c6fc96a2f795..82270915dd7a 100644 --- a/drivers/block/ez.c +++ b/drivers/block/ez.c @@ -101,6 +101,7 @@ #include #include #include +#include #include #include @@ -256,7 +257,7 @@ static struct file_operations ez_fops = { ez_revalidate /* revalidate new media */ }; -int ez_init (void) /* preliminary initialisation */ +__initfunc(int ez_init (void)) /* preliminary initialisation */ { if (register_blkdev(MAJOR_NR,"ez",&ez_fops)) { @@ -271,7 +272,7 @@ int ez_init (void) /* preliminary initialisation */ return 0; } -static void ez_geninit (struct gendisk *ignored) /* real init */ +__initfunc(static void ez_geninit (struct gendisk *ignored)) /* real init */ { int i; @@ -507,7 +508,7 @@ void cleanup_module(void) syntax: ez=base[,irq[,rep[,nybble]]] */ -void ez_setup(char *str, int *ints) +__initfunc(void ez_setup(char *str, int *ints)) { if (ints[0] > 0) ez_base = ints[1]; if (ints[0] > 1) ez_irq = ints[2]; @@ -748,7 +749,7 @@ static void ez_doorlock( int func ) /* ez_media_check: check for and acknowledge the MC flag */ -static void ez_media_check( void ) +__initfunc(static void ez_media_check( void )) { int r; @@ -768,7 +769,7 @@ static void ez_media_check( void ) disconnect(); } -static int ez_identify( void ) +__initfunc(static int ez_identify( void )) { int k, r; @@ -800,7 +801,7 @@ static int ez_identify( void ) #define word_val(n) (ez_scratch[2*n]+256*ez_scratch[2*n+1]) -static void ez_get_capacity( void ) +__initfunc(static void ez_get_capacity( void )) { int ez_cylinders; @@ -821,7 +822,7 @@ static void ez_get_capacity( void ) ez_heads,ez_sectors); } -static void ez_standby_off( void ) +__initfunc(static void ez_standby_off( void )) { connect(); wait_for(0,NULL); @@ -830,7 +831,7 @@ static void ez_standby_off( void ) disconnect(); } -static int ez_port_check( void ) /* check for 8-bit port */ +__initfunc(static int ez_port_check( void )) /* check for 8-bit port */ { int r; @@ -843,7 +844,7 @@ static int ez_port_check( void ) /* check for 8-bit port */ return 0; } -static int ez_detect( void ) +__initfunc(static int ez_detect( void )) { int j, k; char sig[EZ_SIGLEN] = EZ_SIG; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 0fd999e186fa..fdc01f3d272f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -140,6 +140,7 @@ static int allowed_drive_mask = 0x33; #include /* CMOS defines */ #include #include +#include #include #include @@ -3726,7 +3727,7 @@ static struct file_operations floppy_fops = { /* Determine the floppy disk controller type */ /* This routine was written by David C. Niemi */ -static char get_fdc_version(void) +__initfunc(static char get_fdc_version(void)) { int r; @@ -3804,7 +3805,7 @@ static char get_fdc_version(void) /* lilo configuration */ -static void floppy_set_flags(int *ints,int param, int param2) +__initfunc(static void floppy_set_flags(int *ints,int param, int param2)) { int i; @@ -3817,7 +3818,7 @@ static void floppy_set_flags(int *ints,int param, int param2) DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param); } -static void daring(int *ints,int param, int param2) +__initfunc(static void daring(int *ints,int param, int param2)) { int i; @@ -3833,7 +3834,7 @@ static void daring(int *ints,int param, int param2) DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken"); } -static void set_cmos(int *ints, int dummy, int dummy2) +__initfunc(static void set_cmos(int *ints, int dummy, int dummy2)) { int current_drive=0; @@ -3894,7 +3895,7 @@ static struct param_table { { "L40SX", 0, &print_unex, 0, 0 } }; #define FLOPPY_SETUP -void floppy_setup(char *str, int *ints) +__initfunc(void floppy_setup(char *str, int *ints)) { int i; int param; @@ -3930,7 +3931,7 @@ void floppy_setup(char *str, int *ints) static int have_no_fdc= -EIO; -int floppy_init(void) +__initfunc(int floppy_init(void)) { int i,unit,drive; @@ -4135,7 +4136,7 @@ extern char *get_options(char *str, int *ints); char *floppy=NULL; -static void parse_floppy_cfg_string(char *cfg) +__initfunc(static void parse_floppy_cfg_string(char *cfg)) { char *ptr; int ints[11]; @@ -4151,7 +4152,7 @@ static void parse_floppy_cfg_string(char *cfg) } } -static void mod_setup(char *pattern, void (*setup)(char *, int *)) +__initfunc(static void mod_setup(char *pattern, void (*setup)(char *, int *))) { unsigned long i; char c; diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index 96d2aea70998..1eb18902de00 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -191,7 +191,7 @@ static void extended_partition(struct gendisk *hd, kdev_t dev) */ bh->b_state = 0; - if (le16_to_cpu(*(unsigned short *) (bh->b_data+510)) != MSDOS_LABEL_MAGIC) + if ((*(unsigned short *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC)) goto done; p = (struct partition *) (0x1BE + bh->b_data); @@ -316,7 +316,7 @@ read_mbr: #ifdef CONFIG_BLK_DEV_IDE check_table: #endif - if (le16_to_cpu(*(unsigned short *) (0x1fe + data)) != MSDOS_LABEL_MAGIC) { + if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) { brelse(bh); return 0; } @@ -359,7 +359,7 @@ check_table: goto read_mbr; /* start over with new MBR */ } } else if (sig <= 0x1ae && - le16_to_cpu(*(unsigned short *)(data + sig)) == 0x55AA && + *(unsigned short *)(data + sig) == cpu_to_le16(0x55AA) && (1 & *(unsigned char *)(data + sig + 2))) { /* DM6 signature in MBR, courtesy of OnTrack */ (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]"); @@ -424,7 +424,7 @@ check_table: /* * Check for old-style Disk Manager partition table */ - if (le16_to_cpu(*(unsigned short *) (data+0xfc)) == MSDOS_LABEL_MAGIC) { + if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) { p = (struct partition *) (0x1be + data); for (i = 4 ; i < 16 ; i++, current_minor++) { p--; @@ -603,7 +603,7 @@ checksum_block(__u32 *m, int size) } static int -amiga_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector) +amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) { struct buffer_head *bh; struct RigidDiskBlock *rdb; @@ -618,13 +618,15 @@ amiga_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) { if(!(bh = bread(dev,blk,512))) { - printk("Dev %d: unable to read RDB block %d\n",dev,blk); + printk("Dev %s: unable to read RDB block %d\n", + kdevname(dev),blk); goto rdb_done; } - if (*(__u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) { + if (*(u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) { rdb = (struct RigidDiskBlock *)bh->b_data; - if (checksum_block((__u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) { - printk("Dev %d: RDB in block %d has bad checksum\n",dev,blk); + if (checksum_block((u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) { + printk("Dev %s: RDB in block %d has bad checksum\n", + kdevname(dev),blk); brelse(bh); continue; } @@ -633,14 +635,14 @@ amiga_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector brelse(bh); for (part = 1; blk > 0 && part <= 16; part++) { if (!(bh = bread(dev,blk,512))) { - printk("Dev %d: unable to read partition block %d\n", - dev,blk); + printk("Dev %s: unable to read partition block %d\n", + kdevname(dev),blk); goto rdb_done; } pb = (struct PartitionBlock *)bh->b_data; blk = htonl(pb->pb_Next); if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block( - (__u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) { + (u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) { /* Tell Kernel about it */ diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 9c4d8bb7162a..62e2f8da3c8f 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -39,6 +39,7 @@ #include #include #include /* CMOS defines */ +#include #define REALLY_SLOW_IO #include @@ -110,7 +111,7 @@ unsigned long read_timer(void) } #endif -void hd_setup(char *str, int *ints) +__initfunc(void hd_setup(char *str, int *ints)) { int hdind = 0; @@ -792,7 +793,7 @@ static struct file_operations hd_fops = { block_fsync /* fsync */ }; -int hd_init(void) +__initfunc(int hd_init(void)) { if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { printk("hd: unable to get major %d for harddisk\n",MAJOR_NR); diff --git a/drivers/block/ide.c b/drivers/block/ide.c index e8228a11d5f4..89759dd32ca9 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -307,6 +307,7 @@ #include #include #include +#include #include #include @@ -2144,7 +2145,7 @@ void ide_fixstring (byte *s, const int bytecount, const int byteswap) * stridx() returns the offset of c within s, * or -1 if c is '\0' or not found within s. */ -static int stridx (const char *s, char c) +__initfunc(static int stridx (const char *s, char c)) { char *i = strchr(s, c); return (i && c) ? i - s : -1; @@ -2162,7 +2163,7 @@ static int stridx (const char *s, char c) * and base16 is allowed when prefixed with "0x". * 4. otherwise, zero is returned. */ -static int match_parm (char *s, const char *keywords[], int vals[], int max_vals) +__initfunc(static int match_parm (char *s, const char *keywords[], int vals[], int max_vals)) { static const char *decimal = "0123456789"; static const char *hex = "0123456789abcdef"; @@ -2261,7 +2262,7 @@ static int match_parm (char *s, const char *keywords[], int vals[], int max_vals * "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445) * "ide0=umc8672" : probe/support umc8672 chipsets */ -void ide_setup (char *s) +__initfunc(void ide_setup (char *s)) { int i, vals[3]; ide_hwif_t *hwif; @@ -2558,7 +2559,7 @@ typedef void (ide_pci_init_proc_t)(byte, byte); * ide_probe_pci() scans PCI for a specific vendor/device function, * and invokes the supplied init routine for each instance detected. */ -static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci_init_proc_t *init, int func_adj) +__initfunc(static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci_init_proc_t *init, int func_adj)) { unsigned long flags; unsigned index; @@ -2581,7 +2582,7 @@ static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci * This routine should ideally be using pcibios_find_class() to find all * PCI IDE interfaces, but that function causes some systems to "go weird". */ -static void probe_for_hwifs (void) +__initfunc(static void probe_for_hwifs (void)) { #ifdef CONFIG_PCI /* @@ -2620,7 +2621,7 @@ static void probe_for_hwifs (void) #endif } -void ide_init_builtin_drivers (void) +__initfunc(void ide_init_builtin_drivers (void)) { /* * Probe for special "known" interface chipsets @@ -2889,7 +2890,7 @@ EXPORT_SYMBOL(ide_unregister); /* * This is gets invoked once during initialization, to set *everything* up */ -int ide_init (void) +__initfunc(int ide_init (void)) { init_ide_data (); @@ -2904,7 +2905,7 @@ int ide_init (void) char *options = NULL; MODULE_PARM(options,"s"); -static void parse_options (char *line) +__initfunc(static void parse_options (char *line)) { char *next = line; diff --git a/drivers/block/linear.c b/drivers/block/linear.c index 6fc6960aafd6..f0f9fec79af8 100644 --- a/drivers/block/linear.c +++ b/drivers/block/linear.c @@ -21,6 +21,7 @@ #include #include +#include #include "linear.h" @@ -180,7 +181,7 @@ static struct md_personality linear_personality= #ifndef MODULE -void linear_init (void) +__initfunc(void linear_init (void)) { register_md_personality (LINEAR, &linear_personality); } diff --git a/drivers/block/loop.c b/drivers/block/loop.c index d6af70d4f5bc..212efece2cb8 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -537,8 +538,8 @@ static struct file_operations lo_fops = { #define loop_init init_module #endif -int -loop_init( void ) { +__initfunc(int +loop_init( void )) { int i; if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) { diff --git a/drivers/block/md.c b/drivers/block/md.c index 7b4ec6313b35..078e1e1ee09f 100644 --- a/drivers/block/md.c +++ b/drivers/block/md.c @@ -35,6 +35,7 @@ #include #endif #include +#include #define MAJOR_NR MD_MAJOR #define MD_DRIVER @@ -546,7 +547,7 @@ void raid0_init (void); void raid1_init (void); void raid5_init (void); -int md_init (void) +__initfunc(int md_init (void)) { printk ("md driver %s MAX_MD_DEV=%d, MAX_REAL=%d\n", MD_VERSION, MAX_MD_DEV, MAX_REAL); diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c index 8e845e8d7c64..b4d5146de3ae 100644 --- a/drivers/block/ps2esdi.c +++ b/drivers/block/ps2esdi.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -176,7 +177,7 @@ static struct gendisk ps2esdi_gendisk = }; /* initialization routine called by ll_rw_blk.c */ -int ps2esdi_init(void) +__initfunc(int ps2esdi_init(void)) { /* register the device - pass the name, major number and operations @@ -197,7 +198,7 @@ int ps2esdi_init(void) } /* ps2esdi_init */ /* handles boot time command line parameters */ -void tp720_setup(char *str, int *ints) +__initfunc(void tp720_setup(char *str, int *ints)) { /* no params, just sets the tp720esdi flag if it exists */ @@ -205,7 +206,7 @@ void tp720_setup(char *str, int *ints) tp720esdi = 1; } -void ed_setup(char *str, int *ints) +__initfunc(void ed_setup(char *str, int *ints)) { int hdind = 0; @@ -252,10 +253,9 @@ static int ps2esdi_getinfo(char *buf, int slot, void *d) } /* ps2 esdi specific initialization - called thru the gendisk chain */ -static void ps2esdi_geninit(struct gendisk *ignored) +__initfunc(static void ps2esdi_geninit(struct gendisk *ignored)) { /* - The first part contains the initialization code for the ESDI disk subsystem. All we really do is search for the POS registers of the controller @@ -386,7 +386,7 @@ static void ps2esdi_geninit(struct gendisk *ignored) } /* ps2esdi_geninit */ -static void ps2esdi_get_device_cfg(void) +__initfunc(static void ps2esdi_get_device_cfg(void)) { u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH]; diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 102b19963e86..4ac6c0c41a47 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -51,9 +51,11 @@ #include #include #include +#include #include #include +#include extern void wait_for_keypress(void); @@ -269,7 +271,7 @@ static struct file_operations fd_fops = { }; /* This is the registration and initialization section of the ramdisk driver */ -int rd_init(void) +__initfunc(int rd_init(void)) { int i; @@ -334,8 +336,8 @@ void cleanup_module(void) * romfs * gzip */ -int -identify_ramdisk_image(kdev_t device, struct file *fp, int start_block) +__initfunc(int +identify_ramdisk_image(kdev_t device, struct file *fp, int start_block)) { const int size = 512; struct minix_super_block *minixsb; @@ -440,7 +442,7 @@ done: /* * This routine loads in the ramdisk image. */ -static void rd_load_image(kdev_t device,int offset) +__initfunc(static void rd_load_image(kdev_t device,int offset)) { struct inode inode, out_inode; struct file infile, outfile; @@ -527,7 +529,7 @@ done: } -void rd_load() +__initfunc(void rd_load(void)) { if (rd_doload == 0) return; @@ -549,7 +551,7 @@ void rd_load() #ifdef CONFIG_BLK_DEV_INITRD -void initrd_load(void) +__initfunc(void initrd_load(void)) { rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),0); } @@ -608,21 +610,21 @@ static void gzip_release(void **); #include "../../lib/inflate.c" -static void *malloc(int size) +__initfunc(static void *malloc(int size)) { return kmalloc(size, GFP_KERNEL); } -static void free(void *where) +__initfunc(static void free(void *where)) { kfree(where); } -static void gzip_mark(void **ptr) +__initfunc(static void gzip_mark(void **ptr)) { } -static void gzip_release(void **ptr) +__initfunc(static void gzip_release(void **ptr)) { } @@ -631,7 +633,7 @@ static void gzip_release(void **ptr) * Fill the input buffer. This is called only when the buffer is empty * and at least one byte is really needed. */ -static int fill_inbuf() +__initfunc(static int fill_inbuf(void)) { if (exit_code) return -1; @@ -648,7 +650,7 @@ static int fill_inbuf() * Write the output window window[0..outcnt-1] and update crc and bytes_out. * (Used for the decompressed data only.) */ -static void flush_window() +__initfunc(static void flush_window(void)) { ulg c = crc; /* temporary variable */ unsigned n; @@ -666,14 +668,14 @@ static void flush_window() outcnt = 0; } -static void error(char *x) +__initfunc(static void error(char *x)) { printk(KERN_ERR "%s", x); exit_code = 1; } -static int -crd_load(struct file * fp, struct file *outfp) +__initfunc(static int +crd_load(struct file * fp, struct file *outfp)) { int result; diff --git a/drivers/block/xd.c b/drivers/block/xd.c index 603c4b1423b0..472959603415 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -126,7 +127,7 @@ static u_char xd_override = 0, xd_type = 0; static u_short xd_iobase = 0; /* xd_init: register the block device number and set up pointer tables */ -int xd_init (void) +__initfunc(int xd_init (void)) { if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) { printk("xd_init: unable to get major number %d\n",MAJOR_NR); @@ -141,7 +142,7 @@ int xd_init (void) } /* xd_detect: scan the possible BIOS ROM locations for the signature strings */ -static u_char xd_detect (u_char *controller, unsigned int *address) +__initfunc(static u_char xd_detect (u_char *controller, unsigned int *address)) { u_char i,j,found = 0; @@ -164,7 +165,7 @@ static u_char xd_detect (u_char *controller, unsigned int *address) /* xd_geninit: grab the IRQ and DMA channel, initialise the drives */ /* and set up the "raw" device entries in the table */ -static void xd_geninit (struct gendisk *ignored) +__initfunc(static void xd_geninit (struct gendisk *ignored)) { u_char i,controller; unsigned int address; @@ -527,7 +528,7 @@ static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outd return (csb & CSB_ERROR); } -static u_char xd_initdrives (void (*init_drive)(u_char drive)) +__initfunc(static u_char xd_initdrives (void (*init_drive)(u_char drive))) { u_char cmdblk[6],i,count = 0; @@ -541,7 +542,7 @@ static u_char xd_initdrives (void (*init_drive)(u_char drive)) return (count); } -static void xd_dtc_init_controller (unsigned int address) +__initfunc(static void xd_dtc_init_controller (unsigned int address)) { switch (address) { case 0xC8000: xd_iobase = 0x320; break; @@ -556,7 +557,7 @@ static void xd_dtc_init_controller (unsigned int address) outb(0,XD_RESET); /* reset the controller */ } -static void xd_dtc_init_drive (u_char drive) +__initfunc(static void xd_dtc_init_drive (u_char drive)) { u_char cmdblk[6],buf[64]; @@ -581,7 +582,7 @@ static void xd_dtc_init_drive (u_char drive) printk("xd_dtc_init_drive: error reading geometry for drive %d\n",drive); } -static void xd_wd_init_controller (unsigned int address) +__initfunc(static void xd_wd_init_controller (unsigned int address)) { switch (address) { case 0xC8000: xd_iobase = 0x320; break; @@ -600,7 +601,7 @@ static void xd_wd_init_controller (unsigned int address) /* outb(0,XD_RESET); */ /* reset the controller */ } -static void xd_wd_init_drive (u_char drive) +__initfunc(static void xd_wd_init_drive (u_char drive)) { u_char cmdblk[6],buf[0x200]; @@ -622,7 +623,7 @@ static void xd_wd_init_drive (u_char drive) printk("xd_wd_init_drive: error reading geometry for drive %d\n",drive); } -static void xd_seagate_init_controller (unsigned int address) +__initfunc(static void xd_seagate_init_controller (unsigned int address)) { switch (address) { case 0xC8000: xd_iobase = 0x320; break; @@ -639,7 +640,7 @@ static void xd_seagate_init_controller (unsigned int address) outb(0,XD_RESET); /* reset the controller */ } -static void xd_seagate_init_drive (u_char drive) +__initfunc(static void xd_seagate_init_drive (u_char drive)) { u_char cmdblk[6],buf[0x200]; @@ -655,7 +656,7 @@ static void xd_seagate_init_drive (u_char drive) } /* Omti support courtesy Dirk Melchers */ -static void xd_omti_init_controller (unsigned int address) +__initfunc(static void xd_omti_init_controller (unsigned int address)) { switch (address) { case 0xC8000: xd_iobase = 0x320; break; @@ -673,7 +674,7 @@ static void xd_omti_init_controller (unsigned int address) outb(0,XD_RESET); /* reset the controller */ } -static void xd_omti_init_drive (u_char drive) +__initfunc(static void xd_omti_init_drive (u_char drive)) { /* gets infos from drive */ xd_override_init_drive(drive); @@ -684,7 +685,7 @@ static void xd_omti_init_drive (u_char drive) /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */ -static void xd_override_init_drive (u_char drive) +__initfunc(static void xd_override_init_drive (u_char drive)) { u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 }; u_char cmdblk[6],i; @@ -707,7 +708,7 @@ static void xd_override_init_drive (u_char drive) } /* xd_setup: initialise from command line parameters */ -void xd_setup (char *command,int *integers) +__initfunc(void xd_setup (char *command,int *integers)) { xd_override = 1; @@ -720,7 +721,7 @@ void xd_setup (char *command,int *integers) } /* xd_setparam: set the drive characteristics */ -static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc) +__initfunc(static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc)) { u_char cmdblk[14]; diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 0f556752d768..ac13bcff2e91 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -28,6 +28,7 @@ #include #include #include +#include #if defined(MODULE) #include @@ -282,8 +283,8 @@ static struct file_operations z2_fops = block_fsync /* fsync */ }; -int -z2_init( void ) +__initfunc(int +z2_init( void )) { if ( !MACH_IS_AMIGA ) diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c index 514a7826d01b..c97133141b8d 100644 --- a/drivers/cdrom/aztcd.c +++ b/drivers/cdrom/aztcd.c @@ -166,6 +166,7 @@ #include #include #include +#include #include #include @@ -1049,7 +1050,7 @@ static int aztGetToc(int multi) Kernel Interface Functions ########################################################################## */ -void aztcd_setup(char *str, int *ints) +__initfunc(void aztcd_setup(char *str, int *ints)) { if (ints[0] > 0) azt_port = ints[1]; if (ints[0] > 1) @@ -1567,7 +1568,7 @@ static int aztcd_release(struct inode * inode, struct file * file) * Test for presence of drive and initialize it. Called at boot time. */ -int aztcd_init(void) +__initfunc(int aztcd_init(void)) { long int count, max_count; unsigned char result[50]; int st; diff --git a/drivers/cdrom/bpcd.c b/drivers/cdrom/bpcd.c index 49225ec0c533..9f7e8b39532c 100644 --- a/drivers/cdrom/bpcd.c +++ b/drivers/cdrom/bpcd.c @@ -113,6 +113,7 @@ #include #include #include +#include #include #include @@ -201,7 +202,7 @@ static struct file_operations bp_fops = { nybble value. The following function initialises the table. */ -static void init_nyb_map( void ) +__initfunc(static void init_nyb_map( void )) { int i, j; @@ -212,7 +213,7 @@ static void init_nyb_map( void ) } } -int bpcd_init (void) /* preliminary initialisation */ +__initfunc(int bpcd_init (void)) /* preliminary initialisation */ { init_nyb_map(); @@ -327,7 +328,7 @@ void cleanup_module(void) syntax: bpcd=base[,nybble[,rep]] */ -void bpcd_setup(char *str, int *ints) +__initfunc(void bpcd_setup(char *str, int *ints)) { if (ints[0] > 0) bp_base = ints[1]; if (ints[0] > 1) bp_nybble = ints[2]; @@ -425,7 +426,7 @@ static void read_data( char * buf, int len ) if (bp_mode == 2) { t2(1); t2(0x20); } } -static int probe( int id ) +__initfunc(static int probe( int id )) { int l, h, t; int r = -1; @@ -588,7 +589,7 @@ static void bp_eject( void) bp_atapi(ej_cmd,0,"eject"); } -static int bp_reset( void ) +__initfunc(static int bp_reset( void )) /* the ATAPI standard actually specifies the contents of all 7 registers after a reset, but the specification is ambiguous concerning the last @@ -615,7 +616,7 @@ static int bp_reset( void ) return flg-1; } -static int bp_identify( char * id ) +__initfunc(static int bp_identify( char * id )) { int k; char id_cmd[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0}; @@ -627,7 +628,7 @@ static int bp_identify( char * id ) return 0; } -static int bp_port_check( void ) /* check for 8-bit port */ +__initfunc(static int bp_port_check( void )) /* check for 8-bit port */ { int r; @@ -640,7 +641,7 @@ static int bp_port_check( void ) /* check for 8-bit port */ return 0; } -static int bp_locate( void ) +__initfunc(static int bp_locate( void )) { int k; @@ -652,7 +653,7 @@ static int bp_locate( void ) return -1; } -static int bp_do_detect( int autop ) +__initfunc(static int bp_do_detect( int autop )) { char id[18]; @@ -705,7 +706,7 @@ static int bp_do_detect( int autop ) add it here .... */ -static int bp_detect( void ) +__initfunc(static int bp_detect( void )) { if (bp_base) return bp_do_detect(0); if (!bp_do_detect(0x378)) return 0; diff --git a/drivers/cdrom/cdi.c b/drivers/cdrom/cdi.c index c45056d2e667..ee90de9c6c54 100644 --- a/drivers/cdrom/cdi.c +++ b/drivers/cdrom/cdi.c @@ -28,6 +28,7 @@ #include #include /* where the proto type of cdi_init() is */ +#include #ifdef CONFIG_ISP16_CDI #include #endif CONFIG_ISP16_CDI @@ -35,8 +36,8 @@ /* * Cdrom interface configuration. */ -int -cdi_init(void) +__initfunc(int +cdi_init(void)) { int ret_val = -1; diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index 54c1296861b7..e2c269bcf763 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -190,6 +190,7 @@ #include #include #include +#include #include #include @@ -220,7 +221,7 @@ static struct unsigned short base; /* I/O Base Address */ short int_num; /* Interrupt Number (-1 means scan for it, 0 means don't use) */ -} cdu31a_addresses[] = +} cdu31a_addresses[] __initdata = { #if 0 /* No autoconfig any more. See Note at beginning of this file. */ @@ -2963,12 +2964,12 @@ static struct file_operations scd_fops = { /* The different types of disc loading mechanisms supported */ -static const char *load_mech[] = { "caddy", "tray", "pop-up", "unknown" }; +static const char *load_mech[] __initdata = { "caddy", "tray", "pop-up", "unknown" }; -static void +__initfunc(static void get_drive_configuration(unsigned short base_io, unsigned char res_reg[], - unsigned int *res_size) + unsigned int *res_size)) { int retry_count; @@ -3032,9 +3033,9 @@ get_drive_configuration(unsigned short base_io, /* * Set up base I/O and interrupts, called from main.c. */ -void +__initfunc(void cdu31a_setup(char *strings, - int *ints) + int *ints)) { if (ints[0] > 0) { @@ -3063,8 +3064,8 @@ static int cdu31a_block_size; /* * Initialize the driver. */ -int -cdu31a_init(void) +__initfunc(int +cdu31a_init(void)) { struct s_sony_drive_config drive_config; unsigned int res_size; diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index 9411b3f02ed6..fb55337064cb 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c @@ -138,6 +138,7 @@ History: #include #include #include +#include #include @@ -1186,7 +1187,7 @@ void cleanup(int level) check_region, 15 bits of one port and 6 of another make things likely enough to accept the region on the first hit... */ -int probe_base_port(int base) +__initfunc(int probe_base_port(int base)) { int b=0x300, e=0x370; /* this is the range of start addresses */ volatile int fool, i; @@ -1206,7 +1207,7 @@ int probe_base_port(int base) #if !defined(MODULE) || defined(AUTO_PROBE_MODULE) /* Probe for irq# nr. If nr==0, probe for all possible irq's. */ -int probe_irq(int nr) { +__initfunc(int probe_irq(int nr)) { int irqs, irq; outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */ sti(); @@ -1220,7 +1221,7 @@ int probe_irq(int nr) { } #endif -int cm206_init(void) +__initfunc(int cm206_init(void)) { uch e=0; long int size=sizeof(struct cm206_struct); @@ -1303,7 +1304,7 @@ int cm206_init(void) static int cm206[2] = {0,0}; /* for compatible `insmod' parameter passing */ -void parse_options(void) +__initfunc(void parse_options(void)) { int i; for (i=0; i<2; i++) { @@ -1337,7 +1338,7 @@ void cleanup_module(void) /* This setup function accepts either `auto' or numbers in the range * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */ -void cm206_setup(char *s, int *p) +__initfunc(void cm206_setup(char *s, int *p)) { int i; if (!strcmp(s, "auto")) auto_probe=1; diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c index c9ad14748a50..685990a773cb 100644 --- a/drivers/cdrom/gscd.c +++ b/drivers/cdrom/gscd.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -191,7 +192,7 @@ static int check_gscd_med_chg (kdev_t full_dev) } -void gscd_setup (char *str, int *ints) +__initfunc(void gscd_setup (char *str, int *ints)) { if (ints[0] > 0) { @@ -848,7 +849,7 @@ int i; return; } -int find_drives (void) +__initfunc(int find_drives (void)) { int *pdrv; int drvnum; @@ -899,7 +900,7 @@ int i; return drvnum; } -void init_cd_drive ( int num ) +__initfunc(void init_cd_drive ( int num )) { char resp [50]; int i; @@ -991,7 +992,7 @@ void cleanup_module (void) /* Test for presence of drive and initialize it. Called only at boot time. */ -int gscd_init (void) +__initfunc(int gscd_init (void)) { return my_gscd_init (); } @@ -999,7 +1000,7 @@ int gscd_init (void) /* This is the common initialisation for the GoldStar drive. */ /* It is called at boot time AND for module init. */ -int my_gscd_init (void) +__initfunc(int my_gscd_init (void)) { int i; int result; diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c index c3bb43d24886..88c070eba0a5 100644 --- a/drivers/cdrom/isp16.c +++ b/drivers/cdrom/isp16.c @@ -48,6 +48,7 @@ #include #include #include +#include #include static short isp16_detect(void); @@ -76,8 +77,8 @@ void cleanup_module(void); #define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p)) -void -isp16_setup(char *str, int *ints) +__initfunc(void +isp16_setup(char *str, int *ints)) { if ( ints[0] > 0 ) isp16_cdrom_base = ints[1]; @@ -93,8 +94,8 @@ isp16_setup(char *str, int *ints) * ISP16 initialisation. * */ -int -isp16_init(void) +__initfunc(int +isp16_init(void)) { u_char expected_drive; @@ -143,8 +144,8 @@ isp16_init(void) return(0); } -static short -isp16_detect(void) +__initfunc(static short +isp16_detect(void)) { if ( isp16_c929__detect() >= 0 ) @@ -153,8 +154,8 @@ isp16_detect(void) return(isp16_c928__detect()); } -static short -isp16_c928__detect(void) +__initfunc(static short +isp16_c928__detect(void)) { u_char ctrl; u_char enable_cdrom; @@ -202,8 +203,8 @@ isp16_c928__detect(void) return(i); } -static short -isp16_c929__detect(void) +__initfunc(static short +isp16_c929__detect(void)) { u_char ctrl; u_char tmp; @@ -229,8 +230,8 @@ isp16_c929__detect(void) return(2); } -static short -isp16_cdi_config(int base, u_char drive_type, int irq, int dma) +__initfunc(static short +isp16_cdi_config(int base, u_char drive_type, int irq, int dma)) { u_char base_code; u_char irq_code; diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c index aa6f07ec80d8..e4d1a73f6b51 100644 --- a/drivers/cdrom/mcd.c +++ b/drivers/cdrom/mcd.c @@ -80,6 +80,7 @@ #include #include #include +#include /* #define REALLY_SLOW_IO */ #include @@ -196,7 +197,7 @@ static int GetToc(void); static int getValue(unsigned char *result); -void mcd_setup(char *str, int *ints) +__initfunc(void mcd_setup(char *str, int *ints)) { if (ints[0] > 0) mcd_port = ints[1]; @@ -1175,7 +1176,7 @@ static struct file_operations mcd_fops = { * Test for presence of drive and initialize it. Called at boot time. */ -int mcd_init(void) +__initfunc(int mcd_init(void)) { int count; unsigned char result[3]; diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c index 081bd0d53ab6..9ce2d7ad42ae 100644 --- a/drivers/cdrom/mcdx.c +++ b/drivers/cdrom/mcdx.c @@ -63,6 +63,7 @@ static const char *mcdx_c_version #include #include #include +#include #include #include @@ -910,7 +911,7 @@ int check_mcdx_media_change(kdev_t full_dev) return 1; } -void mcdx_setup(char *str, int *pi) +__initfunc(void mcdx_setup(char *str, int *pi)) { if (pi[0] > 0) mcdx_drive_map[0][0] = pi[1]; if (pi[0] > 1) mcdx_drive_map[0][1] = pi[2]; @@ -1160,7 +1161,7 @@ void cleanup_module(void) /* Support functions ************************************************/ -int mcdx_init(void) +__initfunc(int mcdx_init(void)) { int drive; diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c index 8bd4b84f669e..417769111c8e 100644 --- a/drivers/cdrom/optcd.c +++ b/drivers/cdrom/optcd.c @@ -65,6 +65,7 @@ #include #include #include +#include #include #define MAJOR_NR OPTICS_CDROM_MAJOR @@ -1961,7 +1962,7 @@ static int opt_media_change(kdev_t dev) /* Returns 1 if a drive is detected with a version string starting with "DOLPHIN". Otherwise 0. */ -static int version_ok(void) +__initfunc(static int version_ok(void)) { char devname[100]; int count, i, ch, status; @@ -2016,7 +2017,7 @@ static struct file_operations opt_fops = { /* Get kernel parameter when used as a kernel driver */ -void optcd_setup(char *str, int *ints) +__initfunc(void optcd_setup(char *str, int *ints)) { if (ints[0] > 0) optcd_port = ints[1]; @@ -2024,7 +2025,7 @@ void optcd_setup(char *str, int *ints) /* Test for presence of drive and initialize it. Called at boot time or during module initialisation. */ -int optcd_init(void) +__initfunc(int optcd_init(void)) { int status; diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 6d27b22487dc..f07cade7f04a 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -328,6 +328,7 @@ #include #include #include +#include #include #include @@ -3052,7 +3053,7 @@ static int cc_SubChanInfo(int frame, int count, u_char *buffer) } #endif FUTURE /*==========================================================================*/ -static void check_datarate(void) +__initfunc(static void check_datarate(void)) { int i=0; @@ -3122,7 +3123,7 @@ static int c2_ReadError(int fam) } #endif /*==========================================================================*/ -static void ask_mail(void) +__initfunc(static void ask_mail(void)) { int i; @@ -3141,7 +3142,7 @@ static void ask_mail(void) msg(DBG_INF,"infobuf =%s\n", msgbuf); } /*==========================================================================*/ -static int check_version(void) +__initfunc(static int check_version(void)) { int i, j, l; int teac_possible=0; @@ -3439,7 +3440,7 @@ static void switch_drive(int i) /* * probe for the presence of an interface card */ -static int check_card(int port) +__initfunc(static int check_card(int port)) { #undef N_RESPO #define N_RESPO 20 @@ -3543,7 +3544,7 @@ static int check_card(int port) /* * probe for the presence of drives on the selected controller */ -static int check_drives(void) +__initfunc(static int check_drives(void)) { int i, j; @@ -5284,10 +5285,11 @@ static struct file_operations sbpcd_fops = * bytes above). * */ +__initfunc( #if (SBPCD_ISSUE-1) static #endif -void sbpcd_setup(const char *s, int *p) +void sbpcd_setup(const char *s, int *p)) { setup_done++; msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s); @@ -5338,7 +5340,7 @@ void sbpcd_setup(const char *s, int *p) * port 0x330, we have to use an offset of 8; so, the real CDROM port * address is 0x338. */ -static int config_spea(void) +__initfunc(static int config_spea(void)) { /* * base address offset between configuration port and CDROM port, @@ -5397,7 +5399,7 @@ static int config_spea(void) #ifdef MODULE int init_module(void) #else -int SBPCD_INIT(void) +__initfunc(int SBPCD_INIT(void)) #endif MODULE { int i=0, j=0; diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c index 0ca13dc3d625..67d04134d130 100644 --- a/drivers/cdrom/sjcd.c +++ b/drivers/cdrom/sjcd.c @@ -65,6 +65,7 @@ #include #include #include +#include #include #include @@ -159,7 +160,7 @@ static int sjcd_cleanup(void); * Set up device, i.e., use command line data to set * base address. */ -void sjcd_setup( char *str, int *ints ) +__initfunc(void sjcd_setup( char *str, int *ints )) { if (ints[0] > 0) sjcd_base = ints[1]; @@ -1449,7 +1450,7 @@ static struct { * Test for presence of drive and initialize it. Called at boot time. * Probe cdrom, find out version and status. */ -int sjcd_init( void ){ +__initfunc(int sjcd_init( void )){ int i; printk(KERN_INFO "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", SJCD_VERSION_MAJOR, diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c index 33b4bd42a682..b5c257f9bb60 100644 --- a/drivers/cdrom/sonycd535.c +++ b/drivers/cdrom/sonycd535.c @@ -120,6 +120,7 @@ #include #include #include +#include #define REALLY_SLOW_IO #include @@ -1484,8 +1485,8 @@ static struct file_operations cdu_fops = /* * Initialize the driver. */ -int -sony535_init(void) +__initfunc(int +sony535_init(void)) { struct s535_sony_drive_config drive_config; Byte cmd_buff[3]; @@ -1649,8 +1650,8 @@ sony535_init(void) * * the address value has to be the existing CDROM port address. */ -void -sonycd535_setup(char *strings, int *ints) +__initfunc(void +sonycd535_setup(char *strings, int *ints)) { /* if IRQ change and default io base desired, * then call with io base of 0 diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c index d8b267095cd6..3e2ee97bd4dd 100644 --- a/drivers/char/busmouse.c +++ b/drivers/char/busmouse.c @@ -56,7 +56,7 @@ static struct mouse_status mouse; static int mouse_irq = MOUSE_IRQ; -void bmouse_setup(char *str, int *ints) +__initfunc(void bmouse_setup(char *str, int *ints)) { if (ints[0] > 0) mouse_irq=ints[1]; diff --git a/drivers/char/console.c b/drivers/char/console.c index 763d3c71b3bc..e45e2d67d3c9 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -101,6 +101,7 @@ #include #include #include +#include #ifdef CONFIG_APM #include #endif @@ -1979,7 +1980,7 @@ static void console_bh(void) * Reads the information preserved by setup.s to determine the current display * type and sets everything accordingly. */ -unsigned long con_init(unsigned long kmem_start) +__initfunc(unsigned long con_init(unsigned long kmem_start)) { const char *display_desc = "????"; int currcons = 0; diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c index c2d1648e69c5..878ac0d72f7b 100644 --- a/drivers/char/consolemap.c +++ b/drivers/char/consolemap.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "consolemap.h" @@ -483,8 +484,8 @@ conv_uni_to_pc(long ucs) * initialized. It must be possible to call kmalloc(..., GFP_KERNEL) * from this function, hence the call from sys_setup. */ -void -console_map_init(void) +__initfunc(void +console_map_init(void)) { con_set_default_unimap(); } diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 3d71f60ad9d4..ef97f72557f7 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -34,6 +34,7 @@ #include /* guess what */ #include #include +#include #include #include @@ -529,7 +530,7 @@ static struct file_operations dsp56k_fops = { static int init_error = 0; -void dsp56k_init(void) +__initfunc(void dsp56k_init(void)) { if(!ATARIHW_PRESENT(DSP56K)) { init_error = 1; diff --git a/drivers/char/fbmem.c b/drivers/char/fbmem.c index 1493f49329c8..b267f84d3125 100644 --- a/drivers/char/fbmem.c +++ b/drivers/char/fbmem.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -300,8 +301,8 @@ unregister_framebuffer(int node) return 0; } -void -fbmem_init(void) +__initfunc(void +fbmem_init(void)) { if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) printk("unable to get major %d for fb devs\n", FB_MAJOR); diff --git a/drivers/char/ftape/kernel-interface.c b/drivers/char/ftape/kernel-interface.c index 31719a451b71..9bcb35e46560 100644 --- a/drivers/char/ftape/kernel-interface.c +++ b/drivers/char/ftape/kernel-interface.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -120,7 +121,7 @@ EXPORT_NO_SYMBOLS; #define ftape_init init_module #endif -int ftape_init(void) +__initfunc(int ftape_init(void)) { int n; int order; diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 7fd2f9b35a9b..599ae87fcded 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -631,7 +631,7 @@ MODULE_PARM(parport, "1-" __MODULE_STRING(LP_NO) "i"); static int parport_ptr = 0; -void lp_setup(char *str, int *ints) +__initfunc(void lp_setup(char *str, int *ints)) { /* Ugh. */ if (!strncmp(str, "parport", 7)) { diff --git a/drivers/char/lp_intern.c b/drivers/char/lp_intern.c index 9d676f927a1d..7bb4ec634a63 100644 --- a/drivers/char/lp_intern.c +++ b/drivers/char/lp_intern.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_AMIGA @@ -33,7 +34,6 @@ #endif #include -static int my_inter = 0; static int minor = -1; static void lp_int_out(int, int); @@ -126,24 +126,18 @@ lp_int_online (int dev) } } -static int lp_int_my_interrupt(int dev) -{ - return my_inter; -} - static void lp_int_interrupt(int irq, void *data, struct pt_regs *fp) { - my_inter = 1; - lp_interrupt(irq, data, fp); - my_inter = 0; + lp_interrupt(minor); } -static void lp_int_open(void) +static int lp_int_open(int dev) { MOD_INC_USE_COUNT; + return 0; } -static void lp_int_release(void) +static void lp_int_release(int dev) { MOD_DEC_USE_COUNT; } @@ -155,7 +149,7 @@ static struct lp_struct tab = { lp_int_busy, lp_int_pout, lp_int_online, - lp_int_my_interrupt, + 0, NULL, /* ioctl */ lp_int_open, lp_int_release, @@ -167,7 +161,7 @@ static struct lp_struct tab = { NULL, }; -int lp_internal_init(void) +__initfunc(int lp_internal_init(void)) { #ifdef CONFIG_AMIGA if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL)) diff --git a/drivers/char/lp_m68k.c b/drivers/char/lp_m68k.c index 3cc9458bddd6..17405c191b25 100644 --- a/drivers/char/lp_m68k.c +++ b/drivers/char/lp_m68k.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #ifdef CONFIG_KERNELD #include @@ -465,7 +466,7 @@ EXPORT_SYMBOL(lp_init); EXPORT_SYMBOL(register_parallel); EXPORT_SYMBOL(unregister_parallel); -int lp_init(void) +__initfunc(int lp_init(void)) { extern char m68k_debug_device[]; @@ -498,7 +499,7 @@ int lp_init(void) /* * Currently we do not accept any lp-parameters, but that may change. */ -void lp_setup(char *str, int *ints) +__initfunc(void lp_setup(char *str, int *ints)) { } diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 3d973d2a8af9..516ef6042015 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -139,7 +139,8 @@ static long read_kmem(struct inode *inode, struct file *file, else tmp = count; read = tmp; -#if defined(__sparc__) /* we don't have page 0 mapped on sparc.. */ +#if defined(__sparc__) || defined(__mc68000__) + /* we don't have page 0 mapped on sparc and m68k.. */ while (p < PAGE_SIZE && tmp > 0) { put_user(0,buf); buf++; @@ -172,7 +173,8 @@ static long write_kmem(struct inode * inode, struct file * file, if (count > (unsigned long) high_memory - p) count = (unsigned long) high_memory - p; written = 0; -#if defined(__sparc__) /* we don't have page 0 mapped on sparc.. */ +#if defined(__sparc__) || defined(__mc68000__) + /* we don't have page 0 mapped on sparc and m68k.. */ while (p < PAGE_SIZE && count > 0) { /* Hmm. Do something? */ buf++; diff --git a/drivers/char/misc.c b/drivers/char/misc.c index fd72f33d8447..d632e4788631 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -73,6 +73,7 @@ extern void watchdog_init(void); extern void wdt_init(void); extern void pcwatchdog_init(void); extern int rtc_init(void); +extern int dsp56k_init(void); #ifdef CONFIG_PROC_FS static int misc_read_proc(char *buf, char **start, off_t offset, @@ -235,6 +236,9 @@ __initfunc(int misc_init(void)) #ifdef CONFIG_RTC rtc_init(); #endif +#ifdef CONFIG_ATARI_DSP56K + dsp56k_init(); +#endif #endif /* !MODULE */ if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { printk("unable to get major %d for misc devices\n", diff --git a/drivers/char/msbusmouse.c b/drivers/char/msbusmouse.c index b11730f70d56..8f98231b8dca 100644 --- a/drivers/char/msbusmouse.c +++ b/drivers/char/msbusmouse.c @@ -51,7 +51,7 @@ static struct mouse_status mouse; static int mouse_irq = MOUSE_IRQ; -void msmouse_setup(char *str, int *ints) +__initfunc(void msmouse_setup(char *str, int *ints)) { if (ints[0] > 0) mouse_irq=ints[1]; diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index c09c7dbbe0aa..1e7e67712938 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -895,7 +895,7 @@ static void pcxe_flush_chars(struct tty_struct *tty) * Driver setup function when linked into the kernel to optionally parse multible * "digi="-lines and initialize the driver at boot time. No probing. */ -void pcxx_setup(char *str, int *ints) +__initfunc(void pcxx_setup(char *str, int *ints)) { struct board_info board; diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 301babf81cdc..d0e6b857feb1 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1821,7 +1821,7 @@ static void rc_release_drivers(void) * addresses in this case. * */ -void riscom8_setup(char *str, int * ints) +__initfunc(void riscom8_setup(char *str, int * ints)) { int i; diff --git a/drivers/char/tga.c b/drivers/char/tga.c index 723cbc631301..8a1aa9186b50 100644 --- a/drivers/char/tga.c +++ b/drivers/char/tga.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -140,35 +141,35 @@ unsigned long tga_fb_base; unsigned long tga_regs_base; unsigned int tga_bpp, tga_fb_width, tga_fb_height, tga_fb_stride; -static unsigned int fb_offset_presets[4] = { +static unsigned int fb_offset_presets[4] __initdata = { TGA_8PLANE_FB_OFFSET, TGA_24PLANE_FB_OFFSET, 0xffffffff, TGA_24PLUSZ_FB_OFFSET }; -static unsigned int deep_presets[4] = { +static unsigned int deep_presets[4] __initdata = { 0x00014000, 0x0001440d, 0xffffffff, 0x0001441d }; -static unsigned int rasterop_presets[4] = { +static unsigned int rasterop_presets[4] __initdata = { 0x00000003, 0x00000303, 0xffffffff, 0x00000303 }; -static unsigned int mode_presets[4] = { +static unsigned int mode_presets[4] __initdata = { 0x00002000, 0x00002300, 0xffffffff, 0x00002300 }; -static unsigned int base_addr_presets[4] = { +static unsigned int base_addr_presets[4] __initdata = { 0x00000000, 0x00000001, 0xffffffff, @@ -304,8 +305,8 @@ set_cursor(int currcons) restore_flags(flags); } -unsigned long -con_type_init(unsigned long kmem_start, const char **display_desc) +__initfunc(unsigned long +con_type_init(unsigned long kmem_start, const char **display_desc)) { can_do_color = 1; @@ -323,8 +324,8 @@ con_type_init(unsigned long kmem_start, const char **display_desc) return kmem_start; } -void -con_type_init_finish(void) +__initfunc(void +con_type_init_finish(void)) { } @@ -447,8 +448,8 @@ void set_vesa_blanking(const unsigned long arg) * when TGA console is configured, at the end of the probing code, * we call here to look for a TGA device, and proceed... */ -void -tga_console_init(void) +__initfunc(void +tga_console_init(void)) { unsigned char pci_bus, pci_devfn; int status; @@ -490,9 +491,9 @@ tga_console_init(void) #endif } -unsigned char PLLbits[7] = { 0x80, 0x04, 0x00, 0x24, 0x44, 0x80, 0xb8 }; +unsigned char PLLbits[7] __initdata = { 0x80, 0x04, 0x00, 0x24, 0x44, 0x80, 0xb8 }; -const unsigned long bt485_cursor_source[64] = { +const unsigned long bt485_cursor_source[64] __initdata = { 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff, 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff, 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff, @@ -502,7 +503,7 @@ const unsigned long bt485_cursor_source[64] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -const unsigned int bt463_cursor_source[256] = { +const unsigned int bt463_cursor_source[256] = __initdata { 0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x00000000, 0x00000000, 0x00000000, @@ -533,8 +534,8 @@ const unsigned int bt463_cursor_source[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -void -tga_init_video() +__initfunc(void +tga_init_video(void)) { int i, j, temp; unsigned char *cbp; @@ -750,8 +751,8 @@ tga_init_video() tga_fb_stride = tga_fb_width / sizeof(int); } -void -tga_clear_screen() +__initfunc(void +tga_clear_screen(void)) { register int i, j; register unsigned int *dst; diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c index 4f2dbf768eee..9d4ee2449ab1 100644 --- a/drivers/char/tpqic02.c +++ b/drivers/char/tpqic02.c @@ -89,6 +89,7 @@ #include #include #include +#include #include #include @@ -2866,10 +2867,7 @@ static int qic02_get_resources(void) return 0; } /* qic02_get_resources */ -#ifdef MODULE -static -#endif -int qic02_tape_init(void) +__initfunc(static int qic02_tape_init(void)) { if (TPSTATSIZE != 6) { diff --git a/drivers/char/vga.c b/drivers/char/vga.c index 093593153e7d..bfec037ed4dd 100644 --- a/drivers/char/vga.c +++ b/drivers/char/vga.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -146,8 +147,8 @@ set_cursor(int currcons) hide_cursor(); } -unsigned long -con_type_init(unsigned long kmem_start, const char **display_desc) +__initfunc(unsigned long +con_type_init(unsigned long kmem_start, const char **display_desc)) { if (ORIG_VIDEO_MODE == 7) /* Is this a monochrome display? */ { @@ -239,8 +240,8 @@ con_type_init(unsigned long kmem_start, const char **display_desc) return kmem_start; } -void -con_type_init_finish(void) +__initfunc(void +con_type_init_finish(void)) { } diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c index e32131b6372a..31837eee2c09 100644 --- a/drivers/char/wdt.c +++ b/drivers/char/wdt.c @@ -61,7 +61,7 @@ static int irq=14; * Setup options */ -void wdt_setup(char *str, int *ints) +__initfunc(void wdt_setup(char *str, int *ints)) { if(ints[0]>0) { diff --git a/drivers/isdn/sc/Makefile b/drivers/isdn/sc/Makefile index 5440cdaff4ba..be0d8b76c547 100644 --- a/drivers/isdn/sc/Makefile +++ b/drivers/isdn/sc/Makefile @@ -1,5 +1,5 @@ # -# $Id: Makefile.kernel,v 1.1 1996/11/07 13:07:40 fritz Exp $ +# $Id: Makefile,v 1.2 1997/05/01 08:53:47 davem Exp $ # Copyright (C) 1996 SpellCaster Telecommunications Inc. # # This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index f5b75bb9f8c8..4cf7b49a75d2 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -94,6 +94,7 @@ #include #include #include +#include #include #include @@ -301,7 +302,7 @@ static inline short int SHADOW(short int addr) * checks for presence of EtherExpress card */ -int express_probe(struct device *dev) +__initfunc(int express_probe(struct device *dev)) { unsigned short *port; static unsigned short ports[] = { 0x300,0x310,0x270,0x320,0x340,0 }; @@ -913,7 +914,7 @@ static void eexp_hw_tx_pio(struct device *dev, unsigned short *buf, * than one card in a machine. */ -static int eexp_hw_probe(struct device *dev, unsigned short ioaddr) +__initfunc(static int eexp_hw_probe(struct device *dev, unsigned short ioaddr)) { unsigned short hw_addr[3]; unsigned char buswidth; @@ -1034,8 +1035,8 @@ static int eexp_hw_probe(struct device *dev, unsigned short ioaddr) * Read a word from the EtherExpress on-board serial EEPROM. * The EEPROM contains 64 words of 16 bits. */ -static unsigned short eexp_hw_readeeprom(unsigned short ioaddr, - unsigned char location) +__initfunc(static unsigned short eexp_hw_readeeprom(unsigned short ioaddr, + unsigned char location)) { unsigned short cmd = 0x180|(location&0x7f); unsigned short rval = 0,wval = EC_CS|i586_RST; diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c index 1421356e325c..07e271cec875 100644 --- a/drivers/net/sk_g16.c +++ b/drivers/net/sk_g16.c @@ -68,6 +68,7 @@ static const char *rcsid = "$Id: sk_g16.c,v 1.1 1994/06/30 16:25:15 root Exp $"; #include #include #include +#include #include #include @@ -532,7 +533,7 @@ void SK_print_ram(struct device *dev); * (detachable devices only). */ -int SK_init(struct device *dev) +__initfunc(int SK_init(struct device *dev)) { int ioaddr = 0; /* I/O port address used for POS regs */ int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */ @@ -616,7 +617,7 @@ int SK_init(struct device *dev) * 94/06/30 pwe SK_ADDR now checked and at the correct place -*/ -int SK_probe(struct device *dev, short ioaddr) +__initfunc(int SK_probe(struct device *dev, short ioaddr)) { int i,j; /* Counters */ int sk_addr_flag = 0; /* SK ADDR correct? 1 - no, 0 - yes */ @@ -1740,7 +1741,7 @@ static void set_multicast_list(struct device *dev) * YY/MM/DD uid Description -*/ -unsigned int SK_rom_addr(void) +__initfunc(unsigned int SK_rom_addr(void)) { int i,j; int rom_found = 0; diff --git a/drivers/net/skeleton.c b/drivers/net/skeleton.c index 115d419c973f..3f78f724d377 100644 --- a/drivers/net/skeleton.c +++ b/drivers/net/skeleton.c @@ -56,6 +56,7 @@ static const char *version = #include #include #include +#include #include #include @@ -70,7 +71,7 @@ static const char* cardname = "netcard"; /* First, a few definitions that the brave might change. */ /* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int netcard_portlist[] = +static unsigned int netcard_portlist[] __initdata = { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}; /* use 0 for production, 1 for verification, >2 for debug */ @@ -126,8 +127,8 @@ extern void chipset_init(struct device *dev, int startp); struct netdev_entry netcard_drv = {cardname, netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist}; #else -int -netcard_probe(struct device *dev) +__initfunc(int +netcard_probe(struct device *dev)) { int i; int base_addr = dev ? dev->base_addr : 0; @@ -154,7 +155,7 @@ netcard_probe(struct device *dev) * probes on the ISA bus. A good device probes avoids doing writes, and * verifies that the correct device exists and functions. */ -static int netcard_probe1(struct device *dev, int ioaddr) +__initfunc(static int netcard_probe1(struct device *dev, int ioaddr)) { static unsigned version_printed = 0; int i; diff --git a/drivers/net/soundmodem/sm.c b/drivers/net/soundmodem/sm.c index 777b5142f4cb..7d57dd6923e8 100644 --- a/drivers/net/soundmodem/sm.c +++ b/drivers/net/soundmodem/sm.c @@ -56,6 +56,7 @@ #include #include #include +#include #include "sm.h" /* --------------------------------------------------------------------- */ @@ -662,10 +663,7 @@ static int sm_ioctl(struct device *dev, struct ifreq *ifr, /* --------------------------------------------------------------------- */ -#ifdef MODULE -static -#endif /* MODULE */ -int sm_init(void) +__initfunc(int sm_init(void)) { int i, j, found = 0; char set_hw = 1; @@ -800,7 +798,7 @@ void cleanup_module(void) * modem: afsk1200, fsk9600 */ -void sm_setup(char *str, int *ints) +__initfunc(void sm_setup(char *str, int *ints)) { int i; diff --git a/drivers/net/wavelan.c b/drivers/net/wavelan.c index 0b18de7d9948..11e4a297c65e 100644 --- a/drivers/net/wavelan.c +++ b/drivers/net/wavelan.c @@ -64,8 +64,8 @@ wv_irq_to_psa(int irq) /* * Translate PSA irq parameter to irq number */ -static int -wv_psa_to_irq(u_char irqval) +__initfunc(static int +wv_psa_to_irq(u_char irqval)) { int irq; @@ -3999,8 +3999,8 @@ wavelan_close(device * dev) * device structure * (called by wavelan_probe() & via init_module()) */ -static int -wavelan_config(device * dev) +__initfunc(static int +wavelan_config(device * dev)) { u_long ioaddr = dev->base_addr; u_char irq_mask; @@ -4112,11 +4112,9 @@ wavelan_config(device * dev) * the initial value of dev->base_addr. * We follow the example in drivers/net/ne.c.) * (called in "Space.c") - * As this function is called outside the wavelan module, it should be - * declared extern, but it seem to cause troubles... */ -/* extern */ int -wavelan_probe(device * dev) +__initfunc(int +wavelan_probe(device * dev)) { short base_addr; mac_addr mac; /* Mac address (check wavelan existence) */ diff --git a/drivers/net/wavelan.p.h b/drivers/net/wavelan.p.h index 338ef1f6f81b..18320dcc4434 100644 --- a/drivers/net/wavelan.p.h +++ b/drivers/net/wavelan.p.h @@ -305,6 +305,7 @@ #include #include #include +#include #include /* Wireless extensions */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 8baf90212cf5..cebd4beef18a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -576,8 +577,8 @@ const char *pci_strdev(unsigned int vendor, unsigned int device) /* * Turn on/off PCI bridge optimization. This should allow benchmarking. */ -static void burst_bridge(unsigned char bus, unsigned char devfn, - unsigned char pos, int turn_on) +__initfunc(static void burst_bridge(unsigned char bus, unsigned char devfn, + unsigned char pos, int turn_on)) { #ifdef CONFIG_PCI_OPTIMIZE struct bridge_mapping_type *bmap; @@ -791,7 +792,7 @@ int get_pci_list(char *buf) * pci_malloc() returns initialized memory of size SIZE. Can be * used only while pci_init() is active. */ -static void *pci_malloc(long size, unsigned long *mem_startp) +__initfunc(static void *pci_malloc(long size, unsigned long *mem_startp)) { void *mem; @@ -805,7 +806,7 @@ static void *pci_malloc(long size, unsigned long *mem_startp) } -static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp) +__initfunc(static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp)) { unsigned int devfn, l, max; unsigned char cmd, tmp, hdr_type = 0; @@ -980,12 +981,12 @@ static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp) } -unsigned long pci_init (unsigned long mem_start, unsigned long mem_end) +__initfunc(unsigned long pci_init (unsigned long mem_start, unsigned long mem_end)) { mem_start = pcibios_init(mem_start, mem_end); if (!pcibios_present()) { - printk("pci_init: no BIOS32 detected\n"); + printk("pci_init: no PCI BIOS detected\n"); return mem_start; } diff --git a/drivers/sbus/audio/amd7930.c b/drivers/sbus/audio/amd7930.c index 388949d2184d..1134eb74ef9c 100644 --- a/drivers/sbus/audio/amd7930.c +++ b/drivers/sbus/audio/amd7930.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/sbus/audio/cs4231.c b/drivers/sbus/audio/cs4231.c index ecb09a4d757a..5c361a0b085d 100644 --- a/drivers/sbus/audio/cs4231.c +++ b/drivers/sbus/audio/cs4231.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h index 752bf748ce63..72a883cfc792 100644 --- a/drivers/sbus/char/vfc.h +++ b/drivers/sbus/char/vfc.h @@ -157,10 +157,16 @@ void vfc_unlock_device(struct vfc_dev *); #define VFC_STATUS_CAPTURE 0x08000000 -#ifdef VFC_DEBUG -#define VFC_DEBUG_PRINTK(a) printk a +#ifdef VFC_IOCTL_DEBUG +#define VFC_IOCTL_DEBUG_PRINTK(a) printk a #else -#define VFC_DEBUG_PRINTK(a) +#define VFC_IOCTL_DEBUG_PRINTK(a) +#endif + +#ifdef VFC_I2C_DEBUG +#define VFC_I2C_DEBUG_PRINTK(a) printk a +#else +#define VFC_I2C_DEBUG_PRINTK(a) #endif #endif /* _LINUX_VFC_H_ */ diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index 556d06e9f8f4..20e04258b8fd 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -3,11 +3,11 @@ * * Driver for the Videopix Frame Grabber. * - * In order to use the VFC you need to progeam the video controller + * In order to use the VFC you need to program the video controller * chip. This chip is the Phillips SAA9051. You need to call their * documentation ordering line to get the docs. * - * Their is very little documentation on the VFC itself. There is + * There is very little documentation on the VFC itself. There is * some useful info that can be found in the manuals that come with * the card. I will hopefully write some better docs at a later date. * @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -30,12 +31,11 @@ #include #include #include -#include #define VFC_MAJOR (60) #if 0 -#define VFC_DEBUG +#define VFC_IOCTL_DEBUG #endif #include "vfc.h" @@ -133,30 +133,27 @@ int init_vfc_devstruct(struct vfc_dev *dev, int instance) dev->control_reg=0; dev->poll_wait=NULL; dev->busy=0; - /* initialize the timer struct */ return 0; } int init_vfc_device(struct linux_sbus_device *sdev,struct vfc_dev *dev, int instance) { - struct linux_prom_registers reg; if(!dev) { printk(KERN_ERR "VFC: Bogus pointer passed\n"); return -ENOMEM; } printk("Initializing vfc%d\n",instance); dev->regs=NULL; - memcpy(®,&sdev->reg_addrs[0],sizeof(struct linux_prom_registers)); - prom_apply_sbus_ranges(sdev->my_bus, ®, sdev->num_registers, sdev); - dev->regs=sparc_alloc_io(reg.phys_addr, 0, + prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], sdev->num_registers, sdev); + dev->regs=sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, sizeof(struct vfc_regs), vfcstr, - reg.which_io, 0x0); - dev->which_io=reg.which_io; - dev->phys_regs=(struct vfc_regs *)reg.phys_addr; + sdev->reg_addrs[0].which_io, 0x0); + dev->which_io=sdev->reg_addrs[0].which_io; + dev->phys_regs=(struct vfc_regs *)sdev->reg_addrs[0].phys_addr; if(!dev->regs) return -EIO; printk("vfc%d: registers mapped at phys_addr: 0x%lx\n virt_addr: 0x%lx\n", - instance,(unsigned long)reg.phys_addr,(unsigned long)dev->regs); + instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs); if(init_vfc_devstruct(dev,instance)) return -EINVAL; if(init_vfc_hw(dev)) return -EIO; @@ -191,52 +188,58 @@ static int vfc_open(struct inode *inode, struct file *file) return 0; } -static int vfc_release(struct inode *inode,struct file *file) +static void vfc_release(struct inode *inode,struct file *file) { struct vfc_dev *dev; dev=vfc_get_dev_ptr(MINOR(inode->i_rdev)); - if(!dev) return -EINVAL; - if(!dev->busy) return 0; + if(!dev) return; + if(!dev->busy) return; dev->busy=0; MOD_DEC_USE_COUNT; - return 0; + return; } static int vfc_debug(struct vfc_dev *dev, int cmd, unsigned long arg) { struct vfc_debug_inout inout; unsigned char *buffer; + int ret; + + if(!suser()) return -EPERM; switch(cmd) { case VFC_I2C_SEND: - if(copy_from_user(&inout, (void *)arg, sizeof(inout))) + if(copy_from_user(&inout, (void *)arg, sizeof(inout))) { return -EFAULT; + } buffer = kmalloc(inout.len*sizeof(char), GFP_KERNEL); if (!buffer) return -ENOMEM; - if(copy_from_user(buffer, inout.buffer, inout.len*sizeof(char))) { - kfree_s(buffer,inout.len); + + if(copy_from_user(buffer, inout.buffer, + inout.len*sizeof(char));) { + kfree_s(buffer,inout.len*sizeof(char)); return -EFAULT; } + vfc_lock_device(dev); inout.ret= vfc_i2c_sendbuf(dev,inout.addr & 0xff, inout.buffer,inout.len); - if(copy_to_user((void *)arg,&inout,sizeof(inout))) { - kfree_s(buffer,inout.len); + + if (copy_to_user((void *)arg,&inout,sizeof(inout))) { + kfree_s(buffer, inout.len); return -EFAULT; } vfc_unlock_device(dev); - kfree_s(buffer, inout.len); - break; case VFC_I2C_RECV: - - if(copy_from_user(&inout, (void *)arg, sizeof(inout))) + if (copy_from_user(&inout, (void *)arg, sizeof(inout))) { return -EFAULT; + } buffer = kmalloc(inout.len, GFP_KERNEL); if (!buffer) @@ -248,11 +251,11 @@ static int vfc_debug(struct vfc_dev *dev, int cmd, unsigned long arg) ,buffer,inout.len); vfc_unlock_device(dev); - if(copy_to_user(inout.buffer, buffer, inout.len)) { + if (copy_to_user(inout.buffer, buffer, inout.len)) { kfree_s(buffer,inout.len); return -EFAULT; } - if(copy_to_user((void *)arg,&inout,sizeof(inout))) { + if (copy_to_user((void *)arg,&inout,sizeof(inout))) { kfree_s(buffer,inout.len); return -EFAULT; } @@ -306,12 +309,10 @@ static int vfc_set_control_ioctl(struct inode *inode, struct file *file, struct vfc_dev *dev, unsigned long arg) { int setcmd,ret=0; - if(copy_from_user(&setcmd,(void *)arg,sizeof(unsigned int))) + if (copy_from_user(&setcmd,(void *)arg,sizeof(unsigned int))) return -EFAULT; -#if 0 - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n", - dev->instance,setcmd)); -#endif + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n", + dev->instance,setcmd)); switch(setcmd) { case MEMPRST: vfc_lock_device(dev); @@ -359,13 +360,14 @@ int vfc_port_change_ioctl(struct inode *inode, struct file *file, { int ret=0; int cmd; + if(copy_from_user(&cmd, (void *)arg, sizeof(unsigned int))) { - VFC_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " "vfc_port_change_ioctl\n",dev->instance)); return -EFAULT; } - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n", + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n", dev->instance,cmd)); switch(cmd) { @@ -424,12 +426,12 @@ int vfc_set_video_ioctl(struct inode *inode, struct file *file, int ret=0; int cmd; if(copy_from_user(&cmd, (void *)arg, sizeof(unsigned int))) { - VFC_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " "vfc_set_video_ioctl\n",dev->instance)); - return -EFAULT; + return ret; } - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n", + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n", dev->instance,cmd)); switch(cmd) { @@ -490,12 +492,12 @@ int vfc_get_video_ioctl(struct inode *inode, struct file *file, else status=PAL_NOCOLOR; } - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; buf[0]=%x\n",dev->instance, + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; buf[0]=%x\n",dev->instance, status,buf[0])); - if(copy_to_user((void *)arg,&status,sizeof(unsigned int))) { - VFC_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " + if (copy_to_user((void *)arg,&status,sizeof(unsigned int))) { + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " "vfc_get_video_ioctl\n",dev->instance)); - return -EFAULT; + return ret; } return ret; } @@ -513,11 +515,13 @@ static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, switch(cmd & 0x0000ffff) { case VFCGCTRL: #if 0 - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n",dev->instance)); + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n",dev->instance)); #endif tmp=dev->regs->control; - if(copy_to_user((void *)arg,&tmp,sizeof(unsigned int))) - return -EFAULT; + if(copy_to_user((void *)arg,&tmp, sizeof(unsigned int))) { + ret=-EFAULT; + break; + } ret=0; break; case VFCSCTRL: @@ -530,12 +534,9 @@ static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ret=vfc_set_video_ioctl(inode,file,dev,arg); break; case VFCHUE: -#if 0 - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n",dev->instance)); -#endif - + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n",dev->instance)); if(copy_from_user(&tmp,(void *)arg,sizeof(unsigned int))) { - VFC_DEBUG_PRINTK(("vfc%d: User passed bogus pointer " + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer " "to IOCTL(VFCHUE)",dev->instance)); ret=-EFAULT; } else { @@ -549,7 +550,7 @@ static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, break; case VFCRDINFO: ret=-EINVAL; - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n",dev->instance)); + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n",dev->instance)); break; default: ret=vfc_debug(vfc_get_dev_ptr(MINOR(inode->i_rdev)), @@ -584,8 +585,9 @@ static int vfc_mmap(struct inode *inode, struct file *file, return 0; } -static long long vfc_lseek(struct inode *inode, struct file *file, - long long offset, int origin) + +static int vfc_lseek(struct inode *inode, struct file *file, + off_t offset, int origin) { return -ESPIPE; } @@ -595,14 +597,13 @@ static struct file_operations vfc_fops = { NULL, /* vfc_write */ NULL, /* vfc_read */ NULL, /* vfc_readdir */ - NULL, /* vfc_poll */ + NULL, /* vfc_select */ vfc_ioctl, vfc_mmap, vfc_open, vfc_release, }; - static int vfc_probe(void) { struct linux_sbus *bus; diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c index 952eb9875f18..68cfc44051f3 100644 --- a/drivers/sbus/char/vfc_i2c.c +++ b/drivers/sbus/char/vfc_i2c.c @@ -31,8 +31,8 @@ fairly certain that the flowcharts in the phillips docs are wrong. */ #include #include -#if 0 -#define VFC_DEBUG +#if 0 +#define VFC_I2C_DEBUG #endif #include "vfc.h" @@ -72,6 +72,8 @@ int vfc_pcf8584_init(struct vfc_dev *dev) void vfc_i2c_delay_wakeup(struct vfc_dev *dev) { + /* Used to profile code and eliminate too many delays */ + VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n",dev->instance)); wake_up(&dev->poll_wait); } @@ -95,14 +97,14 @@ void inline vfc_i2c_delay(struct vfc_dev *dev) int vfc_init_i2c_bus(struct vfc_dev *dev) { - dev->regs->i2c_s1= ENABLE_SERIAL | ACK; + dev->regs->i2c_s1= ENABLE_SERIAL | SELECT(S0) | ACK; vfc_i2c_reset_bus(dev); return 0; } int vfc_i2c_reset_bus(struct vfc_dev *dev) { - VFC_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", + VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", dev->instance)); if(!dev) return -EINVAL; if(!dev->regs) return -EINVAL; @@ -110,7 +112,7 @@ int vfc_i2c_reset_bus(struct vfc_dev *dev) dev->regs->i2c_s1=SEND_I2C_STOP | ACK; vfc_i2c_delay(dev); dev->regs->i2c_s1=CLEAR_I2C_BUS; - VFC_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", + VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", dev->instance, dev->regs->i2c_s1)); return 0; } @@ -146,7 +148,7 @@ int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode) { int ret,raddr; #if 1 - dev->regs->i2c_s1=SEND_I2C_STOP; + dev->regs->i2c_s1=SEND_I2C_STOP | ACK; dev->regs->i2c_s1=SELECT(S0) | ENABLE_SERIAL; vfc_i2c_delay(dev); #endif @@ -154,12 +156,12 @@ int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode) switch(mode) { case VFC_I2C_READ: dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr | 0x1); - VFC_DEBUG_PRINTK(("vfc%d: recieving from i2c addr 0x%x\n", + VFC_I2C_DEBUG_PRINTK(("vfc%d: recieving from i2c addr 0x%x\n", dev->instance,addr | 0x1)); break; case VFC_I2C_WRITE: dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr & ~0x1); - VFC_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", + VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", dev->instance,addr & ~0x1)); break; default: @@ -215,7 +217,7 @@ int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, int last) int ret; if(last) { dev->regs->i2c_reg=NEGATIVE_ACK; - VFC_DEBUG_PRINTK((KERN_DEBUG "vfc%d: sending negative ack\n", + VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n", dev->instance)); } else { dev->regs->i2c_s1=ACK; @@ -255,6 +257,8 @@ int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr, printk(KERN_ERR "vfc%d: " "VFC error while recieving byte\n", dev->instance); + dev->regs->i2c_s1=SEND_I2C_STOP; + ret=-EINVAL; } buf++; } @@ -286,7 +290,7 @@ int vfc_i2c_sendbuf(struct vfc_dev *dev, unsigned char addr, ret=vfc_i2c_xmit_byte(dev,buf); switch(ret) { case XMIT_LAST_BYTE: - VFC_DEBUG_PRINTK(("vfc%d: " + VFC_I2C_DEBUG_PRINTK(("vfc%d: " "Reciever ended transmission with " " %d bytes remaining\n", dev->instance,count)); diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index a8638cc97336..0290331cedc2 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -190,7 +191,7 @@ static void dma_stop (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, static int num_a2091 = 0; -int a2091_detect(Scsi_Host_Template *tpnt) +__initfunc(int a2091_detect(Scsi_Host_Template *tpnt)) { static unsigned char called = 0; struct Scsi_Host *instance; @@ -243,13 +244,11 @@ Scsi_Host_Template driver_template = A2091_SCSI; int a2091_release(struct Scsi_Host *instance) { #ifdef MODULE -DMA(instance)->CNTR = 0; -zorro_unconfig_board(instance->unique_id, 0); -if (--num_a2091 == 0) - free_irq(IRQ_AMIGA_PORTS, a2091_intr); -wd33c93_release(); + DMA(instance)->CNTR = 0; + zorro_unconfig_board(instance->unique_id, 0); + if (--num_a2091 == 0) + free_irq(IRQ_AMIGA_PORTS, a2091_intr); + wd33c93_release(); #endif -return 1; + return 1; } - - diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index 93aa6efa7aa3..fdc7fd41d229 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -166,7 +167,7 @@ static void dma_stop (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, } } -int a3000_detect(Scsi_Host_Template *tpnt) +__initfunc(int a3000_detect(Scsi_Host_Template *tpnt)) { static unsigned char called = 0; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 497b47f676a1..c77e5cd71f9e 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -323,7 +323,7 @@ typedef struct { static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */ -static void init_tags( void ) +__initfunc(static void init_tags( void )) { int target, lun; TAG_ALLOC *ta; @@ -665,7 +665,7 @@ static __inline__ void queue_main(void) } -static void NCR5380_all_init (void) +static inline void NCR5380_all_init (void) { static int done = 0; if (!done) { @@ -684,7 +684,7 @@ static void NCR5380_all_init (void) * Inputs : instance, pointer to this instance. Unused. */ -static void NCR5380_print_options (struct Scsi_Host *instance) +__initfunc(static void NCR5380_print_options (struct Scsi_Host *instance)) { printk(" generic options" #ifdef AUTOSENSE @@ -848,7 +848,7 @@ lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length) * */ -static void NCR5380_init (struct Scsi_Host *instance, int flags) +__initfunc(static void NCR5380_init (struct Scsi_Host *instance, int flags)) { int i; SETUP_HOSTDATA(instance); diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index d0de9dcdbf66..e846d38fa724 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -89,6 +89,7 @@ #include #include #include +#include #include #include @@ -765,7 +766,7 @@ int atari_scsi_release (struct Scsi_Host *sh) } #endif -void atari_scsi_setup( char *str, int *ints ) +__initfunc(void atari_scsi_setup( char *str, int *ints )) { /* Format of atascsi parameter is: * atascsi=,,,, @@ -869,7 +870,7 @@ int atari_scsi_reset( Scsi_Cmnd *cmd, unsigned int reset_flags) } -static void atari_scsi_reset_boot( void ) +__initfunc(static void atari_scsi_reset_boot( void )) { unsigned long end; diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 76da3403fb9a..165a68e60d2e 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -198,7 +199,7 @@ static void dma_stop (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, static int num_gvp11 = 0; -int gvp11_detect(Scsi_Host_Template *tpnt) +__initfunc(int gvp11_detect(Scsi_Host_Template *tpnt)) { static unsigned char called = 0; struct Scsi_Host *instance; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 919fb7f0f2a4..eb68d383bffb 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1047,7 +1047,7 @@ static int sd_init_onedisk(int i) spintime = 0; /* Spin up drives, as required. Only do this at boot time */ - if (!MODULE_FLAG){ + /* Spinup needs to be done for module loads too. */ do{ retries = 0; while(retries < 3) @@ -1120,7 +1120,6 @@ static int sd_init_onedisk(int i) else printk( "ready\n" ); } - } /* !MODULE_FLAG */ retries = 3; do { diff --git a/fs/affs/Changes b/fs/affs/Changes new file mode 100644 index 000000000000..a65dc326a7c2 --- /dev/null +++ b/fs/affs/Changes @@ -0,0 +1,95 @@ +(Note: I consider version numbers as cheap. That means +that I do not like numbers like 0.1 and the like for +things that can be used since quite some time. But +then, 3.1 doesn't mean 'perfectly stable', too.) + +Known bugs: +----------- + +- Doesn't work on the alpha. The only 64/32-bit + problem that I'm aware of (pointer/int conversion + in readdir()) gives compiler warnings but is + apparently not causing the failure, as directory + reads basically work (but all files are of size 0). + Alas, I've got no alpha to debug. :-( +- If an affs mounted filesystem is exported via + nfs, it cannot be written to. No networking to + test that, either. :-( + +Please direct bug reports to: hjw@zvw.de + +Version 3.4 +----------- + +- Hash chains are now sorted by block numbers. + (Thanks to Kars de Jong for finding this.) +- Removed all unnecessary external symbols. + +Version 3.3 +----------- + +- Tried to make all types 'correct' and consistent. +- Errors and warnings are now reported via a + function. They are all prefixed by a severity + and have the same appearance: + "AFFS: : " + (There's one exception to this, as in that function + is no pointer to the super block available.) +- The filesystem is remounted read-only after an + error. +- The names of newly created filesystem objects are + now checked for validity. +- Minor cleanups in comments. +- Added this Changes file. At last! + +Version 3.2 +----------- + +- Extension block cache: Reading/writing of huge files + (several MB) is much faster (of course the added + overhead slows down opening, but this is hardly + noticeable). +- The same get_block()-routine can now be used for + both OFS and FFS. +- The super block is now searched in the block that + was calculated and in the one following. This + should remedy the round-off error introduced by + the 1-k blocks that Linux uses. +- Minor changes to adhere to the new VFS interface. +- The number of used blocks is now also calculated + if the filesystem is mounted read-only. +- Prefixed some constants with AFFS_ to avoid name + clashes. +- Removed 'EXPERIMENTAL' status. + +Version 3.1 +----------- + +- Fixed a nasty bug which didn't allow read-only + mounts. +- Allow dir-cache filesystems to be mounted + read only. +- OFS support. +- Several other changes I just cannot remember + any more. + +Version 3.0 +----------- + +- Almost complete rewrite for the new VFS + interface in Linux 1.3. +- Write support. +- Support for hard and symbolic links. +- Lots of things I remeber even less ... + +Version 2.0 +----------- + +- Fixed a few things to get it compiled. +- Automatic root block calculation. +- Partition checker for genhd.c + +======================================== + +Let's just call Ray Burr's original affs +'Version 1.0'. diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 63d76a86ee3e..4afd66e49790 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -5,8 +5,10 @@ * * (C) 1993 Ray Burr - Amiga FFS filesystem. * + * Please send bug reports to: hjw@zvw.de */ +#include #include #include #include @@ -17,6 +19,8 @@ extern struct timezone sys_tz; +static char ErrorBuffer[256]; + /* * Functions for accessing Amiga-FFS structures. * @@ -28,7 +32,7 @@ extern struct timezone sys_tz; 0 is returned. Otherwise, the key number in the next used hash slot is returned. */ -int +static int affs_find_next_hash_entry(int hsize, void *dir_data, int *hash_pos) { struct dir_front *dir_front = dir_data; @@ -54,24 +58,23 @@ affs_get_file_name(int bsize, void *fh_data, char **name) file_end = GET_END_PTR(struct file_end, fh_data, bsize); if (file_end->file_name[0] == 0 || file_end->file_name[0] > 30) { - printk ("affs_get_file_name: OOPS! bad filename\n"); - printk (" file_end->file_name[0] = %d\n", + printk(KERN_WARNING "AFFS: bad filename (length=%d chars)\n", file_end->file_name[0]); *name = "***BAD_FILE***"; return 14; } - *name = (char *) &file_end->file_name[1]; + *name = (char *)&file_end->file_name[1]; return file_end->file_name[0]; } /* Find the predecessor in the hash chain */ int -affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey) +affs_fix_hash_pred(struct inode *startino, int startoffset, s32 key, s32 newkey) { struct buffer_head *bh = NULL; - int nextkey; - int ptype, stype; + s32 nextkey; + s32 ptype, stype; int retval; nextkey = startino->i_ino; @@ -87,14 +90,14 @@ affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey) || ptype != T_SHORT || (stype != ST_FILE && stype != ST_USERDIR && stype != ST_LINKFILE && stype != ST_LINKDIR && stype != ST_ROOT && stype != ST_SOFTLINK)) { - printk("AFFS: bad block found in link chain (ptype=%d, stype=%d)\n", - ptype,stype); + affs_error(startino->i_sb,"affs_fix_hash_pred", + "Bad block in link chain (ptype=%d, stype=%d)",ptype,stype); affs_brelse(bh); break; } - nextkey = htonl(((__u32 *)bh->b_data)[startoffset]); + nextkey = htonl(((s32 *)bh->b_data)[startoffset]); if (nextkey == key) { - ((__u32 *)bh->b_data)[startoffset] = newkey; + ((s32 *)bh->b_data)[startoffset] = newkey; affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5); mark_buffer_dirty(bh,1); affs_brelse(bh); @@ -112,13 +115,13 @@ affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey) /* Remove inode from link chain */ int -affs_fix_link_pred(struct inode *startino, int key, int newkey) +affs_fix_link_pred(struct inode *startino, s32 key, s32 newkey) { struct buffer_head *bh = NULL; - int nextkey; + s32 nextkey; int offset; - int etype = 0; - int ptype, stype; + s32 etype = 0; + s32 ptype, stype; int retval; offset = AFFS_I2BSIZE(startino) / 4 - 10; @@ -150,7 +153,7 @@ affs_fix_link_pred(struct inode *startino, int key, int newkey) retval = -EPERM; break; } - nextkey = htonl(((__u32 *)bh->b_data)[offset]); + nextkey = htonl(((s32 *)bh->b_data)[offset]); if (nextkey == key) { FILE_END(bh->b_data,startino)->link_chain = newkey; affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5); @@ -172,17 +175,17 @@ affs_fix_link_pred(struct inode *startino, int key, int newkey) (which lets us calculate the block size). Returns non-zero if the block is not consistent. */ -__u32 -affs_checksum_block(int bsize, void *data, int *ptype, int *stype) +u32 +affs_checksum_block(int bsize, void *data, s32 *ptype, s32 *stype) { - __u32 sum; - __u32 *p; + u32 sum; + u32 *p; bsize /= 4; if (ptype) - *ptype = htonl(((__s32 *)data)[0]); + *ptype = htonl(((s32 *)data)[0]); if (stype) - *stype = htonl(((__s32 *)data)[bsize - 1]); + *stype = htonl(((s32 *)data)[bsize - 1]); sum = 0; p = data; @@ -194,20 +197,20 @@ affs_checksum_block(int bsize, void *data, int *ptype, int *stype) void affs_fix_checksum(int bsize, void *data, int cspos) { - __u32 ocs; - __u32 cs; + u32 ocs; + u32 cs; cs = affs_checksum_block(bsize,data,NULL,NULL); - ocs = htonl (((__u32 *)data)[cspos]); + ocs = htonl (((u32 *)data)[cspos]); ocs -= cs; - ((__u32 *)data)[cspos] = htonl(ocs); + ((u32 *)data)[cspos] = htonl(ocs); } void -secs_to_datestamp(int secs, struct DateStamp *ds) +secs_to_datestamp(time_t secs, struct DateStamp *ds) { - __u32 days; - __u32 minute; + u32 days; + u32 minute; secs -= sys_tz.tz_minuteswest * 60 +((8 * 365 + 2) * 24 * 60 * 60); if (secs < 0) @@ -223,7 +226,7 @@ secs_to_datestamp(int secs, struct DateStamp *ds) } int -prot_to_mode(__u32 prot) +prot_to_mode(u32 prot) { int mode = 0; @@ -249,10 +252,10 @@ prot_to_mode(__u32 prot) return mode; } -unsigned int +u32 mode_to_prot(int mode) { - unsigned int prot = 0; + u32 prot = 0; if (mode & S_IXUSR) prot |= FIBF_SCRIPT; @@ -271,3 +274,32 @@ mode_to_prot(int mode) return prot; } + +void +affs_error(struct super_block *sb, const char *function, const char *fmt, ...) +{ + va_list args; + + va_start(args,fmt); + vsprintf(ErrorBuffer,fmt,args); + va_end(args); + + printk(KERN_CRIT "AFFS error (device %s): %s(): %s\n",kdevname(sb->s_dev), + function,ErrorBuffer); + if (!(sb->s_flags & MS_RDONLY)) + printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n"); + sb->s_flags |= MS_RDONLY; +} + +void +affs_warning(struct super_block *sb, const char *function, const char *fmt, ...) +{ + va_list args; + + va_start(args,fmt); + vsprintf(ErrorBuffer,fmt,args); + va_end(args); + + printk(KERN_WARNING "AFFS error (device %s): %s(): %s\n",kdevname(sb->s_dev), + function,ErrorBuffer); +} diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c index 1d69d5a3d3a8..658bbdaf1f76 100644 --- a/fs/affs/bitmap.c +++ b/fs/affs/bitmap.c @@ -3,7 +3,6 @@ * * (c) 1996 Hans-Joachim Widmaier * - * * bitmap.c contains the code that handles all bitmap related stuff - * block allocation, deallocation, calculation of free space. */ @@ -54,7 +53,7 @@ affs_count_free_blocks(struct super_block *s) } void -affs_free_block(struct super_block *sb, int block) +affs_free_block(struct super_block *sb, s32 block) { int bmap; int bit; @@ -70,7 +69,7 @@ affs_free_block(struct super_block *sb, int block) zone_no = (bmap << (sb->s_blocksize_bits - 7)) + bit / 1024; bm = &sb->u.affs_sb.s_bitmap[bmap]; if (bmap >= sb->u.affs_sb.s_bm_count) { - printk("AFFS: free_block(): block %d outside partition.\n",block); + affs_error(sb,"affs_free_block","Block %d outside partition",block); return; } blk = 0; @@ -83,15 +82,16 @@ affs_free_block(struct super_block *sb, int block) if (!bm->bm_bh) { bm->bm_count--; unlock_super(sb); - printk("AFFS: free_block(): Cannot read bitmap block %d\n",bm->bm_key); + affs_error(sb,"affs_free_block","Cannot read bitmap block %d",bm->bm_key); return; } } if (set_bit(bit ^ BO_EXBITS,bm->bm_bh->b_data + 4)) - printk("AFFS: free_block(): block %d is already free.\n",block); + affs_warning(sb,"affs_free_block","Trying to free block %d which is already free", + block); else { sb->u.affs_sb.s_alloc[zone_no].az_free++; - ((__u32 *)bm->bm_bh->b_data)[0] = ntohl(htonl(((__u32 *)bm->bm_bh->b_data)[0]) - blk); + ((u32 *)bm->bm_bh->b_data)[0] = ntohl(htonl(((u32 *)bm->bm_bh->b_data)[0]) - blk); mark_buffer_dirty(bm->bm_bh,1); sb->s_dirt = 1; } @@ -102,15 +102,15 @@ affs_free_block(struct super_block *sb, int block) unlock_super(sb); } -static int +static s32 affs_balloc(struct inode *inode, int zone_no) { - __u32 w; - __u32 *bm; + u32 w; + u32 *bm; int fb; int i; int fwb; - int block; + s32 block; struct affs_zone *zone; struct affs_alloc_zone *az; struct super_block *sb; @@ -124,7 +124,7 @@ affs_balloc(struct inode *inode, int zone_no) pr_debug("AFFS: balloc(inode=%lu,zone=%d)\n",inode->i_ino,zone_no); az = &sb->u.affs_sb.s_alloc[zone->z_az_no]; - bm = (__u32 *)zone->z_bm->bm_bh->b_data; + bm = (u32 *)zone->z_bm->bm_bh->b_data; repeat: for (i = zone->z_start; i < zone->z_end; i++) { if (bm[i]) @@ -140,7 +140,7 @@ found: fb = find_first_zero_bit(&w,32); if (fb > 31 || !clear_bit(fb ^ BO_EXBITS,&bm[i])) { unlock_super(sb); - printk("AFFS: balloc(): empty block disappeared somehow\n"); + affs_warning(sb,"balloc","Empty block disappeared somehow"); goto repeat; } block = fwb + fb; @@ -154,7 +154,7 @@ found: if (fb > 31) break; if (!clear_bit(fb ^ BO_EXBITS,&bm[i])) { - printk("AFFS: balloc(): empty block disappeared\n"); + affs_warning(sb,"balloc","Empty block disappeared somehow"); break; } inode->u.affs_i.i_data[inode->u.affs_i.i_pa_last++] = fwb + fb; @@ -204,7 +204,7 @@ affs_find_new_zone(struct super_block *sb, int zone_no) if (az->az_count) az->az_count--; else - printk("AFFS: find_new_zone(): az_count=0, but bm used\n"); + affs_error(sb,"find_new_zone","az_count=0, but bm used"); } while (1) { @@ -247,7 +247,7 @@ affs_find_new_zone(struct super_block *sb, int zone_no) bm->bm_count--; az->az_count--; unlock_super(sb); - printk("AFFS: find_new_zone(): Cannot read bitmap\n"); + affs_error(sb,"find_new_zone","Cannot read bitmap"); return 0; } zone->z_bm = bm; @@ -261,16 +261,16 @@ affs_find_new_zone(struct super_block *sb, int zone_no) return az->az_free; } -int +s32 affs_new_header(struct inode *inode) { - int block; + s32 block; struct buffer_head *bh; pr_debug("AFFS: new_header(ino=%lu)\n",inode->i_ino); if (!(block = affs_balloc(inode,0))) { - while(affs_find_new_zone(inode->i_sb,0)) { + while (affs_find_new_zone(inode->i_sb,0)) { if ((block = affs_balloc(inode,0))) goto init_block; schedule(); @@ -279,7 +279,7 @@ affs_new_header(struct inode *inode) } init_block: if (!(bh = getblk(inode->i_dev,block,AFFS_I2BSIZE(inode)))) { - printk("AFFS: balloc(): cannot read block %d\n",block); + affs_error(inode->i_sb,"new_header","Cannot read block %d",block); return 0; } memset(bh->b_data,0,AFFS_I2BSIZE(inode)); @@ -290,7 +290,7 @@ init_block: return block; } -int +s32 affs_new_data(struct inode *inode) { int empty, old; @@ -299,7 +299,7 @@ affs_new_data(struct inode *inode) struct super_block *sb; struct buffer_head *bh; int i = 0; - int block; + s32 block; pr_debug("AFFS: new_data(ino=%lu)\n",inode->i_ino); @@ -345,7 +345,7 @@ affs_new_data(struct inode *inode) found: zone = &sb->u.affs_sb.s_zones[i]; if (!(block = affs_balloc(inode,i))) { /* No data zones left */ - while(affs_find_new_zone(sb,i)) { + while (affs_find_new_zone(sb,i)) { if ((block = affs_balloc(inode,i))) goto init_block; schedule(); @@ -357,7 +357,7 @@ found: init_block: if (!(bh = getblk(inode->i_dev,block,sb->s_blocksize))) { - printk("AFFS: balloc(): cannot read block %u\n",block); + affs_error(inode->i_sb,"new_data","Cannot read block %d",block); return 0; } memset(bh->b_data,0,sb->s_blocksize); diff --git a/fs/affs/dir.c b/fs/affs/dir.c index f7ec42edeb95..8ae71e5bdf59 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -64,7 +64,7 @@ struct inode_operations affs_dir_inode_operations = { }; static long -affs_dir_read(struct inode * inode, struct file * filp, char * buf, unsigned long count) +affs_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count) { return -EISDIR; } @@ -73,19 +73,18 @@ static int affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t filldir) { int j, namelen; - int i; + s32 i; int hash_pos; int chain_pos; unsigned long ino; unsigned long old; - int stored; - char *name; - struct buffer_head *dir_bh; - struct buffer_head *fh_bh; - struct inode *dir; + int stored; + char *name; + struct buffer_head *dir_bh; + struct buffer_head *fh_bh; + struct inode *dir; pr_debug("AFFS: readdir(ino=%ld,f_pos=%lu)\n",inode->i_ino,filp->f_pos); - if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; @@ -122,7 +121,7 @@ affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t fil chain_pos = (filp->f_pos - 2) & 0xffff; hash_pos = (filp->f_pos - 2) >> 16; if (chain_pos == 0xffff) { - printk("AFFS: more than 65535 entries in chain\n"); + affs_warning(inode->i_sb,"readdir","More than 65535 entries in chain"); chain_pos = 0; hash_pos++; filp->f_pos = ((hash_pos << 16) | chain_pos) + 2; @@ -143,15 +142,15 @@ affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t fil * we can jump directly to where we left off. */ if (filp->private_data && filp->f_version == dir->i_version) { - i = (int)filp->private_data; + i = (s32)filp->private_data; j = 0; pr_debug("AFFS: readdir() left off=%d\n",i); } filp->f_version = dir->i_version; - pr_debug("AFFS: hash_pos=%lu chain_pos=%lu\n", hash_pos, chain_pos); + pr_debug("AFFS: hash_pos=%d chain_pos=%d\n",hash_pos,chain_pos); while (i) { if (!(fh_bh = affs_bread(inode->i_dev,i,AFFS_I2BSIZE(inode)))) { - printk("AFFS: readdir: Can't get block %d\n",i); + affs_error(inode->i_sb,"readdir","Cannot read block %d",i); goto readdir_done; } ino = i; @@ -164,7 +163,7 @@ affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t fil } if (fh_bh) { namelen = affs_get_file_name(AFFS_I2BSIZE(inode),fh_bh->b_data,&name); - pr_debug("AFFS: readdir(): filldir(..,\"%.*s\",ino=%lu), i=%lu\n", + pr_debug("AFFS: readdir(): filldir(..,\"%.*s\",ino=%lu), i=%d\n", namelen,name,ino,i); filp->private_data = (void *)ino; if (filldir(dirent,name,namelen,filp->f_pos,ino) < 0) diff --git a/fs/affs/file.c b/fs/affs/file.c index a450dffce502..0fffbf41e413 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -35,6 +35,8 @@ #error PAGE_SIZE must be at least 4096 #endif +static int affs_bmap(struct inode *inode, int block); +static struct buffer_head * affs_getblock(struct inode *inode, s32 block); static long affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned long count); static long affs_file_write(struct inode *inode, struct file *filp, const char *buf, @@ -200,7 +202,7 @@ index_to_seqnum(int index) return 128 + 192 * 2 + 128 * 4 + 64 * 16 + 32 * 64 + 64 * 256 + (index << 9); } -static int __inline__ +static s32 __inline__ calc_key(struct inode *inode, int *ext) { int index; @@ -226,28 +228,30 @@ calc_key(struct inode *inode, int *ext) return inode->u.affs_i.i_ec->ec[index]; } -int +static int affs_bmap(struct inode *inode, int block) { struct buffer_head *bh; - int ext, key, nkey; - int ptype, stype; + s32 key, nkey; + s32 ptype, stype; + int ext; int index; int keycount; struct key_cache *kc; struct key_cache *tkc; struct timeval tv; - __s32 *keyp; + s32 *keyp; int i; pr_debug("AFFS: bmap(%lu,%d)\n",inode->i_ino,block); if (block < 0) { - printk("affs_bmap: block < 0\n"); + affs_error(inode->i_sb,"bmap","Block < 0"); return 0; } if (!inode->u.affs_i.i_ec) { - printk("affs_bmap(): No ext_cache!?\n"); + affs_error(inode->i_sb,"bmap","No extension cache for open file (inode=%lu)", + inode->i_ino); return 0; } @@ -334,14 +338,14 @@ affs_bmap(struct inode *inode, int block) return key; } -struct buffer_head * -affs_getblock(struct inode *inode, int block) +static struct buffer_head * +affs_getblock(struct inode *inode, s32 block) { struct buffer_head *bh; struct buffer_head *ebh; struct buffer_head *pbh; struct key_cache *kc; - int key, nkey; + s32 key, nkey; int ext; int cf, j, pt; int index; @@ -372,7 +376,7 @@ affs_getblock(struct inode *inode, int block) return NULL; if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cf,&j) || cf != pt || j != ST_FILE) { - printk("AFFS: getblock(): inode %d is not a valid %s\n",key, + affs_error(inode->i_sb,"getblock","Inode %d is not a valid %s",key, pt == T_SHORT ? "file header" : "extension block"); affs_brelse(bh); return NULL; @@ -387,7 +391,8 @@ affs_getblock(struct inode *inode, int block) else pbh = affs_getblock(inode,inode->u.affs_i.i_lastblock); if (!pbh) { - printk("AFFS: getblock(): cannot get last block in file\n"); + affs_error(inode->i_sb,"getblock", + "Cannot get last block in file"); break; } } @@ -397,7 +402,7 @@ affs_getblock(struct inode *inode, int block) lock_super(inode->i_sb); if (AFFS_BLOCK(bh->b_data,inode,j)) { unlock_super(inode->i_sb); - printk("AFFS: getblock(): block already allocated\n"); + affs_warning(inode->i_sb,"getblock","Block already allocated"); affs_free_block(inode->i_sb,nkey); j++; continue; @@ -407,7 +412,8 @@ affs_getblock(struct inode *inode, int block) if (ofs) { ebh = affs_bread(inode->i_dev,nkey,AFFS_I2BSIZE(inode)); if (!ebh) { - printk("AFFS: getblock(): cannot get block %d\n",nkey); + affs_error(inode->i_sb,"getblock", + "Cannot get block %d",nkey); affs_free_block(inode->i_sb,nkey); AFFS_BLOCK(bh->b_data,inode,j) = 0; break; @@ -492,10 +498,6 @@ affs_getblock(struct inode *inode, int block) return affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); } -/* This could be made static, regardless of what the former comment said. - * You cannot directly read affs directories. - */ - static long affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned long count) { @@ -508,12 +510,12 @@ affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned l pr_debug("AFFS: file_read_ofs(ino=%lu,pos=%lu,%d)\n",inode->i_ino,(long)filp->f_pos,count); if (!inode) { - printk("affs_file_read: inode = NULL\n"); + affs_error(inode->i_sb,"file_read_ofs","Inode = NULL"); return -EINVAL; } blocksize = AFFS_I2BSIZE(inode) - 24; if (!(S_ISREG(inode->i_mode))) { - pr_debug("affs_file_read: mode = %07o\n",inode->i_mode); + pr_debug("affs_file_read: mode = %07o",inode->i_mode); return -EINVAL; } if (filp->f_pos >= inode->i_size || count <= 0) @@ -524,10 +526,10 @@ affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned l left = MIN (inode->i_size - filp->f_pos,count - (buf - start)); if (!left) break; - sector = affs_bmap(inode,(__u32)filp->f_pos / blocksize); + sector = affs_bmap(inode,(u32)filp->f_pos / blocksize); if (!sector) break; - offset = (__u32)filp->f_pos % blocksize; + offset = (u32)filp->f_pos % blocksize; bh = affs_bread(inode->i_dev,sector,AFFS_I2BSIZE(inode)); if (!bh) break; @@ -554,25 +556,31 @@ affs_file_write(struct inode *inode, struct file *filp, const char *buf, unsigne struct inode *ino; char *p; + /* Not that I wanted to be POSIX compliant ... */ + if (!count) + return 0; pr_debug("AFFS: file_write(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino, (unsigned long)filp->f_pos,count); ino = NULL; if (!inode) { - printk("AFFS: file_write(): inode=NULL\n"); + affs_error(inode->i_sb,"file_write","Inode = NULL"); return -EINVAL; } if (inode->u.affs_i.i_original) { ino = iget(inode->i_sb,inode->u.affs_i.i_original); if (!ino) { - printk("AFFS: could not follow link from inode %lu to %d\n", - inode->i_ino,inode->u.affs_i.i_original); + affs_error(inode->i_sb,"file_write", + "Could not follow link from inode %lu to %d", + inode->i_ino,inode->u.affs_i.i_original); return -EINVAL; } inode = ino; } if (!S_ISREG(inode->i_mode)) { - printk("AFFS: file_write(): mode=%07o\n",inode->i_mode); + affs_error(inode->i_sb,"file_write", + "Trying to write to non-regular file (mode=%07o)", + inode->i_mode); iput(inode); return -EINVAL; } @@ -636,22 +644,27 @@ affs_file_write_ofs(struct inode *inode, struct file *filp, const char *buf, uns pr_debug("AFFS: file_write_ofs(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino, (unsigned long)filp->f_pos,count); + if (!count) + return 0; if (!inode) { - printk("AFFS: file_write_ofs(): inode=NULL\n"); + affs_error(inode->i_sb,"file_write_ofs","Inode = NULL"); return -EINVAL; } ino = NULL; if (inode->u.affs_i.i_original) { ino = iget(inode->i_sb,inode->u.affs_i.i_original); if (!ino) { - printk("AFFS: could not follow link from inode %lu to %d\n", - inode->i_ino,inode->u.affs_i.i_original); + affs_error(inode->i_sb,"file_write_ofs", + "Could not follow link from inode %lu to %d", + inode->i_ino,inode->u.affs_i.i_original); return -EINVAL; } inode = ino; } if (!S_ISREG(inode->i_mode)) { - printk("AFFS: file_write_ofs(): mode=%07o\n",inode->i_mode); + affs_error(inode->i_sb,"file_write_ofs", + "Trying to write to non-regular file (mode=%07o)", + inode->i_mode); iput(inode); return -EINVAL; } @@ -714,10 +727,10 @@ affs_truncate(struct inode *inode) struct affs_zone *zone; int first; int block; - int key; - int *keyp; - int ekey; - int ptype, stype; + s32 key; + s32 *keyp; + s32 ekey; + s32 ptype, stype; int freethis; int blocksize; int rem; @@ -729,8 +742,8 @@ affs_truncate(struct inode *inode) if (inode->u.affs_i.i_original) { ino = iget(inode->i_sb,inode->u.affs_i.i_original); if (!ino) { - printk("AFFS: truncate(): cannot follow link from %lu to %u\n", - inode->i_ino,inode->u.affs_i.i_original); + affs_error(inode->i_sb,"truncate","Cannot follow link from %lu to %d", + inode->i_ino,inode->u.affs_i.i_original); return; } inode = ino; @@ -754,7 +767,7 @@ affs_truncate(struct inode *inode) unlock_super(inode->i_sb); } if (!bh) { - printk("AFFS: truncate(): Cannot extend file\n"); + affs_error(inode->i_sb,"truncate","Cannot extend file"); inode->i_size = blocksize * (inode->u.affs_i.i_lastblock + 1); } else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) { rem = inode->i_size % blocksize; @@ -771,7 +784,7 @@ affs_truncate(struct inode *inode) while (ekey) { if (!(bh = affs_bread(inode->i_dev,ekey,AFFS_I2BSIZE(inode)))) { - printk("AFFS: truncate(): Can't read block %d\n",ekey); + affs_error(inode->i_sb,"truncate","Cannot read block %d",ekey); break; } ptype = htonl(((struct file_front *)bh->b_data)->primary_type); @@ -783,14 +796,14 @@ affs_truncate(struct inode *inode) break; } if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) { - printk("AFFS: truncate(): bad block (ptype=%d, stype=%d)\n", - ptype,stype); + affs_error(inode->i_sb,"truncate","Bad block (ptype=%d, stype=%d)", + ptype,stype); affs_brelse(bh); break; } /* Do not throw away file header */ freethis = first == 0 && ekey != inode->i_ino; - for ( block = first; block < AFFS_I2HSIZE(inode); block++) { + for (block = first; block < AFFS_I2HSIZE(inode); block++) { keyp = &AFFS_BLOCK(bh->b_data,inode,block); key = htonl(*keyp); if (key) { @@ -853,7 +866,7 @@ static int affs_open_file(struct inode *inode, struct file *filp) { int error; - int key; + u32 key; int i; pr_debug("AFFS: open_file(ino=%lu)\n",inode->i_ino); @@ -864,7 +877,7 @@ affs_open_file(struct inode *inode, struct file *filp) if (!inode->u.affs_i.i_ec) { inode->u.affs_i.i_ec = (struct ext_cache *)get_free_page(GFP_KERNEL); if (!inode->u.affs_i.i_ec) { - printk("AFFS: cache allocation failed\n"); + affs_error(inode->i_sb,"open_file","Cache allocation failed"); error = ENOMEM; } else { /* We only have to initialize non-zero values. diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 9b6626f7da20..654a8ca61b6e 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -30,12 +30,26 @@ #include #include +/* AmigaOS allows file names with up to 30 characters length. + * Names longer than that will be silently truncated. If you + * want to disallow this, comment out the following #define. + * Creating filesystem objects with longer names will then + * result in an error (ENAMETOOLONG). + */ +/*#define NO_TRUNCATE */ + extern int *blk_size[]; extern struct timezone sys_tz; #define MIN(a,b) (((a)<(b))?(a):(b)) -void +static int affs_notify_change(struct inode *inode, struct iattr *attr); +static void affs_put_inode(struct inode *inode); +static void affs_read_inode(struct inode *inode); +static void affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static void affs_write_inode(struct inode *inode); + +static void affs_put_super(struct super_block *sb) { int i; @@ -110,13 +124,13 @@ static struct super_operations affs_sops = { NULL /* remount */ }; -int +unsigned long affs_parent_ino(struct inode *dir) { int root_ino = (dir->i_sb->u.affs_sb.s_root_block); if (!S_ISDIR (dir->i_mode)) { - printk ("affs_parent_ino: argument is not a directory\n"); + affs_error(dir->i_sb,"parent_ino","Trying to get parent of non-directory"); return root_ino; } if (dir->i_ino == root_ino) @@ -125,7 +139,7 @@ affs_parent_ino(struct inode *dir) } static int -parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, int *root, +parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root, int *blocksize, char **prefix, char *volume, unsigned long *mount_opts) { char *this_char, *value; @@ -150,14 +164,14 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i *value++ = 0; if (!strcmp(this_char,"protect")) { if (value) { - printk("AFFS: option protect does not take an argument\n"); + printk("AFFS: Option protect does not take an argument\n"); return 0; } *mount_opts |= SF_IMMUTABLE; } else if (!strcmp(this_char,"verbose")) { if (value) { - printk("AFFS: option verbose does not take an argument\n"); + printk("AFFS: Option verbose does not take an argument\n"); return 0; } *mount_opts |= SF_VERBOSE; @@ -166,7 +180,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i if (!value) *uid = current->uid; else if (!*value) { - printk("AFFS: argument for uid option missing\n"); + printk("AFFS: Argument for uid option missing\n"); return 0; } else { *uid = simple_strtoul(value,&value,0); @@ -180,7 +194,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i if (!value) *gid = current->gid; else if (!*value) { - printk("AFFS: argument for gid option missing\n"); + printk("AFFS: Argument for gid option missing\n"); return 0; } else { *gid = simple_strtoul(value,&value,0); @@ -248,7 +262,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i return 0; if (*blocksize != 512 && *blocksize != 1024 && *blocksize != 2048 && *blocksize != 4096) { - printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed).\n"); + printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n"); return 0; } } @@ -270,21 +284,21 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i * hopefully have the guts to do so. Until then: sorry for the mess. */ -struct super_block * +static struct super_block * affs_read_super(struct super_block *s,void *data, int silent) { struct buffer_head *bh = NULL; struct buffer_head *bb; kdev_t dev = s->s_dev; - int root_block; + s32 root_block; int size; - __u32 chksum; - __u32 *bm; - int ptype, stype; + u32 chksum; + u32 *bm; + s32 ptype, stype; int mapidx; int num_bm; int i, j; - int key; + s32 key; int blocksize; uid_t uid; gid_t gid; @@ -300,7 +314,7 @@ affs_read_super(struct super_block *s,void *data, int silent) if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, &blocksize,&s->u.affs_sb.s_prefix,s->u.affs_sb.s_volume,&mount_flags)) { s->s_dev = 0; - printk("AFFS: error parsing options.\n"); + printk(KERN_ERR "AFFS: Error parsing options\n"); MOD_DEC_USE_COUNT; return NULL; } @@ -324,13 +338,13 @@ affs_read_super(struct super_block *s,void *data, int silent) if (size == 0) { s->s_dev = 0; unlock_super(s); - printk("affs_read_super: could not determine device size\n"); + printk(KERN_ERR "AFFS: Could not determine device size\n"); goto out; } s->u.affs_sb.s_partition_size = size; s->u.affs_sb.s_reserved = reserved; - /* Try to find root block. Its location may depend on the block size. */ + /* Try to find root block. Its location depends on the block size. */ s->u.affs_sb.s_hashsize = 0; if (blocksize > 0) { @@ -358,12 +372,12 @@ affs_read_super(struct super_block *s,void *data, int silent) * block behind the calculated one. So we check this one, too. */ for (num_bm = 0; num_bm < 2; num_bm++) { - pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %d, " + pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %u, " "size=%d blocks, %d reserved\n",kdevname(dev),blocksize, s->u.affs_sb.s_root_block + num_bm,size,reserved); bh = affs_bread(dev,s->u.affs_sb.s_root_block + num_bm,blocksize); if (!bh) { - printk("AFFS: unable to read root block\n"); + printk(KERN_ERR "AFFS: Cannot read root block\n"); goto out; } if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) && @@ -383,7 +397,8 @@ affs_read_super(struct super_block *s,void *data, int silent) if (!key) { affs_brelse(bh); if (!silent) - printk("AFFS: Can't find a valid root block on device %s\n",kdevname(dev)); + printk(KERN_ERR "AFFS: Cannot find a valid root block on device %s\n", + kdevname(dev)); goto out; } root_block = s->u.affs_sb.s_root_block; @@ -396,7 +411,7 @@ affs_read_super(struct super_block *s,void *data, int silent) /* Find out which kind of FS we have */ bb = affs_bread(dev,0,s->s_blocksize); if (bb) { - chksum = htonl(*(__u32 *)bb->b_data); + chksum = htonl(*(u32 *)bb->b_data); /* Dircache filesystems are compatible with non-dircache ones * when reading. As long as they aren't supported, writing is @@ -404,7 +419,8 @@ affs_read_super(struct super_block *s,void *data, int silent) */ if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS || chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) { - printk("AFFS: Dircache FS - mounting %s read only.\n",kdevname(dev)); + printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n", + kdevname(dev)); s->s_flags |= MS_RDONLY; } switch (chksum) { @@ -436,22 +452,22 @@ affs_read_super(struct super_block *s,void *data, int silent) s->u.affs_sb.s_flags |= SF_INTL | SF_OFS; break; default: - printk("AFFS: Unknown filesystem on device %s: %08X\n", - kdevname(dev),chksum); + printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n", + kdevname(dev),chksum); affs_brelse(bb); goto out; } affs_brelse(bb); } else { - printk("AFFS: Can't get boot block.\n"); + printk(KERN_ERR "AFFS: Cannot read boot block\n"); goto out; } if (mount_flags & SF_VERBOSE) { chksum = ntohl(chksum); - printk("AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", - GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0], - &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1], - (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); + printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", + GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0], + &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1], + (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); } s->s_magic = AFFS_SUPER_MAGIC; @@ -459,7 +475,7 @@ affs_read_super(struct super_block *s,void *data, int silent) /* Keep super block in cache */ if (!(s->u.affs_sb.s_root_bh = affs_bread(dev,root_block,s->s_blocksize))) { - printk("AFFS: Can't read root block a second time\n"); + printk(KERN_ERR "AFFS: Cannot read root block\n"); goto out; } @@ -473,7 +489,7 @@ affs_read_super(struct super_block *s,void *data, int silent) MAX_ZONES * sizeof(struct affs_zone); pr_debug("num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype); if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype,GFP_KERNEL))) { - printk("AFFS: Not enough memory.\n"); + printk(KERN_ERR "AFFS: Not enough memory\n"); goto out; } memset(s->u.affs_sb.s_bitmap,0,ptype); @@ -486,7 +502,8 @@ affs_read_super(struct super_block *s,void *data, int silent) if (ROOT_END_S(bh->b_data,s)->bm_flag == 0) { if (!(s->s_flags & MS_RDONLY)) { - printk("AFFS: Bitmap invalid - mounting %s read only.\n",kdevname(dev)); + printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n", + kdevname(dev)); s->s_flags |= MS_RDONLY; } affs_brelse(bh); @@ -504,17 +521,17 @@ affs_read_super(struct super_block *s,void *data, int silent) offset = s->u.affs_sb.s_reserved; az_no = 0; while (bh) { - bm = (__u32 *)bh->b_data; + bm = (u32 *)bh->b_data; for (i = ptype; i < stype && bm[i]; i++, mapidx++) { if (mapidx >= num_bm) { - printk("AFFS: Not enough bitmap space!?\n"); + printk(KERN_ERR "AFFS: Not enough bitmap space!?\n"); goto out; } bb = affs_bread(s->s_dev,htonl(bm[i]),s->s_blocksize); if (bb) { if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) && !(s->s_flags & MS_RDONLY)) { - printk("AFFS: Bitmap (%d,key=%lu) invalid - " + printk(KERN_WARNING "AFFS: Bitmap (%d,key=%lu) invalid - " "mounting %s read only.\n",mapidx,htonl(bm[i]), kdevname(dev)); s->s_flags |= MS_RDONLY; @@ -525,7 +542,7 @@ affs_read_super(struct super_block *s,void *data, int silent) key = size & 0x1F; /* used bits */ if (key) { chksum = ntohl(0x7FFFFFFF >> (31 - key)); - ((__u32 *)bb->b_data)[ptype] &= chksum; + ((u32 *)bb->b_data)[ptype] &= chksum; affs_fix_checksum(s->s_blocksize,bb->b_data,0); mark_buffer_dirty(bb,1); } @@ -551,7 +568,7 @@ affs_read_super(struct super_block *s,void *data, int silent) } affs_brelse(bb); } else { - printk("AFFS: Can't read bitmap.\n"); + printk(KERN_ERR "AFFS: Cannot read bitmap\n"); goto out; } } @@ -561,14 +578,14 @@ affs_read_super(struct super_block *s,void *data, int silent) affs_brelse(bh); if (key) { if (!(bh = affs_bread(s->s_dev,key,s->s_blocksize))) { - printk("AFFS: Can't read bitmap extension.\n"); + printk(KERN_ERR "AFFS: Cannot read bitmap extension\n"); goto out; } } else bh = NULL; } if (mapidx != num_bm) { - printk("AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm); + printk(KERN_ERR "AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm); goto out; } nobitmap: @@ -584,7 +601,7 @@ nobitmap: if (!(s->s_mounted)) { s->s_dev = 0; - printk("AFFS: get root inode failed\n"); + printk(KERN_ERR "AFFS: get root inode failed\n"); MOD_DEC_USE_COUNT; return NULL; } @@ -615,7 +632,7 @@ nobitmap: return NULL; } -void +static void affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { int free; @@ -635,15 +652,15 @@ affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) copy_to_user(buf,&tmp,bufsiz); } -void +static void affs_read_inode(struct inode *inode) { struct buffer_head *bh, *lbh; struct file_front *file_front; struct file_end *file_end; - int block; + s32 block; unsigned long prot; - int ptype, stype; + s32 ptype, stype; unsigned short id; pr_debug("AFFS: read_inode(%lu)\n",inode->i_ino); @@ -651,12 +668,12 @@ affs_read_inode(struct inode *inode) lbh = NULL; block = inode->i_ino; if (!(bh = affs_bread(inode->i_dev,block,AFFS_I2BSIZE(inode)))) { - printk("AFFS: unable to read i-node block %d\n",block); + affs_error(inode->i_sb,"read_inode","Cannot read block %d",block); return; } if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) || ptype != T_SHORT) { - printk("AFFS: read_inode(): checksum or type (ptype=%d) error on inode %d\n", - ptype,block); + affs_error(inode->i_sb,"read_inode", + "Checksum or type (ptype=%d) error on inode %d",ptype,block); affs_brelse(bh); return; } @@ -735,7 +752,8 @@ affs_read_inode(struct inode *inode) if (!(lbh = affs_bread(inode->i_dev,inode->u.affs_i.i_original, AFFS_I2BSIZE(inode)))) { affs_brelse(bh); - printk("AFFS: unable to read i-node block %ld\n",inode->i_ino); + affs_error(inode->i_sb,"read_inode","Cannot read block %lu", + inode->i_ino); return; } file_end = GET_END_PTR(struct file_end,lbh->b_data,AFFS_I2BSIZE(inode)); @@ -776,12 +794,13 @@ affs_read_inode(struct inode *inode) inode->i_op = &affs_symlink_inode_operations; } -void +static void affs_write_inode(struct inode *inode) { - struct buffer_head *bh; - struct file_end *file_end; - short uid, gid; + struct buffer_head *bh; + struct file_end *file_end; + uid_t uid; + gid_t gid; pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino); @@ -789,8 +808,7 @@ affs_write_inode(struct inode *inode) if (!inode->i_nlink) return; if (!(bh = bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)))) { - printk("AFFS: Unable to read block of inode %ld on %s\n", - inode->i_ino,kdevname(inode->i_dev)); + affs_error(inode->i_sb,"write_inode","Cannot read block %lu",inode->i_ino); return; } file_end = GET_END_PTR(struct file_end, bh->b_data,AFFS_I2BSIZE(inode)); @@ -820,7 +838,7 @@ affs_write_inode(struct inode *inode) brelse(bh); } -int +static int affs_notify_change(struct inode *inode, struct iattr *attr) { int error; @@ -848,7 +866,7 @@ affs_notify_change(struct inode *inode, struct iattr *attr) return 0; } -void +static void affs_put_inode(struct inode *inode) { pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",inode->i_ino,inode->i_nlink); @@ -867,7 +885,7 @@ affs_new_inode(const struct inode *dir) { struct inode *inode; struct super_block *sb; - int block; + s32 block; if (!dir || !(inode = get_empty_inode())) return NULL; @@ -918,7 +936,10 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, struct buffer_head *dir_bh; struct buffer_head *inode_bh; struct buffer_head *link_bh; - int hash; + struct buffer_head *ibh; + int retval; + int i; + s32 next; pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%d\n",dir->i_ino,inode->i_ino, len,name,type); @@ -926,34 +947,60 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, dir_bh = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir)); inode_bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)); link_bh = NULL; - if (!dir_bh || !inode_bh) { - affs_brelse(dir_bh); - affs_brelse(inode_bh); - return -ENOSPC; - } + retval = -EIO; + if (!dir_bh || !inode_bh) + goto addentry_done; if (link) { link_bh = affs_bread(link->i_dev,link->i_ino,AFFS_I2BSIZE(link)); - if (!link_bh) { - affs_brelse(dir_bh); - affs_brelse(inode_bh); - return -EINVAL; - } + if (!link_bh) + goto addentry_done; } ((struct dir_front *)inode_bh->b_data)->primary_type = ntohl(T_SHORT); ((struct dir_front *)inode_bh->b_data)->own_key = ntohl(inode->i_ino); - if (len > 30) /* truncate name quietly */ + retval = -ENAMETOOLONG; + if (len > 30) +#ifdef NO_TRUNCATE + goto addentry_done; +#else len = 30; +#endif + + /* Check if name is valid */ + retval = -EINVAL; + for (i = 0; i < len; i++) { + if (name[i] < ' ' || name[i] == ':' + || ((unsigned char)name[i] > 0x7e && (unsigned char)name[i] < 0xa0)) + goto addentry_done; + } + retval = 0; DIR_END(inode_bh->b_data,inode)->dir_name[0] = len; strncpy(DIR_END(inode_bh->b_data,inode)->dir_name + 1,name,len); DIR_END(inode_bh->b_data,inode)->secondary_type = ntohl(type); DIR_END(inode_bh->b_data,inode)->parent = ntohl(dir->i_ino); - hash = affs_hash_name(name,len,AFFS_I2FSTYPE(dir),AFFS_I2HSIZE(dir)); + + i = affs_hash_name(name,len,AFFS_I2FSTYPE(dir),AFFS_I2HSIZE(dir)) + 6; + next = dir->i_ino; + + /* Alas, we have to search the insertion point with a locked sb */ lock_super(inode->i_sb); - DIR_END(inode_bh->b_data,inode)->hash_chain = - ((struct dir_front *)dir_bh->b_data)->hashtable[hash]; - ((struct dir_front *)dir_bh->b_data)->hashtable[hash] = ntohl(inode->i_ino); + while (1) { + if (!(ibh = affs_bread(dir->i_dev,next,AFFS_I2BSIZE(dir)))) + goto addentry_done; + next = htonl(((s32 *)ibh->b_data)[i]); + if (!next || next > inode->i_ino) + break; + i = AFFS_I2BSIZE(dir) / 4 - 4; + affs_brelse(ibh); + } + + DIR_END(inode_bh->b_data,inode)->hash_chain = next; + ((s32 *)ibh->b_data)[i] = ntohl(inode->i_ino); + affs_fix_checksum(AFFS_I2BSIZE(dir),ibh->b_data,5); + mark_buffer_dirty(ibh,1); + affs_brelse(ibh); + if (link_bh) { LINK_END(inode_bh->b_data,inode)->original = ntohl(link->i_ino); LINK_END(inode_bh->b_data,inode)->link_chain = @@ -974,11 +1021,13 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, inode->i_dirt = 1; mark_buffer_dirty(dir_bh,1); mark_buffer_dirty(inode_bh,1); + +addentry_done: affs_brelse(dir_bh); affs_brelse(inode_bh); affs_brelse(link_bh); - return 0; + return retval; } static struct file_system_type affs_fs_type = { @@ -999,7 +1048,7 @@ EXPORT_NO_SYMBOLS; int init_module(void) { - return init_affs_fs(); + return register_filesystem(&affs_fs_type); } void diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 0f4bced4398a..6a9b02bac68c 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -20,6 +20,8 @@ #include +static int affs_fixup(struct buffer_head *bh, struct inode *inode); + /* Simple toupper() for DOS\1 */ static inline unsigned int @@ -100,7 +102,7 @@ affs_find_entry(struct inode *dir, const char *name, int namelen, { struct buffer_head *bh; int intl; - int key; + s32 key; pr_debug("AFFS: find_entry(%.*s)=\n",namelen,name); @@ -222,9 +224,7 @@ affs_create(struct inode *dir, const char *name, int len, int mode, struct inode pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir->i_ino,len,name,mode); - *result = NULL; - if (!dir || !dir->i_sb) { iput(dir); return -EINVAL; @@ -472,7 +472,7 @@ affs_link(struct inode *oldinode, struct inode *dir, const char *name, int len) iput(oldinode); oldinode = iget(dir->i_sb,i); if (!oldinode) { - printk("AFFS: link(): original does not exist.\n"); + affs_error(oldinode->i_sb,"link","Cannot get original from link"); iput(dir); return -ENOENT; } @@ -507,7 +507,7 @@ affs_link(struct inode *oldinode, struct inode *dir, const char *name, int len) } static int -subdir(struct inode * new_inode, struct inode * old_inode) +subdir(struct inode *new_inode, struct inode *old_inode) { int ino; int result; @@ -650,11 +650,11 @@ end_rename: return retval; } -int +static int affs_fixup(struct buffer_head *bh, struct inode *inode) { - int key, link_key; - int type; + s32 key, link_key; + s32 type; struct buffer_head *nbh; struct inode *ofinode; @@ -663,7 +663,8 @@ affs_fixup(struct buffer_head *bh, struct inode *inode) key = htonl(LINK_END(bh->b_data,inode)->original); LINK_END(bh->b_data,inode)->original = 0; if (!key) { - printk("AFFS: fixup(): hard link without original: ino=%lu\n",inode->i_ino); + affs_error(inode->i_sb,"fixup","Hard link without original: ino=%lu", + inode->i_ino); return -ENOENT; } if (!(ofinode = iget(inode->i_sb,key))) @@ -676,17 +677,18 @@ affs_fixup(struct buffer_head *bh, struct inode *inode) if ((key = htonl(FILE_END(bh->b_data,inode)->link_chain))) { /* Get first link, turn it to a file */ if (!(ofinode = iget(inode->i_sb,key))) { - printk("AFFS: fixup(): cannot read inode %u\n",key); + affs_error(inode->i_sb,"fixup","Cannot read block %d",key); return -ENOENT; } if (!ofinode->u.affs_i.i_hlink) { - printk("AFFS: fixup(): first link to %lu (%u) is not a link?\n", - inode->i_ino,key); + affs_error(inode->i_sb,"fixup", + "First link to %lu (%d) is not a link", + inode->i_ino,key); iput(ofinode); return -ENOENT; } if (!(nbh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)))) { - printk("AFFS: fixup(): cannot read block %u\n",key); + affs_error(inode->i_sb,"fixup","Cannot read block %d",key); iput(ofinode); return -ENOENT; } @@ -719,13 +721,14 @@ affs_fixup(struct buffer_head *bh, struct inode *inode) break; if ((ofinode = iget(inode->i_sb,key))) { if (!ofinode->u.affs_i.i_hlink) - printk("AFFS: fixup() inode %u in link chain is " - "not a link\n",key); + affs_error(inode->i_sb,"fixup", + "Inode %d in link chain is not a link", + key); ofinode->u.affs_i.i_original = link_key; ofinode->i_dirt = 1; FILE_END(nbh->b_data,inode)->original = htonl(link_key); } else - printk("AFFS: fixup(): cannot get inode %u\n",key); + affs_error(inode->i_sb,"fixup","Cannot read block %d",key); } /* Turn old inode to a link */ inode->u.affs_i.i_hlink = 1; @@ -735,7 +738,7 @@ affs_fixup(struct buffer_head *bh, struct inode *inode) } else if (type == ST_SOFTLINK) { return 0; } else { - printk("AFFS: fixup(): secondary type=%d\n",type); + affs_error(inode->i_sb,"fixup","Bad secondary type (%d)",type); return -EBADF; } } diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index 734df0780e47..de93eac5c7b4 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -82,7 +82,7 @@ affs_follow_link(struct inode *dir, struct inode *inode, int flag, int mode, i = 0; j = 0; if (!bh) { - printk("AFFS: unable to read i-node block %lu\n",inode->i_ino); + affs_error(inode->i_sb,"follow_link","Cannot read block %lu\n",inode->i_ino); kfree(buffer); iput(inode); iput(dir); @@ -138,7 +138,7 @@ affs_readlink(struct inode *inode, char *buffer, int buflen) i = 0; j = 0; if (!bh) { - printk("AFFS: unable to read i-node block %lu\n",inode->i_ino); + affs_error(inode->i_sb,"readlink","Cannot read block %lu\n",inode->i_ino); goto symlink_end; } lf = (struct slink_front *)bh->b_data; diff --git a/fs/autofs/Makefile b/fs/autofs/Makefile index 12f302635856..1681c3d31e83 100644 --- a/fs/autofs/Makefile +++ b/fs/autofs/Makefile @@ -1,11 +1,7 @@ # # Makefile for the linux autofs-filesystem routines. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... +# We can build this either out of the kernel tree or the autofs tools tree. # O_TARGET := autofs.o @@ -13,4 +9,27 @@ O_OBJS := dir.o dirhash.o init.o inode.o root.o symlink.o waitq.o M_OBJS := $(O_TARGET) +ifdef TOPDIR +# +# Part of the kernel code +# include $(TOPDIR)/Rules.make +else +# +# Standalone (handy for development) +# +include ../Makefile.rules + +CFLAGS += -D__KERNEL__ -DMODULE $(KFLAGS) -I../include -I$(KINCLUDE) $(MODFLAGS) + +all: $(O_TARGET) + +$(O_TARGET): $(O_OBJS) + $(LD) -r -o $(O_TARGET) $(O_OBJS) + +install: $(O_TARGET) + install -c $(O_TARGET) /lib/modules/`uname -r`/fs + +clean: + rm -f *.o *.s +endif diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h new file mode 100644 index 000000000000..172e1d4608ee --- /dev/null +++ b/fs/autofs/autofs_i.h @@ -0,0 +1,157 @@ +/* -*- linux-c -*- ------------------------------------------------------- * + * + * linux/fs/autofs/autofs_i.h + * + * Copyright 1997 Transmeta Corporation - All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* Internal header file for autofs */ + +#include + +/* This is the range of ioctl() numbers we claim as ours */ +#define AUTOFS_IOC_FIRST AUTOFS_IOC_READY +#define AUTOFS_IOC_COUNT 32 + +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < 0x20100 + +/* Segmentation stuff for pre-2.1 kernels */ +#include +#define copy_to_user memcpy_tofs +#define copy_from_user memcpy_fromfs + +#else + +/* Segmentation stuff for post-2.1 kernels */ +#include +#define register_symtab(x) ((void)0) + +#endif + +#ifdef DEBUG +#define DPRINTK(D) printk D; +#else +#define DPRINTK(D) +#endif + +#define AUTOFS_SUPER_MAGIC 0x0187 + +/* Structures associated with the root directory hash */ + +#define AUTOFS_HASH_SIZE 67 + +typedef u32 autofs_hash_t; /* Type returned by autofs_hash() */ + +struct autofs_dir_ent { + autofs_hash_t hash; + struct autofs_dir_ent *next; + struct autofs_dir_ent **back; + char *name; + int len; + ino_t ino; + /* The following entries are for the expiry system */ + unsigned long last_usage; + struct autofs_dir_ent *exp_next; + struct autofs_dir_ent *exp_prev; +}; + +struct autofs_dirhash { + struct autofs_dir_ent *h[AUTOFS_HASH_SIZE]; + struct autofs_dir_ent expiry_head; +}; + +struct autofs_wait_queue { + unsigned long wait_queue_token; + struct wait_queue *queue; + struct autofs_wait_queue *next; + /* We use the following to see what we are waiting for */ + autofs_hash_t hash; + int len; + char *name; + /* This is for status reporting upon return */ + int status; + int wait_ctr; +}; + +struct autofs_symlink { + int len; + char *data; + time_t mtime; +}; + +#define AUTOFS_MAX_SYMLINKS 256 + +#define AUTOFS_ROOT_INO 1 +#define AUTOFS_FIRST_SYMLINK 2 +#define AUTOFS_FIRST_DIR_INO (AUTOFS_FIRST_SYMLINK+AUTOFS_MAX_SYMLINKS) + +#define AUTOFS_SYMLINK_BITMAP_LEN ((AUTOFS_MAX_SYMLINKS+31)/32) + +#ifndef END_OF_TIME +#define END_OF_TIME ((time_t)((unsigned long)((time_t)(~0UL)) >> 1)) +#endif + +struct autofs_sb_info { + struct file *pipe; + pid_t oz_pgrp; + int catatonic; + unsigned long exp_timeout; + ino_t next_dir_ino; + struct autofs_wait_queue *queues; /* Wait queue pointer */ + struct autofs_dirhash dirhash; /* Root directory hash */ + struct autofs_symlink symlink[AUTOFS_MAX_SYMLINKS]; + u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN]; +}; + +/* autofs_oz_mode(): do we see the man behind the curtain? */ +static inline int autofs_oz_mode(struct autofs_sb_info *sbi) { + return sbi->catatonic || current->pgrp == sbi->oz_pgrp; +} + +/* Hash operations */ + +autofs_hash_t autofs_hash(const char *,int); +void autofs_initialize_hash(struct autofs_dirhash *); +struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,autofs_hash_t,const char *,int); +void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *); +void autofs_hash_delete(struct autofs_dir_ent *); +struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *); +void autofs_hash_nuke(struct autofs_dirhash *); + +/* Expiration-handling functions */ + +void autofs_update_usage(struct autofs_dirhash *,struct autofs_dir_ent *); +struct autofs_dir_ent *autofs_expire(struct autofs_dirhash *,unsigned long); + +/* Operations structures */ + +extern struct inode_operations autofs_root_inode_operations; +extern struct inode_operations autofs_symlink_inode_operations; +extern struct inode_operations autofs_dir_inode_operations; + +/* Initializing function */ + +struct super_block *autofs_read_super(struct super_block *, void *,int); + +/* Queue management functions */ + +int autofs_wait(struct autofs_sb_info *,autofs_hash_t,const char *,int); +int autofs_wait_release(struct autofs_sb_info *,unsigned long,int); +void autofs_catatonic_mode(struct autofs_sb_info *); + +#ifdef DEBUG +void autofs_say(const char *name, int len); +#else +#define autofs_say(n,l) +#endif diff --git a/fs/autofs/dir.c b/fs/autofs/dir.c index 22081d1a745c..461688e9f871 100644 --- a/fs/autofs/dir.c +++ b/fs/autofs/dir.c @@ -10,7 +10,7 @@ * * ------------------------------------------------------------------------- */ -#include +#include "autofs_i.h" static int autofs_dir_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t filldir) diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c index 8ea5325c45db..90c18695a094 100644 --- a/fs/autofs/dirhash.c +++ b/fs/autofs/dirhash.c @@ -10,9 +10,43 @@ * * ------------------------------------------------------------------------- */ -#include -#include -#include +#include "autofs_i.h" + +/* Functions for maintenance of expiry queue */ + +static void autofs_init_usage(struct autofs_dirhash *dh, + struct autofs_dir_ent *ent) +{ + ent->exp_next = &dh->expiry_head; + ent->exp_prev = dh->expiry_head.exp_prev; + dh->expiry_head.exp_prev->exp_next = ent; + dh->expiry_head.exp_prev = ent; + ent->last_usage = jiffies; +} + +static void autofs_delete_usage(struct autofs_dir_ent *ent) +{ + ent->exp_prev->exp_next = ent->exp_next; + ent->exp_next->exp_prev = ent->exp_prev; +} + +void autofs_update_usage(struct autofs_dirhash *dh, + struct autofs_dir_ent *ent) +{ + autofs_delete_usage(ent); /* Unlink from current position */ + autofs_init_usage(dh,ent); /* Relink at queue tail */ +} + +struct autofs_dir_ent *autofs_expire(struct autofs_dirhash *dh, + unsigned long timeout) +{ + struct autofs_dir_ent *ent; + + ent = dh->expiry_head.exp_next; + + if ( ent == &(dh->expiry_head) ) return NULL; + return (jiffies - ent->last_usage >= timeout) ? ent : NULL; +} /* Adapted from the Dragon Book, page 436 */ /* This particular hashing algorithm requires autofs_hash_t == u32 */ @@ -28,6 +62,8 @@ autofs_hash_t autofs_hash(const char *name, int len) void autofs_initialize_hash(struct autofs_dirhash *dh) { memset(&dh->h, 0, AUTOFS_HASH_SIZE*sizeof(struct autofs_dir_ent *)); + dh->expiry_head.exp_next = dh->expiry_head.exp_prev = + &dh->expiry_head; } struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *dh, autofs_hash_t hash, const char *name, int len) @@ -54,6 +90,8 @@ void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent) DPRINTK(("autofs_hash_insert: hash = 0x%08x, name = ", ent->hash)); autofs_say(ent->name,ent->len); + autofs_init_usage(dh,ent); + dhnp = &dh->h[ent->hash % AUTOFS_HASH_SIZE]; ent->next = *dhnp; ent->back = dhnp; @@ -63,6 +101,9 @@ void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent) void autofs_hash_delete(struct autofs_dir_ent *ent) { *(ent->back) = ent->next; + + autofs_delete_usage(ent); + kfree(ent->name); kfree(ent); } @@ -114,6 +155,8 @@ struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *dh, off_t * return ent; } +/* Delete everything. This is used on filesystem destruction, so we + make no attempt to keep the pointers valid */ void autofs_hash_nuke(struct autofs_dirhash *dh) { int i; diff --git a/fs/autofs/init.c b/fs/autofs/init.c index a4857cb99a19..23ffb70fe48c 100644 --- a/fs/autofs/init.c +++ b/fs/autofs/init.c @@ -10,24 +10,20 @@ * * ------------------------------------------------------------------------- */ +#include #include -#include +#include "autofs_i.h" -struct file_system_type autofs_fs_type = { +static struct file_system_type autofs_fs_type = { autofs_read_super, "autofs", 0, NULL }; -int init_autofs_fs(void) -{ - return register_filesystem(&autofs_fs_type); -} - #ifdef MODULE int init_module(void) { int status; - if ((status = init_autofs_fs()) == 0) + if ((status = register_filesystem(&autofs_fs_type)) == 0) register_symtab(0); return status; } @@ -36,7 +32,15 @@ void cleanup_module(void) { unregister_filesystem(&autofs_fs_type); } -#endif + +#else /* MODULE */ + +__initfunc(int init_autofs_fs(void)) +{ + return register_filesystem(&autofs_fs_type); +} + +#endif /* !MODULE */ #ifdef DEBUG void autofs_say(const char *name, int len) diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 60b805a07c1e..a8c176a02d32 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include "autofs_i.h" #define __NO_VERSION__ #include @@ -28,17 +28,19 @@ static void autofs_put_inode(struct inode *inode) static void autofs_put_super(struct super_block *sb) { - struct autofs_sb_info *sbi; + struct autofs_sb_info *sbi = + (struct autofs_sb_info *) sb->u.generic_sbp; unsigned int n; + if ( !sbi->catatonic ) + autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ + lock_super(sb); - sbi = (struct autofs_sb_info *) sb->u.generic_sbp; autofs_hash_nuke(&sbi->dirhash); for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) { if ( test_bit(n, sbi->symlink_bitmap) ) kfree(sbi->symlink[n].data); } - fput(sbi->pipe, sbi->pipe->f_inode); sb->s_dev = 0; kfree(sb->u.generic_sbp); @@ -149,6 +151,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data, s->u.generic_sbp = sbi; sbi->catatonic = 0; + sbi->exp_timeout = 0; sbi->oz_pgrp = current->pgrp; autofs_initialize_hash(&sbi->dirhash); sbi->queues = NULL; diff --git a/fs/autofs/root.c b/fs/autofs/root.c index d9056dcb1db8..f13472ef406c 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -12,9 +12,8 @@ #include #include -#include -#include -#include +#include +#include "autofs_i.h" static int autofs_root_readdir(struct inode *,struct file *,void *,filldir_t); static int autofs_root_lookup(struct inode *,const char *,int,struct inode **); @@ -171,7 +170,8 @@ static int autofs_root_lookup(struct inode *dir, const char *name, int len, } } } while(!res); - + autofs_update_usage(&sbi->dirhash,ent); + *result = res; iput(dir); return 0; @@ -229,7 +229,6 @@ static int autofs_root_symlink(struct inode *dir, const char *name, int len, con ent->ino = AUTOFS_FIRST_SYMLINK + n; ent->hash = hash; memcpy(ent->name,name,ent->len = len); - ent->expiry = END_OF_TIME; autofs_hash_insert(dh,ent); @@ -322,7 +321,6 @@ static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int m ent->hash = hash; memcpy(ent->name, name, ent->len = len); ent->ino = sbi->next_dir_ino++; - ent->expiry = END_OF_TIME; autofs_hash_insert(dh,ent); dir->i_nlink++; iput(dir); @@ -330,6 +328,52 @@ static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int m return 0; } +/* Get/set timeout ioctl() operation */ +static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi, + unsigned long *p) +{ + int rv; + unsigned long ntimeout; + + if ( (rv = get_user(ntimeout, p)) || + (rv = put_user(sbi->exp_timeout/HZ, p)) ) + return rv; + + if ( ntimeout > ULONG_MAX/HZ ) + sbi->exp_timeout = 0; + else + sbi->exp_timeout = ntimeout * HZ; + + return 0; +} + +/* Perform an expiry operation */ +static inline int autofs_expire_run(struct autofs_sb_info *sbi, + struct autofs_packet_expire *pkt_p) +{ + struct autofs_dir_ent *ent; + struct autofs_packet_expire pkt; + struct autofs_dirhash *dh = &(sbi->dirhash); + + pkt.hdr.proto_version = AUTOFS_PROTO_VERSION; + pkt.hdr.type = autofs_ptype_expire; + + if ( !sbi->exp_timeout || + !(ent = autofs_expire(dh,sbi->exp_timeout)) ) + return -EAGAIN; + + pkt.len = ent->len; + memcpy(pkt.name, ent->name, pkt.len); + pkt.name[pkt.len] = '\0'; + + if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) ) + return -EFAULT; + + autofs_update_usage(dh,ent); + + return 0; +} + /* * ioctl()'s on the root directory is the chief method for the daemon to * generate kernel reactions @@ -337,26 +381,33 @@ static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int m static int autofs_root_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *)inode->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = + (struct autofs_sb_info *)inode->i_sb->u.generic_sbp; - DPRINTK(("autofs_ioctl: cmd = %04x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp)); + DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp)); + if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || + _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT ) + return -ENOTTY; + + if ( !autofs_oz_mode(sbi) && !fsuser() ) + return -EPERM; + switch(cmd) { case AUTOFS_IOC_READY: /* Wait queue: go ahead and retry */ - if ( !autofs_oz_mode(sbi) && !fsuser() ) - return -EPERM; return autofs_wait_release(sbi,arg,0); case AUTOFS_IOC_FAIL: /* Wait queue: fail with ENOENT */ - /* Optional: add to failure cache */ - if ( !autofs_oz_mode(sbi) && !fsuser() ) - return -EPERM; return autofs_wait_release(sbi,arg,-ENOENT); case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */ - if ( !autofs_oz_mode(sbi) && !fsuser() ) - return -EPERM; autofs_catatonic_mode(sbi); return 0; + case AUTOFS_IOC_PROTOVER: /* Get protocol version */ + return put_user(AUTOFS_PROTO_VERSION, (int *)arg); + case AUTOFS_IOC_SETTIMEOUT: + return autofs_get_set_timeout(sbi,(unsigned long *)arg); + case AUTOFS_IOC_EXPIRE: + return autofs_expire_run(sbi,(struct autofs_packet_expire *)arg); default: - return -ENOTTY; /* Should this be ENOSYS? */ + return -ENOSYS; } } diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c index 0e932c169084..46c333103138 100644 --- a/fs/autofs/symlink.c +++ b/fs/autofs/symlink.c @@ -12,7 +12,7 @@ #include #include -#include +#include "autofs_i.h" static int autofs_follow_link(struct inode *dir, struct inode *inode, int flag, int mode, struct inode **res_inode) diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c index 6dc6d0b13746..2190817bb6ba 100644 --- a/fs/autofs/waitq.c +++ b/fs/autofs/waitq.c @@ -11,9 +11,10 @@ * ------------------------------------------------------------------------- */ #include -#include #include -#include +#include +#include +#include "autofs_i.h" /* We make this a static variable rather than a part of the superblock; it is better if we don't reassign numbers easily even across filesystems */ @@ -36,6 +37,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi) wake_up(&wq->queue); wq = nwq; } + fput(sbi->pipe, sbi->pipe->f_inode); /* Close the pipe */ } static int autofs_write(struct file *file, const void *addr, int bytes) diff --git a/fs/proc/array.c b/fs/proc/array.c index 126ed2dfe24d..153c09f770d9 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -501,7 +501,8 @@ static unsigned long get_wchan(struct task_struct *p) */ # define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ + (long)&((struct pt_regs *)0)->reg) -# define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc))) +# define KSTK_EIP(tsk) \ + (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk))) # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) #elif defined(__mc68000__) #define KSTK_EIP(tsk) \ diff --git a/fs/super.c b/fs/super.c index 053c6321aff1..5ae3b0f819d4 100644 --- a/fs/super.c +++ b/fs/super.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -937,7 +938,11 @@ out: return retval; } +#ifdef CONFIG_BLK_DEV_INITRD static void do_mount_root(void) +#else +__initfunc(static void do_mount_root(void)) +#endif { struct file_system_type * fs_type; struct super_block * sb; @@ -1046,7 +1051,7 @@ static void do_mount_root(void) } -void mount_root(void) +__initfunc(void mount_root(void)) { memset(super_blocks, 0, sizeof(super_blocks)); do_mount_root(); diff --git a/include/asm-alpha/atomic.h b/include/asm-alpha/atomic.h index 2485cd781a4a..16366d05581d 100644 --- a/include/asm-alpha/atomic.h +++ b/include/asm-alpha/atomic.h @@ -41,9 +41,9 @@ extern __inline__ void atomic_add(int i, atomic_t * v) " addl %0,%2,%0\n" " stl_c %0,%1\n" " beq %0,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (__atomic_fool_gcc(v)) :"Ir" (i), "m" (__atomic_fool_gcc(v))); } @@ -56,9 +56,9 @@ extern __inline__ void atomic_sub(int i, atomic_t * v) " subl %0,%2,%0\n" " stl_c %0,%1\n" " beq %0,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (__atomic_fool_gcc(v)) :"Ir" (i), "m" (__atomic_fool_gcc(v))); } @@ -75,9 +75,9 @@ extern __inline__ long atomic_add_return(int i, atomic_t * v) " mov %0,%2\n" " stl_c %0,%1\n" " beq %0,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (__atomic_fool_gcc(v)), "=&r" (result) :"Ir" (i), "m" (__atomic_fool_gcc(v))); return result; @@ -92,9 +92,9 @@ extern __inline__ long atomic_sub_return(int i, atomic_t * v) " mov %0,%2\n" " stl_c %0,%1\n" " beq %0,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (__atomic_fool_gcc(v)), "=&r" (result) :"Ir" (i), "m" (__atomic_fool_gcc(v))); return result; diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h index 2a6f33a64961..24e73f8ec1b8 100644 --- a/include/asm-alpha/bitops.h +++ b/include/asm-alpha/bitops.h @@ -31,9 +31,9 @@ extern __inline__ unsigned long set_bit(unsigned long nr, void * addr) " stl_c %0,%1\n" " beq %0,3f\n" "2:\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "3: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (*m), "=&r" (oldbit) :"Ir" (1UL << (nr & 31)), "m" (*m)); @@ -54,9 +54,9 @@ extern __inline__ unsigned long clear_bit(unsigned long nr, void * addr) " stl_c %0,%1\n\t" " beq %0,3f\n" "2:\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "3: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (*m), "=&r" (oldbit) :"Ir" (1UL << (nr & 31)), "m" (*m)); @@ -75,9 +75,9 @@ extern __inline__ unsigned long change_bit(unsigned long nr, void * addr) " xor %0,%3,%0\n\t" " stl_c %0,%1\n\t" " beq %0,3f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "3: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (*m), "=&r" (oldbit) :"Ir" (1UL << (nr & 31)), "m" (*m)); diff --git a/include/asm-alpha/current.h b/include/asm-alpha/current.h index 56d12724b286..8db6dd06e236 100644 --- a/include/asm-alpha/current.h +++ b/include/asm-alpha/current.h @@ -1,12 +1,6 @@ #ifndef _ALPHA_CURRENT_H #define _ALPHA_CURRENT_H -/* Some architectures may want to do something "clever" here since - * this is the most frequently accessed piece of data in the entire - * kernel. - */ -extern struct task_struct *current_set[NR_CPUS]; - register struct task_struct *current __asm__("$8"); #endif /* !(_ALPHA_CURRENT_H) */ diff --git a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h index d2968350f677..9bceac11388f 100644 --- a/include/asm-alpha/processor.h +++ b/include/asm-alpha/processor.h @@ -85,10 +85,12 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long); /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); -/* Allocation and freeing of basic task resources. */ -#define alloc_task_struct() kmalloc(sizeof(struct task_struct), GFP_KERNEL) -#define alloc_kernel_stack(p) __get_free_page(GFP_KERNEL) -#define free_task_struct(p) kfree(p) -#define free_kernel_stack(page) free_page((page)) +/* NOTE: The task struct and the stack go together! */ +#define alloc_task_struct() \ + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0)) +#define free_task_struct(p) free_pages((unsigned long)(p),1) + +#define init_task (init_task_union.task) +#define init_stack (init_task_union.stack) #endif /* __ASM_ALPHA_PROCESSOR_H */ diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h index b94573f1311c..29cbb4a33a79 100644 --- a/include/asm-alpha/semaphore.h +++ b/include/asm-alpha/semaphore.h @@ -47,9 +47,9 @@ static inline int waking_non_zero(struct semaphore *sem) " stl_c %0,%2\n" " beq %0,3f\n" "2:\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "3: br 1b\n" - ".text" + ".previous" : "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking)) : "0"(0)); diff --git a/include/asm-alpha/softirq.h b/include/asm-alpha/softirq.h index fa8124c3866c..f267f6ceb34a 100644 --- a/include/asm-alpha/softirq.h +++ b/include/asm-alpha/softirq.h @@ -17,9 +17,9 @@ static inline void clear_active_bhs(unsigned long x) " and %0,%2,%0\n" " stq_c %0,%1\n" " beq %0,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (bh_active) :"Ir" (x), "m" (bh_active)); } diff --git a/include/asm-alpha/spinlock.h b/include/asm-alpha/spinlock.h index e9119ba9f40a..7b6a218cf4f8 100644 --- a/include/asm-alpha/spinlock.h +++ b/include/asm-alpha/spinlock.h @@ -3,8 +3,9 @@ #ifndef __SMP__ -typedef struct { } spinlock_t; -#define SPIN_LOCK_UNLOCKED { } +/* gcc 2.7.2 can crash initializing an empty structure. */ +typedef struct { int dummy; } spinlock_t; +#define SPIN_LOCK_UNLOCKED { 0 } #define spin_lock_init(lock) do { } while(0) #define spin_lock(lock) do { } while(0) @@ -27,8 +28,8 @@ typedef struct { } spinlock_t; * irq-safe write-lock, but readers can get non-irqsafe * read-locks. */ -typedef struct { } rwlock_t; -#define RW_LOCK_UNLOCKED { } +typedef struct { int dummy; } rwlock_t; +#define RW_LOCK_UNLOCKED { 0 } #define read_lock(lock) do { } while(0) #define read_unlock(lock) do { } while(0) @@ -89,13 +90,13 @@ l1: " stq_c %0,%1\n" " beq %0,3f\n" "4: mb\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: ldq %0,%1\n" " subq %2,1,%2\n" "3: blt %2,4b\n" " blbs %0,2b\n" " br 1b\n" - ".text" + ".previous" : "=r" (tmp), "=m" (__dummy_lock(lock)), "=r" (stuck) diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h index 7821206866ad..eeb9f58608c3 100644 --- a/include/asm-alpha/system.h +++ b/include/asm-alpha/system.h @@ -56,7 +56,7 @@ extern void wrmces (unsigned long); #define halt() __asm__ __volatile__ ("call_pal %0" : : "i" (PAL_halt) : "memory") #define switch_to(prev,next) do { \ - current_set[0] = current = next; \ + current = next; \ alpha_switch_to((unsigned long) ¤t->tss - 0xfffffc0000000000); \ } while (0) @@ -129,9 +129,9 @@ extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val) " bis %3,%3,%1\n" " stl_c %1,%2\n" " beq %1,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" : "=&r" (val), "=&r" (dummy), "=m" (*m) : "r" (val), "m" (*m)); @@ -147,9 +147,9 @@ extern __inline__ unsigned long xchg_u64(volatile long * m, unsigned long val) " bis %3,%3,%1\n" " stq_c %1,%2\n" " beq %1,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" : "=&r" (val), "=&r" (dummy), "=m" (*m) : "r" (val), "m" (*m)); diff --git a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h index 284a30ee4bce..0727437b8645 100644 --- a/include/asm-i386/checksum.h +++ b/include/asm-i386/checksum.h @@ -1,6 +1,8 @@ #ifndef _I386_CHECKSUM_H #define _I386_CHECKSUM_H +#include + /* * computes the checksum of a memory block at buff, length len, * and adds in "sum" (32-bit) @@ -13,7 +15,9 @@ * * it's best to have buff aligned on a 32-bit boundary */ -unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum); + +extern +unsigned int csum_partial (const unsigned char * buff, int len, unsigned int sum); /* * the same as csum_partial, but copies from src while it @@ -23,7 +27,7 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) * better 64-bit) boundary */ -unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum, +unsigned int __csum_partial_copy_i386_generic( const char *src, char *dst, int len, int sum, int *src_err_ptr, int *dst_err_ptr); extern __inline__ @@ -32,7 +36,7 @@ unsigned int csum_partial_copy_nocheck ( const char *src, char *dst, { int *src_err_ptr=NULL, *dst_err_ptr=NULL; - return csum_partial_copy_generic ( src, dst, len, sum, src_err_ptr, dst_err_ptr); + return __csum_partial_copy_i386_generic ( src, dst, len, sum, src_err_ptr, dst_err_ptr); } extern __inline__ @@ -41,7 +45,15 @@ unsigned int csum_partial_copy_from_user ( const char *src, char *dst, { int *dst_err_ptr=NULL; - return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, dst_err_ptr); +/* + * If the source address is invalid, force an exception via NULL pointer. + * The point of this solution is to make the code smaller. The exception path + * doesnt have to be fast. + */ + if (!access_ok(VERIFY_READ, src, len)) + src = NULL; + + return __csum_partial_copy_i386_generic ( src, dst, len, sum, err_ptr, dst_err_ptr); } /* @@ -54,7 +66,10 @@ unsigned int csum_partial_copy_to_user ( const char *src, char *dst, { int *src_err_ptr=NULL; - return csum_partial_copy_generic ( src, dst, len, sum, src_err_ptr, err_ptr); + if (!access_ok(VERIFY_WRITE, dst, len)) + dst = NULL; + + return __csum_partial_copy_i386_generic ( src, dst, len, sum, src_err_ptr, err_ptr); } /* diff --git a/include/asm-i386/current.h b/include/asm-i386/current.h index e103b5e238b1..976320d75ff5 100644 --- a/include/asm-i386/current.h +++ b/include/asm-i386/current.h @@ -1,13 +1,6 @@ #ifndef _I386_CURRENT_H #define _I386_CURRENT_H -/* Some architectures may want to do something "clever" here since - * this is the most frequently accessed piece of data in the entire - * kernel. For an example, see the Sparc implementation where an - * entire register is hard locked to contain the value of current. - */ -extern struct task_struct *current_set[NR_CPUS]; - static inline unsigned long get_esp(void) { unsigned long esp; diff --git a/include/asm-i386/smp_lock.h b/include/asm-i386/smp_lock.h index 160e3562dacc..4f78f97fb69a 100644 --- a/include/asm-i386/smp_lock.h +++ b/include/asm-i386/smp_lock.h @@ -31,14 +31,11 @@ do { \ #define reacquire_kernel_lock(task, cpu, depth) \ do { if (depth) __asm__ __volatile__( \ "cli\n\t" \ - "movl $0f,%%eax\n\t" \ - "jmp __lock_kernel\n" \ - "0:\t" \ + "call __lock_kernel\n\t" \ "movl %2,%0\n\t" \ "sti" \ : "=m" (task->lock_depth) \ - : "d" (cpu), "c" (depth) \ - : "ax"); \ + : "d" (cpu), "c" (depth)); \ } while (0) @@ -62,14 +59,12 @@ l2: printk("Ugh at %p\n", &&l2); cli cmpl $0, %0 jne 0f - movl $0f, %%eax - jmp __lock_kernel -0: - incl %0 + call __lock_kernel +0: incl %0 popfl " : - : "m" (current_set[cpu]->lock_depth), "d" (cpu) - : "ax", "memory"); + : "m" (current->lock_depth), "d" (cpu) + : "memory"); } extern __inline__ void unlock_kernel(void) diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h index dce2968a9aff..f3d2159d4daf 100644 --- a/include/asm-i386/spinlock.h +++ b/include/asm-i386/spinlock.h @@ -80,12 +80,12 @@ __asm__ __volatile__( \ "\n1:\t" \ "lock ; btsl $0,%0\n\t" \ "jc 2f\n" \ - ".text 2\n" \ + ".section .text.lock\n" \ "2:\t" \ "testb $1,%0\n\t" \ "jne 2b\n\t" \ "jmp 1b\n" \ - ".text" \ + ".previous" \ :"=m" (__dummy_lock(lock))) #define spin_unlock(lock) \ @@ -134,12 +134,12 @@ typedef struct { asm volatile("\n1:\t" \ "lock ; incl %0\n\t" \ "js 2f\n" \ - ".text 2\n" \ + ".section .text.lock\n" \ "2:\tlock ; decl %0\n" \ "3:\tcmpl $0,%0\n\t" \ "js 3b\n\t" \ "jmp 1b\n" \ - ".text" \ + ".previous" \ :"=m" (__dummy_lock(&(rw)->lock))) #define read_unlock(rw) \ @@ -153,7 +153,7 @@ typedef struct { "testl $0x7fffffff,%0\n\t" \ "jne 4f\n" \ "2:\n" \ - ".text 2\n" \ + ".section .text.lock\n" \ "3:\ttestl $-1,%0\n\t" \ "js 3b\n\t" \ "lock ; btsl $31,%0\n\t" \ @@ -161,7 +161,7 @@ typedef struct { "4:\ttestl $0x7fffffff,%0\n\t" \ "jne 4b\n\t" \ "jmp 2b\n" \ - ".text" \ + ".previous" \ :"=m" (__dummy_lock(&(rw)->lock))) #define write_unlock(rw) \ diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index a3daf450dbe3..94e01ec2a55f 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h @@ -73,7 +73,6 @@ __asm__("str %%ax\n\t" \ __asm__ __volatile__("fwait"); \ prev->flags&=~PF_USEDFPU; \ } \ - current_set[this_cpu] = next; \ __asm__("ljmp %0\n\t" \ : /* no output */ \ :"m" (*(((char *)&next->tss.tr)-4)), \ @@ -91,8 +90,7 @@ __asm__("ljmp %0\n\t" \ #else #define switch_to(prev,next) do { \ -__asm__("movl %2,"SYMBOL_NAME_STR(current_set)"\n\t" \ - "ljmp %0\n\t" \ +__asm__("ljmp %0\n\t" \ "cmpl %1,"SYMBOL_NAME_STR(last_task_used_math)"\n\t" \ "jne 1f\n\t" \ "clts\n" \ diff --git a/include/asm-m68k/fpu.h b/include/asm-m68k/fpu.h index fc47dac0253c..717ecfa7fed8 100644 --- a/include/asm-m68k/fpu.h +++ b/include/asm-m68k/fpu.h @@ -18,23 +18,3 @@ #endif #endif /* __M68K_FPU_H */ -#ifndef __M68K_FPU_H -#define __M68K_FPU_H - -#include - -/* - * MAX floating point unit state size (FSAVE/FRESTORE) - */ - -#if defined(CONFIG_M68020) || defined(CONFIG_M68030) -#define FPSTATESIZE (216/sizeof(unsigned char)) -#elif defined(CONFIG_M68040) -#define FPSTATESIZE (96/sizeof(unsigned char)) -#elif defined(CONFIG_M68060) -#define FPSTATESIZE (12/sizeof(unsigned char)) -#else -#define FPSTATESIZE error no_cpu_type_configured -#endif - -#endif /* __M68K_FPU_H */ diff --git a/include/asm-m68k/hardirq.h b/include/asm-m68k/hardirq.h index e9d0136c363f..52465a74d1af 100644 --- a/include/asm-m68k/hardirq.h +++ b/include/asm-m68k/hardirq.h @@ -11,16 +11,3 @@ extern unsigned int local_irq_count[NR_CPUS]; #define hardirq_exit(cpu) (local_irq_count[cpu]--) #endif -#ifndef __M68K_HARDIRQ_H -#define __M68K_HARDIRQ_H - -extern unsigned int local_irq_count[NR_CPUS]; -#define in_interrupt() (local_irq_count[smp_processor_id()] != 0) - -#define hardirq_trylock(cpu) ((cpu)==0) /* always true */ -#define hardirq_endlock(cpu) do { } while (0) - -#define hardirq_enter(cpu) (local_irq_count[cpu]++) -#define hardirq_exit(cpu) (local_irq_count[cpu]--) - -#endif diff --git a/include/asm-m68k/init.h b/include/asm-m68k/init.h index 42938ae897fc..93a323fd67a2 100644 --- a/include/asm-m68k/init.h +++ b/include/asm-m68k/init.h @@ -1,14 +1,14 @@ #ifndef _M68K_INIT_H #define _M68K_INIT_H -/* Throwing the initialization code and data out is not supported yet... */ - -#define __init -#define __initdata -#define __initfunc(__arginit) __arginit +#define __init __attribute__ ((__section__ (".text.init"))) +#define __initdata __attribute__ ((__section__ (".data.init"))) +#define __initfunc(__arginit) \ + __arginit __init; \ + __arginit /* For assembly routines */ -#define __INIT -#define __FINIT -#define __INITDATA +#define __INIT .section ".text.init",#alloc,#execinstr +#define __FINIT .previous +#define __INITDATA .section ".data.init",#alloc,#write #endif diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h index c4e3068fa83a..151ff66d6420 100644 --- a/include/asm-m68k/semaphore.h +++ b/include/asm-m68k/semaphore.h @@ -1,6 +1,7 @@ #ifndef _M68K_SEMAPHORE_H #define _M68K_SEMAPHORE_H +#include #include #include #include @@ -38,6 +39,7 @@ static inline void wake_one_more(struct semaphore * sem) static inline int waking_non_zero(struct semaphore *sem) { +#ifndef CONFIG_RMW_INSNS unsigned long flags; int ret = 0; @@ -48,6 +50,21 @@ static inline int waking_non_zero(struct semaphore *sem) ret = 1; } restore_flags(flags); +#else + int ret, tmp; + + __asm__ __volatile__ + ("1: movel %2,%0\n" + " jeq 3f\n" + "2: movel %0,%1\n" + " subql #1,%1\n" + " casl %0,%1,%2\n" + " jeq 3f\n" + " tstl %0\n" + " jne 2b\n" + "3:" + : "=d" (ret), "=d" (tmp), "=m" (sem->waking)); +#endif return ret; } diff --git a/include/asm-m68k/sigcontext.h b/include/asm-m68k/sigcontext.h index 9c13b0951c14..a2d28c218a4e 100644 --- a/include/asm-m68k/sigcontext.h +++ b/include/asm-m68k/sigcontext.h @@ -1,8 +1,6 @@ #ifndef _ASM_M68k_SIGCONTEXT_H #define _ASM_M68k_SIGCONTEXT_H -#include - struct sigcontext { unsigned long sc_mask; /* old sigmask */ unsigned long sc_usp; /* old user stack pointer */ @@ -15,7 +13,7 @@ struct sigcontext { unsigned short sc_formatvec; unsigned long sc_fpregs[2*3]; /* room for two fp registers */ unsigned long sc_fpcntl[3]; - unsigned char sc_fpstate[FPSTATESIZE]; + unsigned char sc_fpstate[216]; }; #endif diff --git a/include/asm-sparc/asm_offsets.h b/include/asm-sparc/asm_offsets.h index 141c0d7cc6f4..b90462a69f37 100644 --- a/include/asm-sparc/asm_offsets.h +++ b/include/asm-sparc/asm_offsets.h @@ -30,148 +30,146 @@ #define ASIZ_task_next_run 0x00000004 #define AOFF_task_prev_run 0x00000050 #define ASIZ_task_prev_run 0x00000004 -#define AOFF_task_saved_kernel_stack 0x00000054 -#define ASIZ_task_saved_kernel_stack 0x00000004 -#define AOFF_task_kernel_stack_page 0x00000058 -#define ASIZ_task_kernel_stack_page 0x00000004 -#define AOFF_task_exit_code 0x0000005c +#define AOFF_task_exit_code 0x00000054 #define ASIZ_task_exit_code 0x00000004 -#define AOFF_task_exit_signal 0x00000060 +#define AOFF_task_exit_signal 0x00000058 #define ASIZ_task_exit_signal 0x00000004 -#define AOFF_task_personality 0x00000064 +#define AOFF_task_personality 0x0000005c #define ASIZ_task_personality 0x00000004 -#define AOFF_task_pid 0x0000006c +#define AOFF_task_pid 0x00000064 #define ASIZ_task_pid 0x00000004 -#define AOFF_task_pgrp 0x00000070 +#define AOFF_task_pgrp 0x00000068 #define ASIZ_task_pgrp 0x00000004 -#define AOFF_task_tty_old_pgrp 0x00000074 +#define AOFF_task_tty_old_pgrp 0x0000006c #define ASIZ_task_tty_old_pgrp 0x00000004 -#define AOFF_task_session 0x00000078 +#define AOFF_task_session 0x00000070 #define ASIZ_task_session 0x00000004 -#define AOFF_task_leader 0x0000007c +#define AOFF_task_leader 0x00000074 #define ASIZ_task_leader 0x00000004 -#define AOFF_task_ngroups 0x00000080 +#define AOFF_task_ngroups 0x00000078 #define ASIZ_task_ngroups 0x00000004 -#define AOFF_task_groups 0x00000084 +#define AOFF_task_groups 0x0000007c #define ASIZ_task_groups 0x00000040 -#define AOFF_task_p_opptr 0x000000c4 +#define AOFF_task_p_opptr 0x000000bc #define ASIZ_task_p_opptr 0x00000004 -#define AOFF_task_p_pptr 0x000000c8 +#define AOFF_task_p_pptr 0x000000c0 #define ASIZ_task_p_pptr 0x00000004 -#define AOFF_task_p_cptr 0x000000cc +#define AOFF_task_p_cptr 0x000000c4 #define ASIZ_task_p_cptr 0x00000004 -#define AOFF_task_p_ysptr 0x000000d0 +#define AOFF_task_p_ysptr 0x000000c8 #define ASIZ_task_p_ysptr 0x00000004 -#define AOFF_task_p_osptr 0x000000d4 +#define AOFF_task_p_osptr 0x000000cc #define ASIZ_task_p_osptr 0x00000004 -#define AOFF_task_pidhash_next 0x000000d8 +#define AOFF_task_pidhash_next 0x000000d0 #define ASIZ_task_pidhash_next 0x00000004 -#define AOFF_task_pidhash_pprev 0x000000dc +#define AOFF_task_pidhash_pprev 0x000000d4 #define ASIZ_task_pidhash_pprev 0x00000004 -#define AOFF_task_tarray_ptr 0x000000e0 +#define AOFF_task_tarray_ptr 0x000000d8 #define ASIZ_task_tarray_ptr 0x00000004 -#define AOFF_task_wait_chldexit 0x000000e4 +#define AOFF_task_wait_chldexit 0x000000dc #define ASIZ_task_wait_chldexit 0x00000004 -#define AOFF_task_uid 0x000000e8 +#define AOFF_task_uid 0x000000e0 #define ASIZ_task_uid 0x00000002 -#define AOFF_task_euid 0x000000ea +#define AOFF_task_euid 0x000000e2 #define ASIZ_task_euid 0x00000002 -#define AOFF_task_suid 0x000000ec +#define AOFF_task_suid 0x000000e4 #define ASIZ_task_suid 0x00000002 -#define AOFF_task_fsuid 0x000000ee +#define AOFF_task_fsuid 0x000000e6 #define ASIZ_task_fsuid 0x00000002 -#define AOFF_task_gid 0x000000f0 +#define AOFF_task_gid 0x000000e8 #define ASIZ_task_gid 0x00000002 -#define AOFF_task_egid 0x000000f2 +#define AOFF_task_egid 0x000000ea #define ASIZ_task_egid 0x00000002 -#define AOFF_task_sgid 0x000000f4 +#define AOFF_task_sgid 0x000000ec #define ASIZ_task_sgid 0x00000002 -#define AOFF_task_fsgid 0x000000f6 +#define AOFF_task_fsgid 0x000000ee #define ASIZ_task_fsgid 0x00000002 -#define AOFF_task_timeout 0x000000f8 +#define AOFF_task_timeout 0x000000f0 #define ASIZ_task_timeout 0x00000004 -#define AOFF_task_policy 0x000000fc +#define AOFF_task_policy 0x000000f4 #define ASIZ_task_policy 0x00000004 -#define AOFF_task_rt_priority 0x00000100 +#define AOFF_task_rt_priority 0x000000f8 #define ASIZ_task_rt_priority 0x00000004 -#define AOFF_task_it_real_value 0x00000104 +#define AOFF_task_it_real_value 0x000000fc #define ASIZ_task_it_real_value 0x00000004 -#define AOFF_task_it_prof_value 0x00000108 +#define AOFF_task_it_prof_value 0x00000100 #define ASIZ_task_it_prof_value 0x00000004 -#define AOFF_task_it_virt_value 0x0000010c +#define AOFF_task_it_virt_value 0x00000104 #define ASIZ_task_it_virt_value 0x00000004 -#define AOFF_task_it_real_incr 0x00000110 +#define AOFF_task_it_real_incr 0x00000108 #define ASIZ_task_it_real_incr 0x00000004 -#define AOFF_task_it_prof_incr 0x00000114 +#define AOFF_task_it_prof_incr 0x0000010c #define ASIZ_task_it_prof_incr 0x00000004 -#define AOFF_task_it_virt_incr 0x00000118 +#define AOFF_task_it_virt_incr 0x00000110 #define ASIZ_task_it_virt_incr 0x00000004 -#define AOFF_task_real_timer 0x0000011c +#define AOFF_task_real_timer 0x00000114 #define ASIZ_task_real_timer 0x00000014 -#define AOFF_task_utime 0x00000130 +#define AOFF_task_utime 0x00000128 #define ASIZ_task_utime 0x00000004 -#define AOFF_task_stime 0x00000134 +#define AOFF_task_stime 0x0000012c #define ASIZ_task_stime 0x00000004 -#define AOFF_task_cutime 0x00000138 +#define AOFF_task_cutime 0x00000130 #define ASIZ_task_cutime 0x00000004 -#define AOFF_task_cstime 0x0000013c +#define AOFF_task_cstime 0x00000134 #define ASIZ_task_cstime 0x00000004 -#define AOFF_task_start_time 0x00000140 +#define AOFF_task_start_time 0x00000138 #define ASIZ_task_start_time 0x00000004 -#define AOFF_task_min_flt 0x00000144 +#define AOFF_task_min_flt 0x0000013c #define ASIZ_task_min_flt 0x00000004 -#define AOFF_task_maj_flt 0x00000148 +#define AOFF_task_maj_flt 0x00000140 #define ASIZ_task_maj_flt 0x00000004 -#define AOFF_task_nswap 0x0000014c +#define AOFF_task_nswap 0x00000144 #define ASIZ_task_nswap 0x00000004 -#define AOFF_task_cmin_flt 0x00000150 +#define AOFF_task_cmin_flt 0x00000148 #define ASIZ_task_cmin_flt 0x00000004 -#define AOFF_task_cmaj_flt 0x00000154 +#define AOFF_task_cmaj_flt 0x0000014c #define ASIZ_task_cmaj_flt 0x00000004 -#define AOFF_task_cnswap 0x00000158 +#define AOFF_task_cnswap 0x00000150 #define ASIZ_task_cnswap 0x00000004 -#define AOFF_task_swap_address 0x00000160 +#define AOFF_task_swap_address 0x00000158 #define ASIZ_task_swap_address 0x00000004 -#define AOFF_task_old_maj_flt 0x00000164 +#define AOFF_task_old_maj_flt 0x0000015c #define ASIZ_task_old_maj_flt 0x00000004 -#define AOFF_task_dec_flt 0x00000168 +#define AOFF_task_dec_flt 0x00000160 #define ASIZ_task_dec_flt 0x00000004 -#define AOFF_task_swap_cnt 0x0000016c +#define AOFF_task_swap_cnt 0x00000164 #define ASIZ_task_swap_cnt 0x00000004 -#define AOFF_task_rlim 0x00000170 +#define AOFF_task_rlim 0x00000168 #define ASIZ_task_rlim 0x00000050 -#define AOFF_task_used_math 0x000001c0 +#define AOFF_task_used_math 0x000001b8 #define ASIZ_task_used_math 0x00000002 -#define AOFF_task_comm 0x000001c2 +#define AOFF_task_comm 0x000001ba #define ASIZ_task_comm 0x00000010 -#define AOFF_task_link_count 0x000001d4 +#define AOFF_task_link_count 0x000001cc #define ASIZ_task_link_count 0x00000004 -#define AOFF_task_tty 0x000001d8 +#define AOFF_task_tty 0x000001d0 #define ASIZ_task_tty 0x00000004 -#define AOFF_task_semundo 0x000001dc +#define AOFF_task_semundo 0x000001d4 #define ASIZ_task_semundo 0x00000004 -#define AOFF_task_semsleeping 0x000001e0 +#define AOFF_task_semsleeping 0x000001d8 #define ASIZ_task_semsleeping 0x00000004 -#define AOFF_task_ldt 0x000001e4 +#define AOFF_task_ldt 0x000001dc #define ASIZ_task_ldt 0x00000004 -#define AOFF_task_tss 0x000001e8 +#define AOFF_task_tss 0x000001e0 #define ASIZ_task_tss 0x00000390 -#define AOFF_task_fs 0x00000578 +#define AOFF_task_fs 0x00000570 #define ASIZ_task_fs 0x00000004 -#define AOFF_task_files 0x0000057c +#define AOFF_task_files 0x00000574 #define ASIZ_task_files 0x00000004 -#define AOFF_task_mm 0x00000580 +#define AOFF_task_mm 0x00000578 #define ASIZ_task_mm 0x00000004 -#define AOFF_task_sig 0x00000584 +#define AOFF_task_sig 0x0000057c #define ASIZ_task_sig 0x00000004 -#define AOFF_task_processor 0x00000588 +#define AOFF_task_has_cpu 0x00000580 +#define ASIZ_task_has_cpu 0x00000004 +#define AOFF_task_processor 0x00000584 #define ASIZ_task_processor 0x00000004 -#define AOFF_task_last_processor 0x0000058c +#define AOFF_task_last_processor 0x00000588 #define ASIZ_task_last_processor 0x00000004 -#define AOFF_task_lock_depth 0x00000590 +#define AOFF_task_lock_depth 0x0000058c #define ASIZ_task_lock_depth 0x00000004 -#define AOFF_task_sigmask_lock 0x00000594 -#define ASIZ_task_sigmask_lock 0x00000001 +#define AOFF_task_sigmask_lock 0x00000590 +#define ASIZ_task_sigmask_lock 0x00000000 #define AOFF_mm_mmap 0x00000000 #define ASIZ_mm_mmap 0x00000004 #define AOFF_mm_mmap_cache 0x00000004 diff --git a/include/asm-sparc/asmmacro.h b/include/asm-sparc/asmmacro.h index 25211c93f828..40c71b0d6cb2 100644 --- a/include/asm-sparc/asmmacro.h +++ b/include/asm-sparc/asmmacro.h @@ -6,22 +6,22 @@ #ifndef _SPARC_ASMMACRO_H #define _SPARC_ASMMACRO_H -/* #define SMP_DEBUG */ - #define GET_PROCESSOR_ID(reg) \ rd %tbr, %reg; \ srl %reg, 12, %reg; \ and %reg, 3, %reg; #define GET_PROCESSOR_MID(reg, tmp) \ - GET_PROCESSOR_ID(reg) \ - set C_LABEL(mid_xlate), %tmp; \ + rd %tbr, %reg; \ + sethi C_LABEL(mid_xlate), %tmp; \ + srl %reg, 12, %reg; \ + or %tmp, %lo(C_LABEL(mid_xlate)), %tmp; \ + and %reg, 3, %reg; \ ldub [%tmp + %reg], %reg; #define GET_PROCESSOR_OFFSET(reg) \ - rd %tbr, %reg; \ - srl %reg, 10, %reg; \ - and %reg, 0xc, %reg; + GET_PROCESSOR_ID(reg) \ + sll %reg, 2, %reg; #define PROCESSOR_OFFSET_TO_ID(reg) \ srl %reg, 2, %reg; diff --git a/include/asm-sparc/auxio.h b/include/asm-sparc/auxio.h index f5b9d5591fd3..f70a447bf121 100644 --- a/include/asm-sparc/auxio.h +++ b/include/asm-sparc/auxio.h @@ -1,4 +1,4 @@ -/* $Id: auxio.h,v 1.16 1997/01/31 23:26:05 tdyas Exp $ +/* $Id: auxio.h,v 1.17 1997/05/01 01:42:02 davem Exp $ * auxio.h: Definitions and code for the Auxiliary I/O register. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -43,30 +43,27 @@ extern unsigned char *auxio_register; #define FLPY_TCNTOFF if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_FLPY_TCNT)) #ifndef __ASSEMBLY__ -extern __inline__ void set_auxio(unsigned char bits_on, unsigned char bits_off) -{ - unsigned char regval; - unsigned long flags; - - save_flags(flags); cli(); - - switch(sparc_cpu_model) { - case sun4c: - regval = *AUXREG; - *AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN; - break; - case sun4m: - if(!AUXREG) - break; /* VME chassic sun4m, no auxio. */ - regval = *AUXREG; - *AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M; - break; - default: - panic("Can't set AUXIO register on this machine."); - }; - - restore_flags(flags); -} +#define set_auxio(bits_on, bits_off) \ +do { \ + unsigned char regval; \ + unsigned long flags; \ + save_flags(flags); cli(); \ + switch(sparc_cpu_model) { \ + case sun4c: \ + regval = *AUXREG; \ + *AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN; \ + break; \ + case sun4m: \ + if(!AUXREG) \ + break; /* VME chassic sun4m, no auxio. */ \ + regval = *AUXREG; \ + *AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M; \ + break; \ + default: \ + panic("Can't set AUXIO register on this machine."); \ + }; \ + restore_flags(flags); \ +} while(0) #endif /* !(__ASSEMBLY__) */ diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h index d3ddb74e38a8..45a7169fd635 100644 --- a/include/asm-sparc/processor.h +++ b/include/asm-sparc/processor.h @@ -1,4 +1,4 @@ -/* $Id: processor.h,v 1.58 1997/04/25 03:13:16 davem Exp $ +/* $Id: processor.h,v 1.59 1997/05/01 01:42:03 davem Exp $ * include/asm-sparc/processor.h * * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) @@ -144,11 +144,14 @@ extern __inline__ void start_thread(struct pt_regs * regs, unsigned long pc, #define release_thread(tsk) do { } while(0) #ifdef __KERNEL__ + /* Allocation and freeing of basic task resources. */ -extern unsigned long (*alloc_kernel_stack)(struct task_struct *tsk); -extern void (*free_kernel_stack)(unsigned long stack); extern struct task_struct *(*alloc_task_struct)(void); extern void (*free_task_struct)(struct task_struct *tsk); + +#define init_task (init_task_union.task) +#define init_stack (init_task_union.stack) + #endif #endif /* __ASM_SPARC_PROCESSOR_H */ diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h index 48da860e45eb..eac2160e7534 100644 --- a/include/asm-sparc/semaphore.h +++ b/include/asm-sparc/semaphore.h @@ -28,20 +28,18 @@ extern void __up(struct semaphore * sem); * XXX spinlock can allow this to be done without grabbing the IRQ * XXX global lock. */ -static inline int waking_non_zero(struct semaphore *sem) -{ - unsigned long flags; - int ret = 0; - - save_flags(flags); - cli(); - if (atomic_read(&sem->waking) > 0) { - atomic_dec(&sem->waking); - ret = 1; - } - restore_flags(flags); - return ret; -} +#define waking_non_zero(sem) \ +({ unsigned long flags; \ + int ret = 0; \ + save_flags(flags); \ + cli(); \ + if (atomic_read(&sem->waking) > 0) { \ + atomic_dec(&sem->waking); \ + ret = 1; \ + } \ + restore_flags(flags); \ + ret; \ +}) /* This isn't quite as clever as the x86 side, I'll be fixing this * soon enough. diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h index 7d4106b03a9e..106fa4e1b057 100644 --- a/include/asm-sparc/smp.h +++ b/include/asm-sparc/smp.h @@ -85,7 +85,7 @@ extern __volatile__ int cpu_number_map[NR_CPUS]; extern __volatile__ int cpu_logical_map[NR_CPUS]; extern unsigned long smp_proc_in_lock[NR_CPUS]; -extern __inline__ int smp_processor_id(void) +extern __inline__ int hard_smp_processor_id(void) { int cpuid; @@ -96,6 +96,8 @@ extern __inline__ int smp_processor_id(void) return cpuid; } +#define smp_processor_id() hard_smp_processor_id() + #endif /* !(__ASSEMBLY__) */ /* Sparc specific messages. */ diff --git a/include/asm-sparc/spinlock.h b/include/asm-sparc/spinlock.h index 877b7416a15b..9d00bf578584 100644 --- a/include/asm-sparc/spinlock.h +++ b/include/asm-sparc/spinlock.h @@ -151,7 +151,7 @@ do { \ "b,a 1b\n\t" \ ".previous\n" \ : "=r" (flags) \ - : "i" (PSR_PIL), "r" (lock) \ + : "i" (PSR_PIL), "r" (lp) \ : "g2", "memory", "cc"); \ } while(0) @@ -198,7 +198,7 @@ typedef struct { volatile unsigned int lock; } rwlock_t; * * Unfortunately this scheme limits us to ~65,000 cpus. */ -extern __inline__ void read_lock(rwlock_t *rw) +extern __inline__ void _read_lock(rwlock_t *rw) { register rwlock_t *lp asm("g1"); lp = rw; @@ -211,7 +211,14 @@ extern __inline__ void read_lock(rwlock_t *rw) : "g2", "g4", "g7", "memory", "cc"); } -extern __inline__ void read_unlock(rwlock_t *rw) +#define read_lock(lock) \ +do { unsigned long flags; \ + __save_and_cli(flags); \ + _read_lock(lock); \ + __restore_flags(flags); \ +} while(0) + +extern __inline__ void _read_unlock(rwlock_t *rw) { register rwlock_t *lp asm("g1"); lp = rw; @@ -224,6 +231,13 @@ extern __inline__ void read_unlock(rwlock_t *rw) : "g2", "g4", "g7", "memory", "cc"); } +#define read_unlock(lock) \ +do { unsigned long flags; \ + __save_and_cli(flags); \ + _read_unlock(lock); \ + __restore_flags(flags); \ +} while(0) + extern __inline__ void write_lock(rwlock_t *rw) { register rwlock_t *lp asm("g1"); @@ -238,15 +252,15 @@ extern __inline__ void write_lock(rwlock_t *rw) } #define write_unlock(rw) do { (rw)->lock = 0; } while(0) -#define read_lock_irq(lock) do { __cli(); read_lock(lock); } while (0) -#define read_unlock_irq(lock) do { read_unlock(lock); __sti(); } while (0) +#define read_lock_irq(lock) do { __cli(); _read_lock(lock); } while (0) +#define read_unlock_irq(lock) do { _read_unlock(lock); __sti(); } while (0) #define write_lock_irq(lock) do { __cli(); write_lock(lock); } while (0) #define write_unlock_irq(lock) do { write_unlock(lock); __sti(); } while (0) #define read_lock_irqsave(lock, flags) \ - do { __save_and_cli(flags); read_lock(lock); } while (0) + do { __save_and_cli(flags); _read_lock(lock); } while (0) #define read_unlock_irqrestore(lock, flags) \ - do { read_unlock(lock); __restore_flags(flags); } while (0) + do { _read_unlock(lock); __restore_flags(flags); } while (0) #define write_lock_irqsave(lock, flags) \ do { __save_and_cli(flags); write_lock(lock); } while (0) #define write_unlock_irqrestore(lock, flags) \ diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h index e1d33e436138..eb33242c23a4 100644 --- a/include/asm-sparc/system.h +++ b/include/asm-sparc/system.h @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.58 1997/04/18 05:44:54 davem Exp $ */ +/* $Id: system.h,v 1.60 1997/05/01 02:26:56 davem Exp $ */ #ifndef __SPARC_SYSTEM_H #define __SPARC_SYSTEM_H @@ -108,7 +108,7 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, "nop\n\t" \ "nop\n\t" \ "jmpl %%o7 + 0x8, %%g0\n\t" \ - " nop\n\t" : : "r" (&(current_set[smp_processor_id()])), "r" (next), \ + " nop\n\t" : : "r" (&(current_set[hard_smp_processor_id()])), "r" (next), \ "i" ((const unsigned long)(&((struct task_struct *)0)->tss.kpsr)), \ "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ksp)), \ "r" (task_pc) \ @@ -233,12 +233,8 @@ do { register unsigned long bits asm("g7"); \ extern unsigned char global_irq_holder; #define save_flags(x) \ -do { int cpuid; \ - __asm__ __volatile__("rd %%tbr, %0; srl %0, 12, %0; and %0, 3, %0" \ - : "=r" (cpuid)); \ - ((x) = ((global_irq_holder == (unsigned char) cpuid) ? 1 : \ - ((getipl() & PSR_PIL) ? 2 : 0))); \ -} while(0) +do { ((x) = ((global_irq_holder == (unsigned char) smp_processor_id()) ? 1 : \ + ((getipl() & PSR_PIL) ? 2 : 0))); } while(0) #define restore_flags(flags) \ do { register unsigned long bits asm("g7"); \ diff --git a/include/asm-sparc/winmacro.h b/include/asm-sparc/winmacro.h index 8ba88ec61329..cb2f4e73b430 100644 --- a/include/asm-sparc/winmacro.h +++ b/include/asm-sparc/winmacro.h @@ -1,4 +1,4 @@ -/* $Id: winmacro.h,v 1.18 1997/03/04 16:27:27 jj Exp $ +/* $Id: winmacro.h,v 1.19 1997/05/01 01:42:05 davem Exp $ * winmacro.h: Window loading-unloading macros. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -114,12 +114,11 @@ #ifdef __SMP__ #define LOAD_CURRENT(dest_reg, idreg) \ rd %tbr, %idreg; \ - srl %idreg, 10, %idreg; \ - and %idreg, 0xc, %idreg; \ sethi %hi(C_LABEL(current_set)), %dest_reg; \ + srl %idreg, 10, %idreg; \ or %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \ - add %dest_reg, %idreg, %idreg; \ - ld [%idreg], %dest_reg; + and %idreg, 0xc, %idreg; \ + ld [%idreg + %dest_reg], %dest_reg; #else #define LOAD_CURRENT(dest_reg, idreg) \ sethi %hi(C_LABEL(current_set)), %idreg; \ diff --git a/include/asm-sparc64/asm_offsets.h b/include/asm-sparc64/asm_offsets.h index a232d9e80d8a..fff6e28230d7 100644 --- a/include/asm-sparc64/asm_offsets.h +++ b/include/asm-sparc64/asm_offsets.h @@ -64,150 +64,158 @@ #define ASIZ_task_p_ysptr 0x00000008 #define AOFF_task_p_osptr 0x00000188 #define ASIZ_task_p_osptr 0x00000008 -#define AOFF_task_wait_chldexit 0x00000190 +#define AOFF_task_pidhash_next 0x00000190 +#define ASIZ_task_pidhash_next 0x00000008 +#define AOFF_task_pidhash_pprev 0x00000198 +#define ASIZ_task_pidhash_pprev 0x00000008 +#define AOFF_task_tarray_ptr 0x000001a0 +#define ASIZ_task_tarray_ptr 0x00000008 +#define AOFF_task_wait_chldexit 0x000001a8 #define ASIZ_task_wait_chldexit 0x00000008 -#define AOFF_task_uid 0x00000198 +#define AOFF_task_uid 0x000001b0 #define ASIZ_task_uid 0x00000002 -#define AOFF_task_euid 0x0000019a +#define AOFF_task_euid 0x000001b2 #define ASIZ_task_euid 0x00000002 -#define AOFF_task_suid 0x0000019c +#define AOFF_task_suid 0x000001b4 #define ASIZ_task_suid 0x00000002 -#define AOFF_task_fsuid 0x0000019e +#define AOFF_task_fsuid 0x000001b6 #define ASIZ_task_fsuid 0x00000002 -#define AOFF_task_gid 0x000001a0 +#define AOFF_task_gid 0x000001b8 #define ASIZ_task_gid 0x00000002 -#define AOFF_task_egid 0x000001a2 +#define AOFF_task_egid 0x000001ba #define ASIZ_task_egid 0x00000002 -#define AOFF_task_sgid 0x000001a4 +#define AOFF_task_sgid 0x000001bc #define ASIZ_task_sgid 0x00000002 -#define AOFF_task_fsgid 0x000001a6 +#define AOFF_task_fsgid 0x000001be #define ASIZ_task_fsgid 0x00000002 -#define AOFF_task_timeout 0x000001a8 +#define AOFF_task_timeout 0x000001c0 #define ASIZ_task_timeout 0x00000008 -#define AOFF_task_policy 0x000001b0 +#define AOFF_task_policy 0x000001c8 #define ASIZ_task_policy 0x00000008 -#define AOFF_task_rt_priority 0x000001b8 +#define AOFF_task_rt_priority 0x000001d0 #define ASIZ_task_rt_priority 0x00000008 -#define AOFF_task_it_real_value 0x000001c0 +#define AOFF_task_it_real_value 0x000001d8 #define ASIZ_task_it_real_value 0x00000008 -#define AOFF_task_it_prof_value 0x000001c8 +#define AOFF_task_it_prof_value 0x000001e0 #define ASIZ_task_it_prof_value 0x00000008 -#define AOFF_task_it_virt_value 0x000001d0 +#define AOFF_task_it_virt_value 0x000001e8 #define ASIZ_task_it_virt_value 0x00000008 -#define AOFF_task_it_real_incr 0x000001d8 +#define AOFF_task_it_real_incr 0x000001f0 #define ASIZ_task_it_real_incr 0x00000008 -#define AOFF_task_it_prof_incr 0x000001e0 +#define AOFF_task_it_prof_incr 0x000001f8 #define ASIZ_task_it_prof_incr 0x00000008 -#define AOFF_task_it_virt_incr 0x000001e8 +#define AOFF_task_it_virt_incr 0x00000200 #define ASIZ_task_it_virt_incr 0x00000008 -#define AOFF_task_real_timer 0x000001f0 +#define AOFF_task_real_timer 0x00000208 #define ASIZ_task_real_timer 0x00000028 -#define AOFF_task_utime 0x00000218 +#define AOFF_task_utime 0x00000230 #define ASIZ_task_utime 0x00000008 -#define AOFF_task_stime 0x00000220 +#define AOFF_task_stime 0x00000238 #define ASIZ_task_stime 0x00000008 -#define AOFF_task_cutime 0x00000228 +#define AOFF_task_cutime 0x00000240 #define ASIZ_task_cutime 0x00000008 -#define AOFF_task_cstime 0x00000230 +#define AOFF_task_cstime 0x00000248 #define ASIZ_task_cstime 0x00000008 -#define AOFF_task_start_time 0x00000238 +#define AOFF_task_start_time 0x00000250 #define ASIZ_task_start_time 0x00000008 -#define AOFF_task_min_flt 0x00000240 +#define AOFF_task_min_flt 0x00000258 #define ASIZ_task_min_flt 0x00000008 -#define AOFF_task_maj_flt 0x00000248 +#define AOFF_task_maj_flt 0x00000260 #define ASIZ_task_maj_flt 0x00000008 -#define AOFF_task_nswap 0x00000250 +#define AOFF_task_nswap 0x00000268 #define ASIZ_task_nswap 0x00000008 -#define AOFF_task_cmin_flt 0x00000258 +#define AOFF_task_cmin_flt 0x00000270 #define ASIZ_task_cmin_flt 0x00000008 -#define AOFF_task_cmaj_flt 0x00000260 +#define AOFF_task_cmaj_flt 0x00000278 #define ASIZ_task_cmaj_flt 0x00000008 -#define AOFF_task_cnswap 0x00000268 +#define AOFF_task_cnswap 0x00000280 #define ASIZ_task_cnswap 0x00000008 -#define AOFF_task_swap_address 0x00000278 +#define AOFF_task_swap_address 0x00000290 #define ASIZ_task_swap_address 0x00000008 -#define AOFF_task_old_maj_flt 0x00000280 +#define AOFF_task_old_maj_flt 0x00000298 #define ASIZ_task_old_maj_flt 0x00000008 -#define AOFF_task_dec_flt 0x00000288 +#define AOFF_task_dec_flt 0x000002a0 #define ASIZ_task_dec_flt 0x00000008 -#define AOFF_task_swap_cnt 0x00000290 +#define AOFF_task_swap_cnt 0x000002a8 #define ASIZ_task_swap_cnt 0x00000008 -#define AOFF_task_rlim 0x00000298 +#define AOFF_task_rlim 0x000002b0 #define ASIZ_task_rlim 0x000000a0 -#define AOFF_task_used_math 0x00000338 +#define AOFF_task_used_math 0x00000350 #define ASIZ_task_used_math 0x00000002 -#define AOFF_task_comm 0x0000033a +#define AOFF_task_comm 0x00000352 #define ASIZ_task_comm 0x00000010 -#define AOFF_task_link_count 0x0000034c +#define AOFF_task_link_count 0x00000364 #define ASIZ_task_link_count 0x00000004 -#define AOFF_task_tty 0x00000350 +#define AOFF_task_tty 0x00000368 #define ASIZ_task_tty 0x00000008 -#define AOFF_task_semundo 0x00000358 +#define AOFF_task_semundo 0x00000370 #define ASIZ_task_semundo 0x00000008 -#define AOFF_task_semsleeping 0x00000360 +#define AOFF_task_semsleeping 0x00000378 #define ASIZ_task_semsleeping 0x00000008 -#define AOFF_task_ldt 0x00000368 +#define AOFF_task_ldt 0x00000380 #define ASIZ_task_ldt 0x00000008 -#define AOFF_task_tss 0x00000380 +#define AOFF_task_tss 0x000003c0 #define ASIZ_task_tss 0x00000600 -#define AOFF_task_fs 0x00000980 +#define AOFF_task_fs 0x000009c0 #define ASIZ_task_fs 0x00000008 -#define AOFF_task_files 0x00000988 +#define AOFF_task_files 0x000009c8 #define ASIZ_task_files 0x00000008 -#define AOFF_task_mm 0x00000990 +#define AOFF_task_mm 0x000009d0 #define ASIZ_task_mm 0x00000008 -#define AOFF_task_sig 0x00000998 +#define AOFF_task_sig 0x000009d8 #define ASIZ_task_sig 0x00000008 -#define AOFF_task_processor 0x000009a0 +#define AOFF_task_processor 0x000009e0 #define ASIZ_task_processor 0x00000004 -#define AOFF_task_last_processor 0x000009a4 +#define AOFF_task_last_processor 0x000009e4 #define ASIZ_task_last_processor 0x00000004 -#define AOFF_task_lock_depth 0x000009a8 +#define AOFF_task_lock_depth 0x000009e8 #define ASIZ_task_lock_depth 0x00000004 -#define AOFF_mm_count 0x00000000 -#define ASIZ_mm_count 0x00000004 -#define AOFF_mm_pgd 0x00000008 +#define AOFF_task_sigmask_lock 0x000009ec +#define ASIZ_task_sigmask_lock 0x00000000 +#define AOFF_mm_mmap 0x00000000 +#define ASIZ_mm_mmap 0x00000008 +#define AOFF_mm_mmap_cache 0x00000008 +#define ASIZ_mm_mmap_cache 0x00000008 +#define AOFF_mm_pgd 0x00000010 #define ASIZ_mm_pgd 0x00000008 -#define AOFF_mm_context 0x00000010 +#define AOFF_mm_count 0x00000018 +#define ASIZ_mm_count 0x00000004 +#define AOFF_mm_mmap_sem 0x00000020 +#define ASIZ_mm_mmap_sem 0x00000010 +#define AOFF_mm_context 0x00000030 #define ASIZ_mm_context 0x00000008 -#define AOFF_mm_start_code 0x00000018 +#define AOFF_mm_start_code 0x00000038 #define ASIZ_mm_start_code 0x00000008 -#define AOFF_mm_end_code 0x00000020 +#define AOFF_mm_end_code 0x00000040 #define ASIZ_mm_end_code 0x00000008 -#define AOFF_mm_start_data 0x00000028 +#define AOFF_mm_start_data 0x00000048 #define ASIZ_mm_start_data 0x00000008 -#define AOFF_mm_end_data 0x00000030 +#define AOFF_mm_end_data 0x00000050 #define ASIZ_mm_end_data 0x00000008 -#define AOFF_mm_start_brk 0x00000038 +#define AOFF_mm_start_brk 0x00000058 #define ASIZ_mm_start_brk 0x00000008 -#define AOFF_mm_brk 0x00000040 +#define AOFF_mm_brk 0x00000060 #define ASIZ_mm_brk 0x00000008 -#define AOFF_mm_start_stack 0x00000048 +#define AOFF_mm_start_stack 0x00000068 #define ASIZ_mm_start_stack 0x00000008 -#define AOFF_mm_start_mmap 0x00000050 +#define AOFF_mm_start_mmap 0x00000070 #define ASIZ_mm_start_mmap 0x00000008 -#define AOFF_mm_arg_start 0x00000058 +#define AOFF_mm_arg_start 0x00000078 #define ASIZ_mm_arg_start 0x00000008 -#define AOFF_mm_arg_end 0x00000060 +#define AOFF_mm_arg_end 0x00000080 #define ASIZ_mm_arg_end 0x00000008 -#define AOFF_mm_env_start 0x00000068 +#define AOFF_mm_env_start 0x00000088 #define ASIZ_mm_env_start 0x00000008 -#define AOFF_mm_env_end 0x00000070 +#define AOFF_mm_env_end 0x00000090 #define ASIZ_mm_env_end 0x00000008 -#define AOFF_mm_rss 0x00000078 +#define AOFF_mm_rss 0x00000098 #define ASIZ_mm_rss 0x00000008 -#define AOFF_mm_total_vm 0x00000080 +#define AOFF_mm_total_vm 0x000000a0 #define ASIZ_mm_total_vm 0x00000008 -#define AOFF_mm_locked_vm 0x00000088 +#define AOFF_mm_locked_vm 0x000000a8 #define ASIZ_mm_locked_vm 0x00000008 -#define AOFF_mm_def_flags 0x00000090 +#define AOFF_mm_def_flags 0x000000b0 #define ASIZ_mm_def_flags 0x00000008 -#define AOFF_mm_mmap 0x00000098 -#define ASIZ_mm_mmap 0x00000008 -#define AOFF_mm_mmap_avl 0x000000a0 -#define ASIZ_mm_mmap_avl 0x00000008 -#define AOFF_mm_mmap_sem 0x000000a8 -#define ASIZ_mm_mmap_sem 0x00000010 #define AOFF_thread_float_regs 0x00000000 #define ASIZ_thread_float_regs 0x00000100 #define AOFF_thread_fsr 0x00000100 diff --git a/include/asm-sparc64/head.h b/include/asm-sparc64/head.h index 60ed4ca66102..6ca263515aaf 100644 --- a/include/asm-sparc64/head.h +++ b/include/asm-sparc64/head.h @@ -1,4 +1,4 @@ -/* $Id: head.h,v 1.16 1997/04/08 11:03:13 davem Exp $ */ +/* $Id: head.h,v 1.17 1997/04/28 14:57:13 davem Exp $ */ #ifndef _SPARC64_HEAD_H #define _SPARC64_HEAD_H @@ -113,7 +113,7 @@ #define INDIRECT_SOLARIS_SYSCALL(tlvl) TRAP_ARG(indirect_syscall, tlvl) #define TRAP_IRQ(routine, level) \ - rdpr %pil, %g4; \ + rdpr %pil, %g2; \ wrpr %g0, 15, %pil; \ ba,pt %xcc, etrap_irq; \ rd %pc, %g7; \ diff --git a/include/linux/affs_fs.h b/include/linux/affs_fs.h index 0067552fc7c0..fc7c46dc842d 100644 --- a/include/linux/affs_fs.h +++ b/include/linux/affs_fs.h @@ -22,9 +22,9 @@ struct DateStamp { - __u32 ds_Days; - __u32 ds_Minute; - __u32 ds_Tick; + u32 ds_Days; + u32 ds_Minute; + u32 ds_Tick; }; @@ -32,66 +32,58 @@ struct DateStamp /* amigaffs.c */ -extern int affs_get_key_entry(int bsize, void *data, int entry_pos); -extern int affs_find_next_hash_entry(int bsize, void *dir_data, int *hash_pos); -extern int affs_get_file_name(int bsize, void *fh_data, char **name); -extern unsigned int affs_checksum_block(int bsize, void *data, int *ptype, int *stype); -extern void affs_fix_checksum(int bsize, void *data, int cspos); -extern void secs_to_datestamp(int secs, struct DateStamp *ds); -extern int prot_to_mode(unsigned int prot); -extern unsigned int mode_to_prot(int mode); -extern int affs_fix_hash_pred(struct inode *startino, int startoffset, - int key, int newkey); -extern int affs_fix_link_pred(struct inode *startino, int key, int newkey); +extern int affs_get_key_entry(int bsize, void *data, int entry_pos); +extern int affs_get_file_name(int bsize, void *fh_data, char **name); +extern u32 affs_checksum_block(int bsize, void *data, s32 *ptype, s32 *stype); +extern void affs_fix_checksum(int bsize, void *data, int cspos); +extern void secs_to_datestamp(time_t secs, struct DateStamp *ds); +extern int prot_to_mode(unsigned int prot); +extern u32 mode_to_prot(int mode); +extern int affs_fix_hash_pred(struct inode *startino, int startoffset, + s32 key, s32 newkey); +extern int affs_fix_link_pred(struct inode *startino, s32 key, s32 newkey); +extern void affs_error(struct super_block *sb, const char *function, const char *fmt, ...); +extern void affs_warning(struct super_block *sb, const char *function, const char *fmt, ...); /* bitmap. c */ -extern int affs_count_free_blocks(struct super_block *s); -extern int affs_count_free_bits(int blocksize, const char *data); -extern void affs_free_block(struct super_block *sb, int block); -extern int affs_new_header(struct inode *inode); -extern int affs_new_data(struct inode *inode); -extern void affs_make_zones(struct super_block *sb); +extern int affs_count_free_blocks(struct super_block *s); +extern int affs_count_free_bits(int blocksize, const char *data); +extern void affs_free_block(struct super_block *sb, s32 block); +extern s32 affs_new_header(struct inode *inode); +extern s32 affs_new_data(struct inode *inode); +extern void affs_make_zones(struct super_block *sb); /* namei.c */ -extern int affs_hash_name(const char *name, int len, int intl, int hashsize); -extern int affs_lookup(struct inode *dir,const char *name, int len, - struct inode **result); -extern int affs_unlink(struct inode *dir, const char *name, int len); -extern int affs_create(struct inode *dir, const char *name, int len, int mode, - struct inode **result); -extern int affs_mkdir(struct inode *dir, const char *name, int len, int mode); -extern int affs_rmdir(struct inode *dir, const char *name, int len); -extern int affs_link(struct inode *oldinode, struct inode *dir, - const char *name, int len); -extern int affs_symlink(struct inode *dir, const char *name, int len, - const char *symname); -extern int affs_fixup(struct buffer_head *bh, struct inode *inode); -extern int affs_rename(struct inode *old_dir, const char *old_name, int old_len, - struct inode *new_dir, const char *new_name, int new_len, - int must_be_dir); +extern int affs_hash_name(const char *name, int len, int intl, int hashsize); +extern int affs_lookup(struct inode *dir,const char *name, int len, + struct inode **result); +extern int affs_unlink(struct inode *dir, const char *name, int len); +extern int affs_create(struct inode *dir, const char *name, int len, int mode, + struct inode **result); +extern int affs_mkdir(struct inode *dir, const char *name, int len, int mode); +extern int affs_rmdir(struct inode *dir, const char *name, int len); +extern int affs_link(struct inode *oldinode, struct inode *dir, + const char *name, int len); +extern int affs_symlink(struct inode *dir, const char *name, int len, + const char *symname); +extern int affs_rename(struct inode *old_dir, const char *old_name, int old_len, + struct inode *new_dir, const char *new_name, int new_len, + int must_be_dir); /* inode.c */ extern struct buffer_head *affs_bread(kdev_t dev, int block, int size); extern void affs_brelse(struct buffer_head *buf); -extern void affs_put_super(struct super_block *); -extern int affs_parent_ino(struct inode *dir); -extern struct super_block *affs_read_super(struct super_block *,void *, int); -extern void affs_statfs(struct super_block *, struct statfs *, int bufsiz); -extern void affs_read_inode(struct inode *); -extern void affs_write_inode(struct inode *); -extern int affs_notify_change(struct inode *inode, struct iattr *attr); -extern void affs_put_inode(struct inode *); +extern unsigned long affs_parent_ino(struct inode *dir); extern struct inode *affs_new_inode(const struct inode *dir); -extern int affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, - const char *name, int len, int type); +extern int affs_add_entry(struct inode *dir, struct inode *link, + struct inode *inode, const char *name, + int len, s32 type); /* file.c */ -extern int affs_bmap(struct inode *inode, int block); -extern struct buffer_head *affs_getblock(struct inode *inode, int block); extern void affs_truncate(struct inode *); extern void affs_truncate_ofs(struct inode *); diff --git a/include/linux/affs_fs_i.h b/include/linux/affs_fs_i.h index 40b8239098a4..beeabb0de9c8 100644 --- a/include/linux/affs_fs_i.h +++ b/include/linux/affs_fs_i.h @@ -9,19 +9,19 @@ struct key_cache { struct timeval kc_lru_time; /* Last time this cache was used */ - int kc_first; /* First cached key */ - int kc_last; /* Last cached key */ - int kc_this_key; /* Key of extension block this data block keys are from */ + s32 kc_first; /* First cached key */ + s32 kc_last; /* Last cached key */ + s32 kc_this_key; /* Key of extension block this data block keys are from */ int kc_this_seq; /* Sequence number of this extension block */ - int kc_next_key; /* Key of next extension block */ - int kc_keys[AFFS_KCSIZE]; /* Key cache */ + s32 kc_next_key; /* Key of next extension block */ + s32 kc_keys[AFFS_KCSIZE]; /* Key cache */ }; #define EC_SIZE (PAGE_SIZE - 4 * sizeof(struct key_cache) - 4) / 4 struct ext_cache { struct key_cache kc[4]; /* The 4 key caches */ - __s32 ec[EC_SIZE]; /* Keys of assorted extension blocks */ + s32 ec[EC_SIZE]; /* Keys of assorted extension blocks */ int max_ext; /* Index of last known extension block */ }; @@ -29,18 +29,18 @@ struct ext_cache { * affs fs inode data in memory */ struct affs_inode_info { - __u32 i_protect; /* unused attribute bits */ - __s32 i_parent; /* parent ino */ - __s32 i_original; /* if != 0, this is the key of the original */ - __s32 i_data[AFFS_MAX_PREALLOC]; /* preallocated blocks */ - struct ext_cache *i_ec; /* Cache gets allocated dynamically */ - int i_cache_users; /* Cache cannot be freed while > 0 */ - int i_lastblock; /* last allocated block */ - short i_pa_cnt; /* number of preallocated blocks */ - short i_pa_next; /* Index of next block in i_data[] */ - short i_pa_last; /* Index of next free slot in i_data[] */ - short i_zone; /* write zone */ - unsigned char i_hlink; /* This is a fake */ + u32 i_protect; /* unused attribute bits */ + s32 i_parent; /* parent ino */ + s32 i_original; /* if != 0, this is the key of the original */ + s32 i_data[AFFS_MAX_PREALLOC]; /* preallocated blocks */ + struct ext_cache *i_ec; /* Cache gets allocated dynamically */ + int i_cache_users; /* Cache cannot be freed while > 0 */ + int i_lastblock; /* last allocated block */ + short i_pa_cnt; /* number of preallocated blocks */ + short i_pa_next; /* Index of next block in i_data[] */ + short i_pa_last; /* Index of next free slot in i_data[] */ + short i_zone; /* write zone */ + unsigned char i_hlink; /* This is a fake */ unsigned char i_pad; }; diff --git a/include/linux/affs_fs_sb.h b/include/linux/affs_fs_sb.h index 0ff862d13810..75af71dba7f1 100644 --- a/include/linux/affs_fs_sb.h +++ b/include/linux/affs_fs_sb.h @@ -15,8 +15,8 @@ struct affs_bm_info { struct buffer_head *bm_bh; /* Buffer head if loaded (bm_count > 0) */ - int bm_firstblk; /* Block number of first bit in this map */ - int bm_key; /* Disk block number */ + s32 bm_firstblk; /* Block number of first bit in this map */ + s32 bm_key; /* Disk block number */ int bm_count; /* Usage counter */ }; @@ -37,11 +37,11 @@ struct affs_zone { struct affs_sb_info { int s_partition_size; /* Partition size in blocks. */ - int s_root_block; /* FFS root block number. */ + s32 s_root_block; /* FFS root block number. */ int s_hashsize; /* Size of hash table. */ unsigned long s_flags; /* See below. */ - short s_uid; /* uid to override */ - short s_gid; /* gid to override */ + s16 s_uid; /* uid to override */ + s16 s_gid; /* gid to override */ umode_t s_mode; /* mode to override */ int s_reserved; /* Number of reserved blocks. */ struct buffer_head *s_root_bh; /* Cached root block. */ diff --git a/include/linux/affs_hardblocks.h b/include/linux/affs_hardblocks.h index 33315488dc54..ae893e022f1a 100644 --- a/include/linux/affs_hardblocks.h +++ b/include/linux/affs_hardblocks.h @@ -4,59 +4,59 @@ /* Just the needed definitions for the RDB of an Amiga HD. */ struct RigidDiskBlock { - __u32 rdb_ID; - __u32 rdb_SummedLongs; - __s32 rdb_ChkSum; - __u32 rdb_HostID; - __u32 rdb_BlockBytes; - __u32 rdb_Flags; - __u32 rdb_BadBlockList; - __u32 rdb_PartitionList; - __u32 rdb_FileSysHeaderList; - __u32 rdb_DriveInit; - __u32 rdb_Reserved1[6]; - __u32 rdb_Cylinders; - __u32 rdb_Sectors; - __u32 rdb_Heads; - __u32 rdb_Interleave; - __u32 rdb_Park; - __u32 rdb_Reserved2[3]; - __u32 rdb_WritePreComp; - __u32 rdb_ReducedWrite; - __u32 rdb_StepRate; - __u32 rdb_Reserved3[5]; - __u32 rdb_RDBBlocksLo; - __u32 rdb_RDBBlocksHi; - __u32 rdb_LoCylinder; - __u32 rdb_HiCylinder; - __u32 rdb_CylBlocks; - __u32 rdb_AutoParkSeconds; - __u32 rdb_HighRDSKBlock; - __u32 rdb_Reserved4; + u32 rdb_ID; + u32 rdb_SummedLongs; + s32 rdb_ChkSum; + u32 rdb_HostID; + u32 rdb_BlockBytes; + u32 rdb_Flags; + u32 rdb_BadBlockList; + u32 rdb_PartitionList; + u32 rdb_FileSysHeaderList; + u32 rdb_DriveInit; + u32 rdb_Reserved1[6]; + u32 rdb_Cylinders; + u32 rdb_Sectors; + u32 rdb_Heads; + u32 rdb_Interleave; + u32 rdb_Park; + u32 rdb_Reserved2[3]; + u32 rdb_WritePreComp; + u32 rdb_ReducedWrite; + u32 rdb_StepRate; + u32 rdb_Reserved3[5]; + u32 rdb_RDBBlocksLo; + u32 rdb_RDBBlocksHi; + u32 rdb_LoCylinder; + u32 rdb_HiCylinder; + u32 rdb_CylBlocks; + u32 rdb_AutoParkSeconds; + u32 rdb_HighRDSKBlock; + u32 rdb_Reserved4; char rdb_DiskVendor[8]; char rdb_DiskProduct[16]; char rdb_DiskRevision[4]; char rdb_ControllerVendor[8]; char rdb_ControllerProduct[16]; char rdb_ControllerRevision[4]; - __u32 rdb_Reserved5[10]; + u32 rdb_Reserved5[10]; }; #define IDNAME_RIGIDDISK 0x5244534B /* "RDSK" */ struct PartitionBlock { - __u32 pb_ID; - __u32 pb_SummedLongs; - __s32 pb_ChkSum; - __u32 pb_HostID; - __u32 pb_Next; - __u32 pb_Flags; - __u32 pb_Reserved1[2]; - __u32 pb_DevFlags; - __u8 pb_DriveName[32]; - __u32 pb_Reserved2[15]; - __u32 pb_Environment[17]; - __u32 pb_EReserved[15]; + u32 pb_ID; + u32 pb_SummedLongs; + s32 pb_ChkSum; + u32 pb_HostID; + u32 pb_Next; + u32 pb_Flags; + u32 pb_Reserved1[2]; + u32 pb_DevFlags; + u8 pb_DriveName[32]; + u32 pb_Reserved2[15]; + u32 pb_Environment[17]; + u32 pb_EReserved[15]; }; #define IDNAME_PARTITION 0x50415254 /* "PART" */ diff --git a/include/linux/amigaffs.h b/include/linux/amigaffs.h index 679f333e5442..8e39a6fe268b 100644 --- a/include/linux/amigaffs.h +++ b/include/linux/amigaffs.h @@ -56,131 +56,131 @@ struct root_front { - __s32 primary_type; - __s32 spare1[2]; - __s32 hash_size; - __s32 spare2; - __u32 checksum; - __s32 hashtable[0]; + s32 primary_type; + s32 spare1[2]; + s32 hash_size; + s32 spare2; + u32 checksum; + s32 hashtable[0]; }; struct root_end { - __s32 bm_flag; - __s32 bm_keys[25]; - __s32 bm_extend; + s32 bm_flag; + s32 bm_keys[25]; + s32 bm_extend; struct DateStamp dir_altered; - __u8 disk_name[40]; + u8 disk_name[40]; struct DateStamp disk_altered; struct DateStamp disk_made; - __s32 spare1[3]; - __s32 secondary_type; + s32 spare1[3]; + s32 secondary_type; }; struct dir_front { - __s32 primary_type; - __s32 own_key; - __s32 spare1[3]; - __u32 checksum; - __s32 hashtable[0]; + s32 primary_type; + s32 own_key; + s32 spare1[3]; + u32 checksum; + s32 hashtable[0]; }; struct dir_end { - __s32 spare1; - __s16 owner_uid; - __s16 owner_gid; - __u32 protect; - __s32 spare2; - __u8 comment[92]; + s32 spare1; + s16 owner_uid; + s16 owner_gid; + u32 protect; + s32 spare2; + u8 comment[92]; struct DateStamp created; - __u8 dir_name[32]; - __s32 spare3[2]; - __s32 link_chain; - __s32 spare4[5]; - __s32 hash_chain; - __s32 parent; - __s32 spare5; - __s32 secondary_type; + u8 dir_name[32]; + s32 spare3[2]; + s32 link_chain; + s32 spare4[5]; + s32 hash_chain; + s32 parent; + s32 spare5; + s32 secondary_type; }; struct file_front { - __s32 primary_type; - __s32 own_key; - __s32 block_count; - __s32 unknown1; - __s32 first_data; - __u32 checksum; - __s32 blocks[0]; + s32 primary_type; + s32 own_key; + s32 block_count; + s32 unknown1; + s32 first_data; + u32 checksum; + s32 blocks[0]; }; struct file_end { - __s32 spare1; - __s16 owner_uid; - __s16 owner_gid; - __u32 protect; - __s32 byte_size; - __u8 comment[92]; + s32 spare1; + s16 owner_uid; + s16 owner_gid; + u32 protect; + s32 byte_size; + u8 comment[92]; struct DateStamp created; - __u8 file_name[32]; - __s32 spare2; - __s32 original; /* not really in file_end */ - __s32 link_chain; - __s32 spare3[5]; - __s32 hash_chain; - __s32 parent; - __s32 extension; - __s32 secondary_type; + u8 file_name[32]; + s32 spare2; + s32 original; /* not really in file_end */ + s32 link_chain; + s32 spare3[5]; + s32 hash_chain; + s32 parent; + s32 extension; + s32 secondary_type; }; struct hlink_front { - __s32 primary_type; - __s32 own_key; - __s32 spare1[3]; - __u32 checksum; + s32 primary_type; + s32 own_key; + s32 spare1[3]; + u32 checksum; }; struct hlink_end { - __s32 spare1; - __s16 owner_uid; - __s16 owner_gid; - __u32 protect; - __u8 comment[92]; + s32 spare1; + s16 owner_uid; + s16 owner_gid; + u32 protect; + u8 comment[92]; struct DateStamp created; - __u8 link_name[32]; - __s32 spare2; - __s32 original; - __s32 link_chain; - __s32 spare3[5]; - __s32 hash_chain; - __s32 parent; - __s32 spare4; - __s32 secondary_type; + u8 link_name[32]; + s32 spare2; + s32 original; + s32 link_chain; + s32 spare3[5]; + s32 hash_chain; + s32 parent; + s32 spare4; + s32 secondary_type; }; struct slink_front { - __s32 primary_type; - __s32 own_key; - __s32 spare1[3]; - __s32 checksum; - __u8 symname[288]; /* depends on block size */ + s32 primary_type; + s32 own_key; + s32 spare1[3]; + s32 checksum; + u8 symname[288]; /* depends on block size */ }; struct data_front { - __s32 primary_type; - __s32 header_key; - __s32 sequence_number; - __s32 data_size; - __s32 next_data; - __s32 checksum; - __u8 data[488]; /* depends on block size */ + s32 primary_type; + s32 header_key; + s32 sequence_number; + s32 data_size; + s32 next_data; + s32 checksum; + u8 data[488]; /* depends on block size */ }; /* Permission bits */ diff --git a/include/linux/auto_fs.h b/include/linux/auto_fs.h index d32a6a253fc9..2b25d2902cb7 100644 --- a/include/linux/auto_fs.h +++ b/include/linux/auto_fs.h @@ -1,14 +1,14 @@ -/* -*- linux-c -*- --------------------------------------------------------- * - * +/* -*- linux-c -*- ------------------------------------------------------- * + * * linux/include/linux/auto_fs.h * - * Copyright 1997 Transmeta Corporation -- All Rights Reserved + * Copyright 1997 Transmeta Corporation - All Rights Reserved * * This file is part of the Linux kernel and is made available under * the terms of the GNU General Public License, version 2, or at your * option, any later version, incorporated herein by reference. * - * ------------------------------------------------------------------------- */ + * ----------------------------------------------------------------------- */ #ifndef _LINUX_AUTO_FS_H @@ -20,11 +20,11 @@ #include #include -#define AUTOFS_PROTO_VERSION 2 +#define AUTOFS_PROTO_VERSION 3 enum autofs_packet_type { - autofs_ptype_missing, /* Missing entry (create wait queue) */ - /* ...need more in the future... */ + autofs_ptype_missing, /* Missing entry (mount request) */ + autofs_ptype_expire, /* Expire entry (umount request) */ }; struct autofs_packet_hdr { @@ -39,139 +39,24 @@ struct autofs_packet_missing { char name[NAME_MAX+1]; }; -#define AUTOFS_IOC_READY _IO(0x93,0x60) -#define AUTOFS_IOC_FAIL _IO(0x93,0x61) -#define AUTOFS_IOC_CATATONIC _IO(0x93,0x62) - -#ifdef __KERNEL__ - -#include -#include - -#if LINUX_VERSION_CODE < 0x20100 - -#include -#define copy_to_user memcpy_tofs -#define copy_from_user memcpy_fromfs - -#else - -#include -#define register_symtab(x) do { } while (0) - -#endif - -#ifndef DPRINTK -#ifdef DEBUG -#define DPRINTK(D) printk D; -#else -#define DPRINTK(D) -#endif -#endif - -#define AUTOFS_SUPER_MAGIC 0x0187 - -/* Structures associated with the root directory hash */ - -#define AUTOFS_HASH_SIZE 67 - -typedef u32 autofs_hash_t; /* Type returned by autofs_hash() */ - -struct autofs_dir_ent { - autofs_hash_t hash; - struct autofs_dir_ent *next; - struct autofs_dir_ent **back; - char *name; - int len; - ino_t ino; - time_t expiry; /* Reserved for use in failed-lookup cache */ -}; - -struct autofs_dirhash { - struct autofs_dir_ent *h[AUTOFS_HASH_SIZE]; -}; - -struct autofs_wait_queue { - unsigned long wait_queue_token; - struct wait_queue *queue; - struct autofs_wait_queue *next; - /* We use the following to see what we are waiting for */ - autofs_hash_t hash; - int len; - char *name; - /* This is for status reporting upon return */ - int status; - int wait_ctr; -}; - -struct autofs_symlink { +struct autofs_packet_expire { + struct autofs_packet_hdr hdr; int len; - char *data; - time_t mtime; + char name[NAME_MAX+1]; }; -#define AUTOFS_MAX_SYMLINKS 256 - -#define AUTOFS_ROOT_INO 1 -#define AUTOFS_FIRST_SYMLINK 2 -#define AUTOFS_FIRST_DIR_INO (AUTOFS_FIRST_SYMLINK+AUTOFS_MAX_SYMLINKS) +#define AUTOFS_IOC_READY _IO(0x93,0x60) +#define AUTOFS_IOC_FAIL _IO(0x93,0x61) +#define AUTOFS_IOC_CATATONIC _IO(0x93,0x62) +#define AUTOFS_IOC_PROTOVER _IOR(0x93,0x63,int) +#define AUTOFS_IOC_SETTIMEOUT _IOWR(0x93,0x64,unsigned long) +#define AUTOFS_IOC_EXPIRE _IOR(0x93,0x65,struct autofs_packet_expire) -#define AUTOFS_SYMLINK_BITMAP_LEN ((AUTOFS_MAX_SYMLINKS+31)/32) - -#ifndef END_OF_TIME -#define END_OF_TIME ((time_t)((unsigned long)((time_t)(~0UL)) >> 1)) -#endif - -struct autofs_sb_info { - struct file *pipe; - pid_t oz_pgrp; - int catatonic; - ino_t next_dir_ino; - struct autofs_wait_queue *queues; /* Wait queue pointer */ - struct autofs_dirhash dirhash; /* Root directory hash */ - struct autofs_symlink symlink[AUTOFS_MAX_SYMLINKS]; - u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN]; -}; - -/* autofs_oz_mode(): do we see the man behind the curtain? */ -static inline int autofs_oz_mode(struct autofs_sb_info *sbi) { - return sbi->catatonic || current->pgrp == sbi->oz_pgrp; -} +#ifdef __KERNEL__ /* Init function */ int init_autofs_fs(void); -/* Hash operations */ - -autofs_hash_t autofs_hash(const char *,int); -void autofs_initialize_hash(struct autofs_dirhash *); -struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,autofs_hash_t,const char *,int); -void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *); -void autofs_hash_delete(struct autofs_dir_ent *); -struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *); -void autofs_hash_nuke(struct autofs_dirhash *); - -/* Operations structures */ - -extern struct inode_operations autofs_root_inode_operations; -extern struct inode_operations autofs_symlink_inode_operations; -extern struct inode_operations autofs_dir_inode_operations; - -/* Initializing function */ - -struct super_block *autofs_read_super(struct super_block *, void *,int); - -/* Queue management functions */ - -int autofs_wait(struct autofs_sb_info *,autofs_hash_t,const char *,int); -int autofs_wait_release(struct autofs_sb_info *,unsigned long,int); -void autofs_catatonic_mode(struct autofs_sb_info *); - -#ifdef DEBUG -void autofs_say(const char *name, int len); -#else -#define autofs_say(n,l) -#endif - #endif /* __KERNEL__ */ + #endif /* _LINUX_AUTO_FS_H */ diff --git a/include/linux/console.h b/include/linux/console.h index 7589ce794fcf..16f1754ec277 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -27,19 +27,20 @@ struct vc_data; /* DPC: 1994-04-13 !!! con_putcs is new entry !!! */ struct consw { - unsigned long (*con_startup)(unsigned long, char **); - void (*con_init)(struct vc_data *); - int (*con_deinit)(struct vc_data *); - int (*con_clear)(struct vc_data *, int, int, int, int); - int (*con_putc)(struct vc_data *, int, int, int); - int (*con_putcs)(struct vc_data *, const char *, int, int, int); - int (*con_cursor)(struct vc_data *, int); - int (*con_scroll)(struct vc_data *, int, int, int, int); - int (*con_bmove)(struct vc_data *, int, int, int, int, int, int); - int (*con_switch)(struct vc_data *); - int (*con_blank)(int); - int (*con_get_font)(struct vc_data *, int *, int *, char *); - int (*con_set_font)(struct vc_data *, int, int, char *); + unsigned long (*con_startup)(unsigned long, const char **); + void (*con_init)(struct vc_data *); + int (*con_deinit)(struct vc_data *); + int (*con_clear)(struct vc_data *, int, int, int, int); + int (*con_putc)(struct vc_data *, int, int, int); + int (*con_putcs)(struct vc_data *, const char *, int, int, int); + int (*con_cursor)(struct vc_data *, int); + int (*con_scroll)(struct vc_data *, int, int, int, int); + int (*con_bmove)(struct vc_data *, int, int, int, int, int, int); + int (*con_switch)(struct vc_data *); + int (*con_blank)(int); + int (*con_get_font)(struct vc_data *, int *, int *, char *); + int (*con_set_font)(struct vc_data *, int, int, char *); + int (*con_set_palette)(struct vc_data *, unsigned char *); }; extern struct consw *conswitchp; diff --git a/include/linux/fb.h b/include/linux/fb.h index f97a313c60fe..9ed7546d5f9c 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -59,6 +59,7 @@ struct fb_bitfield { #define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */ #define FB_ACCEL_AMIGABLITT 2 /* Amiga Blitter */ #define FB_ACCEL_CYBERVISION 3 /* Cybervision64 (S3 Trio64) */ +#define FB_ACCEL_RETINAZ3 4 /* RetinaZ3 (NCR77C32BLT) */ #define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ #define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ @@ -205,6 +206,7 @@ struct fb_info { int (*switch_con)(int); /* tell fb to switch consoles */ int (*updatevar)(int); /* tell fb to update the vars */ void (*blank)(int); /* tell fb to (un)blank the screen */ + int (*setcmap)(struct fb_cmap *, int); /* tell fb to set the colormap */ }; #endif /* __KERNEL__ */ diff --git a/include/linux/lp_m68k.h b/include/linux/lp_m68k.h index 6cd60e19dfa6..ca8f7a31dc9e 100644 --- a/include/linux/lp_m68k.h +++ b/include/linux/lp_m68k.h @@ -91,7 +91,8 @@ enum lp_type { LP_UNKNOWN = 0, LP_AMIGA = 1, LP_ATARI = 2, -LP_MFC = 3 +LP_MFC = 3, +LP_IOEXT = 4 }; /* @@ -105,10 +106,10 @@ struct lp_struct { int (*lp_is_busy)(int); int (*lp_has_pout)(int); int (*lp_is_online)(int); - int (*lp_my_interrupt)(int); + int (*lp_dummy)(int); int (*lp_ioctl)(int, unsigned int, unsigned long); - void (*lp_open)(void); /* for module use counter */ - void (*lp_release)(void); /* for module use counter */ + int (*lp_open)(int); /* for module use counter */ + void (*lp_release)(int); /* for module use counter */ int flags; /*for BUSY... */ unsigned int chars; /*busy timeout */ unsigned int time; /*wait time */ @@ -124,7 +125,7 @@ struct lp_struct { extern struct lp_struct *lp_table[MAX_LP]; extern unsigned int lp_irq; -void lp_interrupt(int, void *, struct pt_regs *); +void lp_interrupt(int dev); int lp_init(void); int register_parallel(struct lp_struct *, int); void unregister_parallel(int); diff --git a/include/linux/major.h b/include/linux/major.h index ee58c06f0916..6e785af86895 100644 --- a/include/linux/major.h +++ b/include/linux/major.h @@ -70,6 +70,7 @@ #define RISCOM8_NORMAL_MAJOR 48 #define RISCOM8_CALLOUT_MAJOR 49 #define MKISS_MAJOR 55 +#define DSP56K_MAJOR 55 /* DSP56001 processor device */ /* * Tests for SCSI devices. diff --git a/include/linux/sched.h b/include/linux/sched.h index fab7bfb38005..1bacbde98dc8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -291,6 +291,16 @@ struct task_struct { #define DEF_PRIORITY (20*HZ/100) /* 200 ms time slices */ +/* Note: This is very ugly I admit. But some versions of gcc will + * dump core when an empty structure constant is parsed at + * the end of a large top level structure initialization. -DaveM + */ +#ifdef __SMP__ +#define INIT_LOCKS SPIN_LOCK_UNLOCKED +#else +#define INIT_LOCKS +#endif + /* * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB) @@ -326,7 +336,7 @@ struct task_struct { /* mm */ &init_mm, \ /* signals */ &init_signals, \ /* SMP */ 0,0,0,0, \ -/* lock */ SPIN_LOCK_UNLOCKED \ +/* locks */ INIT_LOCKS \ } union task_union { @@ -404,6 +414,9 @@ extern __inline__ struct task_struct *find_task_by_pid(int pid) return p; } +/* per-UID process charging. */ +extern int charge_uid(struct task_struct *p, int count); + #include extern unsigned long volatile jiffies; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 86a5e64171ee..6fb8529074b8 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -123,6 +123,9 @@ struct sk_buff #endif }; +/* These are just the default values. This is run time configurable. + * FIXME: Probably the config option should go away. -- erics + */ #ifdef CONFIG_SKB_LARGE #define SK_WMEM_MAX 65535 #define SK_RMEM_MAX 65535 diff --git a/include/linux/smp.h b/include/linux/smp.h index 72984f1541c6..ff4427960801 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -47,6 +47,7 @@ extern volatile int smp_msg_id; #define smp_num_cpus 1 #define smp_processor_id() 0 +#define hard_smp_processor_id() 0 #define smp_message_pass(t,m,d,w) #define smp_threads_ready 1 #define kernel_lock() diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 0e01fba0fe72..8ab7e77cae41 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -104,6 +104,13 @@ enum /* /proc/sys/net/core */ +enum +{ + NET_CORE_WMEM_MAX=1, + NET_CORE_RMEM_MAX, + NET_CORE_WMEM_DEFAULT, + NET_CORE_RMEM_DEFAULT, +}; /* /proc/sys/net/ethernet */ diff --git a/include/net/sock.h b/include/net/sock.h index 61936854f74a..354d8dae5647 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -216,6 +216,7 @@ struct tcp_opt * Options received (usually on last packet, some only on SYN packets). */ char tstamp_ok, /* TIMESTAMP seen on SYN packet */ + wscale_ok, /* Wscale seen on SYN packet */ sack_ok; /* SACK_PERM seen on SYN packet */ char saw_tstamp; /* Saw TIMESTAMP on last packet */ __u16 in_mss; /* MSS option received from sender */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 3822b461f2ed..cedc7f3b1040 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -43,6 +43,17 @@ extern struct sock *tcp_established_hash[TCP_HTABLE_SIZE]; extern struct sock *tcp_listening_hash[TCP_LHTABLE_SIZE]; extern struct sock *tcp_bound_hash[TCP_BHTABLE_SIZE]; +/* tcp_ipv4.c: These sysctl variables need to be shared between v4 and v6 + * because the v6 tcp code to intialize a connection needs to interoperate + * with the v4 code using the same variables. + * FIXME: It would be better to rewrite the connection code to be + * address family independent and just leave one copy in the ipv4 section. + * This would also clean up some code duplication. -- erics + */ +extern int sysctl_tcp_sack; +extern int sysctl_tcp_timestamps; +extern int sysctl_tcp_window_scaling; + /* These are AF independant. */ static __inline__ int tcp_bhashfn(__u16 lport) { @@ -224,8 +235,12 @@ struct open_request { __u16 rmt_port; __u16 mss; __u8 snd_wscale; + __u8 rcv_wscale; char sack_ok; char tstamp_ok; + char wscale_ok; + __u32 window_clamp; /* window clamp at creation time */ + __u32 rcv_wnd; /* rcv_wnd offered first time */ __u32 ts_recent; unsigned long expires; int retrans; @@ -452,6 +467,10 @@ struct tcp_sl_timer { extern struct tcp_sl_timer tcp_slt_array[TCP_SLT_MAX]; +/* + * FIXME: this method of choosing when to send a window update + * does not seem correct to me. -- erics + */ static __inline__ unsigned short tcp_raise_window(struct sock *sk) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; @@ -553,9 +572,9 @@ static __inline__ void tcp_set_state(struct sock *sk, int state) * It would be especially magical to compute the checksum for this * stuff on the fly here. */ -extern __inline__ int tcp_syn_build_options(struct sk_buff *skb, int mss, int sack, int ts, int wscale) +extern __inline__ int tcp_syn_build_options(struct sk_buff *skb, int mss, int sack, int ts, int offer_wscale, int wscale) { - int count = 4 + (wscale ? 4 : 0) + ((ts || sack) ? 4 : 0) + (ts ? 8 : 0); + int count = 4 + (offer_wscale ? 4 : 0) + ((ts || sack) ? 4 : 0) + (ts ? 8 : 0); unsigned char *optr = skb_put(skb,count); __u32 *ptr = (__u32 *)optr; @@ -579,12 +598,53 @@ extern __inline__ int tcp_syn_build_options(struct sk_buff *skb, int mss, int sa *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) | (TCPOPT_NOP << 8) | TCPOPT_NOP); } - if (wscale) - *ptr++ = htonl((TCPOPT_WINDOW << 24) | (TCPOLEN_WINDOW << 16) | wscale); + if (offer_wscale) + *ptr++ = htonl((TCPOPT_WINDOW << 24) | (TCPOLEN_WINDOW << 16) | (wscale << 8)); skb->csum = csum_partial(optr, count, 0); return count; } +/* Determine a window scaling and initial window to offer. + * Based on the assumption that the given amount of space + * will be offered. Store the results in the tp structure. + * NOTE: for smooth operation initial space offering should + * be a multiple of mss if possible. We assume here that mss >= 1. + * This MUST be enforced by all callers. + */ +extern __inline__ void tcp_select_initial_window(__u32 space, __u16 mss, + __u32 *rcv_wnd, + __u32 *window_clamp, + int wscale_ok, + __u8 *rcv_wscale) +{ + /* If no clamp set the clamp to the max possible scaled window */ + if (*window_clamp == 0) + (*window_clamp) = (65535<<14); + space = min(*window_clamp,space); + + /* Quantize space offering to a multiple of mss if possible. */ + if (space > mss) + space = (space/mss)*mss; + + /* NOTE: offering an initial window larger than 32767 + * will break some buggy TCP stacks. We try to be nice. + * If we are not window scaling, then this truncates + * our initial window offering to 32k. There should also + * be a sysctl option to stop being nice. + */ + (*rcv_wnd) = min(space,32767); + (*rcv_wscale) = 0; + if (wscale_ok) { + /* See RFC1323 for an explanation of the limit to 14 */ + while (space > 65535 && (*rcv_wscale) < 14) { + space >>= 1; + (*rcv_wscale)++; + } + } + /* Set the clamp no higher than max representable value */ + (*window_clamp) = min(65535<<(*rcv_wscale),*window_clamp); +} + extern __inline__ void tcp_synq_unlink(struct tcp_opt *tp, struct open_request *req) { if(req->dl_next) diff --git a/init/main.c b/init/main.c index 0f6cba379873..87be33d42b6e 100644 --- a/init/main.c +++ b/init/main.c @@ -68,6 +68,7 @@ extern void init_modules(void); extern long console_init(long, long); extern long kmalloc_init(long,long); extern void sock_init(void); +extern void uidcache_init(void); extern unsigned long pci_init(unsigned long, unsigned long); extern long mca_init(long, long); extern long sbus_init(long, long); @@ -644,6 +645,7 @@ __initfunc(static void parse_root_dev(char * line)) { "gscd", 0x1000 }, { "sbpcd", 0x1900 }, { "sonycd", 0x1800 }, + { "eda", 0x2400 }, { "eza", 0x2800 }, { "bpcd", 0x2900 }, #if CONFIG_APBLOCK @@ -881,6 +883,7 @@ __initfunc(asmlinkage void start_kernel(void)) proc_root_init(); #endif kmem_cache_sizes_init(); + uidcache_init(); vma_init(); buffer_init(); inode_init(); diff --git a/ipc/msg.c b/ipc/msg.c index fcef8357f90e..49d8f043f6a4 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -39,7 +40,7 @@ static int kerneld_msqid = -1; static int kerneld_arr[MAX_KERNELDS]; static int n_kernelds = 0; -void msg_init (void) +__initfunc(void msg_init (void)) { int id; diff --git a/ipc/sem.c b/ipc/sem.c index 8aecbfb48a4c..f63f2a7a9104 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -55,7 +56,7 @@ static int max_semid = 0; static unsigned short sem_seq = 0; -void sem_init (void) +__initfunc(void sem_init (void)) { int i; diff --git a/ipc/shm.c b/ipc/shm.c index d598696a6c08..d2afb7d2f1de 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,7 @@ static ulong swap_attempts = 0; static ulong swap_successes = 0; static ulong used_segs = 0; -void shm_init (void) +__initfunc(void shm_init (void)) { int id; @@ -803,9 +804,10 @@ int shm_swap (int prio, int dma) if (shmd->vm_mm->rss > 0) shmd->vm_mm->rss--; flush_tlb_page(shmd, tmp); - /* continue looping through circular list */ + /* continue looping through the linked list */ } while (0); - if ((shmd = shmd->vm_next_share) == shp->attaches) + shmd = shmd->vm_next_share; + if (!shmd) break; } diff --git a/ipc/util.c b/ipc/util.c index e81afc36f6a8..88e63c6fc407 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -18,7 +19,7 @@ extern void sem_init (void), msg_init (void), shm_init (void); -void ipc_init (void) +__initfunc(void ipc_init (void)) { sem_init(); msg_init(); diff --git a/kernel/exit.c b/kernel/exit.c index 1abe1ef2ea1b..7b1c9e096723 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -132,6 +132,7 @@ static void release(struct task_struct * p) barrier(); spin_unlock_wait(&scheduler_lock); #endif + charge_uid(p, -1); nr_tasks--; add_free_taskslot(p->tarray_ptr); unhash_pid(p); diff --git a/kernel/fork.c b/kernel/fork.c index 4175f5e476d5..f75cd7e35c57 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -42,31 +42,105 @@ spinlock_t pidhash_lock = SPIN_LOCK_UNLOCKED; struct task_struct **tarray_freelist = NULL; spinlock_t taskslot_lock = SPIN_LOCK_UNLOCKED; +/* UID task count cache, to prevent walking entire process list every + * single fork() operation. + */ +#define UIDHASH_SZ (PIDHASH_SZ >> 2) + +static struct uid_taskcount { + struct uid_taskcount *next, **pprev; + unsigned short uid; + int task_count; +} *uidhash[UIDHASH_SZ]; +static spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED; + +kmem_cache_t *uid_cachep; + +#define uidhashfn(uid) (((uid >> 8) ^ uid) & (UIDHASH_SZ - 1)) + +static inline void uid_hash_insert(struct uid_taskcount *up, unsigned int hashent) +{ + spin_lock(&uidhash_lock); + if((up->next = uidhash[hashent]) != NULL) + uidhash[hashent]->pprev = &up->next; + up->pprev = &uidhash[hashent]; + uidhash[hashent] = up; + spin_unlock(&uidhash_lock); +} + +static inline void uid_hash_remove(struct uid_taskcount *up) +{ + spin_lock(&uidhash_lock); + if(up->next) + up->next->pprev = up->pprev; + *up->pprev = up->next; + spin_unlock(&uidhash_lock); +} + +static inline struct uid_taskcount *uid_find(unsigned short uid, unsigned int hashent) +{ + struct uid_taskcount *up; + + spin_lock(&uidhash_lock); + for(up = uidhash[hashent]; (up && up->uid != uid); up = up->next) + ; + spin_unlock(&uidhash_lock); + return up; +} + +int charge_uid(struct task_struct *p, int count) +{ + unsigned int hashent = uidhashfn(p->uid); + struct uid_taskcount *up = uid_find(p->uid, hashent); + + if(up) { + int limit = p->rlim[RLIMIT_NPROC].rlim_cur; + int newcnt = up->task_count + count; + + if(newcnt > limit) + return -EAGAIN; + else if(newcnt == 0) { + uid_hash_remove(up); + kmem_cache_free(uid_cachep, up); + return 0; + } + } else { + up = kmem_cache_alloc(uid_cachep, SLAB_KERNEL); + if(!up) + return -EAGAIN; + up->uid = p->uid; + up->task_count = 0; + uid_hash_insert(up, hashent); + } + up->task_count += count; + return 0; +} + +void uidcache_init(void) +{ + int i; + + uid_cachep = kmem_cache_create("uid_cache", sizeof(struct uid_taskcount), + sizeof(unsigned long) * 2, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if(!uid_cachep) + panic("Cannot create uid taskcount SLAB cache\n"); + + for(i = 0; i < UIDHASH_SZ; i++) + uidhash[i] = 0; +} + static inline int find_empty_process(void) { struct task_struct **tslot; - if (nr_tasks >= NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT) { - if (current->uid) + if(current->uid) { + int error; + + if(nr_tasks >= NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT) return -EAGAIN; - } - if (current->uid) { - long max_tasks = current->rlim[RLIMIT_NPROC].rlim_cur; - - max_tasks--; /* count the new process.. */ - if (max_tasks < nr_tasks) { - struct task_struct *p; - - read_lock(&tasklist_lock); - for_each_task (p) { - if (p->uid == current->uid) - if (--max_tasks < 0) { - read_unlock(&tasklist_lock); - return -EAGAIN; - } - } - read_unlock(&tasklist_lock); - } + if((error = charge_uid(current, 1)) < 0) + return error; } tslot = get_free_taskslot(); if(tslot) @@ -74,24 +148,48 @@ static inline int find_empty_process(void) return -EAGAIN; } +/* Protects next_safe and last_pid. */ +static spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED; + static int get_pid(unsigned long flags) { + static int next_safe = PID_MAX; struct task_struct *p; if (flags & CLONE_PID) return current->pid; - read_lock(&tasklist_lock); -repeat: - if ((++last_pid) & 0xffff8000) - last_pid=1; - for_each_task (p) { - if (p->pid == last_pid || - p->pgrp == last_pid || - p->session == last_pid) - goto repeat; + spin_lock(&lastpid_lock); + if((++last_pid) & 0xffff8000) { + last_pid = 300; /* Skip daemons etc. */ + goto inside; + } + if(last_pid >= next_safe) { +inside: + next_safe = PID_MAX; + read_lock(&tasklist_lock); + repeat: + for_each_task(p) { + if(p->pid == last_pid || + p->pgrp == last_pid || + p->session == last_pid) { + if(++last_pid >= next_safe) { + if(last_pid & 0xffff8000) + last_pid = 300; + next_safe = PID_MAX; + goto repeat; + } + } + if(p->pid > last_pid && next_safe > p->pid) + next_safe = p->pid; + if(p->pgrp > last_pid && next_safe > p->pgrp) + next_safe = p->pgrp; + if(p->session > last_pid && next_safe > p->session) + next_safe = p->session; + } + read_unlock(&tasklist_lock); } - read_unlock(&tasklist_lock); + spin_unlock(&lastpid_lock); return last_pid; } @@ -350,6 +448,7 @@ bad_fork_cleanup_fs: bad_fork_cleanup_files: exit_files(p); bad_fork_cleanup: + charge_uid(current, -1); if (p->exec_domain && p->exec_domain->module) __MOD_DEC_USE_COUNT(p->exec_domain->module); if (p->binfmt && p->binfmt->module) diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 835833cbc7dc..5c2e2be0a870 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -301,7 +301,6 @@ EXPORT_SYMBOL(wake_up_interruptible); EXPORT_SYMBOL(sleep_on); EXPORT_SYMBOL(interruptible_sleep_on); EXPORT_SYMBOL(schedule); -EXPORT_SYMBOL(current_set); EXPORT_SYMBOL(jiffies); EXPORT_SYMBOL(xtime); EXPORT_SYMBOL(do_gettimeofday); diff --git a/kernel/panic.c b/kernel/panic.c index 992296e68438..9c03a3c1e30a 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -15,6 +15,7 @@ #include #include #include +#include asmlinkage void sys_sync(void); /* it's really int */ extern void unblank_console(void); @@ -22,7 +23,7 @@ extern int C_A_D; int panic_timeout = 0; -void panic_setup(char *str, int *ints) +__initfunc(void panic_setup(char *str, int *ints)) { if (ints[0] == 1) panic_timeout = ints[1]; diff --git a/kernel/printk.c b/kernel/printk.c index 0d5d619b0932..3d409f2d5527 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -261,7 +262,7 @@ void unblank_console(void) * print any messages that were printed by the kernel before the * console driver was initialized. */ -void register_console(struct console * console) +__initfunc(void register_console(struct console * console)) { int i,j,len; int p = log_start; diff --git a/kernel/resource.c b/kernel/resource.c index 27abcf4dc79c..ff7c7492a341 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -12,6 +12,7 @@ #include #include #include +#include #define IOTABLE_SIZE 128 @@ -181,7 +182,7 @@ unsigned long occupy_region(unsigned long base, unsigned long end, #endif /* Called from init/main.c to reserve IO ports. */ -void reserve_setup(char *str, int *ints) +__initfunc(void reserve_setup(char *str, int *ints)) { int i; diff --git a/kernel/sched.c b/kernel/sched.c index 0d9edf495e9e..a6b0ab58c9bf 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -95,7 +96,6 @@ unsigned long volatile jiffies=0; * via the SMP irq return path. */ -struct task_struct *current_set[NR_CPUS] = {&init_task, }; struct task_struct *last_task_used_math = NULL; struct task_struct * task[NR_TASKS] = {&init_task, }; @@ -409,7 +409,7 @@ asmlinkage int sys_pause(void) #endif -rwlock_t waitqueue_lock; +rwlock_t waitqueue_lock = RW_LOCK_UNLOCKED; /* * wake_up doesn't wake up stopped processes - they have to be awakened @@ -1605,7 +1605,7 @@ void show_state(void) read_unlock(&tasklist_lock); } -void sched_init(void) +__initfunc(void sched_init(void)) { /* * We have to do a little magic to get the first @@ -1614,17 +1614,7 @@ void sched_init(void) int cpu=hard_smp_processor_id(); int nr = NR_TASKS; -#ifndef __SMP__ - current_set[cpu]=&init_task; -#else init_task.processor=cpu; - /* - * This looks strange, but we don't necessarily know which CPU - * we're booting on yet, so do them all.. - */ - for(cpu = 0; cpu < NR_CPUS; cpu++) - current_set[cpu] = &init_task; -#endif /* Init task array free list and pidhash table. */ while(--nr > 0) diff --git a/kernel/sys.c b/kernel/sys.c index d51b04e5fd7e..936fb89d2973 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -523,16 +523,15 @@ asmlinkage int sys_old_syscall(void) */ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid) { - int old_ruid; - int old_euid; + int old_ruid, old_euid, new_ruid; - old_ruid = current->uid; + new_ruid = old_ruid = current->uid; old_euid = current->euid; if (ruid != (uid_t) -1) { if ((old_ruid == ruid) || (current->euid==ruid) || suser()) - current->uid = ruid; + new_ruid = ruid; else return -EPERM; } @@ -542,10 +541,8 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid) (current->suid == euid) || suser()) current->fsuid = current->euid = euid; - else { - current->uid = old_ruid; + else return -EPERM; - } } if (ruid != (uid_t) -1 || (euid != (uid_t) -1 && euid != old_ruid)) @@ -553,6 +550,18 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid) current->fsuid = current->euid; if (current->euid != old_euid) current->dumpable = 0; + + if(new_ruid != old_ruid) { + /* What if a process setreuid()'s and this brings the + * new uid over his NPROC rlimit? We can check this now + * cheaply with the new uid cache, so if it matters + * we should be checking for it. -DaveM + */ + charge_uid(current, -1); + current->uid = new_ruid; + if(new_ruid) + charge_uid(current, 1); + } return 0; } @@ -570,9 +579,11 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid) asmlinkage int sys_setuid(uid_t uid) { int old_euid = current->euid; + int old_ruid, new_ruid; + old_ruid = new_ruid = current->uid; if (suser()) - current->uid = current->euid = current->suid = current->fsuid = uid; + new_ruid = current->euid = current->suid = current->fsuid = uid; else if ((uid == current->uid) || (uid == current->suid)) current->fsuid = current->euid = uid; else @@ -580,6 +591,14 @@ asmlinkage int sys_setuid(uid_t uid) if (current->euid != old_euid) current->dumpable = 0; + + if(new_ruid != old_ruid) { + /* See comment above about NPROC rlimit issues... */ + charge_uid(current, -1); + current->uid = new_ruid; + if(new_ruid) + charge_uid(current, 1); + } return 0; } @@ -605,8 +624,13 @@ asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) if ((suid != (uid_t) -1) && (suid != current->uid) && (suid != current->euid) && (suid != current->suid)) return -EPERM; - if (ruid != (uid_t) -1) + if (ruid != (uid_t) -1) { + /* See above commentary about NPROC rlimit issues here. */ + charge_uid(current, -1); current->uid = ruid; + if(ruid) + charge_uid(current, 1); + } if (euid != (uid_t) -1) current->euid = euid; if (suid != (uid_t) -1) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 9e0bb0fd8aae..3f2e86a6bbe0 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -210,7 +211,7 @@ static ctl_table dev_table[] = { }; -void sysctl_init(void) +__initfunc(void sysctl_init(void)) { #ifdef CONFIG_PROC_FS register_proc_table(root_table, &proc_sys_root); diff --git a/mm/kmalloc.c b/mm/kmalloc.c index 57ebde688f91..a4e357ee7b84 100644 --- a/mm/kmalloc.c +++ b/mm/kmalloc.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -201,7 +202,7 @@ static inline void free_kmalloc_pages(struct page_descriptor * page, free_pages((unsigned long) page, order); } -long kmalloc_init(long start_mem, long end_mem) +__initfunc(long kmalloc_init(long start_mem, long end_mem)) { int order; diff --git a/mm/mmap.c b/mm/mmap.c index 639a88aa78b9..a48f45013755 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -654,7 +655,7 @@ no_vma: up(&mm->mmap_sem); } -void vma_init(void) +__initfunc(void vma_init(void)) { vm_area_cachep = kmem_cache_create("vm_area_struct", sizeof(struct vm_area_struct), diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 589f52815b83..6bb16aa415a1 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include /* for cli()/sti() */ @@ -265,7 +266,7 @@ void show_free_areas(void) * - mark all memory queues empty * - clear the memory bitmaps */ -unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem) +__initfunc(unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem)) { mem_map_t * p; unsigned long mask = PAGE_MASK; @@ -273,7 +274,7 @@ unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem) /* * select nr of pages we try to keep free for important stuff - * with a minimum of 16 pages. This is totally arbitrary + * with a minimum of 48 pages. This is totally arbitrary */ i = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT+7); if (i < 48) diff --git a/mm/slab.c b/mm/slab.c index baa4f027fdc5..0d32ca1b2dbe 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -269,8 +270,8 @@ static void kmem_hash_ctor(void *ptr, int size, unsigned long flags) static kmem_cache_t *clock_searchp = &cache_cache; /* Init an internal cache */ -static void -kmem_own_cache_init(kmem_cache_t *cachep) +__initfunc(static void +kmem_own_cache_init(kmem_cache_t *cachep)) { unsigned long size, i; @@ -293,8 +294,8 @@ kmem_own_cache_init(kmem_cache_t *cachep) } /* Initialisation - setup all internal caches */ -long -kmem_cache_init(long start, long end) +__initfunc(long +kmem_cache_init(long start, long end)) { /* sanity */ #define kmem_cache_offset(x) ((unsigned long)&((kmem_cache_t *)0)->x) @@ -319,8 +320,8 @@ kmem_cache_init(long start, long end) } /* Initialisation - setup general caches */ -void -kmem_cache_sizes_init(void) +__initfunc(void +kmem_cache_sizes_init(void)) { unsigned long i; diff --git a/mm/swap.c b/mm/swap.c index 7b6a0eb49f14..80817ecf16c5 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include /* for cli()/sti() */ @@ -67,7 +68,7 @@ swapstat_t swapstats = {0}; /* General swap control */ /* Parse the kernel command line "swap=" option at load time: */ -void swap_setup(char *str, int *ints) +__initfunc(void swap_setup(char *str, int *ints)) { int * swap_vars[8] = { &MAX_PAGE_AGE, @@ -87,7 +88,7 @@ void swap_setup(char *str, int *ints) } /* Parse the kernel command line "buff=" option at load time: */ -void buff_setup(char *str, int *ints) +__initfunc(void buff_setup(char *str, int *ints)) { int * buff_vars[6] = { &MAX_BUFF_AGE, diff --git a/mm/swap_state.c b/mm/swap_state.c index 044180721738..f3ffa46d54b5 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include /* for cli()/sti() */ @@ -69,8 +70,8 @@ int add_to_swap_cache(unsigned long index, unsigned long entry) return 0; } -unsigned long init_swap_cache(unsigned long mem_start, - unsigned long mem_end) +__initfunc(unsigned long init_swap_cache(unsigned long mem_start, + unsigned long mem_end)) { unsigned long swap_cache_size; diff --git a/net/802/llc_macinit.c b/net/802/llc_macinit.c index 1ee0a9699c67..c72be3d4d1c0 100644 --- a/net/802/llc_macinit.c +++ b/net/802/llc_macinit.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -202,7 +203,7 @@ EXPORT_SYMBOL(llc_xid_request); #define ALL_TYPES_8022 0 -void llc_init(struct net_proto *proto) +__initfunc(void llc_init(struct net_proto *proto)) { printk(KERN_NOTICE "IEEE 802.2 LLC for Linux 2.1 (c) 1996 Tim Alpaerts\n"); return; diff --git a/net/802/p8022.c b/net/802/p8022.c index 23e6f2fad59f..1a12f4d6099c 100644 --- a/net/802/p8022.c +++ b/net/802/p8022.c @@ -23,6 +23,7 @@ #include #include #include +#include #include static struct datalink_proto *p8022_list = NULL; @@ -90,7 +91,7 @@ static struct packet_type p8022_packet_type = EXPORT_SYMBOL(register_8022_client); EXPORT_SYMBOL(unregister_8022_client); -void p8022_proto_init(struct net_proto *pro) +__initfunc(void p8022_proto_init(struct net_proto *pro)) { p8022_packet_type.type=htons(ETH_P_802_2); dev_add_pack(&p8022_packet_type); diff --git a/net/802/p8022tr.c b/net/802/p8022tr.c index 6a5864d544e7..ef6a4976a957 100644 --- a/net/802/p8022tr.c +++ b/net/802/p8022tr.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #define SNAP_HEADER_LEN 8 @@ -91,7 +92,7 @@ static struct packet_type p8022tr_packet_type = EXPORT_SYMBOL(register_8022tr_client); EXPORT_SYMBOL(unregister_8022tr_client); -void p8022tr_proto_init(struct net_proto *pro) +__initfunc(void p8022tr_proto_init(struct net_proto *pro)) { p8022tr_packet_type.type=htons(ETH_P_TR_802_2); dev_add_pack(&p8022tr_packet_type); diff --git a/net/802/psnap.c b/net/802/psnap.c index bdcb5efd2df7..6ce58da353ce 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -19,6 +19,7 @@ #include #include #include +#include static struct datalink_proto *snap_list = NULL; static struct datalink_proto *snap_dl = NULL; /* 802.2 DL for SNAP */ @@ -87,7 +88,7 @@ static void snap_datalink_header(struct datalink_proto *dl, struct sk_buff *skb, EXPORT_SYMBOL(register_snap_client); EXPORT_SYMBOL(unregister_snap_client); -void snap_proto_init(struct net_proto *pro) +__initfunc(void snap_proto_init(struct net_proto *pro)) { snap_dl=register_8022_client(0xAA, snap_rcv); if(snap_dl==NULL) diff --git a/net/802/tr.c b/net/802/tr.c index e903924f78f0..627dd9a9905a 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -31,6 +31,7 @@ #include #include #include +#include #include static void tr_source_route(struct trh_hdr *trh, struct device *dev); @@ -460,7 +461,7 @@ int rif_get_info(char *buffer,char **start, off_t offset, int length, int dummy) * too much for this. */ -void rif_init(struct net_proto *unused) +__initfunc(void rif_init(struct net_proto *unused)) { rif_timer.expires = RIF_TIMEOUT; diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index e3e87f9e4b72..9ad9b8e93ca6 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -47,6 +47,7 @@ #include #include #include +#include /* * Lists of aarp entries @@ -796,7 +797,7 @@ static struct notifier_block aarp_notifier={ static char aarp_snap_id[]={0x00,0x00,0x00,0x80,0xF3}; -void aarp_proto_init(void) +__initfunc(void aarp_proto_init(void)) { if((aarp_dl=register_snap_client(aarp_snap_id, aarp_rcv))==NULL) printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index eba533a23dae..4dbcc0a9cdcb 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -67,6 +67,7 @@ #include #include #include +#include #undef APPLETALK_DEBUG @@ -2034,7 +2035,7 @@ static struct proc_dir_entry proc_atalk_iface = { /* Called by proto.c on kernel start up */ -void atalk_proto_init(struct net_proto *pro) +__initfunc(void atalk_proto_init(struct net_proto *pro)) { (void) sock_register(&atalk_family_ops); if ((ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv)) == NULL) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 489993da6b27..f3692d833c2e 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -126,6 +126,7 @@ #include #include #include +#include #include #include @@ -1795,7 +1796,7 @@ static struct proc_dir_entry proc_ax25_calls = { }; #endif -void ax25_proto_init(struct net_proto *pro) +__initfunc(void ax25_proto_init(struct net_proto *pro)) { sock_register(&ax25_family_ops); ax25_packet_type.type = htons(ETH_P_AX25); diff --git a/net/core/firewall.c b/net/core/firewall.c index 32cf52655bf1..44e0709cfa5d 100644 --- a/net/core/firewall.c +++ b/net/core/firewall.c @@ -10,6 +10,7 @@ #include #include #include +#include #include struct semaphore firewall_sem = MUTEX; @@ -150,7 +151,7 @@ EXPORT_SYMBOL(call_in_firewall); EXPORT_SYMBOL(call_out_firewall); EXPORT_SYMBOL(call_fw_firewall); -void fwchain_init(void) +__initfunc(void fwchain_init(void)) { int i; for(i=0;i SK_WMEM_MAX*2) + /* printk(KERN_DEBUG "setting SO_SNDBUF %d\n", val); */ + if (val > sysctl_wmem_max) return -EINVAL; - /* - * Once this is all 32bit values we can - * drop this check. + + /* FIXME: the tcp code should be made to work even + * with small sndbuf values. */ - if(val > 65535) - return -EINVAL; - sk->sndbuf = max(val,2048); + sk->sndbuf = max(val*2,2048); + /* * Wake up sending tasks if we * upped the value. @@ -206,12 +207,13 @@ int sock_setsockopt(struct socket *sock, int level, int optname, break; case SO_RCVBUF: - if(val > SK_RMEM_MAX*2) - return -EINVAL; - /* Can go soon: FIXME */ - if(val > 65535) + /* printk(KERN_DEBUG "setting SO_RCVBUF %d\n", val); */ + + if (val > sysctl_rmem_max) return -EINVAL; - sk->rcvbuf = max(val,256); + + /* FIXME: is this lower bound the right one? */ + sk->rcvbuf = max(val*2,256); break; case SO_KEEPALIVE: @@ -533,15 +535,29 @@ struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int } +/* FIXME: this is insane. We are trying suppose to be controlling how + * how much space we have for data bytes, not packet headers. + * This really points out that we need a better system for doing the + * receive buffer. -- erics + * WARNING: This is currently ONLY used in tcp. If you need it else where + * this will probably not be what you want. Possibly these two routines + * should move over to the ipv4 directory. + */ unsigned long sock_rspace(struct sock *sk) { int amt; - if (sk != NULL) - { - if (atomic_read(&sk->rmem_alloc) >= sk->rcvbuf-2*MIN_WINDOW) - return(0); - amt = min((sk->rcvbuf-atomic_read(&sk->rmem_alloc))/2-MIN_WINDOW, MAX_WINDOW); + if (sk != NULL) { + /* This used to have some bizzare complications that + * to attempt to reserve some amount of space. This doesn't + * make sense, since the number returned here does not + * actually reflect allocated space, but rather the amount + * of space we committed to. We gamble that we won't + * run out of memory, and returning a smaller number does + * not change the gamble. If we loose the gamble tcp still + * works, it may just slow down for retransmissions. + */ + amt = sk->rcvbuf - atomic_read(&sk->rmem_alloc); if (amt < 0) return(0); return(amt); @@ -550,10 +566,10 @@ unsigned long sock_rspace(struct sock *sk) } +/* FIXME: this is also insane. See above comment */ unsigned long sock_wspace(struct sock *sk) { - if (sk != NULL) - { + if (sk != NULL) { if (sk->shutdown & SEND_SHUTDOWN) return(0); if (atomic_read(&sk->wmem_alloc) >= sk->sndbuf) @@ -868,8 +884,8 @@ void sock_init_data(struct socket *sock, struct sock *sk) init_timer(&sk->timer); sk->allocation = GFP_KERNEL; - sk->rcvbuf = SK_RMEM_MAX; - sk->sndbuf = SK_WMEM_MAX; + sk->rcvbuf = sysctl_rmem_default*2; + sk->sndbuf = sysctl_wmem_default*2; sk->priority = SOPRI_NORMAL; sk->state = TCP_CLOSE; sk->zapped = 1; diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 8b5848e6b1cf..3a8bea47052a 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -8,6 +8,22 @@ #include #include +extern __u32 sysctl_wmem_max; +extern __u32 sysctl_rmem_max; +extern __u32 sysctl_wmem_default; +extern __u32 sysctl_rmem_default; + ctl_table core_table[] = { - {0} + {NET_CORE_WMEM_MAX, "wmem_max", + &sysctl_wmem_max, sizeof(int), 0644, NULL, + &proc_dointvec}, + {NET_CORE_RMEM_MAX, "rmem_max", + &sysctl_rmem_max, sizeof(int), 0644, NULL, + &proc_dointvec}, + {NET_CORE_WMEM_DEFAULT, "wmem_default", + &sysctl_wmem_default, sizeof(int), 0644, NULL, + &proc_dointvec}, + {NET_CORE_RMEM_DEFAULT, "rmem_default", + &sysctl_rmem_default, sizeof(int), 0644, NULL, + &proc_dointvec}, }; diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 9f4477807655..bdc6b37fd582 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -36,8 +36,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include -#include #include #include #include @@ -52,16 +50,17 @@ #include #include #include +#include #include #include #include #include - - +#include +#include #include -void eth_setup(char *str, int *ints) +__initfunc(void eth_setup(char *str, int *ints)) { struct device *d = dev_base; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index d96910bb001e..a3a126529ff6 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -76,6 +76,7 @@ #include #include #include +#include #include #include @@ -1063,7 +1064,7 @@ extern void tcp_init(void); * Called by socket.c on kernel startup. */ -void inet_proto_init(struct net_proto *pro) +__initfunc(void inet_proto_init(struct net_proto *pro)) { struct sk_buff *dummy_skb; struct inet_protocol *p; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 8ef0be2aff97..554809f6343d 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -90,6 +90,7 @@ #include #include #include +#include #include #include @@ -1976,7 +1977,7 @@ static struct proc_dir_entry proc_net_arp = { }; #endif -void arp_init (void) +__initfunc(void arp_init (void)) { dev_add_pack(&arp_packet_type); /* Start with the regular checks for expired arp entries. */ diff --git a/net/ipv4/fib.c b/net/ipv4/fib.c index c2182728c1e3..7daab2e613ff 100644 --- a/net/ipv4/fib.c +++ b/net/ipv4/fib.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -2020,7 +2021,7 @@ int ip_rt_event(int event, struct device *dev) } -void ip_fib_init() +__initfunc(void ip_fib_init(void)) { struct in_rtrulemsg r; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 6b697d00110d..36a69cd16903 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -256,6 +256,7 @@ #include #include #include +#include #include #include #include @@ -373,7 +374,7 @@ struct socket *icmp_socket=&icmp_inode.u.socket_i; #ifndef CONFIG_NO_ICMP_LIMIT -static void xrlim_init(void) +__initfunc(static void xrlim_init(void)) { int type, entry; struct icmp_xrlim *xr; @@ -1167,7 +1168,7 @@ static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1] = { { &icmp_statistics.IcmpOutAddrMaskReps, &icmp_statistics.IcmpInAddrMaskReps, icmp_address_reply, 0, NULL } }; -void icmp_init(struct net_proto_family *ops) +__initfunc(void icmp_init(struct net_proto_family *ops)) { int err; diff --git a/net/ipv4/ip_alias.c b/net/ipv4/ip_alias.c index 74ff42a741aa..a78eef17a95d 100644 --- a/net/ipv4/ip_alias.c +++ b/net/ipv4/ip_alias.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #ifdef ALIAS_USER_LAND_DEBUG @@ -137,7 +138,7 @@ struct net_alias_type ip_alias_type = * ip_alias module initialization */ -int ip_alias_init(void) +__initfunc(int ip_alias_init(void)) { return register_net_alias_type(&ip_alias_type, AF_INET); } diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index bf549b0475c1..117b75d34216 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -518,7 +518,7 @@ struct sk_buff *ip_defrag(struct sk_buff *skb) prev = NULL; for(next = qp->fragments; next != NULL; next = next->next) { - if (next->offset > offset) + if (next->offset >= offset) break; /* bingo! */ prev = next; } diff --git a/net/ipv4/ip_fw.c b/net/ipv4/ip_fw.c index e516a2baafcb..ea9fe48b071a 100644 --- a/net/ipv4/ip_fw.c +++ b/net/ipv4/ip_fw.c @@ -107,6 +107,7 @@ #include #include #include +#include #ifdef CONFIG_IP_MASQUERADE #include @@ -1298,7 +1299,7 @@ static struct proc_dir_entry proc_net_ipfwfwd = { #endif -void ip_fw_init(void) +__initfunc(void ip_fw_init(void)) { #ifdef CONFIG_PROC_FS #ifdef CONFIG_IP_ACCT diff --git a/net/ipv4/ip_masq.c b/net/ipv4/ip_masq.c index c5976614ed1b..2d2fd37171f1 100644 --- a/net/ipv4/ip_masq.c +++ b/net/ipv4/ip_masq.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1010,7 +1011,7 @@ static struct proc_dir_entry proc_net_ipmsqhst = { /* * Initialize ip masquerading */ -int ip_masq_init(void) +__initfunc(int ip_masq_init(void)) { #ifdef CONFIG_PROC_FS proc_net_register(&proc_net_ipmsqhst); diff --git a/net/ipv4/ip_masq_app.c b/net/ipv4/ip_masq_app.c index 86f6d456da0a..9862add850db 100644 --- a/net/ipv4/ip_masq_app.c +++ b/net/ipv4/ip_masq_app.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -482,7 +483,7 @@ static struct proc_dir_entry proc_net_ip_masq_app = { * Initialization routine */ -int ip_masq_app_init(void) +__initfunc(int ip_masq_app_init(void)) { #ifdef CONFIG_PROC_FS proc_net_register(&proc_net_ip_masq_app); diff --git a/net/ipv4/ip_masq_ftp.c b/net/ipv4/ip_masq_ftp.c index cc2481746f6a..4d5568d0a466 100644 --- a/net/ipv4/ip_masq_ftp.c +++ b/net/ipv4/ip_masq_ftp.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -187,7 +188,7 @@ struct ip_masq_app ip_masq_ftp = { * ip_masq_ftp initialization */ -int ip_masq_ftp_init(void) +__initfunc(int ip_masq_ftp_init(void)) { return register_ip_masq_app(&ip_masq_ftp, IPPROTO_TCP, 21); } diff --git a/net/ipv4/ip_masq_irc.c b/net/ipv4/ip_masq_irc.c index e0b94f0d6bdc..a1be56f818bd 100644 --- a/net/ipv4/ip_masq_irc.c +++ b/net/ipv4/ip_masq_irc.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -238,7 +239,7 @@ struct ip_masq_app ip_masq_irc = { * ip_masq_irc initialization */ -int ip_masq_irc_init(void) +__initfunc(int ip_masq_irc_init(void)) { return register_ip_masq_app(&ip_masq_irc, IPPROTO_TCP, 6667); } diff --git a/net/ipv4/ip_masq_quake.c b/net/ipv4/ip_masq_quake.c index 3614f0cf543b..08a062bc7f52 100644 --- a/net/ipv4/ip_masq_quake.c +++ b/net/ipv4/ip_masq_quake.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -279,7 +280,7 @@ struct ip_masq_app ip_masq_quakenew = { * ip_masq_quake initialization */ -int ip_masq_quake_init(void) +__initfunc(int ip_masq_quake_init(void)) { return (register_ip_masq_app(&ip_masq_quake, IPPROTO_UDP, 26000) + register_ip_masq_app(&ip_masq_quakenew, IPPROTO_UDP, 27000)); diff --git a/net/ipv4/ip_masq_raudio.c b/net/ipv4/ip_masq_raudio.c index 85bba590e561..52f439102b60 100644 --- a/net/ipv4/ip_masq_raudio.c +++ b/net/ipv4/ip_masq_raudio.c @@ -2,7 +2,7 @@ * IP_MASQ_RAUDIO - Real Audio masquerading module * * - * Version: @(#)$Id: ip_masq_raudio.c,v 1.5 1997/04/03 08:52:02 davem Exp $ + * Version: @(#)$Id: ip_masq_raudio.c,v 1.6 1997/04/29 09:38:26 mj Exp $ * * Author: Nigel Metheringham * [strongly based on ftp module by Juan Jose Ciarlante & Wouter Gadeyne] @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -200,7 +201,7 @@ struct ip_masq_app ip_masq_raudio = { * ip_masq_raudio initialization */ -int ip_masq_raudio_init(void) +__initfunc(int ip_masq_raudio_init(void)) { return register_ip_masq_app(&ip_masq_raudio, IPPROTO_TCP, 7070); } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 41e60de61f0c..6558b56e42bb 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -27,6 +27,8 @@ * (in case if packet not accepted by * output firewall rules) * Alexey Kuznetsov: use new route cache + * Andi Kleen: Fix broken PMTU recovery and remove + * some redundant tests. */ #include @@ -47,6 +49,7 @@ #include #include #include +#include #include #include @@ -126,9 +129,8 @@ int ip_build_pkt(struct sk_buff *skb, struct sock *sk, u32 saddr, u32 daddr, iph->ihl = 5; iph->tos = sk->ip_tos; iph->frag_off = 0; - if (sk->ip_pmtudisc == IP_PMTUDISC_DONT || - (sk->ip_pmtudisc == IP_PMTUDISC_WANT && - rt->rt_flags&RTF_NOPMTUDISC)) + if (sk->ip_pmtudisc == IP_PMTUDISC_WANT && + !(rt->rt_flags & RTF_NOPMTUDISC)) iph->frag_off |= htons(IP_DF); iph->ttl = sk->ip_ttl; iph->daddr = rt->rt_dst; @@ -207,9 +209,8 @@ int ip_build_header(struct sk_buff *skb, struct sock *sk) iph->ihl = 5; iph->tos = sk->ip_tos; iph->frag_off = 0; - if (sk->ip_pmtudisc == IP_PMTUDISC_DONT || - (sk->ip_pmtudisc == IP_PMTUDISC_WANT && - rt->rt_flags&RTF_NOPMTUDISC)) + if (sk->ip_pmtudisc == IP_PMTUDISC_WANT && + !(rt->rt_flags & RTF_NOPMTUDISC)) iph->frag_off |= htons(IP_DF); iph->ttl = sk->ip_ttl; iph->daddr = rt->rt_dst; @@ -480,8 +481,7 @@ int ip_build_xmit(struct sock *sk, #endif if (sk->ip_pmtudisc == IP_PMTUDISC_DONT || - (sk->ip_pmtudisc == IP_PMTUDISC_WANT && - rt->rt_flags&RTF_NOPMTUDISC)) + rt->rt_flags&RTF_NOPMTUDISC) df = 0; @@ -1036,7 +1036,7 @@ static struct proc_dir_entry proc_net_igmp = { * IP registers the packet type and then calls the subprotocol initialisers */ -void ip_init(void) +__initfunc(void ip_init(void)) { dev_add_pack(&ip_packet_type); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index f76c5b52d08c..1a38c5275b29 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -1065,7 +1066,7 @@ static struct proc_dir_entry proc_net_ipmr_mfc = { * Setup for IP multicast routing */ -void ip_mr_init(void) +__initfunc(void ip_mr_init(void)) { printk(KERN_INFO "Linux IP multicast router 0.06.\n"); register_netdevice_notifier(&ip_mr_notifier); diff --git a/net/ipv4/rarp.c b/net/ipv4/rarp.c index fb9e2a738532..e0323bb8503a 100644 --- a/net/ipv4/rarp.c +++ b/net/ipv4/rarp.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -553,8 +554,8 @@ struct proc_dir_entry proc_net_rarp = { rarp_get_info }; -void -rarp_init(void) +__initfunc(void +rarp_init(void)) { proc_net_register(&proc_net_rarp); rarp_ioctl_hook = rarp_ioctl; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 5ba6467d93a2..4a4c5321ccee 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -1379,7 +1380,7 @@ void ip_rt_multicast_event(struct device *dev) rt_cache_flush(0); } -void ip_rt_init() +__initfunc(void ip_rt_init(void)) { ip_fib_init(); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 420db4777ec9..74fd6ad91546 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.61 1997/04/22 02:53:10 davem Exp $ + * Version: $Id: tcp.c,v 1.63 1997/04/29 09:38:33 mj Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -424,6 +424,7 @@ #include #include #include +#include #include #include @@ -849,7 +850,6 @@ int tcp_do_sendmsg(struct sock *sk, int iovlen, struct iovec *iov, int flags) tcp_size = skb->tail - ((unsigned char *)(skb->h.th) + tp->tcp_header_len); - /* printk("extending buffer\n"); */ /* This window_seq test is somewhat dangerous * If the remote does SWS avoidance we should * queue the best we can if not we should in @@ -1100,6 +1100,9 @@ static void cleanup_rbuf(struct sock *sk) struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); __u32 rcv_wnd; + /* FIXME: double check this rule, then check against + * other use of similar rules. Abtract if possible. + */ rcv_wnd = tp->rcv_wnd - (tp->rcv_nxt - tp->rcv_wup); if ((rcv_wnd < sk->mss) && (sock_rspace(sk) > rcv_wnd)) @@ -1655,7 +1658,7 @@ void tcp_set_keepalive(struct sock *sk, int val) tcp_dec_slow_timer(TCP_SLT_KEEPALIVE); } -void tcp_init(void) +__initfunc(void tcp_init(void)) { tcp_openreq_cachep = kmem_cache_create("tcp_open_request", sizeof(struct open_request), diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index ab2b1ef82f28..3ab1dee42c27 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.50 1997/04/22 02:53:12 davem Exp $ + * Version: $Id: tcp_input.c,v 1.51 1997/04/27 19:24:40 schenk Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -321,8 +321,10 @@ void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp) break; case TCPOPT_WINDOW: if(opsize==TCPOLEN_WINDOW && th->syn) - if (sysctl_tcp_window_scaling) + if (sysctl_tcp_window_scaling) { + tp->wscale_ok = 1; tp->snd_wscale = *(__u8 *)ptr; + } break; case TCPOPT_SACK_PERM: if(opsize==TCPOLEN_SACK_PERM && th->syn) @@ -816,7 +818,7 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, */ if (before(tp->snd_wl1, ack_seq) || (tp->snd_wl1 == ack_seq && !after(tp->snd_wl2, ack))) { - unsigned long nwin = ntohs(th->window); + unsigned long nwin = ntohs(th->window) << tp->snd_wscale; if ((tp->snd_wl2 != ack) || (nwin > tp->snd_wnd)) { flag |= FLAG_WIN_UPDATE; @@ -1464,17 +1466,21 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if(tp->af_specific->conn_request(sk, skb, opt, isn) < 0) return 1; - /* Now we have several options: In theory there is - * nothing else in the frame. KA9Q has an option to - * send data with the syn, BSD accepts data with the - * syn up to the [to be] advertised window and - * Solaris 2.1 gives you a protocol error. For now - * we just ignore it, that fits the spec precisely - * and avoids incompatibilities. It would be nice in - * future to drop through and process the data. + /* Now we have several options: In theory there is + * nothing else in the frame. KA9Q has an option to + * send data with the syn, BSD accepts data with the + * syn up to the [to be] advertised window and + * Solaris 2.1 gives you a protocol error. For now + * we just ignore it, that fits the spec precisely + * and avoids incompatibilities. It would be nice in + * future to drop through and process the data. * - * Now that TTCP is starting to be used we ought to - * queue this data. + * Now that TTCP is starting to be used we ought to + * queue this data. + * But, this leaves one open to an easy denial of + * service attack, and SYN cookies can't defend + * against this problem. So, we drop the data + * in the interest of security over speed. */ return 0; } @@ -1514,10 +1520,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, * move to established. */ tp->rcv_nxt = skb->seq+1; - tp->rcv_wnd = 0; tp->rcv_wup = skb->seq+1; - tp->snd_wnd = htons(th->window); + tp->snd_wnd = htons(th->window) << tp->snd_wscale; tp->snd_wl1 = skb->seq; tp->snd_wl2 = skb->ack_seq; @@ -1526,6 +1531,10 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, tcp_set_state(sk, TCP_ESTABLISHED); tcp_parse_options(th,tp); /* FIXME: need to make room for SACK still */ + if (tp->wscale_ok == 0) { + tp->snd_wscale = tp->rcv_wscale = 0; + tp->window_clamp = min(tp->window_clamp,65535); + } if (tp->tstamp_ok) { tp->tcp_header_len = sizeof(struct tcphdr) + 12; /* FIXME: Define constant! */ sk->dummy_th.doff += 3; /* reserve space of options */ @@ -1695,7 +1704,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, sk->state_change(sk); tp->snd_una = skb->ack_seq; - tp->snd_wnd = htons(th->window); + tp->snd_wnd = htons(th->window) << tp->snd_wscale; tp->snd_wl1 = skb->seq; tp->snd_wl2 = skb->ack_seq; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f4528f5526d4..97b75b020de6 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.39 1997/04/22 02:53:14 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.42 1997/04/29 16:09:46 schenk Exp $ * * IPv4 specific functions * @@ -465,7 +465,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) struct sk_buff *buff; struct sk_buff *skb1; int tmp; - struct tcphdr *t1; + struct tcphdr *th; struct rtable *rt; struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; @@ -546,20 +546,17 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) return(-ENETUNREACH); } - t1 = (struct tcphdr *) skb_put(buff,sizeof(struct tcphdr)); - buff->h.th = t1; + th = (struct tcphdr *) skb_put(buff,sizeof(struct tcphdr)); + buff->h.th = th; - memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1)); + memcpy(th,(void *)&(sk->dummy_th), sizeof(*th)); buff->seq = sk->write_seq++; - t1->seq = htonl(buff->seq); + th->seq = htonl(buff->seq); tp->snd_nxt = sk->write_seq; buff->end_seq = sk->write_seq; - t1->ack = 0; - t1->window = htons(512); - t1->syn = 1; + th->ack = 0; + th->syn = 1; - /* Use 512 or whatever user asked for. */ - tp->window_clamp = rt->u.dst.window; sk->mtu = rt->u.dst.pmtu; if ((sk->ip_pmtudisc == IP_PMTUDISC_DONT || @@ -577,13 +574,26 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) sk->mss = (sk->mtu - sizeof(struct iphdr) - sizeof(struct tcphdr)); + if (sk->mss < 1) { + printk(KERN_DEBUG "intial sk->mss below 1\n"); + sk->mss = 1; /* Sanity limit */ + } + + tp->window_clamp = rt->u.dst.window; + tcp_select_initial_window(sock_rspace(sk)/2,sk->mss, + &tp->rcv_wnd, + &tp->window_clamp, + sysctl_tcp_window_scaling, + &tp->rcv_wscale); + th->window = htons(tp->rcv_wnd); + tmp = tcp_syn_build_options(buff, sk->mss, sysctl_tcp_sack, sysctl_tcp_timestamps, - sysctl_tcp_window_scaling?tp->rcv_wscale:0); + sysctl_tcp_window_scaling,tp->rcv_wscale); buff->csum = 0; - t1->doff = (sizeof(*t1)+ tmp)>>2; + th->doff = (sizeof(*th)+ tmp)>>2; - tcp_v4_send_check(sk, t1, sizeof(struct tcphdr) + tmp, buff); + tcp_v4_send_check(sk, th, sizeof(struct tcphdr) + tmp, buff); tcp_set_state(sk,TCP_SYN_SENT); @@ -803,7 +813,6 @@ int tcp_chkaddr(struct sk_buff *skb) static void tcp_v4_send_synack(struct sock *sk, struct open_request *req) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; struct sk_buff * skb; struct tcphdr *th; int tmp; @@ -829,6 +838,11 @@ static void tcp_v4_send_synack(struct sock *sk, struct open_request *req) */ req->mss = min(mss, req->mss); + if (req->mss < 1) { + printk(KERN_DEBUG "initial req->mss below 1\n"); + req->mss = 1; + } + /* Yuck, make this header setup more efficient... -DaveM */ memset(th, 0, sizeof(struct tcphdr)); th->syn = 1; @@ -839,7 +853,16 @@ static void tcp_v4_send_synack(struct sock *sk, struct open_request *req) skb->end_seq = skb->seq + 1; th->seq = ntohl(skb->seq); th->ack_seq = htonl(req->rcv_isn + 1); - th->window = ntohs(tp->rcv_wnd); + if (req->rcv_wnd == 0) { + /* Set this up on the first call only */ + req->window_clamp = skb->dst->window; + tcp_select_initial_window(sock_rspace(sk)/2,req->mss, + &req->rcv_wnd, + &req->window_clamp, + req->wscale_ok, + &req->rcv_wscale); + } + th->window = htons(req->rcv_wnd); /* XXX Partial csum of 4 byte quantity is itself! -DaveM * Yes, but it's a bit harder to special case now. It's @@ -850,7 +873,7 @@ static void tcp_v4_send_synack(struct sock *sk, struct open_request *req) */ tmp = tcp_syn_build_options(skb, req->mss, req->sack_ok, req->tstamp_ok, - (req->snd_wscale)?tp->rcv_wscale:0); + req->wscale_ok,req->rcv_wscale); skb->csum = 0; th->doff = (sizeof(*th) + tmp)>>2; th->check = tcp_v4_check(th, sizeof(*th) + tmp, @@ -881,7 +904,7 @@ static int tcp_v4_syn_filter(struct sock *sk, struct sk_buff *skb, __u32 saddr) int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 isn) { struct ip_options *opt = (struct ip_options *) ptr; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt tp; struct open_request *req; struct tcphdr *th = skb->h.th; __u32 saddr = skb->nh.iph->saddr; @@ -913,19 +936,20 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 i sk->ack_backlog++; + req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */ + req->rcv_isn = skb->seq; req->snt_isn = isn; - tp->tstamp_ok = tp->sack_ok = tp->snd_wscale = 0; - tcp_parse_options(th,tp); - if (tp->saw_tstamp) { - tp->ts_recent = tp->rcv_tsval; - tp->ts_recent_stamp = jiffies; - } - req->mss = tp->in_mss; - req->tstamp_ok = tp->tstamp_ok; - req->sack_ok = tp->sack_ok; - req->snd_wscale = tp->snd_wscale; - req->ts_recent = tp->ts_recent; + tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0; + tp.in_mss = 536; + tcp_parse_options(th,&tp); + if (tp.saw_tstamp) + req->ts_recent = tp.rcv_tsval; + req->mss = tp.in_mss; + req->tstamp_ok = tp.tstamp_ok; + req->sack_ok = tp.sack_ok; + req->snd_wscale = tp.snd_wscale; + req->wscale_ok = tp.wscale_ok; req->rmt_port = th->source; req->af.v4_req.loc_addr = daddr; req->af.v4_req.rmt_addr = saddr; @@ -1004,8 +1028,6 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, atomic_set(&newsk->rmem_alloc, 0); newsk->localroute = sk->localroute; - newsk->max_unacked = MAX_WINDOW - TCP_WINDOW_DIFF; - newsk->err = 0; newsk->shutdown = 0; newsk->ack_backlog = 0; @@ -1060,7 +1082,6 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newsk->dst_cache = &rt->u.dst; - newtp->window_clamp = rt->u.dst.window; snd_mss = rt->u.dst.pmtu; /* FIXME: is mtu really the same as snd_mss? */ @@ -1072,10 +1093,19 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newtp->sack_ok = req->sack_ok; newtp->tstamp_ok = req->tstamp_ok; - newtp->snd_wscale = req->snd_wscale; - newtp->ts_recent = req->ts_recent; - newtp->ts_recent_stamp = jiffies; + newtp->window_clamp = req->window_clamp; + newtp->rcv_wnd = req->rcv_wnd; + newtp->wscale_ok = req->wscale_ok; + if (newtp->wscale_ok) { + newtp->snd_wscale = req->snd_wscale; + newtp->rcv_wscale = req->rcv_wscale; + } else { + newtp->snd_wscale = newtp->rcv_wscale = 0; + newtp->window_clamp = min(newtp->window_clamp,65535); + } if (newtp->tstamp_ok) { + newtp->ts_recent = req->ts_recent; + newtp->ts_recent_stamp = jiffies; newtp->tcp_header_len = sizeof(struct tcphdr) + 12; /* FIXME: define constant! */ newsk->dummy_th.doff += 3; } else { @@ -1219,9 +1249,8 @@ int tcp_v4_rcv(struct sk_buff *skb, unsigned short len) case CHECKSUM_HW: if (tcp_v4_check(th,len,saddr,daddr,skb->csum)) { struct iphdr * iph = skb->nh.iph; - printk(KERN_DEBUG "TCPv4 bad checksum from %08x:%04x to %08x:%04x, ack = %u, seq = %u, len=%d/%d/%d\n", + printk(KERN_DEBUG "TCPv4 bad checksum from %08x:%04x to %08x:%04x, len=%d/%d/%d\n", saddr, ntohs(th->source), daddr, - ntohl(th->ack_seq), ntohl(th->seq), ntohs(th->dest), len, skb->len, ntohs(iph->tot_len)); goto discard_it; } @@ -1346,10 +1375,12 @@ static int tcp_v4_init_sock(struct sock *sk) tp->ato = 0; tp->iat = (HZ/5) << 3; - tp->rcv_wnd = 8192; + /* FIXME: tie this to sk->rcvbuf? (May be unnecessary) */ + /* tp->rcv_wnd = 8192; */ tp->tstamp_ok = 0; tp->sack_ok = 0; - tp->in_mss = 0; + tp->wscale_ok = 0; + tp->in_mss = 536; tp->snd_wscale = 0; tp->sacks = 0; tp->saw_tstamp = 0; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 7f157abe267c..bdc79525f1f2 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.42 1997/04/22 01:06:33 davem Exp $ + * Version: $Id: tcp_output.c,v 1.43 1997/04/27 19:24:43 schenk Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -404,14 +404,115 @@ void tcp_write_xmit(struct sock *sk) -/* - * This function returns the amount that we can raise the - * usable window based on the following constraints +/* This function returns the amount that we can raise the + * usable window based on the following constraints * - * 1. The window can never be shrunk once it is offered (RFC 793) - * 2. We limit memory per socket + * 1. The window can never be shrunk once it is offered (RFC 793) + * 2. We limit memory per socket + * + * RFC 1122: + * "the suggested [SWS] avoidance algoritm for the receiver is to keep + * RECV.NEXT + RCV.WIN fixed until: + * RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)" + * + * i.e. don't raise the right edge of the window until you can raise + * it at least MSS bytes. + * + * Unfortunately, the recomended algorithm breaks header prediction, + * since header prediction assumes th->window stays fixed. + * + * Strictly speaking, keeping th->window fixed violates the receiver + * side SWS prevention criteria. The problem is that under this rule + * a stream of single byte packets will cause the right side of the + * window to always advance by a single byte. + * + * Of course, if the sender implements sender side SWS prevention + * then this will not be a problem. + * + * BSD seems to make the following compromise: + * + * If the free space is less than the 1/4 of the maximum + * space available and the free space is less than 1/2 mss, + * then set the window to 0. + * Otherwise, just prevent the window from shrinking + * and from being larger than the largest representable value. + * + * This prevents incremental opening of the window in the regime + * where TCP is limited by the speed of the reader side taking + * data out of the TCP receive queue. It does nothing about + * those cases where the window is constrained on the sender side + * because the pipeline is full. + * + * BSD also seems to "accidentally" limit itself to windows that are a + * multiple of MSS, at least until the free space gets quite small. + * This would appear to be a side effect of the mbuf implementation. + * Combining these two algorithms results in the observed behavior + * of having a fixed window size at almost all times. + * + * Below we obtain similar behavior by forcing the offered window to + * a multiple of the mss when it is feasible to do so. + * + * FIXME: In our current implementation the value returned by sock_rpsace(sk) + * is the total space we have allocated to the socket to store skbuf's. + * The current design assumes that up to half of that space will be + * taken by headers, and the remaining space will be available for TCP data. + * This should be accounted for correctly instead. */ +unsigned short tcp_select_window(struct sock *sk) +{ + struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + int mss = sk->mss; + long free_space = sock_rspace(sk)/2; + long window, cur_win; + + if (tp->window_clamp) { + free_space = min(tp->window_clamp, free_space); + mss = min(tp->window_clamp, mss); + } else + printk(KERN_DEBUG "Clamp failure. Water leaking.\n"); + + if (mss < 1) { + mss = 1; + printk(KERN_DEBUG "tcp_select_window: mss fell to 0.\n"); + } + + /* compute the actual window i.e. + * old_window - received_bytes_on_that_win + */ + cur_win = tp->rcv_wnd - (tp->rcv_nxt - tp->rcv_wup); + window = tp->rcv_wnd; + + if (cur_win < 0) { + cur_win = 0; + printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n", + tp->rcv_wnd, tp->rcv_nxt, tp->rcv_wup); + } + + if (free_space < sk->rcvbuf/4 && free_space < mss/2) + window = 0; + + /* Get the largest window that is a nice multiple of mss. + * Window clamp already applied above. + * If our current window offering is within 1 mss of the + * free space we just keep it. This prevents the divide + * and multiply from happening most of the time. + * We also don't do any window rounding when the free space + * is too small. + */ + if (window < free_space - mss && free_space > mss) + window = (free_space/mss)*mss; + /* Never shrink the offered window */ + if (window < cur_win) + window = cur_win; + + tp->rcv_wnd = window; + tp->rcv_wup = tp->rcv_nxt; + return window >> tp->rcv_wscale; /* RFC1323 scaling applied */ +} + +#if 0 +/* Old algorithm for window selection */ unsigned short tcp_select_window(struct sock *sk) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; @@ -427,37 +528,31 @@ unsigned short tcp_select_window(struct sock *sk) /* compute the actual window i.e. * old_window - received_bytes_on_that_win */ - cur_win = tp->rcv_wup - (tp->rcv_nxt - tp->rcv_wnd); + cur_win = tp->rcv_wnd - (tp->rcv_nxt - tp->rcv_wup); window = tp->rcv_wnd; - + if (cur_win < 0) { cur_win = 0; printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n", tp->rcv_wnd, tp->rcv_nxt, tp->rcv_wup); } - /* - * RFC 1122: + /* RFC 1122: * "the suggested [SWS] avoidance algoritm for the receiver is to keep * RECV.NEXT + RCV.WIN fixed until: * RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)" * - * i.e. don't raise the right edge of the window until you can't raise - * it MSS bytes + * i.e. don't raise the right edge of the window until you can raise + * it at least MSS bytes. */ - /* It would be a good idea if it didn't break header prediction. - * and BSD made the header predition standard... - * It expects the same value in the header i.e. th->window to be - * constant - */ usable = free_space - cur_win; if (usable < 0) usable = 0; if (window < usable) { /* Window is not blocking the sender - * and we have enought free space for it + * and we have enough free space for it */ if (cur_win > (sk->mss << 1)) goto out; @@ -469,7 +564,7 @@ unsigned short tcp_select_window(struct sock *sk) */ window = max(usable, cur_win); } else { - if ((usable - window) >= mss) + while ((usable - window) >= mss) window += mss; } out: @@ -477,6 +572,7 @@ out: tp->rcv_wup = tp->rcv_nxt; return window; } +#endif static int tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb) { @@ -703,6 +799,11 @@ void tcp_send_fin(struct sock *sk) } } +/* WARNING: This routine must only be called when we have already sent + * a SYN packet that crossed the incoming SYN that caused this routine + * to get called. If this assumption fails then the initial rcv_wnd + * and rcv_wscale values will not be correct. + */ int tcp_send_synack(struct sock *sk) { struct tcp_opt * tp = &(sk->tp_pinfo.af_tcp); @@ -735,13 +836,16 @@ int tcp_send_synack(struct sock *sk) skb->end_seq = skb->seq + 1 /* th->syn */ ; th->seq = ntohl(skb->seq); - th->window = ntohs(tp->rcv_wnd); + /* This is a resend of a previous SYN, now with an ACK. + * we must reuse the previously offered window. + */ + th->window = htons(tp->rcv_wnd); tp->last_ack_sent = th->ack_seq = htonl(tp->rcv_nxt); tmp = tcp_syn_build_options(skb, sk->mss, tp->sack_ok, tp->tstamp_ok, - tp->snd_wscale?tp->rcv_wscale:0); + tp->wscale_ok,tp->rcv_wscale); skb->csum = 0; th->doff = (sizeof(*th) + tmp)>>2; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 9173a77600df..961d7310f9c0 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: addrconf.c,v 1.18 1997/04/16 05:58:03 davem Exp $ + * $Id: addrconf.c,v 1.19 1997/04/29 09:38:41 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -1215,7 +1216,7 @@ void addrconf_verify(unsigned long foo) * Init / cleanup code */ -void addrconf_init() +__initfunc(void addrconf_init(void)) { struct device *dev; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 0f6bbf4de09e..f6707030d2e6 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.16 1997/03/18 18:24:26 davem Exp $ + * $Id: af_inet6.c,v 1.17 1997/04/29 09:38:39 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -459,7 +460,7 @@ static struct proc_dir_entry proc_net_sockstat6 = { #ifdef MODULE int init_module(void) #else -void inet6_proto_init(struct net_proto *pro) +__initfunc(void inet6_proto_init(struct net_proto *pro)) #endif { struct sk_buff *dummy_skb; diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index a898f6008bd2..b5fbbde5fa6e 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: datagram.c,v 1.10 1997/04/14 05:39:42 davem Exp $ + * $Id: datagram.c,v 1.11 1997/05/03 00:58:25 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,6 +15,9 @@ #include #include +#include +#include +#include #include #include #include diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 37bd7f814c85..71ff84b4bb9b 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: icmp.c,v 1.8 1997/03/18 18:24:30 davem Exp $ + * $Id: icmp.c,v 1.9 1997/04/29 09:38:42 mj Exp $ * * Based on net/ipv4/icmp.c * @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -486,7 +487,7 @@ discard_it: return 0; } -void icmpv6_init(struct net_proto_family *ops) +__initfunc(void icmpv6_init(struct net_proto_family *ops)) { struct sock *sk; int err; diff --git a/net/ipv6/ip6_fw.c b/net/ipv6/ip6_fw.c index f6e7f8da483e..5a47cc251c17 100644 --- a/net/ipv6/ip6_fw.c +++ b/net/ipv6/ip6_fw.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: ip6_fw.c,v 1.4 1997/03/18 18:24:34 davem Exp $ + * $Id: ip6_fw.c,v 1.5 1997/04/29 09:38:44 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -365,7 +366,7 @@ static void ip6_fw_destroy(struct flow_rule *rl) #define ip6_fw_init module_init #endif -void ip6_fw_init(void) +__initfunc(void ip6_fw_init(void)) { netlink_attach(NETLINK_IP6_FW, ip6_fw_msgrcv); } diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 88920bb732ba..8b91819e30e2 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -7,7 +7,7 @@ * * Based on linux/net/ipv4/ip_sockglue.c * - * $Id: ipv6_sockglue.c,v 1.11 1997/04/20 09:44:33 davem Exp $ + * $Id: ipv6_sockglue.c,v 1.12 1997/04/29 09:38:45 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,12 +31,11 @@ #include #include #include - +#include #include #include #include - #include #include #include @@ -239,7 +238,7 @@ extern void ipv6_sysctl_register(void); extern void ipv6_sysctl_unregister(void); #endif -void ipv6_init(void) +__initfunc(void ipv6_init(void)) { dev_add_pack(&ipv6_packet_type); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 573f1f611657..6e68255e3471 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: mcast.c,v 1.8 1997/04/12 04:32:48 davem Exp $ + * $Id: mcast.c,v 1.9 1997/04/29 09:38:46 mj Exp $ * * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c * @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -495,7 +496,7 @@ void igmp6_timer_handler(unsigned long data) ma->mca_flags &= ~MAF_TIMER_RUNNING; } -void igmp6_init(struct net_proto_family *ops) +__initfunc(void igmp6_init(struct net_proto_family *ops)) { struct sock *sk; int err; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3a1704f37db1..83b5cf3bcc7f 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -6,7 +6,7 @@ * Pedro Roque * Mike Shaver * - * $Id: ndisc.c,v 1.14 1997/04/12 04:32:51 davem Exp $ + * $Id: ndisc.c,v 1.15 1997/04/29 09:38:48 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -1647,7 +1648,7 @@ struct proc_dir_entry ndisc_proc_entry = }; #endif /* CONFIG_PROC_FS */ -void ndisc_init(struct net_proto_family *ops) +__initfunc(void ndisc_init(struct net_proto_family *ops)) { struct sock *sk; int err; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d04464e26060..b8e6ac4a5946 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: route.c,v 1.11 1997/04/16 05:58:05 davem Exp $ + * $Id: route.c,v 1.12 1997/04/29 09:38:50 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef CONFIG_PROC_FS #include @@ -1573,7 +1574,7 @@ static struct proc_dir_entry proc_rt6_tree = { }; #endif /* CONFIG_PROC_FS */ -void ip6_route_init(void) +__initfunc(void ip6_route_init(void)) { #ifdef CONFIG_PROC_FS proc_net_register(&proc_rt6_info); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 4b072889c477..d818bc777c50 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: sit.c,v 1.13 1997/03/18 18:24:50 davem Exp $ + * $Id: sit.c,v 1.14 1997/04/29 09:38:52 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -243,7 +244,7 @@ static int sit_close(struct device *dev) return 0; } -int sit_init(void) +__initfunc(int sit_init(void)) { int i; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5151013a7233..3c61f7b50556 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.27 1997/04/22 02:53:20 davem Exp $ + * $Id: tcp_ipv6.c,v 1.31 1997/04/29 21:51:23 davem Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -432,21 +433,32 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, tp->snd_nxt = sk->write_seq; buff->end_seq = sk->write_seq; th->ack = 0; - th->window = 2; th->syn = 1; - tp->window_clamp = 0; sk->mtu = dst->pmtu; sk->mss = sk->mtu - sizeof(struct ipv6hdr) - sizeof(struct tcphdr); + if (sk->mss < 1) { + printk(KERN_DEBUG "intial ipv6 sk->mss below 1\n"); + sk->mss = 1; /* Sanity limit */ + } + + tp->window_clamp = 0; /* FIXME: shouldn't ipv6 dst cache have this? */ + tcp_select_initial_window(sock_rspace(sk)/2,sk->mss, + &tp->rcv_wnd, + &tp->window_clamp, + sysctl_tcp_window_scaling, + &tp->rcv_wscale); + th->window = htons(tp->rcv_wnd); + /* * Put in the TCP options to say MTU. */ tmp = tcp_syn_build_options(buff, sk->mss, sysctl_tcp_sack, sysctl_tcp_timestamps, - sysctl_tcp_window_scaling?tp->rcv_wscale:0); + sysctl_tcp_window_scaling,tp->rcv_wscale); th->doff = sizeof(*th)/4 + (tmp>>2); buff->csum = 0; tcp_v6_send_check(sk, th, sizeof(struct tcphdr) + tmp, buff); @@ -586,9 +598,11 @@ void tcp_v6_err(int type, int code, unsigned char *header, __u32 info, } +/* FIXME: this is substantially similar to the ipv4 code. + * Can some kind of merge be done? -- erics + */ static void tcp_v6_send_synack(struct sock *sk, struct open_request *req) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; struct sk_buff * skb; struct tcphdr *th; struct dst_entry *dst; @@ -630,11 +644,32 @@ static void tcp_v6_send_synack(struct sock *sk, struct open_request *req) th->seq = ntohl(skb->seq); th->ack_seq = htonl(req->rcv_isn + 1); th->doff = sizeof(*th)/4 + 1; - - th->window = ntohs(tp->rcv_wnd); - tmp = tcp_syn_build_options(skb, sk->mss, req->sack_ok, req->tstamp_ok, - (req->snd_wscale)?tp->rcv_wscale:0); + /* Don't offer more than they did. + * This way we don't have to memorize who said what. + * FIXME: the selection of initial mss here doesn't quite + * match what happens under IPV4. Figure out the right thing to do. + */ + req->mss = min(sk->mss, req->mss); + + if (req->mss < 1) { + printk(KERN_DEBUG "initial req->mss below 1\n"); + req->mss = 1; + } + + if (req->rcv_wnd == 0) { + /* Set this up on the first call only */ + req->window_clamp = 0; /* FIXME: should be in dst cache */ + tcp_select_initial_window(sock_rspace(sk)/2,req->mss, + &req->rcv_wnd, + &req->window_clamp, + req->wscale_ok, + &req->rcv_wscale); + } + th->window = htons(req->rcv_wnd); + + tmp = tcp_syn_build_options(skb, req->mss, req->sack_ok, req->tstamp_ok, + req->snd_wscale,req->rcv_wscale); th->doff = sizeof(*th)/4 + (tmp>>2); th->check = tcp_v6_check(th, sizeof(*th) + tmp, &req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr, @@ -656,10 +691,13 @@ static struct or_calltable or_ipv6 = { tcp_v6_or_free }; +/* FIXME: this is substantially similar to the ipv4 code. + * Can some kind of merge be done? -- erics + */ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 isn) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt tp; struct open_request *req; __u16 req_mss; @@ -691,14 +729,20 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, sk->ack_backlog++; + req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */ + req->rcv_isn = skb->seq; req->snt_isn = isn; - - tcp_parse_options(skb->h.th,tp); - req_mss = tp->in_mss; - if (!req_mss) - req_mss = 536; - req->mss = req_mss; + tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0; + tp.in_mss = 536; + tcp_parse_options(skb->h.th,&tp); + if (tp.saw_tstamp) + req->ts_recent = tp.rcv_tsval; + req->mss = tp.in_mss; + req->tstamp_ok = tp.tstamp_ok; + req->sack_ok = tp.sack_ok; + req->snd_wscale = tp.snd_wscale; + req->wscale_ok = tp.wscale_ok; req->rmt_port = skb->h.th->source; ipv6_addr_copy(&req->af.v6_req.rmt_addr, &skb->nh.ipv6h->saddr); ipv6_addr_copy(&req->af.v6_req.loc_addr, &skb->nh.ipv6h->daddr); @@ -876,6 +920,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newtp->sack_ok = req->sack_ok; newtp->tstamp_ok = req->tstamp_ok; newtp->snd_wscale = req->snd_wscale; + newtp->wscale_ok = req->wscale_ok; newtp->ts_recent = req->ts_recent; if (newtp->tstamp_ok) { newtp->tcp_header_len = sizeof(struct tcphdr) + 12; /* FIXME: define the contant. */ @@ -1305,8 +1350,11 @@ static int tcp_v6_init_sock(struct sock *sk) tp->ato = 0; tp->iat = (HZ/5) << 3; - - tp->rcv_wnd = 8192; + + /* FIXME: right thing? */ + tp->rcv_wnd = 0; + tp->in_mss = 536; + /* tp->rcv_wnd = 8192; */ /* start with only sending one packet at a time. */ tp->snd_cwnd = 1; @@ -1320,7 +1368,7 @@ static int tcp_v6_init_sock(struct sock *sk) sk->max_ack_backlog = SOMAXCONN; sk->mtu = 576; - sk->mss = 516; + sk->mss = 536; sk->dummy_th.doff = sizeof(sk->dummy_th)/4; @@ -1416,7 +1464,7 @@ static struct inet6_protocol tcpv6_protocol = "TCPv6" /* name */ }; -void tcpv6_init(void) +__initfunc(void tcpv6_init(void)) { /* register inet6 protocol */ inet6_add_protocol(&tcpv6_protocol); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 1f0fb8ce5421..f18f5a6f8d32 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -7,7 +7,7 @@ * * Based on linux/ipv4/udp.c * - * $Id: udp.c,v 1.16 1997/04/11 22:22:57 davem Exp $ + * $Id: udp.c,v 1.17 1997/04/29 09:38:55 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -770,7 +771,7 @@ struct proto udpv6_prot = { 0 /* highestinuse */ }; -void udpv6_init(void) +__initfunc(void udpv6_init(void)) { inet6_add_protocol(&udpv6_protocol); } diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 5b131e4a920d..cfb47bb422d7 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -91,6 +91,7 @@ #include #include #include +#include #ifdef MODULE static void ipx_proto_finito(void); @@ -2434,7 +2435,7 @@ ipx_proto_init(struct net_proto *pro) * sockets be closed from user space. */ -static void ipx_proto_finito(void) +__initfunc(static void ipx_proto_finito(void)) { ipx_interface *ifc; while (ipx_interfaces) { diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index d5b586e047f8..f28f8fb8d71a 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c @@ -39,6 +39,7 @@ #include #include #include +#include #include static lapb_cb *volatile lapb_list = NULL; @@ -397,7 +398,7 @@ EXPORT_SYMBOL(lapb_disconnect_request); EXPORT_SYMBOL(lapb_data_request); EXPORT_SYMBOL(lapb_data_received); -void lapb_proto_init(struct net_proto *pro) +__initfunc(void lapb_proto_init(struct net_proto *pro)) { printk(KERN_INFO "LAPB for Linux. Version 0.01 for Linux NET3.038 (Linux 2.1)\n"); } diff --git a/net/netbeui/af_netbeui.c b/net/netbeui/af_netbeui.c index e6683d00ff5f..9b14449975f7 100644 --- a/net/netbeui/af_netbeui.c +++ b/net/netbeui/af_netbeui.c @@ -31,6 +31,7 @@ #include #include #include +#include #undef NETBEUI_DEBUG @@ -620,7 +621,7 @@ static struct proc_dir_entry proc_netbeui = { /* Called by proto.c on kernel start up */ -void netbeui_proto_init(struct net_proto *pro) +__initfunc(void netbeui_proto_init(struct net_proto *pro)) { (void) sock_register(netbeui_proto_ops.family, &netbeui_proto_ops); if ((nb_dl = register_8022_client(nb_8022_id, netbeui_rcv)) == NULL) diff --git a/net/netlink.c b/net/netlink.c index 8c3b0aecce40..539ec42957d8 100644 --- a/net/netlink.c +++ b/net/netlink.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -443,7 +444,7 @@ void nlmsg_transmit(struct nlmsg_ctl *ctl) } -int init_netlink(void) +__initfunc(int init_netlink(void)) { int ct; diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index d6609413475f..c7383e228e6b 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -64,6 +64,7 @@ #include #include #include +#include int sysctl_netrom_default_path_quality = NR_DEFAULT_QUAL; int sysctl_netrom_obsolescence_count_initialiser = NR_DEFAULT_OBS; @@ -1361,7 +1362,7 @@ static struct device dev_nr[] = { {"nr3", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, nr_init} }; -void nr_proto_init(struct net_proto *pro) +__initfunc(void nr_proto_init(struct net_proto *pro)) { int i; diff --git a/net/netrom/sysctl_net_netrom.c b/net/netrom/sysctl_net_netrom.c index 2502885a3a2d..c6a415ee6ae5 100644 --- a/net/netrom/sysctl_net_netrom.c +++ b/net/netrom/sysctl_net_netrom.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -78,7 +79,7 @@ static ctl_table nr_root_table[] = { {0} }; -void nr_register_sysctl(void) +__initfunc(void nr_register_sysctl(void)) { nr_table_header = register_sysctl_table(nr_root_table, 1); } diff --git a/net/netsyms.c b/net/netsyms.c index 34946a5b7770..6737ca445d49 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -200,6 +200,10 @@ EXPORT_SYMBOL(csum_partial_copy_fromiovecend); EXPORT_SYMBOL(__release_sock); EXPORT_SYMBOL(net_timer); /* UDP/TCP exported functions for TCPv6 */ +EXPORT_SYMBOL(sysctl_tcp_sack); +EXPORT_SYMBOL(sysctl_tcp_timestamps); +EXPORT_SYMBOL(sysctl_tcp_window_scaling); +EXPORT_SYMBOL(sock_rspace); EXPORT_SYMBOL(udp_ioctl); EXPORT_SYMBOL(udp_connect); EXPORT_SYMBOL(udp_sendmsg); diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index f173dedaf0c0..f3309ade9ba9 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -52,6 +52,7 @@ #include #include #include +#include int sysctl_rose_restart_request_timeout = ROSE_DEFAULT_T0; int sysctl_rose_call_request_timeout = ROSE_DEFAULT_T1; @@ -1381,7 +1382,7 @@ static struct device dev_rose[] = { {"rose5", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init} }; -void rose_proto_init(struct net_proto *pro) +__initfunc(void rose_proto_init(struct net_proto *pro)) { int i; diff --git a/net/rose/sysctl_net_rose.c b/net/rose/sysctl_net_rose.c index c899a1837c21..8cd49695f0fd 100644 --- a/net/rose/sysctl_net_rose.c +++ b/net/rose/sysctl_net_rose.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -58,7 +59,7 @@ static ctl_table rose_root_table[] = { {0} }; -void rose_register_sysctl(void) +__initfunc(void rose_register_sysctl(void)) { rose_table_header = register_sysctl_table(rose_root_table, 1); } diff --git a/net/socket.c b/net/socket.c index dc4d962201e1..e3d2d6fcf553 100644 --- a/net/socket.c +++ b/net/socket.c @@ -71,6 +71,7 @@ #include #include #include +#include #if defined(CONFIG_KERNELD) && defined(CONFIG_NET) #include @@ -1399,7 +1400,7 @@ int sock_unregister(int family) return 0; } -void proto_init(void) +__initfunc(void proto_init(void)) { extern struct net_proto protocols[]; /* Network protocols */ struct net_proto *pro; @@ -1416,7 +1417,7 @@ void proto_init(void) extern void sk_init(void); -void sock_init(void) +__initfunc(void sock_init(void)) { int i; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 7c4d4679d9e1..80d91481efb9 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -81,6 +81,7 @@ #include #include #include +#include #include @@ -1459,7 +1460,7 @@ struct net_proto_family unix_family_ops = { unix_create }; -void unix_proto_init(struct net_proto *pro) +__initfunc(void unix_proto_init(struct net_proto *pro)) { struct sk_buff *dummy_skb; struct proc_dir_entry *ent; diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 948bf81fa07a..4c00420829f6 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -34,6 +34,7 @@ #include /* htons(), etc. */ #include /* copy_to/from_user */ #include /* WAN router API definitions */ +#include /* __initfunc et al. */ /****** Defines and Macros **************************************************/ @@ -130,7 +131,7 @@ void cleanup_module (void) #else -void wanrouter_init(void) +__initfunc(void wanrouter_init(void)) { int err = wanrouter_proc_init(); if (err) printk(KERN_ERR diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index ce7140db022b..de207d319873 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -23,6 +23,7 @@ #include /* kmalloc(), kfree() */ #include /* verify_area(), etc. */ #include /* inline mem*, str* functions */ +#include /* __initfunc et al. */ #include /* kernel <-> user copy */ #include /* htons(), etc. */ #include /* copy_to_user */ @@ -271,7 +272,7 @@ static struct proc_dir_entry proc_router_stat = * Initialize router proc interface. */ -int wanrouter_proc_init (void) +__initfunc(int wanrouter_proc_init (void)) { int err = proc_register(&proc_net, &proc_router); diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 971ae497dfe6..63a616e89d91 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -45,6 +45,7 @@ #include #include #include +#include #include int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; @@ -1283,7 +1284,7 @@ static struct proc_dir_entry proc_net_x25_routes = { }; #endif -void x25_proto_init(struct net_proto *pro) +__initfunc(void x25_proto_init(struct net_proto *pro)) { sock_register(&x25_family_ops); diff --git a/net/x25/sysctl_net_x25.c b/net/x25/sysctl_net_x25.c index 892d817d7f5c..8454ac9d962c 100644 --- a/net/x25/sysctl_net_x25.c +++ b/net/x25/sysctl_net_x25.c @@ -10,6 +10,7 @@ #include #include #include +#include #include static int min_timer[] = {1 * X25_SLOWHZ}; @@ -46,7 +47,7 @@ static ctl_table x25_root_table[] = { {0} }; -void x25_register_sysctl(void) +__initfunc(void x25_register_sysctl(void)) { x25_table_header = register_sysctl_table(x25_root_table, 1); } -- 2.39.5